From: Adrian Grange Date: Mon, 16 Jun 2014 23:22:28 +0000 (-0700) Subject: Allocate buffers based on correct chroma format X-Git-Tag: v1.4.0~1356 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8c1f071f1ea03b33bcf31edc1eec3d549d134b37;p=libvpx 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 --- diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index e56a0b7a8..2386b13e7 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -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); } diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h index 06636a905..c4b1b8d2d 100644 --- a/vp9/common/vp9_alloccommon.h +++ b/vp9/common/vp9_alloccommon.h @@ -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); diff --git a/vp9/common/vp9_scale.h b/vp9/common/vp9_scale.h index a9dda1889..04aae659f 100644 --- a/vp9/common/vp9_scale.h +++ b/vp9/common/vp9_scale.h @@ -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 diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index 75ccebc56..bc240ff55 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -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; diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 5e82bb3f4..54c3ec090 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -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) {