From: angiebird Date: Tue, 26 May 2020 19:00:36 +0000 (-0700) Subject: Make SetExternalGroupOfPicture support no arf mode X-Git-Tag: v1.9.0-rc1~11 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5c8431b9e4e0534f25031cf745b5d71b9492ee1e;p=libvpx Make SetExternalGroupOfPicture support no arf mode Rename external_arf_indexes by gop_map Use kGopMapFlagStart to indicate the start of a gop in the gop_map. Use kGopMapFlagUseAltRef to indicate whether to use altref in the gop_map. Change-Id: I743e3199a24b9ae1abd5acd290da1a1f8660e6ac --- diff --git a/test/simple_encode_test.cc b/test/simple_encode_test.cc index 3dfc81265..45dcad050 100644 --- a/test/simple_encode_test.cc +++ b/test/simple_encode_test.cc @@ -291,35 +291,39 @@ TEST(SimpleEncode, EncodeConsistencyTest3) { // Get QPs and arf locations from the first encode. // Set external arfs and QPs for the second encode. // Expect to get matched results. -TEST(SimpleEncode, EncodeConsistencyTestUseExternalArfs) { +TEST(SimpleEncode, EncodeConsistencySetExternalGroupOfPicture) { std::vector quantize_index_list; std::vector ref_sse_list; std::vector ref_psnr_list; std::vector ref_bit_size_list; - std::vector external_arf_indexes(num_frames, 0); + std::vector gop_map(num_frames, 0); { // The first encode. SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den, target_bitrate, num_frames, infile_path); simple_encode.ComputeFirstPassStats(); - const int num_coding_frames = simple_encode.GetCodingFrameNum(); simple_encode.StartEncode(); - for (int i = 0; i < num_coding_frames; ++i) { - EncodeFrameResult encode_frame_result; - simple_encode.EncodeFrame(&encode_frame_result); - quantize_index_list.push_back(encode_frame_result.quantize_index); - ref_sse_list.push_back(encode_frame_result.sse); - ref_psnr_list.push_back(encode_frame_result.psnr); - ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size); - if (encode_frame_result.frame_type == kFrameTypeKey) { - external_arf_indexes[encode_frame_result.show_idx] = 0; - } else if (encode_frame_result.frame_type == kFrameTypeAltRef) { - external_arf_indexes[encode_frame_result.show_idx] = 1; - } else { - // This has to be |= because we can't let overlay overwrites the - // arf type for the same frame. - external_arf_indexes[encode_frame_result.show_idx] |= 0; + + int coded_show_frame_count = 0; + while (coded_show_frame_count < num_frames) { + const GroupOfPicture group_of_picture = + simple_encode.ObserveGroupOfPicture(); + gop_map[coded_show_frame_count] |= kGopMapFlagStart; + if (group_of_picture.use_alt_ref) { + gop_map[coded_show_frame_count] |= kGopMapFlagUseAltRef; + } + const std::vector &encode_frame_list = + group_of_picture.encode_frame_list; + for (size_t group_index = 0; group_index < encode_frame_list.size(); + ++group_index) { + EncodeFrameResult encode_frame_result; + simple_encode.EncodeFrame(&encode_frame_result); + quantize_index_list.push_back(encode_frame_result.quantize_index); + ref_sse_list.push_back(encode_frame_result.sse); + ref_psnr_list.push_back(encode_frame_result.psnr); + ref_bit_size_list.push_back(encode_frame_result.coding_data_bit_size); } + coded_show_frame_count += group_of_picture.show_frame_count; } simple_encode.EndEncode(); } @@ -329,7 +333,7 @@ TEST(SimpleEncode, EncodeConsistencyTestUseExternalArfs) { SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den, target_bitrate, num_frames, infile_path); simple_encode.ComputeFirstPassStats(); - simple_encode.SetExternalGroupOfPicture(external_arf_indexes); + simple_encode.SetExternalGroupOfPicture(gop_map); const int num_coding_frames = simple_encode.GetCodingFrameNum(); EXPECT_EQ(static_cast(num_coding_frames), quantize_index_list.size()); diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index 45d32c59d..7e6ecf8ea 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -612,6 +612,9 @@ static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, group_of_picture->show_frame_count = coding_frame_count - use_alt_ref; group_of_picture->start_show_index = first_show_idx; group_of_picture->start_coding_index = start_coding_index; + group_of_picture->first_is_key_frame = first_is_key_frame; + group_of_picture->use_alt_ref = use_alt_ref; + group_of_picture->last_gop_use_alt_ref = last_gop_use_alt_ref; // We need to make a copy of start reference frame info because we // use it to simulate the ref frame update. @@ -800,9 +803,8 @@ std::vector> SimpleEncode::ObserveFirstPassStats() { return output_stats; } -void SimpleEncode::SetExternalGroupOfPicture( - std::vector external_arf_indexes) { - external_arf_indexes_ = external_arf_indexes; +void SimpleEncode::SetExternalGroupOfPicture(std::vector gop_map) { + gop_map_ = gop_map; } template @@ -816,15 +818,18 @@ T *GetVectorData(const std::vector &v) { static GOP_COMMAND GetGopCommand(const std::vector &gop_map, int start_show_index) { assert(static_cast(start_show_index) < gop_map.size()); + assert((gop_map[start_show_index] & kGopMapFlagStart) != 0); GOP_COMMAND gop_command; if (gop_map.size() > 0) { int end_show_index = start_show_index + 1; + // gop_map[end_show_index] & kGopMapFlagStart == 0 means this is + // the start of a gop. while (static_cast(end_show_index) < gop_map.size() && - gop_map[end_show_index] == 0) { + (gop_map[end_show_index] & kGopMapFlagStart) == 0) { ++end_show_index; } const int show_frame_count = end_show_index - start_show_index; - int use_alt_ref = 1; + int use_alt_ref = (gop_map[start_show_index] & kGopMapFlagUseAltRef) != 0; if (static_cast(end_show_index) == gop_map.size()) { // This is the last gop group, there must be no altref. use_alt_ref = 0; @@ -934,8 +939,7 @@ void SimpleEncode::PostUpdateState( IncreaseGroupOfPictureIndex(&group_of_picture_); if (IsGroupOfPictureFinished(group_of_picture_)) { - const GOP_COMMAND gop_command = - GetGopCommand(external_arf_indexes_, show_frame_count_); + const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_); encode_command_set_gop_command(&impl_ptr_->cpi->encode_command, gop_command); // This function needs to be called after ref_frame_info_ is updated @@ -1040,8 +1044,8 @@ static int GetCodingFrameNumFromGopMap(const std::vector &gop_map) { int SimpleEncode::GetCodingFrameNum() const { assert(impl_ptr_->first_pass_stats.size() > 0); - if (external_arf_indexes_.size() > 0) { - return GetCodingFrameNumFromGopMap(external_arf_indexes_); + if (gop_map_.size() > 0) { + return GetCodingFrameNumFromGopMap(gop_map_); } // These are the default settings for now. diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 4221a7015..d84760ac9 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -39,6 +39,14 @@ enum RefFrameType { kRefFrameTypeNone = -1, }; +enum GopMapFlag { + kGopMapFlagStart = + 1 << 0, // Indicate this location is the start of a group of pictures. + kGopMapFlagUseAltRef = + 1 << 1, // Indicate this group of pictures will use an alt ref. Only set + // this flag when kGopMapFlagStart is set. +}; + // The frame is split to 4x4 blocks. // This structure contains the information of each 4x4 block. struct PartitionInfo { @@ -255,6 +263,7 @@ struct GroupOfPicture { // triggered when the coded frame is the last one in the previous group of // pictures. std::vector encode_frame_list; + // Indicates the index of the next coding frame in encode_frame_list. // In other words, EncodeFrameInfo of the next coding frame can be // obtained with encode_frame_list[next_encode_frame_index]. @@ -263,13 +272,25 @@ struct GroupOfPicture { // will be increased after each EncodeFrame()/EncodeFrameWithQuantizeIndex() // call. int next_encode_frame_index; + // Number of show frames in this group of pictures. int show_frame_count; + // The show index/timestamp of the earliest show frame in the group of // pictures. int start_show_index; - // The coding index of the first coding frame in the group of picture. + + // The coding index of the first coding frame in the group of pictures. int start_coding_index; + + // Indicates whether this group of pictures starts with a key frame. + int first_is_key_frame; + + // Indicates whether this group of pictures uses an alt ref. + int use_alt_ref; + + // Indicates whether previous group of pictures used an alt ref. + int last_gop_use_alt_ref; }; class SimpleEncode { @@ -293,13 +314,17 @@ class SimpleEncode { // values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h std::vector> ObserveFirstPassStats(); - // Sets arf indexes for the video from external input. - // The arf index determines whether a frame is arf or not. - // Therefore it also determines the group of picture size. - // If set, VP9 will use the external arf index to make decision. + // Sets group of pictures map for coding the entire video. + // Each entry in the gop_map corresponds to a show frame in the video. + // Therefore, the size of gop_map should equal to the number of show frames in + // the entire video. + // If a given entry's kGopMapFlagStart is set, it means this is the start of a + // gop. Once kGopMapFlagStart is set, one can set kGopMapFlagUseAltRef to + // indicate whether this gop use altref. + // If a given entry is zero, it means it's in the middle of a gop. // This function should be called only once after ComputeFirstPassStats(), // before StartEncode(). - void SetExternalGroupOfPicture(std::vector external_arf_indexes); + void SetExternalGroupOfPicture(std::vector gop_map); // Initializes the encoder for actual encoding. // This function should be called after ComputeFirstPassStats(). @@ -363,7 +388,7 @@ class SimpleEncode { std::FILE *out_file_; std::unique_ptr impl_ptr_; - std::vector external_arf_indexes_; + std::vector gop_map_; GroupOfPicture group_of_picture_; // The key frame group size includes one key frame plus the number of