Commit 8c1f071f authored by Adrian Grange's avatar Adrian Grange Committed by Gerrit Code Review

Allocate buffers based on correct chroma format

The encoder currently allocates frame buffers before
it establishes what the chroma sub-sampling factor is,
always allocating based on the 4:4:4 format.

This patch detects the chroma format as early as
possible allowing the encoder to allocate buffers of
the correct size.

Future patches will change the encoder to allocate
frame buffers on demand to further reduce the memory
profile of the encoder and rationalize the buffer
management in the encoder and decoder.

Change-Id: Ifd41dd96e67d0011719ba40fada0bae74f3a0d57
parent 97d0cb58
......@@ -109,7 +109,9 @@ void vp9_free_frame_buffers(VP9_COMMON *cm) {
}
vp9_free_frame_buffer(&cm->post_proc_buffer);
}
void vp9_free_context_buffers(VP9_COMMON *cm) {
free_mi(cm);
vpx_free(cm->last_frame_seg_map);
......@@ -165,37 +167,55 @@ int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height) {
fail:
vp9_free_frame_buffers(cm);
vp9_free_context_buffers(cm);
return 1;
}
static void init_frame_bufs(VP9_COMMON *cm) {
int i;
cm->new_fb_idx = FRAME_BUFFERS - 1;
cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
for (i = 0; i < REF_FRAMES; ++i) {
cm->ref_frame_map[i] = i;
cm->frame_bufs[i].ref_count = 1;
}
}
int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
int i;
const int ss_x = cm->subsampling_x;
const int ss_y = cm->subsampling_y;
int i;
vp9_free_frame_buffers(cm);
for (i = 0; i < FRAME_BUFFERS; i++) {
for (i = 0; i < FRAME_BUFFERS; ++i) {
cm->frame_bufs[i].ref_count = 0;
if (vp9_alloc_frame_buffer(&cm->frame_bufs[i].buf, width, height,
ss_x, ss_y, VP9_ENC_BORDER_IN_PIXELS) < 0)
goto fail;
}
cm->new_fb_idx = FRAME_BUFFERS - 1;
cm->frame_bufs[cm->new_fb_idx].ref_count = 1;
for (i = 0; i < REF_FRAMES; i++) {
cm->ref_frame_map[i] = i;
cm->frame_bufs[i].ref_count = 1;
}
init_frame_bufs(cm);
if (vp9_alloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y,
VP9_ENC_BORDER_IN_PIXELS) < 0)
goto fail;
return 0;
fail:
vp9_free_frame_buffers(cm);
return 1;
}
int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) {
const int aligned_width = ALIGN_POWER_OF_TWO(width, MI_SIZE_LOG2);
const int aligned_height = ALIGN_POWER_OF_TWO(height, MI_SIZE_LOG2);
vp9_free_context_buffers(cm);
set_mb_mi(cm, aligned_width, aligned_height);
if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE)))
......@@ -224,12 +244,13 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) {
return 0;
fail:
vp9_free_frame_buffers(cm);
vp9_free_context_buffers(cm);
return 1;
}
void vp9_remove_common(VP9_COMMON *cm) {
vp9_free_frame_buffers(cm);
vp9_free_context_buffers(cm);
vp9_free_internal_frame_buffers(&cm->int_frame_buffers);
}
......
......@@ -23,8 +23,12 @@ void vp9_remove_common(struct VP9Common *cm);
int vp9_resize_frame_buffers(struct VP9Common *cm, int width, int height);
int vp9_alloc_frame_buffers(struct VP9Common *cm, int width, int height);
int vp9_alloc_state_buffers(struct VP9Common *cm, int width, int height);
int vp9_alloc_context_buffers(struct VP9Common *cm, int width, int height);
void vp9_free_frame_buffers(struct VP9Common *cm);
void vp9_free_state_buffers(struct VP9Common *cm);
void vp9_free_context_buffers(struct VP9Common *cm);
void vp9_update_frame_size(struct VP9Common *cm);
......
......@@ -46,8 +46,8 @@ static INLINE int vp9_is_valid_scale(const struct scale_factors *sf) {
}
static INLINE int vp9_is_scaled(const struct scale_factors *sf) {
return sf->x_scale_fp != REF_NO_SCALE ||
sf->y_scale_fp != REF_NO_SCALE;
return vp9_is_valid_scale(sf) &&
(sf->x_scale_fp != REF_NO_SCALE || sf->y_scale_fp != REF_NO_SCALE);
}
#ifdef __cplusplus
......
......@@ -178,6 +178,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
cpi->active_map = NULL;
vp9_free_frame_buffers(cm);
vp9_free_context_buffers(cm);
vp9_free_frame_buffer(&cpi->last_frame_uf);
vp9_free_frame_buffer(&cpi->scaled_source);
......@@ -415,83 +416,56 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) {
"Failed to allocate altref buffer");
}
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
static void alloc_ref_frame_buffers(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
if (vp9_alloc_frame_buffers(cm, cm->width, cm->height))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffers");
if (vp9_alloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate last frame buffer");
if (vp9_alloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer");
if (vp9_alloc_frame_buffer(&cpi->scaled_last_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled last source buffer");
vpx_free(cpi->tok);
{
unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
CHECK_MEM_ERROR(cm, cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
}
vp9_setup_pc_tree(&cpi->common, cpi);
}
static void update_frame_size(VP9_COMP *cpi) {
static void alloc_util_frame_buffers(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
vp9_update_frame_size(cm);
// Update size of buffers local to this frame
if (vp9_realloc_frame_buffer(&cpi->last_frame_uf,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate last frame buffer");
"Failed to allocate last frame buffer");
if (vp9_realloc_frame_buffer(&cpi->scaled_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer");
"Failed to allocate scaled source buffer");
if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
cm->width, cm->height,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled last source buffer");
"Failed to allocate scaled last source buffer");
}
{
int y_stride = cpi->scaled_source.y_stride;
void vp9_alloc_compressor_data(VP9_COMP *cpi) {
VP9_COMMON *cm = &cpi->common;
if (cpi->sf.mv.search_method == NSTEP) {
vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
} else if (cpi->sf.mv.search_method == DIAMOND) {
vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
}
vp9_alloc_context_buffers(cm, cm->width, cm->height);
vpx_free(cpi->tok);
{
unsigned int tokens = get_token_alloc(cm->mb_rows, cm->mb_cols);
CHECK_MEM_ERROR(cm, cpi->tok, vpx_calloc(tokens, sizeof(*cpi->tok)));
}
vp9_setup_pc_tree(&cpi->common, cpi);
}
static void update_frame_size(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &cpi->mb.e_mbd;
vp9_update_frame_size(cm);
init_macroblockd(cm, xd);
}
......@@ -529,8 +503,6 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
cm->width = oxcf->width;
cm->height = oxcf->height;
cm->subsampling_x = 0;
cm->subsampling_y = 0;
vp9_alloc_compressor_data(cpi);
// Spatial scalability.
......@@ -1612,8 +1584,7 @@ void vp9_scale_references(VP9_COMP *cpi) {
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
const YV12_BUFFER_CONFIG *const ref = &cm->frame_bufs[idx].buf;
if (ref->y_crop_width != cm->width ||
ref->y_crop_height != cm->height) {
if (ref->y_crop_width != cm->width || ref->y_crop_height != cm->height) {
const int new_fb = get_free_fb(cm);
vp9_realloc_frame_buffer(&cm->frame_bufs[new_fb].buf,
cm->width, cm->height,
......@@ -2317,6 +2288,16 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size,
vp9_twopass_postencode_update(cpi);
}
static void init_motion_estimation(VP9_COMP *cpi) {
int y_stride = cpi->scaled_source.y_stride;
if (cpi->sf.mv.search_method == NSTEP) {
vp9_init3smotion_compensation(&cpi->ss_cfg, y_stride);
} else if (cpi->sf.mv.search_method == DIAMOND) {
vp9_init_dsmotion_compensation(&cpi->ss_cfg, y_stride);
}
}
static void check_initial_width(VP9_COMP *cpi, int subsampling_x,
int subsampling_y) {
VP9_COMMON *const cm = &cpi->common;
......@@ -2324,7 +2305,13 @@ static void check_initial_width(VP9_COMP *cpi, int subsampling_x,
if (!cpi->initial_width) {
cm->subsampling_x = subsampling_x;
cm->subsampling_y = subsampling_y;
alloc_raw_frame_buffers(cpi);
alloc_ref_frame_buffers(cpi);
alloc_util_frame_buffers(cpi);
init_motion_estimation(cpi);
cpi->initial_width = cm->width;
cpi->initial_height = cm->height;
}
......@@ -2341,6 +2328,7 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, unsigned int frame_flags,
const int subsampling_y = sd->uv_height < sd->y_height;
check_initial_width(cpi, subsampling_x, subsampling_y);
vpx_usec_timer_start(&timer);
if (vp9_lookahead_push(cpi->lookahead,
sd, time_stamp, end_time, frame_flags))
......@@ -2545,11 +2533,11 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
: &cpi->source->img;
if (cpi->last_source != NULL) {
cpi->unscaled_last_source = &cpi->last_source->img;
} else {
cpi->unscaled_last_source = NULL;
}
if (cpi->last_source != NULL) {
cpi->unscaled_last_source = &cpi->last_source->img;
} else {
cpi->unscaled_last_source = NULL;
}
*time_stamp = cpi->source->ts_start;
*time_end = cpi->source->ts_end;
......@@ -2624,6 +2612,9 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
cm->subsampling_x, cm->subsampling_y,
VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL);
alloc_util_frame_buffers(cpi);
init_motion_estimation(cpi);
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
const int idx = cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)];
YV12_BUFFER_CONFIG *const buf = &cm->frame_bufs[idx].buf;
......
......@@ -497,6 +497,8 @@ void vp9_first_pass(VP9_COMP *cpi) {
&cpi->scaled_source);
}
vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
vp9_setup_src_planes(x, cpi->Source, 0, 0);
vp9_setup_pre_planes(xd, 0, first_ref_buf, 0, 0, NULL);
vp9_setup_dst_planes(xd->plane, new_yv12, 0, 0);
......@@ -504,8 +506,6 @@ void vp9_first_pass(VP9_COMP *cpi) {
xd->mi = cm->mi_grid_visible;
xd->mi[0] = cm->mi;
vp9_setup_block_planes(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
vp9_frame_init_quantizer(cpi);
for (i = 0; i < MAX_MB_PLANE; ++i) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment