xref: /aosp_15_r20/external/libvpx/examples/vp9_spatial_svc_encoder.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2012 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 /*
12*fb1b10abSAndroid Build Coastguard Worker  * This is an example demonstrating how to implement a multi-layer
13*fb1b10abSAndroid Build Coastguard Worker  * VP9 encoding scheme based on spatial scalability for video applications
14*fb1b10abSAndroid Build Coastguard Worker  * that benefit from a scalable bitstream.
15*fb1b10abSAndroid Build Coastguard Worker  */
16*fb1b10abSAndroid Build Coastguard Worker 
17*fb1b10abSAndroid Build Coastguard Worker #include <math.h>
18*fb1b10abSAndroid Build Coastguard Worker #include <stdarg.h>
19*fb1b10abSAndroid Build Coastguard Worker #include <stdio.h>
20*fb1b10abSAndroid Build Coastguard Worker #include <stdlib.h>
21*fb1b10abSAndroid Build Coastguard Worker #include <string.h>
22*fb1b10abSAndroid Build Coastguard Worker #include <time.h>
23*fb1b10abSAndroid Build Coastguard Worker 
24*fb1b10abSAndroid Build Coastguard Worker #include "../args.h"
25*fb1b10abSAndroid Build Coastguard Worker #include "../tools_common.h"
26*fb1b10abSAndroid Build Coastguard Worker #include "../video_writer.h"
27*fb1b10abSAndroid Build Coastguard Worker 
28*fb1b10abSAndroid Build Coastguard Worker #include "../vpx_ports/vpx_timer.h"
29*fb1b10abSAndroid Build Coastguard Worker #include "./svc_context.h"
30*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vp8cx.h"
31*fb1b10abSAndroid Build Coastguard Worker #include "vpx/vpx_encoder.h"
32*fb1b10abSAndroid Build Coastguard Worker #include "../vpxstats.h"
33*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
34*fb1b10abSAndroid Build Coastguard Worker #include "./y4minput.h"
35*fb1b10abSAndroid Build Coastguard Worker 
36*fb1b10abSAndroid Build Coastguard Worker #define OUTPUT_FRAME_STATS 0
37*fb1b10abSAndroid Build Coastguard Worker #define OUTPUT_RC_STATS 1
38*fb1b10abSAndroid Build Coastguard Worker 
39*fb1b10abSAndroid Build Coastguard Worker #define SIMULCAST_MODE 0
40*fb1b10abSAndroid Build Coastguard Worker 
41*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t outputfile =
42*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("o", "output", 1, "Output filename");
43*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t skip_frames_arg =
44*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("s", "skip-frames", 1, "input frames to skip");
45*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t frames_arg =
46*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("f", "frames", 1, "number of frames to encode");
47*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t threads_arg =
48*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("th", "threads", 1, "number of threads to use");
49*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
50*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t output_rc_stats_arg =
51*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats");
52*fb1b10abSAndroid Build Coastguard Worker #endif
53*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
54*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
55*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t timebase_arg =
56*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("t", "timebase", 1, "timebase (num/den)");
57*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t bitrate_arg = ARG_DEF(
58*fb1b10abSAndroid Build Coastguard Worker     "b", "target-bitrate", 1, "encoding bitrate, in kilobits per second");
59*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t spatial_layers_arg =
60*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
61*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t temporal_layers_arg =
62*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
63*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t temporal_layering_mode_arg =
64*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("tlm", "temporal-layering-mode", 1,
65*fb1b10abSAndroid Build Coastguard Worker             "temporal layering scheme."
66*fb1b10abSAndroid Build Coastguard Worker             "VP9E_TEMPORAL_LAYERING_MODE");
67*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t kf_dist_arg =
68*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
69*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t scale_factors_arg =
70*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)");
71*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t min_q_arg =
72*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "min-q", 1, "Minimum quantizer");
73*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t max_q_arg =
74*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "max-q", 1, "Maximum quantizer");
75*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t min_bitrate_arg =
76*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate");
77*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t max_bitrate_arg =
78*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate");
79*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t lag_in_frame_arg =
80*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "lag-in-frames", 1,
81*fb1b10abSAndroid Build Coastguard Worker             "Number of frame to input before "
82*fb1b10abSAndroid Build Coastguard Worker             "generating any outputs");
83*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t rc_end_usage_arg =
84*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
85*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t speed_arg =
86*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("sp", "speed", 1, "speed configuration");
87*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t aqmode_arg =
88*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
89*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t bitrates_arg =
90*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF("bl", "bitrates", 1, "bitrates[sl * num_tl + tl]");
91*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t dropframe_thresh_arg =
92*fb1b10abSAndroid Build Coastguard Worker     ARG_DEF(NULL, "drop-frame", 1, "Temporal resampling threshold (buf %)");
93*fb1b10abSAndroid Build Coastguard Worker static const struct arg_enum_list tune_content_enum[] = {
94*fb1b10abSAndroid Build Coastguard Worker   { "default", VP9E_CONTENT_DEFAULT },
95*fb1b10abSAndroid Build Coastguard Worker   { "screen", VP9E_CONTENT_SCREEN },
96*fb1b10abSAndroid Build Coastguard Worker   { "film", VP9E_CONTENT_FILM },
97*fb1b10abSAndroid Build Coastguard Worker   { NULL, 0 }
98*fb1b10abSAndroid Build Coastguard Worker };
99*fb1b10abSAndroid Build Coastguard Worker 
100*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t tune_content_arg = ARG_DEF_ENUM(
101*fb1b10abSAndroid Build Coastguard Worker     NULL, "tune-content", 1, "Tune content type", tune_content_enum);
102*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t inter_layer_pred_arg = ARG_DEF(
103*fb1b10abSAndroid Build Coastguard Worker     NULL, "inter-layer-pred", 1, "0 - 3: On, Off, Key-frames, Constrained");
104*fb1b10abSAndroid Build Coastguard Worker 
105*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
106*fb1b10abSAndroid Build Coastguard Worker static const struct arg_enum_list bitdepth_enum[] = {
107*fb1b10abSAndroid Build Coastguard Worker   { "8", VPX_BITS_8 }, { "10", VPX_BITS_10 }, { "12", VPX_BITS_12 }, { NULL, 0 }
108*fb1b10abSAndroid Build Coastguard Worker };
109*fb1b10abSAndroid Build Coastguard Worker 
110*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t bitdepth_arg = ARG_DEF_ENUM(
111*fb1b10abSAndroid Build Coastguard Worker     "d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ", bitdepth_enum);
112*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
113*fb1b10abSAndroid Build Coastguard Worker 
114*fb1b10abSAndroid Build Coastguard Worker static const arg_def_t *svc_args[] = { &frames_arg,
115*fb1b10abSAndroid Build Coastguard Worker                                        &outputfile,
116*fb1b10abSAndroid Build Coastguard Worker                                        &width_arg,
117*fb1b10abSAndroid Build Coastguard Worker                                        &height_arg,
118*fb1b10abSAndroid Build Coastguard Worker                                        &timebase_arg,
119*fb1b10abSAndroid Build Coastguard Worker                                        &bitrate_arg,
120*fb1b10abSAndroid Build Coastguard Worker                                        &skip_frames_arg,
121*fb1b10abSAndroid Build Coastguard Worker                                        &spatial_layers_arg,
122*fb1b10abSAndroid Build Coastguard Worker                                        &kf_dist_arg,
123*fb1b10abSAndroid Build Coastguard Worker                                        &scale_factors_arg,
124*fb1b10abSAndroid Build Coastguard Worker                                        &min_q_arg,
125*fb1b10abSAndroid Build Coastguard Worker                                        &max_q_arg,
126*fb1b10abSAndroid Build Coastguard Worker                                        &min_bitrate_arg,
127*fb1b10abSAndroid Build Coastguard Worker                                        &max_bitrate_arg,
128*fb1b10abSAndroid Build Coastguard Worker                                        &temporal_layers_arg,
129*fb1b10abSAndroid Build Coastguard Worker                                        &temporal_layering_mode_arg,
130*fb1b10abSAndroid Build Coastguard Worker                                        &lag_in_frame_arg,
131*fb1b10abSAndroid Build Coastguard Worker                                        &threads_arg,
132*fb1b10abSAndroid Build Coastguard Worker                                        &aqmode_arg,
133*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
134*fb1b10abSAndroid Build Coastguard Worker                                        &output_rc_stats_arg,
135*fb1b10abSAndroid Build Coastguard Worker #endif
136*fb1b10abSAndroid Build Coastguard Worker 
137*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
138*fb1b10abSAndroid Build Coastguard Worker                                        &bitdepth_arg,
139*fb1b10abSAndroid Build Coastguard Worker #endif
140*fb1b10abSAndroid Build Coastguard Worker                                        &speed_arg,
141*fb1b10abSAndroid Build Coastguard Worker                                        &rc_end_usage_arg,
142*fb1b10abSAndroid Build Coastguard Worker                                        &bitrates_arg,
143*fb1b10abSAndroid Build Coastguard Worker                                        &dropframe_thresh_arg,
144*fb1b10abSAndroid Build Coastguard Worker                                        &tune_content_arg,
145*fb1b10abSAndroid Build Coastguard Worker                                        &inter_layer_pred_arg,
146*fb1b10abSAndroid Build Coastguard Worker                                        NULL };
147*fb1b10abSAndroid Build Coastguard Worker 
148*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_frames_to_skip = 0;
149*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_frames_to_code = 60 * 60;
150*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_width = 1920;
151*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_height = 1080;
152*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_timebase_num = 1;
153*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_timebase_den = 60;
154*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_bitrate = 1000;
155*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_spatial_layers = 5;
156*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_temporal_layers = 1;
157*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_kf_dist = 100;
158*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_temporal_layering_mode = 0;
159*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_output_rc_stats = 0;
160*fb1b10abSAndroid Build Coastguard Worker static const int32_t default_speed = -1;    // -1 means use library default.
161*fb1b10abSAndroid Build Coastguard Worker static const uint32_t default_threads = 0;  // zero means use library default.
162*fb1b10abSAndroid Build Coastguard Worker 
163*fb1b10abSAndroid Build Coastguard Worker typedef struct {
164*fb1b10abSAndroid Build Coastguard Worker   const char *output_filename;
165*fb1b10abSAndroid Build Coastguard Worker   uint32_t frames_to_code;
166*fb1b10abSAndroid Build Coastguard Worker   uint32_t frames_to_skip;
167*fb1b10abSAndroid Build Coastguard Worker   struct VpxInputContext input_ctx;
168*fb1b10abSAndroid Build Coastguard Worker   stats_io_t rc_stats;
169*fb1b10abSAndroid Build Coastguard Worker   int tune_content;
170*fb1b10abSAndroid Build Coastguard Worker   int inter_layer_pred;
171*fb1b10abSAndroid Build Coastguard Worker } AppInput;
172*fb1b10abSAndroid Build Coastguard Worker 
173*fb1b10abSAndroid Build Coastguard Worker static const char *exec_name;
174*fb1b10abSAndroid Build Coastguard Worker 
usage_exit(void)175*fb1b10abSAndroid Build Coastguard Worker void usage_exit(void) {
176*fb1b10abSAndroid Build Coastguard Worker   fprintf(stderr, "Usage: %s <options> input_filename -o output_filename\n",
177*fb1b10abSAndroid Build Coastguard Worker           exec_name);
178*fb1b10abSAndroid Build Coastguard Worker   fprintf(stderr, "Options:\n");
179*fb1b10abSAndroid Build Coastguard Worker   arg_show_usage(stderr, svc_args);
180*fb1b10abSAndroid Build Coastguard Worker   exit(EXIT_FAILURE);
181*fb1b10abSAndroid Build Coastguard Worker }
182*fb1b10abSAndroid Build Coastguard Worker 
parse_command_line(int argc,const char ** argv_,AppInput * app_input,SvcContext * svc_ctx,vpx_codec_enc_cfg_t * enc_cfg)183*fb1b10abSAndroid Build Coastguard Worker static void parse_command_line(int argc, const char **argv_,
184*fb1b10abSAndroid Build Coastguard Worker                                AppInput *app_input, SvcContext *svc_ctx,
185*fb1b10abSAndroid Build Coastguard Worker                                vpx_codec_enc_cfg_t *enc_cfg) {
186*fb1b10abSAndroid Build Coastguard Worker   struct arg arg;
187*fb1b10abSAndroid Build Coastguard Worker   char **argv = NULL;
188*fb1b10abSAndroid Build Coastguard Worker   char **argi = NULL;
189*fb1b10abSAndroid Build Coastguard Worker   char **argj = NULL;
190*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res;
191*fb1b10abSAndroid Build Coastguard Worker   unsigned int min_bitrate = 0;
192*fb1b10abSAndroid Build Coastguard Worker   unsigned int max_bitrate = 0;
193*fb1b10abSAndroid Build Coastguard Worker   char string_options[1024] = { 0 };
194*fb1b10abSAndroid Build Coastguard Worker 
195*fb1b10abSAndroid Build Coastguard Worker   // initialize SvcContext with parameters that will be passed to vpx_svc_init
196*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->log_level = SVC_LOG_DEBUG;
197*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->spatial_layers = default_spatial_layers;
198*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->temporal_layers = default_temporal_layers;
199*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->temporal_layering_mode = default_temporal_layering_mode;
200*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
201*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->output_rc_stat = default_output_rc_stats;
202*fb1b10abSAndroid Build Coastguard Worker #endif
203*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->speed = default_speed;
204*fb1b10abSAndroid Build Coastguard Worker   svc_ctx->threads = default_threads;
205*fb1b10abSAndroid Build Coastguard Worker 
206*fb1b10abSAndroid Build Coastguard Worker   // start with default encoder configuration
207*fb1b10abSAndroid Build Coastguard Worker   res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
208*fb1b10abSAndroid Build Coastguard Worker   if (res) {
209*fb1b10abSAndroid Build Coastguard Worker     die("Failed to get config: %s\n", vpx_codec_err_to_string(res));
210*fb1b10abSAndroid Build Coastguard Worker   }
211*fb1b10abSAndroid Build Coastguard Worker   // update enc_cfg with app default values
212*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->g_w = default_width;
213*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->g_h = default_height;
214*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->g_timebase.num = default_timebase_num;
215*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->g_timebase.den = default_timebase_den;
216*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->rc_target_bitrate = default_bitrate;
217*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->kf_min_dist = default_kf_dist;
218*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->kf_max_dist = default_kf_dist;
219*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->rc_end_usage = VPX_CQ;
220*fb1b10abSAndroid Build Coastguard Worker 
221*fb1b10abSAndroid Build Coastguard Worker   // initialize AppInput with default values
222*fb1b10abSAndroid Build Coastguard Worker   app_input->frames_to_code = default_frames_to_code;
223*fb1b10abSAndroid Build Coastguard Worker   app_input->frames_to_skip = default_frames_to_skip;
224*fb1b10abSAndroid Build Coastguard Worker 
225*fb1b10abSAndroid Build Coastguard Worker   // process command line options
226*fb1b10abSAndroid Build Coastguard Worker   argv = argv_dup(argc - 1, argv_ + 1);
227*fb1b10abSAndroid Build Coastguard Worker   if (!argv) {
228*fb1b10abSAndroid Build Coastguard Worker     fprintf(stderr, "Error allocating argument list\n");
229*fb1b10abSAndroid Build Coastguard Worker     exit(EXIT_FAILURE);
230*fb1b10abSAndroid Build Coastguard Worker   }
231*fb1b10abSAndroid Build Coastguard Worker   for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
232*fb1b10abSAndroid Build Coastguard Worker     arg.argv_step = 1;
233*fb1b10abSAndroid Build Coastguard Worker 
234*fb1b10abSAndroid Build Coastguard Worker     if (arg_match(&arg, &frames_arg, argi)) {
235*fb1b10abSAndroid Build Coastguard Worker       app_input->frames_to_code = arg_parse_uint(&arg);
236*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &outputfile, argi)) {
237*fb1b10abSAndroid Build Coastguard Worker       app_input->output_filename = arg.val;
238*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &width_arg, argi)) {
239*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_w = arg_parse_uint(&arg);
240*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &height_arg, argi)) {
241*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_h = arg_parse_uint(&arg);
242*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &timebase_arg, argi)) {
243*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_timebase = arg_parse_rational(&arg);
244*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &bitrate_arg, argi)) {
245*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_target_bitrate = arg_parse_uint(&arg);
246*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &skip_frames_arg, argi)) {
247*fb1b10abSAndroid Build Coastguard Worker       app_input->frames_to_skip = arg_parse_uint(&arg);
248*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &spatial_layers_arg, argi)) {
249*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->spatial_layers = arg_parse_uint(&arg);
250*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &temporal_layers_arg, argi)) {
251*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->temporal_layers = arg_parse_uint(&arg);
252*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
253*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &output_rc_stats_arg, argi)) {
254*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->output_rc_stat = arg_parse_uint(&arg);
255*fb1b10abSAndroid Build Coastguard Worker #endif
256*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &speed_arg, argi)) {
257*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->speed = arg_parse_uint(&arg);
258*fb1b10abSAndroid Build Coastguard Worker       if (svc_ctx->speed > 9) {
259*fb1b10abSAndroid Build Coastguard Worker         warn("Mapping speed %d to speed 9.\n", svc_ctx->speed);
260*fb1b10abSAndroid Build Coastguard Worker       }
261*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &aqmode_arg, argi)) {
262*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->aqmode = arg_parse_uint(&arg);
263*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &threads_arg, argi)) {
264*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->threads = arg_parse_uint(&arg);
265*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
266*fb1b10abSAndroid Build Coastguard Worker       svc_ctx->temporal_layering_mode = enc_cfg->temporal_layering_mode =
267*fb1b10abSAndroid Build Coastguard Worker           arg_parse_int(&arg);
268*fb1b10abSAndroid Build Coastguard Worker       if (svc_ctx->temporal_layering_mode) {
269*fb1b10abSAndroid Build Coastguard Worker         enc_cfg->g_error_resilient = 1;
270*fb1b10abSAndroid Build Coastguard Worker       }
271*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &kf_dist_arg, argi)) {
272*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->kf_min_dist = arg_parse_uint(&arg);
273*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
274*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &scale_factors_arg, argi)) {
275*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, " scale-factors=",
276*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
277*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, arg.val,
278*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
279*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &bitrates_arg, argi)) {
280*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, " bitrates=",
281*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
282*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, arg.val,
283*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
284*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &min_q_arg, argi)) {
285*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, " min-quantizers=",
286*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
287*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, arg.val,
288*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
289*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &max_q_arg, argi)) {
290*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, " max-quantizers=",
291*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
292*fb1b10abSAndroid Build Coastguard Worker       strncat(string_options, arg.val,
293*fb1b10abSAndroid Build Coastguard Worker               sizeof(string_options) - strlen(string_options) - 1);
294*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &min_bitrate_arg, argi)) {
295*fb1b10abSAndroid Build Coastguard Worker       min_bitrate = arg_parse_uint(&arg);
296*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &max_bitrate_arg, argi)) {
297*fb1b10abSAndroid Build Coastguard Worker       max_bitrate = arg_parse_uint(&arg);
298*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &lag_in_frame_arg, argi)) {
299*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_lag_in_frames = arg_parse_uint(&arg);
300*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &rc_end_usage_arg, argi)) {
301*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_end_usage = arg_parse_uint(&arg);
302*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
303*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &bitdepth_arg, argi)) {
304*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_bit_depth = arg_parse_enum_or_int(&arg);
305*fb1b10abSAndroid Build Coastguard Worker       switch (enc_cfg->g_bit_depth) {
306*fb1b10abSAndroid Build Coastguard Worker         case VPX_BITS_8:
307*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_input_bit_depth = 8;
308*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_profile = 0;
309*fb1b10abSAndroid Build Coastguard Worker           break;
310*fb1b10abSAndroid Build Coastguard Worker         case VPX_BITS_10:
311*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_input_bit_depth = 10;
312*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_profile = 2;
313*fb1b10abSAndroid Build Coastguard Worker           break;
314*fb1b10abSAndroid Build Coastguard Worker         case VPX_BITS_12:
315*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_input_bit_depth = 12;
316*fb1b10abSAndroid Build Coastguard Worker           enc_cfg->g_profile = 2;
317*fb1b10abSAndroid Build Coastguard Worker           break;
318*fb1b10abSAndroid Build Coastguard Worker         default:
319*fb1b10abSAndroid Build Coastguard Worker           die("Error: Invalid bit depth selected (%d)\n", enc_cfg->g_bit_depth);
320*fb1b10abSAndroid Build Coastguard Worker       }
321*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
322*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &dropframe_thresh_arg, argi)) {
323*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_dropframe_thresh = arg_parse_uint(&arg);
324*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &tune_content_arg, argi)) {
325*fb1b10abSAndroid Build Coastguard Worker       app_input->tune_content = arg_parse_uint(&arg);
326*fb1b10abSAndroid Build Coastguard Worker     } else if (arg_match(&arg, &inter_layer_pred_arg, argi)) {
327*fb1b10abSAndroid Build Coastguard Worker       app_input->inter_layer_pred = arg_parse_uint(&arg);
328*fb1b10abSAndroid Build Coastguard Worker     } else {
329*fb1b10abSAndroid Build Coastguard Worker       ++argj;
330*fb1b10abSAndroid Build Coastguard Worker     }
331*fb1b10abSAndroid Build Coastguard Worker   }
332*fb1b10abSAndroid Build Coastguard Worker 
333*fb1b10abSAndroid Build Coastguard Worker   // There will be a space in front of the string options
334*fb1b10abSAndroid Build Coastguard Worker   if (strlen(string_options) > 0)
335*fb1b10abSAndroid Build Coastguard Worker     vpx_svc_set_options(svc_ctx, string_options + 1);
336*fb1b10abSAndroid Build Coastguard Worker 
337*fb1b10abSAndroid Build Coastguard Worker   enc_cfg->g_pass = VPX_RC_ONE_PASS;
338*fb1b10abSAndroid Build Coastguard Worker 
339*fb1b10abSAndroid Build Coastguard Worker   if (enc_cfg->rc_target_bitrate > 0) {
340*fb1b10abSAndroid Build Coastguard Worker     if (min_bitrate > 0) {
341*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_2pass_vbr_minsection_pct =
342*fb1b10abSAndroid Build Coastguard Worker           min_bitrate * 100 / enc_cfg->rc_target_bitrate;
343*fb1b10abSAndroid Build Coastguard Worker     }
344*fb1b10abSAndroid Build Coastguard Worker     if (max_bitrate > 0) {
345*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_2pass_vbr_maxsection_pct =
346*fb1b10abSAndroid Build Coastguard Worker           max_bitrate * 100 / enc_cfg->rc_target_bitrate;
347*fb1b10abSAndroid Build Coastguard Worker     }
348*fb1b10abSAndroid Build Coastguard Worker   }
349*fb1b10abSAndroid Build Coastguard Worker 
350*fb1b10abSAndroid Build Coastguard Worker   // Check for unrecognized options
351*fb1b10abSAndroid Build Coastguard Worker   for (argi = argv; *argi; ++argi)
352*fb1b10abSAndroid Build Coastguard Worker     if (argi[0][0] == '-' && strlen(argi[0]) > 1)
353*fb1b10abSAndroid Build Coastguard Worker       die("Error: Unrecognized option %s\n", *argi);
354*fb1b10abSAndroid Build Coastguard Worker 
355*fb1b10abSAndroid Build Coastguard Worker   if (argv[0] == NULL) {
356*fb1b10abSAndroid Build Coastguard Worker     usage_exit();
357*fb1b10abSAndroid Build Coastguard Worker   }
358*fb1b10abSAndroid Build Coastguard Worker   app_input->input_ctx.filename = argv[0];
359*fb1b10abSAndroid Build Coastguard Worker   free(argv);
360*fb1b10abSAndroid Build Coastguard Worker 
361*fb1b10abSAndroid Build Coastguard Worker   open_input_file(&app_input->input_ctx);
362*fb1b10abSAndroid Build Coastguard Worker   if (app_input->input_ctx.file_type == FILE_TYPE_Y4M) {
363*fb1b10abSAndroid Build Coastguard Worker     enc_cfg->g_w = app_input->input_ctx.width;
364*fb1b10abSAndroid Build Coastguard Worker     enc_cfg->g_h = app_input->input_ctx.height;
365*fb1b10abSAndroid Build Coastguard Worker     enc_cfg->g_timebase.den = app_input->input_ctx.framerate.numerator;
366*fb1b10abSAndroid Build Coastguard Worker     enc_cfg->g_timebase.num = app_input->input_ctx.framerate.denominator;
367*fb1b10abSAndroid Build Coastguard Worker   }
368*fb1b10abSAndroid Build Coastguard Worker 
369*fb1b10abSAndroid Build Coastguard Worker   if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 ||
370*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_h % 2)
371*fb1b10abSAndroid Build Coastguard Worker     die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h);
372*fb1b10abSAndroid Build Coastguard Worker 
373*fb1b10abSAndroid Build Coastguard Worker   printf(
374*fb1b10abSAndroid Build Coastguard Worker       "Codec %s\nframes: %d, skip: %d\n"
375*fb1b10abSAndroid Build Coastguard Worker       "layers: %d\n"
376*fb1b10abSAndroid Build Coastguard Worker       "width %d, height: %d,\n"
377*fb1b10abSAndroid Build Coastguard Worker       "num: %d, den: %d, bitrate: %d,\n"
378*fb1b10abSAndroid Build Coastguard Worker       "gop size: %d\n",
379*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code,
380*fb1b10abSAndroid Build Coastguard Worker       app_input->frames_to_skip, svc_ctx->spatial_layers, enc_cfg->g_w,
381*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->g_h, enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
382*fb1b10abSAndroid Build Coastguard Worker       enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
383*fb1b10abSAndroid Build Coastguard Worker }
384*fb1b10abSAndroid Build Coastguard Worker 
385*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
386*fb1b10abSAndroid Build Coastguard Worker // For rate control encoding stats.
387*fb1b10abSAndroid Build Coastguard Worker struct RateControlStats {
388*fb1b10abSAndroid Build Coastguard Worker   // Number of input frames per layer.
389*fb1b10abSAndroid Build Coastguard Worker   int layer_input_frames[VPX_MAX_LAYERS];
390*fb1b10abSAndroid Build Coastguard Worker   // Total (cumulative) number of encoded frames per layer.
391*fb1b10abSAndroid Build Coastguard Worker   int layer_tot_enc_frames[VPX_MAX_LAYERS];
392*fb1b10abSAndroid Build Coastguard Worker   // Number of encoded non-key frames per layer.
393*fb1b10abSAndroid Build Coastguard Worker   int layer_enc_frames[VPX_MAX_LAYERS];
394*fb1b10abSAndroid Build Coastguard Worker   // Framerate per layer (cumulative).
395*fb1b10abSAndroid Build Coastguard Worker   double layer_framerate[VPX_MAX_LAYERS];
396*fb1b10abSAndroid Build Coastguard Worker   // Target average frame size per layer (per-frame-bandwidth per layer).
397*fb1b10abSAndroid Build Coastguard Worker   double layer_pfb[VPX_MAX_LAYERS];
398*fb1b10abSAndroid Build Coastguard Worker   // Actual average frame size per layer.
399*fb1b10abSAndroid Build Coastguard Worker   double layer_avg_frame_size[VPX_MAX_LAYERS];
400*fb1b10abSAndroid Build Coastguard Worker   // Average rate mismatch per layer (|target - actual| / target).
401*fb1b10abSAndroid Build Coastguard Worker   double layer_avg_rate_mismatch[VPX_MAX_LAYERS];
402*fb1b10abSAndroid Build Coastguard Worker   // Actual encoding bitrate per layer (cumulative).
403*fb1b10abSAndroid Build Coastguard Worker   double layer_encoding_bitrate[VPX_MAX_LAYERS];
404*fb1b10abSAndroid Build Coastguard Worker   // Average of the short-time encoder actual bitrate.
405*fb1b10abSAndroid Build Coastguard Worker   // TODO(marpan): Should we add these short-time stats for each layer?
406*fb1b10abSAndroid Build Coastguard Worker   double avg_st_encoding_bitrate;
407*fb1b10abSAndroid Build Coastguard Worker   // Variance of the short-time encoder actual bitrate.
408*fb1b10abSAndroid Build Coastguard Worker   double variance_st_encoding_bitrate;
409*fb1b10abSAndroid Build Coastguard Worker   // Window (number of frames) for computing short-time encoding bitrate.
410*fb1b10abSAndroid Build Coastguard Worker   int window_size;
411*fb1b10abSAndroid Build Coastguard Worker   // Number of window measurements.
412*fb1b10abSAndroid Build Coastguard Worker   int window_count;
413*fb1b10abSAndroid Build Coastguard Worker };
414*fb1b10abSAndroid Build Coastguard Worker 
415*fb1b10abSAndroid Build Coastguard Worker // Note: these rate control stats assume only 1 key frame in the
416*fb1b10abSAndroid Build Coastguard Worker // sequence (i.e., first frame only).
set_rate_control_stats(struct RateControlStats * rc,vpx_codec_enc_cfg_t * cfg)417*fb1b10abSAndroid Build Coastguard Worker static void set_rate_control_stats(struct RateControlStats *rc,
418*fb1b10abSAndroid Build Coastguard Worker                                    vpx_codec_enc_cfg_t *cfg) {
419*fb1b10abSAndroid Build Coastguard Worker   unsigned int sl, tl;
420*fb1b10abSAndroid Build Coastguard Worker   // Set the layer (cumulative) framerate and the target layer (non-cumulative)
421*fb1b10abSAndroid Build Coastguard Worker   // per-frame-bandwidth, for the rate control encoding stats below.
422*fb1b10abSAndroid Build Coastguard Worker   const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
423*fb1b10abSAndroid Build Coastguard Worker 
424*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
425*fb1b10abSAndroid Build Coastguard Worker     for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
426*fb1b10abSAndroid Build Coastguard Worker       const int layer = sl * cfg->ts_number_layers + tl;
427*fb1b10abSAndroid Build Coastguard Worker       if (cfg->ts_number_layers == 1)
428*fb1b10abSAndroid Build Coastguard Worker         rc->layer_framerate[layer] = framerate;
429*fb1b10abSAndroid Build Coastguard Worker       else
430*fb1b10abSAndroid Build Coastguard Worker         rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl];
431*fb1b10abSAndroid Build Coastguard Worker       if (tl > 0) {
432*fb1b10abSAndroid Build Coastguard Worker         rc->layer_pfb[layer] =
433*fb1b10abSAndroid Build Coastguard Worker             1000.0 *
434*fb1b10abSAndroid Build Coastguard Worker             (cfg->layer_target_bitrate[layer] -
435*fb1b10abSAndroid Build Coastguard Worker              cfg->layer_target_bitrate[layer - 1]) /
436*fb1b10abSAndroid Build Coastguard Worker             (rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]);
437*fb1b10abSAndroid Build Coastguard Worker       } else {
438*fb1b10abSAndroid Build Coastguard Worker         rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
439*fb1b10abSAndroid Build Coastguard Worker                                rc->layer_framerate[layer];
440*fb1b10abSAndroid Build Coastguard Worker       }
441*fb1b10abSAndroid Build Coastguard Worker       rc->layer_input_frames[layer] = 0;
442*fb1b10abSAndroid Build Coastguard Worker       rc->layer_enc_frames[layer] = 0;
443*fb1b10abSAndroid Build Coastguard Worker       rc->layer_tot_enc_frames[layer] = 0;
444*fb1b10abSAndroid Build Coastguard Worker       rc->layer_encoding_bitrate[layer] = 0.0;
445*fb1b10abSAndroid Build Coastguard Worker       rc->layer_avg_frame_size[layer] = 0.0;
446*fb1b10abSAndroid Build Coastguard Worker       rc->layer_avg_rate_mismatch[layer] = 0.0;
447*fb1b10abSAndroid Build Coastguard Worker     }
448*fb1b10abSAndroid Build Coastguard Worker   }
449*fb1b10abSAndroid Build Coastguard Worker   rc->window_count = 0;
450*fb1b10abSAndroid Build Coastguard Worker   rc->window_size = 15;
451*fb1b10abSAndroid Build Coastguard Worker   rc->avg_st_encoding_bitrate = 0.0;
452*fb1b10abSAndroid Build Coastguard Worker   rc->variance_st_encoding_bitrate = 0.0;
453*fb1b10abSAndroid Build Coastguard Worker }
454*fb1b10abSAndroid Build Coastguard Worker 
printout_rate_control_summary(struct RateControlStats * rc,vpx_codec_enc_cfg_t * cfg,int frame_cnt)455*fb1b10abSAndroid Build Coastguard Worker static void printout_rate_control_summary(struct RateControlStats *rc,
456*fb1b10abSAndroid Build Coastguard Worker                                           vpx_codec_enc_cfg_t *cfg,
457*fb1b10abSAndroid Build Coastguard Worker                                           int frame_cnt) {
458*fb1b10abSAndroid Build Coastguard Worker   unsigned int sl, tl;
459*fb1b10abSAndroid Build Coastguard Worker   double perc_fluctuation = 0.0;
460*fb1b10abSAndroid Build Coastguard Worker   int tot_num_frames = 0;
461*fb1b10abSAndroid Build Coastguard Worker   printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
462*fb1b10abSAndroid Build Coastguard Worker   printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
463*fb1b10abSAndroid Build Coastguard Worker          cfg->ss_number_layers, cfg->ts_number_layers);
464*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
465*fb1b10abSAndroid Build Coastguard Worker     tot_num_frames = 0;
466*fb1b10abSAndroid Build Coastguard Worker     for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
467*fb1b10abSAndroid Build Coastguard Worker       const int layer = sl * cfg->ts_number_layers + tl;
468*fb1b10abSAndroid Build Coastguard Worker       const int num_dropped =
469*fb1b10abSAndroid Build Coastguard Worker           (tl > 0)
470*fb1b10abSAndroid Build Coastguard Worker               ? (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer])
471*fb1b10abSAndroid Build Coastguard Worker               : (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] -
472*fb1b10abSAndroid Build Coastguard Worker                  1);
473*fb1b10abSAndroid Build Coastguard Worker       tot_num_frames += rc->layer_input_frames[layer];
474*fb1b10abSAndroid Build Coastguard Worker       rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
475*fb1b10abSAndroid Build Coastguard Worker                                           rc->layer_encoding_bitrate[layer] /
476*fb1b10abSAndroid Build Coastguard Worker                                           tot_num_frames;
477*fb1b10abSAndroid Build Coastguard Worker       rc->layer_avg_frame_size[layer] =
478*fb1b10abSAndroid Build Coastguard Worker           rc->layer_avg_frame_size[layer] / rc->layer_enc_frames[layer];
479*fb1b10abSAndroid Build Coastguard Worker       rc->layer_avg_rate_mismatch[layer] = 100.0 *
480*fb1b10abSAndroid Build Coastguard Worker                                            rc->layer_avg_rate_mismatch[layer] /
481*fb1b10abSAndroid Build Coastguard Worker                                            rc->layer_enc_frames[layer];
482*fb1b10abSAndroid Build Coastguard Worker       printf("For layer#: sl%d tl%d \n", sl, tl);
483*fb1b10abSAndroid Build Coastguard Worker       printf("Bitrate (target vs actual): %d %f.0 kbps\n",
484*fb1b10abSAndroid Build Coastguard Worker              cfg->layer_target_bitrate[layer],
485*fb1b10abSAndroid Build Coastguard Worker              rc->layer_encoding_bitrate[layer]);
486*fb1b10abSAndroid Build Coastguard Worker       printf("Average frame size (target vs actual): %f %f bits\n",
487*fb1b10abSAndroid Build Coastguard Worker              rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]);
488*fb1b10abSAndroid Build Coastguard Worker       printf("Average rate_mismatch: %f\n", rc->layer_avg_rate_mismatch[layer]);
489*fb1b10abSAndroid Build Coastguard Worker       printf(
490*fb1b10abSAndroid Build Coastguard Worker           "Number of input frames, encoded (non-key) frames, "
491*fb1b10abSAndroid Build Coastguard Worker           "and percent dropped frames: %d %d %f.0 \n",
492*fb1b10abSAndroid Build Coastguard Worker           rc->layer_input_frames[layer], rc->layer_enc_frames[layer],
493*fb1b10abSAndroid Build Coastguard Worker           100.0 * num_dropped / rc->layer_input_frames[layer]);
494*fb1b10abSAndroid Build Coastguard Worker       printf("\n");
495*fb1b10abSAndroid Build Coastguard Worker     }
496*fb1b10abSAndroid Build Coastguard Worker   }
497*fb1b10abSAndroid Build Coastguard Worker   rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
498*fb1b10abSAndroid Build Coastguard Worker   rc->variance_st_encoding_bitrate =
499*fb1b10abSAndroid Build Coastguard Worker       rc->variance_st_encoding_bitrate / rc->window_count -
500*fb1b10abSAndroid Build Coastguard Worker       (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
501*fb1b10abSAndroid Build Coastguard Worker   perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
502*fb1b10abSAndroid Build Coastguard Worker                      rc->avg_st_encoding_bitrate;
503*fb1b10abSAndroid Build Coastguard Worker   printf("Short-time stats, for window of %d frames: \n", rc->window_size);
504*fb1b10abSAndroid Build Coastguard Worker   printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
505*fb1b10abSAndroid Build Coastguard Worker          rc->avg_st_encoding_bitrate, sqrt(rc->variance_st_encoding_bitrate),
506*fb1b10abSAndroid Build Coastguard Worker          perc_fluctuation);
507*fb1b10abSAndroid Build Coastguard Worker   printf("Num of input, num of encoded (super) frames: %d %d \n", frame_cnt,
508*fb1b10abSAndroid Build Coastguard Worker          tot_num_frames);
509*fb1b10abSAndroid Build Coastguard Worker }
510*fb1b10abSAndroid Build Coastguard Worker 
parse_superframe_index(const uint8_t * data,size_t data_sz,uint64_t sizes[8],int * count)511*fb1b10abSAndroid Build Coastguard Worker static vpx_codec_err_t parse_superframe_index(const uint8_t *data,
512*fb1b10abSAndroid Build Coastguard Worker                                               size_t data_sz, uint64_t sizes[8],
513*fb1b10abSAndroid Build Coastguard Worker                                               int *count) {
514*fb1b10abSAndroid Build Coastguard Worker   // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
515*fb1b10abSAndroid Build Coastguard Worker   // it is a super frame index. If the last byte of real video compression
516*fb1b10abSAndroid Build Coastguard Worker   // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
517*fb1b10abSAndroid Build Coastguard Worker   // not the associated matching marker byte at the front of the index we have
518*fb1b10abSAndroid Build Coastguard Worker   // an invalid bitstream and need to return an error.
519*fb1b10abSAndroid Build Coastguard Worker 
520*fb1b10abSAndroid Build Coastguard Worker   uint8_t marker;
521*fb1b10abSAndroid Build Coastguard Worker 
522*fb1b10abSAndroid Build Coastguard Worker   marker = *(data + data_sz - 1);
523*fb1b10abSAndroid Build Coastguard Worker   *count = 0;
524*fb1b10abSAndroid Build Coastguard Worker 
525*fb1b10abSAndroid Build Coastguard Worker   if ((marker & 0xe0) == 0xc0) {
526*fb1b10abSAndroid Build Coastguard Worker     const uint32_t frames = (marker & 0x7) + 1;
527*fb1b10abSAndroid Build Coastguard Worker     const uint32_t mag = ((marker >> 3) & 0x3) + 1;
528*fb1b10abSAndroid Build Coastguard Worker     const size_t index_sz = 2 + mag * frames;
529*fb1b10abSAndroid Build Coastguard Worker 
530*fb1b10abSAndroid Build Coastguard Worker     // This chunk is marked as having a superframe index but doesn't have
531*fb1b10abSAndroid Build Coastguard Worker     // enough data for it, thus it's an invalid superframe index.
532*fb1b10abSAndroid Build Coastguard Worker     if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
533*fb1b10abSAndroid Build Coastguard Worker 
534*fb1b10abSAndroid Build Coastguard Worker     {
535*fb1b10abSAndroid Build Coastguard Worker       const uint8_t marker2 = *(data + data_sz - index_sz);
536*fb1b10abSAndroid Build Coastguard Worker 
537*fb1b10abSAndroid Build Coastguard Worker       // This chunk is marked as having a superframe index but doesn't have
538*fb1b10abSAndroid Build Coastguard Worker       // the matching marker byte at the front of the index therefore it's an
539*fb1b10abSAndroid Build Coastguard Worker       // invalid chunk.
540*fb1b10abSAndroid Build Coastguard Worker       if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
541*fb1b10abSAndroid Build Coastguard Worker     }
542*fb1b10abSAndroid Build Coastguard Worker 
543*fb1b10abSAndroid Build Coastguard Worker     {
544*fb1b10abSAndroid Build Coastguard Worker       // Found a valid superframe index.
545*fb1b10abSAndroid Build Coastguard Worker       uint32_t i, j;
546*fb1b10abSAndroid Build Coastguard Worker       const uint8_t *x = &data[data_sz - index_sz + 1];
547*fb1b10abSAndroid Build Coastguard Worker 
548*fb1b10abSAndroid Build Coastguard Worker       for (i = 0; i < frames; ++i) {
549*fb1b10abSAndroid Build Coastguard Worker         uint32_t this_sz = 0;
550*fb1b10abSAndroid Build Coastguard Worker 
551*fb1b10abSAndroid Build Coastguard Worker         for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
552*fb1b10abSAndroid Build Coastguard Worker         sizes[i] = this_sz;
553*fb1b10abSAndroid Build Coastguard Worker       }
554*fb1b10abSAndroid Build Coastguard Worker       *count = frames;
555*fb1b10abSAndroid Build Coastguard Worker     }
556*fb1b10abSAndroid Build Coastguard Worker   }
557*fb1b10abSAndroid Build Coastguard Worker   return VPX_CODEC_OK;
558*fb1b10abSAndroid Build Coastguard Worker }
559*fb1b10abSAndroid Build Coastguard Worker #endif
560*fb1b10abSAndroid Build Coastguard Worker 
561*fb1b10abSAndroid Build Coastguard Worker // Example pattern for spatial layers and 2 temporal layers used in the
562*fb1b10abSAndroid Build Coastguard Worker // bypass/flexible mode. The pattern corresponds to the pattern
563*fb1b10abSAndroid Build Coastguard Worker // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
564*fb1b10abSAndroid Build Coastguard Worker // non-flexible mode.
set_frame_flags_bypass_mode_ex0(int tl,int num_spatial_layers,int is_key_frame,vpx_svc_ref_frame_config_t * ref_frame_config)565*fb1b10abSAndroid Build Coastguard Worker static void set_frame_flags_bypass_mode_ex0(
566*fb1b10abSAndroid Build Coastguard Worker     int tl, int num_spatial_layers, int is_key_frame,
567*fb1b10abSAndroid Build Coastguard Worker     vpx_svc_ref_frame_config_t *ref_frame_config) {
568*fb1b10abSAndroid Build Coastguard Worker   int sl;
569*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < num_spatial_layers; ++sl)
570*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->update_buffer_slot[sl] = 0;
571*fb1b10abSAndroid Build Coastguard Worker 
572*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < num_spatial_layers; ++sl) {
573*fb1b10abSAndroid Build Coastguard Worker     // Set the buffer idx.
574*fb1b10abSAndroid Build Coastguard Worker     if (tl == 0) {
575*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->lst_fb_idx[sl] = sl;
576*fb1b10abSAndroid Build Coastguard Worker       if (sl) {
577*fb1b10abSAndroid Build Coastguard Worker         if (is_key_frame) {
578*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->lst_fb_idx[sl] = sl - 1;
579*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->gld_fb_idx[sl] = sl;
580*fb1b10abSAndroid Build Coastguard Worker         } else {
581*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->gld_fb_idx[sl] = sl - 1;
582*fb1b10abSAndroid Build Coastguard Worker         }
583*fb1b10abSAndroid Build Coastguard Worker       } else {
584*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->gld_fb_idx[sl] = 0;
585*fb1b10abSAndroid Build Coastguard Worker       }
586*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->alt_fb_idx[sl] = 0;
587*fb1b10abSAndroid Build Coastguard Worker     } else if (tl == 1) {
588*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->lst_fb_idx[sl] = sl;
589*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->gld_fb_idx[sl] =
590*fb1b10abSAndroid Build Coastguard Worker           (sl == 0) ? 0 : num_spatial_layers + sl - 1;
591*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
592*fb1b10abSAndroid Build Coastguard Worker     }
593*fb1b10abSAndroid Build Coastguard Worker     // Set the reference and update flags.
594*fb1b10abSAndroid Build Coastguard Worker     if (!tl) {
595*fb1b10abSAndroid Build Coastguard Worker       if (!sl) {
596*fb1b10abSAndroid Build Coastguard Worker         // Base spatial and base temporal (sl = 0, tl = 0)
597*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_last[sl] = 1;
598*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_golden[sl] = 0;
599*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_alt_ref[sl] = 0;
600*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->update_buffer_slot[sl] |=
601*fb1b10abSAndroid Build Coastguard Worker             1 << ref_frame_config->lst_fb_idx[sl];
602*fb1b10abSAndroid Build Coastguard Worker       } else {
603*fb1b10abSAndroid Build Coastguard Worker         if (is_key_frame) {
604*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_last[sl] = 1;
605*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_golden[sl] = 0;
606*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_alt_ref[sl] = 0;
607*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->update_buffer_slot[sl] |=
608*fb1b10abSAndroid Build Coastguard Worker               1 << ref_frame_config->gld_fb_idx[sl];
609*fb1b10abSAndroid Build Coastguard Worker         } else {
610*fb1b10abSAndroid Build Coastguard Worker           // Non-zero spatiall layer.
611*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_last[sl] = 1;
612*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_golden[sl] = 1;
613*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_alt_ref[sl] = 1;
614*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->update_buffer_slot[sl] |=
615*fb1b10abSAndroid Build Coastguard Worker               1 << ref_frame_config->lst_fb_idx[sl];
616*fb1b10abSAndroid Build Coastguard Worker         }
617*fb1b10abSAndroid Build Coastguard Worker       }
618*fb1b10abSAndroid Build Coastguard Worker     } else if (tl == 1) {
619*fb1b10abSAndroid Build Coastguard Worker       if (!sl) {
620*fb1b10abSAndroid Build Coastguard Worker         // Base spatial and top temporal (tl = 1)
621*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_last[sl] = 1;
622*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_golden[sl] = 0;
623*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->reference_alt_ref[sl] = 0;
624*fb1b10abSAndroid Build Coastguard Worker         ref_frame_config->update_buffer_slot[sl] |=
625*fb1b10abSAndroid Build Coastguard Worker             1 << ref_frame_config->alt_fb_idx[sl];
626*fb1b10abSAndroid Build Coastguard Worker       } else {
627*fb1b10abSAndroid Build Coastguard Worker         // Non-zero spatial.
628*fb1b10abSAndroid Build Coastguard Worker         if (sl < num_spatial_layers - 1) {
629*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_last[sl] = 1;
630*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_golden[sl] = 1;
631*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_alt_ref[sl] = 0;
632*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->update_buffer_slot[sl] |=
633*fb1b10abSAndroid Build Coastguard Worker               1 << ref_frame_config->alt_fb_idx[sl];
634*fb1b10abSAndroid Build Coastguard Worker         } else if (sl == num_spatial_layers - 1) {
635*fb1b10abSAndroid Build Coastguard Worker           // Top spatial and top temporal (non-reference -- doesn't update any
636*fb1b10abSAndroid Build Coastguard Worker           // reference buffers)
637*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_last[sl] = 1;
638*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_golden[sl] = 1;
639*fb1b10abSAndroid Build Coastguard Worker           ref_frame_config->reference_alt_ref[sl] = 0;
640*fb1b10abSAndroid Build Coastguard Worker         }
641*fb1b10abSAndroid Build Coastguard Worker       }
642*fb1b10abSAndroid Build Coastguard Worker     }
643*fb1b10abSAndroid Build Coastguard Worker   }
644*fb1b10abSAndroid Build Coastguard Worker }
645*fb1b10abSAndroid Build Coastguard Worker 
646*fb1b10abSAndroid Build Coastguard Worker // Example pattern for 2 spatial layers and 2 temporal layers used in the
647*fb1b10abSAndroid Build Coastguard Worker // bypass/flexible mode, except only 1 spatial layer when temporal_layer_id = 1.
set_frame_flags_bypass_mode_ex1(int tl,int num_spatial_layers,int is_key_frame,vpx_svc_ref_frame_config_t * ref_frame_config)648*fb1b10abSAndroid Build Coastguard Worker static void set_frame_flags_bypass_mode_ex1(
649*fb1b10abSAndroid Build Coastguard Worker     int tl, int num_spatial_layers, int is_key_frame,
650*fb1b10abSAndroid Build Coastguard Worker     vpx_svc_ref_frame_config_t *ref_frame_config) {
651*fb1b10abSAndroid Build Coastguard Worker   int sl;
652*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < num_spatial_layers; ++sl)
653*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->update_buffer_slot[sl] = 0;
654*fb1b10abSAndroid Build Coastguard Worker 
655*fb1b10abSAndroid Build Coastguard Worker   if (tl == 0) {
656*fb1b10abSAndroid Build Coastguard Worker     if (is_key_frame) {
657*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->lst_fb_idx[1] = 0;
658*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->gld_fb_idx[1] = 1;
659*fb1b10abSAndroid Build Coastguard Worker     } else {
660*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->lst_fb_idx[1] = 1;
661*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->gld_fb_idx[1] = 0;
662*fb1b10abSAndroid Build Coastguard Worker     }
663*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->alt_fb_idx[1] = 0;
664*fb1b10abSAndroid Build Coastguard Worker 
665*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->lst_fb_idx[0] = 0;
666*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->gld_fb_idx[0] = 0;
667*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->alt_fb_idx[0] = 0;
668*fb1b10abSAndroid Build Coastguard Worker   }
669*fb1b10abSAndroid Build Coastguard Worker   if (tl == 1) {
670*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->lst_fb_idx[0] = 0;
671*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->gld_fb_idx[0] = 1;
672*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->alt_fb_idx[0] = 2;
673*fb1b10abSAndroid Build Coastguard Worker 
674*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->lst_fb_idx[1] = 1;
675*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->gld_fb_idx[1] = 2;
676*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->alt_fb_idx[1] = 3;
677*fb1b10abSAndroid Build Coastguard Worker   }
678*fb1b10abSAndroid Build Coastguard Worker   // Set the reference and update flags.
679*fb1b10abSAndroid Build Coastguard Worker   if (tl == 0) {
680*fb1b10abSAndroid Build Coastguard Worker     // Base spatial and base temporal (sl = 0, tl = 0)
681*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_last[0] = 1;
682*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_golden[0] = 0;
683*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_alt_ref[0] = 0;
684*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->update_buffer_slot[0] |=
685*fb1b10abSAndroid Build Coastguard Worker         1 << ref_frame_config->lst_fb_idx[0];
686*fb1b10abSAndroid Build Coastguard Worker 
687*fb1b10abSAndroid Build Coastguard Worker     if (is_key_frame) {
688*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_last[1] = 1;
689*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_golden[1] = 0;
690*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_alt_ref[1] = 0;
691*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->update_buffer_slot[1] |=
692*fb1b10abSAndroid Build Coastguard Worker           1 << ref_frame_config->gld_fb_idx[1];
693*fb1b10abSAndroid Build Coastguard Worker     } else {
694*fb1b10abSAndroid Build Coastguard Worker       // Non-zero spatiall layer.
695*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_last[1] = 1;
696*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_golden[1] = 1;
697*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->reference_alt_ref[1] = 1;
698*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config->update_buffer_slot[1] |=
699*fb1b10abSAndroid Build Coastguard Worker           1 << ref_frame_config->lst_fb_idx[1];
700*fb1b10abSAndroid Build Coastguard Worker     }
701*fb1b10abSAndroid Build Coastguard Worker   }
702*fb1b10abSAndroid Build Coastguard Worker   if (tl == 1) {
703*fb1b10abSAndroid Build Coastguard Worker     // Top spatial and top temporal (non-reference -- doesn't update any
704*fb1b10abSAndroid Build Coastguard Worker     // reference buffers)
705*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_last[1] = 1;
706*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_golden[1] = 0;
707*fb1b10abSAndroid Build Coastguard Worker     ref_frame_config->reference_alt_ref[1] = 0;
708*fb1b10abSAndroid Build Coastguard Worker   }
709*fb1b10abSAndroid Build Coastguard Worker }
710*fb1b10abSAndroid Build Coastguard Worker 
711*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_DECODER && !SIMULCAST_MODE
test_decode(vpx_codec_ctx_t * encoder,vpx_codec_ctx_t * decoder,const int frames_out,int * mismatch_seen)712*fb1b10abSAndroid Build Coastguard Worker static void test_decode(vpx_codec_ctx_t *encoder, vpx_codec_ctx_t *decoder,
713*fb1b10abSAndroid Build Coastguard Worker                         const int frames_out, int *mismatch_seen) {
714*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t enc_img, dec_img;
715*fb1b10abSAndroid Build Coastguard Worker   struct vp9_ref_frame ref_enc, ref_dec;
716*fb1b10abSAndroid Build Coastguard Worker   if (*mismatch_seen) return;
717*fb1b10abSAndroid Build Coastguard Worker   /* Get the internal reference frame */
718*fb1b10abSAndroid Build Coastguard Worker   ref_enc.idx = 0;
719*fb1b10abSAndroid Build Coastguard Worker   ref_dec.idx = 0;
720*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(encoder, VP9_GET_REFERENCE, &ref_enc);
721*fb1b10abSAndroid Build Coastguard Worker   enc_img = ref_enc.img;
722*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(decoder, VP9_GET_REFERENCE, &ref_dec);
723*fb1b10abSAndroid Build Coastguard Worker   dec_img = ref_dec.img;
724*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
725*fb1b10abSAndroid Build Coastguard Worker   if ((enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) !=
726*fb1b10abSAndroid Build Coastguard Worker       (dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH)) {
727*fb1b10abSAndroid Build Coastguard Worker     if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
728*fb1b10abSAndroid Build Coastguard Worker       vpx_img_alloc(&enc_img, enc_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
729*fb1b10abSAndroid Build Coastguard Worker                     enc_img.d_w, enc_img.d_h, 16);
730*fb1b10abSAndroid Build Coastguard Worker       vpx_img_truncate_16_to_8(&enc_img, &ref_enc.img);
731*fb1b10abSAndroid Build Coastguard Worker     }
732*fb1b10abSAndroid Build Coastguard Worker     if (dec_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
733*fb1b10abSAndroid Build Coastguard Worker       vpx_img_alloc(&dec_img, dec_img.fmt - VPX_IMG_FMT_HIGHBITDEPTH,
734*fb1b10abSAndroid Build Coastguard Worker                     dec_img.d_w, dec_img.d_h, 16);
735*fb1b10abSAndroid Build Coastguard Worker       vpx_img_truncate_16_to_8(&dec_img, &ref_dec.img);
736*fb1b10abSAndroid Build Coastguard Worker     }
737*fb1b10abSAndroid Build Coastguard Worker   }
738*fb1b10abSAndroid Build Coastguard Worker #endif
739*fb1b10abSAndroid Build Coastguard Worker 
740*fb1b10abSAndroid Build Coastguard Worker   if (!compare_img(&enc_img, &dec_img)) {
741*fb1b10abSAndroid Build Coastguard Worker     int y[4], u[4], v[4];
742*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
743*fb1b10abSAndroid Build Coastguard Worker     if (enc_img.fmt & VPX_IMG_FMT_HIGHBITDEPTH) {
744*fb1b10abSAndroid Build Coastguard Worker       find_mismatch_high(&enc_img, &dec_img, y, u, v);
745*fb1b10abSAndroid Build Coastguard Worker     } else {
746*fb1b10abSAndroid Build Coastguard Worker       find_mismatch(&enc_img, &dec_img, y, u, v);
747*fb1b10abSAndroid Build Coastguard Worker     }
748*fb1b10abSAndroid Build Coastguard Worker #else
749*fb1b10abSAndroid Build Coastguard Worker     find_mismatch(&enc_img, &dec_img, y, u, v);
750*fb1b10abSAndroid Build Coastguard Worker #endif
751*fb1b10abSAndroid Build Coastguard Worker     decoder->err = 1;
752*fb1b10abSAndroid Build Coastguard Worker     printf(
753*fb1b10abSAndroid Build Coastguard Worker         "Encode/decode mismatch on frame %d at"
754*fb1b10abSAndroid Build Coastguard Worker         " Y[%d, %d] {%d/%d},"
755*fb1b10abSAndroid Build Coastguard Worker         " U[%d, %d] {%d/%d},"
756*fb1b10abSAndroid Build Coastguard Worker         " V[%d, %d] {%d/%d}\n",
757*fb1b10abSAndroid Build Coastguard Worker         frames_out, y[0], y[1], y[2], y[3], u[0], u[1], u[2], u[3], v[0], v[1],
758*fb1b10abSAndroid Build Coastguard Worker         v[2], v[3]);
759*fb1b10abSAndroid Build Coastguard Worker     *mismatch_seen = frames_out;
760*fb1b10abSAndroid Build Coastguard Worker   }
761*fb1b10abSAndroid Build Coastguard Worker 
762*fb1b10abSAndroid Build Coastguard Worker   vpx_img_free(&enc_img);
763*fb1b10abSAndroid Build Coastguard Worker   vpx_img_free(&dec_img);
764*fb1b10abSAndroid Build Coastguard Worker }
765*fb1b10abSAndroid Build Coastguard Worker #endif
766*fb1b10abSAndroid Build Coastguard Worker 
767*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
svc_output_rc_stats(vpx_codec_ctx_t * codec,vpx_codec_enc_cfg_t * enc_cfg,vpx_svc_layer_id_t * layer_id,const vpx_codec_cx_pkt_t * cx_pkt,struct RateControlStats * rc,VpxVideoWriter ** outfile,const uint32_t frame_cnt,const double framerate)768*fb1b10abSAndroid Build Coastguard Worker static void svc_output_rc_stats(
769*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_ctx_t *codec, vpx_codec_enc_cfg_t *enc_cfg,
770*fb1b10abSAndroid Build Coastguard Worker     vpx_svc_layer_id_t *layer_id, const vpx_codec_cx_pkt_t *cx_pkt,
771*fb1b10abSAndroid Build Coastguard Worker     struct RateControlStats *rc, VpxVideoWriter **outfile,
772*fb1b10abSAndroid Build Coastguard Worker     const uint32_t frame_cnt, const double framerate) {
773*fb1b10abSAndroid Build Coastguard Worker   int num_layers_encoded = 0;
774*fb1b10abSAndroid Build Coastguard Worker   unsigned int sl, tl;
775*fb1b10abSAndroid Build Coastguard Worker   uint64_t sizes[8];
776*fb1b10abSAndroid Build Coastguard Worker   uint64_t sizes_parsed[8];
777*fb1b10abSAndroid Build Coastguard Worker   int count = 0;
778*fb1b10abSAndroid Build Coastguard Worker   double sum_bitrate = 0.0;
779*fb1b10abSAndroid Build Coastguard Worker   double sum_bitrate2 = 0.0;
780*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(sizes);
781*fb1b10abSAndroid Build Coastguard Worker   vp9_zero(sizes_parsed);
782*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(codec, VP9E_GET_SVC_LAYER_ID, layer_id);
783*fb1b10abSAndroid Build Coastguard Worker   parse_superframe_index(cx_pkt->data.frame.buf, cx_pkt->data.frame.sz,
784*fb1b10abSAndroid Build Coastguard Worker                          sizes_parsed, &count);
785*fb1b10abSAndroid Build Coastguard Worker   if (enc_cfg->ss_number_layers == 1) {
786*fb1b10abSAndroid Build Coastguard Worker     sizes[0] = cx_pkt->data.frame.sz;
787*fb1b10abSAndroid Build Coastguard Worker   } else {
788*fb1b10abSAndroid Build Coastguard Worker     for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
789*fb1b10abSAndroid Build Coastguard Worker       sizes[sl] = 0;
790*fb1b10abSAndroid Build Coastguard Worker       if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
791*fb1b10abSAndroid Build Coastguard Worker         sizes[sl] = sizes_parsed[num_layers_encoded];
792*fb1b10abSAndroid Build Coastguard Worker         num_layers_encoded++;
793*fb1b10abSAndroid Build Coastguard Worker       }
794*fb1b10abSAndroid Build Coastguard Worker     }
795*fb1b10abSAndroid Build Coastguard Worker   }
796*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
797*fb1b10abSAndroid Build Coastguard Worker     unsigned int sl2;
798*fb1b10abSAndroid Build Coastguard Worker     uint64_t tot_size = 0;
799*fb1b10abSAndroid Build Coastguard Worker #if SIMULCAST_MODE
800*fb1b10abSAndroid Build Coastguard Worker     for (sl2 = 0; sl2 < sl; ++sl2) {
801*fb1b10abSAndroid Build Coastguard Worker       if (cx_pkt->data.frame.spatial_layer_encoded[sl2]) tot_size += sizes[sl2];
802*fb1b10abSAndroid Build Coastguard Worker     }
803*fb1b10abSAndroid Build Coastguard Worker     vpx_video_writer_write_frame(outfile[sl],
804*fb1b10abSAndroid Build Coastguard Worker                                  (uint8_t *)(cx_pkt->data.frame.buf) + tot_size,
805*fb1b10abSAndroid Build Coastguard Worker                                  (size_t)(sizes[sl]), cx_pkt->data.frame.pts);
806*fb1b10abSAndroid Build Coastguard Worker #else
807*fb1b10abSAndroid Build Coastguard Worker     for (sl2 = 0; sl2 <= sl; ++sl2) {
808*fb1b10abSAndroid Build Coastguard Worker       if (cx_pkt->data.frame.spatial_layer_encoded[sl2]) tot_size += sizes[sl2];
809*fb1b10abSAndroid Build Coastguard Worker     }
810*fb1b10abSAndroid Build Coastguard Worker     if (tot_size > 0)
811*fb1b10abSAndroid Build Coastguard Worker       vpx_video_writer_write_frame(outfile[sl], cx_pkt->data.frame.buf,
812*fb1b10abSAndroid Build Coastguard Worker                                    (size_t)(tot_size), cx_pkt->data.frame.pts);
813*fb1b10abSAndroid Build Coastguard Worker #endif  // SIMULCAST_MODE
814*fb1b10abSAndroid Build Coastguard Worker   }
815*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
816*fb1b10abSAndroid Build Coastguard Worker     if (cx_pkt->data.frame.spatial_layer_encoded[sl]) {
817*fb1b10abSAndroid Build Coastguard Worker       for (tl = layer_id->temporal_layer_id; tl < enc_cfg->ts_number_layers;
818*fb1b10abSAndroid Build Coastguard Worker            ++tl) {
819*fb1b10abSAndroid Build Coastguard Worker         const int layer = sl * enc_cfg->ts_number_layers + tl;
820*fb1b10abSAndroid Build Coastguard Worker         ++rc->layer_tot_enc_frames[layer];
821*fb1b10abSAndroid Build Coastguard Worker         rc->layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
822*fb1b10abSAndroid Build Coastguard Worker         // Keep count of rate control stats per layer, for non-key
823*fb1b10abSAndroid Build Coastguard Worker         // frames.
824*fb1b10abSAndroid Build Coastguard Worker         if (tl == (unsigned int)layer_id->temporal_layer_id &&
825*fb1b10abSAndroid Build Coastguard Worker             !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
826*fb1b10abSAndroid Build Coastguard Worker           rc->layer_avg_frame_size[layer] += 8.0 * sizes[sl];
827*fb1b10abSAndroid Build Coastguard Worker           rc->layer_avg_rate_mismatch[layer] +=
828*fb1b10abSAndroid Build Coastguard Worker               fabs(8.0 * sizes[sl] - rc->layer_pfb[layer]) /
829*fb1b10abSAndroid Build Coastguard Worker               rc->layer_pfb[layer];
830*fb1b10abSAndroid Build Coastguard Worker           ++rc->layer_enc_frames[layer];
831*fb1b10abSAndroid Build Coastguard Worker         }
832*fb1b10abSAndroid Build Coastguard Worker       }
833*fb1b10abSAndroid Build Coastguard Worker     }
834*fb1b10abSAndroid Build Coastguard Worker   }
835*fb1b10abSAndroid Build Coastguard Worker 
836*fb1b10abSAndroid Build Coastguard Worker   // Update for short-time encoding bitrate states, for moving
837*fb1b10abSAndroid Build Coastguard Worker   // window of size rc->window, shifted by rc->window / 2.
838*fb1b10abSAndroid Build Coastguard Worker   // Ignore first window segment, due to key frame.
839*fb1b10abSAndroid Build Coastguard Worker   if (frame_cnt > (unsigned int)rc->window_size) {
840*fb1b10abSAndroid Build Coastguard Worker     for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
841*fb1b10abSAndroid Build Coastguard Worker       if (cx_pkt->data.frame.spatial_layer_encoded[sl])
842*fb1b10abSAndroid Build Coastguard Worker         sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
843*fb1b10abSAndroid Build Coastguard Worker     }
844*fb1b10abSAndroid Build Coastguard Worker     if (frame_cnt % rc->window_size == 0) {
845*fb1b10abSAndroid Build Coastguard Worker       rc->window_count += 1;
846*fb1b10abSAndroid Build Coastguard Worker       rc->avg_st_encoding_bitrate += sum_bitrate / rc->window_size;
847*fb1b10abSAndroid Build Coastguard Worker       rc->variance_st_encoding_bitrate +=
848*fb1b10abSAndroid Build Coastguard Worker           (sum_bitrate / rc->window_size) * (sum_bitrate / rc->window_size);
849*fb1b10abSAndroid Build Coastguard Worker     }
850*fb1b10abSAndroid Build Coastguard Worker   }
851*fb1b10abSAndroid Build Coastguard Worker 
852*fb1b10abSAndroid Build Coastguard Worker   // Second shifted window.
853*fb1b10abSAndroid Build Coastguard Worker   if (frame_cnt > (unsigned int)(rc->window_size + rc->window_size / 2)) {
854*fb1b10abSAndroid Build Coastguard Worker     for (sl = 0; sl < enc_cfg->ss_number_layers; ++sl) {
855*fb1b10abSAndroid Build Coastguard Worker       sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
856*fb1b10abSAndroid Build Coastguard Worker     }
857*fb1b10abSAndroid Build Coastguard Worker 
858*fb1b10abSAndroid Build Coastguard Worker     if (frame_cnt > (unsigned int)(2 * rc->window_size) &&
859*fb1b10abSAndroid Build Coastguard Worker         frame_cnt % rc->window_size == 0) {
860*fb1b10abSAndroid Build Coastguard Worker       rc->window_count += 1;
861*fb1b10abSAndroid Build Coastguard Worker       rc->avg_st_encoding_bitrate += sum_bitrate2 / rc->window_size;
862*fb1b10abSAndroid Build Coastguard Worker       rc->variance_st_encoding_bitrate +=
863*fb1b10abSAndroid Build Coastguard Worker           (sum_bitrate2 / rc->window_size) * (sum_bitrate2 / rc->window_size);
864*fb1b10abSAndroid Build Coastguard Worker     }
865*fb1b10abSAndroid Build Coastguard Worker   }
866*fb1b10abSAndroid Build Coastguard Worker }
867*fb1b10abSAndroid Build Coastguard Worker #endif
868*fb1b10abSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)869*fb1b10abSAndroid Build Coastguard Worker int main(int argc, const char **argv) {
870*fb1b10abSAndroid Build Coastguard Worker   AppInput app_input;
871*fb1b10abSAndroid Build Coastguard Worker   VpxVideoWriter *writer = NULL;
872*fb1b10abSAndroid Build Coastguard Worker   VpxVideoInfo info;
873*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_ctx_t encoder;
874*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_enc_cfg_t enc_cfg;
875*fb1b10abSAndroid Build Coastguard Worker   SvcContext svc_ctx;
876*fb1b10abSAndroid Build Coastguard Worker   vpx_svc_frame_drop_t svc_drop_frame;
877*fb1b10abSAndroid Build Coastguard Worker   uint32_t i;
878*fb1b10abSAndroid Build Coastguard Worker   uint32_t frame_cnt = 0;
879*fb1b10abSAndroid Build Coastguard Worker   vpx_image_t raw;
880*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_err_t res;
881*fb1b10abSAndroid Build Coastguard Worker   int pts = 0;            /* PTS starts at 0 */
882*fb1b10abSAndroid Build Coastguard Worker   int frame_duration = 1; /* 1 timebase tick per frame */
883*fb1b10abSAndroid Build Coastguard Worker   int end_of_stream = 0;
884*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_FRAME_STATS
885*fb1b10abSAndroid Build Coastguard Worker   int frames_received = 0;
886*fb1b10abSAndroid Build Coastguard Worker #endif
887*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
888*fb1b10abSAndroid Build Coastguard Worker   VpxVideoWriter *outfile[VPX_SS_MAX_LAYERS] = { NULL };
889*fb1b10abSAndroid Build Coastguard Worker   struct RateControlStats rc;
890*fb1b10abSAndroid Build Coastguard Worker   vpx_svc_layer_id_t layer_id;
891*fb1b10abSAndroid Build Coastguard Worker   vpx_svc_ref_frame_config_t ref_frame_config;
892*fb1b10abSAndroid Build Coastguard Worker   unsigned int sl;
893*fb1b10abSAndroid Build Coastguard Worker   double framerate = 30.0;
894*fb1b10abSAndroid Build Coastguard Worker #endif
895*fb1b10abSAndroid Build Coastguard Worker   struct vpx_usec_timer timer;
896*fb1b10abSAndroid Build Coastguard Worker   int64_t cx_time = 0;
897*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
898*fb1b10abSAndroid Build Coastguard Worker   FILE *f = fopen("opsnr.stt", "a");
899*fb1b10abSAndroid Build Coastguard Worker #endif
900*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_DECODER && !SIMULCAST_MODE
901*fb1b10abSAndroid Build Coastguard Worker   int mismatch_seen = 0;
902*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_ctx_t decoder;
903*fb1b10abSAndroid Build Coastguard Worker #endif
904*fb1b10abSAndroid Build Coastguard Worker   memset(&svc_ctx, 0, sizeof(svc_ctx));
905*fb1b10abSAndroid Build Coastguard Worker   memset(&app_input, 0, sizeof(AppInput));
906*fb1b10abSAndroid Build Coastguard Worker   memset(&info, 0, sizeof(VpxVideoInfo));
907*fb1b10abSAndroid Build Coastguard Worker   memset(&layer_id, 0, sizeof(vpx_svc_layer_id_t));
908*fb1b10abSAndroid Build Coastguard Worker   memset(&rc, 0, sizeof(struct RateControlStats));
909*fb1b10abSAndroid Build Coastguard Worker   exec_name = argv[0];
910*fb1b10abSAndroid Build Coastguard Worker 
911*fb1b10abSAndroid Build Coastguard Worker   /* Setup default input stream settings */
912*fb1b10abSAndroid Build Coastguard Worker   app_input.input_ctx.framerate.numerator = 30;
913*fb1b10abSAndroid Build Coastguard Worker   app_input.input_ctx.framerate.denominator = 1;
914*fb1b10abSAndroid Build Coastguard Worker   app_input.input_ctx.only_i420 = 1;
915*fb1b10abSAndroid Build Coastguard Worker   app_input.input_ctx.bit_depth = 0;
916*fb1b10abSAndroid Build Coastguard Worker 
917*fb1b10abSAndroid Build Coastguard Worker   parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
918*fb1b10abSAndroid Build Coastguard Worker 
919*fb1b10abSAndroid Build Coastguard Worker   // Y4M reader handles its own allocation.
920*fb1b10abSAndroid Build Coastguard Worker   if (app_input.input_ctx.file_type != FILE_TYPE_Y4M) {
921*fb1b10abSAndroid Build Coastguard Worker // Allocate image buffer
922*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_HIGHBITDEPTH
923*fb1b10abSAndroid Build Coastguard Worker     if (!vpx_img_alloc(&raw,
924*fb1b10abSAndroid Build Coastguard Worker                        enc_cfg.g_input_bit_depth == 8 ? VPX_IMG_FMT_I420
925*fb1b10abSAndroid Build Coastguard Worker                                                       : VPX_IMG_FMT_I42016,
926*fb1b10abSAndroid Build Coastguard Worker                        enc_cfg.g_w, enc_cfg.g_h, 32)) {
927*fb1b10abSAndroid Build Coastguard Worker       die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
928*fb1b10abSAndroid Build Coastguard Worker     }
929*fb1b10abSAndroid Build Coastguard Worker #else
930*fb1b10abSAndroid Build Coastguard Worker     if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) {
931*fb1b10abSAndroid Build Coastguard Worker       die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
932*fb1b10abSAndroid Build Coastguard Worker     }
933*fb1b10abSAndroid Build Coastguard Worker #endif  // CONFIG_VP9_HIGHBITDEPTH
934*fb1b10abSAndroid Build Coastguard Worker   }
935*fb1b10abSAndroid Build Coastguard Worker 
936*fb1b10abSAndroid Build Coastguard Worker   // Initialize codec
937*fb1b10abSAndroid Build Coastguard Worker   if (vpx_svc_init(&svc_ctx, &encoder, vpx_codec_vp9_cx(), &enc_cfg) !=
938*fb1b10abSAndroid Build Coastguard Worker       VPX_CODEC_OK)
939*fb1b10abSAndroid Build Coastguard Worker     die("Failed to initialize encoder\n");
940*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_DECODER && !SIMULCAST_MODE
941*fb1b10abSAndroid Build Coastguard Worker   if (vpx_codec_dec_init(
942*fb1b10abSAndroid Build Coastguard Worker           &decoder, get_vpx_decoder_by_name("vp9")->codec_interface(), NULL, 0))
943*fb1b10abSAndroid Build Coastguard Worker     die("Failed to initialize decoder\n");
944*fb1b10abSAndroid Build Coastguard Worker #endif
945*fb1b10abSAndroid Build Coastguard Worker 
946*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
947*fb1b10abSAndroid Build Coastguard Worker   rc.window_count = 1;
948*fb1b10abSAndroid Build Coastguard Worker   rc.window_size = 15;  // Silence a static analysis warning.
949*fb1b10abSAndroid Build Coastguard Worker   rc.avg_st_encoding_bitrate = 0.0;
950*fb1b10abSAndroid Build Coastguard Worker   rc.variance_st_encoding_bitrate = 0.0;
951*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.output_rc_stat) {
952*fb1b10abSAndroid Build Coastguard Worker     set_rate_control_stats(&rc, &enc_cfg);
953*fb1b10abSAndroid Build Coastguard Worker     framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
954*fb1b10abSAndroid Build Coastguard Worker   }
955*fb1b10abSAndroid Build Coastguard Worker #endif
956*fb1b10abSAndroid Build Coastguard Worker 
957*fb1b10abSAndroid Build Coastguard Worker   info.codec_fourcc = VP9_FOURCC;
958*fb1b10abSAndroid Build Coastguard Worker   info.frame_width = enc_cfg.g_w;
959*fb1b10abSAndroid Build Coastguard Worker   info.frame_height = enc_cfg.g_h;
960*fb1b10abSAndroid Build Coastguard Worker   info.time_base.numerator = enc_cfg.g_timebase.num;
961*fb1b10abSAndroid Build Coastguard Worker   info.time_base.denominator = enc_cfg.g_timebase.den;
962*fb1b10abSAndroid Build Coastguard Worker 
963*fb1b10abSAndroid Build Coastguard Worker   writer =
964*fb1b10abSAndroid Build Coastguard Worker       vpx_video_writer_open(app_input.output_filename, kContainerIVF, &info);
965*fb1b10abSAndroid Build Coastguard Worker   if (!writer)
966*fb1b10abSAndroid Build Coastguard Worker     die("Failed to open %s for writing\n", app_input.output_filename);
967*fb1b10abSAndroid Build Coastguard Worker 
968*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
969*fb1b10abSAndroid Build Coastguard Worker   // Write out spatial layer stream.
970*fb1b10abSAndroid Build Coastguard Worker   // TODO(marpan/jianj): allow for writing each spatial and temporal stream.
971*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.output_rc_stat) {
972*fb1b10abSAndroid Build Coastguard Worker     for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
973*fb1b10abSAndroid Build Coastguard Worker       char file_name[PATH_MAX];
974*fb1b10abSAndroid Build Coastguard Worker 
975*fb1b10abSAndroid Build Coastguard Worker       snprintf(file_name, sizeof(file_name), "%s_s%d.ivf",
976*fb1b10abSAndroid Build Coastguard Worker                app_input.output_filename, sl);
977*fb1b10abSAndroid Build Coastguard Worker       outfile[sl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
978*fb1b10abSAndroid Build Coastguard Worker       if (!outfile[sl]) die("Failed to open %s for writing", file_name);
979*fb1b10abSAndroid Build Coastguard Worker     }
980*fb1b10abSAndroid Build Coastguard Worker   }
981*fb1b10abSAndroid Build Coastguard Worker #endif
982*fb1b10abSAndroid Build Coastguard Worker 
983*fb1b10abSAndroid Build Coastguard Worker   // skip initial frames
984*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < app_input.frames_to_skip; ++i)
985*fb1b10abSAndroid Build Coastguard Worker     read_frame(&app_input.input_ctx, &raw);
986*fb1b10abSAndroid Build Coastguard Worker 
987*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.speed != -1)
988*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_control(&encoder, VP8E_SET_CPUUSED, svc_ctx.speed);
989*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.threads) {
990*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_control(&encoder, VP9E_SET_TILE_COLUMNS,
991*fb1b10abSAndroid Build Coastguard Worker                       get_msb(svc_ctx.threads));
992*fb1b10abSAndroid Build Coastguard Worker     if (svc_ctx.threads > 1)
993*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_control(&encoder, VP9E_SET_ROW_MT, 1);
994*fb1b10abSAndroid Build Coastguard Worker     else
995*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_control(&encoder, VP9E_SET_ROW_MT, 0);
996*fb1b10abSAndroid Build Coastguard Worker   }
997*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
998*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_control(&encoder, VP9E_SET_AQ_MODE, 3);
999*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.speed >= 5)
1000*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_control(&encoder, VP8E_SET_STATIC_THRESHOLD, 1);
1001*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP8E_SET_MAX_INTRA_BITRATE_PCT, 900);
1002*fb1b10abSAndroid Build Coastguard Worker 
1003*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_SVC_INTER_LAYER_PRED,
1004*fb1b10abSAndroid Build Coastguard Worker                     app_input.inter_layer_pred);
1005*fb1b10abSAndroid Build Coastguard Worker 
1006*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_NOISE_SENSITIVITY, 0);
1007*fb1b10abSAndroid Build Coastguard Worker 
1008*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_TUNE_CONTENT, app_input.tune_content);
1009*fb1b10abSAndroid Build Coastguard Worker 
1010*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR, 0);
1011*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_DISABLE_LOOPFILTER, 0);
1012*fb1b10abSAndroid Build Coastguard Worker 
1013*fb1b10abSAndroid Build Coastguard Worker   svc_drop_frame.framedrop_mode = FULL_SUPERFRAME_DROP;
1014*fb1b10abSAndroid Build Coastguard Worker   for (sl = 0; sl < (unsigned int)svc_ctx.spatial_layers; ++sl)
1015*fb1b10abSAndroid Build Coastguard Worker     svc_drop_frame.framedrop_thresh[sl] = enc_cfg.rc_dropframe_thresh;
1016*fb1b10abSAndroid Build Coastguard Worker   svc_drop_frame.max_consec_drop = INT_MAX;
1017*fb1b10abSAndroid Build Coastguard Worker   vpx_codec_control(&encoder, VP9E_SET_SVC_FRAME_DROP_LAYER, &svc_drop_frame);
1018*fb1b10abSAndroid Build Coastguard Worker 
1019*fb1b10abSAndroid Build Coastguard Worker   // Encode frames
1020*fb1b10abSAndroid Build Coastguard Worker   while (!end_of_stream) {
1021*fb1b10abSAndroid Build Coastguard Worker     vpx_codec_iter_t iter = NULL;
1022*fb1b10abSAndroid Build Coastguard Worker     const vpx_codec_cx_pkt_t *cx_pkt;
1023*fb1b10abSAndroid Build Coastguard Worker     // Example patterns for bypass/flexible mode:
1024*fb1b10abSAndroid Build Coastguard Worker     // example_pattern = 0: 2 temporal layers, and spatial_layers = 1,2,3. Exact
1025*fb1b10abSAndroid Build Coastguard Worker     // to fixed SVC patterns. example_pattern = 1: 2 spatial and 2 temporal
1026*fb1b10abSAndroid Build Coastguard Worker     // layers, with SL0 only has TL0, and SL1 has both TL0 and TL1. This example
1027*fb1b10abSAndroid Build Coastguard Worker     // uses the extended API.
1028*fb1b10abSAndroid Build Coastguard Worker     int example_pattern = 0;
1029*fb1b10abSAndroid Build Coastguard Worker     if (frame_cnt >= app_input.frames_to_code ||
1030*fb1b10abSAndroid Build Coastguard Worker         !read_frame(&app_input.input_ctx, &raw)) {
1031*fb1b10abSAndroid Build Coastguard Worker       // We need one extra vpx_svc_encode call at end of stream to flush
1032*fb1b10abSAndroid Build Coastguard Worker       // encoder and get remaining data
1033*fb1b10abSAndroid Build Coastguard Worker       end_of_stream = 1;
1034*fb1b10abSAndroid Build Coastguard Worker     }
1035*fb1b10abSAndroid Build Coastguard Worker 
1036*fb1b10abSAndroid Build Coastguard Worker     // For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
1037*fb1b10abSAndroid Build Coastguard Worker     // and the buffer indices for each spatial layer of the current
1038*fb1b10abSAndroid Build Coastguard Worker     // (super)frame to be encoded. The spatial and temporal layer_id for the
1039*fb1b10abSAndroid Build Coastguard Worker     // current frame also needs to be set.
1040*fb1b10abSAndroid Build Coastguard Worker     // TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
1041*fb1b10abSAndroid Build Coastguard Worker     // mode to "VP9E_LAYERING_MODE_BYPASS".
1042*fb1b10abSAndroid Build Coastguard Worker     if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
1043*fb1b10abSAndroid Build Coastguard Worker       layer_id.spatial_layer_id = 0;
1044*fb1b10abSAndroid Build Coastguard Worker       // Example for 2 temporal layers.
1045*fb1b10abSAndroid Build Coastguard Worker       if (frame_cnt % 2 == 0) {
1046*fb1b10abSAndroid Build Coastguard Worker         layer_id.temporal_layer_id = 0;
1047*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < VPX_SS_MAX_LAYERS; i++)
1048*fb1b10abSAndroid Build Coastguard Worker           layer_id.temporal_layer_id_per_spatial[i] = 0;
1049*fb1b10abSAndroid Build Coastguard Worker       } else {
1050*fb1b10abSAndroid Build Coastguard Worker         layer_id.temporal_layer_id = 1;
1051*fb1b10abSAndroid Build Coastguard Worker         for (i = 0; i < VPX_SS_MAX_LAYERS; i++)
1052*fb1b10abSAndroid Build Coastguard Worker           layer_id.temporal_layer_id_per_spatial[i] = 1;
1053*fb1b10abSAndroid Build Coastguard Worker       }
1054*fb1b10abSAndroid Build Coastguard Worker       if (example_pattern == 1) {
1055*fb1b10abSAndroid Build Coastguard Worker         // example_pattern 1 is hard-coded for 2 spatial and 2 temporal layers.
1056*fb1b10abSAndroid Build Coastguard Worker         assert(svc_ctx.spatial_layers == 2);
1057*fb1b10abSAndroid Build Coastguard Worker         assert(svc_ctx.temporal_layers == 2);
1058*fb1b10abSAndroid Build Coastguard Worker         if (frame_cnt % 2 == 0) {
1059*fb1b10abSAndroid Build Coastguard Worker           // Spatial layer 0 and 1 are encoded.
1060*fb1b10abSAndroid Build Coastguard Worker           layer_id.temporal_layer_id_per_spatial[0] = 0;
1061*fb1b10abSAndroid Build Coastguard Worker           layer_id.temporal_layer_id_per_spatial[1] = 0;
1062*fb1b10abSAndroid Build Coastguard Worker           layer_id.spatial_layer_id = 0;
1063*fb1b10abSAndroid Build Coastguard Worker         } else {
1064*fb1b10abSAndroid Build Coastguard Worker           // Only spatial layer 1 is encoded here.
1065*fb1b10abSAndroid Build Coastguard Worker           layer_id.temporal_layer_id_per_spatial[1] = 1;
1066*fb1b10abSAndroid Build Coastguard Worker           layer_id.spatial_layer_id = 1;
1067*fb1b10abSAndroid Build Coastguard Worker         }
1068*fb1b10abSAndroid Build Coastguard Worker       }
1069*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_control(&encoder, VP9E_SET_SVC_LAYER_ID, &layer_id);
1070*fb1b10abSAndroid Build Coastguard Worker       // TODO(jianj): Fix the parameter passing for "is_key_frame" in
1071*fb1b10abSAndroid Build Coastguard Worker       // set_frame_flags_bypass_model() for case of periodic key frames.
1072*fb1b10abSAndroid Build Coastguard Worker       if (example_pattern == 0) {
1073*fb1b10abSAndroid Build Coastguard Worker         set_frame_flags_bypass_mode_ex0(layer_id.temporal_layer_id,
1074*fb1b10abSAndroid Build Coastguard Worker                                         svc_ctx.spatial_layers, frame_cnt == 0,
1075*fb1b10abSAndroid Build Coastguard Worker                                         &ref_frame_config);
1076*fb1b10abSAndroid Build Coastguard Worker       } else if (example_pattern == 1) {
1077*fb1b10abSAndroid Build Coastguard Worker         set_frame_flags_bypass_mode_ex1(layer_id.temporal_layer_id,
1078*fb1b10abSAndroid Build Coastguard Worker                                         svc_ctx.spatial_layers, frame_cnt == 0,
1079*fb1b10abSAndroid Build Coastguard Worker                                         &ref_frame_config);
1080*fb1b10abSAndroid Build Coastguard Worker       }
1081*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config.duration[0] = frame_duration * 1;
1082*fb1b10abSAndroid Build Coastguard Worker       ref_frame_config.duration[1] = frame_duration * 1;
1083*fb1b10abSAndroid Build Coastguard Worker 
1084*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_control(&encoder, VP9E_SET_SVC_REF_FRAME_CONFIG,
1085*fb1b10abSAndroid Build Coastguard Worker                         &ref_frame_config);
1086*fb1b10abSAndroid Build Coastguard Worker       // Keep track of input frames, to account for frame drops in rate control
1087*fb1b10abSAndroid Build Coastguard Worker       // stats/metrics.
1088*fb1b10abSAndroid Build Coastguard Worker       for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
1089*fb1b10abSAndroid Build Coastguard Worker         ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
1090*fb1b10abSAndroid Build Coastguard Worker                                 layer_id.temporal_layer_id];
1091*fb1b10abSAndroid Build Coastguard Worker       }
1092*fb1b10abSAndroid Build Coastguard Worker     } else {
1093*fb1b10abSAndroid Build Coastguard Worker       // For the fixed pattern SVC, temporal layer is given by superframe count.
1094*fb1b10abSAndroid Build Coastguard Worker       unsigned int tl = 0;
1095*fb1b10abSAndroid Build Coastguard Worker       if (enc_cfg.ts_number_layers == 2)
1096*fb1b10abSAndroid Build Coastguard Worker         tl = (frame_cnt % 2 != 0);
1097*fb1b10abSAndroid Build Coastguard Worker       else if (enc_cfg.ts_number_layers == 3) {
1098*fb1b10abSAndroid Build Coastguard Worker         if (frame_cnt % 2 != 0) tl = 2;
1099*fb1b10abSAndroid Build Coastguard Worker         if ((frame_cnt > 1) && ((frame_cnt - 2) % 4 == 0)) tl = 1;
1100*fb1b10abSAndroid Build Coastguard Worker       }
1101*fb1b10abSAndroid Build Coastguard Worker       for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl)
1102*fb1b10abSAndroid Build Coastguard Worker         ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers + tl];
1103*fb1b10abSAndroid Build Coastguard Worker     }
1104*fb1b10abSAndroid Build Coastguard Worker 
1105*fb1b10abSAndroid Build Coastguard Worker     vpx_usec_timer_start(&timer);
1106*fb1b10abSAndroid Build Coastguard Worker     res = vpx_svc_encode(
1107*fb1b10abSAndroid Build Coastguard Worker         &svc_ctx, &encoder, (end_of_stream ? NULL : &raw), pts, frame_duration,
1108*fb1b10abSAndroid Build Coastguard Worker         svc_ctx.speed >= 5 ? VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
1109*fb1b10abSAndroid Build Coastguard Worker     vpx_usec_timer_mark(&timer);
1110*fb1b10abSAndroid Build Coastguard Worker     cx_time += vpx_usec_timer_elapsed(&timer);
1111*fb1b10abSAndroid Build Coastguard Worker 
1112*fb1b10abSAndroid Build Coastguard Worker     fflush(stdout);
1113*fb1b10abSAndroid Build Coastguard Worker     if (res != VPX_CODEC_OK) {
1114*fb1b10abSAndroid Build Coastguard Worker       die_codec(&encoder, "Failed to encode frame");
1115*fb1b10abSAndroid Build Coastguard Worker     }
1116*fb1b10abSAndroid Build Coastguard Worker 
1117*fb1b10abSAndroid Build Coastguard Worker     while ((cx_pkt = vpx_codec_get_cx_data(&encoder, &iter)) != NULL) {
1118*fb1b10abSAndroid Build Coastguard Worker       switch (cx_pkt->kind) {
1119*fb1b10abSAndroid Build Coastguard Worker         case VPX_CODEC_CX_FRAME_PKT: {
1120*fb1b10abSAndroid Build Coastguard Worker           SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
1121*fb1b10abSAndroid Build Coastguard Worker           if (cx_pkt->data.frame.sz > 0) {
1122*fb1b10abSAndroid Build Coastguard Worker             vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf,
1123*fb1b10abSAndroid Build Coastguard Worker                                          cx_pkt->data.frame.sz,
1124*fb1b10abSAndroid Build Coastguard Worker                                          cx_pkt->data.frame.pts);
1125*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
1126*fb1b10abSAndroid Build Coastguard Worker             if (svc_ctx.output_rc_stat) {
1127*fb1b10abSAndroid Build Coastguard Worker               svc_output_rc_stats(&encoder, &enc_cfg, &layer_id, cx_pkt, &rc,
1128*fb1b10abSAndroid Build Coastguard Worker                                   outfile, frame_cnt, framerate);
1129*fb1b10abSAndroid Build Coastguard Worker             }
1130*fb1b10abSAndroid Build Coastguard Worker #endif
1131*fb1b10abSAndroid Build Coastguard Worker           }
1132*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_FRAME_STATS
1133*fb1b10abSAndroid Build Coastguard Worker           printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
1134*fb1b10abSAndroid Build Coastguard Worker                  !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
1135*fb1b10abSAndroid Build Coastguard Worker                  (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
1136*fb1b10abSAndroid Build Coastguard Worker           ++frames_received;
1137*fb1b10abSAndroid Build Coastguard Worker #endif
1138*fb1b10abSAndroid Build Coastguard Worker           if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1)
1139*fb1b10abSAndroid Build Coastguard Worker             si->bytes_sum[0] += (int)cx_pkt->data.frame.sz;
1140*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_DECODER && !SIMULCAST_MODE
1141*fb1b10abSAndroid Build Coastguard Worker           if (vpx_codec_decode(&decoder, cx_pkt->data.frame.buf,
1142*fb1b10abSAndroid Build Coastguard Worker                                (unsigned int)cx_pkt->data.frame.sz, NULL, 0))
1143*fb1b10abSAndroid Build Coastguard Worker             die_codec(&decoder, "Failed to decode frame.");
1144*fb1b10abSAndroid Build Coastguard Worker #endif
1145*fb1b10abSAndroid Build Coastguard Worker           break;
1146*fb1b10abSAndroid Build Coastguard Worker         }
1147*fb1b10abSAndroid Build Coastguard Worker         case VPX_CODEC_STATS_PKT: {
1148*fb1b10abSAndroid Build Coastguard Worker           stats_write(&app_input.rc_stats, cx_pkt->data.twopass_stats.buf,
1149*fb1b10abSAndroid Build Coastguard Worker                       cx_pkt->data.twopass_stats.sz);
1150*fb1b10abSAndroid Build Coastguard Worker           break;
1151*fb1b10abSAndroid Build Coastguard Worker         }
1152*fb1b10abSAndroid Build Coastguard Worker         default: {
1153*fb1b10abSAndroid Build Coastguard Worker           break;
1154*fb1b10abSAndroid Build Coastguard Worker         }
1155*fb1b10abSAndroid Build Coastguard Worker       }
1156*fb1b10abSAndroid Build Coastguard Worker 
1157*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_VP9_DECODER && !SIMULCAST_MODE
1158*fb1b10abSAndroid Build Coastguard Worker       vpx_codec_control(&encoder, VP9E_GET_SVC_LAYER_ID, &layer_id);
1159*fb1b10abSAndroid Build Coastguard Worker       // Don't look for mismatch on top spatial and top temporal layers as they
1160*fb1b10abSAndroid Build Coastguard Worker       // are non reference frames. Don't look at frames whose top spatial layer
1161*fb1b10abSAndroid Build Coastguard Worker       // is dropped.
1162*fb1b10abSAndroid Build Coastguard Worker       if ((enc_cfg.ss_number_layers > 1 || enc_cfg.ts_number_layers > 1) &&
1163*fb1b10abSAndroid Build Coastguard Worker           cx_pkt->data.frame
1164*fb1b10abSAndroid Build Coastguard Worker               .spatial_layer_encoded[enc_cfg.ss_number_layers - 1] &&
1165*fb1b10abSAndroid Build Coastguard Worker           !(layer_id.temporal_layer_id > 0 &&
1166*fb1b10abSAndroid Build Coastguard Worker             layer_id.temporal_layer_id == (int)enc_cfg.ts_number_layers - 1)) {
1167*fb1b10abSAndroid Build Coastguard Worker         test_decode(&encoder, &decoder, frame_cnt, &mismatch_seen);
1168*fb1b10abSAndroid Build Coastguard Worker       }
1169*fb1b10abSAndroid Build Coastguard Worker #endif
1170*fb1b10abSAndroid Build Coastguard Worker     }
1171*fb1b10abSAndroid Build Coastguard Worker 
1172*fb1b10abSAndroid Build Coastguard Worker     if (!end_of_stream) {
1173*fb1b10abSAndroid Build Coastguard Worker       ++frame_cnt;
1174*fb1b10abSAndroid Build Coastguard Worker       pts += frame_duration;
1175*fb1b10abSAndroid Build Coastguard Worker     }
1176*fb1b10abSAndroid Build Coastguard Worker   }
1177*fb1b10abSAndroid Build Coastguard Worker 
1178*fb1b10abSAndroid Build Coastguard Worker   printf("Processed %d frames\n", frame_cnt);
1179*fb1b10abSAndroid Build Coastguard Worker 
1180*fb1b10abSAndroid Build Coastguard Worker   close_input_file(&app_input.input_ctx);
1181*fb1b10abSAndroid Build Coastguard Worker 
1182*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
1183*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.output_rc_stat) {
1184*fb1b10abSAndroid Build Coastguard Worker     printout_rate_control_summary(&rc, &enc_cfg, frame_cnt);
1185*fb1b10abSAndroid Build Coastguard Worker     printf("\n");
1186*fb1b10abSAndroid Build Coastguard Worker   }
1187*fb1b10abSAndroid Build Coastguard Worker #endif
1188*fb1b10abSAndroid Build Coastguard Worker   if (vpx_codec_destroy(&encoder))
1189*fb1b10abSAndroid Build Coastguard Worker     die_codec(&encoder, "Failed to destroy codec");
1190*fb1b10abSAndroid Build Coastguard Worker   if (writer) {
1191*fb1b10abSAndroid Build Coastguard Worker     vpx_video_writer_close(writer);
1192*fb1b10abSAndroid Build Coastguard Worker   }
1193*fb1b10abSAndroid Build Coastguard Worker #if OUTPUT_RC_STATS
1194*fb1b10abSAndroid Build Coastguard Worker   if (svc_ctx.output_rc_stat) {
1195*fb1b10abSAndroid Build Coastguard Worker     for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
1196*fb1b10abSAndroid Build Coastguard Worker       vpx_video_writer_close(outfile[sl]);
1197*fb1b10abSAndroid Build Coastguard Worker     }
1198*fb1b10abSAndroid Build Coastguard Worker   }
1199*fb1b10abSAndroid Build Coastguard Worker #endif
1200*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_INTERNAL_STATS
1201*fb1b10abSAndroid Build Coastguard Worker   if (mismatch_seen) {
1202*fb1b10abSAndroid Build Coastguard Worker     fprintf(f, "First mismatch occurred in frame %d\n", mismatch_seen);
1203*fb1b10abSAndroid Build Coastguard Worker   } else {
1204*fb1b10abSAndroid Build Coastguard Worker     fprintf(f, "No mismatch detected in recon buffers\n");
1205*fb1b10abSAndroid Build Coastguard Worker   }
1206*fb1b10abSAndroid Build Coastguard Worker   fclose(f);
1207*fb1b10abSAndroid Build Coastguard Worker #endif
1208*fb1b10abSAndroid Build Coastguard Worker   printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
1209*fb1b10abSAndroid Build Coastguard Worker          frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
1210*fb1b10abSAndroid Build Coastguard Worker          1000000 * (double)frame_cnt / (double)cx_time);
1211*fb1b10abSAndroid Build Coastguard Worker   if (app_input.input_ctx.file_type != FILE_TYPE_Y4M) {
1212*fb1b10abSAndroid Build Coastguard Worker     vpx_img_free(&raw);
1213*fb1b10abSAndroid Build Coastguard Worker   }
1214*fb1b10abSAndroid Build Coastguard Worker   // display average size, psnr
1215*fb1b10abSAndroid Build Coastguard Worker   vpx_svc_dump_statistics(&svc_ctx);
1216*fb1b10abSAndroid Build Coastguard Worker   vpx_svc_release(&svc_ctx);
1217*fb1b10abSAndroid Build Coastguard Worker   return EXIT_SUCCESS;
1218*fb1b10abSAndroid Build Coastguard Worker }
1219