From 7328fc2897d01a8e99a32849c21b26f972f0bd38 Mon Sep 17 00:00:00 2001 From: Ari Koivula Date: Tue, 18 Mar 2014 15:26:40 +0200 Subject: [PATCH] Add special handling for bottom right LCU pixel. I didn't take into account that the reference pixel on the top-left of the LCU gets over written if we just replace the top reference pixels for current LCU with the bottom reference pixels after doing the search. To handle this I copy the pixel that gets overwritten to the vertical reference pixels. --- src/encoder.c | 18 ++++++++++++++---- src/picture.c | 14 ++++++++++---- src/search.c | 10 +++++++--- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/encoder.c b/src/encoder.c index 46ebc1cf..bef9dcc3 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -384,7 +384,9 @@ static void write_aud(encoder_control* encoder) void encode_one_frame(encoder_control* encoder) { yuv_t *hor_buf = alloc_yuv_t(encoder->in.width); - yuv_t *ver_buf = alloc_yuv_t(LCU_WIDTH); + // Allocate 2 extra luma pixels so we get 1 extra chroma pixel for the + // for the extra pixel on the top right. + yuv_t *ver_buf = alloc_yuv_t(LCU_WIDTH + 2); const int is_first_frame = (encoder->frame == 0); const int is_i_radl = (encoder->cfg->intra_period == 1 && encoder->frame % 2 == 0); @@ -483,6 +485,14 @@ void encode_one_frame(encoder_control* encoder) search_lcu(encoder, px.x, px.y, hor_buf, ver_buf); + // Take the bottom right pixel from the LCU above and put it as the + // first pixel in this LCUs rightmost pixels. + if (lcu.y > 0) { + ver_buf->y[0] = hor_buf->y[right - 1]; + ver_buf->u[0] = hor_buf->u[right / 2 - 1]; + ver_buf->v[0] = hor_buf->v[right / 2 - 1]; + } + // Take bottom and right pixels from this LCU to be used on the search of next LCU. picture_blit_pixels(&pic->y_recdata[(bottom - 1) * size.x + px.x], &hor_buf->y[px.x], @@ -495,13 +505,13 @@ void encode_one_frame(encoder_control* encoder) lcu_dim.x / 2, 1, size.x / 2, size.x / 2); picture_blit_pixels(&pic->y_recdata[px.y * size.x + right - 1], - ver_buf->y, + &ver_buf->y[1], 1, lcu_dim.y, size.x, 1); picture_blit_pixels(&pic->u_recdata[px.y * size.x / 4 + (right / 2) - 1], - ver_buf->u, + &ver_buf->u[1], 1, lcu_dim.y / 2, size.x / 2, 1); picture_blit_pixels(&pic->v_recdata[px.y * size.x / 4 + (right / 2) - 1], - ver_buf->v, + &ver_buf->v[1], 1, lcu_dim.y / 2, size.x / 2, 1); //encode_lcu(encoder, x.px, y.px, hor_buf, ver_buf); diff --git a/src/picture.c b/src/picture.c index 6022e297..14e60322 100644 --- a/src/picture.c +++ b/src/picture.c @@ -36,16 +36,22 @@ yuv_t * alloc_yuv_t(int luma_size) { - yuv_t * yuv = (yuv_t *)malloc(sizeof(yuv_t) + luma_size * sizeof(pixel) * 2); + // Get buffers with separate mallocs in order to take advantage of + // automatic buffer overrun checks. + yuv_t *yuv = (yuv_t *)malloc(sizeof(*yuv)); + yuv->y = (pixel *)malloc(luma_size * sizeof(*yuv->y)); + yuv->u = (pixel *)malloc(luma_size / 2 * sizeof(*yuv->u)); + yuv->v = (pixel *)malloc(luma_size / 2 * sizeof(*yuv->v)); yuv->size = luma_size; - yuv->y = (pixel *)yuv + sizeof(yuv_t); - yuv->u = yuv->y + luma_size * sizeof(pixel); - yuv->v = yuv->u + luma_size / 2 * sizeof(pixel); + return yuv; } void dealloc_yuv_t(yuv_t * yuv) { + free(yuv->y); + free(yuv->u); + free(yuv->v); free(yuv); } diff --git a/src/search.c b/src/search.c index 5999cce1..519fcf55 100644 --- a/src/search.c +++ b/src/search.c @@ -977,9 +977,9 @@ static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t &lcu->left_ref.v[1], 1, y_max_c, pic_width_c, 1); - assert(!memcmp(ver_buf->y, &lcu->left_ref.y[1], y_max)); - assert(!memcmp(ver_buf->u, &lcu->left_ref.u[1], y_max_c)); - assert(!memcmp(ver_buf->v, &lcu->left_ref.v[1], y_max_c)); + assert(!memcmp(&ver_buf->y[1], &lcu->left_ref.y[1], y_max)); + assert(!memcmp(&ver_buf->u[1], &lcu->left_ref.u[1], y_max_c)); + assert(!memcmp(&ver_buf->v[1], &lcu->left_ref.v[1], y_max_c)); } // Copy top-left reference pixel. if (x > 0 && y > 0) { @@ -991,6 +991,10 @@ static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t lcu->top_ref.v[0] = pic->v_recdata[(x_c - 1) + (y_c - 1) * pic_width_c]; lcu->left_ref.v[0] = pic->v_recdata[(x_c - 1) + (y_c - 1) * pic_width_c]; + + assert(ver_buf->y[0] == lcu->top_ref.y[0]); + assert(ver_buf->u[0] == lcu->top_ref.u[0]); + assert(ver_buf->v[0] == lcu->top_ref.v[0]); } }