ref: 6956e393c710fab99833500a57062862e97096b6
parent: f975d02d6dc095c97c6950a2b8c3768f29644fe5
author: angiebird <angiebird@google.com>
date: Mon Nov 11 07:32:10 EST 2019
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
--- a/test/simple_encode_test.cc
+++ b/test/simple_encode_test.cc
@@ -62,13 +62,31 @@
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();
}
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -7087,9 +7087,21 @@
#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 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);
@@ -7335,6 +7348,12 @@
#if CONFIG_BITSTREAM_DEBUG || CONFIG_MISMATCH_DEBUG
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
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -822,6 +822,11 @@
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_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);
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -73,6 +73,25 @@
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 @@
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 @@
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() {
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -8,8 +8,8 @@
};
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
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -1249,11 +1249,12 @@
// 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 @@
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