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.
This commit is contained in:
Ari Koivula 2014-03-18 15:26:40 +02:00
parent 57ce7e990b
commit 7328fc2897
3 changed files with 31 additions and 11 deletions

View file

@ -384,7 +384,9 @@ static void write_aud(encoder_control* encoder)
void encode_one_frame(encoder_control* encoder) void encode_one_frame(encoder_control* encoder)
{ {
yuv_t *hor_buf = alloc_yuv_t(encoder->in.width); 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_first_frame = (encoder->frame == 0);
const int is_i_radl = (encoder->cfg->intra_period == 1 && encoder->frame % 2 == 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); 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. // 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], picture_blit_pixels(&pic->y_recdata[(bottom - 1) * size.x + px.x],
&hor_buf->y[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); lcu_dim.x / 2, 1, size.x / 2, size.x / 2);
picture_blit_pixels(&pic->y_recdata[px.y * size.x + right - 1], 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); 1, lcu_dim.y, size.x, 1);
picture_blit_pixels(&pic->u_recdata[px.y * size.x / 4 + (right / 2) - 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); 1, lcu_dim.y / 2, size.x / 2, 1);
picture_blit_pixels(&pic->v_recdata[px.y * size.x / 4 + (right / 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); 1, lcu_dim.y / 2, size.x / 2, 1);
//encode_lcu(encoder, x.px, y.px, hor_buf, ver_buf); //encode_lcu(encoder, x.px, y.px, hor_buf, ver_buf);

View file

@ -36,16 +36,22 @@
yuv_t * alloc_yuv_t(int luma_size) 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->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; return yuv;
} }
void dealloc_yuv_t(yuv_t * yuv) void dealloc_yuv_t(yuv_t * yuv)
{ {
free(yuv->y);
free(yuv->u);
free(yuv->v);
free(yuv); free(yuv);
} }

View file

@ -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], &lcu->left_ref.v[1],
1, y_max_c, pic_width_c, 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->y[1], &lcu->left_ref.y[1], y_max));
assert(!memcmp(ver_buf->u, &lcu->left_ref.u[1], y_max_c)); assert(!memcmp(&ver_buf->u[1], &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->v[1], &lcu->left_ref.v[1], y_max_c));
} }
// Copy top-left reference pixel. // Copy top-left reference pixel.
if (x > 0 && y > 0) { 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->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]; 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]);
} }
} }