Merge "Add max luma picture width/height constraint in VP9 level"

This commit is contained in:
Hui Su 2017-12-06 18:46:19 +00:00 committed by Gerrit Code Review
commit 2e44f16443
4 changed files with 67 additions and 38 deletions

View File

@ -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 picture width/height is too large.",
"The luma sample rate is too large.", "The luma sample rate is too large.",
"The CPB size is too large.", "The CPB size is too large.",
"The compression ratio is too small", "The compression ratio is too small",
"Too many column tiles are used.", "Too many column tiles are used.",
"The alt-ref distance is too small.", "The alt-ref distance is too small.",
"Too many reference buffers are used." }; "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) {
(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) {
} }
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);
} }
@ -4829,6 +4834,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;
@ -4932,6 +4938,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 /
@ -4952,6 +4963,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)) {

View File

@ -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 {
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) {
// 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);
} }
} }

View File

@ -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);
} }

View File

@ -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 =