Add new reference pixel buffer management to encoding loop.

- This is necessary because after we add in-loop filters to be done per LCU,
  the reconstruction buffer will have the deblocked pixels. We only need the
  edge-pixels for intra prediction though so we just save those.

- Right now it only copies the pixels and passes them on to search, where
  the copied pixels are asserted to be the same ones we copy from
  reconstruction buffer.

- New yuv_t struct added for arrays of dynamic length. We might want to change
  other buffers to use it or something like it in the future.
This commit is contained in:
Ari Koivula 2014-03-18 11:26:42 +02:00
parent eacad83ff9
commit 57ce7e990b
6 changed files with 85 additions and 23 deletions

View file

@ -383,6 +383,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);
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_p_radl = (encoder->cfg->intra_period > 1 && (encoder->frame % encoder->cfg->intra_period) == 0);
@ -464,17 +467,50 @@ void encode_one_frame(encoder_control* encoder)
{
vector2d lcu;
picture *pic = encoder->in.cur_pic;
for (lcu.y = 0; lcu.y < encoder->in.height_in_lcu; lcu.y++) {
for (lcu.x = 0; lcu.x < encoder->in.width_in_lcu; lcu.x++) {
const vector2d px = { lcu.x * LCU_WIDTH, lcu.y * LCU_WIDTH };
const vector2d size = { encoder->in.width, encoder->in.height };
search_lcu(encoder, px.x, px.y);
// Handle partial LCUs on the right and bottom.
const vector2d lcu_dim = {
MIN(LCU_WIDTH, size.x - px.x), MIN(LCU_WIDTH, size.y - px.y)
};
const int right = px.x + lcu_dim.x;
const int bottom = px.y + lcu_dim.y;
search_lcu(encoder, px.x, px.y, hor_buf, ver_buf);
// 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],
lcu_dim.x, 1, size.x, size.x);
picture_blit_pixels(&pic->u_recdata[(bottom / 2 - 1) * size.x / 2 + px.x / 2],
&hor_buf->u[px.x / 2],
lcu_dim.x / 2, 1, size.x / 2, size.x / 2);
picture_blit_pixels(&pic->v_recdata[(bottom / 2 - 1) * size.x / 2 + px.x / 2],
&hor_buf->v[px.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],
ver_buf->y,
1, lcu_dim.y, size.x, 1);
picture_blit_pixels(&pic->u_recdata[px.y * size.x / 4 + (right / 2) - 1],
ver_buf->u,
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,
1, lcu_dim.y / 2, size.x / 2, 1);
//encode_lcu(encoder, x.px, y.px, hor_buf, ver_buf);
}
}
}
encode_slice_data(encoder);
cabac_flush(&cabac);
bitstream_align(encoder->stream);
bitstream_flush(encoder->stream);
@ -495,6 +531,9 @@ void encode_one_frame(encoder_control* encoder)
add_checksum(encoder);
encoder->in.cur_pic->poc = encoder->poc;
dealloc_yuv_t(hor_buf);
dealloc_yuv_t(ver_buf);
}
static void fill_after_frame(unsigned height, unsigned array_width,

View file

@ -32,7 +32,7 @@
//////////////////////////////////////////////////////////////////////////
// FUNCTIONS
// Deblocking
void filter_deblock_cu(encoder_control *encoder, int32_t x_cu, int32_t y_cu,
void filter_deblock_cu(encoder_control *encoder, int32_t x_px, int32_t y_px,
int8_t depth, int32_t edge);
void filter_deblock_edge_luma(encoder_control *encoder,
int32_t x_pos, int32_t y_pos,

View file

@ -33,6 +33,23 @@
#define PSNRMAX (255.0 * 255.0)
yuv_t * alloc_yuv_t(int luma_size)
{
yuv_t * yuv = (yuv_t *)malloc(sizeof(yuv_t) + luma_size * sizeof(pixel) * 2);
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);
}
/**
* \brief BLock Image Transfer from one buffer to another.
*

View file

@ -177,6 +177,13 @@ typedef struct {
pixel v[LCU_CHROMA_SIZE];
} lcu_yuv_t;
typedef struct {
int size;
pixel *y;
pixel *u;
pixel *v;
} yuv_t;
typedef struct {
lcu_ref_px_t top_ref; //!< Reference pixels from adjacent LCUs.
lcu_ref_px_t left_ref; //!< Reference pixels from adjacent LCUs.
@ -202,6 +209,9 @@ typedef struct {
//////////////////////////////////////////////////////////////////////////
// FUNCTIONS
yuv_t * alloc_yuv_t(int luma_size);
void dealloc_yuv_t(yuv_t * yuv);
picture * picture_init(int32_t width, int32_t height,
int32_t width_in_lcu, int32_t height_in_lcu);
int picture_destroy(picture *pic);

View file

@ -26,6 +26,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "config.h"
#include "bitstream.h"
@ -882,7 +883,7 @@ static int search_cu(encoder_control *encoder, int x, int y, int depth, lcu_t wo
* - Copy reference pixels from neighbouring LCUs.
* - Copy reference pixels from this LCU.
*/
static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t *lcu)
static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t *lcu, yuv_t *hor_buf, yuv_t *ver_buf)
{
// Copy reference cu_info structs from neighbouring LCUs.
{
@ -952,14 +953,18 @@ static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t
picture_blit_pixels(&pic->u_recdata[x_c + (y_c - 1) * pic_width_c],
&lcu->top_ref.u[1],
x_max, 1, pic_width_c, ref_size_c);
x_max_c, 1, pic_width_c, ref_size_c);
picture_blit_pixels(&pic->v_recdata[x_c + (y_c - 1) * pic_width_c],
&lcu->top_ref.v[1],
x_max, 1, pic_width_c, ref_size_c);
x_max_c, 1, pic_width_c, ref_size_c);
assert(!memcmp(&hor_buf->y[x], &lcu->top_ref.y[1], x_max));
assert(!memcmp(&hor_buf->u[x / 2], &lcu->top_ref.u[1], x_max_c));
assert(!memcmp(&hor_buf->v[x / 2], &lcu->top_ref.v[1], x_max_c));
}
// Copy left reference pixels.
if (x > 0) {
int y_max = MIN(LCU_REF_PX_WIDTH, pic_height - y);
int y_max = MIN(LCU_WIDTH, pic_height - y);
int y_max_c = y_max / 2;
picture_blit_pixels(&pic->y_recdata[(x - 1) + y * pic_width],
&lcu->left_ref.y[1],
@ -971,6 +976,10 @@ static void init_lcu_t(encoder_control *encoder, const int x, const int y, lcu_t
picture_blit_pixels(&pic->v_recdata[(x_c - 1) + (y_c) * pic_width_c],
&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));
}
// Copy top-left reference pixel.
if (x > 0 && y > 0) {
@ -1065,14 +1074,14 @@ static void copy_lcu_to_cu_data(encoder_control *encoder, int x_px, int y_px, co
* Search LCU for modes.
* - Best mode gets copied to current picture.
*/
void search_lcu(encoder_control *encoder, int x, int y)
void search_lcu(encoder_control *encoder, int x, int y, yuv_t *hor_buf, yuv_t *ver_buf)
{
lcu_t work_tree[MAX_PU_DEPTH + 1];
int depth;
// Initialize work tree.
for (depth = 0; depth <= MAX_PU_DEPTH; ++depth) {
memset(&work_tree[depth], 0, sizeof(work_tree[depth]));
init_lcu_t(encoder, x, y, &work_tree[depth]);
init_lcu_t(encoder, x, y, &work_tree[depth], hor_buf, ver_buf);
}
// Start search from depth 0.
@ -1080,17 +1089,3 @@ void search_lcu(encoder_control *encoder, int x, int y)
copy_lcu_to_cu_data(encoder, x, y, &work_tree[0]);
}
/**
* Perform mode search for every LCU in the current picture.
*/
static void search_frame(encoder_control *encoder)
{
int y_lcu, x_lcu;
for (y_lcu = 0; y_lcu < encoder->in.height_in_lcu; y_lcu++) {
for (x_lcu = 0; x_lcu < encoder->in.width_in_lcu; x_lcu++) {
search_lcu(encoder, x_lcu * LCU_WIDTH, y_lcu * LCU_WIDTH);
}
}
}

View file

@ -27,8 +27,9 @@
#include "global.h"
#include "encoder.h"
#include "picture.h"
void search_lcu(encoder_control *encoder, int x, int y);
void search_lcu(encoder_control *encoder, int x, int y, yuv_t *hor_buf, yuv_t *ver_buf);
#endif