From 38144ed8b24138bd764f4201fe4d73438465c653 Mon Sep 17 00:00:00 2001 From: Adrian Grange Date: Thu, 14 Nov 2013 14:55:49 -0800 Subject: [PATCH] fix scalling bug by buffer auto-reallocation Change-Id: Ib748eb287520c794631697204da6ebe19523ce95 --- vp9/common/vp9_alloccommon.c | 51 ++++++++++++++++++++++++++++++++++ vp9/common/vp9_alloccommon.h | 1 + vp9/common/vp9_extend.c | 2 +- vp9/decoder/vp9_decodframe.c | 23 ++++++++------- vpx_scale/generic/yv12config.c | 5 +++- 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index 0d65651f0..d2981601b 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -79,6 +79,57 @@ static void setup_mi(VP9_COMMON *cm) { vp9_update_mode_info_border(cm, cm->prev_mip); } +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); + const int ss_x = cm->subsampling_x; + const int ss_y = cm->subsampling_y; + int mi_size; + + if (vp9_realloc_frame_buffer(&cm->post_proc_buffer, width, height, ss_x, ss_y, + VP9BORDERINPIXELS) < 0) + goto fail; + + set_mb_mi(cm, aligned_width, aligned_height); + + // Allocation + mi_size = cm->mode_info_stride * (cm->mi_rows + MI_BLOCK_SIZE); + + vpx_free(cm->mip); + cm->mip = vpx_calloc(mi_size, sizeof(MODE_INFO)); + if (!cm->mip) + goto fail; + + vpx_free(cm->prev_mip); + cm->prev_mip = vpx_calloc(mi_size, sizeof(MODE_INFO)); + if (!cm->prev_mip) + goto fail; + + vpx_free(cm->mi_grid_base); + cm->mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->mi_grid_base)); + if (!cm->mi_grid_base) + goto fail; + + vpx_free(cm->prev_mi_grid_base); + cm->prev_mi_grid_base = vpx_calloc(mi_size, sizeof(*cm->prev_mi_grid_base)); + if (!cm->prev_mi_grid_base) + goto fail; + + setup_mi(cm); + + // Create the segmentation map structure and set to 0. + vpx_free(cm->last_frame_seg_map); + cm->last_frame_seg_map = vpx_calloc(cm->mi_rows * cm->mi_cols, 1); + if (!cm->last_frame_seg_map) + goto fail; + + return 0; + + fail: + vp9_free_frame_buffers(cm); + return 1; +} + int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height) { int i; diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h index 5d5fae993..cf8dca573 100644 --- a/vp9/common/vp9_alloccommon.h +++ b/vp9/common/vp9_alloccommon.h @@ -21,6 +21,7 @@ void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi); void vp9_create_common(VP9_COMMON *cm); void vp9_remove_common(VP9_COMMON *cm); +int vp9_resize_frame_buffers(VP9_COMMON *cm, int width, int height); int vp9_alloc_frame_buffers(VP9_COMMON *cm, int width, int height); void vp9_free_frame_buffers(VP9_COMMON *cm); diff --git a/vp9/common/vp9_extend.c b/vp9/common/vp9_extend.c index 07c68c84a..836bf0e79 100644 --- a/vp9/common/vp9_extend.c +++ b/vp9/common/vp9_extend.c @@ -62,7 +62,7 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src, const int et_y = 16; const int el_y = 16; // Motion estimation may use src block variance with the block size up - // to 64x64, so the right and bottom need to be extended to 64 mulitple + // to 64x64, so the right and bottom need to be extended to 64 multiple // or up to 16, whichever is greater. const int eb_y = MAX(ALIGN_POWER_OF_TWO(src->y_width, 6) - src->y_width, 16); diff --git a/vp9/decoder/vp9_decodframe.c b/vp9/decoder/vp9_decodframe.c index 2d9b8f31c..3c4781bde 100644 --- a/vp9/decoder/vp9_decodframe.c +++ b/vp9/decoder/vp9_decodframe.c @@ -704,20 +704,19 @@ static void apply_frame_size(VP9D_COMP *pbi, int width, int height) { VP9_COMMON *cm = &pbi->common; if (cm->width != width || cm->height != height) { - if (!pbi->initial_width || !pbi->initial_height) { - if (vp9_alloc_frame_buffers(cm, width, height)) + // Change in frame size. + if (cm->width == 0 || cm->height == 0) { + // Assign new frame buffer on first call. + cm->new_fb_idx = NUM_YV12_BUFFERS - 1; + cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1; + } + + // 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)) vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR, "Failed to allocate frame buffers"); - pbi->initial_width = width; - pbi->initial_height = height; - } else { - if (width > pbi->initial_width) - vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, - "Frame width too large"); - - if (height > pbi->initial_height) - vpx_internal_error(&cm->error, VPX_CODEC_CORRUPT_FRAME, - "Frame height too large"); } cm->width = width; diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c index a89e29d86..7c3f7ece9 100644 --- a/vpx_scale/generic/yv12config.c +++ b/vpx_scale/generic/yv12config.c @@ -148,7 +148,10 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, #else const int frame_size = yplane_size + 2 * uvplane_size; #endif - if (!ybf->buffer_alloc) { + if (frame_size > ybf->buffer_alloc_sz) { + // Allocation to hold larger frame, or first allocation. + if (ybf->buffer_alloc) + vpx_free(ybf->buffer_alloc); ybf->buffer_alloc = vpx_memalign(32, frame_size); ybf->buffer_alloc_sz = frame_size; } -- 2.40.0