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