From: Adrian Grange Date: Thu, 10 Jul 2014 22:35:51 +0000 (-0700) Subject: Modified frame buffer handling X-Git-Tag: v1.4.0~1203^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f68aaa38d65c0e97945b102c55e66c111396937c;p=libvpx Modified frame buffer handling This patch is the first step toward simplifying the frame buffer handling. The final goal is to have a common frame buffer handling framework for both encoder and decoder that incorporates the existing ability to use externally allocated memory. Change-Id: I2c378a4f54a39908915f46c4260e17a080db7ff1 --- diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index ccbf3f64a..b379656b3 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -28,7 +28,10 @@ static void clear_mi_border(const VP9_COMMON *cm, MODE_INFO *mi) { vpx_memset(&mi[i * cm->mi_stride], 0, sizeof(*mi)); } -static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) { +void vp9_set_mb_mi(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); + cm->mi_cols = aligned_width >> MI_SIZE_LOG2; cm->mi_rows = aligned_height >> MI_SIZE_LOG2; cm->mi_stride = cm->mi_cols + MI_BLOCK_SIZE; @@ -95,7 +98,7 @@ static void free_mi(VP9_COMMON *cm) { cm->prev_mi_grid_base = NULL; } -void vp9_free_frame_buffers(VP9_COMMON *cm) { +void vp9_free_ref_frame_buffers(VP9_COMMON *cm) { int i; for (i = 0; i < FRAME_BUFFERS; ++i) { @@ -124,52 +127,27 @@ void vp9_free_context_buffers(VP9_COMMON *cm) { cm->above_seg_context = NULL; } -int vp9_resize_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); -#if CONFIG_INTERNAL_STATS || CONFIG_VP9_POSTPROC - const int ss_x = cm->subsampling_x; - const int ss_y = cm->subsampling_y; - - // TODO(agrange): this should be conditionally allocated. - if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, - VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0) - goto fail; -#endif - - set_mb_mi(cm, aligned_width, aligned_height); - - free_mi(cm); - if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE))) - goto fail; +int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) { + vp9_free_context_buffers(cm); - setup_mi(cm); + vp9_set_mb_mi(cm, width, height); + if (alloc_mi(cm, cm->mi_stride * (cm->mi_rows + MI_BLOCK_SIZE))) goto fail; - // Create the segmentation map structure and set to 0. - vpx_free(cm->last_frame_seg_map); cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1); - if (!cm->last_frame_seg_map) - goto fail; + if (!cm->last_frame_seg_map) goto fail; - vpx_free(cm->above_context); - cm->above_context = - (ENTROPY_CONTEXT *)vpx_calloc(2 * mi_cols_aligned_to_sb(cm->mi_cols) * - MAX_MB_PLANE, - sizeof(*cm->above_context)); - if (!cm->above_context) - goto fail; + cm->above_context = (ENTROPY_CONTEXT *)vpx_calloc( + 2 * mi_cols_aligned_to_sb(cm->mi_cols) * MAX_MB_PLANE, + sizeof(*cm->above_context)); + if (!cm->above_context) goto fail; - vpx_free(cm->above_seg_context); - cm->above_seg_context = - (PARTITION_CONTEXT *)vpx_calloc(mi_cols_aligned_to_sb(cm->mi_cols), - sizeof(*cm->above_seg_context)); - if (!cm->above_seg_context) - goto fail; + cm->above_seg_context = (PARTITION_CONTEXT *)vpx_calloc( + mi_cols_aligned_to_sb(cm->mi_cols), sizeof(*cm->above_seg_context)); + if (!cm->above_seg_context) goto fail; return 0; fail: - vp9_free_frame_buffers(cm); vp9_free_context_buffers(cm); return 1; } @@ -186,12 +164,12 @@ static void init_frame_bufs(VP9_COMMON *cm) { } } -int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { +int vp9_alloc_ref_frame_buffers(VP9_COMMON *cm, int width, int height) { int i; const int ss_x = cm->subsampling_x; const int ss_y = cm->subsampling_y; - vp9_free_frame_buffers(cm); + vp9_free_ref_frame_buffers(cm); for (i = 0; i < FRAME_BUFFERS; ++i) { cm->frame_bufs[i].ref_count = 0; @@ -211,62 +189,18 @@ int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { 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))) - goto fail; - - setup_mi(cm); - - // Create the segmentation map structure and set to 0. - cm->last_frame_seg_map = (uint8_t *)vpx_calloc(cm->mi_rows * cm->mi_cols, 1); - if (!cm->last_frame_seg_map) - goto fail; - - cm->above_context = - (ENTROPY_CONTEXT *)vpx_calloc(2 * mi_cols_aligned_to_sb(cm->mi_cols) * - MAX_MB_PLANE, - sizeof(*cm->above_context)); - if (!cm->above_context) - goto fail; - - cm->above_seg_context = - (PARTITION_CONTEXT *)vpx_calloc(mi_cols_aligned_to_sb(cm->mi_cols), - sizeof(*cm->above_seg_context)); - if (!cm->above_seg_context) - goto fail; - - return 0; - - fail: - vp9_free_context_buffers(cm); + vp9_free_ref_frame_buffers(cm); return 1; } void vp9_remove_common(VP9_COMMON *cm) { - vp9_free_frame_buffers(cm); + vp9_free_ref_frame_buffers(cm); vp9_free_context_buffers(cm); vp9_free_internal_frame_buffers(&cm->int_frame_buffers); } -void vp9_update_frame_size(VP9_COMMON *cm) { - const int aligned_width = ALIGN_POWER_OF_TWO(cm->width, MI_SIZE_LOG2); - const int aligned_height = ALIGN_POWER_OF_TWO(cm->height, MI_SIZE_LOG2); - - set_mb_mi(cm, aligned_width, aligned_height); +void vp9_init_context_buffers(VP9_COMMON *cm) { setup_mi(cm); - - // Initialize the previous frame segment map to 0. if (cm->last_frame_seg_map) vpx_memset(cm->last_frame_seg_map, 0, cm->mi_rows * cm->mi_cols); } diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h index c4b1b8d2d..c5b893fac 100644 --- a/vp9/common/vp9_alloccommon.h +++ b/vp9/common/vp9_alloccommon.h @@ -20,18 +20,17 @@ struct VP9Common; 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_init_context_buffers(struct VP9Common *cm); void vp9_free_context_buffers(struct VP9Common *cm); -void vp9_update_frame_size(struct VP9Common *cm); +int vp9_alloc_ref_frame_buffers(struct VP9Common *cm, int width, int height); +void vp9_free_ref_frame_buffers(struct VP9Common *cm); + +int vp9_alloc_state_buffers(struct VP9Common *cm, int width, int height); +void vp9_free_state_buffers(struct VP9Common *cm); +void vp9_set_mb_mi(struct VP9Common *cm, int width, int height); void vp9_swap_mi_and_prev_mi(struct VP9Common *cm); #ifdef __cplusplus diff --git a/vp9/common/vp9_postproc.c b/vp9/common/vp9_postproc.c index 9f3210479..7d96e6e01 100644 --- a/vp9/common/vp9_postproc.c +++ b/vp9/common/vp9_postproc.c @@ -411,6 +411,14 @@ int vp9_post_proc_frame(struct VP9Common *cm, vp9_clear_system_state(); +#if CONFIG_VP9_POSTPROC || CONFIG_INTERNAL_STATS + if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, + VP9_DEC_BORDER_IN_PIXELS, NULL, NULL, NULL) < 0) + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate post-processing buffer"); +#endif + if (flags & VP9D_DEMACROBLOCK) { deblock_and_de_macro_block(cm->frame_to_show, ppbuf, q + (ppflags->deblocking_level - 5) * 10, 1, 0); diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c index 615fa4c76..5c4d74f46 100644 --- a/vp9/decoder/vp9_decodeframe.c +++ b/vp9/decoder/vp9_decodeframe.c @@ -620,28 +620,28 @@ static void setup_display_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { vp9_read_frame_size(rb, &cm->display_width, &cm->display_height); } -static void apply_frame_size(VP9_COMMON *cm, int width, int height) { -#if CONFIG_SIZE_LIMIT - if (width > DECODE_WIDTH_LIMIT || height > DECODE_HEIGHT_LIMIT) - vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, - "Width and height beyond allowed size."); -#endif - +static void resize_context_buffers(VP9_COMMON *cm, int width, int height) { if (cm->width != width || cm->height != height) { - // Change in frame size. - // TODO(agrange) Don't test width/height, check overall size. - if (width > cm->width || height > cm->height) { - // Rescale frame buffers only if they're not big enough already. - if (vp9_resize_frame_buffers(cm, width, height)) + // Change in frame size (assumption: color format does not change). + if (cm->width == 0 || cm->height == 0 || + width * height > cm->width * cm->height) { + if (vp9_alloc_context_buffers(cm, width, height)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate frame buffers"); + } else { + vp9_set_mb_mi(cm, width, height); } - + vp9_init_context_buffers(cm); cm->width = width; cm->height = height; - - vp9_update_frame_size(cm); } +} + +static void setup_frame_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { + int width, height; + vp9_read_frame_size(rb, &width, &height); + resize_context_buffers(cm, width, height); + setup_display_size(cm, rb); if (vp9_realloc_frame_buffer( get_frame_new_buffer(cm), cm->width, cm->height, @@ -653,13 +653,6 @@ static void apply_frame_size(VP9_COMMON *cm, int width, int height) { } } -static void setup_frame_size(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { - int width, height; - vp9_read_frame_size(rb, &width, &height); - apply_frame_size(cm, width, height); - setup_display_size(cm, rb); -} - static void setup_frame_size_with_refs(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { int width, height; @@ -681,16 +674,23 @@ static void setup_frame_size_with_refs(VP9_COMMON *cm, // dimensions. for (i = 0; i < REFS_PER_FRAME; ++i) { RefBuffer *const ref_frame = &cm->frame_refs[i]; - const int ref_width = ref_frame->buf->y_width; - const int ref_height = ref_frame->buf->y_height; - - if (!valid_ref_frame_size(ref_width, ref_height, width, height)) + if (!valid_ref_frame_size(ref_frame->buf->y_width, ref_frame->buf->y_height, + width, height)) vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, "Referenced frame has invalid size"); } - apply_frame_size(cm, width, height); + resize_context_buffers(cm, width, height); setup_display_size(cm, rb); + + if (vp9_realloc_frame_buffer( + get_frame_new_buffer(cm), cm->width, cm->height, + cm->subsampling_x, cm->subsampling_y, VP9_DEC_BORDER_IN_PIXELS, + &cm->frame_bufs[cm->new_fb_idx].raw_frame_buffer, cm->get_fb_cb, + cm->cb_priv)) { + vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, + "Failed to allocate frame buffer"); + } } static void setup_tile_info(VP9_COMMON *cm, struct vp9_read_bit_buffer *rb) { @@ -1144,8 +1144,8 @@ static size_t read_uncompressed_header(VP9Decoder *pbi, pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1; for (i = 0; i < REFS_PER_FRAME; ++i) { - cm->frame_refs[i].idx = cm->new_fb_idx; - cm->frame_refs[i].buf = get_frame_new_buffer(cm); + cm->frame_refs[i].idx = -1; + cm->frame_refs[i].buf = NULL; } setup_frame_size(cm, rb); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index d3e0e17bc..a65c9a053 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -172,7 +172,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) { vp9_cyclic_refresh_free(cpi->cyclic_refresh); cpi->cyclic_refresh = NULL; - vp9_free_frame_buffers(cm); + vp9_free_ref_frame_buffers(cm); vp9_free_context_buffers(cm); vp9_free_frame_buffer(&cpi->last_frame_uf); @@ -424,7 +424,7 @@ static void alloc_raw_frame_buffers(VP9_COMP *cpi) { 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)) + if (vp9_alloc_ref_frame_buffers(cm, cm->width, cm->height)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate frame buffers"); } @@ -471,7 +471,9 @@ void vp9_alloc_compressor_data(VP9_COMP *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); + + vp9_set_mb_mi(cm, cm->width, cm->height); + vp9_init_context_buffers(cm); init_macroblockd(cm, xd); if (cpi->use_svc && cpi->svc.number_temporal_layers == 1) { @@ -2842,6 +2844,8 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, PSNR_STATS psnr2; double frame_ssim2 = 0, weight = 0; #if CONFIG_VP9_POSTPROC + // TODO(agrange) Add resizing of post-proc buffer in here when the + // encoder is changed to use on-demand buffer allocation. vp9_deblock(cm->frame_to_show, &cm->post_proc_buffer, cm->lf.filter_level * 10 / 6); #endif @@ -2959,10 +2963,11 @@ int vp9_set_internal_size(VP9_COMP *cpi, // always go to the next whole number cm->width = (hs - 1 + cpi->oxcf.width * hr) / hs; cm->height = (vs - 1 + cpi->oxcf.height * vr) / vs; - assert(cm->width <= cpi->initial_width); assert(cm->height <= cpi->initial_height); + update_frame_size(cpi); + return 0; } @@ -2995,10 +3000,11 @@ int vp9_set_size_literal(VP9_COMP *cpi, unsigned int width, printf("Warning: Desired height too large, changed to %d\n", cm->height); } } - assert(cm->width <= cpi->initial_width); assert(cm->height <= cpi->initial_height); + update_frame_size(cpi); + return 0; }