From: Marco Date: Wed, 10 Feb 2016 19:39:04 +0000 (-0800) Subject: vp9-resize: Fix an issue with external dynamic resize. X-Git-Tag: v1.6.0~357^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3cbc26f31b82a045d44ba2fde1ce54a3d8e39cd6;p=libvpx vp9-resize: Fix an issue with external dynamic resize. External dynamic resize with swapping width and height was not handled properly. Fix is to re-init loop-filter under certain condtions. Modify unittest to test this case. Without this change test will fail. Relates to: https://bugs.chromium.org/p/webm/issues/detail?id=1140 Change-Id: I7d81ca7fe0783b3bc103a52a7b7cf073a96be26e --- diff --git a/test/resize_test.cc b/test/resize_test.cc index c5f05f310..017730899 100644 --- a/test/resize_test.cc +++ b/test/resize_test.cc @@ -90,74 +90,178 @@ struct FrameInfo { unsigned int h; }; -unsigned int ScaleForFrameNumber(unsigned int frame, unsigned int val) { - if (frame < 10) - return val; - if (frame < 20) - return val * 3 / 4; - if (frame < 30) - return val / 2; - if (frame < 40) - return val; - if (frame < 50) - return val * 3 / 4; - if (frame < 60) - return val / 2; - if (frame < 70) - return val * 3 / 4; - if (frame < 80) - return val; - if (frame < 90) - return val * 3 / 4; - if (frame < 100) - return val / 2; - if (frame < 110) - return val * 3 / 4; - if (frame < 120) - return val; - if (frame < 130) - return val * 3 / 4; - if (frame < 140) - return val / 2; - if (frame < 150) - return val * 3 / 4; - if (frame < 160) - return val; - if (frame < 170) - return val / 2; - if (frame < 180) - return val * 3 / 4; - if (frame < 190) - return val; - if (frame < 200) - return val * 3 / 4; - if (frame < 210) - return val / 2; - if (frame < 220) - return val * 3 / 4; - if (frame < 230) - return val; - if (frame < 240) - return val / 2; - if (frame < 250) - return val * 3 / 4; - return val; +void ScaleForFrameNumber(unsigned int frame, + unsigned int initial_w, + unsigned int initial_h, + unsigned int *w, + unsigned int *h, + int flag_codec) { + if (frame < 10) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 20) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 30) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 40) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 50) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 60) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 70) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 80) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 90) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 100) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 110) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 120) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 130) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 140) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 150) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 160) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 170) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 180) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 190) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 200) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 210) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 220) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 230) { + *w = initial_w; + *h = initial_h; + return; + } + if (frame < 240) { + *w = initial_w * 3 / 4; + *h = initial_h * 3 / 4; + return; + } + if (frame < 250) { + *w = initial_w / 2; + *h = initial_h / 2; + return; + } + if (frame < 260) { + *w = initial_w; + *h = initial_h; + return; + } + // Go down very low. + if (frame < 270) { + *w = initial_w / 4; + *h = initial_h / 4; + return; + } + if (flag_codec == 1) { + // Cases that only works for VP9. + // For VP9: Swap width and height of original. + if (frame < 320) { + *w = initial_h; + *h = initial_w; + return; + } + } + *w = initial_w; + *h = initial_h; } class ResizingVideoSource : public ::libvpx_test::DummyVideoSource { public: ResizingVideoSource() { SetSize(kInitialWidth, kInitialHeight); - limit_ = 300; + limit_ = 350; } - + int flag_codec_; virtual ~ResizingVideoSource() {} protected: virtual void Next() { ++frame_; - SetSize(ScaleForFrameNumber(frame_, kInitialWidth), - ScaleForFrameNumber(frame_, kInitialHeight)); + unsigned int width; + unsigned int height; + ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height, + flag_codec_); + SetSize(width, height); FillFrame(); } }; @@ -184,15 +288,17 @@ class ResizeTest : public ::libvpx_test::EncoderTest, TEST_P(ResizeTest, TestExternalResizeWorks) { ResizingVideoSource video; + video.flag_codec_ = 0; cfg_.g_lag_in_frames = 0; ASSERT_NO_FATAL_FAILURE(RunLoop(&video)); for (std::vector::const_iterator info = frame_info_list_.begin(); info != frame_info_list_.end(); ++info) { const unsigned int frame = static_cast(info->pts); - const unsigned int expected_w = ScaleForFrameNumber(frame, kInitialWidth); - const unsigned int expected_h = ScaleForFrameNumber(frame, kInitialHeight); - + unsigned int expected_w; + unsigned int expected_h; + ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, + &expected_w, &expected_h, 0); EXPECT_EQ(expected_w, info->w) << "Frame " << frame << " had unexpected width"; EXPECT_EQ(expected_h, info->h) @@ -386,6 +492,7 @@ class ResizeRealtimeTest : public ::libvpx_test::EncoderTest, TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) { ResizingVideoSource video; + video.flag_codec_ = 1; DefaultConfig(); // Disable internal resize for this test. cfg_.rc_resize_allowed = 0; @@ -395,9 +502,10 @@ TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) { for (std::vector::const_iterator info = frame_info_list_.begin(); info != frame_info_list_.end(); ++info) { const unsigned int frame = static_cast(info->pts); - const unsigned int expected_w = ScaleForFrameNumber(frame, kInitialWidth); - const unsigned int expected_h = ScaleForFrameNumber(frame, kInitialHeight); - + unsigned int expected_w; + unsigned int expected_h; + ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight, + &expected_w, &expected_h, 1); EXPECT_EQ(expected_w, info->w) << "Frame " << frame << " had unexpected width"; EXPECT_EQ(expected_h, info->h) diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c index 24c6c54ed..7dd1005d3 100644 --- a/vp9/common/vp9_alloccommon.c +++ b/vp9/common/vp9_alloccommon.c @@ -119,6 +119,20 @@ void vp9_free_context_buffers(VP9_COMMON *cm) { cm->lf.lfm = NULL; } + +int vp9_alloc_loop_filter(VP9_COMMON *cm) { + vpx_free(cm->lf.lfm); + // Each lfm holds bit masks for all the 8x8 blocks in a 64x64 region. The + // stride and rows are rounded up / truncated to a multiple of 8. + cm->lf.lfm_stride = (cm->mi_cols + (MI_BLOCK_SIZE - 1)) >> 3; + cm->lf.lfm = (LOOP_FILTER_MASK *)vpx_calloc( + ((cm->mi_rows + (MI_BLOCK_SIZE - 1)) >> 3) * cm->lf.lfm_stride, + sizeof(*cm->lf.lfm)); + if (!cm->lf.lfm) + return 1; + return 0; +} + int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) { int new_mi_size; @@ -151,15 +165,8 @@ int vp9_alloc_context_buffers(VP9_COMMON *cm, int width, int height) { cm->above_context_alloc_cols = cm->mi_cols; } - vpx_free(cm->lf.lfm); - - // Each lfm holds bit masks for all the 8x8 blocks in a 64x64 region. The - // stride and rows are rounded up / truncated to a multiple of 8. - cm->lf.lfm_stride = (cm->mi_cols + (MI_BLOCK_SIZE - 1)) >> 3; - cm->lf.lfm = (LOOP_FILTER_MASK *)vpx_calloc( - ((cm->mi_rows + (MI_BLOCK_SIZE - 1)) >> 3) * cm->lf.lfm_stride, - sizeof(*cm->lf.lfm)); - if (!cm->lf.lfm) goto fail; + if (vp9_alloc_loop_filter(cm)) + goto fail; return 0; diff --git a/vp9/common/vp9_alloccommon.h b/vp9/common/vp9_alloccommon.h index c0e51a6ce..e53955b99 100644 --- a/vp9/common/vp9_alloccommon.h +++ b/vp9/common/vp9_alloccommon.h @@ -23,6 +23,7 @@ struct BufferPool; void vp9_remove_common(struct VP9Common *cm); +int vp9_alloc_loop_filter(struct VP9Common *cm); int vp9_alloc_context_buffers(struct VP9Common *cm, int width, int height); void vp9_init_context_buffers(struct VP9Common *cm); void vp9_free_context_buffers(struct VP9Common *cm); diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index ff176fb93..429a9cecd 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -1538,8 +1538,12 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { realloc_segmentation_maps(cpi); cpi->initial_width = cpi->initial_height = 0; cpi->external_resize = 0; + } else if (cm->mi_alloc_size == new_mi_size && + (cpi->oxcf.width > last_w || cpi->oxcf.height > last_h)) { + vp9_alloc_loop_filter(cm); } } + update_frame_size(cpi); if ((last_w != cpi->oxcf.width || last_h != cpi->oxcf.height) &&