From 320fb4c34a6d6bed560fbe564e7e1eae328be100 Mon Sep 17 00:00:00 2001 From: angiebird Date: Thu, 20 Feb 2020 14:11:25 -0800 Subject: [PATCH] Add kGoldenFrame and kOverlayFrame to FrameType Add coding_index to EncodeFrameInfo Add start_coding_index to GroupOfPicture Add frame_coding_index_ to SimpleEncode The definition of coding index is as follows. Each show or no show frame is assigned with a coding index based on its coding order (starting from zero) in the coding process of the entire video. The coding index for each frame is unique. Change-Id: I43e18434a0dff0d1cd6f927a693d6860e4038337 --- vp9/encoder/vp9_firstpass.c | 7 +++--- vp9/encoder/vp9_firstpass.h | 4 ++-- vp9/simple_encode.cc | 43 +++++++++++++++++++++++++++---------- vp9/simple_encode.h | 24 +++++++++++++++++---- 4 files changed, 58 insertions(+), 20 deletions(-) diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c index ba35e6b9c..126e939f2 100644 --- a/vp9/encoder/vp9_firstpass.c +++ b/vp9/encoder/vp9_firstpass.c @@ -3645,12 +3645,12 @@ void vp9_twopass_postencode_update(VP9_COMP *cpi) { #if CONFIG_RATE_CTRL void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame, int *use_alt_ref, int *coding_frame_count, - int *first_show_idx) { + int *first_show_idx, + int *last_gop_use_alt_ref) { // 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 @@ -3658,6 +3658,7 @@ void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame, // the end of encode_frame_to_data_rate(). // TODO(angiebird): Avoid this kind of fragile style. *first_show_idx = cpi->common.current_video_frame; + *last_gop_use_alt_ref = rc.source_alt_ref_active; *first_is_key_frame = 0; if (rc.frames_to_key == 0) { @@ -3671,7 +3672,7 @@ void vp9_get_next_group_of_picture(const VP9_COMP *cpi, int *first_is_key_frame, *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); + *last_gop_use_alt_ref, use_alt_ref); } int vp9_get_gop_coding_frame_count(const VP9EncoderConfig *oxcf, diff --git a/vp9/encoder/vp9_firstpass.h b/vp9/encoder/vp9_firstpass.h index 8462cb05c..2cddc8062 100644 --- a/vp9/encoder/vp9_firstpass.h +++ b/vp9/encoder/vp9_firstpass.h @@ -260,8 +260,8 @@ int vp9_get_frames_to_next_key(const struct VP9EncoderConfig *oxcf, */ void vp9_get_next_group_of_picture(const struct VP9_COMP *cpi, int *first_is_key_frame, int *use_alt_ref, - int *coding_frame_count, - int *first_show_idx); + int *coding_frame_count, int *first_show_idx, + int *last_gop_use_alt_ref); /*!\brief Call this function before coding a new group of pictures to get * information about it. diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index ee7bd1b90..623dff1e2 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -132,12 +132,16 @@ static INLINE vpx_rational_t invert_vpx_rational(vpx_rational_t v) { static INLINE FrameType get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) { - // TODO(angiebird): Figure out if we need frame type other than key frame, - // alternate reference and inter frame switch (update_type) { - case KF_UPDATE: return kKeyFrame; break; - case ARF_UPDATE: return kAlternateReference; break; - default: return kInterFrame; break; + case KF_UPDATE: return kKeyFrame; + case ARF_UPDATE: return kAlternateReference; + case GF_UPDATE: return kGoldenFrame; + case OVERLAY_UPDATE: return kOverlayFrame; + case LF_UPDATE: return kInterFrame; + default: + fprintf(stderr, "Unsupported update_type %d\n", update_type); + abort(); + return kInterFrame; } } @@ -507,12 +511,14 @@ static int IsGroupOfPictureFinished(const GroupOfPicture &group_of_picture) { static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, int coding_frame_count, int first_show_idx, + int last_gop_use_alt_ref, int start_coding_index, GroupOfPicture *group_of_picture) { // Clean up the state of previous group of picture. group_of_picture->encode_frame_list.clear(); group_of_picture->next_encode_frame_index = 0; 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; { // First frame in the group of pictures. It's either key frame or show inter // frame. @@ -520,9 +526,14 @@ static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, if (first_is_key_frame) { encode_frame_info.frame_type = kKeyFrame; } else { - encode_frame_info.frame_type = kInterFrame; + if (last_gop_use_alt_ref) { + encode_frame_info.frame_type = kOverlayFrame; + } else { + encode_frame_info.frame_type = kGoldenFrame; + } } encode_frame_info.show_idx = first_show_idx; + encode_frame_info.coding_index = start_coding_index; group_of_picture->encode_frame_list.push_back(encode_frame_info); } @@ -533,6 +544,7 @@ static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, EncodeFrameInfo encode_frame_info; encode_frame_info.frame_type = kAlternateReference; encode_frame_info.show_idx = first_show_idx + show_frame_count; + encode_frame_info.coding_index = start_coding_index + 1; group_of_picture->encode_frame_list.push_back(encode_frame_info); } @@ -541,20 +553,24 @@ static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref, EncodeFrameInfo encode_frame_info; encode_frame_info.frame_type = kInterFrame; encode_frame_info.show_idx = first_show_idx + i; + encode_frame_info.coding_index = start_coding_index + use_alt_ref + i; group_of_picture->encode_frame_list.push_back(encode_frame_info); } } -static void UpdateGroupOfPicture(const VP9_COMP *cpi, +static void UpdateGroupOfPicture(const VP9_COMP *cpi, int start_coding_index, GroupOfPicture *group_of_picture) { int first_is_key_frame; int use_alt_ref; int coding_frame_count; int first_show_idx; + int last_gop_use_alt_ref; vp9_get_next_group_of_picture(cpi, &first_is_key_frame, &use_alt_ref, - &coding_frame_count, &first_show_idx); + &coding_frame_count, &first_show_idx, + &last_gop_use_alt_ref); SetGroupOfPicture(first_is_key_frame, use_alt_ref, coding_frame_count, - first_show_idx, group_of_picture); + first_show_idx, last_gop_use_alt_ref, start_coding_index, + group_of_picture); } SimpleEncode::SimpleEncode(int frame_width, int frame_height, @@ -568,6 +584,7 @@ SimpleEncode::SimpleEncode(int frame_width, int frame_height, frame_rate_den_ = frame_rate_den; target_bitrate_ = target_bitrate; num_frames_ = num_frames; + frame_coding_index_ = 0; // TODO(angirbid): Should we keep a file pointer here or keep the file_path? in_file_ = fopen(infile_path, "r"); if (outfile_path != nullptr) { @@ -672,7 +689,8 @@ 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(impl_ptr_->cpi, &group_of_picture_); + frame_coding_index_ = 0; + UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, &group_of_picture_); rewind(in_file_); if (out_file_ != nullptr) { @@ -771,10 +789,13 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) { abort(); } + // TODO(angiebird): Add a function to update internal state of SimpleEncode update_encode_frame_result(encode_frame_result, &encode_frame_info); + ++frame_coding_index_; IncreaseGroupOfPictureIndex(&group_of_picture_); if (IsGroupOfPictureFinished(group_of_picture_)) { - UpdateGroupOfPicture(impl_ptr_->cpi, &group_of_picture_); + UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, + &group_of_picture_); } } else { // TODO(angiebird): Clean up encode_frame_result. diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index 60f405e97..4e8fefff1 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -23,15 +23,18 @@ enum FrameType { kKeyFrame = 0, kInterFrame, kAlternateReference, + kOverlayFrame, + kGoldenFrame, }; // The enum type is similar to vp9: |MV_REFERENCE_FRAME|. +// TODO(angiebird): Clarify the difference between FrameType and RefFrameType. enum RefFrameType { - kIntraFrame = 0, - kLastFrame = 1, - kGoldenFrame = 2, + kIntraRefFrame = 0, + kLastRefFrame = 1, + kGoldenRefFrame = 2, kAltRefFrame = 3, - kNoneRefFrame = -1, + kNoneRefRefFrame = -1, }; // The frame is split to 4x4 blocks. @@ -68,6 +71,11 @@ struct MotionVectorInfo { struct EncodeFrameInfo { int show_idx; + + // Each show or no show frame is assigned with a coding index based on its + // coding order (starting from zero) in the coding process of the entire + // video. The coding index for each frame is unique. + int coding_index; FrameType frame_type; }; @@ -237,6 +245,8 @@ struct GroupOfPicture { // 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. + int start_coding_index; }; class SimpleEncode { @@ -309,11 +319,17 @@ class SimpleEncode { int frame_rate_den_; int target_bitrate_; int num_frames_; + std::FILE *in_file_; std::FILE *out_file_; std::unique_ptr impl_ptr_; GroupOfPicture group_of_picture_; + + // Each show or no show frame is assigned with a coding index based on its + // coding order (starting from zero) in the coding process of the entire + // video. The coding index of to-be-coded frame. + int frame_coding_index_; }; } // namespace vp9 -- 2.40.0