shithub: libvpx

Download patch

ref: 9330bd71a10a216aa0098b2a7a6e17c40c247c27
parent: 7ee697a5daea0dfd7470cc9d1b352de01af0836f
author: angiebird <angiebird@google.com>
date: Sun Nov 10 15:01:42 EST 2019

Add SimpleEncode::EncodeFrame()

Change-Id: I08f074b7db2011f88769bd1d9d50cb376c238fe5

--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -46,6 +46,8 @@
 class SimpleEncode::impl {
  public:
   VP9_COMP *cpi;
+  vpx_img_fmt_t img_fmt;
+  vpx_image_t tmp_img;
   std::vector<FIRSTPASS_STATS> frame_stats;
 };
 
@@ -83,14 +85,14 @@
   this->num_frames = num_frames;
   this->file = file;
   pimpl->cpi = NULL;
+  pimpl->img_fmt = VPX_IMG_FMT_I420;
 }
 
 void SimpleEncode::ComputeFirstPassStats() {
-  const vpx_img_fmt_t img_fmt = VPX_IMG_FMT_I420;
   vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
   const VP9EncoderConfig oxcf = vp9_get_encoder_config(
       frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_FIRST_PASS);
-  VP9_COMP *cpi = init_encoder(&oxcf, img_fmt);
+  VP9_COMP *cpi = init_encoder(&oxcf, pimpl->img_fmt);
   struct lookahead_ctx *lookahead = cpi->lookahead;
   int i;
   int use_highbitdepth = 0;
@@ -98,7 +100,7 @@
   use_highbitdepth = cpi->common.use_highbitdepth;
 #endif
   vpx_image_t img;
-  vpx_img_alloc(&img, img_fmt, frame_width, frame_height, 1);
+  vpx_img_alloc(&img, pimpl->img_fmt, frame_width, frame_height, 1);
   rewind(file);
   pimpl->frame_stats.clear();
   for (i = 0; i < num_frames; ++i) {
@@ -156,11 +158,18 @@
 }
 
 void SimpleEncode::StartEncode() {
+  assert(pimpl->frame_stats.size() > 0);
   vpx_rational_t frame_rate = make_vpx_rational(frame_rate_num, frame_rate_den);
   VP9EncoderConfig oxcf = vp9_get_encoder_config(
       frame_width, frame_height, frame_rate, target_bitrate, VPX_RC_LAST_PASS);
+  vpx_fixed_buf_t stats;
+  stats.buf = pimpl->frame_stats.data();
+  stats.sz = sizeof(pimpl->frame_stats[0]) * pimpl->frame_stats.size();
+
+  vp9_set_first_pass_stats(&oxcf, &stats);
   assert(pimpl->cpi == NULL);
-  pimpl->cpi = init_encoder(&oxcf, VPX_IMG_FMT_I420);
+  pimpl->cpi = init_encoder(&oxcf, pimpl->img_fmt);
+  vpx_img_alloc(&pimpl->tmp_img, pimpl->img_fmt, frame_width, frame_height, 1);
   rewind(file);
 }
 
@@ -167,7 +176,51 @@
 void SimpleEncode::EndEncode() {
   free_encoder(pimpl->cpi);
   pimpl->cpi = nullptr;
+  vpx_img_free(&pimpl->tmp_img);
   rewind(file);
+}
+
+void SimpleEncode::EncodeFrame(char *cx_data, size_t *size, size_t max_size) {
+  VP9_COMP *cpi = pimpl->cpi;
+  struct lookahead_ctx *lookahead = cpi->lookahead;
+  int use_highbitdepth = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+  use_highbitdepth = cpi->common.use_highbitdepth;
+#endif
+  // The lookahead's size is set to oxcf->lag_in_frames.
+  // We want to fill lookahead to it's max capacity if possible so that the
+  // encoder can construct alt ref frame in time.
+  // In the other words, we hope vp9_get_compressed_data to encode a frame
+  // every time in the function
+  while (!vp9_lookahead_full(lookahead)) {
+    // TODO(angiebird): Check whether we can move this file read logics to
+    // lookahead
+    if (img_read(&pimpl->tmp_img, file)) {
+      int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
+      int64_t ts_start =
+          timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts, next_show_idx);
+      int64_t ts_end = timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts,
+                                               next_show_idx + 1);
+      YV12_BUFFER_CONFIG sd;
+      image2yuvconfig(&pimpl->tmp_img, &sd);
+      vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
+    } else {
+      break;
+    }
+  }
+  int64_t time_stamp;
+  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, size,
+                          reinterpret_cast<uint8_t *>(cx_data), &time_stamp,
+                          &time_end, flush);
+  // vp9_get_compressed_data is expected to encode a frame every time, so the
+  // data size should be greater than zero.
+  assert(*size > 0);
+  if (*size >= max_size) {
+    assert(0);
+  }
 }
 
 SimpleEncode::~SimpleEncode() {}
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -22,6 +22,9 @@
   // Free the encoder
   void EndEncode();
 
+  // Encode a frame
+  void EncodeFrame(char *cx_data, size_t *size, size_t max_size);
+
  private:
   class impl;
   int frame_width;
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -566,7 +566,7 @@
   }
   oxcf->sharpness = extra_cfg->sharpness;
 
-  oxcf->two_pass_stats_in = cfg->rc_twopass_stats_in;
+  vp9_set_first_pass_stats(oxcf, &cfg->rc_twopass_stats_in);
 
 #if CONFIG_FP_MB_STATS
   oxcf->firstpass_mb_stats_in = cfg->rc_firstpass_mb_stats_in;
@@ -1944,4 +1944,9 @@
                   frame_info.mi_rows, frame_info.mi_cols);
   // TODO(angiebird): Figure out how to get subsampling_x/y here
   return frame_info;
+}
+
+void vp9_set_first_pass_stats(VP9EncoderConfig *oxcf,
+                              const vpx_fixed_buf_t *stats) {
+  oxcf->two_pass_stats_in = *stats;
 }
--- a/vp9/vp9_cx_iface.h
+++ b/vp9/vp9_cx_iface.h
@@ -35,6 +35,9 @@
   return (n * timestamp_ratio->den + round) / timestamp_ratio->num;
 }
 
+void vp9_set_first_pass_stats(VP9EncoderConfig *oxcf,
+                              const vpx_fixed_buf_t *stats);
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif