From: angiebird Date: Mon, 11 Nov 2019 20:32:10 +0000 (-0800) Subject: Add frame_type and show_idx to EncodeFrameResult X-Git-Tag: v1.8.2~37 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6956e393c710fab99833500a57062862e97096b6;p=libvpx Add frame_type and show_idx to EncodeFrameResult Let vp9_get_compressed_data update ENCODE_FRAME_RESULT, a C version of EncodeFrameResult. Let unit test to test frame_type and show_idx properly. Change-Id: Id810c26c826254fd82249f19ab855ea3b440d99c --- diff --git a/test/simple_encode_test.cc b/test/simple_encode_test.cc index f9643f612..30970514f 100644 --- a/test/simple_encode_test.cc +++ b/test/simple_encode_test.cc @@ -62,13 +62,31 @@ TEST(SimpleEncode, EncodeFrame) { target_bitrate, num_frames, file); simple_encode.ComputeFirstPassStats(); int num_coding_frames = simple_encode.GetCodingFrameNum(); + EXPECT_GE(num_coding_frames, num_frames); + // The coding frames include actual show frames and alternate reference + // frames, i.e. no show frame. + int ref_num_alternate_refereces = num_coding_frames - num_frames; + int num_alternate_refereces = 0; simple_encode.StartEncode(); for (int i = 0; i < num_coding_frames; ++i) { EncodeFrameResult encode_frame_result; + if (i == 0) { + EXPECT_EQ(encode_frame_result.show_idx, 0); + EXPECT_EQ(encode_frame_result.frame_type, kKeyFrame) + << "The first coding frame should be key frame"; + } simple_encode.EncodeFrame(&encode_frame_result); - // TODO(angiebird): For now, this test just check whether EncodeFrame can be - // run proprly. Add extra check later. + if (encode_frame_result.frame_type == kAlternateReference) { + ++num_alternate_refereces; + } + EXPECT_GE(encode_frame_result.show_idx, 0); + EXPECT_LT(encode_frame_result.show_idx, num_frames); + if (i == num_coding_frames - 1) { + EXPECT_EQ(encode_frame_result.show_idx, num_frames - 1) + << "The last coding frame should should be the last display order"; + } } + EXPECT_EQ(num_alternate_refereces, ref_num_alternate_refereces); simple_encode.EndEncode(); } diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c index c3dcb3ad7..07f2d3444 100644 --- a/vp9/encoder/vp9_encoder.c +++ b/vp9/encoder/vp9_encoder.c @@ -7087,9 +7087,21 @@ static void setup_tpl_stats(VP9_COMP *cpi) { #endif // CONFIG_NON_GREEDY_MV } +static void init_encode_frame_result(ENCODE_FRAME_RESULT *encode_frame_result) { + encode_frame_result->show_idx = -1; // Actual encoding deosn't happen. +} + +static void update_encode_frame_result(ENCODE_FRAME_RESULT *encode_frame_result, + int show_idx, + FRAME_UPDATE_TYPE update_type) { + encode_frame_result->show_idx = show_idx; + encode_frame_result->update_type = update_type; +} + int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, size_t *size, uint8_t *dest, int64_t *time_stamp, - int64_t *time_end, int flush) { + int64_t *time_end, int flush, + ENCODE_FRAME_RESULT *encode_frame_result) { const VP9EncoderConfig *const oxcf = &cpi->oxcf; VP9_COMMON *const cm = &cpi->common; BufferPool *const pool = cm->buffer_pool; @@ -7101,6 +7113,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, int arf_src_index; const int gf_group_index = cpi->twopass.gf_group.index; int i; + init_encode_frame_result(encode_frame_result); if (is_one_pass_cbr_svc(cpi)) { vp9_one_pass_cbr_svc_start_layer(cpi); @@ -7336,6 +7349,12 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, bitstream_queue_set_frame_write(cm->current_video_frame * 2 + cm->show_frame); #endif + if (oxcf->pass != 1) { + update_encode_frame_result( + encode_frame_result, source->show_idx, + cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index]); + } + cpi->td.mb.fp_src_pred = 0; #if CONFIG_REALTIME_ONLY if (cpi->use_svc) { diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h index e52ab65dd..230420953 100644 --- a/vp9/encoder/vp9_encoder.h +++ b/vp9/encoder/vp9_encoder.h @@ -822,6 +822,11 @@ typedef struct VP9_COMP { vpx_roi_map_t roi; } VP9_COMP; +typedef struct ENCODE_FRAME_RESULT { + int show_idx; + FRAME_UPDATE_TYPE update_type; +} ENCODE_FRAME_RESULT; + void vp9_initialize_enc(void); void vp9_update_compressor_with_img_fmt(VP9_COMP *cpi, vpx_img_fmt_t img_fmt); @@ -839,7 +844,8 @@ int vp9_receive_raw_frame(VP9_COMP *cpi, vpx_enc_frame_flags_t frame_flags, int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags, size_t *size, uint8_t *dest, int64_t *time_stamp, - int64_t *time_end, int flush); + int64_t *time_end, int flush, + ENCODE_FRAME_RESULT *encode_frame_result); int vp9_get_preview_raw_frame(VP9_COMP *cpi, YV12_BUFFER_CONFIG *dest, vp9_ppflags_t *flags); diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc index 020ea9fe8..9319a7f9f 100644 --- a/vp9/simple_encode.cc +++ b/vp9/simple_encode.cc @@ -73,6 +73,25 @@ static INLINE vpx_rational_t make_vpx_rational(int num, int den) { return 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; + } +} + +static void update_encode_frame_result( + EncodeFrameResult *encode_frame_result, + const ENCODE_FRAME_RESULT *encode_frame_info) { + encode_frame_result->show_idx = encode_frame_info->show_idx; + encode_frame_result->frame_type = + get_frame_type_from_update_type(encode_frame_info->update_type); +} + SimpleEncode::SimpleEncode(int frame_width, int frame_height, int frame_rate_num, int frame_rate_den, int target_bitrate, int num_frames, FILE *file) @@ -120,9 +139,10 @@ void SimpleEncode::ComputeFirstPassStats() { int flush = 1; // Make vp9_get_compressed_data process a frame size_t size; unsigned int frame_flags = 0; + ENCODE_FRAME_RESULT encode_frame_info; // TODO(angiebird): Call vp9_first_pass directly vp9_get_compressed_data(cpi, &frame_flags, &size, NULL, &time_stamp, - &time_end, flush); + &time_end, flush, &encode_frame_info); // vp9_get_compressed_data only generates first pass stats not // compresses data assert(size == 0); @@ -218,13 +238,17 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) { int64_t time_end; int flush = 1; // Make vp9_get_compressed_data encode a frame unsigned int frame_flags = 0; - vp9_get_compressed_data( - cpi, &frame_flags, &encode_frame_result->coding_data_size, - encode_frame_result->coding_data.get(), &time_stamp, &time_end, flush); + ENCODE_FRAME_RESULT encode_frame_info; + vp9_get_compressed_data(cpi, &frame_flags, + &encode_frame_result->coding_data_size, + encode_frame_result->coding_data.get(), &time_stamp, + &time_end, flush, &encode_frame_info); // vp9_get_compressed_data is expected to encode a frame every time, so the // data size should be greater than zero. assert(encode_frame_result->coding_data_size > 0); assert(encode_frame_result->coding_data_size < max_coding_data_size); + + update_encode_frame_result(encode_frame_result, &encode_frame_info); } int SimpleEncode::GetCodingFrameNum() { diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h index b06339f43..26415a3c2 100644 --- a/vp9/simple_encode.h +++ b/vp9/simple_encode.h @@ -8,8 +8,8 @@ enum FrameType { }; struct EncodeFrameResult { - // TODO(angiebird): int show_index; - // TODO(angiebird): FrameType frame_type; + int show_idx; + FrameType frame_type; size_t coding_data_size; // The EncodeFrame will allocate a buffer, write the coding data into the // buffer and give the ownership of the buffer to coding_data diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c index a019b976c..3f5170859 100644 --- a/vp9/vp9_cx_iface.c +++ b/vp9/vp9_cx_iface.c @@ -1249,11 +1249,12 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, // compute first pass stats if (img) { int ret; + ENCODE_FRAME_RESULT encode_frame_result; vpx_codec_cx_pkt_t fps_pkt; // TODO(angiebird): Call vp9_first_pass directly - ret = - vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, - &dst_time_stamp, &dst_end_time_stamp, !img); + ret = vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, + &dst_time_stamp, &dst_end_time_stamp, + !img, &encode_frame_result); assert(size == 0); // There is no compressed data in the first pass (void)ret; assert(ret == 0); @@ -1271,10 +1272,11 @@ static vpx_codec_err_t encoder_encode(vpx_codec_alg_priv_t *ctx, assert(0); #endif // !CONFIG_REALTIME_ONLY } else { + ENCODE_FRAME_RESULT encode_frame_result; while (cx_data_sz >= ctx->cx_data_sz / 2 && -1 != vp9_get_compressed_data(cpi, &lib_flags, &size, cx_data, &dst_time_stamp, &dst_end_time_stamp, - !img)) { + !img, &encode_frame_result)) { // Pack psnr pkt if (size > 0 && !cpi->use_svc) { // TODO(angiebird): Figure out while we don't need psnr pkt when