Detect chroma subsampling more directly In av1_copy_and_extend_frame(), detect chroma subsampling more directly by testing src->subsampling_x and src->subsampling_y. The original tests do not work when src->y_width or src->y_height is equal to 1. BUG=aomedia:3113 Change-Id: I4665e2eeeeec415d73b50beaa896b66490fa97ba (cherry picked from commit bce31a8248b3f339acbf695972384177370c4cb0)
diff --git a/av1/encoder/extend.c b/av1/encoder/extend.c index 381aec8..46b7402 100644 --- a/av1/encoder/extend.c +++ b/av1/encoder/extend.c
@@ -9,6 +9,8 @@ * PATENTS file, you can obtain it at www.aomedia.org/license/patent. */ +#include <assert.h> + #include "aom_dsp/aom_dsp_common.h" #include "aom_mem/aom_mem.h" #include "aom_ports/mem.h" @@ -45,6 +47,7 @@ dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; dst_ptr2 = dst + dst_pitch * (h)-extend_left; linesize = extend_left + extend_right + w; + assert(linesize <= dst_pitch); for (i = 0; i < extend_top; i++) { memcpy(dst_ptr1, src_ptr1, linesize); @@ -88,6 +91,7 @@ dst_ptr1 = dst + dst_pitch * (-extend_top) - extend_left; dst_ptr2 = dst + dst_pitch * (h)-extend_left; linesize = extend_left + extend_right + w; + assert(linesize <= dst_pitch); for (i = 0; i < extend_top; i++) { memcpy(dst_ptr1, src_ptr1, linesize * sizeof(src_ptr1[0])); @@ -111,8 +115,8 @@ const int eb_y = AOMMAX(src->y_height + dst->border, ALIGN_POWER_OF_TWO(src->y_height, 6)) - src->y_crop_height; - const int uv_width_subsampling = (src->uv_width != src->y_width); - const int uv_height_subsampling = (src->uv_height != src->y_height); + const int uv_width_subsampling = src->subsampling_x; + const int uv_height_subsampling = src->subsampling_y; const int et_uv = et_y >> uv_height_subsampling; const int el_uv = el_y >> uv_width_subsampling; const int eb_uv = eb_y >> uv_height_subsampling;
diff --git a/test/encode_small_width_height_test.cc b/test/encode_small_width_height_test.cc index 6f52fd5..9bd9471 100644 --- a/test/encode_small_width_height_test.cc +++ b/test/encode_small_width_height_test.cc
@@ -15,10 +15,11 @@ // (<= one AV1 superblock) with multiple threads. aom_codec_encode() should // not crash. -#include "third_party/googletest/src/googletest/include/gtest/gtest.h" +#include <memory> #include "aom/aomcx.h" #include "aom/aom_encoder.h" +#include "third_party/googletest/src/googletest/include/gtest/gtest.h" namespace { @@ -121,4 +122,54 @@ EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); } +// A reproducer test for aomedia:3113. The test should complete without any +// memory errors. +TEST(EncodeSmallWidthHeight, 1x1) { + constexpr int kWidth = 1; + constexpr int kHeight = 1; + + // This test cannot use aom_img_alloc() or aom_img_wrap() because they call + // align_image_dimension() to align img.w and img.h to the next even number + // (2). In this test it is important to set img.w and img.h to 1. Therefore we + // set up img manually. + aom_image_t img; + memset(&img, 0, sizeof(img)); + img.fmt = AOM_IMG_FMT_I420; + img.bit_depth = 8; + img.w = kWidth; + img.h = kHeight; + img.d_w = kWidth; + img.d_h = kHeight; + img.x_chroma_shift = 1; + img.y_chroma_shift = 1; + img.bps = 12; + int y_stride = kWidth; + int uv_stride = (kWidth + 1) >> 1; + int y_height = kHeight; + int uv_height = (kHeight + 1) >> 1; + img.stride[AOM_PLANE_Y] = y_stride; + img.stride[AOM_PLANE_U] = img.stride[AOM_PLANE_V] = uv_stride; + std::unique_ptr<unsigned char[]> y_plane( + new unsigned char[y_height * y_stride]()); + std::unique_ptr<unsigned char[]> u_plane( + new unsigned char[uv_height * uv_stride]()); + std::unique_ptr<unsigned char[]> v_plane( + new unsigned char[uv_height * uv_stride]()); + img.planes[AOM_PLANE_Y] = y_plane.get(); + img.planes[AOM_PLANE_U] = u_plane.get(); + img.planes[AOM_PLANE_V] = v_plane.get(); + + aom_codec_iface_t *iface = aom_codec_av1_cx(); + aom_codec_enc_cfg_t cfg; + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_default(iface, &cfg, 0)); + cfg.g_w = kWidth; + cfg.g_h = kHeight; + aom_codec_ctx_t enc; + EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 5)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img, 0, 1, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, NULL, 0, 0, 0)); + EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc)); +} + } // namespace