Merge "Refactor decode_api_test and realtime_test"
diff --git a/test/simple_encode_test.cc b/test/simple_encode_test.cc
index 3dfc812..cbcae46 100644
--- a/test/simple_encode_test.cc
+++ b/test/simple_encode_test.cc
@@ -106,6 +106,34 @@
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) {
SimpleEncode simple_encode(w, h, frame_rate_num, frame_rate_den,
target_bitrate, num_frames, infile_path);
@@ -291,35 +319,39 @@
// 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();
}
@@ -329,7 +361,7 @@
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());
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 1a25a496..7aa4bf7 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -532,24 +532,50 @@
int_mv mv[2];
} MOTION_VECTOR_INFO;
+typedef struct GOP_COMMAND {
+ int use; // use this command to set gop or not. If not, use vp9's decision.
+ int show_frame_count;
+ int use_alt_ref;
+} GOP_COMMAND;
+
+static INLINE void gop_command_on(GOP_COMMAND *gop_command,
+ int show_frame_count, int use_alt_ref) {
+ gop_command->use = 1;
+ gop_command->show_frame_count = show_frame_count;
+ gop_command->use_alt_ref = use_alt_ref;
+}
+
+static INLINE void gop_command_off(GOP_COMMAND *gop_command) {
+ gop_command->use = 0;
+ gop_command->show_frame_count = 0;
+ gop_command->use_alt_ref = 0;
+}
+
+static INLINE int gop_command_coding_frame_count(
+ const GOP_COMMAND *gop_command) {
+ if (gop_command->use == 0) {
+ assert(0);
+ return -1;
+ }
+ return gop_command->show_frame_count + gop_command->use_alt_ref;
+}
+
typedef struct ENCODE_COMMAND {
int use_external_quantize_index;
int external_quantize_index;
- // A list of binary flags set from the external controller.
- // Each binary flag indicates whether the frame is an arf or not.
- const int *external_arf_indexes;
+ GOP_COMMAND gop_command;
} ENCODE_COMMAND;
static INLINE void encode_command_init(ENCODE_COMMAND *encode_command) {
vp9_zero(*encode_command);
encode_command->use_external_quantize_index = 0;
encode_command->external_quantize_index = -1;
- encode_command->external_arf_indexes = NULL;
+ gop_command_off(&encode_command->gop_command);
}
-static INLINE void encode_command_set_external_arf_indexes(
- ENCODE_COMMAND *encode_command, const int *external_arf_indexes) {
- encode_command->external_arf_indexes = external_arf_indexes;
+static INLINE void encode_command_set_gop_command(
+ ENCODE_COMMAND *encode_command, GOP_COMMAND gop_command) {
+ encode_command->gop_command = gop_command;
}
static INLINE void encode_command_set_external_quantize_index(
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 3a48174..45b003e 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -2508,9 +2508,6 @@
* structs.
*/
static int get_gop_coding_frame_num(
-#if CONFIG_RATE_CTRL
- const int *external_arf_indexes,
-#endif
int *use_alt_ref, const FRAME_INFO *frame_info,
const FIRST_PASS_INFO *first_pass_info, const RATE_CONTROL *rc,
int gf_start_show_idx, const RANGE *active_gf_interval,
@@ -2526,24 +2523,6 @@
(frame_info->frame_height + frame_info->frame_width) / 4.0;
double zero_motion_accumulator = 1.0;
int gop_coding_frames;
-#if CONFIG_RATE_CTRL
- (void)mv_ratio_accumulator_thresh;
- (void)active_gf_interval;
- (void)gop_intra_factor;
-
- if (external_arf_indexes != NULL && rc->frames_to_key > 1) {
- // gop_coding_frames = 1 is necessary to filter out the overlay frame,
- // since the arf is in this group of picture and its overlay is in the next.
- gop_coding_frames = 1;
- *use_alt_ref = 1;
- while (gop_coding_frames < rc->frames_to_key) {
- const int frame_index = gf_start_show_idx + gop_coding_frames;
- ++gop_coding_frames;
- if (external_arf_indexes[frame_index] == 1) break;
- }
- return gop_coding_frames;
- }
-#endif // CONFIG_RATE_CTRL
*use_alt_ref = 1;
gop_coding_frames = 0;
@@ -2770,15 +2749,26 @@
gop_intra_factor = 1.0;
}
- {
- gop_coding_frames = get_gop_coding_frame_num(
#if CONFIG_RATE_CTRL
- cpi->encode_command.external_arf_indexes,
-#endif
- &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
- &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
- use_alt_ref &= allow_alt_ref;
+ {
+ const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
+ assert(allow_alt_ref == 1);
+ if (gop_command->use) {
+ gop_coding_frames = gop_command_coding_frame_count(gop_command);
+ use_alt_ref = gop_command->use_alt_ref;
+ } else {
+ gop_coding_frames = get_gop_coding_frame_num(
+ &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
+ &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
+ use_alt_ref &= allow_alt_ref;
+ }
}
+#else
+ gop_coding_frames = get_gop_coding_frame_num(
+ &use_alt_ref, frame_info, first_pass_info, rc, gf_start_show_idx,
+ &active_gf_interval, gop_intra_factor, cpi->oxcf.lag_in_frames);
+ use_alt_ref &= allow_alt_ref;
+#endif
// Was the group length constrained by the requirement for a new KF?
rc->constrained_gf_group = (gop_coding_frames >= rc->frames_to_key) ? 1 : 0;
@@ -3704,6 +3694,7 @@
int *use_alt_ref, int *coding_frame_count,
int *first_show_idx,
int *last_gop_use_alt_ref) {
+ const GOP_COMMAND *gop_command = &cpi->encode_command.gop_command;
// We make a copy of rc here because we want to get information from the
// encoder without changing its state.
// TODO(angiebird): Avoid copying rc here.
@@ -3726,14 +3717,19 @@
*first_is_key_frame = 1;
}
- *coding_frame_count = vp9_get_gop_coding_frame_count(
- cpi->encode_command.external_arf_indexes, &cpi->oxcf, &cpi->frame_info,
- &cpi->twopass.first_pass_info, &rc, *first_show_idx, multi_layer_arf,
- allow_alt_ref, *first_is_key_frame, *last_gop_use_alt_ref, use_alt_ref);
+ if (gop_command->use) {
+ *coding_frame_count = gop_command_coding_frame_count(gop_command);
+ *use_alt_ref = gop_command->use_alt_ref;
+ assert(*coding_frame_count < rc.frames_to_key);
+ } else {
+ *coding_frame_count = vp9_get_gop_coding_frame_count(
+ &cpi->oxcf, &cpi->frame_info, &cpi->twopass.first_pass_info, &rc,
+ *first_show_idx, multi_layer_arf, allow_alt_ref, *first_is_key_frame,
+ *last_gop_use_alt_ref, use_alt_ref);
+ }
}
-int vp9_get_gop_coding_frame_count(const int *external_arf_indexes,
- const VP9EncoderConfig *oxcf,
+int vp9_get_gop_coding_frame_count(const VP9EncoderConfig *oxcf,
const FRAME_INFO *frame_info,
const FIRST_PASS_INFO *first_pass_info,
const RATE_CONTROL *rc, int show_idx,
@@ -3756,9 +3752,6 @@
}
frame_count = get_gop_coding_frame_num(
-#if CONFIG_RATE_CTRL
- external_arf_indexes,
-#endif
use_alt_ref, frame_info, first_pass_info, rc, show_idx,
&active_gf_interval, gop_intra_factor, oxcf->lag_in_frames);
*use_alt_ref &= allow_alt_ref;
@@ -3767,8 +3760,7 @@
// Under CONFIG_RATE_CTRL, once the first_pass_info is ready, the number of
// coding frames (including show frame and alt ref) can be determined.
-int vp9_get_coding_frame_num(const int *external_arf_indexes,
- const VP9EncoderConfig *oxcf,
+int vp9_get_coding_frame_num(const VP9EncoderConfig *oxcf,
const FRAME_INFO *frame_info,
const FIRST_PASS_INFO *first_pass_info,
int multi_layer_arf, int allow_alt_ref) {
@@ -3779,7 +3771,6 @@
int show_idx = 0;
int last_gop_use_alt_ref = 0;
vp9_rc_init(oxcf, 1, &rc);
- rc.static_scene_max_gf_interval = 250;
while (show_idx < first_pass_info->num_frames) {
int use_alt_ref;
@@ -3792,9 +3783,8 @@
}
gop_coding_frame_count = vp9_get_gop_coding_frame_count(
- external_arf_indexes, oxcf, frame_info, first_pass_info, &rc, show_idx,
- multi_layer_arf, allow_alt_ref, first_is_key_frame,
- last_gop_use_alt_ref, &use_alt_ref);
+ oxcf, frame_info, first_pass_info, &rc, show_idx, multi_layer_arf,
+ allow_alt_ref, first_is_key_frame, last_gop_use_alt_ref, &use_alt_ref);
rc.source_alt_ref_active = use_alt_ref;
last_gop_use_alt_ref = use_alt_ref;
@@ -3806,6 +3796,30 @@
}
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
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass) {
diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h
index dcaf2ee..b1047ea 100644
--- a/vp9/encoder/vp9_firstpass.h
+++ b/vp9/encoder/vp9_firstpass.h
@@ -264,7 +264,6 @@
/*!\brief Call this function before coding a new group of pictures to get
* information about it.
- * \param[in] external_arf_indexes External arf indexs passed in
* \param[in] oxcf Encoder config
* \param[in] frame_info Frame info
* \param[in] first_pass_info First pass stats
@@ -279,8 +278,7 @@
*
* \return Returns coding frame count
*/
-int vp9_get_gop_coding_frame_count(const int *external_arf_indexes,
- const struct VP9EncoderConfig *oxcf,
+int vp9_get_gop_coding_frame_count(const struct VP9EncoderConfig *oxcf,
const FRAME_INFO *frame_info,
const FIRST_PASS_INFO *first_pass_info,
const RATE_CONTROL *rc, int show_idx,
@@ -288,11 +286,20 @@
int first_is_key_frame,
int last_gop_use_alt_ref, int *use_alt_ref);
-int vp9_get_coding_frame_num(const int *external_arf_indexes,
- const struct VP9EncoderConfig *oxcf,
+int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf,
const FRAME_INFO *frame_info,
const FIRST_PASS_INFO *first_pass_info,
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
FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass);
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 4da5037..2d03bad 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -431,6 +431,11 @@
rc->max_gf_interval = vp9_rc_get_default_max_gf_interval(
oxcf->init_framerate, rc->min_gf_interval);
rc->baseline_gf_interval = (rc->min_gf_interval + rc->max_gf_interval) / 2;
+ if ((oxcf->pass == 0) && (oxcf->rc_mode == VPX_Q)) {
+ rc->static_scene_max_gf_interval = FIXED_GF_INTERVAL;
+ } else {
+ rc->static_scene_max_gf_interval = MAX_STATIC_GF_GROUP_LENGTH;
+ }
rc->force_max_q = 0;
rc->last_post_encode_dropped_scene_change = 0;
diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc
index c417a25..f52c180 100644
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -612,6 +612,9 @@
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.
@@ -776,6 +779,9 @@
free_encoder(cpi);
rewind(in_file_);
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() {
@@ -800,9 +806,8 @@
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>
@@ -813,6 +818,32 @@
return const_cast<T *>(v.data());
}
+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] & kGopMapFlagStart) == 0) {
+ ++end_show_index;
+ }
+ const int show_frame_count = end_show_index - start_show_index;
+ 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;
+ }
+ gop_command_on(&gop_command, show_frame_count, use_alt_ref);
+ } else {
+ gop_command_off(&gop_command);
+ }
+ return gop_command;
+}
+
void SimpleEncode::StartEncode() {
assert(impl_ptr_->first_pass_stats.size() > 0);
vpx_rational_t frame_rate =
@@ -834,9 +865,6 @@
frame_coding_index_ = 0;
show_frame_count_ = 0;
- encode_command_set_external_arf_indexes(&impl_ptr_->cpi->encode_command,
- GetVectorData(external_arf_indexes_));
-
UpdateKeyFrameGroup(show_frame_count_);
UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
@@ -914,6 +942,9 @@
IncreaseGroupOfPictureIndex(&group_of_picture_);
if (IsGroupOfPictureFinished(group_of_picture_)) {
+ 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
// properly in PostUpdateRefFrameInfo() and UpdateKeyFrameGroup().
UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
@@ -1002,8 +1033,24 @@
encode_command_reset_external_quantize_index(&impl_ptr_->cpi->encode_command);
}
+static int GetCodingFrameNumFromGopMap(const std::vector<int> &gop_map) {
+ int start_show_index = 0;
+ int coding_frame_count = 0;
+ while (static_cast<size_t>(start_show_index) < gop_map.size()) {
+ const GOP_COMMAND gop_command = GetGopCommand(gop_map, start_show_index);
+ start_show_index += gop_command.show_frame_count;
+ coding_frame_count += gop_command_coding_frame_count(&gop_command);
+ }
+ assert(start_show_index == gop_map.size());
+ return coding_frame_count;
+}
+
int SimpleEncode::GetCodingFrameNum() const {
- assert(impl_ptr_->first_pass_stats.size() - 1 > 0);
+ assert(impl_ptr_->first_pass_stats.size() > 0);
+ if (gop_map_.size() > 0) {
+ return GetCodingFrameNumFromGopMap(gop_map_);
+ }
+
// These are the default settings for now.
const int multi_layer_arf = 0;
const int allow_alt_ref = 1;
@@ -1017,11 +1064,32 @@
fps_init_first_pass_info(&first_pass_info,
GetVectorData(impl_ptr_->first_pass_stats),
num_frames_);
- return vp9_get_coding_frame_num(external_arf_indexes_.data(), &oxcf,
- &frame_info, &first_pass_info,
+ return vp9_get_coding_frame_num(&oxcf, &frame_info, &first_pass_info,
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 {
assert(frame_width_ % 2 == 0);
assert(frame_height_ % 2 == 0);
diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h
index 4221a70..80ecafd 100644
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -39,6 +39,14 @@
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 @@
// 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].
@@ -263,13 +272,25 @@
// 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 {
@@ -283,8 +304,9 @@
SimpleEncode(SimpleEncode &) = delete;
SimpleEncode &operator=(const SimpleEncode &) = delete;
- // Makes encoder compute the first pass stats and store it internally for
- // future encode.
+ // Makes encoder compute the first pass stats and store it at
+ // impl_ptr_->first_pass_stats. key_frame_map_ is also computed based on the
+ // first pass stats.
void ComputeFirstPassStats();
// Outputs the first pass stats represented by a 2-D vector.
@@ -293,13 +315,23 @@
// 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.
+ // 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.
+ // 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
+ // 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().
@@ -341,6 +373,12 @@
uint64_t GetFramePixelCount() const;
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
// ref_frame_info_.
void UpdateKeyFrameGroup(int key_frame_show_index);
@@ -363,7 +401,8 @@
std::FILE *out_file_;
std::unique_ptr<EncodeImpl> impl_ptr_;
- std::vector<int> external_arf_indexes_;
+ std::vector<int> key_frame_map_;
+ std::vector<int> gop_map_;
GroupOfPicture group_of_picture_;
// The key frame group size includes one key frame plus the number of