From: Cheng Chen Date: Wed, 30 Mar 2022 22:47:17 +0000 (-0700) Subject: L2E: Make SimpleEncode take vp9 level as an input X-Git-Tag: v1.12.0-rc1~56^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2c32425851cb89a1623ac7f3cf3d7bbba7aa32c6;p=libvpx L2E: Make SimpleEncode take vp9 level as an input Level conformance is standadized in vp9. If a specific target level is set, the vp9 encoder is required to produce conformant bitstream with limit on frame size, rate, min alt-ref distance, etc. This change makes the SimpleEncode environment take the target level as an input. To make existing tests pass, we set the level to 0. Change-Id: Ia35224f75c2fe50338b5b86a50c84355f5daf6fd --- diff --git a/test/simple_encode_test.cc b/test/simple_encode_test.cc index 03e28e338..01fc25856 100644 --- a/test/simple_encode_test.cc +++ b/test/simple_encode_test.cc @@ -37,13 +37,14 @@ class SimpleEncodeTest : public ::testing::Test { const int frame_rate_den_ = 1; const int target_bitrate_ = 1000; const int num_frames_ = 17; + const int target_level_ = LEVEL_UNKNOWN; const std::string in_file_path_str_ = libvpx_test::GetDataPath() + "/bus_352x288_420_f20_b8.yuv"; }; TEST_F(SimpleEncodeTest, ComputeFirstPassStats) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); std::vector> frame_stats = @@ -64,7 +65,7 @@ TEST_F(SimpleEncodeTest, ComputeFirstPassStats) { TEST_F(SimpleEncodeTest, ObserveFirstPassMotionVectors) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); std::vector> fps_motion_vectors = @@ -86,7 +87,7 @@ TEST_F(SimpleEncodeTest, ObserveFirstPassMotionVectors) { TEST_F(SimpleEncodeTest, GetCodingFrameNum) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -95,7 +96,7 @@ TEST_F(SimpleEncodeTest, GetCodingFrameNum) { TEST_F(SimpleEncodeTest, EncodeFrame) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -138,7 +139,7 @@ TEST_F(SimpleEncodeTest, EncodeFrame) { TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); std::vector key_frame_map = simple_encode.ObserveKeyFrameMap(); @@ -167,7 +168,7 @@ TEST_F(SimpleEncodeTest, ObserveKeyFrameMap) { TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -205,7 +206,7 @@ TEST_F(SimpleEncodeTest, EncodeFrameWithTargetFrameBits) { TEST_F(SimpleEncodeTest, EncodeFrameWithQuantizeIndex) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -237,7 +238,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest) { // The first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); simple_encode.StartEncode(); @@ -257,7 +258,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest) { // The second encode with quantize index got from the first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); EXPECT_EQ(static_cast(num_coding_frames), @@ -286,7 +287,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest2) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; // The first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -309,7 +310,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest2) { // The second encode. SimpleEncode simple_encode_2(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode_2.ComputeFirstPassStats(); const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum(); simple_encode_2.StartEncode(); @@ -357,7 +358,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest3) { const int num_units_4x4 = num_rows_4x4 * num_cols_4x4; // The first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -377,7 +378,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencyTest3) { // The second encode. SimpleEncode simple_encode_2(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode_2.ComputeFirstPassStats(); const int num_coding_frames_2 = simple_encode_2.GetCodingFrameNum(); simple_encode_2.StartEncode(); @@ -417,7 +418,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencySetExternalGroupOfPicturesMap) { // The first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); simple_encode.StartEncode(); @@ -449,7 +450,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencySetExternalGroupOfPicturesMap) { // The external arfs are the same as the first encode. SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, target_bitrate_, num_frames_, - in_file_path_str_.c_str()); + target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); simple_encode.SetExternalGroupOfPicturesMap(gop_map.data(), gop_map.size()); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -471,7 +472,7 @@ TEST_F(SimpleEncodeTest, EncodeConsistencySetExternalGroupOfPicturesMap) { TEST_F(SimpleEncodeTest, SetExternalGroupOfPicturesMap) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); @@ -541,7 +542,7 @@ TEST_F(SimpleEncodeTest, GetEncodeFrameInfo) { // Makes sure that the encode_frame_info obtained from GetEncodeFrameInfo() // matches the counterpart in encode_frame_result obtained from EncodeFrame() SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); simple_encode.ComputeFirstPassStats(); const int num_coding_frames = simple_encode.GetCodingFrameNum(); @@ -558,7 +559,7 @@ TEST_F(SimpleEncodeTest, GetEncodeFrameInfo) { TEST_F(SimpleEncodeTest, GetFramePixelCount) { SimpleEncode simple_encode(width_, height_, frame_rate_num_, frame_rate_den_, - target_bitrate_, num_frames_, + target_bitrate_, num_frames_, target_level_, in_file_path_str_.c_str()); EXPECT_EQ(simple_encode.GetFramePixelCount(), static_cast(width_ * height_ * 3 / 2)); diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index 6ba37a321..1a0ada119 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -782,11 +782,12 @@ static void UpdateEncodeConfig(const EncodeConfig &config, static VP9EncoderConfig GetEncodeConfig( int frame_width, int frame_height, vpx_rational_t frame_rate, - int target_bitrate, int encode_speed, vpx_enc_pass enc_pass, + int target_bitrate, int encode_speed, int target_level, + vpx_enc_pass enc_pass, const std::vector &encode_config_list) { - VP9EncoderConfig oxcf = - vp9_get_encoder_config(frame_width, frame_height, frame_rate, - target_bitrate, encode_speed, enc_pass); + VP9EncoderConfig oxcf = vp9_get_encoder_config( + frame_width, frame_height, frame_rate, target_bitrate, encode_speed, + target_level, enc_pass); for (const auto &config : encode_config_list) { UpdateEncodeConfig(config, &oxcf); } @@ -799,7 +800,7 @@ static VP9EncoderConfig GetEncodeConfig( SimpleEncode::SimpleEncode(int frame_width, int frame_height, int frame_rate_num, int frame_rate_den, - int target_bitrate, int num_frames, + int target_bitrate, int num_frames, int target_level, const char *infile_path, const char *outfile_path) { impl_ptr_ = std::unique_ptr(new EncodeImpl()); frame_width_ = frame_width; @@ -809,6 +810,7 @@ SimpleEncode::SimpleEncode(int frame_width, int frame_height, target_bitrate_ = target_bitrate; num_frames_ = num_frames; encode_speed_ = 0; + target_level_ = target_level; frame_coding_index_ = 0; show_frame_count_ = 0; @@ -860,9 +862,9 @@ StatusCode SimpleEncode::DumpEncodeConfigs(int pass, FILE *fp) { } const vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num_, frame_rate_den_); - const VP9EncoderConfig oxcf = - GetEncodeConfig(frame_width_, frame_height_, frame_rate, target_bitrate_, - encode_speed_, enc_pass, impl_ptr_->encode_config_list); + const VP9EncoderConfig oxcf = GetEncodeConfig( + frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_, + target_level_, enc_pass, impl_ptr_->encode_config_list); vp9_dump_encoder_config(&oxcf, fp); return StatusOk; } @@ -872,7 +874,7 @@ void SimpleEncode::ComputeFirstPassStats() { make_vpx_rational(frame_rate_num_, frame_rate_den_); const VP9EncoderConfig oxcf = GetEncodeConfig( frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_, - VPX_RC_FIRST_PASS, impl_ptr_->encode_config_list); + target_level_, VPX_RC_FIRST_PASS, impl_ptr_->encode_config_list); impl_ptr_->cpi = init_encoder(&oxcf, impl_ptr_->img_fmt); struct lookahead_ctx *lookahead = impl_ptr_->cpi->lookahead; int i; @@ -1038,7 +1040,7 @@ void SimpleEncode::StartEncode() { make_vpx_rational(frame_rate_num_, frame_rate_den_); VP9EncoderConfig oxcf = GetEncodeConfig( frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_, - VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); + target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); vpx_fixed_buf_t stats; stats.buf = GetVectorData(impl_ptr_->first_pass_stats); @@ -1266,7 +1268,7 @@ int SimpleEncode::GetCodingFrameNum() const { make_vpx_rational(frame_rate_num_, frame_rate_den_); const VP9EncoderConfig oxcf = GetEncodeConfig( frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_, - VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); + target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); FRAME_INFO frame_info = vp9_get_frame_info(&oxcf); fps_init_first_pass_info(&twopass.first_pass_info, GetVectorData(impl_ptr_->first_pass_stats), @@ -1285,7 +1287,7 @@ std::vector SimpleEncode::ComputeKeyFrameMap() const { make_vpx_rational(frame_rate_num_, frame_rate_den_); const VP9EncoderConfig oxcf = GetEncodeConfig( frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_, - VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); + target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list); TWO_PASS twopass; fps_init_first_pass_info(&twopass.first_pass_info, GetVectorData(impl_ptr_->first_pass_stats), diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 8ec7069e8..7920e95ee 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -44,6 +44,26 @@ enum RefFrameType { kRefFrameTypeNone = -1, }; +enum VP9_LEVEL { + LEVEL_UNKNOWN = 0, + LEVEL_AUTO = 1, + LEVEL_1 = 10, + LEVEL_1_1 = 11, + LEVEL_2 = 20, + LEVEL_2_1 = 21, + LEVEL_3 = 30, + LEVEL_3_1 = 31, + LEVEL_4 = 40, + LEVEL_4_1 = 41, + LEVEL_5 = 50, + LEVEL_5_1 = 51, + LEVEL_5_2 = 52, + LEVEL_6 = 60, + LEVEL_6_1 = 61, + LEVEL_6_2 = 62, + LEVEL_MAX = 255 +}; + enum GopMapFlag { kGopMapFlagStart = 1 << 0, // Indicate this location is the start of a group of pictures. @@ -343,7 +363,8 @@ class SimpleEncode { // format. SimpleEncode(int frame_width, int frame_height, int frame_rate_num, int frame_rate_den, int target_bitrate, int num_frames, - const char *infile_path, const char *outfile_path = nullptr); + int target_level, const char *infile_path, + const char *outfile_path = nullptr); ~SimpleEncode(); SimpleEncode(SimpleEncode &) = delete; SimpleEncode &operator=(const SimpleEncode &) = delete; @@ -513,6 +534,7 @@ class SimpleEncode { int target_bitrate_; int num_frames_; int encode_speed_; + int target_level_; std::FILE *in_file_; std::FILE *out_file_; diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index 76274437c..b809ab3e6 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -2143,6 +2143,7 @@ static vp9_extracfg get_extra_cfg() { VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, vpx_rational_t frame_rate, int target_bitrate, int encode_speed, + int target_level, vpx_enc_pass enc_pass) { /* This function will generate the same VP9EncoderConfig used by the * vpxenc command given below. @@ -2154,6 +2155,7 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, * FPS: frame_rate * BITRATE: target_bitrate * CPU_USED:encode_speed + * TARGET_LEVEL: target_level * * INPUT, OUTPUT, LIMIT will not affect VP9EncoderConfig * @@ -2166,6 +2168,7 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, * FPS=30/1 * LIMIT=150 * CPU_USED=0 + * TARGET_LEVEL=0 * ./vpxenc --limit=$LIMIT --width=$WIDTH --height=$HEIGHT --fps=$FPS * --lag-in-frames=25 \ * --codec=vp9 --good --cpu-used=CPU_USED --threads=0 --profile=0 \ @@ -2174,7 +2177,7 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, * --minsection-pct=0 --maxsection-pct=150 --arnr-maxframes=7 --psnr \ * --arnr-strength=5 --sharpness=0 --undershoot-pct=100 --overshoot-pct=100 \ * --frame-parallel=0 --tile-columns=0 --cpu-used=0 --end-usage=vbr \ - * --target-bitrate=$BITRATE -o $OUTPUT $INPUT + * --target-bitrate=$BITRATE --target-level=0 -o $OUTPUT $INPUT */ VP9EncoderConfig oxcf; @@ -2192,6 +2195,7 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, oxcf.frame_parallel_decoding_mode = 0; oxcf.two_pass_vbrmax_section = 150; oxcf.speed = abs(encode_speed); + oxcf.target_level = target_level; return oxcf; } diff --git a/vp9/vp9_cx_iface.h b/vp9/vp9_cx_iface.h index 01338adb4..f2de8507f 100644 --- a/vp9/vp9_cx_iface.h +++ b/vp9/vp9_cx_iface.h @@ -20,6 +20,7 @@ extern "C" { VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height, vpx_rational_t frame_rate, int target_bitrate, int encode_speed, + int target_level, vpx_enc_pass enc_pass); void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf, FILE *fp);