diff options
Diffstat (limited to 'vp9')
-rw-r--r-- | vp9/encoder/vp9_firstpass.c | 31 | ||||
-rw-r--r-- | vp9/encoder/vp9_firstpass.h | 14 | ||||
-rw-r--r-- | vp9/simple_encode.cc | 73 | ||||
-rw-r--r-- | vp9/simple_encode.h | 20 |
4 files changed, 136 insertions, 2 deletions
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index 3350cdaf4..48ef8d7ba 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -3643,6 +3643,37 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { } #if CONFIG_RATE_CTRL +void vp9_get_next_group_of_picture(int *first_is_key_frame, int *use_alt_ref, + int *coding_frame_count, int *first_show_idx, + const VP9_COMP *cpi) { + // 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. + RATE_CONTROL rc = cpi->rc; + const int last_gop_use_alt_ref = rc.source_alt_ref_active; + const int multi_layer_arf = 0; + const int allow_alt_ref = 1; + // We assume that current_video_frame is updated to the show index of the + // frame we are about to called. Note that current_video_frame is updated at + // the end of encode_frame_to_data_rate(). + // TODO(angiebird): Avoid this kind of fragile style. + *first_show_idx = cpi->common.current_video_frame; + + *first_is_key_frame = 0; + if (rc.frames_to_key == 0) { + rc.frames_to_key = vp9_get_frames_to_next_key( + &cpi->oxcf, &cpi->frame_info, &cpi->twopass.first_pass_info, + *first_show_idx, rc.min_gf_interval); + rc.frames_since_key = 0; + *first_is_key_frame = 1; + } + + *coding_frame_count = vp9_get_gop_coding_frame_count( + use_alt_ref, &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); +} + int vp9_get_gop_coding_frame_count( int *use_alt_ref, const VP9EncoderConfig *oxcf, const FRAME_INFO *frame_info, const FIRST_PASS_INFO *first_pass_info, diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 712a840d5..108416b47 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -252,6 +252,16 @@ int vp9_get_frames_to_next_key(const struct VP9EncoderConfig *oxcf, const FIRST_PASS_INFO *first_pass_info, int kf_show_idx, int min_gf_interval); #if CONFIG_RATE_CTRL + +/* Call this function to get info about the next group of pictures. + * This function should be called after vp9_create_compressor() when encoding + * starts or after vp9_get_compressed_data() when the encoding process of + * the last group of pictures is just finished. + */ +void vp9_get_next_group_of_picture(int *first_is_key_frame, int *use_alt_ref, + int *coding_frame_count, int *first_show_idx, + const struct VP9_COMP *cpi); + /*!\brief Call this function before coding a new group of pictures to get * information about it. * \param[in] oxcf Encoder config @@ -280,8 +290,8 @@ int vp9_get_coding_frame_num(const struct VP9EncoderConfig *oxcf, int multi_layer_arf, int allow_alt_ref); #endif -FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *two_pass); -FIRSTPASS_STATS vp9_get_total_stats(const TWO_PASS *two_pass); +FIRSTPASS_STATS vp9_get_frame_stats(const TWO_PASS *twopass); +FIRSTPASS_STATS vp9_get_total_stats(const TWO_PASS *twopass); #ifdef __cplusplus } // extern "C" diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index 6a35eb6bc..3f2f01f79 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -102,6 +102,65 @@ static void update_encode_frame_result( encode_frame_result->quantize_index = encode_frame_info->quantize_index; } +static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) { + ++group_of_picture->encode_frame_index; +} + +static int IsGroupOfPictureFinished(const GroupOfPicture &group_of_picture) { + return static_cast<size_t>(group_of_picture.encode_frame_index) == + group_of_picture.encode_frame_list.size(); +} + +static void SetGroupOfPicture(GroupOfPicture *group_of_picture, + int first_is_key_frame, int use_alt_ref, + int coding_frame_count, int first_show_idx) { + // Clean up the state of previous group of picture. + group_of_picture->encode_frame_list.clear(); + group_of_picture->encode_frame_index = 0; + { + // First frame in the group of pictures. It's either key frame or show inter + // frame. + EncodeFrameInfo encode_frame_info; + if (first_is_key_frame) { + encode_frame_info.frame_type = kKeyFrame; + } else { + encode_frame_info.frame_type = kInterFrame; + } + encode_frame_info.show_idx = first_show_idx; + group_of_picture->encode_frame_list.push_back(encode_frame_info); + } + + const int show_frame_count = coding_frame_count - use_alt_ref; + if (use_alt_ref) { + // If there is alternate reference, it is always coded at the second place. + // Its show index (or timestamp) is at the last of this group + EncodeFrameInfo encode_frame_info; + encode_frame_info.frame_type = kAlternateReference; + encode_frame_info.show_idx = first_show_idx + show_frame_count; + group_of_picture->encode_frame_list.push_back(encode_frame_info); + } + + // Encode the rest show inter frames. + for (int i = 1; i < show_frame_count; ++i) { + EncodeFrameInfo encode_frame_info; + encode_frame_info.frame_type = kInterFrame; + encode_frame_info.show_idx = first_show_idx + i; + group_of_picture->encode_frame_list.push_back(encode_frame_info); + } +} + +static void UpdateGroupOfPicture(GroupOfPicture *group_of_picture, + const VP9_COMP *cpi) { + int first_is_key_frame; + int use_alt_ref; + int coding_frame_count; + int first_show_idx; + vp9_get_next_group_of_picture(&first_is_key_frame, &use_alt_ref, + &coding_frame_count, &first_show_idx, cpi); + SetGroupOfPicture(group_of_picture, first_is_key_frame, use_alt_ref, + coding_frame_count, first_show_idx); +} + SimpleEncode::SimpleEncode(int frame_width, int frame_height, int frame_rate_num, int frame_rate_den, int target_bitrate, int num_frames, @@ -211,6 +270,7 @@ void SimpleEncode::StartEncode() { impl_ptr_->cpi = init_encoder(&oxcf, impl_ptr_->img_fmt); vpx_img_alloc(&impl_ptr_->tmp_img, impl_ptr_->img_fmt, frame_width_, frame_height_, 1); + UpdateGroupOfPicture(&group_of_picture_, impl_ptr_->cpi); rewind(file_); } @@ -228,6 +288,15 @@ int SimpleEncode::GetKeyFrameGroupSize(int key_frame_index) const { key_frame_index, cpi->rc.min_gf_interval); } +GroupOfPicture SimpleEncode::ObserveGroupOfPicture() const { + return group_of_picture_; +} + +EncodeFrameInfo SimpleEncode::GetNextEncodeFrameInfo() const { + return group_of_picture_ + .encode_frame_list[group_of_picture_.encode_frame_index]; +} + void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) { VP9_COMP *cpi = impl_ptr_->cpi; struct lookahead_ctx *lookahead = cpi->lookahead; @@ -276,6 +345,10 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) { max_coding_data_byte_size); update_encode_frame_result(encode_frame_result, &encode_frame_info); + IncreaseGroupOfPictureIndex(&group_of_picture_); + if (IsGroupOfPictureFinished(group_of_picture_)) { + UpdateGroupOfPicture(&group_of_picture_, impl_ptr_->cpi); + } } void SimpleEncode::EncodeFrameWithQuantizeIndex( diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 471b4e7a8..b8085298b 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -25,6 +25,11 @@ enum FrameType { kAlternateReference, }; +struct EncodeFrameInfo { + int show_idx; + FrameType frame_type; +}; + struct EncodeFrameResult { int show_idx; FrameType frame_type; @@ -38,6 +43,11 @@ struct EncodeFrameResult { int quantize_index; }; +struct GroupOfPicture { + std::vector<EncodeFrameInfo> encode_frame_list; + int encode_frame_index; +}; + class SimpleEncode { public: SimpleEncode(int frame_width, int frame_height, int frame_rate_num, @@ -72,6 +82,14 @@ class SimpleEncode { // counted. int GetKeyFrameGroupSize(int key_frame_index) const; + // Provides the group of pictures that the next coding frame is in. + // Only call this function between StartEncode() and EndEncode() + GroupOfPicture ObserveGroupOfPicture() const; + + // Gets encode_frame_info for the next coding frame. + // Only call this function between StartEncode() and EndEncode() + EncodeFrameInfo GetNextEncodeFrameInfo() const; + // Encodes a frame // This function should be called after StartEncode() and before EndEncode(). void EncodeFrame(EncodeFrameResult *encode_frame_result); @@ -97,6 +115,8 @@ class SimpleEncode { int num_frames_; std::FILE *file_; std::unique_ptr<EncodeImpl> impl_ptr_; + + GroupOfPicture group_of_picture_; }; } // namespace vp9 |