Commit 07b12aad authored by Hui Su's avatar Hui Su

Add max luma picture width/height constraint in VP9 level

BUG=b/65412009

Change-Id: I9e1478dcbd2ef9e97f5f8fb5a1c733b5f5cdf396
parent bd990cad
...@@ -437,34 +437,37 @@ static int is_psnr_calc_enabled(VP9_COMP *cpi) { ...@@ -437,34 +437,37 @@ static int is_psnr_calc_enabled(VP9_COMP *cpi) {
/* clang-format off */ /* clang-format off */
const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = { const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = {
{ LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8 }, // sample rate size breadth bitrate cpb
{ LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8 }, { LEVEL_1, 829440, 36864, 512, 200, 400, 2, 1, 4, 8 },
{ LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8 }, { LEVEL_1_1, 2764800, 73728, 768, 800, 1000, 2, 1, 4, 8 },
{ LEVEL_2_1, 9216000, 245760, 3600, 2800, 2, 2, 4, 8 }, { LEVEL_2, 4608000, 122880, 960, 1800, 1500, 2, 1, 4, 8 },
{ LEVEL_3, 20736000, 552960, 7200, 6000, 2, 4, 4, 8 }, { LEVEL_2_1, 9216000, 245760, 1344, 3600, 2800, 2, 2, 4, 8 },
{ LEVEL_3_1, 36864000, 983040, 12000, 10000, 2, 4, 4, 8 }, { LEVEL_3, 20736000, 552960, 2048, 7200, 6000, 2, 4, 4, 8 },
{ LEVEL_4, 83558400, 2228224, 18000, 16000, 4, 4, 4, 8 }, { LEVEL_3_1, 36864000, 983040, 2752, 12000, 10000, 2, 4, 4, 8 },
{ LEVEL_4_1, 160432128, 2228224, 30000, 18000, 4, 4, 5, 6 }, { LEVEL_4, 83558400, 2228224, 4160, 18000, 16000, 4, 4, 4, 8 },
{ LEVEL_5, 311951360, 8912896, 60000, 36000, 6, 8, 6, 4 }, { LEVEL_4_1, 160432128, 2228224, 4160, 30000, 18000, 4, 4, 5, 6 },
{ LEVEL_5_1, 588251136, 8912896, 120000, 46000, 8, 8, 10, 4 }, { LEVEL_5, 311951360, 8912896, 8384, 60000, 36000, 6, 8, 6, 4 },
{ LEVEL_5_1, 588251136, 8912896, 8384, 120000, 46000, 8, 8, 10, 4 },
// TODO(huisu): update max_cpb_size for level 5_2 ~ 6_2 when // TODO(huisu): update max_cpb_size for level 5_2 ~ 6_2 when
// they are finalized (currently tentative). // they are finalized (currently tentative).
{ LEVEL_5_2, 1176502272, 8912896, 180000, 90000, 8, 8, 10, 4 }, { LEVEL_5_2, 1176502272, 8912896, 8384, 180000, 90000, 8, 8, 10, 4 },
{ LEVEL_6, 1176502272, 35651584, 180000, 90000, 8, 16, 10, 4 }, { LEVEL_6, 1176502272, 35651584, 16832, 180000, 90000, 8, 16, 10, 4 },
{ LEVEL_6_1, 2353004544u, 35651584, 240000, 180000, 8, 16, 10, 4 }, { LEVEL_6_1, 2353004544u, 35651584, 16832, 240000, 180000, 8, 16, 10, 4 },
{ LEVEL_6_2, 4706009088u, 35651584, 480000, 360000, 8, 16, 10, 4 }, { LEVEL_6_2, 4706009088u, 35651584, 16832, 480000, 360000, 8, 16, 10, 4 },
}; };
/* clang-format on */ /* clang-format on */
static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = {
{ "The average bit-rate is too high.", "The average bit-rate is too high.",
"The picture size is too large.", "The picture size is too large.",
"The luma sample rate is too large.", "The picture width/height is too large.",
"The CPB size is too large.", "The luma sample rate is too large.",
"The compression ratio is too small", "The CPB size is too large.",
"Too many column tiles are used.", "The compression ratio is too small",
"The alt-ref distance is too small.", "Too many column tiles are used.",
"Too many reference buffers are used." }; "The alt-ref distance is too small.",
"Too many reference buffers are used."
};
static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) { static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) {
switch (mode) { switch (mode) {
...@@ -566,6 +569,8 @@ VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec) { ...@@ -566,6 +569,8 @@ VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec) {
(double)this_level->max_luma_sample_rate * (double)this_level->max_luma_sample_rate *
(1 + SAMPLE_RATE_GRACE_P) || (1 + SAMPLE_RATE_GRACE_P) ||
level_spec->max_luma_picture_size > this_level->max_luma_picture_size || level_spec->max_luma_picture_size > this_level->max_luma_picture_size ||
level_spec->max_luma_picture_breadth >
this_level->max_luma_picture_breadth ||
level_spec->average_bitrate > this_level->average_bitrate || level_spec->average_bitrate > this_level->average_bitrate ||
level_spec->max_cpb_size > this_level->max_cpb_size || level_spec->max_cpb_size > this_level->max_cpb_size ||
level_spec->compression_ratio < this_level->compression_ratio || level_spec->compression_ratio < this_level->compression_ratio ||
...@@ -1219,8 +1224,8 @@ static void set_tile_limits(VP9_COMP *cpi) { ...@@ -1219,8 +1224,8 @@ static void set_tile_limits(VP9_COMP *cpi) {
} }
if (cpi->oxcf.target_level == LEVEL_AUTO) { if (cpi->oxcf.target_level == LEVEL_AUTO) {
const uint32_t pic_size = cpi->common.width * cpi->common.height; const int level_tile_cols =
const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size); log_tile_cols_from_picsize_level(cpi->common.width, cpi->common.height);
if (cm->log2_tile_cols > level_tile_cols) { if (cm->log2_tile_cols > level_tile_cols) {
cm->log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols); cm->log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
} }
...@@ -4825,6 +4830,7 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { ...@@ -4825,6 +4830,7 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) {
int i, idx; int i, idx;
uint64_t luma_samples, dur_end; uint64_t luma_samples, dur_end;
const uint32_t luma_pic_size = cm->width * cm->height; const uint32_t luma_pic_size = cm->width * cm->height;
const uint32_t luma_pic_breadth = VPXMAX(cm->width, cm->height);
LevelConstraint *const level_constraint = &cpi->level_constraint; LevelConstraint *const level_constraint = &cpi->level_constraint;
const int8_t level_index = level_constraint->level_index; const int8_t level_index = level_constraint->level_index;
double cpb_data_size; double cpb_data_size;
...@@ -4928,6 +4934,11 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { ...@@ -4928,6 +4934,11 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) {
level_spec->max_luma_picture_size = luma_pic_size; level_spec->max_luma_picture_size = luma_pic_size;
} }
// update max_luma_picture_breadth
if (luma_pic_breadth > level_spec->max_luma_picture_breadth) {
level_spec->max_luma_picture_breadth = luma_pic_breadth;
}
// update compression_ratio // update compression_ratio
level_spec->compression_ratio = (double)level_stats->total_uncompressed_size * level_spec->compression_ratio = (double)level_stats->total_uncompressed_size *
cm->bit_depth / cm->bit_depth /
...@@ -4948,6 +4959,15 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { ...@@ -4948,6 +4959,15 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) {
level_fail_messages[LUMA_PIC_SIZE_TOO_LARGE]); level_fail_messages[LUMA_PIC_SIZE_TOO_LARGE]);
} }
if (level_spec->max_luma_picture_breadth >
vp9_level_defs[level_index].max_luma_picture_breadth) {
level_constraint->fail_flag |= (1 << LUMA_PIC_BREADTH_TOO_LARGE);
vpx_internal_error(&cm->error, VPX_CODEC_ERROR,
"Failed to encode to the target level %d. %s",
vp9_level_defs[level_index].level,
level_fail_messages[LUMA_PIC_BREADTH_TOO_LARGE]);
}
if ((double)level_spec->max_luma_sample_rate > if ((double)level_spec->max_luma_sample_rate >
(double)vp9_level_defs[level_index].max_luma_sample_rate * (double)vp9_level_defs[level_index].max_luma_sample_rate *
(1 + SAMPLE_RATE_GRACE_P)) { (1 + SAMPLE_RATE_GRACE_P)) {
......
...@@ -383,6 +383,7 @@ typedef struct { ...@@ -383,6 +383,7 @@ typedef struct {
VP9_LEVEL level; VP9_LEVEL level;
uint64_t max_luma_sample_rate; uint64_t max_luma_sample_rate;
uint32_t max_luma_picture_size; uint32_t max_luma_picture_size;
uint32_t max_luma_picture_breadth;
double average_bitrate; // in kilobits per second double average_bitrate; // in kilobits per second
double max_cpb_size; // in kilobits double max_cpb_size; // in kilobits
double compression_ratio; double compression_ratio;
...@@ -422,14 +423,15 @@ typedef struct { ...@@ -422,14 +423,15 @@ typedef struct {
typedef enum { typedef enum {
BITRATE_TOO_LARGE = 0, BITRATE_TOO_LARGE = 0,
LUMA_PIC_SIZE_TOO_LARGE = 1, LUMA_PIC_SIZE_TOO_LARGE,
LUMA_SAMPLE_RATE_TOO_LARGE = 2, LUMA_PIC_BREADTH_TOO_LARGE,
CPB_TOO_LARGE = 3, LUMA_SAMPLE_RATE_TOO_LARGE,
COMPRESSION_RATIO_TOO_SMALL = 4, CPB_TOO_LARGE,
TOO_MANY_COLUMN_TILE = 5, COMPRESSION_RATIO_TOO_SMALL,
ALTREF_DIST_TOO_SMALL = 6, TOO_MANY_COLUMN_TILE,
TOO_MANY_REF_BUFFER = 7, ALTREF_DIST_TOO_SMALL,
TARGET_LEVEL_FAIL_IDS = 8 TOO_MANY_REF_BUFFER,
TARGET_LEVEL_FAIL_IDS
} TARGET_LEVEL_FAIL_ID; } TARGET_LEVEL_FAIL_ID;
typedef struct { typedef struct {
...@@ -920,10 +922,14 @@ static INLINE int get_level_index(VP9_LEVEL level) { ...@@ -920,10 +922,14 @@ static INLINE int get_level_index(VP9_LEVEL level) {
// Return the log2 value of max column tiles corresponding to the level that // Return the log2 value of max column tiles corresponding to the level that
// the picture size fits into. // the picture size fits into.
static INLINE int log_tile_cols_from_picsize_level(uint32_t pic_size) { static INLINE int log_tile_cols_from_picsize_level(uint32_t width,
uint32_t height) {
int i; int i;
const uint32_t pic_size = width * height;
const uint32_t pic_breadth = VPXMAX(width, height);
for (i = LEVEL_1; i < LEVEL_MAX; ++i) { for (i = LEVEL_1; i < LEVEL_MAX; ++i) {
if (vp9_level_defs[i].max_luma_picture_size > pic_size) { if (vp9_level_defs[i].max_luma_picture_size >= pic_size &&
vp9_level_defs[i].max_luma_picture_breadth >= pic_breadth) {
return get_msb(vp9_level_defs[i].max_col_tiles); return get_msb(vp9_level_defs[i].max_col_tiles);
} }
} }
......
...@@ -66,8 +66,8 @@ static int get_max_tile_cols(VP9_COMP *cpi) { ...@@ -66,8 +66,8 @@ static int get_max_tile_cols(VP9_COMP *cpi) {
log2_tile_cols = log2_tile_cols =
clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols); clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
if (cpi->oxcf.target_level == LEVEL_AUTO) { if (cpi->oxcf.target_level == LEVEL_AUTO) {
const uint32_t pic_size = cpi->common.width * cpi->common.height; const int level_tile_cols =
const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size); log_tile_cols_from_picsize_level(cpi->common.width, cpi->common.height);
if (log2_tile_cols > level_tile_cols) { if (log2_tile_cols > level_tile_cols) {
log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols); log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
} }
......
...@@ -1873,9 +1873,12 @@ void vp9_rc_set_gf_interval_range(const VP9_COMP *const cpi, ...@@ -1873,9 +1873,12 @@ void vp9_rc_set_gf_interval_range(const VP9_COMP *const cpi,
if (oxcf->target_level == LEVEL_AUTO) { if (oxcf->target_level == LEVEL_AUTO) {
const uint32_t pic_size = cpi->common.width * cpi->common.height; const uint32_t pic_size = cpi->common.width * cpi->common.height;
const uint32_t pic_breadth =
VPXMAX(cpi->common.width, cpi->common.height);
int i; int i;
for (i = LEVEL_1; i < LEVEL_MAX; ++i) { for (i = LEVEL_1; i < LEVEL_MAX; ++i) {
if (vp9_level_defs[i].max_luma_picture_size > pic_size) { if (vp9_level_defs[i].max_luma_picture_size >= pic_size &&
vp9_level_defs[i].max_luma_picture_breadth >= pic_breadth) {
if (rc->min_gf_interval <= if (rc->min_gf_interval <=
(int)vp9_level_defs[i].min_altref_distance) { (int)vp9_level_defs[i].min_altref_distance) {
rc->min_gf_interval = rc->min_gf_interval =
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment