ref: 07b12aad7787c4346c9e42b3134bc0062eba89c6
parent: bd990cad72ecdc864ebfd4470dbbd747974f3aa9
author: Hui Su <huisu@google.com>
date: Tue Nov 28 12:38:47 EST 2017
Add max luma picture width/height constraint in VP9 level BUG=b/65412009 Change-Id: I9e1478dcbd2ef9e97f5f8fb5a1c733b5f5cdf396
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -437,34 +437,37 @@
/* clang-format off */
const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = {
- { LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8 },
- { LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8 },
- { LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8 },
- { LEVEL_2_1, 9216000, 245760, 3600, 2800, 2, 2, 4, 8 },
- { LEVEL_3, 20736000, 552960, 7200, 6000, 2, 4, 4, 8 },
- { LEVEL_3_1, 36864000, 983040, 12000, 10000, 2, 4, 4, 8 },
- { LEVEL_4, 83558400, 2228224, 18000, 16000, 4, 4, 4, 8 },
- { LEVEL_4_1, 160432128, 2228224, 30000, 18000, 4, 4, 5, 6 },
- { LEVEL_5, 311951360, 8912896, 60000, 36000, 6, 8, 6, 4 },
- { LEVEL_5_1, 588251136, 8912896, 120000, 46000, 8, 8, 10, 4 },
+ // sample rate size breadth bitrate cpb
+ { LEVEL_1, 829440, 36864, 512, 200, 400, 2, 1, 4, 8 },
+ { LEVEL_1_1, 2764800, 73728, 768, 800, 1000, 2, 1, 4, 8 },
+ { LEVEL_2, 4608000, 122880, 960, 1800, 1500, 2, 1, 4, 8 },
+ { LEVEL_2_1, 9216000, 245760, 1344, 3600, 2800, 2, 2, 4, 8 },
+ { LEVEL_3, 20736000, 552960, 2048, 7200, 6000, 2, 4, 4, 8 },
+ { LEVEL_3_1, 36864000, 983040, 2752, 12000, 10000, 2, 4, 4, 8 },
+ { LEVEL_4, 83558400, 2228224, 4160, 18000, 16000, 4, 4, 4, 8 },
+ { LEVEL_4_1, 160432128, 2228224, 4160, 30000, 18000, 4, 4, 5, 6 },
+ { 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
// they are finalized (currently tentative).
- { LEVEL_5_2, 1176502272, 8912896, 180000, 90000, 8, 8, 10, 4 },
- { LEVEL_6, 1176502272, 35651584, 180000, 90000, 8, 16, 10, 4 },
- { LEVEL_6_1, 2353004544u, 35651584, 240000, 180000, 8, 16, 10, 4 },
- { LEVEL_6_2, 4706009088u, 35651584, 480000, 360000, 8, 16, 10, 4 },
+ { LEVEL_5_2, 1176502272, 8912896, 8384, 180000, 90000, 8, 8, 10, 4 },
+ { LEVEL_6, 1176502272, 35651584, 16832, 180000, 90000, 8, 16, 10, 4 },
+ { LEVEL_6_1, 2353004544u, 35651584, 16832, 240000, 180000, 8, 16, 10, 4 },
+ { LEVEL_6_2, 4706009088u, 35651584, 16832, 480000, 360000, 8, 16, 10, 4 },
};
/* clang-format on */
-static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] =
- { "The average bit-rate is too high.",
- "The picture size is too large.",
- "The luma sample rate is too large.",
- "The CPB size is too large.",
- "The compression ratio is too small",
- "Too many column tiles are used.",
- "The alt-ref distance is too small.",
- "Too many reference buffers are used." };
+static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = {
+ "The average bit-rate is too high.",
+ "The picture size is too large.",
+ "The picture width/height is too large.",
+ "The luma sample rate is too large.",
+ "The CPB size is too large.",
+ "The compression ratio is too small",
+ "Too many column tiles 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) {
switch (mode) {
@@ -566,6 +569,8 @@
(double)this_level->max_luma_sample_rate *
(1 + SAMPLE_RATE_GRACE_P) ||
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->max_cpb_size > this_level->max_cpb_size ||
level_spec->compression_ratio < this_level->compression_ratio ||
@@ -1219,8 +1224,8 @@
}
if (cpi->oxcf.target_level == LEVEL_AUTO) {
- const uint32_t pic_size = cpi->common.width * cpi->common.height;
- const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size);
+ const int level_tile_cols =
+ log_tile_cols_from_picsize_level(cpi->common.width, cpi->common.height);
if (cm->log2_tile_cols > level_tile_cols) {
cm->log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
}
@@ -4825,6 +4830,7 @@
int i, idx;
uint64_t luma_samples, dur_end;
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;
const int8_t level_index = level_constraint->level_index;
double cpb_data_size;
@@ -4928,6 +4934,11 @@
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
level_spec->compression_ratio = (double)level_stats->total_uncompressed_size *
cm->bit_depth /
@@ -4946,6 +4957,15 @@
"Failed to encode to the target level %d. %s",
vp9_level_defs[level_index].level,
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 >
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -383,6 +383,7 @@
VP9_LEVEL level;
uint64_t max_luma_sample_rate;
uint32_t max_luma_picture_size;
+ uint32_t max_luma_picture_breadth;
double average_bitrate; // in kilobits per second
double max_cpb_size; // in kilobits
double compression_ratio;
@@ -422,14 +423,15 @@
typedef enum {
BITRATE_TOO_LARGE = 0,
- LUMA_PIC_SIZE_TOO_LARGE = 1,
- LUMA_SAMPLE_RATE_TOO_LARGE = 2,
- CPB_TOO_LARGE = 3,
- COMPRESSION_RATIO_TOO_SMALL = 4,
- TOO_MANY_COLUMN_TILE = 5,
- ALTREF_DIST_TOO_SMALL = 6,
- TOO_MANY_REF_BUFFER = 7,
- TARGET_LEVEL_FAIL_IDS = 8
+ LUMA_PIC_SIZE_TOO_LARGE,
+ LUMA_PIC_BREADTH_TOO_LARGE,
+ LUMA_SAMPLE_RATE_TOO_LARGE,
+ CPB_TOO_LARGE,
+ COMPRESSION_RATIO_TOO_SMALL,
+ TOO_MANY_COLUMN_TILE,
+ ALTREF_DIST_TOO_SMALL,
+ TOO_MANY_REF_BUFFER,
+ TARGET_LEVEL_FAIL_IDS
} TARGET_LEVEL_FAIL_ID;
typedef struct {
@@ -920,10 +922,14 @@
// Return the log2 value of max column tiles corresponding to the level that
// 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;
+ const uint32_t pic_size = width * height;
+ const uint32_t pic_breadth = VPXMAX(width, height);
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);
}
}
--- a/vp9/encoder/vp9_ethread.c
+++ b/vp9/encoder/vp9_ethread.c
@@ -66,8 +66,8 @@
log2_tile_cols =
clamp(cpi->oxcf.tile_columns, min_log2_tile_cols, max_log2_tile_cols);
if (cpi->oxcf.target_level == LEVEL_AUTO) {
- const uint32_t pic_size = cpi->common.width * cpi->common.height;
- const int level_tile_cols = log_tile_cols_from_picsize_level(pic_size);
+ const int level_tile_cols =
+ log_tile_cols_from_picsize_level(cpi->common.width, cpi->common.height);
if (log2_tile_cols > level_tile_cols) {
log2_tile_cols = VPXMAX(level_tile_cols, min_log2_tile_cols);
}
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -1873,9 +1873,12 @@
if (oxcf->target_level == LEVEL_AUTO) {
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;
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 <=
(int)vp9_level_defs[i].min_altref_distance) {
rc->min_gf_interval =