Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions av2/encoder/extend.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
* aomedia.org/license/patent-license/.
*/

#include <assert.h>

#include "avm_dsp/avm_dsp_common.h"
#include "avm_mem/avm_mem.h"
#include "avm_ports/mem.h"
Expand Down Expand Up @@ -46,6 +48,7 @@ static void highbd_copy_and_extend_plane(const uint16_t *src, int src_pitch,
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]));
Expand All @@ -69,8 +72,8 @@ void av2_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
const int eb_y = AVMMAX(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;
Expand Down
5 changes: 3 additions & 2 deletions avm_scale/generic/yv12extend.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ static void extend_plane_high(uint16_t *const src, int src_stride, int width,
int extend_bottom, int extend_right) {
int i;
const int linesize = extend_left + extend_right + width;
assert(linesize <= src_stride);

/* copy the left and right most columns out */
uint16_t *src_ptr1 = src;
Expand Down Expand Up @@ -62,8 +63,8 @@ static void extend_plane_high(uint16_t *const src, int src_stride, int width,

static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size,
const int num_planes) {
const int ss_x = ybf->uv_width < ybf->y_width;
const int ss_y = ybf->uv_height < ybf->y_height;
const int ss_x = ybf->subsampling_x;
const int ss_y = ybf->subsampling_y;

assert(ybf->y_height - ybf->y_crop_height < 16);
assert(ybf->y_width - ybf->y_crop_width < 16);
Expand Down
5 changes: 3 additions & 2 deletions avm_scale/mips/dspr2/yv12extend_dspr2.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ static void extend_plane(uint8_t *const src, int src_stride, int width,
top_dst = src + src_stride * (-extend_top) - extend_left;
bot_dst = src + src_stride * (height)-extend_left;
linesize = extend_left + extend_right + width;
assert(linesize <= src_stride);
Comment thread
wantehchang marked this conversation as resolved.

for (i = 0; i < extend_top; i++) {
memcpy(top_dst, top_src, linesize);
Expand All @@ -106,8 +107,8 @@ static void extend_plane(uint8_t *const src, int src_stride, int width,
static void extend_frame(YV12_BUFFER_CONFIG *const ybf, int ext_size) {
const int c_w = ybf->uv_crop_width;
const int c_h = ybf->uv_crop_height;
const int ss_x = ybf->uv_width < ybf->y_width;
const int ss_y = ybf->uv_height < ybf->y_height;
const int ss_x = ybf->subsampling_x;
const int ss_y = ybf->subsampling_y;
const int c_et = ext_size >> ss_y;
const int c_el = ext_size >> ss_x;
const int c_eb = c_et + ybf->uv_height - ybf->uv_crop_height;
Expand Down
53 changes: 53 additions & 0 deletions test/encode_small_width_height_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
// (<= one AV2 superblock) with multiple threads. avm_codec_encode() should
// not crash.

#include <cstring>
#include <memory>

#include "third_party/googletest/src/googletest/include/gtest/gtest.h"

#include "avm/avmcx.h"
Expand Down Expand Up @@ -138,4 +141,54 @@ TEST(EncodeSmallWidthHeight, SmallHeightMultiThreadedSpeed0) {
EXPECT_EQ(AVM_CODEC_OK, avm_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 avm_img_alloc() or avm_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.
avm_image_t img;
memset(&img, 0, sizeof(img));
img.fmt = AVM_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[AVM_PLANE_Y] = y_stride;
img.stride[AVM_PLANE_U] = img.stride[AVM_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[AVM_PLANE_Y] = y_plane.get();
img.planes[AVM_PLANE_U] = u_plane.get();
img.planes[AVM_PLANE_V] = v_plane.get();

avm_codec_iface_t *iface = avm_codec_av2_cx();
avm_codec_enc_cfg_t cfg;
EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_config_default(iface, &cfg, 0));
cfg.g_w = kWidth;
cfg.g_h = kHeight;
avm_codec_ctx_t enc;
EXPECT_EQ(AVM_CODEC_OK, avm_codec_enc_init(&enc, iface, &cfg, 0));
EXPECT_EQ(AVM_CODEC_OK, avm_codec_control(&enc, AVME_SET_CPUUSED, 5));
EXPECT_EQ(AVM_CODEC_OK, avm_codec_encode(&enc, &img, 0, 1, 0));
EXPECT_EQ(AVM_CODEC_OK, avm_codec_encode(&enc, NULL, 0, 0, 0));
EXPECT_EQ(AVM_CODEC_OK, avm_codec_destroy(&enc));
}

} // namespace
Loading