mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
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:
parent
eacad83ff9
commit
57ce7e990b
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
|
|
35
src/search.c
35
src/search.c
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue