| @@ -108,7 +108,7 @@ static int is_psnr_calc_enabled(VP9_COMP *cpi) { · 107 unmodified lines |
| 108 | 108 | } |
| 109 | 109 | |
| 110 | 110 | /* clang-format off */ |
| 111 | | −static const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = { |
| 111 | +const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = { |
| 112 | 112 | { LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8 }, |
| 113 | 113 | { LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8 }, |
| 114 | 114 | { LEVEL_2, 4608000, 122880, 1800, 1500, 2, 1, 4, 8 }, |
| @@ -128,6 +128,16 @@ static const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = { · 13 unmodified lines |
| 128 | 128 | }; |
| 129 | 129 | /* clang-format on */ |
| 130 | 130 | |
| 131 | +static const char *level_fail_messages[TARGET_LEVEL_FAIL_IDS] = |
| 132 | + { "The average bit-rate is too high.", |
| 133 | + "The picture size is too large.", |
| 134 | + "The luma sample rate is too large.", |
| 135 | + "The CPB size is too large.", |
| 136 | + "The compression ratio is too small", |
| 137 | + "Too many column tiles are used.", |
| 138 | + "The alt-ref distance is too small.", |
| 139 | + "Too many reference buffers are used." }; |
| 140 | + |
| 131 | 141 | static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) { |
| 132 | 142 | switch (mode) { |
| 133 | 143 | case NORMAL: |
| @@ -224,8 +234,9 @@ VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec) { · 90 unmodified lines |
| 224 | 234 | |
| 225 | 235 | for (i = 0; i < VP9_LEVELS; ++i) { |
| 226 | 236 | this_level = &vp9_level_defs[i]; |
| 227 | | − if ((double)level_spec->max_luma_sample_rate * (1 + SAMPLE_RATE_GRACE_P) > |
| 228 | | − (double)this_level->max_luma_sample_rate || |
| 237 | + if ((double)level_spec->max_luma_sample_rate > |
| 238 | + (double)this_level->max_luma_sample_rate * |
| 239 | + (1 + SAMPLE_RATE_GRACE_P) || |
| 229 | 240 | level_spec->max_luma_picture_size > this_level->max_luma_picture_size || |
| 230 | 241 | level_spec->average_bitrate > this_level->average_bitrate || |
| 231 | 242 | level_spec->max_cpb_size > this_level->max_cpb_size || |
| @@ -878,6 +889,22 @@ static void init_buffer_indices(VP9_COMP *cpi) { · 646 unmodified lines |
| 878 | 889 | cpi->alt_fb_idx = 2; |
| 879 | 890 | } |
| 880 | 891 | |
| 892 | +static void init_level_constraint(LevelConstraint *lc) { |
| 893 | + lc->level_index = -1; |
| 894 | + lc->max_cpb_size = INT_MAX; |
| 895 | + lc->max_frame_size = INT_MAX; |
| 896 | + lc->rc_config_updated = 0; |
| 897 | + lc->fail_flag = 0; |
| 898 | +} |
| 899 | + |
| 900 | +static void set_level_constraint(LevelConstraint *ls, int8_t level_index) { |
| 901 | + vpx_clear_system_state(); |
| 902 | + ls->level_index = level_index; |
| 903 | + if (level_index >= 0) { |
| 904 | + ls->max_cpb_size = vp9_level_defs[level_index].max_cpb_size * (double)1000; |
| 905 | + } |
| 906 | +} |
| 907 | + |
| 881 | 908 | static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) { |
| 882 | 909 | VP9_COMMON *const cm = &cpi->common; |
| 883 | 910 | |
| @@ -893,6 +920,8 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) { · 9 unmodified lines |
| 893 | 920 | |
| 894 | 921 | cpi->target_level = oxcf->target_level; |
| 895 | 922 | cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX; |
| 923 | + set_level_constraint(&cpi->level_constraint, |
| 924 | + get_level_index(cpi->target_level)); |
| 896 | 925 | |
| 897 | 926 | cm->width = oxcf->width; |
| 898 | 927 | cm->height = oxcf->height; |
| @@ -1409,6 +1438,8 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { · 510 unmodified lines |
| 1409 | 1438 | |
| 1410 | 1439 | cpi->target_level = oxcf->target_level; |
| 1411 | 1440 | cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX; |
| 1441 | + set_level_constraint(&cpi->level_constraint, |
| 1442 | + get_level_index(cpi->target_level)); |
| 1412 | 1443 | |
| 1413 | 1444 | if (cm->profile <= PROFILE_1) |
| 1414 | 1445 | assert(cm->bit_depth == VPX_BITS_8); |
| @@ -1685,6 +1716,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf, · 270 unmodified lines |
| 1685 | 1716 | cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS; |
| 1686 | 1717 | |
| 1687 | 1718 | init_level_info(&cpi->level_info); |
| 1719 | + init_level_constraint(&cpi->level_constraint); |
| 1688 | 1720 | |
| 1689 | 1721 | #if CONFIG_INTERNAL_STATS |
| 1690 | 1722 | cpi->b_calculate_blockiness = 1; |
| @@ -4313,6 +4345,26 @@ static void adjust_image_stat(double y, double u, double v, double all, · 2622 unmodified lines |
| 4313 | 4345 | } |
| 4314 | 4346 | #endif // CONFIG_INTERNAL_STATS |
| 4315 | 4347 | |
| 4348 | +// Adjust the maximum allowable frame size for the target level. |
| 4349 | +static void level_rc_framerate(VP9_COMP *cpi, int arf_src_index) { |
| 4350 | + RATE_CONTROL *const rc = &cpi->rc; |
| 4351 | + LevelConstraint *const ls = &cpi->level_constraint; |
| 4352 | + VP9_COMMON *const cm = &cpi->common; |
| 4353 | + const double max_cpb_size = ls->max_cpb_size; |
| 4354 | + vpx_clear_system_state(); |
| 4355 | + rc->max_frame_bandwidth = VPXMIN(rc->max_frame_bandwidth, ls->max_frame_size); |
| 4356 | + if (frame_is_intra_only(cm)) { |
| 4357 | + rc->max_frame_bandwidth = |
| 4358 | + VPXMIN(rc->max_frame_bandwidth, (int)(max_cpb_size * 0.5)); |
| 4359 | + } else if (arf_src_index > 0) { |
| 4360 | + rc->max_frame_bandwidth = |
| 4361 | + VPXMIN(rc->max_frame_bandwidth, (int)(max_cpb_size * 0.4)); |
| 4362 | + } else { |
| 4363 | + rc->max_frame_bandwidth = |
| 4364 | + VPXMIN(rc->max_frame_bandwidth, (int)(max_cpb_size * 0.2)); |
| 4365 | + } |
| 4366 | +} |
| 4367 | + |
| 4316 | 4368 | static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { |
| 4317 | 4369 | VP9_COMMON *const cm = &cpi->common; |
| 4318 | 4370 | Vp9LevelInfo *const level_info = &cpi->level_info; |
| @@ -4321,6 +4373,8 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { · 2 unmodified lines |
| 4321 | 4373 | int i, idx; |
| 4322 | 4374 | uint64_t luma_samples, dur_end; |
| 4323 | 4375 | const uint32_t luma_pic_size = cm->width * cm->height; |
| 4376 | + LevelConstraint *const level_constraint = &cpi->level_constraint; |
| 4377 | + const int8_t level_index = level_constraint->level_index; |
| 4324 | 4378 | double cpb_data_size; |
| 4325 | 4379 | |
| 4326 | 4380 | vpx_clear_system_state(); |
| @@ -4431,6 +4485,78 @@ static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) { · 104 unmodified lines |
| 4431 | 4485 | if (level_spec->max_col_tiles < (1 << cm->log2_tile_cols)) { |
| 4432 | 4486 | level_spec->max_col_tiles = (1 << cm->log2_tile_cols); |
| 4433 | 4487 | } |
| 4488 | + |
| 4489 | + if (level_index >= 0 && level_constraint->fail_flag == 0) { |
| 4490 | + if (level_spec->max_luma_picture_size > |
| 4491 | + vp9_level_defs[level_index].max_luma_picture_size) { |
| 4492 | + level_constraint->fail_flag |= (1 << LUMA_PIC_SIZE_TOO_LARGE); |
| 4493 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4494 | + "Failed to encode to the target level %d. %s", |
| 4495 | + vp9_level_defs[level_index].level, |
| 4496 | + level_fail_messages[LUMA_PIC_SIZE_TOO_LARGE]); |
| 4497 | + } |
| 4498 | + |
| 4499 | + if ((double)level_spec->max_luma_sample_rate > |
| 4500 | + (double)vp9_level_defs[level_index].max_luma_sample_rate * |
| 4501 | + (1 + SAMPLE_RATE_GRACE_P)) { |
| 4502 | + level_constraint->fail_flag |= (1 << LUMA_SAMPLE_RATE_TOO_LARGE); |
| 4503 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4504 | + "Failed to encode to the target level %d. %s", |
| 4505 | + vp9_level_defs[level_index].level, |
| 4506 | + level_fail_messages[LUMA_SAMPLE_RATE_TOO_LARGE]); |
| 4507 | + } |
| 4508 | + |
| 4509 | + if (level_spec->max_col_tiles > vp9_level_defs[level_index].max_col_tiles) { |
| 4510 | + level_constraint->fail_flag |= (1 << TOO_MANY_COLUMN_TILE); |
| 4511 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4512 | + "Failed to encode to the target level %d. %s", |
| 4513 | + vp9_level_defs[level_index].level, |
| 4514 | + level_fail_messages[TOO_MANY_COLUMN_TILE]); |
| 4515 | + } |
| 4516 | + |
| 4517 | + if (level_spec->min_altref_distance < |
| 4518 | + vp9_level_defs[level_index].min_altref_distance) { |
| 4519 | + level_constraint->fail_flag |= (1 << ALTREF_DIST_TOO_SMALL); |
| 4520 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4521 | + "Failed to encode to the target level %d. %s", |
| 4522 | + vp9_level_defs[level_index].level, |
| 4523 | + level_fail_messages[ALTREF_DIST_TOO_SMALL]); |
| 4524 | + } |
| 4525 | + |
| 4526 | + if (level_spec->max_ref_frame_buffers > |
| 4527 | + vp9_level_defs[level_index].max_ref_frame_buffers) { |
| 4528 | + level_constraint->fail_flag |= (1 << TOO_MANY_REF_BUFFER); |
| 4529 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4530 | + "Failed to encode to the target level %d. %s", |
| 4531 | + vp9_level_defs[level_index].level, |
| 4532 | + level_fail_messages[TOO_MANY_REF_BUFFER]); |
| 4533 | + } |
| 4534 | + |
| 4535 | + if (level_spec->max_cpb_size > vp9_level_defs[level_index].max_cpb_size) { |
| 4536 | + level_constraint->fail_flag |= (1 << CPB_TOO_LARGE); |
| 4537 | + vpx_internal_error(&cm->error, VPX_CODEC_ERROR, |
| 4538 | + "Failed to encode to the target level %d. %s", |
| 4539 | + vp9_level_defs[level_index].level, |
| 4540 | + level_fail_messages[CPB_TOO_LARGE]); |
| 4541 | + } |
| 4542 | + |
| 4543 | + // Set an upper bound for the next frame size. It will be used in |
| 4544 | + // level_rc_framerate() before encoding the next frame. |
| 4545 | + cpb_data_size = 0; |
| 4546 | + for (i = 0; i < CPB_WINDOW_SIZE - 1; ++i) { |
| 4547 | + if (i >= level_stats->frame_window_buffer.len) break; |
| 4548 | + idx = (level_stats->frame_window_buffer.start + |
| 4549 | + level_stats->frame_window_buffer.len - 1 - i) % |
| 4550 | + FRAME_WINDOW_SIZE; |
| 4551 | + cpb_data_size += level_stats->frame_window_buffer.buf[idx].size; |
| 4552 | + } |
| 4553 | + cpb_data_size = cpb_data_size / 125.0; |
| 4554 | + level_constraint->max_frame_size = |
| 4555 | + (int)((vp9_level_defs[level_index].max_cpb_size - cpb_data_size) * |
| 4556 | + 1000.0); |
| 4557 | + if (level_stats->frame_window_buffer.len < CPB_WINDOW_SIZE - 1) |
| 4558 | + level_constraint->max_frame_size >>= 1; |
| 4559 | + } |
| 4434 | 4560 | } |
| 4435 | 4561 | |
| 4436 | 4562 | int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, |
| @@ -4658,6 +4784,10 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, · 221 unmodified lines |
| 4658 | 4784 | set_frame_size(cpi); |
| 4659 | 4785 | } |
| 4660 | 4786 | |
| 4787 | + if (oxcf->pass != 1 && cpi->level_constraint.level_index >= 0 && |
| 4788 | + cpi->level_constraint.fail_flag == 0) |
| 4789 | + level_rc_framerate(cpi, arf_src_index); |
| 4790 | + |
| 4661 | 4791 | if (cpi->oxcf.pass != 0 || cpi->use_svc || frame_is_intra_only(cm) == 1) { |
| 4662 | 4792 | for (i = 0; i < MAX_REF_FRAMES; ++i) cpi->scaled_ref_idx[i] = INVALID_IDX; |
| 4663 | 4793 | } |