shithub: libvpx

Download patch

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