Fix to buffer alloc for vp9_bitstream_worker_data

The code was using the bitstream_worker_data when it
wasn't allocated for big enough size. This is because
the existing condition was to only re-alloc the
bitstream_worker_data when current dest_size was larger
than the current frame_size. But under resolution change
where frame_size is increased, beyond the current dest_size,
we need to allow re-alloc to the new size.

The existing condition to re-alloc when dest_size is
larger than frame_size (which is not required) is kept
for now.

Also increase the dest_size to account for image format.

Added tests, for both ROW_MT=0 and 1, that reproduce
the failures in the bugs below.

Note: this issue only affects the REALTIME encoding path.

Bug: b/329088759, b/329674887, b/329179808

Change-Id: Icd65dbc5317120304d803f648d4bd9405710db6f
This commit is contained in:
Marco Paniconi
2024-03-13 10:58:17 -07:00
parent 7fb8ceccf9
commit c29e637283
2 changed files with 104 additions and 6 deletions
+93 -3
View File
@@ -875,12 +875,14 @@ TEST(EncodeAPI, ConfigLargeTargetBitrateVp9) {
class VP9Encoder {
public:
explicit VP9Encoder(int speed)
: speed_(speed), bit_depth_(VPX_BITS_8), fmt_(VPX_IMG_FMT_I420) {}
: speed_(speed), row_mt_(0), bit_depth_(VPX_BITS_8),
fmt_(VPX_IMG_FMT_I420) {}
// The image format `fmt` must not have the VPX_IMG_FMT_HIGHBITDEPTH bit set.
// If bit_depth > 8, we will set the VPX_IMG_FMT_HIGHBITDEPTH bit before
// passing the image format to vpx_img_alloc().
VP9Encoder(int speed, vpx_bit_depth_t bit_depth, vpx_img_fmt_t fmt)
: speed_(speed), bit_depth_(bit_depth), fmt_(fmt) {}
VP9Encoder(int speed, unsigned int row_mt, vpx_bit_depth_t bit_depth,
vpx_img_fmt_t fmt)
: speed_(speed), row_mt_(row_mt), bit_depth_(bit_depth), fmt_(fmt) {}
~VP9Encoder();
void Configure(unsigned int threads, unsigned int width, unsigned int height,
@@ -889,6 +891,7 @@ class VP9Encoder {
private:
const int speed_;
const unsigned int row_mt_;
const vpx_bit_depth_t bit_depth_;
const vpx_img_fmt_t fmt_;
bool initialized_ = false;
@@ -938,6 +941,7 @@ void VP9Encoder::Configure(unsigned int threads, unsigned int width,
high_bit_depth ? VPX_CODEC_USE_HIGHBITDEPTH : 0),
VPX_CODEC_OK);
ASSERT_EQ(vpx_codec_control(&enc_, VP8E_SET_CPUUSED, speed_), VPX_CODEC_OK);
ASSERT_EQ(vpx_codec_control(&enc_, VP9E_SET_ROW_MT, row_mt_), VPX_CODEC_OK);
initialized_ = true;
return;
}
@@ -1312,6 +1316,92 @@ TEST(EncodeAPI, Buganizer319964497) {
encoder.Encode(/*key_frame=*/false);
}
TEST(EncodeAPI, Buganizer329088759RowMT0) {
VP9Encoder encoder(8, 0, VPX_BITS_8, VPX_IMG_FMT_I444);
encoder.Configure(/*threads=*/8, /*width=*/1686, /*height=*/398, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/0, /*width=*/1686, /*height=*/1, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/0, /*width=*/1482, /*height=*/113, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/0, /*width=*/881, /*height=*/59, VPX_CBR,
VPX_DL_REALTIME);
encoder.Configure(/*threads=*/13, /*width=*/1271, /*height=*/385, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/2, /*width=*/1, /*height=*/62, VPX_VBR,
VPX_DL_REALTIME);
}
TEST(EncodeAPI, Buganizer329088759RowMT1) {
VP9Encoder encoder(8, 1, VPX_BITS_8, VPX_IMG_FMT_I444);
encoder.Configure(/*threads=*/8, /*width=*/1686, /*height=*/398, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Encode(/*key_frame=*/false);
// Needs to set threads to non-zero to repro the issue.
encoder.Configure(/*threads=*/2, /*width=*/1686, /*height=*/1, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/2, /*width=*/1482, /*height=*/113, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/2, /*width=*/881, /*height=*/59, VPX_CBR,
VPX_DL_REALTIME);
encoder.Configure(/*threads=*/13, /*width=*/1271, /*height=*/385, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/2, /*width=*/1, /*height=*/62, VPX_VBR,
VPX_DL_REALTIME);
}
#if CONFIG_VP9_HIGHBITDEPTH
TEST(EncodeAPI, Buganizer329674887RowMT0BitDepth12) {
VP9Encoder encoder(8, 0, VPX_BITS_12, VPX_IMG_FMT_I444);
encoder.Configure(/*threads=*/2, /*width=*/1030, /*height=*/583, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/0, /*width=*/1030, /*height=*/1, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/0, /*width=*/548, /*height=*/322, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/16, /*width=*/24, /*height=*/583, VPX_CBR,
VPX_DL_GOOD_QUALITY);
}
TEST(EncodeAPI, Buganizer329179808RowMT0BitDepth10) {
VP9Encoder encoder(4, 0, VPX_BITS_10, VPX_IMG_FMT_I444);
encoder.Configure(/*threads=*/16, /*width=*/1488, /*height=*/5, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/16, /*width=*/839, /*height=*/1, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/11, /*width=*/657, /*height=*/5, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
}
TEST(EncodeAPI, Buganizer329179808RowMT1BitDepth10) {
VP9Encoder encoder(4, 1, VPX_BITS_10, VPX_IMG_FMT_I444);
encoder.Configure(/*threads=*/16, /*width=*/1488, /*height=*/5, VPX_VBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/true);
encoder.Configure(/*threads=*/16, /*width=*/839, /*height=*/1, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
encoder.Configure(/*threads=*/11, /*width=*/657, /*height=*/5, VPX_CBR,
VPX_DL_REALTIME);
encoder.Encode(/*key_frame=*/false);
}
#endif
#endif // CONFIG_VP9_ENCODER
} // namespace
+11 -3
View File
@@ -962,6 +962,14 @@ void vp9_bitstream_encode_tiles_buffer_dealloc(VP9_COMP *const cpi) {
}
}
static int encode_tiles_buffer_alloc_size(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
const int image_bps =
(8 + 2 * (8 >> (cm->subsampling_x + cm->subsampling_y))) *
(1 + (cm->bit_depth > 8));
return cpi->oxcf.width * cpi->oxcf.height * image_bps / 8;
}
static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
VP9_COMMON *const cm = &cpi->common;
int i;
@@ -972,7 +980,7 @@ static void encode_tiles_buffer_alloc(VP9_COMP *const cpi) {
memset(cpi->vp9_bitstream_worker_data, 0, worker_data_size);
for (i = 1; i < cpi->num_workers; ++i) {
cpi->vp9_bitstream_worker_data[i].dest_size =
cpi->oxcf.width * cpi->oxcf.height;
encode_tiles_buffer_alloc_size(cpi);
CHECK_MEM_ERROR(&cm->error, cpi->vp9_bitstream_worker_data[i].dest,
vpx_malloc(cpi->vp9_bitstream_worker_data[i].dest_size));
}
@@ -987,8 +995,8 @@ static size_t encode_tiles_mt(VP9_COMP *cpi, uint8_t *data_ptr) {
int tile_col = 0;
if (!cpi->vp9_bitstream_worker_data ||
cpi->vp9_bitstream_worker_data[1].dest_size >
(cpi->oxcf.width * cpi->oxcf.height)) {
cpi->vp9_bitstream_worker_data[1].dest_size !=
encode_tiles_buffer_alloc_size(cpi)) {
vp9_bitstream_encode_tiles_buffer_dealloc(cpi);
encode_tiles_buffer_alloc(cpi);
}