Add functions to compute/observe key frame map
Change-Id: I2fc0efb2ac35e64af3350bddaa802a206d1aa13c
This commit is contained in:
@@ -106,6 +106,34 @@ TEST(SimpleEncode, EncodeFrame) {
|
|||||||
simple_encode.EndEncode();
|
simple_encode.EndEncode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SimpleEncode, ObserveKeyFrameMap) {
|
||||||
|
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
|
||||||
|
target_bitrate, num_frames, infile_path);
|
||||||
|
simple_encode.ComputeFirstPassStats();
|
||||||
|
std::vector<int> key_frame_map = simple_encode.ObserveKeyFrameMap();
|
||||||
|
EXPECT_EQ(key_frame_map.size(), static_cast<size_t>(num_frames));
|
||||||
|
simple_encode.StartEncode();
|
||||||
|
int coded_show_frame_count = 0;
|
||||||
|
while (coded_show_frame_count < num_frames) {
|
||||||
|
const GroupOfPicture group_of_picture =
|
||||||
|
simple_encode.ObserveGroupOfPicture();
|
||||||
|
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);
|
||||||
|
if (encode_frame_result.frame_type == kFrameTypeKey) {
|
||||||
|
EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 1);
|
||||||
|
} else {
|
||||||
|
EXPECT_EQ(key_frame_map[encode_frame_result.show_idx], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
coded_show_frame_count += group_of_picture.show_frame_count;
|
||||||
|
}
|
||||||
|
simple_encode.EndEncode();
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SimpleEncode, EncodeFrameWithQuantizeIndex) {
|
TEST(SimpleEncode, EncodeFrameWithQuantizeIndex) {
|
||||||
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
|
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
|
||||||
target_bitrate, num_frames, infile_path);
|
target_bitrate, num_frames, infile_path);
|
||||||
|
|||||||
@@ -3796,6 +3796,30 @@ int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf,
|
|||||||
}
|
}
|
||||||
return coding_frame_num;
|
return coding_frame_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vp9_get_key_frame_map(const VP9EncoderConfig *oxcf,
|
||||||
|
const FRAME_INFO *frame_info,
|
||||||
|
const FIRST_PASS_INFO *first_pass_info,
|
||||||
|
int *key_frame_map) {
|
||||||
|
int show_idx = 0;
|
||||||
|
RATE_CONTROL rc;
|
||||||
|
vp9_rc_init(oxcf, 1, &rc);
|
||||||
|
|
||||||
|
// key_frame_map points to an int array with size equal to
|
||||||
|
// first_pass_info->num_frames, which is also the number of show frames in the
|
||||||
|
// video.
|
||||||
|
memset(key_frame_map, 0,
|
||||||
|
sizeof(*key_frame_map) * first_pass_info->num_frames);
|
||||||
|
while (show_idx < first_pass_info->num_frames) {
|
||||||
|
int key_frame_group_size;
|
||||||
|
key_frame_map[show_idx] = 1;
|
||||||
|
key_frame_group_size = vp9_get_frames_to_next_key(
|
||||||
|
oxcf, frame_info, first_pass_info, show_idx, rc.min_gf_interval);
|
||||||
|
assert(key_frame_group_size > 0);
|
||||||
|
show_idx += key_frame_group_size;
|
||||||
|
}
|
||||||
|
assert(show_idx == first_pass_info->num_frames);
|
||||||
|
}
|
||||||
#endif // CONFIG_RATE_CTRL
|
#endif // CONFIG_RATE_CTRL
|
||||||
|
|
||||||
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass) {
|
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass) {
|
||||||
|
|||||||
@@ -290,6 +290,16 @@ int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf,
|
|||||||
const FRAME_INFO *frame_info,
|
const FRAME_INFO *frame_info,
|
||||||
const FIRST_PASS_INFO *first_pass_info,
|
const FIRST_PASS_INFO *first_pass_info,
|
||||||
int multi_layer_arf, int allow_alt_ref);
|
int multi_layer_arf, int allow_alt_ref);
|
||||||
|
|
||||||
|
/*!\brief Compute a key frame binary map indicates whether key frames appear
|
||||||
|
* in the corresponding positions. The passed in key_frame_map must point to an
|
||||||
|
* integer array with length equal to first_pass_info->num_frames, which is the
|
||||||
|
* number of show frames in the video.
|
||||||
|
*/
|
||||||
|
void vp9_get_key_frame_map(const struct VP9EncoderConfig *oxcf,
|
||||||
|
const FRAME_INFO *frame_info,
|
||||||
|
const FIRST_PASS_INFO *first_pass_info,
|
||||||
|
int *key_frame_map);
|
||||||
#endif // CONFIG_RATE_CTRL
|
#endif // CONFIG_RATE_CTRL
|
||||||
|
|
||||||
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass);
|
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass);
|
||||||
|
|||||||
@@ -779,6 +779,9 @@ void SimpleEncode::ComputeFirstPassStats() {
|
|||||||
free_encoder(cpi);
|
free_encoder(cpi);
|
||||||
rewind(in_file_);
|
rewind(in_file_);
|
||||||
vpx_img_free(&img);
|
vpx_img_free(&img);
|
||||||
|
|
||||||
|
// Generate key_frame_map based on impl_ptr_->first_pass_stats.
|
||||||
|
key_frame_map_ = ComputeKeyFrameMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() {
|
std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() {
|
||||||
@@ -1065,6 +1068,28 @@ int SimpleEncode::GetCodingFrameNum() const {
|
|||||||
multi_layer_arf, allow_alt_ref);
|
multi_layer_arf, allow_alt_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> SimpleEncode::ComputeKeyFrameMap() const {
|
||||||
|
assert(impl_ptr_->first_pass_stats.size() == num_frames_);
|
||||||
|
vpx_rational_t frame_rate =
|
||||||
|
make_vpx_rational(frame_rate_num_, frame_rate_den_);
|
||||||
|
const VP9EncoderConfig oxcf =
|
||||||
|
vp9_get_encoder_config(frame_width_, frame_height_, frame_rate,
|
||||||
|
target_bitrate_, VPX_RC_LAST_PASS);
|
||||||
|
FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
|
||||||
|
FIRST_PASS_INFO first_pass_info;
|
||||||
|
fps_init_first_pass_info(&first_pass_info,
|
||||||
|
GetVectorData(impl_ptr_->first_pass_stats),
|
||||||
|
num_frames_);
|
||||||
|
std::vector<int> key_frame_map(num_frames_, 0);
|
||||||
|
vp9_get_key_frame_map(&oxcf, &frame_info, &first_pass_info,
|
||||||
|
GetVectorData(key_frame_map));
|
||||||
|
return key_frame_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> SimpleEncode::ObserveKeyFrameMap() const {
|
||||||
|
return key_frame_map_;
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t SimpleEncode::GetFramePixelCount() const {
|
uint64_t SimpleEncode::GetFramePixelCount() const {
|
||||||
assert(frame_width_ % 2 == 0);
|
assert(frame_width_ % 2 == 0);
|
||||||
assert(frame_height_ % 2 == 0);
|
assert(frame_height_ % 2 == 0);
|
||||||
|
|||||||
@@ -304,8 +304,9 @@ class SimpleEncode {
|
|||||||
SimpleEncode(SimpleEncode &) = delete;
|
SimpleEncode(SimpleEncode &) = delete;
|
||||||
SimpleEncode &operator=(const SimpleEncode &) = delete;
|
SimpleEncode &operator=(const SimpleEncode &) = delete;
|
||||||
|
|
||||||
// Makes encoder compute the first pass stats and store it internally for
|
// Makes encoder compute the first pass stats and store it at
|
||||||
// future encode.
|
// impl_ptr_->first_pass_stats. key_frame_map_ is also computed based on the
|
||||||
|
// first pass stats.
|
||||||
void ComputeFirstPassStats();
|
void ComputeFirstPassStats();
|
||||||
|
|
||||||
// Outputs the first pass stats represented by a 2-D vector.
|
// Outputs the first pass stats represented by a 2-D vector.
|
||||||
@@ -314,8 +315,14 @@ class SimpleEncode {
|
|||||||
// values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h
|
// values. For details, please check FIRSTPASS_STATS in vp9_firstpass.h
|
||||||
std::vector<std::vector<double>> ObserveFirstPassStats();
|
std::vector<std::vector<double>> ObserveFirstPassStats();
|
||||||
|
|
||||||
|
// Ouputs a copy of key_frame_map_, a binary vector with size equal to the
|
||||||
|
// number of show frames in the video. For each entry in the vector, 1
|
||||||
|
// indicates the position is a key frame and 0 indicates it's not a key frame.
|
||||||
|
// This function should be called after ComputeFirstPassStats()
|
||||||
|
std::vector<int> ObserveKeyFrameMap() const;
|
||||||
|
|
||||||
// Sets group of pictures map for coding the entire video.
|
// Sets group of pictures map for coding the entire video.
|
||||||
// Each entry in the gop_map corresponds to a show frame in the video.
|
// Each entry in the gop_map is corresponding to a show frame in the video.
|
||||||
// Therefore, the size of gop_map should equal to the number of show frames in
|
// Therefore, the size of gop_map should equal to the number of show frames in
|
||||||
// the entire video.
|
// the entire video.
|
||||||
// If a given entry's kGopMapFlagStart is set, it means this is the start of a
|
// If a given entry's kGopMapFlagStart is set, it means this is the start of a
|
||||||
@@ -366,6 +373,12 @@ class SimpleEncode {
|
|||||||
uint64_t GetFramePixelCount() const;
|
uint64_t GetFramePixelCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// Compute the key frame locations of the video based on first pass stats.
|
||||||
|
// The results are returned as a binary vector with 1s indicating keyframes
|
||||||
|
// and 0s indicating non keyframes.
|
||||||
|
// It has to be called after impl_ptr_->first_pass_stats is computed.
|
||||||
|
std::vector<int> ComputeKeyFrameMap() const;
|
||||||
|
|
||||||
// Updates key_frame_group_size_, reset key_frame_group_index_ and init
|
// Updates key_frame_group_size_, reset key_frame_group_index_ and init
|
||||||
// ref_frame_info_.
|
// ref_frame_info_.
|
||||||
void UpdateKeyFrameGroup(int key_frame_show_index);
|
void UpdateKeyFrameGroup(int key_frame_show_index);
|
||||||
@@ -388,6 +401,7 @@ class SimpleEncode {
|
|||||||
std::FILE *out_file_;
|
std::FILE *out_file_;
|
||||||
std::unique_ptr<EncodeImpl> impl_ptr_;
|
std::unique_ptr<EncodeImpl> impl_ptr_;
|
||||||
|
|
||||||
|
std::vector<int> key_frame_map_;
|
||||||
std::vector<int> gop_map_;
|
std::vector<int> gop_map_;
|
||||||
GroupOfPicture group_of_picture_;
|
GroupOfPicture group_of_picture_;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user