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:
+93
-3
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user