History

Merge "Add support for VP9 level targeting"

Hui Su committed 9 years ago

Commit c7e2bd62 parents 316071d 337ad834 files · +265 −4Browse files

Unified · Split

4 files
  1. test/level_test.cc +31 −0
  2. vp9/encoder/vp9_encoder.c +133 −3
  3. vp9/encoder/vp9_encoder.h +33 −1
  4. vp9/vp9_cx_iface.c +68 −0
test/level_test.cc+31−0
@@ -66,6 +66,36 @@ class LevelTest · 65 unmodified lines
6666 int level_;
6767 };
6868
69+TEST_P(LevelTest, TestTargetLevel11) {
70+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
71+ ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
72+ 90);
73+ target_level_ = 11;
74+ cfg_.rc_target_bitrate = 150;
75+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
76+ ASSERT_EQ(target_level_, level_);
77+}
78+
79+TEST_P(LevelTest, TestTargetLevel20) {
80+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
81+ ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
82+ 30, 1, 0, 90);
83+ target_level_ = 20;
84+ cfg_.rc_target_bitrate = 1200;
85+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
86+ ASSERT_EQ(target_level_, level_);
87+}
88+
89+TEST_P(LevelTest, TestTargetLevel31) {
90+ ASSERT_NE(encoding_mode_, ::libvpx_test::kRealTime);
91+ ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720, 30,
92+ 1, 0, 60);
93+ target_level_ = 31;
94+ cfg_.rc_target_bitrate = 8000;
95+ ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
96+ ASSERT_EQ(target_level_, level_);
97+}
98+
6999 // Test for keeping level stats only
70100 TEST_P(LevelTest, TestTargetLevel0) {
71101 ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
@@ -94,6 +124,7 @@ TEST_P(LevelTest, TestTargetLevelApi) { · 22 unmodified lines
94124 vpx_codec_ctx_t enc;
95125 vpx_codec_enc_cfg_t cfg;
96126 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(codec, &cfg, 0));
127+ cfg.rc_target_bitrate = 100;
97128 EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, codec, &cfg, 0));
98129 for (int level = 0; level <= 256; ++level) {
99130 if (level == 10 || level == 11 || level == 20 || level == 21 ||
vp9/encoder/vp9_encoder.c+133−3
@@ -108,7 +108,7 @@ static int is_psnr_calc_enabled(VP9_COMP *cpi) { · 107 unmodified lines
108108 }
109109
110110 /* clang-format off */
111−static const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = {
111+const Vp9LevelSpec vp9_level_defs[VP9_LEVELS] = {
112112 { LEVEL_1, 829440, 36864, 200, 400, 2, 1, 4, 8 },
113113 { LEVEL_1_1, 2764800, 73728, 800, 1000, 2, 1, 4, 8 },
114114 { 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
128128 };
129129 /* clang-format on */
130130
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+
131141 static INLINE void Scale2Ratio(VPX_SCALING mode, int *hr, int *hs) {
132142 switch (mode) {
133143 case NORMAL:
@@ -224,8 +234,9 @@ VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec) { · 90 unmodified lines
224234
225235 for (i = 0; i < VP9_LEVELS; ++i) {
226236 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) ||
229240 level_spec->max_luma_picture_size > this_level->max_luma_picture_size ||
230241 level_spec->average_bitrate > this_level->average_bitrate ||
231242 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
878889 cpi->alt_fb_idx = 2;
879890 }
880891
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+
881908 static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) {
882909 VP9_COMMON *const cm = &cpi->common;
883910
@@ -893,6 +920,8 @@ static void init_config(struct VP9_COMP *cpi, VP9EncoderConfig *oxcf) { · 9 unmodified lines
893920
894921 cpi->target_level = oxcf->target_level;
895922 cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX;
923+ set_level_constraint(&cpi->level_constraint,
924+ get_level_index(cpi->target_level));
896925
897926 cm->width = oxcf->width;
898927 cm->height = oxcf->height;
@@ -1409,6 +1438,8 @@ void vp9_change_config(struct VP9_COMP *cpi, const VP9EncoderConfig *oxcf) { · 510 unmodified lines
14091438
14101439 cpi->target_level = oxcf->target_level;
14111440 cpi->keep_level_stats = oxcf->target_level != LEVEL_MAX;
1441+ set_level_constraint(&cpi->level_constraint,
1442+ get_level_index(cpi->target_level));
14121443
14131444 if (cm->profile <= PROFILE_1)
14141445 assert(cm->bit_depth == VPX_BITS_8);
@@ -1685,6 +1716,7 @@ VP9_COMP *vp9_create_compressor(VP9EncoderConfig *oxcf, · 270 unmodified lines
16851716 cpi->b_calculate_psnr = CONFIG_INTERNAL_STATS;
16861717
16871718 init_level_info(&cpi->level_info);
1719+ init_level_constraint(&cpi->level_constraint);
16881720
16891721 #if CONFIG_INTERNAL_STATS
16901722 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
43134345 }
43144346 #endif // CONFIG_INTERNAL_STATS
43154347
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+
43164368 static void update_level_info(VP9_COMP *cpi, size_t *size, int arf_src_index) {
43174369 VP9_COMMON *const cm = &cpi->common;
43184370 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
43214373 int i, idx;
43224374 uint64_t luma_samples, dur_end;
43234375 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;
43244378 double cpb_data_size;
43254379
43264380 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
44314485 if (level_spec->max_col_tiles < (1 << cm->log2_tile_cols)) {
44324486 level_spec->max_col_tiles = (1 << cm->log2_tile_cols);
44334487 }
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+ }
44344560 }
44354561
44364562 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
46584784 set_frame_size(cpi);
46594785 }
46604786
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+
46614791 if (cpi->oxcf.pass != 0 || cpi->use_svc || frame_is_intra_only(cm) == 1) {
46624792 for (i = 0; i < MAX_REF_FRAMES; ++i) cpi->scaled_ref_idx[i] = INVALID_IDX;
46634793 }
vp9/encoder/vp9_encoder.h+33−1
@@ -237,7 +237,7 @@ typedef struct VP9EncoderConfig { · 236 unmodified lines
237237
238238 int max_threads;
239239
240− int target_level;
240+ unsigned int target_level;
241241
242242 vpx_fixed_buf_t two_pass_stats_in;
243243 struct vpx_codec_pkt_list *output_pkt_list;
@@ -341,6 +341,8 @@ typedef struct { · 97 unmodified lines
341341 uint8_t max_ref_frame_buffers;
342342 } Vp9LevelSpec;
343343
344+extern const Vp9LevelSpec vp9_level_defs[VP9_LEVELS];
345+
344346 typedef struct {
345347 int64_t ts; // timestamp
346348 uint32_t luma_samples;
@@ -368,6 +370,26 @@ typedef struct { · 21 unmodified lines
368370 Vp9LevelSpec level_spec;
369371 } Vp9LevelInfo;
370372
373+typedef enum {
374+ BITRATE_TOO_LARGE = 0,
375+ LUMA_PIC_SIZE_TOO_LARGE = 1,
376+ LUMA_SAMPLE_RATE_TOO_LARGE = 2,
377+ CPB_TOO_LARGE = 3,
378+ COMPRESSION_RATIO_TOO_SMALL = 4,
379+ TOO_MANY_COLUMN_TILE = 5,
380+ ALTREF_DIST_TOO_SMALL = 6,
381+ TOO_MANY_REF_BUFFER = 7,
382+ TARGET_LEVEL_FAIL_IDS = 8
383+} TARGET_LEVEL_FAIL_ID;
384+
385+typedef struct {
386+ int8_t level_index;
387+ uint8_t rc_config_updated;
388+ uint8_t fail_flag;
389+ int max_frame_size; // in bits
390+ double max_cpb_size; // in bits
391+} LevelConstraint;
392+
371393 typedef struct VP9_COMP {
372394 QUANTS quants;
373395 ThreadData td;
@@ -611,6 +633,8 @@ typedef struct VP9_COMP { · 237 unmodified lines
611633 // Previous Partition Info
612634 BLOCK_SIZE *prev_partition;
613635 int8_t *prev_segment_id;
636+
637+ LevelConstraint level_constraint;
614638 } VP9_COMP;
615639
616640 void vp9_initialize_enc(void);
@@ -766,6 +790,14 @@ static INLINE int *cond_cost_list(const struct VP9_COMP *cpi, int *cost_list) { · 149 unmodified lines
766790 return cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL;
767791 }
768792
793+static INLINE int get_level_index(VP9_LEVEL level) {
794+ int i;
795+ for (i = 0; i < VP9_LEVELS; ++i) {
796+ if (level == vp9_level_defs[i].level) return i;
797+ }
798+ return -1;
799+}
800+
769801 VP9_LEVEL vp9_get_level(const Vp9LevelSpec *const level_spec);
770802
771803 void vp9_new_framerate(VP9_COMP *cpi, double framerate);
vp9/vp9_cx_iface.c+68−0
@@ -390,6 +390,50 @@ static int get_image_bps(const vpx_image_t *img) { · 389 unmodified lines
390390 return 0;
391391 }
392392
393+// Modify the encoder config for the target level.
394+static void config_target_level(VP9EncoderConfig *oxcf) {
395+ double max_average_bitrate; // in bits per second
396+ int max_over_shoot_pct;
397+ const int target_level_index = get_level_index(oxcf->target_level);
398+
399+ vpx_clear_system_state();
400+ assert(target_level_index >= 0);
401+ assert(target_level_index < VP9_LEVELS);
402+
403+ // Maximum target bit-rate is level_limit * 80%.
404+ max_average_bitrate =
405+ vp9_level_defs[target_level_index].average_bitrate * 800.0;
406+ if ((double)oxcf->target_bandwidth > max_average_bitrate)
407+ oxcf->target_bandwidth = (int64_t)(max_average_bitrate);
408+ if (oxcf->ss_number_layers == 1 && oxcf->pass != 0)
409+ oxcf->ss_target_bitrate[0] = (int)oxcf->target_bandwidth;
410+
411+ // Adjust max over-shoot percentage.
412+ max_over_shoot_pct =
413+ (int)((max_average_bitrate * 1.10 - (double)oxcf->target_bandwidth) *
414+ 100 / (double)(oxcf->target_bandwidth));
415+ if (oxcf->over_shoot_pct > max_over_shoot_pct)
416+ oxcf->over_shoot_pct = max_over_shoot_pct;
417+
418+ // Adjust worst allowed quantizer.
419+ oxcf->worst_allowed_q = vp9_quantizer_to_qindex(63);
420+
421+ // Adjust minimum art-ref distance.
422+ if (oxcf->min_gf_interval <
423+ (int)vp9_level_defs[target_level_index].min_altref_distance)
424+ oxcf->min_gf_interval =
425+ (int)vp9_level_defs[target_level_index].min_altref_distance;
426+
427+ // Adjust maximum column tiles.
428+ if (vp9_level_defs[target_level_index].max_col_tiles <
429+ (1 << oxcf->tile_columns)) {
430+ while (oxcf->tile_columns > 0 &&
431+ vp9_level_defs[target_level_index].max_col_tiles <
432+ (1 << oxcf->tile_columns))
433+ --oxcf->tile_columns;
434+ }
435+}
436+
393437 static vpx_codec_err_t set_encoder_config(
394438 VP9EncoderConfig *oxcf, const vpx_codec_enc_cfg_t *cfg,
395439 const struct vp9_extracfg *extra_cfg) {
@@ -533,6 +577,8 @@ static vpx_codec_err_t set_encoder_config( · 137 unmodified lines
533577 } else if (oxcf->ts_number_layers == 1) {
534578 oxcf->ts_rate_decimator[0] = 1;
535579 }
580+
581+ if (get_level_index(oxcf->target_level) >= 0) config_target_level(oxcf);
536582 /*
537583 printf("Current VP9 Settings: \n");
538584 printf("target_bandwidth: %d\n", oxcf->target_bandwidth);
@@ -1003,6 +1049,28 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, · 464 unmodified lines
10031049
10041050 if (cpi == NULL) return VPX_CODEC_INVALID_PARAM;
10051051
1052+ if (cpi->oxcf.pass == 2 && cpi->level_constraint.level_index >= 0 &&
1053+ !cpi->level_constraint.rc_config_updated) {
1054+ SVC *const svc = &cpi->svc;
1055+ const int is_two_pass_svc =
1056+ (svc->number_spatial_layers > 1) || (svc->number_temporal_layers > 1);
1057+ const VP9EncoderConfig *const oxcf = &cpi->oxcf;
1058+ TWO_PASS *const twopass = &cpi->twopass;
1059+ FIRSTPASS_STATS *stats = &twopass->total_stats;
1060+ if (is_two_pass_svc) {
1061+ const double frame_rate = 10000000.0 * stats->count / stats->duration;
1062+ vp9_update_spatial_layer_framerate(cpi, frame_rate);
1063+ twopass->bits_left =
1064+ (int64_t)(stats->duration *
1065+ svc->layer_context[svc->spatial_layer_id].target_bandwidth /
1066+ 10000000.0);
1067+ } else {
1068+ twopass->bits_left =
1069+ (int64_t)(stats->duration * oxcf->target_bandwidth / 10000000.0);
1070+ }
1071+ cpi->level_constraint.rc_config_updated = 1;
1072+ }
1073+
10061074 if (img != NULL) {
10071075 res = validate_img(ctx, img);
10081076 if (res == VPX_CODEC_OK) {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t