xref: /aosp_15_r20/external/libvpx/vp9/simple_encode.cc (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2019 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
12*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
13*fb1b10abSAndroid Build Coastguard Worker 
14*fb1b10abSAndroid Build Coastguard Worker #include <memory>
15*fb1b10abSAndroid Build Coastguard Worker #include <vector>
16*fb1b10abSAndroid Build Coastguard Worker 
17*fb1b10abSAndroid Build Coastguard Worker #include "./ivfenc.h"
18*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_entropymode.h"
19*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_enums.h"
20*fb1b10abSAndroid Build Coastguard Worker #include "vp9/common/vp9_onyxc_int.h"
21*fb1b10abSAndroid Build Coastguard Worker #include "vp9/vp9_iface_common.h"
22*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
23*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_firstpass.h"
24*fb1b10abSAndroid Build Coastguard Worker #include "vp9/simple_encode.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "vp9/vp9_cx_iface.h"
26*fb1b10abSAndroid Build Coastguard Worker 
27*fb1b10abSAndroid Build Coastguard Worker namespace vp9 {
28*fb1b10abSAndroid Build Coastguard Worker 
get_plane_height(vpx_img_fmt_t img_fmt,int frame_height,int plane)29*fb1b10abSAndroid Build Coastguard Worker static int get_plane_height(vpx_img_fmt_t img_fmt, int frame_height,
30*fb1b10abSAndroid Build Coastguard Worker                             int plane) {
31*fb1b10abSAndroid Build Coastguard Worker   assert(plane < 3);
32*fb1b10abSAndroid Build Coastguard Worker   if (plane == 0) {
33*fb1b10abSAndroid Build Coastguard Worker     return frame_height;
34*fb1b10abSAndroid Build Coastguard Worker   }
35*fb1b10abSAndroid Build Coastguard Worker   switch (img_fmt) {
36*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I420:
37*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I440:
38*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_YV12:
39*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I42016:
40*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I44016: return (frame_height + 1) >> 1;
41*fb1b10abSAndroid Build Coastguard Worker     default: return frame_height;
42*fb1b10abSAndroid Build Coastguard Worker   }
43*fb1b10abSAndroid Build Coastguard Worker }
44*fb1b10abSAndroid Build Coastguard Worker 
get_plane_width(vpx_img_fmt_t img_fmt,int frame_width,int plane)45*fb1b10abSAndroid Build Coastguard Worker static int get_plane_width(vpx_img_fmt_t img_fmt, int frame_width, int plane) {
46*fb1b10abSAndroid Build Coastguard Worker   assert(plane < 3);
47*fb1b10abSAndroid Build Coastguard Worker   if (plane == 0) {
48*fb1b10abSAndroid Build Coastguard Worker     return frame_width;
49*fb1b10abSAndroid Build Coastguard Worker   }
50*fb1b10abSAndroid Build Coastguard Worker   switch (img_fmt) {
51*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I420:
52*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_YV12:
53*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I422:
54*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I42016:
55*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I42216: return (frame_width + 1) >> 1;
56*fb1b10abSAndroid Build Coastguard Worker     default: return frame_width;
57*fb1b10abSAndroid Build Coastguard Worker   }
58*fb1b10abSAndroid Build Coastguard Worker }
59*fb1b10abSAndroid Build Coastguard Worker 
60*fb1b10abSAndroid Build Coastguard Worker // TODO(angiebird): Merge this function with vpx_img_plane_width()
img_plane_width(const vpx_image_t * img,int plane)61*fb1b10abSAndroid Build Coastguard Worker static int img_plane_width(const vpx_image_t *img, int plane) {
62*fb1b10abSAndroid Build Coastguard Worker   if (plane > 0 && img->x_chroma_shift > 0)
63*fb1b10abSAndroid Build Coastguard Worker     return (img->d_w + 1) >> img->x_chroma_shift;
64*fb1b10abSAndroid Build Coastguard Worker   else
65*fb1b10abSAndroid Build Coastguard Worker     return img->d_w;
66*fb1b10abSAndroid Build Coastguard Worker }
67*fb1b10abSAndroid Build Coastguard Worker 
68*fb1b10abSAndroid Build Coastguard Worker // TODO(angiebird): Merge this function with vpx_img_plane_height()
img_plane_height(const vpx_image_t * img,int plane)69*fb1b10abSAndroid Build Coastguard Worker static int img_plane_height(const vpx_image_t *img, int plane) {
70*fb1b10abSAndroid Build Coastguard Worker   if (plane > 0 && img->y_chroma_shift > 0)
71*fb1b10abSAndroid Build Coastguard Worker     return (img->d_h + 1) >> img->y_chroma_shift;
72*fb1b10abSAndroid Build Coastguard Worker   else
73*fb1b10abSAndroid Build Coastguard Worker     return img->d_h;
74*fb1b10abSAndroid Build Coastguard Worker }
75*fb1b10abSAndroid Build Coastguard Worker 
76*fb1b10abSAndroid Build Coastguard Worker // TODO(angiebird): Merge this function with vpx_img_read()
img_read(vpx_image_t * img,FILE * file)77*fb1b10abSAndroid Build Coastguard Worker static int img_read(vpx_image_t *img, FILE *file) {
78*fb1b10abSAndroid Build Coastguard Worker   int plane;
79*fb1b10abSAndroid Build Coastguard Worker 
80*fb1b10abSAndroid Build Coastguard Worker   for (plane = 0; plane < 3; ++plane) {
81*fb1b10abSAndroid Build Coastguard Worker     unsigned char *buf = img->planes[plane];
82*fb1b10abSAndroid Build Coastguard Worker     const int stride = img->stride[plane];
83*fb1b10abSAndroid Build Coastguard Worker     const int w = img_plane_width(img, plane) *
84*fb1b10abSAndroid Build Coastguard Worker                   ((img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1);
85*fb1b10abSAndroid Build Coastguard Worker     const int h = img_plane_height(img, plane);
86*fb1b10abSAndroid Build Coastguard Worker     int y;
87*fb1b10abSAndroid Build Coastguard Worker 
88*fb1b10abSAndroid Build Coastguard Worker     for (y = 0; y < h; ++y) {
89*fb1b10abSAndroid Build Coastguard Worker       if (fread(buf, 1, w, file) != (size_t)w) return 0;
90*fb1b10abSAndroid Build Coastguard Worker       buf += stride;
91*fb1b10abSAndroid Build Coastguard Worker     }
92*fb1b10abSAndroid Build Coastguard Worker   }
93*fb1b10abSAndroid Build Coastguard Worker 
94*fb1b10abSAndroid Build Coastguard Worker   return 1;
95*fb1b10abSAndroid Build Coastguard Worker }
96*fb1b10abSAndroid Build Coastguard Worker 
97*fb1b10abSAndroid Build Coastguard Worker // Assume every config in VP9EncoderConfig is less than 100 characters.
98*fb1b10abSAndroid Build Coastguard Worker #define ENCODE_CONFIG_BUF_SIZE 100
99*fb1b10abSAndroid Build Coastguard Worker struct EncodeConfig {
100*fb1b10abSAndroid Build Coastguard Worker   char name[ENCODE_CONFIG_BUF_SIZE];
101*fb1b10abSAndroid Build Coastguard Worker   char value[ENCODE_CONFIG_BUF_SIZE];
102*fb1b10abSAndroid Build Coastguard Worker };
103*fb1b10abSAndroid Build Coastguard Worker 
104*fb1b10abSAndroid Build Coastguard Worker class SimpleEncode::EncodeImpl {
105*fb1b10abSAndroid Build Coastguard Worker  public:
106*fb1b10abSAndroid Build Coastguard Worker   VP9_COMP *cpi;
107*fb1b10abSAndroid Build Coastguard Worker   vpx_img_fmt_t img_fmt;
108*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t tmp_img;
109*fb1b10abSAndroid Build Coastguard Worker   std::vector<FIRSTPASS_STATS> first_pass_stats;
110*fb1b10abSAndroid Build Coastguard Worker   std::vector<EncodeConfig> encode_config_list;
111*fb1b10abSAndroid Build Coastguard Worker };
112*fb1b10abSAndroid Build Coastguard Worker 
init_encoder(const VP9EncoderConfig * oxcf,vpx_img_fmt_t img_fmt)113*fb1b10abSAndroid Build Coastguard Worker static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf,
114*fb1b10abSAndroid Build Coastguard Worker                               vpx_img_fmt_t img_fmt) {
115*fb1b10abSAndroid Build Coastguard Worker   VP9_COMP *cpi;
116*fb1b10abSAndroid Build Coastguard Worker   BufferPool *buffer_pool = (BufferPool *)vpx_calloc(1, sizeof(*buffer_pool));
117*fb1b10abSAndroid Build Coastguard Worker   if (!buffer_pool) return NULL;
118*fb1b10abSAndroid Build Coastguard Worker   vp9_initialize_enc();
119*fb1b10abSAndroid Build Coastguard Worker   cpi = vp9_create_compressor(oxcf, buffer_pool);
120*fb1b10abSAndroid Build Coastguard Worker   vp9_update_compressor_with_img_fmt(cpi, img_fmt);
121*fb1b10abSAndroid Build Coastguard Worker   return cpi;
122*fb1b10abSAndroid Build Coastguard Worker }
123*fb1b10abSAndroid Build Coastguard Worker 
free_encoder(VP9_COMP * cpi)124*fb1b10abSAndroid Build Coastguard Worker static void free_encoder(VP9_COMP *cpi) {
125*fb1b10abSAndroid Build Coastguard Worker   BufferPool *buffer_pool = cpi->common.buffer_pool;
126*fb1b10abSAndroid Build Coastguard Worker   vp9_remove_compressor(cpi);
127*fb1b10abSAndroid Build Coastguard Worker   // buffer_pool needs to be free after cpi because buffer_pool contains
128*fb1b10abSAndroid Build Coastguard Worker   // allocated buffers that will be free in vp9_remove_compressor()
129*fb1b10abSAndroid Build Coastguard Worker   vpx_free(buffer_pool);
130*fb1b10abSAndroid Build Coastguard Worker }
131*fb1b10abSAndroid Build Coastguard Worker 
make_vpx_rational(int num,int den)132*fb1b10abSAndroid Build Coastguard Worker static INLINE vpx_rational_t make_vpx_rational(int num, int den) {
133*fb1b10abSAndroid Build Coastguard Worker   vpx_rational_t v;
134*fb1b10abSAndroid Build Coastguard Worker   v.num = num;
135*fb1b10abSAndroid Build Coastguard Worker   v.den = den;
136*fb1b10abSAndroid Build Coastguard Worker   return v;
137*fb1b10abSAndroid Build Coastguard Worker }
138*fb1b10abSAndroid Build Coastguard Worker 
139*fb1b10abSAndroid Build Coastguard Worker static INLINE FrameType
get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type)140*fb1b10abSAndroid Build Coastguard Worker get_frame_type_from_update_type(FRAME_UPDATE_TYPE update_type) {
141*fb1b10abSAndroid Build Coastguard Worker   switch (update_type) {
142*fb1b10abSAndroid Build Coastguard Worker     case KF_UPDATE: return kFrameTypeKey;
143*fb1b10abSAndroid Build Coastguard Worker     case ARF_UPDATE: return kFrameTypeAltRef;
144*fb1b10abSAndroid Build Coastguard Worker     case GF_UPDATE: return kFrameTypeGolden;
145*fb1b10abSAndroid Build Coastguard Worker     case OVERLAY_UPDATE: return kFrameTypeOverlay;
146*fb1b10abSAndroid Build Coastguard Worker     case LF_UPDATE: return kFrameTypeInter;
147*fb1b10abSAndroid Build Coastguard Worker     default:
148*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "Unsupported update_type %d\n", update_type);
149*fb1b10abSAndroid Build Coastguard Worker       abort();
150*fb1b10abSAndroid Build Coastguard Worker   }
151*fb1b10abSAndroid Build Coastguard Worker }
152*fb1b10abSAndroid Build Coastguard Worker 
update_partition_info(const PARTITION_INFO * input_partition_info,const int num_rows_4x4,const int num_cols_4x4,PartitionInfo * output_partition_info)153*fb1b10abSAndroid Build Coastguard Worker static void update_partition_info(const PARTITION_INFO *input_partition_info,
154*fb1b10abSAndroid Build Coastguard Worker                                   const int num_rows_4x4,
155*fb1b10abSAndroid Build Coastguard Worker                                   const int num_cols_4x4,
156*fb1b10abSAndroid Build Coastguard Worker                                   PartitionInfo *output_partition_info) {
157*fb1b10abSAndroid Build Coastguard Worker   const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
158*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < num_units_4x4; ++i) {
159*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].row = input_partition_info[i].row;
160*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].column = input_partition_info[i].column;
161*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].row_start = input_partition_info[i].row_start;
162*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].column_start =
163*fb1b10abSAndroid Build Coastguard Worker         input_partition_info[i].column_start;
164*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].width = input_partition_info[i].width;
165*fb1b10abSAndroid Build Coastguard Worker     output_partition_info[i].height = input_partition_info[i].height;
166*fb1b10abSAndroid Build Coastguard Worker   }
167*fb1b10abSAndroid Build Coastguard Worker }
168*fb1b10abSAndroid Build Coastguard Worker 
169*fb1b10abSAndroid Build Coastguard Worker // translate MV_REFERENCE_FRAME to RefFrameType
mv_ref_frame_to_ref_frame_type(MV_REFERENCE_FRAME mv_ref_frame)170*fb1b10abSAndroid Build Coastguard Worker static RefFrameType mv_ref_frame_to_ref_frame_type(
171*fb1b10abSAndroid Build Coastguard Worker     MV_REFERENCE_FRAME mv_ref_frame) {
172*fb1b10abSAndroid Build Coastguard Worker   switch (mv_ref_frame) {
173*fb1b10abSAndroid Build Coastguard Worker     case LAST_FRAME: return kRefFrameTypeLast;
174*fb1b10abSAndroid Build Coastguard Worker     case GOLDEN_FRAME: return kRefFrameTypePast;
175*fb1b10abSAndroid Build Coastguard Worker     case ALTREF_FRAME: return kRefFrameTypeFuture;
176*fb1b10abSAndroid Build Coastguard Worker     default: return kRefFrameTypeNone;
177*fb1b10abSAndroid Build Coastguard Worker   }
178*fb1b10abSAndroid Build Coastguard Worker }
179*fb1b10abSAndroid Build Coastguard Worker 
update_motion_vector_info(const MOTION_VECTOR_INFO * input_motion_vector_info,const int num_rows_4x4,const int num_cols_4x4,MotionVectorInfo * output_motion_vector_info,int motion_vector_scale)180*fb1b10abSAndroid Build Coastguard Worker static void update_motion_vector_info(
181*fb1b10abSAndroid Build Coastguard Worker     const MOTION_VECTOR_INFO *input_motion_vector_info, const int num_rows_4x4,
182*fb1b10abSAndroid Build Coastguard Worker     const int num_cols_4x4, MotionVectorInfo *output_motion_vector_info,
183*fb1b10abSAndroid Build Coastguard Worker     int motion_vector_scale) {
184*fb1b10abSAndroid Build Coastguard Worker   const int num_units_4x4 = num_rows_4x4 * num_cols_4x4;
185*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < num_units_4x4; ++i) {
186*fb1b10abSAndroid Build Coastguard Worker     const MV_REFERENCE_FRAME *in_ref_frame =
187*fb1b10abSAndroid Build Coastguard Worker         input_motion_vector_info[i].ref_frame;
188*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].mv_count =
189*fb1b10abSAndroid Build Coastguard Worker         (in_ref_frame[0] == INTRA_FRAME)
190*fb1b10abSAndroid Build Coastguard Worker             ? 0
191*fb1b10abSAndroid Build Coastguard Worker             : ((in_ref_frame[1] == NO_REF_FRAME) ? 1 : 2);
192*fb1b10abSAndroid Build Coastguard Worker     if (in_ref_frame[0] == NO_REF_FRAME) {
193*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "in_ref_frame[0] shouldn't be NO_REF_FRAME\n");
194*fb1b10abSAndroid Build Coastguard Worker       abort();
195*fb1b10abSAndroid Build Coastguard Worker     }
196*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].ref_frame[0] =
197*fb1b10abSAndroid Build Coastguard Worker         mv_ref_frame_to_ref_frame_type(in_ref_frame[0]);
198*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].ref_frame[1] =
199*fb1b10abSAndroid Build Coastguard Worker         mv_ref_frame_to_ref_frame_type(in_ref_frame[1]);
200*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].mv_row[0] =
201*fb1b10abSAndroid Build Coastguard Worker         (double)input_motion_vector_info[i].mv[0].as_mv.row /
202*fb1b10abSAndroid Build Coastguard Worker         motion_vector_scale;
203*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].mv_column[0] =
204*fb1b10abSAndroid Build Coastguard Worker         (double)input_motion_vector_info[i].mv[0].as_mv.col /
205*fb1b10abSAndroid Build Coastguard Worker         motion_vector_scale;
206*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].mv_row[1] =
207*fb1b10abSAndroid Build Coastguard Worker         (double)input_motion_vector_info[i].mv[1].as_mv.row /
208*fb1b10abSAndroid Build Coastguard Worker         motion_vector_scale;
209*fb1b10abSAndroid Build Coastguard Worker     output_motion_vector_info[i].mv_column[1] =
210*fb1b10abSAndroid Build Coastguard Worker         (double)input_motion_vector_info[i].mv[1].as_mv.col /
211*fb1b10abSAndroid Build Coastguard Worker         motion_vector_scale;
212*fb1b10abSAndroid Build Coastguard Worker   }
213*fb1b10abSAndroid Build Coastguard Worker }
214*fb1b10abSAndroid Build Coastguard Worker 
update_tpl_stats_info(const TplDepStats * input_tpl_stats_info,const int show_frame_count,TplStatsInfo * output_tpl_stats_info)215*fb1b10abSAndroid Build Coastguard Worker static void update_tpl_stats_info(const TplDepStats *input_tpl_stats_info,
216*fb1b10abSAndroid Build Coastguard Worker                                   const int show_frame_count,
217*fb1b10abSAndroid Build Coastguard Worker                                   TplStatsInfo *output_tpl_stats_info) {
218*fb1b10abSAndroid Build Coastguard Worker   int frame_idx;
219*fb1b10abSAndroid Build Coastguard Worker   for (frame_idx = 0; frame_idx < show_frame_count; ++frame_idx) {
220*fb1b10abSAndroid Build Coastguard Worker     output_tpl_stats_info[frame_idx].intra_cost =
221*fb1b10abSAndroid Build Coastguard Worker         input_tpl_stats_info[frame_idx].intra_cost;
222*fb1b10abSAndroid Build Coastguard Worker     output_tpl_stats_info[frame_idx].inter_cost =
223*fb1b10abSAndroid Build Coastguard Worker         input_tpl_stats_info[frame_idx].inter_cost;
224*fb1b10abSAndroid Build Coastguard Worker     output_tpl_stats_info[frame_idx].mc_flow =
225*fb1b10abSAndroid Build Coastguard Worker         input_tpl_stats_info[frame_idx].mc_flow;
226*fb1b10abSAndroid Build Coastguard Worker     output_tpl_stats_info[frame_idx].mc_dep_cost =
227*fb1b10abSAndroid Build Coastguard Worker         input_tpl_stats_info[frame_idx].mc_dep_cost;
228*fb1b10abSAndroid Build Coastguard Worker     output_tpl_stats_info[frame_idx].mc_ref_cost =
229*fb1b10abSAndroid Build Coastguard Worker         input_tpl_stats_info[frame_idx].mc_ref_cost;
230*fb1b10abSAndroid Build Coastguard Worker   }
231*fb1b10abSAndroid Build Coastguard Worker }
232*fb1b10abSAndroid Build Coastguard Worker 
update_frame_counts(const FRAME_COUNTS * input_counts,FrameCounts * output_counts)233*fb1b10abSAndroid Build Coastguard Worker static void update_frame_counts(const FRAME_COUNTS *input_counts,
234*fb1b10abSAndroid Build Coastguard Worker                                 FrameCounts *output_counts) {
235*fb1b10abSAndroid Build Coastguard Worker   // Init array sizes.
236*fb1b10abSAndroid Build Coastguard Worker   output_counts->y_mode.resize(BLOCK_SIZE_GROUPS);
237*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
238*fb1b10abSAndroid Build Coastguard Worker     output_counts->y_mode[i].resize(INTRA_MODES);
239*fb1b10abSAndroid Build Coastguard Worker   }
240*fb1b10abSAndroid Build Coastguard Worker 
241*fb1b10abSAndroid Build Coastguard Worker   output_counts->uv_mode.resize(INTRA_MODES);
242*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTRA_MODES; ++i) {
243*fb1b10abSAndroid Build Coastguard Worker     output_counts->uv_mode[i].resize(INTRA_MODES);
244*fb1b10abSAndroid Build Coastguard Worker   }
245*fb1b10abSAndroid Build Coastguard Worker 
246*fb1b10abSAndroid Build Coastguard Worker   output_counts->partition.resize(PARTITION_CONTEXTS);
247*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < PARTITION_CONTEXTS; ++i) {
248*fb1b10abSAndroid Build Coastguard Worker     output_counts->partition[i].resize(PARTITION_TYPES);
249*fb1b10abSAndroid Build Coastguard Worker   }
250*fb1b10abSAndroid Build Coastguard Worker 
251*fb1b10abSAndroid Build Coastguard Worker   output_counts->coef.resize(TX_SIZES);
252*fb1b10abSAndroid Build Coastguard Worker   output_counts->eob_branch.resize(TX_SIZES);
253*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < TX_SIZES; ++i) {
254*fb1b10abSAndroid Build Coastguard Worker     output_counts->coef[i].resize(PLANE_TYPES);
255*fb1b10abSAndroid Build Coastguard Worker     output_counts->eob_branch[i].resize(PLANE_TYPES);
256*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < PLANE_TYPES; ++j) {
257*fb1b10abSAndroid Build Coastguard Worker       output_counts->coef[i][j].resize(REF_TYPES);
258*fb1b10abSAndroid Build Coastguard Worker       output_counts->eob_branch[i][j].resize(REF_TYPES);
259*fb1b10abSAndroid Build Coastguard Worker       for (int k = 0; k < REF_TYPES; ++k) {
260*fb1b10abSAndroid Build Coastguard Worker         output_counts->coef[i][j][k].resize(COEF_BANDS);
261*fb1b10abSAndroid Build Coastguard Worker         output_counts->eob_branch[i][j][k].resize(COEF_BANDS);
262*fb1b10abSAndroid Build Coastguard Worker         for (int l = 0; l < COEF_BANDS; ++l) {
263*fb1b10abSAndroid Build Coastguard Worker           output_counts->coef[i][j][k][l].resize(COEFF_CONTEXTS);
264*fb1b10abSAndroid Build Coastguard Worker           output_counts->eob_branch[i][j][k][l].resize(COEFF_CONTEXTS);
265*fb1b10abSAndroid Build Coastguard Worker           for (int m = 0; m < COEFF_CONTEXTS; ++m) {
266*fb1b10abSAndroid Build Coastguard Worker             output_counts->coef[i][j][k][l][m].resize(UNCONSTRAINED_NODES + 1);
267*fb1b10abSAndroid Build Coastguard Worker           }
268*fb1b10abSAndroid Build Coastguard Worker         }
269*fb1b10abSAndroid Build Coastguard Worker       }
270*fb1b10abSAndroid Build Coastguard Worker     }
271*fb1b10abSAndroid Build Coastguard Worker   }
272*fb1b10abSAndroid Build Coastguard Worker 
273*fb1b10abSAndroid Build Coastguard Worker   output_counts->switchable_interp.resize(SWITCHABLE_FILTER_CONTEXTS);
274*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) {
275*fb1b10abSAndroid Build Coastguard Worker     output_counts->switchable_interp[i].resize(SWITCHABLE_FILTERS);
276*fb1b10abSAndroid Build Coastguard Worker   }
277*fb1b10abSAndroid Build Coastguard Worker 
278*fb1b10abSAndroid Build Coastguard Worker   output_counts->inter_mode.resize(INTER_MODE_CONTEXTS);
279*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) {
280*fb1b10abSAndroid Build Coastguard Worker     output_counts->inter_mode[i].resize(INTER_MODES);
281*fb1b10abSAndroid Build Coastguard Worker   }
282*fb1b10abSAndroid Build Coastguard Worker 
283*fb1b10abSAndroid Build Coastguard Worker   output_counts->intra_inter.resize(INTRA_INTER_CONTEXTS);
284*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) {
285*fb1b10abSAndroid Build Coastguard Worker     output_counts->intra_inter[i].resize(2);
286*fb1b10abSAndroid Build Coastguard Worker   }
287*fb1b10abSAndroid Build Coastguard Worker 
288*fb1b10abSAndroid Build Coastguard Worker   output_counts->comp_inter.resize(COMP_INTER_CONTEXTS);
289*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) {
290*fb1b10abSAndroid Build Coastguard Worker     output_counts->comp_inter[i].resize(2);
291*fb1b10abSAndroid Build Coastguard Worker   }
292*fb1b10abSAndroid Build Coastguard Worker 
293*fb1b10abSAndroid Build Coastguard Worker   output_counts->single_ref.resize(REF_CONTEXTS);
294*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < REF_CONTEXTS; ++i) {
295*fb1b10abSAndroid Build Coastguard Worker     output_counts->single_ref[i].resize(2);
296*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
297*fb1b10abSAndroid Build Coastguard Worker       output_counts->single_ref[i][j].resize(2);
298*fb1b10abSAndroid Build Coastguard Worker     }
299*fb1b10abSAndroid Build Coastguard Worker   }
300*fb1b10abSAndroid Build Coastguard Worker 
301*fb1b10abSAndroid Build Coastguard Worker   output_counts->comp_ref.resize(REF_CONTEXTS);
302*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < REF_CONTEXTS; ++i) {
303*fb1b10abSAndroid Build Coastguard Worker     output_counts->comp_ref[i].resize(2);
304*fb1b10abSAndroid Build Coastguard Worker   }
305*fb1b10abSAndroid Build Coastguard Worker 
306*fb1b10abSAndroid Build Coastguard Worker   output_counts->skip.resize(SKIP_CONTEXTS);
307*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < SKIP_CONTEXTS; ++i) {
308*fb1b10abSAndroid Build Coastguard Worker     output_counts->skip[i].resize(2);
309*fb1b10abSAndroid Build Coastguard Worker   }
310*fb1b10abSAndroid Build Coastguard Worker 
311*fb1b10abSAndroid Build Coastguard Worker   output_counts->tx.p32x32.resize(TX_SIZE_CONTEXTS);
312*fb1b10abSAndroid Build Coastguard Worker   output_counts->tx.p16x16.resize(TX_SIZE_CONTEXTS);
313*fb1b10abSAndroid Build Coastguard Worker   output_counts->tx.p8x8.resize(TX_SIZE_CONTEXTS);
314*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < TX_SIZE_CONTEXTS; i++) {
315*fb1b10abSAndroid Build Coastguard Worker     output_counts->tx.p32x32[i].resize(TX_SIZES);
316*fb1b10abSAndroid Build Coastguard Worker     output_counts->tx.p16x16[i].resize(TX_SIZES - 1);
317*fb1b10abSAndroid Build Coastguard Worker     output_counts->tx.p8x8[i].resize(TX_SIZES - 2);
318*fb1b10abSAndroid Build Coastguard Worker   }
319*fb1b10abSAndroid Build Coastguard Worker   output_counts->tx.tx_totals.resize(TX_SIZES);
320*fb1b10abSAndroid Build Coastguard Worker 
321*fb1b10abSAndroid Build Coastguard Worker   output_counts->mv.joints.resize(MV_JOINTS);
322*fb1b10abSAndroid Build Coastguard Worker   output_counts->mv.comps.resize(2);
323*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < 2; ++i) {
324*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].sign.resize(2);
325*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].classes.resize(MV_CLASSES);
326*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].class0.resize(CLASS0_SIZE);
327*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].bits.resize(MV_OFFSET_BITS);
328*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < MV_OFFSET_BITS; ++j) {
329*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[i].bits[j].resize(2);
330*fb1b10abSAndroid Build Coastguard Worker     }
331*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].class0_fp.resize(CLASS0_SIZE);
332*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < CLASS0_SIZE; ++j) {
333*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[i].class0_fp[j].resize(MV_FP_SIZE);
334*fb1b10abSAndroid Build Coastguard Worker     }
335*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].fp.resize(MV_FP_SIZE);
336*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].class0_hp.resize(2);
337*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.comps[i].hp.resize(2);
338*fb1b10abSAndroid Build Coastguard Worker   }
339*fb1b10abSAndroid Build Coastguard Worker 
340*fb1b10abSAndroid Build Coastguard Worker   // Populate counts.
341*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < BLOCK_SIZE_GROUPS; ++i) {
342*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < INTRA_MODES; ++j) {
343*fb1b10abSAndroid Build Coastguard Worker       output_counts->y_mode[i][j] = input_counts->y_mode[i][j];
344*fb1b10abSAndroid Build Coastguard Worker     }
345*fb1b10abSAndroid Build Coastguard Worker   }
346*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTRA_MODES; ++i) {
347*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < INTRA_MODES; ++j) {
348*fb1b10abSAndroid Build Coastguard Worker       output_counts->uv_mode[i][j] = input_counts->uv_mode[i][j];
349*fb1b10abSAndroid Build Coastguard Worker     }
350*fb1b10abSAndroid Build Coastguard Worker   }
351*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < PARTITION_CONTEXTS; ++i) {
352*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < PARTITION_TYPES; ++j) {
353*fb1b10abSAndroid Build Coastguard Worker       output_counts->partition[i][j] = input_counts->partition[i][j];
354*fb1b10abSAndroid Build Coastguard Worker     }
355*fb1b10abSAndroid Build Coastguard Worker   }
356*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < TX_SIZES; ++i) {
357*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < PLANE_TYPES; ++j) {
358*fb1b10abSAndroid Build Coastguard Worker       for (int k = 0; k < REF_TYPES; ++k) {
359*fb1b10abSAndroid Build Coastguard Worker         for (int l = 0; l < COEF_BANDS; ++l) {
360*fb1b10abSAndroid Build Coastguard Worker           for (int m = 0; m < COEFF_CONTEXTS; ++m) {
361*fb1b10abSAndroid Build Coastguard Worker             output_counts->eob_branch[i][j][k][l][m] =
362*fb1b10abSAndroid Build Coastguard Worker                 input_counts->eob_branch[i][j][k][l][m];
363*fb1b10abSAndroid Build Coastguard Worker             for (int n = 0; n < UNCONSTRAINED_NODES + 1; n++) {
364*fb1b10abSAndroid Build Coastguard Worker               output_counts->coef[i][j][k][l][m][n] =
365*fb1b10abSAndroid Build Coastguard Worker                   input_counts->coef[i][j][k][l][m][n];
366*fb1b10abSAndroid Build Coastguard Worker             }
367*fb1b10abSAndroid Build Coastguard Worker           }
368*fb1b10abSAndroid Build Coastguard Worker         }
369*fb1b10abSAndroid Build Coastguard Worker       }
370*fb1b10abSAndroid Build Coastguard Worker     }
371*fb1b10abSAndroid Build Coastguard Worker   }
372*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < SWITCHABLE_FILTER_CONTEXTS; ++i) {
373*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < SWITCHABLE_FILTERS; ++j) {
374*fb1b10abSAndroid Build Coastguard Worker       output_counts->switchable_interp[i][j] =
375*fb1b10abSAndroid Build Coastguard Worker           input_counts->switchable_interp[i][j];
376*fb1b10abSAndroid Build Coastguard Worker     }
377*fb1b10abSAndroid Build Coastguard Worker   }
378*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTER_MODE_CONTEXTS; ++i) {
379*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < INTER_MODES; ++j) {
380*fb1b10abSAndroid Build Coastguard Worker       output_counts->inter_mode[i][j] = input_counts->inter_mode[i][j];
381*fb1b10abSAndroid Build Coastguard Worker     }
382*fb1b10abSAndroid Build Coastguard Worker   }
383*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < INTRA_INTER_CONTEXTS; ++i) {
384*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
385*fb1b10abSAndroid Build Coastguard Worker       output_counts->intra_inter[i][j] = input_counts->intra_inter[i][j];
386*fb1b10abSAndroid Build Coastguard Worker     }
387*fb1b10abSAndroid Build Coastguard Worker   }
388*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < COMP_INTER_CONTEXTS; ++i) {
389*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
390*fb1b10abSAndroid Build Coastguard Worker       output_counts->comp_inter[i][j] = input_counts->comp_inter[i][j];
391*fb1b10abSAndroid Build Coastguard Worker     }
392*fb1b10abSAndroid Build Coastguard Worker   }
393*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < REF_CONTEXTS; ++i) {
394*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
395*fb1b10abSAndroid Build Coastguard Worker       for (int k = 0; k < 2; ++k) {
396*fb1b10abSAndroid Build Coastguard Worker         output_counts->single_ref[i][j][k] = input_counts->single_ref[i][j][k];
397*fb1b10abSAndroid Build Coastguard Worker       }
398*fb1b10abSAndroid Build Coastguard Worker     }
399*fb1b10abSAndroid Build Coastguard Worker   }
400*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < REF_CONTEXTS; ++i) {
401*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
402*fb1b10abSAndroid Build Coastguard Worker       output_counts->comp_ref[i][j] = input_counts->comp_ref[i][j];
403*fb1b10abSAndroid Build Coastguard Worker     }
404*fb1b10abSAndroid Build Coastguard Worker   }
405*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < SKIP_CONTEXTS; ++i) {
406*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < 2; ++j) {
407*fb1b10abSAndroid Build Coastguard Worker       output_counts->skip[i][j] = input_counts->skip[i][j];
408*fb1b10abSAndroid Build Coastguard Worker     }
409*fb1b10abSAndroid Build Coastguard Worker   }
410*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < TX_SIZE_CONTEXTS; i++) {
411*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < TX_SIZES; j++) {
412*fb1b10abSAndroid Build Coastguard Worker       output_counts->tx.p32x32[i][j] = input_counts->tx.p32x32[i][j];
413*fb1b10abSAndroid Build Coastguard Worker     }
414*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < TX_SIZES - 1; j++) {
415*fb1b10abSAndroid Build Coastguard Worker       output_counts->tx.p16x16[i][j] = input_counts->tx.p16x16[i][j];
416*fb1b10abSAndroid Build Coastguard Worker     }
417*fb1b10abSAndroid Build Coastguard Worker     for (int j = 0; j < TX_SIZES - 2; j++) {
418*fb1b10abSAndroid Build Coastguard Worker       output_counts->tx.p8x8[i][j] = input_counts->tx.p8x8[i][j];
419*fb1b10abSAndroid Build Coastguard Worker     }
420*fb1b10abSAndroid Build Coastguard Worker   }
421*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < TX_SIZES; i++) {
422*fb1b10abSAndroid Build Coastguard Worker     output_counts->tx.tx_totals[i] = input_counts->tx.tx_totals[i];
423*fb1b10abSAndroid Build Coastguard Worker   }
424*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < MV_JOINTS; i++) {
425*fb1b10abSAndroid Build Coastguard Worker     output_counts->mv.joints[i] = input_counts->mv.joints[i];
426*fb1b10abSAndroid Build Coastguard Worker   }
427*fb1b10abSAndroid Build Coastguard Worker   for (int k = 0; k < 2; k++) {
428*fb1b10abSAndroid Build Coastguard Worker     const nmv_component_counts *const comps_t = &input_counts->mv.comps[k];
429*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < 2; i++) {
430*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].sign[i] = comps_t->sign[i];
431*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].class0_hp[i] = comps_t->class0_hp[i];
432*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].hp[i] = comps_t->hp[i];
433*fb1b10abSAndroid Build Coastguard Worker     }
434*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < MV_CLASSES; i++) {
435*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].classes[i] = comps_t->classes[i];
436*fb1b10abSAndroid Build Coastguard Worker     }
437*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < CLASS0_SIZE; i++) {
438*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].class0[i] = comps_t->class0[i];
439*fb1b10abSAndroid Build Coastguard Worker       for (int j = 0; j < MV_FP_SIZE; j++) {
440*fb1b10abSAndroid Build Coastguard Worker         output_counts->mv.comps[k].class0_fp[i][j] = comps_t->class0_fp[i][j];
441*fb1b10abSAndroid Build Coastguard Worker       }
442*fb1b10abSAndroid Build Coastguard Worker     }
443*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < MV_OFFSET_BITS; i++) {
444*fb1b10abSAndroid Build Coastguard Worker       for (int j = 0; j < 2; j++) {
445*fb1b10abSAndroid Build Coastguard Worker         output_counts->mv.comps[k].bits[i][j] = comps_t->bits[i][j];
446*fb1b10abSAndroid Build Coastguard Worker       }
447*fb1b10abSAndroid Build Coastguard Worker     }
448*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < MV_FP_SIZE; i++) {
449*fb1b10abSAndroid Build Coastguard Worker       output_counts->mv.comps[k].fp[i] = comps_t->fp[i];
450*fb1b10abSAndroid Build Coastguard Worker     }
451*fb1b10abSAndroid Build Coastguard Worker   }
452*fb1b10abSAndroid Build Coastguard Worker }
453*fb1b10abSAndroid Build Coastguard Worker 
output_image_buffer(const ImageBuffer & image_buffer,std::FILE * out_file)454*fb1b10abSAndroid Build Coastguard Worker void output_image_buffer(const ImageBuffer &image_buffer, std::FILE *out_file) {
455*fb1b10abSAndroid Build Coastguard Worker   for (int plane = 0; plane < 3; ++plane) {
456*fb1b10abSAndroid Build Coastguard Worker     const int w = image_buffer.plane_width[plane];
457*fb1b10abSAndroid Build Coastguard Worker     const int h = image_buffer.plane_height[plane];
458*fb1b10abSAndroid Build Coastguard Worker     const uint8_t *buf = image_buffer.plane_buffer[plane].get();
459*fb1b10abSAndroid Build Coastguard Worker     fprintf(out_file, "%d %d\n", h, w);
460*fb1b10abSAndroid Build Coastguard Worker     for (int i = 0; i < w * h; ++i) {
461*fb1b10abSAndroid Build Coastguard Worker       fprintf(out_file, "%d ", (int)buf[i]);
462*fb1b10abSAndroid Build Coastguard Worker     }
463*fb1b10abSAndroid Build Coastguard Worker     fprintf(out_file, "\n");
464*fb1b10abSAndroid Build Coastguard Worker   }
465*fb1b10abSAndroid Build Coastguard Worker }
466*fb1b10abSAndroid Build Coastguard Worker 
init_image_buffer(ImageBuffer * image_buffer,int frame_width,int frame_height,vpx_img_fmt_t img_fmt)467*fb1b10abSAndroid Build Coastguard Worker static bool init_image_buffer(ImageBuffer *image_buffer, int frame_width,
468*fb1b10abSAndroid Build Coastguard Worker                               int frame_height, vpx_img_fmt_t img_fmt) {
469*fb1b10abSAndroid Build Coastguard Worker   for (int plane = 0; plane < 3; ++plane) {
470*fb1b10abSAndroid Build Coastguard Worker     const int w = get_plane_width(img_fmt, frame_width, plane);
471*fb1b10abSAndroid Build Coastguard Worker     const int h = get_plane_height(img_fmt, frame_height, plane);
472*fb1b10abSAndroid Build Coastguard Worker     image_buffer->plane_width[plane] = w;
473*fb1b10abSAndroid Build Coastguard Worker     image_buffer->plane_height[plane] = h;
474*fb1b10abSAndroid Build Coastguard Worker     image_buffer->plane_buffer[plane].reset(new (std::nothrow) uint8_t[w * h]);
475*fb1b10abSAndroid Build Coastguard Worker     if (image_buffer->plane_buffer[plane].get() == nullptr) {
476*fb1b10abSAndroid Build Coastguard Worker       return false;
477*fb1b10abSAndroid Build Coastguard Worker     }
478*fb1b10abSAndroid Build Coastguard Worker   }
479*fb1b10abSAndroid Build Coastguard Worker   return true;
480*fb1b10abSAndroid Build Coastguard Worker }
481*fb1b10abSAndroid Build Coastguard Worker 
ImageBuffer_to_IMAGE_BUFFER(const ImageBuffer & image_buffer,IMAGE_BUFFER * image_buffer_c)482*fb1b10abSAndroid Build Coastguard Worker static void ImageBuffer_to_IMAGE_BUFFER(const ImageBuffer &image_buffer,
483*fb1b10abSAndroid Build Coastguard Worker                                         IMAGE_BUFFER *image_buffer_c) {
484*fb1b10abSAndroid Build Coastguard Worker   image_buffer_c->allocated = 1;
485*fb1b10abSAndroid Build Coastguard Worker   for (int plane = 0; plane < 3; ++plane) {
486*fb1b10abSAndroid Build Coastguard Worker     image_buffer_c->plane_width[plane] = image_buffer.plane_width[plane];
487*fb1b10abSAndroid Build Coastguard Worker     image_buffer_c->plane_height[plane] = image_buffer.plane_height[plane];
488*fb1b10abSAndroid Build Coastguard Worker     image_buffer_c->plane_buffer[plane] =
489*fb1b10abSAndroid Build Coastguard Worker         image_buffer.plane_buffer[plane].get();
490*fb1b10abSAndroid Build Coastguard Worker   }
491*fb1b10abSAndroid Build Coastguard Worker }
492*fb1b10abSAndroid Build Coastguard Worker 
get_max_coding_data_byte_size(int frame_width,int frame_height)493*fb1b10abSAndroid Build Coastguard Worker static size_t get_max_coding_data_byte_size(int frame_width, int frame_height) {
494*fb1b10abSAndroid Build Coastguard Worker   return frame_width * frame_height * 3;
495*fb1b10abSAndroid Build Coastguard Worker }
496*fb1b10abSAndroid Build Coastguard Worker 
init_encode_frame_result(EncodeFrameResult * encode_frame_result,int frame_width,int frame_height,vpx_img_fmt_t img_fmt)497*fb1b10abSAndroid Build Coastguard Worker static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result,
498*fb1b10abSAndroid Build Coastguard Worker                                      int frame_width, int frame_height,
499*fb1b10abSAndroid Build Coastguard Worker                                      vpx_img_fmt_t img_fmt) {
500*fb1b10abSAndroid Build Coastguard Worker   const size_t max_coding_data_byte_size =
501*fb1b10abSAndroid Build Coastguard Worker       get_max_coding_data_byte_size(frame_width, frame_height);
502*fb1b10abSAndroid Build Coastguard Worker 
503*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->coding_data.reset(
504*fb1b10abSAndroid Build Coastguard Worker       new (std::nothrow) uint8_t[max_coding_data_byte_size]);
505*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->max_coding_data_byte_size = max_coding_data_byte_size;
506*fb1b10abSAndroid Build Coastguard Worker 
507*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->num_rows_4x4 = get_num_unit_4x4(frame_height);
508*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->num_cols_4x4 = get_num_unit_4x4(frame_width);
509*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->partition_info.resize(encode_frame_result->num_rows_4x4 *
510*fb1b10abSAndroid Build Coastguard Worker                                              encode_frame_result->num_cols_4x4);
511*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->motion_vector_info.resize(
512*fb1b10abSAndroid Build Coastguard Worker       encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4);
513*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->tpl_stats_info.resize(MAX_LAG_BUFFERS);
514*fb1b10abSAndroid Build Coastguard Worker 
515*fb1b10abSAndroid Build Coastguard Worker   if (encode_frame_result->coding_data.get() == nullptr) {
516*fb1b10abSAndroid Build Coastguard Worker     encode_frame_result->max_coding_data_byte_size = 0;
517*fb1b10abSAndroid Build Coastguard Worker     return false;
518*fb1b10abSAndroid Build Coastguard Worker   }
519*fb1b10abSAndroid Build Coastguard Worker   return init_image_buffer(&encode_frame_result->coded_frame, frame_width,
520*fb1b10abSAndroid Build Coastguard Worker                            frame_height, img_fmt);
521*fb1b10abSAndroid Build Coastguard Worker }
522*fb1b10abSAndroid Build Coastguard Worker 
encode_frame_result_update_rq_history(const RATE_QINDEX_HISTORY * rq_history,EncodeFrameResult * encode_frame_result)523*fb1b10abSAndroid Build Coastguard Worker static void encode_frame_result_update_rq_history(
524*fb1b10abSAndroid Build Coastguard Worker     const RATE_QINDEX_HISTORY *rq_history,
525*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameResult *encode_frame_result) {
526*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->recode_count = rq_history->recode_count;
527*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < encode_frame_result->recode_count; ++i) {
528*fb1b10abSAndroid Build Coastguard Worker     const int q_index = rq_history->q_index_history[i];
529*fb1b10abSAndroid Build Coastguard Worker     const int rate = rq_history->rate_history[i];
530*fb1b10abSAndroid Build Coastguard Worker     encode_frame_result->q_index_history.push_back(q_index);
531*fb1b10abSAndroid Build Coastguard Worker     encode_frame_result->rate_history.push_back(rate);
532*fb1b10abSAndroid Build Coastguard Worker   }
533*fb1b10abSAndroid Build Coastguard Worker }
534*fb1b10abSAndroid Build Coastguard Worker 
update_encode_frame_result(EncodeFrameResult * encode_frame_result,const int show_frame_count,const ENCODE_FRAME_RESULT * encode_frame_info)535*fb1b10abSAndroid Build Coastguard Worker static void update_encode_frame_result(
536*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameResult *encode_frame_result, const int show_frame_count,
537*fb1b10abSAndroid Build Coastguard Worker     const ENCODE_FRAME_RESULT *encode_frame_info) {
538*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->coding_data_bit_size =
539*fb1b10abSAndroid Build Coastguard Worker       encode_frame_result->coding_data_byte_size * 8;
540*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->show_idx = encode_frame_info->show_idx;
541*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->coding_idx = encode_frame_info->frame_coding_index;
542*fb1b10abSAndroid Build Coastguard Worker   assert(kRefFrameTypeMax == MAX_INTER_REF_FRAMES);
543*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < kRefFrameTypeMax; ++i) {
544*fb1b10abSAndroid Build Coastguard Worker     encode_frame_result->ref_frame_info.coding_indexes[i] =
545*fb1b10abSAndroid Build Coastguard Worker         encode_frame_info->ref_frame_coding_indexes[i];
546*fb1b10abSAndroid Build Coastguard Worker     encode_frame_result->ref_frame_info.valid_list[i] =
547*fb1b10abSAndroid Build Coastguard Worker         encode_frame_info->ref_frame_valid_list[i];
548*fb1b10abSAndroid Build Coastguard Worker   }
549*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->frame_type =
550*fb1b10abSAndroid Build Coastguard Worker       get_frame_type_from_update_type(encode_frame_info->update_type);
551*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->psnr = encode_frame_info->psnr;
552*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->sse = encode_frame_info->sse;
553*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result->quantize_index = encode_frame_info->quantize_index;
554*fb1b10abSAndroid Build Coastguard Worker   update_partition_info(encode_frame_info->partition_info,
555*fb1b10abSAndroid Build Coastguard Worker                         encode_frame_result->num_rows_4x4,
556*fb1b10abSAndroid Build Coastguard Worker                         encode_frame_result->num_cols_4x4,
557*fb1b10abSAndroid Build Coastguard Worker                         &encode_frame_result->partition_info[0]);
558*fb1b10abSAndroid Build Coastguard Worker   update_motion_vector_info(encode_frame_info->motion_vector_info,
559*fb1b10abSAndroid Build Coastguard Worker                             encode_frame_result->num_rows_4x4,
560*fb1b10abSAndroid Build Coastguard Worker                             encode_frame_result->num_cols_4x4,
561*fb1b10abSAndroid Build Coastguard Worker                             &encode_frame_result->motion_vector_info[0],
562*fb1b10abSAndroid Build Coastguard Worker                             kMotionVectorSubPixelPrecision);
563*fb1b10abSAndroid Build Coastguard Worker   update_frame_counts(&encode_frame_info->frame_counts,
564*fb1b10abSAndroid Build Coastguard Worker                       &encode_frame_result->frame_counts);
565*fb1b10abSAndroid Build Coastguard Worker   if (encode_frame_result->frame_type == kFrameTypeAltRef) {
566*fb1b10abSAndroid Build Coastguard Worker     update_tpl_stats_info(encode_frame_info->tpl_stats_info, show_frame_count,
567*fb1b10abSAndroid Build Coastguard Worker                           &encode_frame_result->tpl_stats_info[0]);
568*fb1b10abSAndroid Build Coastguard Worker   }
569*fb1b10abSAndroid Build Coastguard Worker   encode_frame_result_update_rq_history(&encode_frame_info->rq_history,
570*fb1b10abSAndroid Build Coastguard Worker                                         encode_frame_result);
571*fb1b10abSAndroid Build Coastguard Worker }
572*fb1b10abSAndroid Build Coastguard Worker 
IncreaseGroupOfPictureIndex(GroupOfPicture * group_of_picture)573*fb1b10abSAndroid Build Coastguard Worker static void IncreaseGroupOfPictureIndex(GroupOfPicture *group_of_picture) {
574*fb1b10abSAndroid Build Coastguard Worker   ++group_of_picture->next_encode_frame_index;
575*fb1b10abSAndroid Build Coastguard Worker }
576*fb1b10abSAndroid Build Coastguard Worker 
IsGroupOfPictureFinished(const GroupOfPicture & group_of_picture)577*fb1b10abSAndroid Build Coastguard Worker static int IsGroupOfPictureFinished(const GroupOfPicture &group_of_picture) {
578*fb1b10abSAndroid Build Coastguard Worker   return static_cast<size_t>(group_of_picture.next_encode_frame_index) ==
579*fb1b10abSAndroid Build Coastguard Worker          group_of_picture.encode_frame_list.size();
580*fb1b10abSAndroid Build Coastguard Worker }
581*fb1b10abSAndroid Build Coastguard Worker 
operator ==(const RefFrameInfo & a,const RefFrameInfo & b)582*fb1b10abSAndroid Build Coastguard Worker bool operator==(const RefFrameInfo &a, const RefFrameInfo &b) {
583*fb1b10abSAndroid Build Coastguard Worker   bool match = true;
584*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < kRefFrameTypeMax; ++i) {
585*fb1b10abSAndroid Build Coastguard Worker     match &= a.coding_indexes[i] == b.coding_indexes[i];
586*fb1b10abSAndroid Build Coastguard Worker     match &= a.valid_list[i] == b.valid_list[i];
587*fb1b10abSAndroid Build Coastguard Worker   }
588*fb1b10abSAndroid Build Coastguard Worker   return match;
589*fb1b10abSAndroid Build Coastguard Worker }
590*fb1b10abSAndroid Build Coastguard Worker 
InitRefFrameInfo(RefFrameInfo * ref_frame_info)591*fb1b10abSAndroid Build Coastguard Worker static void InitRefFrameInfo(RefFrameInfo *ref_frame_info) {
592*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < kRefFrameTypeMax; ++i) {
593*fb1b10abSAndroid Build Coastguard Worker     ref_frame_info->coding_indexes[i] = -1;
594*fb1b10abSAndroid Build Coastguard Worker     ref_frame_info->valid_list[i] = 0;
595*fb1b10abSAndroid Build Coastguard Worker   }
596*fb1b10abSAndroid Build Coastguard Worker }
597*fb1b10abSAndroid Build Coastguard Worker 
598*fb1b10abSAndroid Build Coastguard Worker // After finishing coding a frame, this function will update the coded frame
599*fb1b10abSAndroid Build Coastguard Worker // into the ref_frame_info based on the frame_type and the coding_index.
PostUpdateRefFrameInfo(FrameType frame_type,int frame_coding_index,RefFrameInfo * ref_frame_info)600*fb1b10abSAndroid Build Coastguard Worker static void PostUpdateRefFrameInfo(FrameType frame_type, int frame_coding_index,
601*fb1b10abSAndroid Build Coastguard Worker                                    RefFrameInfo *ref_frame_info) {
602*fb1b10abSAndroid Build Coastguard Worker   // This part is written based on the logics in vp9_configure_buffer_updates()
603*fb1b10abSAndroid Build Coastguard Worker   // and update_ref_frames()
604*fb1b10abSAndroid Build Coastguard Worker   int *ref_frame_coding_indexes = ref_frame_info->coding_indexes;
605*fb1b10abSAndroid Build Coastguard Worker   switch (frame_type) {
606*fb1b10abSAndroid Build Coastguard Worker     case kFrameTypeKey:
607*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeLast] = frame_coding_index;
608*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypePast] = frame_coding_index;
609*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeFuture] = frame_coding_index;
610*fb1b10abSAndroid Build Coastguard Worker       break;
611*fb1b10abSAndroid Build Coastguard Worker     case kFrameTypeInter:
612*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeLast] = frame_coding_index;
613*fb1b10abSAndroid Build Coastguard Worker       break;
614*fb1b10abSAndroid Build Coastguard Worker     case kFrameTypeAltRef:
615*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeFuture] = frame_coding_index;
616*fb1b10abSAndroid Build Coastguard Worker       break;
617*fb1b10abSAndroid Build Coastguard Worker     case kFrameTypeOverlay:
618*fb1b10abSAndroid Build Coastguard Worker       // Reserve the past coding_index in the future slot. This logic is from
619*fb1b10abSAndroid Build Coastguard Worker       // update_ref_frames() with condition vp9_preserve_existing_gf() == 1
620*fb1b10abSAndroid Build Coastguard Worker       // TODO(angiebird): Invetegate why we need this.
621*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeFuture] =
622*fb1b10abSAndroid Build Coastguard Worker           ref_frame_coding_indexes[kRefFrameTypePast];
623*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypePast] = frame_coding_index;
624*fb1b10abSAndroid Build Coastguard Worker       break;
625*fb1b10abSAndroid Build Coastguard Worker     case kFrameTypeGolden:
626*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypePast] = frame_coding_index;
627*fb1b10abSAndroid Build Coastguard Worker       ref_frame_coding_indexes[kRefFrameTypeLast] = frame_coding_index;
628*fb1b10abSAndroid Build Coastguard Worker       break;
629*fb1b10abSAndroid Build Coastguard Worker   }
630*fb1b10abSAndroid Build Coastguard Worker 
631*fb1b10abSAndroid Build Coastguard Worker   //  This part is written based on the logics in get_ref_frame_flags() but we
632*fb1b10abSAndroid Build Coastguard Worker   //  rename the flags alt, golden to future, past respectively. Mark
633*fb1b10abSAndroid Build Coastguard Worker   //  non-duplicated reference frames as valid. The priorities are
634*fb1b10abSAndroid Build Coastguard Worker   //  kRefFrameTypeLast > kRefFrameTypePast > kRefFrameTypeFuture.
635*fb1b10abSAndroid Build Coastguard Worker   const int last_index = ref_frame_coding_indexes[kRefFrameTypeLast];
636*fb1b10abSAndroid Build Coastguard Worker   const int past_index = ref_frame_coding_indexes[kRefFrameTypePast];
637*fb1b10abSAndroid Build Coastguard Worker   const int future_index = ref_frame_coding_indexes[kRefFrameTypeFuture];
638*fb1b10abSAndroid Build Coastguard Worker 
639*fb1b10abSAndroid Build Coastguard Worker   int *ref_frame_valid_list = ref_frame_info->valid_list;
640*fb1b10abSAndroid Build Coastguard Worker   for (int ref_frame_idx = 0; ref_frame_idx < kRefFrameTypeMax;
641*fb1b10abSAndroid Build Coastguard Worker        ++ref_frame_idx) {
642*fb1b10abSAndroid Build Coastguard Worker     ref_frame_valid_list[ref_frame_idx] = 1;
643*fb1b10abSAndroid Build Coastguard Worker   }
644*fb1b10abSAndroid Build Coastguard Worker 
645*fb1b10abSAndroid Build Coastguard Worker   if (past_index == last_index) {
646*fb1b10abSAndroid Build Coastguard Worker     ref_frame_valid_list[kRefFrameTypePast] = 0;
647*fb1b10abSAndroid Build Coastguard Worker   }
648*fb1b10abSAndroid Build Coastguard Worker 
649*fb1b10abSAndroid Build Coastguard Worker   if (future_index == last_index) {
650*fb1b10abSAndroid Build Coastguard Worker     ref_frame_valid_list[kRefFrameTypeFuture] = 0;
651*fb1b10abSAndroid Build Coastguard Worker   }
652*fb1b10abSAndroid Build Coastguard Worker 
653*fb1b10abSAndroid Build Coastguard Worker   if (future_index == past_index) {
654*fb1b10abSAndroid Build Coastguard Worker     ref_frame_valid_list[kRefFrameTypeFuture] = 0;
655*fb1b10abSAndroid Build Coastguard Worker   }
656*fb1b10abSAndroid Build Coastguard Worker }
657*fb1b10abSAndroid Build Coastguard Worker 
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,const RefFrameInfo & start_ref_frame_info,GroupOfPicture * group_of_picture)658*fb1b10abSAndroid Build Coastguard Worker static void SetGroupOfPicture(int first_is_key_frame, int use_alt_ref,
659*fb1b10abSAndroid Build Coastguard Worker                               int coding_frame_count, int first_show_idx,
660*fb1b10abSAndroid Build Coastguard Worker                               int last_gop_use_alt_ref, int start_coding_index,
661*fb1b10abSAndroid Build Coastguard Worker                               const RefFrameInfo &start_ref_frame_info,
662*fb1b10abSAndroid Build Coastguard Worker                               GroupOfPicture *group_of_picture) {
663*fb1b10abSAndroid Build Coastguard Worker   // Clean up the state of previous group of picture.
664*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->encode_frame_list.clear();
665*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->next_encode_frame_index = 0;
666*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->show_frame_count = coding_frame_count - use_alt_ref;
667*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->start_show_index = first_show_idx;
668*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->start_coding_index = start_coding_index;
669*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->first_is_key_frame = first_is_key_frame;
670*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->use_alt_ref = use_alt_ref;
671*fb1b10abSAndroid Build Coastguard Worker   group_of_picture->last_gop_use_alt_ref = last_gop_use_alt_ref;
672*fb1b10abSAndroid Build Coastguard Worker 
673*fb1b10abSAndroid Build Coastguard Worker   // We need to make a copy of start reference frame info because we
674*fb1b10abSAndroid Build Coastguard Worker   // use it to simulate the ref frame update.
675*fb1b10abSAndroid Build Coastguard Worker   RefFrameInfo ref_frame_info = start_ref_frame_info;
676*fb1b10abSAndroid Build Coastguard Worker 
677*fb1b10abSAndroid Build Coastguard Worker   {
678*fb1b10abSAndroid Build Coastguard Worker     // First frame in the group of pictures. It's either key frame or show inter
679*fb1b10abSAndroid Build Coastguard Worker     // frame.
680*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameInfo encode_frame_info;
681*fb1b10abSAndroid Build Coastguard Worker     // Set frame_type
682*fb1b10abSAndroid Build Coastguard Worker     if (first_is_key_frame) {
683*fb1b10abSAndroid Build Coastguard Worker       encode_frame_info.frame_type = kFrameTypeKey;
684*fb1b10abSAndroid Build Coastguard Worker     } else {
685*fb1b10abSAndroid Build Coastguard Worker       if (last_gop_use_alt_ref) {
686*fb1b10abSAndroid Build Coastguard Worker         encode_frame_info.frame_type = kFrameTypeOverlay;
687*fb1b10abSAndroid Build Coastguard Worker       } else {
688*fb1b10abSAndroid Build Coastguard Worker         encode_frame_info.frame_type = kFrameTypeGolden;
689*fb1b10abSAndroid Build Coastguard Worker       }
690*fb1b10abSAndroid Build Coastguard Worker     }
691*fb1b10abSAndroid Build Coastguard Worker 
692*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.show_idx = first_show_idx;
693*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.coding_index = start_coding_index;
694*fb1b10abSAndroid Build Coastguard Worker 
695*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.ref_frame_info = ref_frame_info;
696*fb1b10abSAndroid Build Coastguard Worker     PostUpdateRefFrameInfo(encode_frame_info.frame_type,
697*fb1b10abSAndroid Build Coastguard Worker                            encode_frame_info.coding_index, &ref_frame_info);
698*fb1b10abSAndroid Build Coastguard Worker 
699*fb1b10abSAndroid Build Coastguard Worker     group_of_picture->encode_frame_list.push_back(encode_frame_info);
700*fb1b10abSAndroid Build Coastguard Worker   }
701*fb1b10abSAndroid Build Coastguard Worker 
702*fb1b10abSAndroid Build Coastguard Worker   const int show_frame_count = coding_frame_count - use_alt_ref;
703*fb1b10abSAndroid Build Coastguard Worker   if (use_alt_ref) {
704*fb1b10abSAndroid Build Coastguard Worker     // If there is alternate reference, it is always coded at the second place.
705*fb1b10abSAndroid Build Coastguard Worker     // Its show index (or timestamp) is at the last of this group
706*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameInfo encode_frame_info;
707*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.frame_type = kFrameTypeAltRef;
708*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.show_idx = first_show_idx + show_frame_count;
709*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.coding_index = start_coding_index + 1;
710*fb1b10abSAndroid Build Coastguard Worker 
711*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.ref_frame_info = ref_frame_info;
712*fb1b10abSAndroid Build Coastguard Worker     PostUpdateRefFrameInfo(encode_frame_info.frame_type,
713*fb1b10abSAndroid Build Coastguard Worker                            encode_frame_info.coding_index, &ref_frame_info);
714*fb1b10abSAndroid Build Coastguard Worker 
715*fb1b10abSAndroid Build Coastguard Worker     group_of_picture->encode_frame_list.push_back(encode_frame_info);
716*fb1b10abSAndroid Build Coastguard Worker   }
717*fb1b10abSAndroid Build Coastguard Worker 
718*fb1b10abSAndroid Build Coastguard Worker   // Encode the rest show inter frames.
719*fb1b10abSAndroid Build Coastguard Worker   for (int i = 1; i < show_frame_count; ++i) {
720*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameInfo encode_frame_info;
721*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.frame_type = kFrameTypeInter;
722*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.show_idx = first_show_idx + i;
723*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.coding_index = start_coding_index + use_alt_ref + i;
724*fb1b10abSAndroid Build Coastguard Worker 
725*fb1b10abSAndroid Build Coastguard Worker     encode_frame_info.ref_frame_info = ref_frame_info;
726*fb1b10abSAndroid Build Coastguard Worker     PostUpdateRefFrameInfo(encode_frame_info.frame_type,
727*fb1b10abSAndroid Build Coastguard Worker                            encode_frame_info.coding_index, &ref_frame_info);
728*fb1b10abSAndroid Build Coastguard Worker 
729*fb1b10abSAndroid Build Coastguard Worker     group_of_picture->encode_frame_list.push_back(encode_frame_info);
730*fb1b10abSAndroid Build Coastguard Worker   }
731*fb1b10abSAndroid Build Coastguard Worker }
732*fb1b10abSAndroid Build Coastguard Worker 
733*fb1b10abSAndroid Build Coastguard Worker // Gets group of picture information from VP9's decision, and update
734*fb1b10abSAndroid Build Coastguard Worker // |group_of_picture| accordingly.
735*fb1b10abSAndroid Build Coastguard Worker // This is called at the starting of encoding of each group of picture.
UpdateGroupOfPicture(const VP9_COMP * cpi,int start_coding_index,const RefFrameInfo & start_ref_frame_info,GroupOfPicture * group_of_picture)736*fb1b10abSAndroid Build Coastguard Worker static void UpdateGroupOfPicture(const VP9_COMP *cpi, int start_coding_index,
737*fb1b10abSAndroid Build Coastguard Worker                                  const RefFrameInfo &start_ref_frame_info,
738*fb1b10abSAndroid Build Coastguard Worker                                  GroupOfPicture *group_of_picture) {
739*fb1b10abSAndroid Build Coastguard Worker   int first_is_key_frame;
740*fb1b10abSAndroid Build Coastguard Worker   int use_alt_ref;
741*fb1b10abSAndroid Build Coastguard Worker   int coding_frame_count;
742*fb1b10abSAndroid Build Coastguard Worker   int first_show_idx;
743*fb1b10abSAndroid Build Coastguard Worker   int last_gop_use_alt_ref;
744*fb1b10abSAndroid Build Coastguard Worker   vp9_get_next_group_of_picture(cpi, &first_is_key_frame, &use_alt_ref,
745*fb1b10abSAndroid Build Coastguard Worker                                 &coding_frame_count, &first_show_idx,
746*fb1b10abSAndroid Build Coastguard Worker                                 &last_gop_use_alt_ref);
747*fb1b10abSAndroid Build Coastguard Worker   SetGroupOfPicture(first_is_key_frame, use_alt_ref, coding_frame_count,
748*fb1b10abSAndroid Build Coastguard Worker                     first_show_idx, last_gop_use_alt_ref, start_coding_index,
749*fb1b10abSAndroid Build Coastguard Worker                     start_ref_frame_info, group_of_picture);
750*fb1b10abSAndroid Build Coastguard Worker }
751*fb1b10abSAndroid Build Coastguard Worker 
752*fb1b10abSAndroid Build Coastguard Worker #define SET_STRUCT_VALUE(config, structure, ret, field) \
753*fb1b10abSAndroid Build Coastguard Worker   do {                                                  \
754*fb1b10abSAndroid Build Coastguard Worker     if (strcmp(config.name, #field) == 0) {             \
755*fb1b10abSAndroid Build Coastguard Worker       structure->field = atoi(config.value);            \
756*fb1b10abSAndroid Build Coastguard Worker       ret = 1;                                          \
757*fb1b10abSAndroid Build Coastguard Worker     }                                                   \
758*fb1b10abSAndroid Build Coastguard Worker   } while (false)
759*fb1b10abSAndroid Build Coastguard Worker 
UpdateEncodeConfig(const EncodeConfig & config,VP9EncoderConfig * oxcf)760*fb1b10abSAndroid Build Coastguard Worker static void UpdateEncodeConfig(const EncodeConfig &config,
761*fb1b10abSAndroid Build Coastguard Worker                                VP9EncoderConfig *oxcf) {
762*fb1b10abSAndroid Build Coastguard Worker   int ret = 0;
763*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, key_freq);
764*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, two_pass_vbrmin_section);
765*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, two_pass_vbrmax_section);
766*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, under_shoot_pct);
767*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, over_shoot_pct);
768*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, max_threads);
769*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, frame_parallel_decoding_mode);
770*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, tile_columns);
771*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, arnr_max_frames);
772*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, arnr_strength);
773*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, lag_in_frames);
774*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, encode_breakout);
775*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, enable_tpl_model);
776*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, enable_auto_arf);
777*fb1b10abSAndroid Build Coastguard Worker   if (strcmp(config.name, "rc_mode") == 0) {
778*fb1b10abSAndroid Build Coastguard Worker     int rc_mode = atoi(config.value);
779*fb1b10abSAndroid Build Coastguard Worker     if (rc_mode >= VPX_VBR && rc_mode <= VPX_Q) {
780*fb1b10abSAndroid Build Coastguard Worker       oxcf->rc_mode = (enum vpx_rc_mode)rc_mode;
781*fb1b10abSAndroid Build Coastguard Worker       ret = 1;
782*fb1b10abSAndroid Build Coastguard Worker     } else {
783*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "Invalid rc_mode value: %d\n", rc_mode);
784*fb1b10abSAndroid Build Coastguard Worker     }
785*fb1b10abSAndroid Build Coastguard Worker   }
786*fb1b10abSAndroid Build Coastguard Worker   SET_STRUCT_VALUE(config, oxcf, ret, cq_level);
787*fb1b10abSAndroid Build Coastguard Worker   if (ret == 0) {
788*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "Ignored unsupported encode_config %s\n", config.name);
789*fb1b10abSAndroid Build Coastguard Worker   }
790*fb1b10abSAndroid Build Coastguard Worker }
791*fb1b10abSAndroid Build Coastguard Worker 
GetEncodeConfig(int frame_width,int frame_height,vpx_rational_t frame_rate,int target_bitrate,int encode_speed,int target_level,vpx_enc_pass enc_pass,const std::vector<EncodeConfig> & encode_config_list)792*fb1b10abSAndroid Build Coastguard Worker static VP9EncoderConfig GetEncodeConfig(
793*fb1b10abSAndroid Build Coastguard Worker     int frame_width, int frame_height, vpx_rational_t frame_rate,
794*fb1b10abSAndroid Build Coastguard Worker     int target_bitrate, int encode_speed, int target_level,
795*fb1b10abSAndroid Build Coastguard Worker     vpx_enc_pass enc_pass,
796*fb1b10abSAndroid Build Coastguard Worker     const std::vector<EncodeConfig> &encode_config_list) {
797*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig oxcf = vp9_get_encoder_config(
798*fb1b10abSAndroid Build Coastguard Worker       frame_width, frame_height, frame_rate, target_bitrate, encode_speed,
799*fb1b10abSAndroid Build Coastguard Worker       target_level, enc_pass);
800*fb1b10abSAndroid Build Coastguard Worker   for (const auto &config : encode_config_list) {
801*fb1b10abSAndroid Build Coastguard Worker     UpdateEncodeConfig(config, &oxcf);
802*fb1b10abSAndroid Build Coastguard Worker   }
803*fb1b10abSAndroid Build Coastguard Worker   if (enc_pass == VPX_RC_FIRST_PASS) {
804*fb1b10abSAndroid Build Coastguard Worker     oxcf.lag_in_frames = 0;
805*fb1b10abSAndroid Build Coastguard Worker   }
806*fb1b10abSAndroid Build Coastguard Worker   oxcf.use_simple_encode_api = 1;
807*fb1b10abSAndroid Build Coastguard Worker   return oxcf;
808*fb1b10abSAndroid Build Coastguard Worker }
809*fb1b10abSAndroid Build Coastguard Worker 
SimpleEncode(int frame_width,int frame_height,int frame_rate_num,int frame_rate_den,int target_bitrate,int num_frames,int target_level,const char * infile_path,const char * outfile_path)810*fb1b10abSAndroid Build Coastguard Worker SimpleEncode::SimpleEncode(int frame_width, int frame_height,
811*fb1b10abSAndroid Build Coastguard Worker                            int frame_rate_num, int frame_rate_den,
812*fb1b10abSAndroid Build Coastguard Worker                            int target_bitrate, int num_frames, int target_level,
813*fb1b10abSAndroid Build Coastguard Worker                            const char *infile_path, const char *outfile_path) {
814*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_ = std::unique_ptr<EncodeImpl>(new EncodeImpl());
815*fb1b10abSAndroid Build Coastguard Worker   frame_width_ = frame_width;
816*fb1b10abSAndroid Build Coastguard Worker   frame_height_ = frame_height;
817*fb1b10abSAndroid Build Coastguard Worker   frame_rate_num_ = frame_rate_num;
818*fb1b10abSAndroid Build Coastguard Worker   frame_rate_den_ = frame_rate_den;
819*fb1b10abSAndroid Build Coastguard Worker   target_bitrate_ = target_bitrate;
820*fb1b10abSAndroid Build Coastguard Worker   num_frames_ = num_frames;
821*fb1b10abSAndroid Build Coastguard Worker   encode_speed_ = 0;
822*fb1b10abSAndroid Build Coastguard Worker   target_level_ = target_level;
823*fb1b10abSAndroid Build Coastguard Worker 
824*fb1b10abSAndroid Build Coastguard Worker   frame_coding_index_ = 0;
825*fb1b10abSAndroid Build Coastguard Worker   show_frame_count_ = 0;
826*fb1b10abSAndroid Build Coastguard Worker 
827*fb1b10abSAndroid Build Coastguard Worker   key_frame_group_index_ = 0;
828*fb1b10abSAndroid Build Coastguard Worker   key_frame_group_size_ = 0;
829*fb1b10abSAndroid Build Coastguard Worker 
830*fb1b10abSAndroid Build Coastguard Worker   // TODO(angirbid): Should we keep a file pointer here or keep the file_path?
831*fb1b10abSAndroid Build Coastguard Worker   assert(infile_path != nullptr);
832*fb1b10abSAndroid Build Coastguard Worker   in_file_ = fopen(infile_path, "r");
833*fb1b10abSAndroid Build Coastguard Worker   if (outfile_path != nullptr) {
834*fb1b10abSAndroid Build Coastguard Worker     out_file_ = fopen(outfile_path, "w");
835*fb1b10abSAndroid Build Coastguard Worker   } else {
836*fb1b10abSAndroid Build Coastguard Worker     out_file_ = nullptr;
837*fb1b10abSAndroid Build Coastguard Worker   }
838*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->cpi = nullptr;
839*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->img_fmt = VPX_IMG_FMT_I420;
840*fb1b10abSAndroid Build Coastguard Worker 
841*fb1b10abSAndroid Build Coastguard Worker   InitRefFrameInfo(&ref_frame_info_);
842*fb1b10abSAndroid Build Coastguard Worker }
843*fb1b10abSAndroid Build Coastguard Worker 
SetEncodeSpeed(int encode_speed)844*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::SetEncodeSpeed(int encode_speed) {
845*fb1b10abSAndroid Build Coastguard Worker   encode_speed_ = encode_speed;
846*fb1b10abSAndroid Build Coastguard Worker }
847*fb1b10abSAndroid Build Coastguard Worker 
SetEncodeConfig(const char * name,const char * value)848*fb1b10abSAndroid Build Coastguard Worker StatusCode SimpleEncode::SetEncodeConfig(const char *name, const char *value) {
849*fb1b10abSAndroid Build Coastguard Worker   if (name == nullptr || value == nullptr) {
850*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "SetEncodeConfig: null pointer, name %p value %p\n", name,
851*fb1b10abSAndroid Build Coastguard Worker             value);
852*fb1b10abSAndroid Build Coastguard Worker     return StatusError;
853*fb1b10abSAndroid Build Coastguard Worker   }
854*fb1b10abSAndroid Build Coastguard Worker   EncodeConfig config;
855*fb1b10abSAndroid Build Coastguard Worker   snprintf(config.name, ENCODE_CONFIG_BUF_SIZE, "%s", name);
856*fb1b10abSAndroid Build Coastguard Worker   snprintf(config.value, ENCODE_CONFIG_BUF_SIZE, "%s", value);
857*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->encode_config_list.push_back(config);
858*fb1b10abSAndroid Build Coastguard Worker   return StatusOk;
859*fb1b10abSAndroid Build Coastguard Worker }
860*fb1b10abSAndroid Build Coastguard Worker 
DumpEncodeConfigs(int pass,FILE * fp)861*fb1b10abSAndroid Build Coastguard Worker StatusCode SimpleEncode::DumpEncodeConfigs(int pass, FILE *fp) {
862*fb1b10abSAndroid Build Coastguard Worker   if (fp == nullptr) {
863*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "DumpEncodeConfigs: null pointer, fp %p\n", fp);
864*fb1b10abSAndroid Build Coastguard Worker     return StatusError;
865*fb1b10abSAndroid Build Coastguard Worker   }
866*fb1b10abSAndroid Build Coastguard Worker   vpx_enc_pass enc_pass;
867*fb1b10abSAndroid Build Coastguard Worker   if (pass == 1) {
868*fb1b10abSAndroid Build Coastguard Worker     enc_pass = VPX_RC_FIRST_PASS;
869*fb1b10abSAndroid Build Coastguard Worker   } else {
870*fb1b10abSAndroid Build Coastguard Worker     enc_pass = VPX_RC_LAST_PASS;
871*fb1b10abSAndroid Build Coastguard Worker   }
872*fb1b10abSAndroid Build Coastguard Worker   const vpx_rational_t frame_rate =
873*fb1b10abSAndroid Build Coastguard Worker       make_vpx_rational(frame_rate_num_, frame_rate_den_);
874*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig oxcf = GetEncodeConfig(
875*fb1b10abSAndroid Build Coastguard Worker       frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
876*fb1b10abSAndroid Build Coastguard Worker       target_level_, enc_pass, impl_ptr_->encode_config_list);
877*fb1b10abSAndroid Build Coastguard Worker   vp9_dump_encoder_config(&oxcf, fp);
878*fb1b10abSAndroid Build Coastguard Worker   return StatusOk;
879*fb1b10abSAndroid Build Coastguard Worker }
880*fb1b10abSAndroid Build Coastguard Worker 
ComputeFirstPassStats()881*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::ComputeFirstPassStats() {
882*fb1b10abSAndroid Build Coastguard Worker   vpx_rational_t frame_rate =
883*fb1b10abSAndroid Build Coastguard Worker       make_vpx_rational(frame_rate_num_, frame_rate_den_);
884*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig oxcf = GetEncodeConfig(
885*fb1b10abSAndroid Build Coastguard Worker       frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
886*fb1b10abSAndroid Build Coastguard Worker       target_level_, VPX_RC_FIRST_PASS, impl_ptr_->encode_config_list);
887*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->cpi = init_encoder(&oxcf, impl_ptr_->img_fmt);
888*fb1b10abSAndroid Build Coastguard Worker   struct lookahead_ctx *lookahead = impl_ptr_->cpi->lookahead;
889*fb1b10abSAndroid Build Coastguard Worker   int i;
890*fb1b10abSAndroid Build Coastguard Worker   int use_highbitdepth = 0;
891*fb1b10abSAndroid Build Coastguard Worker   const int num_rows_16x16 = get_num_unit_16x16(frame_height_);
892*fb1b10abSAndroid Build Coastguard Worker   const int num_cols_16x16 = get_num_unit_16x16(frame_width_);
893*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
894*fb1b10abSAndroid Build Coastguard Worker   use_highbitdepth = impl_ptr_->cpi->common.use_highbitdepth;
895*fb1b10abSAndroid Build Coastguard Worker #endif
896*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t img;
897*fb1b10abSAndroid Build Coastguard Worker   if (impl_ptr_->img_fmt == VPX_IMG_FMT_NV12) {
898*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "VPX_IMG_FMT_NV12 is not supported\n");
899*fb1b10abSAndroid Build Coastguard Worker     abort();
900*fb1b10abSAndroid Build Coastguard Worker   }
901*fb1b10abSAndroid Build Coastguard Worker   vpx_img_alloc(&img, impl_ptr_->img_fmt, frame_width_, frame_height_, 1);
902*fb1b10abSAndroid Build Coastguard Worker   rewind(in_file_);
903*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->first_pass_stats.clear();
904*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < num_frames_; ++i) {
905*fb1b10abSAndroid Build Coastguard Worker     assert(!vp9_lookahead_full(lookahead));
906*fb1b10abSAndroid Build Coastguard Worker     if (img_read(&img, in_file_)) {
907*fb1b10abSAndroid Build Coastguard Worker       int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
908*fb1b10abSAndroid Build Coastguard Worker       int64_t ts_start =
909*fb1b10abSAndroid Build Coastguard Worker           timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx);
910*fb1b10abSAndroid Build Coastguard Worker       int64_t ts_end =
911*fb1b10abSAndroid Build Coastguard Worker           timebase_units_to_ticks(&oxcf.g_timebase_in_ts, next_show_idx + 1);
912*fb1b10abSAndroid Build Coastguard Worker       YV12_BUFFER_CONFIG sd;
913*fb1b10abSAndroid Build Coastguard Worker       image2yuvconfig(&img, &sd);
914*fb1b10abSAndroid Build Coastguard Worker       vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
915*fb1b10abSAndroid Build Coastguard Worker       {
916*fb1b10abSAndroid Build Coastguard Worker         int64_t time_stamp;
917*fb1b10abSAndroid Build Coastguard Worker         int64_t time_end;
918*fb1b10abSAndroid Build Coastguard Worker         int flush = 1;  // Makes vp9_get_compressed_data process a frame
919*fb1b10abSAndroid Build Coastguard Worker         size_t size;
920*fb1b10abSAndroid Build Coastguard Worker         unsigned int frame_flags = 0;
921*fb1b10abSAndroid Build Coastguard Worker         ENCODE_FRAME_RESULT encode_frame_info;
922*fb1b10abSAndroid Build Coastguard Worker         vp9_init_encode_frame_result(&encode_frame_info);
923*fb1b10abSAndroid Build Coastguard Worker         // TODO(angiebird): Call vp9_first_pass directly
924*fb1b10abSAndroid Build Coastguard Worker         vp9_get_compressed_data(impl_ptr_->cpi, &frame_flags, &size, nullptr, 0,
925*fb1b10abSAndroid Build Coastguard Worker                                 &time_stamp, &time_end, flush,
926*fb1b10abSAndroid Build Coastguard Worker                                 &encode_frame_info);
927*fb1b10abSAndroid Build Coastguard Worker         // vp9_get_compressed_data only generates first pass stats not
928*fb1b10abSAndroid Build Coastguard Worker         // compresses data
929*fb1b10abSAndroid Build Coastguard Worker         assert(size == 0);
930*fb1b10abSAndroid Build Coastguard Worker         // Get vp9 first pass motion vector info.
931*fb1b10abSAndroid Build Coastguard Worker         std::vector<MotionVectorInfo> mv_info(num_rows_16x16 * num_cols_16x16);
932*fb1b10abSAndroid Build Coastguard Worker         update_motion_vector_info(
933*fb1b10abSAndroid Build Coastguard Worker             impl_ptr_->cpi->fp_motion_vector_info, num_rows_16x16,
934*fb1b10abSAndroid Build Coastguard Worker             num_cols_16x16, mv_info.data(), kMotionVectorFullPixelPrecision);
935*fb1b10abSAndroid Build Coastguard Worker         fp_motion_vector_info_.push_back(mv_info);
936*fb1b10abSAndroid Build Coastguard Worker       }
937*fb1b10abSAndroid Build Coastguard Worker       impl_ptr_->first_pass_stats.push_back(
938*fb1b10abSAndroid Build Coastguard Worker           vp9_get_frame_stats(&impl_ptr_->cpi->twopass));
939*fb1b10abSAndroid Build Coastguard Worker     }
940*fb1b10abSAndroid Build Coastguard Worker   }
941*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): Store the total_stats apart form first_pass_stats
942*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->first_pass_stats.push_back(
943*fb1b10abSAndroid Build Coastguard Worker       vp9_get_total_stats(&impl_ptr_->cpi->twopass));
944*fb1b10abSAndroid Build Coastguard Worker   vp9_end_first_pass(impl_ptr_->cpi);
945*fb1b10abSAndroid Build Coastguard Worker 
946*fb1b10abSAndroid Build Coastguard Worker   // Generate key_frame_map based on impl_ptr_->first_pass_stats.
947*fb1b10abSAndroid Build Coastguard Worker   key_frame_map_ = ComputeKeyFrameMap();
948*fb1b10abSAndroid Build Coastguard Worker 
949*fb1b10abSAndroid Build Coastguard Worker   free_encoder(impl_ptr_->cpi);
950*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->cpi = nullptr;
951*fb1b10abSAndroid Build Coastguard Worker   rewind(in_file_);
952*fb1b10abSAndroid Build Coastguard Worker   vpx_img_free(&img);
953*fb1b10abSAndroid Build Coastguard Worker }
954*fb1b10abSAndroid Build Coastguard Worker 
ObserveFirstPassStats()955*fb1b10abSAndroid Build Coastguard Worker std::vector<std::vector<double>> SimpleEncode::ObserveFirstPassStats() {
956*fb1b10abSAndroid Build Coastguard Worker   std::vector<std::vector<double>> output_stats;
957*fb1b10abSAndroid Build Coastguard Worker   // TODO(angiebird): This function make several assumptions of
958*fb1b10abSAndroid Build Coastguard Worker   // FIRSTPASS_STATS. 1) All elements in FIRSTPASS_STATS are double except the
959*fb1b10abSAndroid Build Coastguard Worker   // last one. 2) The last entry of first_pass_stats is the total_stats.
960*fb1b10abSAndroid Build Coastguard Worker   // Change the code structure, so that we don't have to make these assumptions
961*fb1b10abSAndroid Build Coastguard Worker 
962*fb1b10abSAndroid Build Coastguard Worker   // Note the last entry of first_pass_stats is the total_stats, we don't need
963*fb1b10abSAndroid Build Coastguard Worker   // it.
964*fb1b10abSAndroid Build Coastguard Worker   for (size_t i = 0; i < impl_ptr_->first_pass_stats.size() - 1; ++i) {
965*fb1b10abSAndroid Build Coastguard Worker     double *buf_start =
966*fb1b10abSAndroid Build Coastguard Worker         reinterpret_cast<double *>(&impl_ptr_->first_pass_stats[i]);
967*fb1b10abSAndroid Build Coastguard Worker     // We use - 1 here because the last member in FIRSTPASS_STATS is not double
968*fb1b10abSAndroid Build Coastguard Worker     double *buf_end =
969*fb1b10abSAndroid Build Coastguard Worker         buf_start + sizeof(impl_ptr_->first_pass_stats[i]) / sizeof(*buf_end) -
970*fb1b10abSAndroid Build Coastguard Worker         1;
971*fb1b10abSAndroid Build Coastguard Worker     std::vector<double> this_stats(buf_start, buf_end);
972*fb1b10abSAndroid Build Coastguard Worker     output_stats.push_back(this_stats);
973*fb1b10abSAndroid Build Coastguard Worker   }
974*fb1b10abSAndroid Build Coastguard Worker   return output_stats;
975*fb1b10abSAndroid Build Coastguard Worker }
976*fb1b10abSAndroid Build Coastguard Worker 
977*fb1b10abSAndroid Build Coastguard Worker std::vector<std::vector<MotionVectorInfo>>
ObserveFirstPassMotionVectors()978*fb1b10abSAndroid Build Coastguard Worker SimpleEncode::ObserveFirstPassMotionVectors() {
979*fb1b10abSAndroid Build Coastguard Worker   return fp_motion_vector_info_;
980*fb1b10abSAndroid Build Coastguard Worker }
981*fb1b10abSAndroid Build Coastguard Worker 
SetExternalGroupOfPicturesMap(int * gop_map,int gop_map_size)982*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::SetExternalGroupOfPicturesMap(int *gop_map,
983*fb1b10abSAndroid Build Coastguard Worker                                                  int gop_map_size) {
984*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; i < gop_map_size; ++i) {
985*fb1b10abSAndroid Build Coastguard Worker     gop_map_.push_back(gop_map[i]);
986*fb1b10abSAndroid Build Coastguard Worker   }
987*fb1b10abSAndroid Build Coastguard Worker   // The following will check and modify gop_map_ to make sure the
988*fb1b10abSAndroid Build Coastguard Worker   // gop_map_ satisfies the constraints.
989*fb1b10abSAndroid Build Coastguard Worker   // 1) Each key frame position should be at the start of a gop.
990*fb1b10abSAndroid Build Coastguard Worker   // 2) The last gop should not use an alt ref.
991*fb1b10abSAndroid Build Coastguard Worker   assert(gop_map_.size() == key_frame_map_.size());
992*fb1b10abSAndroid Build Coastguard Worker   int last_gop_start = 0;
993*fb1b10abSAndroid Build Coastguard Worker   for (int i = 0; static_cast<size_t>(i) < gop_map_.size(); ++i) {
994*fb1b10abSAndroid Build Coastguard Worker     if (key_frame_map_[i] == 1 && gop_map_[i] == 0) {
995*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "Add an extra gop start at show_idx %d\n", i);
996*fb1b10abSAndroid Build Coastguard Worker       // Insert a gop start at key frame location.
997*fb1b10abSAndroid Build Coastguard Worker       gop_map_[i] |= kGopMapFlagStart;
998*fb1b10abSAndroid Build Coastguard Worker       gop_map_[i] |= kGopMapFlagUseAltRef;
999*fb1b10abSAndroid Build Coastguard Worker     }
1000*fb1b10abSAndroid Build Coastguard Worker     if (gop_map_[i] & kGopMapFlagStart) {
1001*fb1b10abSAndroid Build Coastguard Worker       last_gop_start = i;
1002*fb1b10abSAndroid Build Coastguard Worker     }
1003*fb1b10abSAndroid Build Coastguard Worker   }
1004*fb1b10abSAndroid Build Coastguard Worker   if (gop_map_[last_gop_start] & kGopMapFlagUseAltRef) {
1005*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr,
1006*fb1b10abSAndroid Build Coastguard Worker             "Last group of pictures starting at show_idx %d shouldn't use alt "
1007*fb1b10abSAndroid Build Coastguard Worker             "ref\n",
1008*fb1b10abSAndroid Build Coastguard Worker             last_gop_start);
1009*fb1b10abSAndroid Build Coastguard Worker     gop_map_[last_gop_start] &= ~kGopMapFlagUseAltRef;
1010*fb1b10abSAndroid Build Coastguard Worker   }
1011*fb1b10abSAndroid Build Coastguard Worker }
1012*fb1b10abSAndroid Build Coastguard Worker 
ObserveExternalGroupOfPicturesMap()1013*fb1b10abSAndroid Build Coastguard Worker std::vector<int> SimpleEncode::ObserveExternalGroupOfPicturesMap() {
1014*fb1b10abSAndroid Build Coastguard Worker   return gop_map_;
1015*fb1b10abSAndroid Build Coastguard Worker }
1016*fb1b10abSAndroid Build Coastguard Worker 
1017*fb1b10abSAndroid Build Coastguard Worker template <typename T>
GetVectorData(const std::vector<T> & v)1018*fb1b10abSAndroid Build Coastguard Worker T *GetVectorData(const std::vector<T> &v) {
1019*fb1b10abSAndroid Build Coastguard Worker   if (v.empty()) {
1020*fb1b10abSAndroid Build Coastguard Worker     return nullptr;
1021*fb1b10abSAndroid Build Coastguard Worker   }
1022*fb1b10abSAndroid Build Coastguard Worker   return const_cast<T *>(v.data());
1023*fb1b10abSAndroid Build Coastguard Worker }
1024*fb1b10abSAndroid Build Coastguard Worker 
GetGopCommand(const std::vector<int> & gop_map,int start_show_index)1025*fb1b10abSAndroid Build Coastguard Worker static GOP_COMMAND GetGopCommand(const std::vector<int> &gop_map,
1026*fb1b10abSAndroid Build Coastguard Worker                                  int start_show_index) {
1027*fb1b10abSAndroid Build Coastguard Worker   GOP_COMMAND gop_command;
1028*fb1b10abSAndroid Build Coastguard Worker   if (static_cast<size_t>(start_show_index) < gop_map.size()) {
1029*fb1b10abSAndroid Build Coastguard Worker     assert((gop_map[start_show_index] & kGopMapFlagStart) != 0);
1030*fb1b10abSAndroid Build Coastguard Worker     int end_show_index = start_show_index + 1;
1031*fb1b10abSAndroid Build Coastguard Worker     // gop_map[end_show_index] & kGopMapFlagStart == 0 means this is
1032*fb1b10abSAndroid Build Coastguard Worker     // the start of a gop.
1033*fb1b10abSAndroid Build Coastguard Worker     while (static_cast<size_t>(end_show_index) < gop_map.size() &&
1034*fb1b10abSAndroid Build Coastguard Worker            (gop_map[end_show_index] & kGopMapFlagStart) == 0) {
1035*fb1b10abSAndroid Build Coastguard Worker       ++end_show_index;
1036*fb1b10abSAndroid Build Coastguard Worker     }
1037*fb1b10abSAndroid Build Coastguard Worker     const int show_frame_count = end_show_index - start_show_index;
1038*fb1b10abSAndroid Build Coastguard Worker     int use_alt_ref = (gop_map[start_show_index] & kGopMapFlagUseAltRef) != 0;
1039*fb1b10abSAndroid Build Coastguard Worker     if (static_cast<size_t>(end_show_index) == gop_map.size()) {
1040*fb1b10abSAndroid Build Coastguard Worker       // This is the last gop group, there must be no altref.
1041*fb1b10abSAndroid Build Coastguard Worker       use_alt_ref = 0;
1042*fb1b10abSAndroid Build Coastguard Worker     }
1043*fb1b10abSAndroid Build Coastguard Worker     gop_command_on(&gop_command, show_frame_count, use_alt_ref);
1044*fb1b10abSAndroid Build Coastguard Worker   } else {
1045*fb1b10abSAndroid Build Coastguard Worker     gop_command_off(&gop_command);
1046*fb1b10abSAndroid Build Coastguard Worker   }
1047*fb1b10abSAndroid Build Coastguard Worker   return gop_command;
1048*fb1b10abSAndroid Build Coastguard Worker }
1049*fb1b10abSAndroid Build Coastguard Worker 
StartEncode()1050*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::StartEncode() {
1051*fb1b10abSAndroid Build Coastguard Worker   assert(impl_ptr_->first_pass_stats.size() > 0);
1052*fb1b10abSAndroid Build Coastguard Worker   vpx_rational_t frame_rate =
1053*fb1b10abSAndroid Build Coastguard Worker       make_vpx_rational(frame_rate_num_, frame_rate_den_);
1054*fb1b10abSAndroid Build Coastguard Worker   VP9EncoderConfig oxcf = GetEncodeConfig(
1055*fb1b10abSAndroid Build Coastguard Worker       frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
1056*fb1b10abSAndroid Build Coastguard Worker       target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
1057*fb1b10abSAndroid Build Coastguard Worker 
1058*fb1b10abSAndroid Build Coastguard Worker   vpx_fixed_buf_t stats;
1059*fb1b10abSAndroid Build Coastguard Worker   stats.buf = GetVectorData(impl_ptr_->first_pass_stats);
1060*fb1b10abSAndroid Build Coastguard Worker   stats.sz = sizeof(impl_ptr_->first_pass_stats[0]) *
1061*fb1b10abSAndroid Build Coastguard Worker              impl_ptr_->first_pass_stats.size();
1062*fb1b10abSAndroid Build Coastguard Worker 
1063*fb1b10abSAndroid Build Coastguard Worker   vp9_set_first_pass_stats(&oxcf, &stats);
1064*fb1b10abSAndroid Build Coastguard Worker   assert(impl_ptr_->cpi == nullptr);
1065*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->cpi = init_encoder(&oxcf, impl_ptr_->img_fmt);
1066*fb1b10abSAndroid Build Coastguard Worker   if (impl_ptr_->img_fmt == VPX_IMG_FMT_NV12) {
1067*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "VPX_IMG_FMT_NV12 is not supported\n");
1068*fb1b10abSAndroid Build Coastguard Worker     abort();
1069*fb1b10abSAndroid Build Coastguard Worker   }
1070*fb1b10abSAndroid Build Coastguard Worker   vpx_img_alloc(&impl_ptr_->tmp_img, impl_ptr_->img_fmt, frame_width_,
1071*fb1b10abSAndroid Build Coastguard Worker                 frame_height_, 1);
1072*fb1b10abSAndroid Build Coastguard Worker 
1073*fb1b10abSAndroid Build Coastguard Worker   frame_coding_index_ = 0;
1074*fb1b10abSAndroid Build Coastguard Worker   show_frame_count_ = 0;
1075*fb1b10abSAndroid Build Coastguard Worker 
1076*fb1b10abSAndroid Build Coastguard Worker   assert(impl_ptr_->cpi != nullptr);
1077*fb1b10abSAndroid Build Coastguard Worker   FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
1078*fb1b10abSAndroid Build Coastguard Worker   unsigned int screen_area = frame_info.frame_width * frame_info.frame_height;
1079*fb1b10abSAndroid Build Coastguard Worker   vp9_init_vizier_params(&impl_ptr_->cpi->twopass, screen_area);
1080*fb1b10abSAndroid Build Coastguard Worker 
1081*fb1b10abSAndroid Build Coastguard Worker   UpdateKeyFrameGroup(show_frame_count_);
1082*fb1b10abSAndroid Build Coastguard Worker 
1083*fb1b10abSAndroid Build Coastguard Worker   const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_);
1084*fb1b10abSAndroid Build Coastguard Worker   encode_command_set_gop_command(&impl_ptr_->cpi->encode_command, gop_command);
1085*fb1b10abSAndroid Build Coastguard Worker   UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
1086*fb1b10abSAndroid Build Coastguard Worker                        &group_of_picture_);
1087*fb1b10abSAndroid Build Coastguard Worker   rewind(in_file_);
1088*fb1b10abSAndroid Build Coastguard Worker 
1089*fb1b10abSAndroid Build Coastguard Worker   if (out_file_ != nullptr) {
1090*fb1b10abSAndroid Build Coastguard Worker     const char *fourcc = "VP90";
1091*fb1b10abSAndroid Build Coastguard Worker     // In SimpleEncode, we use time_base = 1 / TICKS_PER_SEC.
1092*fb1b10abSAndroid Build Coastguard Worker     // Based on that, the ivf_timestamp for each image is set to
1093*fb1b10abSAndroid Build Coastguard Worker     // show_idx * TICKS_PER_SEC / frame_rate
1094*fb1b10abSAndroid Build Coastguard Worker     // such that each image's actual timestamp in seconds can be computed as
1095*fb1b10abSAndroid Build Coastguard Worker     // ivf_timestamp * time_base == show_idx / frame_rate
1096*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): 1) Add unit test for ivf timestamp.
1097*fb1b10abSAndroid Build Coastguard Worker     // 2) Simplify the frame_rate setting process.
1098*fb1b10abSAndroid Build Coastguard Worker     vpx_rational_t time_base = make_vpx_rational(1, TICKS_PER_SEC);
1099*fb1b10abSAndroid Build Coastguard Worker     ivf_write_file_header_with_video_info(out_file_, *(const uint32_t *)fourcc,
1100*fb1b10abSAndroid Build Coastguard Worker                                           num_frames_, frame_width_,
1101*fb1b10abSAndroid Build Coastguard Worker                                           frame_height_, time_base);
1102*fb1b10abSAndroid Build Coastguard Worker   }
1103*fb1b10abSAndroid Build Coastguard Worker }
1104*fb1b10abSAndroid Build Coastguard Worker 
EndEncode()1105*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::EndEncode() {
1106*fb1b10abSAndroid Build Coastguard Worker   free_encoder(impl_ptr_->cpi);
1107*fb1b10abSAndroid Build Coastguard Worker   impl_ptr_->cpi = nullptr;
1108*fb1b10abSAndroid Build Coastguard Worker   vpx_img_free(&impl_ptr_->tmp_img);
1109*fb1b10abSAndroid Build Coastguard Worker   rewind(in_file_);
1110*fb1b10abSAndroid Build Coastguard Worker }
1111*fb1b10abSAndroid Build Coastguard Worker 
UpdateKeyFrameGroup(int key_frame_show_index)1112*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::UpdateKeyFrameGroup(int key_frame_show_index) {
1113*fb1b10abSAndroid Build Coastguard Worker   const VP9_COMP *cpi = impl_ptr_->cpi;
1114*fb1b10abSAndroid Build Coastguard Worker   key_frame_group_index_ = 0;
1115*fb1b10abSAndroid Build Coastguard Worker   key_frame_group_size_ = vp9_get_frames_to_next_key(
1116*fb1b10abSAndroid Build Coastguard Worker       &cpi->oxcf, &cpi->twopass, key_frame_show_index, cpi->rc.min_gf_interval);
1117*fb1b10abSAndroid Build Coastguard Worker   assert(key_frame_group_size_ > 0);
1118*fb1b10abSAndroid Build Coastguard Worker   // Init the reference frame info when a new key frame group appears.
1119*fb1b10abSAndroid Build Coastguard Worker   InitRefFrameInfo(&ref_frame_info_);
1120*fb1b10abSAndroid Build Coastguard Worker }
1121*fb1b10abSAndroid Build Coastguard Worker 
PostUpdateKeyFrameGroupIndex(FrameType frame_type)1122*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::PostUpdateKeyFrameGroupIndex(FrameType frame_type) {
1123*fb1b10abSAndroid Build Coastguard Worker   if (frame_type != kFrameTypeAltRef) {
1124*fb1b10abSAndroid Build Coastguard Worker     // key_frame_group_index_ only counts show frames
1125*fb1b10abSAndroid Build Coastguard Worker     ++key_frame_group_index_;
1126*fb1b10abSAndroid Build Coastguard Worker   }
1127*fb1b10abSAndroid Build Coastguard Worker }
1128*fb1b10abSAndroid Build Coastguard Worker 
GetKeyFrameGroupSize() const1129*fb1b10abSAndroid Build Coastguard Worker int SimpleEncode::GetKeyFrameGroupSize() const { return key_frame_group_size_; }
1130*fb1b10abSAndroid Build Coastguard Worker 
ObserveGroupOfPicture() const1131*fb1b10abSAndroid Build Coastguard Worker GroupOfPicture SimpleEncode::ObserveGroupOfPicture() const {
1132*fb1b10abSAndroid Build Coastguard Worker   return group_of_picture_;
1133*fb1b10abSAndroid Build Coastguard Worker }
1134*fb1b10abSAndroid Build Coastguard Worker 
GetNextEncodeFrameInfo() const1135*fb1b10abSAndroid Build Coastguard Worker EncodeFrameInfo SimpleEncode::GetNextEncodeFrameInfo() const {
1136*fb1b10abSAndroid Build Coastguard Worker   return group_of_picture_
1137*fb1b10abSAndroid Build Coastguard Worker       .encode_frame_list[group_of_picture_.next_encode_frame_index];
1138*fb1b10abSAndroid Build Coastguard Worker }
1139*fb1b10abSAndroid Build Coastguard Worker 
PostUpdateState(const EncodeFrameResult & encode_frame_result)1140*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::PostUpdateState(
1141*fb1b10abSAndroid Build Coastguard Worker     const EncodeFrameResult &encode_frame_result) {
1142*fb1b10abSAndroid Build Coastguard Worker   // This function needs to be called before the increament of
1143*fb1b10abSAndroid Build Coastguard Worker   // frame_coding_index_
1144*fb1b10abSAndroid Build Coastguard Worker   PostUpdateRefFrameInfo(encode_frame_result.frame_type, frame_coding_index_,
1145*fb1b10abSAndroid Build Coastguard Worker                          &ref_frame_info_);
1146*fb1b10abSAndroid Build Coastguard Worker   ++frame_coding_index_;
1147*fb1b10abSAndroid Build Coastguard Worker   if (encode_frame_result.frame_type != kFrameTypeAltRef) {
1148*fb1b10abSAndroid Build Coastguard Worker     // Only kFrameTypeAltRef is not a show frame
1149*fb1b10abSAndroid Build Coastguard Worker     ++show_frame_count_;
1150*fb1b10abSAndroid Build Coastguard Worker   }
1151*fb1b10abSAndroid Build Coastguard Worker 
1152*fb1b10abSAndroid Build Coastguard Worker   PostUpdateKeyFrameGroupIndex(encode_frame_result.frame_type);
1153*fb1b10abSAndroid Build Coastguard Worker   if (key_frame_group_index_ == key_frame_group_size_) {
1154*fb1b10abSAndroid Build Coastguard Worker     UpdateKeyFrameGroup(show_frame_count_);
1155*fb1b10abSAndroid Build Coastguard Worker   }
1156*fb1b10abSAndroid Build Coastguard Worker 
1157*fb1b10abSAndroid Build Coastguard Worker   IncreaseGroupOfPictureIndex(&group_of_picture_);
1158*fb1b10abSAndroid Build Coastguard Worker   if (IsGroupOfPictureFinished(group_of_picture_)) {
1159*fb1b10abSAndroid Build Coastguard Worker     const GOP_COMMAND gop_command = GetGopCommand(gop_map_, show_frame_count_);
1160*fb1b10abSAndroid Build Coastguard Worker     encode_command_set_gop_command(&impl_ptr_->cpi->encode_command,
1161*fb1b10abSAndroid Build Coastguard Worker                                    gop_command);
1162*fb1b10abSAndroid Build Coastguard Worker     // This function needs to be called after ref_frame_info_ is updated
1163*fb1b10abSAndroid Build Coastguard Worker     // properly in PostUpdateRefFrameInfo() and UpdateKeyFrameGroup().
1164*fb1b10abSAndroid Build Coastguard Worker     UpdateGroupOfPicture(impl_ptr_->cpi, frame_coding_index_, ref_frame_info_,
1165*fb1b10abSAndroid Build Coastguard Worker                          &group_of_picture_);
1166*fb1b10abSAndroid Build Coastguard Worker   }
1167*fb1b10abSAndroid Build Coastguard Worker }
1168*fb1b10abSAndroid Build Coastguard Worker 
EncodeFrame(EncodeFrameResult * encode_frame_result)1169*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
1170*fb1b10abSAndroid Build Coastguard Worker   VP9_COMP *cpi = impl_ptr_->cpi;
1171*fb1b10abSAndroid Build Coastguard Worker   struct lookahead_ctx *lookahead = cpi->lookahead;
1172*fb1b10abSAndroid Build Coastguard Worker   int use_highbitdepth = 0;
1173*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
1174*fb1b10abSAndroid Build Coastguard Worker   use_highbitdepth = cpi->common.use_highbitdepth;
1175*fb1b10abSAndroid Build Coastguard Worker #endif
1176*fb1b10abSAndroid Build Coastguard Worker   // The lookahead's size is set to oxcf->lag_in_frames.
1177*fb1b10abSAndroid Build Coastguard Worker   // We want to fill lookahead to it's max capacity if possible so that the
1178*fb1b10abSAndroid Build Coastguard Worker   // encoder can construct alt ref frame in time.
1179*fb1b10abSAndroid Build Coastguard Worker   // In the other words, we hope vp9_get_compressed_data to encode a frame
1180*fb1b10abSAndroid Build Coastguard Worker   // every time in the function
1181*fb1b10abSAndroid Build Coastguard Worker   while (!vp9_lookahead_full(lookahead)) {
1182*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): Check whether we can move this file read logics to
1183*fb1b10abSAndroid Build Coastguard Worker     // lookahead
1184*fb1b10abSAndroid Build Coastguard Worker     if (img_read(&impl_ptr_->tmp_img, in_file_)) {
1185*fb1b10abSAndroid Build Coastguard Worker       int next_show_idx = vp9_lookahead_next_show_idx(lookahead);
1186*fb1b10abSAndroid Build Coastguard Worker       int64_t ts_start =
1187*fb1b10abSAndroid Build Coastguard Worker           timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts, next_show_idx);
1188*fb1b10abSAndroid Build Coastguard Worker       int64_t ts_end = timebase_units_to_ticks(&cpi->oxcf.g_timebase_in_ts,
1189*fb1b10abSAndroid Build Coastguard Worker                                                next_show_idx + 1);
1190*fb1b10abSAndroid Build Coastguard Worker       YV12_BUFFER_CONFIG sd;
1191*fb1b10abSAndroid Build Coastguard Worker       image2yuvconfig(&impl_ptr_->tmp_img, &sd);
1192*fb1b10abSAndroid Build Coastguard Worker       vp9_lookahead_push(lookahead, &sd, ts_start, ts_end, use_highbitdepth, 0);
1193*fb1b10abSAndroid Build Coastguard Worker     } else {
1194*fb1b10abSAndroid Build Coastguard Worker       break;
1195*fb1b10abSAndroid Build Coastguard Worker     }
1196*fb1b10abSAndroid Build Coastguard Worker   }
1197*fb1b10abSAndroid Build Coastguard Worker 
1198*fb1b10abSAndroid Build Coastguard Worker   if (init_encode_frame_result(encode_frame_result, frame_width_, frame_height_,
1199*fb1b10abSAndroid Build Coastguard Worker                                impl_ptr_->img_fmt)) {
1200*fb1b10abSAndroid Build Coastguard Worker     int64_t time_stamp;
1201*fb1b10abSAndroid Build Coastguard Worker     int64_t time_end;
1202*fb1b10abSAndroid Build Coastguard Worker     int flush = 1;  // Make vp9_get_compressed_data encode a frame
1203*fb1b10abSAndroid Build Coastguard Worker     unsigned int frame_flags = 0;
1204*fb1b10abSAndroid Build Coastguard Worker     ENCODE_FRAME_RESULT encode_frame_info;
1205*fb1b10abSAndroid Build Coastguard Worker     vp9_init_encode_frame_result(&encode_frame_info);
1206*fb1b10abSAndroid Build Coastguard Worker     ImageBuffer_to_IMAGE_BUFFER(encode_frame_result->coded_frame,
1207*fb1b10abSAndroid Build Coastguard Worker                                 &encode_frame_info.coded_frame);
1208*fb1b10abSAndroid Build Coastguard Worker     vp9_get_compressed_data(cpi, &frame_flags,
1209*fb1b10abSAndroid Build Coastguard Worker                             &encode_frame_result->coding_data_byte_size,
1210*fb1b10abSAndroid Build Coastguard Worker                             encode_frame_result->coding_data.get(),
1211*fb1b10abSAndroid Build Coastguard Worker                             encode_frame_result->max_coding_data_byte_size,
1212*fb1b10abSAndroid Build Coastguard Worker                             &time_stamp, &time_end, flush, &encode_frame_info);
1213*fb1b10abSAndroid Build Coastguard Worker     if (out_file_ != nullptr) {
1214*fb1b10abSAndroid Build Coastguard Worker       ivf_write_frame_header(out_file_, time_stamp,
1215*fb1b10abSAndroid Build Coastguard Worker                              encode_frame_result->coding_data_byte_size);
1216*fb1b10abSAndroid Build Coastguard Worker       fwrite(encode_frame_result->coding_data.get(), 1,
1217*fb1b10abSAndroid Build Coastguard Worker              encode_frame_result->coding_data_byte_size, out_file_);
1218*fb1b10abSAndroid Build Coastguard Worker     }
1219*fb1b10abSAndroid Build Coastguard Worker 
1220*fb1b10abSAndroid Build Coastguard Worker     // vp9_get_compressed_data is expected to encode a frame every time, so the
1221*fb1b10abSAndroid Build Coastguard Worker     // data size should be greater than zero.
1222*fb1b10abSAndroid Build Coastguard Worker     if (encode_frame_result->coding_data_byte_size <= 0) {
1223*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "Coding data size <= 0\n");
1224*fb1b10abSAndroid Build Coastguard Worker       abort();
1225*fb1b10abSAndroid Build Coastguard Worker     }
1226*fb1b10abSAndroid Build Coastguard Worker     if (encode_frame_result->coding_data_byte_size >
1227*fb1b10abSAndroid Build Coastguard Worker         encode_frame_result->max_coding_data_byte_size) {
1228*fb1b10abSAndroid Build Coastguard Worker       fprintf(stderr, "Coding data size exceeds the maximum.\n");
1229*fb1b10abSAndroid Build Coastguard Worker       abort();
1230*fb1b10abSAndroid Build Coastguard Worker     }
1231*fb1b10abSAndroid Build Coastguard Worker 
1232*fb1b10abSAndroid Build Coastguard Worker     const GroupOfPicture group_of_picture = this->ObserveGroupOfPicture();
1233*fb1b10abSAndroid Build Coastguard Worker     const int show_frame_count = group_of_picture.show_frame_count;
1234*fb1b10abSAndroid Build Coastguard Worker     update_encode_frame_result(encode_frame_result, show_frame_count,
1235*fb1b10abSAndroid Build Coastguard Worker                                &encode_frame_info);
1236*fb1b10abSAndroid Build Coastguard Worker     PostUpdateState(*encode_frame_result);
1237*fb1b10abSAndroid Build Coastguard Worker   } else {
1238*fb1b10abSAndroid Build Coastguard Worker     // TODO(angiebird): Clean up encode_frame_result.
1239*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "init_encode_frame_result() failed.\n");
1240*fb1b10abSAndroid Build Coastguard Worker     this->EndEncode();
1241*fb1b10abSAndroid Build Coastguard Worker   }
1242*fb1b10abSAndroid Build Coastguard Worker }
1243*fb1b10abSAndroid Build Coastguard Worker 
EncodeFrameWithQuantizeIndex(EncodeFrameResult * encode_frame_result,int quantize_index)1244*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::EncodeFrameWithQuantizeIndex(
1245*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameResult *encode_frame_result, int quantize_index) {
1246*fb1b10abSAndroid Build Coastguard Worker   encode_command_set_external_quantize_index(&impl_ptr_->cpi->encode_command,
1247*fb1b10abSAndroid Build Coastguard Worker                                              quantize_index);
1248*fb1b10abSAndroid Build Coastguard Worker   EncodeFrame(encode_frame_result);
1249*fb1b10abSAndroid Build Coastguard Worker   encode_command_reset_external_quantize_index(&impl_ptr_->cpi->encode_command);
1250*fb1b10abSAndroid Build Coastguard Worker }
1251*fb1b10abSAndroid Build Coastguard Worker 
EncodeFrameWithTargetFrameBits(EncodeFrameResult * encode_frame_result,int target_frame_bits,double percent_diff)1252*fb1b10abSAndroid Build Coastguard Worker void SimpleEncode::EncodeFrameWithTargetFrameBits(
1253*fb1b10abSAndroid Build Coastguard Worker     EncodeFrameResult *encode_frame_result, int target_frame_bits,
1254*fb1b10abSAndroid Build Coastguard Worker     double percent_diff) {
1255*fb1b10abSAndroid Build Coastguard Worker   encode_command_set_target_frame_bits(&impl_ptr_->cpi->encode_command,
1256*fb1b10abSAndroid Build Coastguard Worker                                        target_frame_bits, percent_diff);
1257*fb1b10abSAndroid Build Coastguard Worker   EncodeFrame(encode_frame_result);
1258*fb1b10abSAndroid Build Coastguard Worker   encode_command_reset_target_frame_bits(&impl_ptr_->cpi->encode_command);
1259*fb1b10abSAndroid Build Coastguard Worker }
1260*fb1b10abSAndroid Build Coastguard Worker 
GetCodingFrameNumFromGopMap(const std::vector<int> & gop_map)1261*fb1b10abSAndroid Build Coastguard Worker static int GetCodingFrameNumFromGopMap(const std::vector<int> &gop_map) {
1262*fb1b10abSAndroid Build Coastguard Worker   int start_show_index = 0;
1263*fb1b10abSAndroid Build Coastguard Worker   int coding_frame_count = 0;
1264*fb1b10abSAndroid Build Coastguard Worker   while (static_cast<size_t>(start_show_index) < gop_map.size()) {
1265*fb1b10abSAndroid Build Coastguard Worker     const GOP_COMMAND gop_command = GetGopCommand(gop_map, start_show_index);
1266*fb1b10abSAndroid Build Coastguard Worker     start_show_index += gop_command.show_frame_count;
1267*fb1b10abSAndroid Build Coastguard Worker     coding_frame_count += gop_command_coding_frame_count(&gop_command);
1268*fb1b10abSAndroid Build Coastguard Worker   }
1269*fb1b10abSAndroid Build Coastguard Worker   assert(static_cast<size_t>(start_show_index) == gop_map.size());
1270*fb1b10abSAndroid Build Coastguard Worker   return coding_frame_count;
1271*fb1b10abSAndroid Build Coastguard Worker }
1272*fb1b10abSAndroid Build Coastguard Worker 
GetCodingFrameNum() const1273*fb1b10abSAndroid Build Coastguard Worker int SimpleEncode::GetCodingFrameNum() const {
1274*fb1b10abSAndroid Build Coastguard Worker   assert(impl_ptr_->first_pass_stats.size() > 0);
1275*fb1b10abSAndroid Build Coastguard Worker   if (gop_map_.size() > 0) {
1276*fb1b10abSAndroid Build Coastguard Worker     return GetCodingFrameNumFromGopMap(gop_map_);
1277*fb1b10abSAndroid Build Coastguard Worker   }
1278*fb1b10abSAndroid Build Coastguard Worker 
1279*fb1b10abSAndroid Build Coastguard Worker   // These are the default settings for now.
1280*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS twopass;
1281*fb1b10abSAndroid Build Coastguard Worker   const int multi_layer_arf = 0;
1282*fb1b10abSAndroid Build Coastguard Worker   const int allow_alt_ref = 1;
1283*fb1b10abSAndroid Build Coastguard Worker   vpx_rational_t frame_rate =
1284*fb1b10abSAndroid Build Coastguard Worker       make_vpx_rational(frame_rate_num_, frame_rate_den_);
1285*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig oxcf = GetEncodeConfig(
1286*fb1b10abSAndroid Build Coastguard Worker       frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
1287*fb1b10abSAndroid Build Coastguard Worker       target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
1288*fb1b10abSAndroid Build Coastguard Worker   FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
1289*fb1b10abSAndroid Build Coastguard Worker   fps_init_first_pass_info(&twopass.first_pass_info,
1290*fb1b10abSAndroid Build Coastguard Worker                            GetVectorData(impl_ptr_->first_pass_stats),
1291*fb1b10abSAndroid Build Coastguard Worker                            num_frames_);
1292*fb1b10abSAndroid Build Coastguard Worker   unsigned int screen_area = frame_info.frame_width * frame_info.frame_height;
1293*fb1b10abSAndroid Build Coastguard Worker   vp9_init_vizier_params(&twopass, screen_area);
1294*fb1b10abSAndroid Build Coastguard Worker   return vp9_get_coding_frame_num(&oxcf, &twopass, &frame_info, multi_layer_arf,
1295*fb1b10abSAndroid Build Coastguard Worker                                   allow_alt_ref);
1296*fb1b10abSAndroid Build Coastguard Worker }
1297*fb1b10abSAndroid Build Coastguard Worker 
ComputeKeyFrameMap() const1298*fb1b10abSAndroid Build Coastguard Worker std::vector<int> SimpleEncode::ComputeKeyFrameMap() const {
1299*fb1b10abSAndroid Build Coastguard Worker   // The last entry of first_pass_stats is the overall stats.
1300*fb1b10abSAndroid Build Coastguard Worker   assert(impl_ptr_->first_pass_stats.size() ==
1301*fb1b10abSAndroid Build Coastguard Worker          static_cast<size_t>(num_frames_) + 1);
1302*fb1b10abSAndroid Build Coastguard Worker   vpx_rational_t frame_rate =
1303*fb1b10abSAndroid Build Coastguard Worker       make_vpx_rational(frame_rate_num_, frame_rate_den_);
1304*fb1b10abSAndroid Build Coastguard Worker   const VP9EncoderConfig oxcf = GetEncodeConfig(
1305*fb1b10abSAndroid Build Coastguard Worker       frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
1306*fb1b10abSAndroid Build Coastguard Worker       target_level_, VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
1307*fb1b10abSAndroid Build Coastguard Worker   TWO_PASS twopass;
1308*fb1b10abSAndroid Build Coastguard Worker   fps_init_first_pass_info(&twopass.first_pass_info,
1309*fb1b10abSAndroid Build Coastguard Worker                            GetVectorData(impl_ptr_->first_pass_stats),
1310*fb1b10abSAndroid Build Coastguard Worker                            num_frames_);
1311*fb1b10abSAndroid Build Coastguard Worker   std::vector<int> key_frame_map(num_frames_, 0);
1312*fb1b10abSAndroid Build Coastguard Worker   vp9_get_key_frame_map(&oxcf, &twopass, GetVectorData(key_frame_map));
1313*fb1b10abSAndroid Build Coastguard Worker   return key_frame_map;
1314*fb1b10abSAndroid Build Coastguard Worker }
1315*fb1b10abSAndroid Build Coastguard Worker 
ObserveKeyFrameMap() const1316*fb1b10abSAndroid Build Coastguard Worker std::vector<int> SimpleEncode::ObserveKeyFrameMap() const {
1317*fb1b10abSAndroid Build Coastguard Worker   return key_frame_map_;
1318*fb1b10abSAndroid Build Coastguard Worker }
1319*fb1b10abSAndroid Build Coastguard Worker 
GetFramePixelCount() const1320*fb1b10abSAndroid Build Coastguard Worker uint64_t SimpleEncode::GetFramePixelCount() const {
1321*fb1b10abSAndroid Build Coastguard Worker   assert(frame_width_ % 2 == 0);
1322*fb1b10abSAndroid Build Coastguard Worker   assert(frame_height_ % 2 == 0);
1323*fb1b10abSAndroid Build Coastguard Worker   switch (impl_ptr_->img_fmt) {
1324*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I420: return frame_width_ * frame_height_ * 3 / 2;
1325*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I422: return frame_width_ * frame_height_ * 2;
1326*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I444: return frame_width_ * frame_height_ * 3;
1327*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I440: return frame_width_ * frame_height_ * 2;
1328*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I42016: return frame_width_ * frame_height_ * 3 / 2;
1329*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I42216: return frame_width_ * frame_height_ * 2;
1330*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I44416: return frame_width_ * frame_height_ * 3;
1331*fb1b10abSAndroid Build Coastguard Worker     case VPX_IMG_FMT_I44016: return frame_width_ * frame_height_ * 2;
1332*fb1b10abSAndroid Build Coastguard Worker     default: return 0;
1333*fb1b10abSAndroid Build Coastguard Worker   }
1334*fb1b10abSAndroid Build Coastguard Worker }
1335*fb1b10abSAndroid Build Coastguard Worker 
~SimpleEncode()1336*fb1b10abSAndroid Build Coastguard Worker SimpleEncode::~SimpleEncode() {
1337*fb1b10abSAndroid Build Coastguard Worker   if (in_file_ != nullptr) {
1338*fb1b10abSAndroid Build Coastguard Worker     fclose(in_file_);
1339*fb1b10abSAndroid Build Coastguard Worker   }
1340*fb1b10abSAndroid Build Coastguard Worker   if (out_file_ != nullptr) {
1341*fb1b10abSAndroid Build Coastguard Worker     fclose(out_file_);
1342*fb1b10abSAndroid Build Coastguard Worker   }
1343*fb1b10abSAndroid Build Coastguard Worker }
1344*fb1b10abSAndroid Build Coastguard Worker 
1345*fb1b10abSAndroid Build Coastguard Worker }  // namespace vp9
1346