// 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<int> quantize_index_list;
std::vector<uint64_t> ref_sse_list;
std::vector<double> ref_psnr_list;
std::vector<size_t> ref_bit_size_list;
- std::vector<int> external_arf_indexes(num_frames, 0);
+ std::vector<int> 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<EncodeFrameInfo> &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();
}
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<size_t>(num_coding_frames),
quantize_index_list.size());
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.
return output_stats;
}
-void SimpleEncode::SetExternalGroupOfPicture(
- std::vector<int> external_arf_indexes) {
- external_arf_indexes_ = external_arf_indexes;
+void SimpleEncode::SetExternalGroupOfPicture(std::vector<int> gop_map) {
+ gop_map_ = gop_map;
}
template <typename T>
static GOP_COMMAND GetGopCommand(const std::vector<int> &gop_map,
int start_show_index) {
assert(static_cast<size_t>(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<size_t>(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<size_t>(end_show_index) == gop_map.size()) {
// This is the last gop group, there must be no altref.
use_alt_ref = 0;
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
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.
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 {
// triggered when the coded frame is the last one in the previous group of
// pictures.
std::vector<EncodeFrameInfo> 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].
// 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 {
// values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h
std::vector<std::vector<double>> 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<int> external_arf_indexes);
+ void SetExternalGroupOfPicture(std::vector<int> gop_map);
// Initializes the encoder for actual encoding.
// This function should be called after ComputeFirstPassStats().
std::FILE *out_file_;
std::unique_ptr<EncodeImpl> impl_ptr_;
- std::vector<int> external_arf_indexes_;
+ std::vector<int> gop_map_;
GroupOfPicture group_of_picture_;
// The key frame group size includes one key frame plus the number of