WebM Codec SDK
vp9_spatial_svc_encoder
1 /*
2  * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
3  *
4  * Use of this source code is governed by a BSD-style license
5  * that can be found in the LICENSE file in the root of the source
6  * tree. An additional intellectual property rights grant can be found
7  * in the file PATENTS. All contributing project authors may
8  * be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 /*
12  * This is an example demonstrating how to implement a multi-layer
13  * VP9 encoding scheme based on spatial scalability for video applications
14  * that benefit from a scalable bitstream.
15  */
16 
17 #include <math.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 
23 #include "../args.h"
24 #include "../tools_common.h"
25 #include "../video_writer.h"
26 
27 #include "../vpx_ports/vpx_timer.h"
28 #include "vpx/svc_context.h"
29 #include "vpx/vp8cx.h"
30 #include "vpx/vpx_encoder.h"
31 #include "../vpxstats.h"
32 #include "vp9/encoder/vp9_encoder.h"
33 #define OUTPUT_RC_STATS 1
34 
35 static const arg_def_t skip_frames_arg =
36  ARG_DEF("s", "skip-frames", 1, "input frames to skip");
37 static const arg_def_t frames_arg =
38  ARG_DEF("f", "frames", 1, "number of frames to encode");
39 static const arg_def_t threads_arg =
40  ARG_DEF("th", "threads", 1, "number of threads to use");
41 #if OUTPUT_RC_STATS
42 static const arg_def_t output_rc_stats_arg =
43  ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats");
44 #endif
45 static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
46 static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
47 static const arg_def_t timebase_arg =
48  ARG_DEF("t", "timebase", 1, "timebase (num/den)");
49 static const arg_def_t bitrate_arg = ARG_DEF(
50  "b", "target-bitrate", 1, "encoding bitrate, in kilobits per second");
51 static const arg_def_t spatial_layers_arg =
52  ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
53 static const arg_def_t temporal_layers_arg =
54  ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
55 static const arg_def_t temporal_layering_mode_arg =
56  ARG_DEF("tlm", "temporal-layering-mode", 1,
57  "temporal layering scheme."
58  "VP9E_TEMPORAL_LAYERING_MODE");
59 static const arg_def_t kf_dist_arg =
60  ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
61 static const arg_def_t scale_factors_arg =
62  ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)");
63 static const arg_def_t passes_arg =
64  ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
65 static const arg_def_t pass_arg =
66  ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)");
67 static const arg_def_t fpf_name_arg =
68  ARG_DEF(NULL, "fpf", 1, "First pass statistics file name");
69 static const arg_def_t min_q_arg =
70  ARG_DEF(NULL, "min-q", 1, "Minimum quantizer");
71 static const arg_def_t max_q_arg =
72  ARG_DEF(NULL, "max-q", 1, "Maximum quantizer");
73 static const arg_def_t min_bitrate_arg =
74  ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate");
75 static const arg_def_t max_bitrate_arg =
76  ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate");
77 static const arg_def_t lag_in_frame_arg =
78  ARG_DEF(NULL, "lag-in-frames", 1,
79  "Number of frame to input before "
80  "generating any outputs");
81 static const arg_def_t rc_end_usage_arg =
82  ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
83 static const arg_def_t speed_arg =
84  ARG_DEF("sp", "speed", 1, "speed configuration");
85 static const arg_def_t aqmode_arg =
86  ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
87 static const arg_def_t bitrates_arg =
88  ARG_DEF("bl", "bitrates", 1, "bitrates[sl * num_tl + tl]");
89 
90 #if CONFIG_VP9_HIGHBITDEPTH
91 static const struct arg_enum_list bitdepth_enum[] = {
92  { "8", VPX_BITS_8 }, { "10", VPX_BITS_10 }, { "12", VPX_BITS_12 }, { NULL, 0 }
93 };
94 
95 static const arg_def_t bitdepth_arg = ARG_DEF_ENUM(
96  "d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ", bitdepth_enum);
97 #endif // CONFIG_VP9_HIGHBITDEPTH
98 
99 static const arg_def_t *svc_args[] = { &frames_arg,
100  &width_arg,
101  &height_arg,
102  &timebase_arg,
103  &bitrate_arg,
104  &skip_frames_arg,
105  &spatial_layers_arg,
106  &kf_dist_arg,
107  &scale_factors_arg,
108  &passes_arg,
109  &pass_arg,
110  &fpf_name_arg,
111  &min_q_arg,
112  &max_q_arg,
113  &min_bitrate_arg,
114  &max_bitrate_arg,
115  &temporal_layers_arg,
116  &temporal_layering_mode_arg,
117  &lag_in_frame_arg,
118  &threads_arg,
119  &aqmode_arg,
120 #if OUTPUT_RC_STATS
121  &output_rc_stats_arg,
122 #endif
123 
124 #if CONFIG_VP9_HIGHBITDEPTH
125  &bitdepth_arg,
126 #endif
127  &speed_arg,
128  &rc_end_usage_arg,
129  &bitrates_arg,
130  NULL };
131 
132 static const uint32_t default_frames_to_skip = 0;
133 static const uint32_t default_frames_to_code = 60 * 60;
134 static const uint32_t default_width = 1920;
135 static const uint32_t default_height = 1080;
136 static const uint32_t default_timebase_num = 1;
137 static const uint32_t default_timebase_den = 60;
138 static const uint32_t default_bitrate = 1000;
139 static const uint32_t default_spatial_layers = 5;
140 static const uint32_t default_temporal_layers = 1;
141 static const uint32_t default_kf_dist = 100;
142 static const uint32_t default_temporal_layering_mode = 0;
143 static const uint32_t default_output_rc_stats = 0;
144 static const int32_t default_speed = -1; // -1 means use library default.
145 static const uint32_t default_threads = 0; // zero means use library default.
146 
147 typedef struct {
148  const char *input_filename;
149  const char *output_filename;
150  uint32_t frames_to_code;
151  uint32_t frames_to_skip;
152  struct VpxInputContext input_ctx;
153  stats_io_t rc_stats;
154  int passes;
155  int pass;
156 } AppInput;
157 
158 static const char *exec_name;
159 
160 void usage_exit(void) {
161  fprintf(stderr, "Usage: %s <options> input_filename output_filename\n",
162  exec_name);
163  fprintf(stderr, "Options:\n");
164  arg_show_usage(stderr, svc_args);
165  exit(EXIT_FAILURE);
166 }
167 
168 static void parse_command_line(int argc, const char **argv_,
169  AppInput *app_input, SvcContext *svc_ctx,
170  vpx_codec_enc_cfg_t *enc_cfg) {
171  struct arg arg;
172  char **argv = NULL;
173  char **argi = NULL;
174  char **argj = NULL;
175  vpx_codec_err_t res;
176  int passes = 0;
177  int pass = 0;
178  const char *fpf_file_name = NULL;
179  unsigned int min_bitrate = 0;
180  unsigned int max_bitrate = 0;
181  char string_options[1024] = { 0 };
182 
183  // initialize SvcContext with parameters that will be passed to vpx_svc_init
184  svc_ctx->log_level = SVC_LOG_DEBUG;
185  svc_ctx->spatial_layers = default_spatial_layers;
186  svc_ctx->temporal_layers = default_temporal_layers;
187  svc_ctx->temporal_layering_mode = default_temporal_layering_mode;
188 #if OUTPUT_RC_STATS
189  svc_ctx->output_rc_stat = default_output_rc_stats;
190 #endif
191  svc_ctx->speed = default_speed;
192  svc_ctx->threads = default_threads;
193 
194  // start with default encoder configuration
195  res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
196  if (res) {
197  die("Failed to get config: %s\n", vpx_codec_err_to_string(res));
198  }
199  // update enc_cfg with app default values
200  enc_cfg->g_w = default_width;
201  enc_cfg->g_h = default_height;
202  enc_cfg->g_timebase.num = default_timebase_num;
203  enc_cfg->g_timebase.den = default_timebase_den;
204  enc_cfg->rc_target_bitrate = default_bitrate;
205  enc_cfg->kf_min_dist = default_kf_dist;
206  enc_cfg->kf_max_dist = default_kf_dist;
207  enc_cfg->rc_end_usage = VPX_CQ;
208 
209  // initialize AppInput with default values
210  app_input->frames_to_code = default_frames_to_code;
211  app_input->frames_to_skip = default_frames_to_skip;
212 
213  // process command line options
214  argv = argv_dup(argc - 1, argv_ + 1);
215  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
216  arg.argv_step = 1;
217 
218  if (arg_match(&arg, &frames_arg, argi)) {
219  app_input->frames_to_code = arg_parse_uint(&arg);
220  } else if (arg_match(&arg, &width_arg, argi)) {
221  enc_cfg->g_w = arg_parse_uint(&arg);
222  } else if (arg_match(&arg, &height_arg, argi)) {
223  enc_cfg->g_h = arg_parse_uint(&arg);
224  } else if (arg_match(&arg, &timebase_arg, argi)) {
225  enc_cfg->g_timebase = arg_parse_rational(&arg);
226  } else if (arg_match(&arg, &bitrate_arg, argi)) {
227  enc_cfg->rc_target_bitrate = arg_parse_uint(&arg);
228  } else if (arg_match(&arg, &skip_frames_arg, argi)) {
229  app_input->frames_to_skip = arg_parse_uint(&arg);
230  } else if (arg_match(&arg, &spatial_layers_arg, argi)) {
231  svc_ctx->spatial_layers = arg_parse_uint(&arg);
232  } else if (arg_match(&arg, &temporal_layers_arg, argi)) {
233  svc_ctx->temporal_layers = arg_parse_uint(&arg);
234 #if OUTPUT_RC_STATS
235  } else if (arg_match(&arg, &output_rc_stats_arg, argi)) {
236  svc_ctx->output_rc_stat = arg_parse_uint(&arg);
237 #endif
238  } else if (arg_match(&arg, &speed_arg, argi)) {
239  svc_ctx->speed = arg_parse_uint(&arg);
240  } else if (arg_match(&arg, &aqmode_arg, argi)) {
241  svc_ctx->aqmode = arg_parse_uint(&arg);
242  } else if (arg_match(&arg, &threads_arg, argi)) {
243  svc_ctx->threads = arg_parse_uint(&arg);
244  } else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
245  svc_ctx->temporal_layering_mode = enc_cfg->temporal_layering_mode =
246  arg_parse_int(&arg);
247  if (svc_ctx->temporal_layering_mode) {
248  enc_cfg->g_error_resilient = 1;
249  }
250  } else if (arg_match(&arg, &kf_dist_arg, argi)) {
251  enc_cfg->kf_min_dist = arg_parse_uint(&arg);
252  enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
253  } else if (arg_match(&arg, &scale_factors_arg, argi)) {
254  snprintf(string_options, sizeof(string_options), "%s scale-factors=%s",
255  string_options, arg.val);
256  } else if (arg_match(&arg, &bitrates_arg, argi)) {
257  snprintf(string_options, sizeof(string_options), "%s bitrates=%s",
258  string_options, arg.val);
259  } else if (arg_match(&arg, &passes_arg, argi)) {
260  passes = arg_parse_uint(&arg);
261  if (passes < 1 || passes > 2) {
262  die("Error: Invalid number of passes (%d)\n", passes);
263  }
264  } else if (arg_match(&arg, &pass_arg, argi)) {
265  pass = arg_parse_uint(&arg);
266  if (pass < 1 || pass > 2) {
267  die("Error: Invalid pass selected (%d)\n", pass);
268  }
269  } else if (arg_match(&arg, &fpf_name_arg, argi)) {
270  fpf_file_name = arg.val;
271  } else if (arg_match(&arg, &min_q_arg, argi)) {
272  snprintf(string_options, sizeof(string_options), "%s min-quantizers=%s",
273  string_options, arg.val);
274  } else if (arg_match(&arg, &max_q_arg, argi)) {
275  snprintf(string_options, sizeof(string_options), "%s max-quantizers=%s",
276  string_options, arg.val);
277  } else if (arg_match(&arg, &min_bitrate_arg, argi)) {
278  min_bitrate = arg_parse_uint(&arg);
279  } else if (arg_match(&arg, &max_bitrate_arg, argi)) {
280  max_bitrate = arg_parse_uint(&arg);
281  } else if (arg_match(&arg, &lag_in_frame_arg, argi)) {
282  enc_cfg->g_lag_in_frames = arg_parse_uint(&arg);
283  } else if (arg_match(&arg, &rc_end_usage_arg, argi)) {
284  enc_cfg->rc_end_usage = arg_parse_uint(&arg);
285 #if CONFIG_VP9_HIGHBITDEPTH
286  } else if (arg_match(&arg, &bitdepth_arg, argi)) {
287  enc_cfg->g_bit_depth = arg_parse_enum_or_int(&arg);
288  switch (enc_cfg->g_bit_depth) {
289  case VPX_BITS_8:
290  enc_cfg->g_input_bit_depth = 8;
291  enc_cfg->g_profile = 0;
292  break;
293  case VPX_BITS_10:
294  enc_cfg->g_input_bit_depth = 10;
295  enc_cfg->g_profile = 2;
296  break;
297  case VPX_BITS_12:
298  enc_cfg->g_input_bit_depth = 12;
299  enc_cfg->g_profile = 2;
300  break;
301  default:
302  die("Error: Invalid bit depth selected (%d)\n", enc_cfg->g_bit_depth);
303  break;
304  }
305 #endif // CONFIG_VP9_HIGHBITDEPTH
306  } else {
307  ++argj;
308  }
309  }
310 
311  // There will be a space in front of the string options
312  if (strlen(string_options) > 0)
313  vpx_svc_set_options(svc_ctx, string_options + 1);
314 
315  if (passes == 0 || passes == 1) {
316  if (pass) {
317  fprintf(stderr, "pass is ignored since there's only one pass\n");
318  }
319  enc_cfg->g_pass = VPX_RC_ONE_PASS;
320  } else {
321  if (pass == 0) {
322  die("pass must be specified when passes is 2\n");
323  }
324 
325  if (fpf_file_name == NULL) {
326  die("fpf must be specified when passes is 2\n");
327  }
328 
329  if (pass == 1) {
330  enc_cfg->g_pass = VPX_RC_FIRST_PASS;
331  if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) {
332  fatal("Failed to open statistics store");
333  }
334  } else {
335  enc_cfg->g_pass = VPX_RC_LAST_PASS;
336  if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) {
337  fatal("Failed to open statistics store");
338  }
339  enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats);
340  }
341  app_input->passes = passes;
342  app_input->pass = pass;
343  }
344 
345  if (enc_cfg->rc_target_bitrate > 0) {
346  if (min_bitrate > 0) {
347  enc_cfg->rc_2pass_vbr_minsection_pct =
348  min_bitrate * 100 / enc_cfg->rc_target_bitrate;
349  }
350  if (max_bitrate > 0) {
351  enc_cfg->rc_2pass_vbr_maxsection_pct =
352  max_bitrate * 100 / enc_cfg->rc_target_bitrate;
353  }
354  }
355 
356  // Check for unrecognized options
357  for (argi = argv; *argi; ++argi)
358  if (argi[0][0] == '-' && strlen(argi[0]) > 1)
359  die("Error: Unrecognized option %s\n", *argi);
360 
361  if (argv[0] == NULL || argv[1] == 0) {
362  usage_exit();
363  }
364  app_input->input_filename = argv[0];
365  app_input->output_filename = argv[1];
366  free(argv);
367 
368  if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 ||
369  enc_cfg->g_h % 2)
370  die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h);
371 
372  printf(
373  "Codec %s\nframes: %d, skip: %d\n"
374  "layers: %d\n"
375  "width %d, height: %d,\n"
376  "num: %d, den: %d, bitrate: %d,\n"
377  "gop size: %d\n",
378  vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code,
379  app_input->frames_to_skip, svc_ctx->spatial_layers, enc_cfg->g_w,
380  enc_cfg->g_h, enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
381  enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
382 }
383 
384 #if OUTPUT_RC_STATS
385 // For rate control encoding stats.
386 struct RateControlStats {
387  // Number of input frames per layer.
388  int layer_input_frames[VPX_MAX_LAYERS];
389  // Total (cumulative) number of encoded frames per layer.
390  int layer_tot_enc_frames[VPX_MAX_LAYERS];
391  // Number of encoded non-key frames per layer.
392  int layer_enc_frames[VPX_MAX_LAYERS];
393  // Framerate per layer (cumulative).
394  double layer_framerate[VPX_MAX_LAYERS];
395  // Target average frame size per layer (per-frame-bandwidth per layer).
396  double layer_pfb[VPX_MAX_LAYERS];
397  // Actual average frame size per layer.
398  double layer_avg_frame_size[VPX_MAX_LAYERS];
399  // Average rate mismatch per layer (|target - actual| / target).
400  double layer_avg_rate_mismatch[VPX_MAX_LAYERS];
401  // Actual encoding bitrate per layer (cumulative).
402  double layer_encoding_bitrate[VPX_MAX_LAYERS];
403  // Average of the short-time encoder actual bitrate.
404  // TODO(marpan): Should we add these short-time stats for each layer?
405  double avg_st_encoding_bitrate;
406  // Variance of the short-time encoder actual bitrate.
407  double variance_st_encoding_bitrate;
408  // Window (number of frames) for computing short-time encoding bitrate.
409  int window_size;
410  // Number of window measurements.
411  int window_count;
412 };
413 
414 // Note: these rate control stats assume only 1 key frame in the
415 // sequence (i.e., first frame only).
416 static void set_rate_control_stats(struct RateControlStats *rc,
417  vpx_codec_enc_cfg_t *cfg) {
418  unsigned int sl, tl;
419  // Set the layer (cumulative) framerate and the target layer (non-cumulative)
420  // per-frame-bandwidth, for the rate control encoding stats below.
421  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
422 
423  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
424  for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
425  const int layer = sl * cfg->ts_number_layers + tl;
426  if (cfg->ts_number_layers == 1)
427  rc->layer_framerate[layer] = framerate;
428  else
429  rc->layer_framerate[layer] = framerate / cfg->ts_rate_decimator[tl];
430  if (tl > 0) {
431  rc->layer_pfb[layer] =
432  1000.0 * (cfg->layer_target_bitrate[layer] -
433  cfg->layer_target_bitrate[layer - 1]) /
434  (rc->layer_framerate[layer] - rc->layer_framerate[layer - 1]);
435  } else {
436  rc->layer_pfb[layer] = 1000.0 * cfg->layer_target_bitrate[layer] /
437  rc->layer_framerate[layer];
438  }
439  rc->layer_input_frames[layer] = 0;
440  rc->layer_enc_frames[layer] = 0;
441  rc->layer_tot_enc_frames[layer] = 0;
442  rc->layer_encoding_bitrate[layer] = 0.0;
443  rc->layer_avg_frame_size[layer] = 0.0;
444  rc->layer_avg_rate_mismatch[layer] = 0.0;
445  }
446  }
447  rc->window_count = 0;
448  rc->window_size = 15;
449  rc->avg_st_encoding_bitrate = 0.0;
450  rc->variance_st_encoding_bitrate = 0.0;
451 }
452 
453 static void printout_rate_control_summary(struct RateControlStats *rc,
454  vpx_codec_enc_cfg_t *cfg,
455  int frame_cnt) {
456  unsigned int sl, tl;
457  double perc_fluctuation = 0.0;
458  int tot_num_frames = 0;
459  printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
460  printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
462  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
463  tot_num_frames = 0;
464  for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
465  const int layer = sl * cfg->ts_number_layers + tl;
466  const int num_dropped =
467  (tl > 0)
468  ? (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer])
469  : (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] -
470  1);
471  tot_num_frames += rc->layer_input_frames[layer];
472  rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
473  rc->layer_encoding_bitrate[layer] /
474  tot_num_frames;
475  rc->layer_avg_frame_size[layer] =
476  rc->layer_avg_frame_size[layer] / rc->layer_enc_frames[layer];
477  rc->layer_avg_rate_mismatch[layer] = 100.0 *
478  rc->layer_avg_rate_mismatch[layer] /
479  rc->layer_enc_frames[layer];
480  printf("For layer#: sl%d tl%d \n", sl, tl);
481  printf("Bitrate (target vs actual): %d %f.0 kbps\n",
482  cfg->layer_target_bitrate[layer],
483  rc->layer_encoding_bitrate[layer]);
484  printf("Average frame size (target vs actual): %f %f bits\n",
485  rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]);
486  printf("Average rate_mismatch: %f\n", rc->layer_avg_rate_mismatch[layer]);
487  printf(
488  "Number of input frames, encoded (non-key) frames, "
489  "and percent dropped frames: %d %d %f.0 \n",
490  rc->layer_input_frames[layer], rc->layer_enc_frames[layer],
491  100.0 * num_dropped / rc->layer_input_frames[layer]);
492  printf("\n");
493  }
494  }
495  rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
496  rc->variance_st_encoding_bitrate =
497  rc->variance_st_encoding_bitrate / rc->window_count -
498  (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
499  perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
500  rc->avg_st_encoding_bitrate;
501  printf("Short-time stats, for window of %d frames: \n", rc->window_size);
502  printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
503  rc->avg_st_encoding_bitrate, sqrt(rc->variance_st_encoding_bitrate),
504  perc_fluctuation);
505  if (frame_cnt != tot_num_frames)
506  die("Error: Number of input frames not equal to output encoded frames != "
507  "%d tot_num_frames = %d\n",
508  frame_cnt, tot_num_frames);
509 }
510 
511 vpx_codec_err_t parse_superframe_index(const uint8_t *data, size_t data_sz,
512  uint64_t sizes[8], int *count) {
513  // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
514  // it is a super frame index. If the last byte of real video compression
515  // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
516  // not the associated matching marker byte at the front of the index we have
517  // an invalid bitstream and need to return an error.
518 
519  uint8_t marker;
520 
521  marker = *(data + data_sz - 1);
522  *count = 0;
523 
524  if ((marker & 0xe0) == 0xc0) {
525  const uint32_t frames = (marker & 0x7) + 1;
526  const uint32_t mag = ((marker >> 3) & 0x3) + 1;
527  const size_t index_sz = 2 + mag * frames;
528 
529  // This chunk is marked as having a superframe index but doesn't have
530  // enough data for it, thus it's an invalid superframe index.
531  if (data_sz < index_sz) return VPX_CODEC_CORRUPT_FRAME;
532 
533  {
534  const uint8_t marker2 = *(data + data_sz - index_sz);
535 
536  // This chunk is marked as having a superframe index but doesn't have
537  // the matching marker byte at the front of the index therefore it's an
538  // invalid chunk.
539  if (marker != marker2) return VPX_CODEC_CORRUPT_FRAME;
540  }
541 
542  {
543  // Found a valid superframe index.
544  uint32_t i, j;
545  const uint8_t *x = &data[data_sz - index_sz + 1];
546 
547  for (i = 0; i < frames; ++i) {
548  uint32_t this_sz = 0;
549 
550  for (j = 0; j < mag; ++j) this_sz |= (*x++) << (j * 8);
551  sizes[i] = this_sz;
552  }
553  *count = frames;
554  }
555  }
556  return VPX_CODEC_OK;
557 }
558 #endif
559 
560 // Example pattern for spatial layers and 2 temporal layers used in the
561 // bypass/flexible mode. The pattern corresponds to the pattern
562 // VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
563 // non-flexible mode.
564 void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
565  int is_key_frame,
566  vpx_svc_ref_frame_config_t *ref_frame_config) {
567  for (sl = 0; sl < num_spatial_layers; ++sl) {
568  if (!tl) {
569  if (!sl) {
570  ref_frame_config->frame_flags[sl] =
573  } else {
574  if (is_key_frame) {
575  ref_frame_config->frame_flags[sl] =
578  } else {
579  ref_frame_config->frame_flags[sl] =
581  }
582  }
583  } else if (tl == 1) {
584  if (!sl) {
585  ref_frame_config->frame_flags[sl] =
588  } else {
589  ref_frame_config->frame_flags[sl] =
591  }
592  }
593  if (tl == 0) {
594  ref_frame_config->lst_fb_idx[sl] = sl;
595  if (sl)
596  ref_frame_config->gld_fb_idx[sl] = sl - 1;
597  else
598  ref_frame_config->gld_fb_idx[sl] = 0;
599  ref_frame_config->alt_fb_idx[sl] = 0;
600  } else if (tl == 1) {
601  ref_frame_config->lst_fb_idx[sl] = sl;
602  ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1;
603  ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
604  }
605  }
606 }
607 
608 int main(int argc, const char **argv) {
609  AppInput app_input;
610  VpxVideoWriter *writer = NULL;
611  VpxVideoInfo info;
612  vpx_codec_ctx_t codec;
613  vpx_codec_enc_cfg_t enc_cfg;
614  SvcContext svc_ctx;
615  uint32_t i;
616  uint32_t frame_cnt = 0;
617  vpx_image_t raw;
618  vpx_codec_err_t res;
619  int pts = 0; /* PTS starts at 0 */
620  int frame_duration = 1; /* 1 timebase tick per frame */
621  FILE *infile = NULL;
622  int end_of_stream = 0;
623  int frames_received = 0;
624 #if OUTPUT_RC_STATS
625  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = { NULL };
626  struct RateControlStats rc;
627  vpx_svc_layer_id_t layer_id;
628  vpx_svc_ref_frame_config_t ref_frame_config;
629  unsigned int sl, tl;
630  double sum_bitrate = 0.0;
631  double sum_bitrate2 = 0.0;
632  double framerate = 30.0;
633 #endif
634  struct vpx_usec_timer timer;
635  int64_t cx_time = 0;
636  memset(&svc_ctx, 0, sizeof(svc_ctx));
637  svc_ctx.log_print = 1;
638  exec_name = argv[0];
639  parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
640 
641 // Allocate image buffer
642 #if CONFIG_VP9_HIGHBITDEPTH
643  if (!vpx_img_alloc(&raw,
644  enc_cfg.g_input_bit_depth == 8 ? VPX_IMG_FMT_I420
646  enc_cfg.g_w, enc_cfg.g_h, 32)) {
647  die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
648  }
649 #else
650  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) {
651  die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
652  }
653 #endif // CONFIG_VP9_HIGHBITDEPTH
654 
655  if (!(infile = fopen(app_input.input_filename, "rb")))
656  die("Failed to open %s for reading\n", app_input.input_filename);
657 
658  // Initialize codec
659  if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
660  VPX_CODEC_OK)
661  die("Failed to initialize encoder\n");
662 
663 #if OUTPUT_RC_STATS
664  if (svc_ctx.output_rc_stat) {
665  set_rate_control_stats(&rc, &enc_cfg);
666  framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
667  }
668 #endif
669 
670  info.codec_fourcc = VP9_FOURCC;
671  info.time_base.numerator = enc_cfg.g_timebase.num;
672  info.time_base.denominator = enc_cfg.g_timebase.den;
673 
674  if (!(app_input.passes == 2 && app_input.pass == 1)) {
675  // We don't save the bitstream for the 1st pass on two pass rate control
676  writer =
677  vpx_video_writer_open(app_input.output_filename, kContainerIVF, &info);
678  if (!writer)
679  die("Failed to open %s for writing\n", app_input.output_filename);
680  }
681 #if OUTPUT_RC_STATS
682  // For now, just write temporal layer streams.
683  // TODO(marpan): do spatial by re-writing superframe.
684  if (svc_ctx.output_rc_stat) {
685  for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
686  char file_name[PATH_MAX];
687 
688  snprintf(file_name, sizeof(file_name), "%s_t%d.ivf",
689  app_input.output_filename, tl);
690  outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
691  if (!outfile[tl]) die("Failed to open %s for writing", file_name);
692  }
693  }
694 #endif
695 
696  // skip initial frames
697  for (i = 0; i < app_input.frames_to_skip; ++i) vpx_img_read(&raw, infile);
698 
699  if (svc_ctx.speed != -1)
700  vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
701  if (svc_ctx.threads) {
702  vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
703  if (svc_ctx.threads > 1)
705  else
707  }
708  if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
710  if (svc_ctx.speed >= 5)
713 
714  // Encode frames
715  while (!end_of_stream) {
716  vpx_codec_iter_t iter = NULL;
717  const vpx_codec_cx_pkt_t *cx_pkt;
718  if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) {
719  // We need one extra vpx_svc_encode call at end of stream to flush
720  // encoder and get remaining data
721  end_of_stream = 1;
722  }
723 
724  // For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
725  // and the buffer indices for each spatial layer of the current
726  // (super)frame to be encoded. The temporal layer_id for the current frame
727  // also needs to be set.
728  // TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
729  // mode to "VP9E_LAYERING_MODE_BYPASS".
730  if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
731  layer_id.spatial_layer_id = 0;
732  // Example for 2 temporal layers.
733  if (frame_cnt % 2 == 0)
734  layer_id.temporal_layer_id = 0;
735  else
736  layer_id.temporal_layer_id = 1;
737  // Note that we only set the temporal layer_id, since we are calling
738  // the encode for the whole superframe. The encoder will internally loop
739  // over all the spatial layers for the current superframe.
740  vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
741  set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
742  svc_ctx.spatial_layers, frame_cnt == 0,
743  &ref_frame_config);
745  &ref_frame_config);
746  // Keep track of input frames, to account for frame drops in rate control
747  // stats/metrics.
748  for (sl = 0; sl < (unsigned int)enc_cfg.ss_number_layers; ++sl) {
749  ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
750  layer_id.temporal_layer_id];
751  }
752  }
753 
754  vpx_usec_timer_start(&timer);
755  res = vpx_svc_encode(
756  &svc_ctx, &codec, (end_of_stream ? NULL : &raw), pts, frame_duration,
757  svc_ctx.speed >= 5 ? VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
758  vpx_usec_timer_mark(&timer);
759  cx_time += vpx_usec_timer_elapsed(&timer);
760 
761  printf("%s", vpx_svc_get_message(&svc_ctx));
762  fflush(stdout);
763  if (res != VPX_CODEC_OK) {
764  die_codec(&codec, "Failed to encode frame");
765  }
766 
767  while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
768  switch (cx_pkt->kind) {
769  case VPX_CODEC_CX_FRAME_PKT: {
770  SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
771  if (cx_pkt->data.frame.sz > 0) {
772 #if OUTPUT_RC_STATS
773  uint64_t sizes[8];
774  int count = 0;
775 #endif
776  vpx_video_writer_write_frame(writer, cx_pkt->data.frame.buf,
777  cx_pkt->data.frame.sz,
778  cx_pkt->data.frame.pts);
779 #if OUTPUT_RC_STATS
780  // TODO(marpan): Put this (to line728) in separate function.
781  if (svc_ctx.output_rc_stat) {
782  vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
783  parse_superframe_index(cx_pkt->data.frame.buf,
784  cx_pkt->data.frame.sz, sizes, &count);
785  if (enc_cfg.ss_number_layers == 1)
786  sizes[0] = cx_pkt->data.frame.sz;
787  // Note computing input_layer_frames here won't account for frame
788  // drops in rate control stats.
789  // TODO(marpan): Fix this for non-bypass mode so we can get stats
790  // for dropped frames.
791  if (svc_ctx.temporal_layering_mode !=
793  for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
794  ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
795  layer_id.temporal_layer_id];
796  }
797  }
798  for (tl = layer_id.temporal_layer_id;
799  tl < enc_cfg.ts_number_layers; ++tl) {
800  vpx_video_writer_write_frame(
801  outfile[tl], cx_pkt->data.frame.buf, cx_pkt->data.frame.sz,
802  cx_pkt->data.frame.pts);
803  }
804 
805  for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
806  for (tl = layer_id.temporal_layer_id;
807  tl < enc_cfg.ts_number_layers; ++tl) {
808  const int layer = sl * enc_cfg.ts_number_layers + tl;
809  ++rc.layer_tot_enc_frames[layer];
810  rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
811  // Keep count of rate control stats per layer, for non-key
812  // frames.
813  if (tl == (unsigned int)layer_id.temporal_layer_id &&
814  !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
815  rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
816  rc.layer_avg_rate_mismatch[layer] +=
817  fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
818  rc.layer_pfb[layer];
819  ++rc.layer_enc_frames[layer];
820  }
821  }
822  }
823 
824  // Update for short-time encoding bitrate states, for moving
825  // window of size rc->window, shifted by rc->window / 2.
826  // Ignore first window segment, due to key frame.
827  if (frame_cnt > (unsigned int)rc.window_size) {
828  tl = layer_id.temporal_layer_id;
829  for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
830  sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
831  }
832  if (frame_cnt % rc.window_size == 0) {
833  rc.window_count += 1;
834  rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
835  rc.variance_st_encoding_bitrate +=
836  (sum_bitrate / rc.window_size) *
837  (sum_bitrate / rc.window_size);
838  sum_bitrate = 0.0;
839  }
840  }
841 
842  // Second shifted window.
843  if (frame_cnt >
844  (unsigned int)(rc.window_size + rc.window_size / 2)) {
845  tl = layer_id.temporal_layer_id;
846  for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
847  sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
848  }
849 
850  if (frame_cnt > (unsigned int)(2 * rc.window_size) &&
851  frame_cnt % rc.window_size == 0) {
852  rc.window_count += 1;
853  rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
854  rc.variance_st_encoding_bitrate +=
855  (sum_bitrate2 / rc.window_size) *
856  (sum_bitrate2 / rc.window_size);
857  sum_bitrate2 = 0.0;
858  }
859  }
860  }
861 #endif
862  }
863  /*
864  printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
865  !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
866  (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
867  */
868  if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1)
869  si->bytes_sum[0] += (int)cx_pkt->data.frame.sz;
870  ++frames_received;
871  break;
872  }
873  case VPX_CODEC_STATS_PKT: {
874  stats_write(&app_input.rc_stats, cx_pkt->data.twopass_stats.buf,
875  cx_pkt->data.twopass_stats.sz);
876  break;
877  }
878  default: { break; }
879  }
880  }
881 
882  if (!end_of_stream) {
883  ++frame_cnt;
884  pts += frame_duration;
885  }
886  }
887 
888  // Compensate for the extra frame count for the bypass mode.
889  if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
890  for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
891  const int layer =
892  sl * enc_cfg.ts_number_layers + layer_id.temporal_layer_id;
893  --rc.layer_input_frames[layer];
894  }
895  }
896 
897  printf("Processed %d frames\n", frame_cnt);
898  fclose(infile);
899 #if OUTPUT_RC_STATS
900  if (svc_ctx.output_rc_stat) {
901  printout_rate_control_summary(&rc, &enc_cfg, frame_cnt);
902  printf("\n");
903  }
904 #endif
905  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
906  if (app_input.passes == 2) stats_close(&app_input.rc_stats, 1);
907  if (writer) {
908  vpx_video_writer_close(writer);
909  }
910 #if OUTPUT_RC_STATS
911  if (svc_ctx.output_rc_stat) {
912  for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
913  vpx_video_writer_close(outfile[tl]);
914  }
915  }
916 #endif
917  printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
918  frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
919  1000000 * (double)frame_cnt / (double)cx_time);
920  vpx_img_free(&raw);
921  // display average size, psnr
922  printf("%s", vpx_svc_dump_statistics(&svc_ctx));
923  vpx_svc_release(&svc_ctx);
924  return EXIT_SUCCESS;
925 }
vpx_fixed_buf_t twopass_stats
Definition: vpx_encoder.h:186
unsigned int ts_number_layers
Number of temporal coding layers.
Definition: vpx_encoder.h:663
Codec control function to set encoder internal speed settings.
Definition: vp8cx.h:155
#define VPX_MAX_LAYERS
Definition: vpx_encoder.h:46
#define VP8_EFLAG_NO_REF_LAST
Don&#39;t reference the last frame.
Definition: vp8cx.h:58
#define VP8_EFLAG_NO_UPD_GF
Don&#39;t update the golden frame.
Definition: vp8cx.h:88
Image Descriptor.
Definition: vpx_image.h:88
Describes the encoder algorithm interface to applications.
const char * vpx_codec_iface_name(vpx_codec_iface_t *iface)
Return the name for a given interface.
const char * vpx_codec_err_to_string(vpx_codec_err_t err)
Convert error number to printable string.
int lst_fb_idx[5]
Definition: vp8cx.h:733
#define VPX_TS_MAX_LAYERS
Definition: vpx_encoder.h:40
struct vpx_rational g_timebase
Stream timebase units.
Definition: vpx_encoder.h:357
unsigned int layer_target_bitrate[12]
Target bitrate for each spatial/temporal layer.
Definition: vpx_encoder.h:703
#define VP8_EFLAG_NO_REF_GF
Don&#39;t reference the golden frame.
Definition: vp8cx.h:66
unsigned int g_input_bit_depth
Bit-depth of the input frames.
Definition: vpx_encoder.h:343
int den
Definition: vpx_encoder.h:231
Definition: vpx_encoder.h:154
unsigned int kf_max_dist
Keyframe maximum interval.
Definition: vpx_encoder.h:633
unsigned int g_lag_in_frames
Allow lagged encoding.
Definition: vpx_encoder.h:386
Encoder configuration structure.
Definition: vpx_encoder.h:279
The coded data for this stream is corrupt or incomplete.
Definition: vpx_codec.h:130
Codec control function to set row level multi-threading.
Definition: vp8cx.h:558
Codec control function to set Max data rate for Intra frames.
Definition: vp8cx.h:251
Encoder output packet.
Definition: vpx_encoder.h:170
void * buf
Definition: vpx_encoder.h:103
unsigned int ts_rate_decimator[5]
Frame rate decimation factor for each temporal layer.
Definition: vpx_encoder.h:677
unsigned int kf_min_dist
Keyframe minimum interval.
Definition: vpx_encoder.h:624
Definition: vpx_encoder.h:237
unsigned int g_profile
Bitstream profile to use.
Definition: vpx_encoder.h:309
Definition: vpx_encoder.h:238
Codec control function to set number of tile columns.
Definition: vp8cx.h:345
struct vpx_codec_cx_pkt::@1::@2 frame
int frame_flags[5]
Definition: vp8cx.h:732
vpx_image_t * vpx_img_alloc(vpx_image_t *img, vpx_img_fmt_t fmt, unsigned int d_w, unsigned int d_h, unsigned int align)
Open a descriptor, allocating storage for the underlying image.
Definition: vpx_image.h:55
unsigned int g_w
Width of the frame.
Definition: vpx_encoder.h:318
Codec control function to set adaptive quantization mode.
Definition: vp8cx.h:392
Codec control function to get svc layer ID.
Definition: vp8cx.h:459
unsigned int g_h
Height of the frame.
Definition: vpx_encoder.h:327
enum vpx_codec_cx_pkt_kind kind
Definition: vpx_encoder.h:171
vp9 svc layer parameters
Definition: vp8cx.h:718
Operation completed without error.
Definition: vpx_codec.h:92
#define VP8_EFLAG_NO_UPD_LAST
Don&#39;t update the last frame.
Definition: vp8cx.h:81
void vpx_img_free(vpx_image_t *img)
Close an image descriptor.
unsigned int rc_target_bitrate
Target data rate.
Definition: vpx_encoder.h:477
#define VPX_DL_REALTIME
deadline parameter analogous to VPx REALTIME mode.
Definition: vpx_encoder.h:849
int num
Definition: vpx_encoder.h:230
Definition: vpx_codec.h:220
Codec control function to set the frame flags and buffer indices for spatial layers. The frame flags and buffer indices are set using the struct vpx_svc_ref_frame_config defined below.
Definition: vp8cx.h:533
enum vpx_enc_pass g_pass
Multi-pass Encoding Mode.
Definition: vpx_encoder.h:372
#define VPX_DL_GOOD_QUALITY
deadline parameter analogous to VPx GOOD QUALITY mode.
Definition: vpx_encoder.h:851
unsigned int ss_number_layers
Number of spatial coding layers.
Definition: vpx_encoder.h:643
vpx_bit_depth_t g_bit_depth
Bit-depth of the codec.
Definition: vpx_encoder.h:335
Provides definitions for using VP8 or VP9 encoder algorithm within the vpx Codec Interface.
Bypass mode. Used when application needs to control temporal layering. This will only work when the n...
Definition: vp8cx.h:628
vpx_codec_err_t
Algorithm return codes.
Definition: vpx_codec.h:90
const vpx_codec_cx_pkt_t * vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter)
Encoded data iterator.
union vpx_codec_cx_pkt::@1 data
int temporal_layering_mode
Temporal layering mode indicating which temporal layering scheme to use.
Definition: vpx_encoder.h:712
vpx_fixed_buf_t rc_twopass_stats_in
Two-pass stats buffer.
Definition: vpx_encoder.h:464
Definition: vpx_image.h:63
vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface, vpx_codec_enc_cfg_t *cfg, unsigned int reserved)
Get a default configuration.
Definition: vpx_encoder.h:245
#define vpx_codec_control(ctx, id, data)
vpx_codec_control wrapper macro
Definition: vpx_codec.h:404
#define VP8_EFLAG_NO_REF_ARF
Don&#39;t reference the alternate reference frame.
Definition: vp8cx.h:74
vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
Destroy a codec instance.
size_t sz
Definition: vpx_encoder.h:104
Definition: vpx_codec.h:218
vp9 svc frame flag parameters.
Definition: vp8cx.h:731
Codec control function to set the threshold for MBs treated static.
Definition: vp8cx.h:182
#define VPX_FRAME_IS_KEY
Definition: vpx_encoder.h:122
Definition: vpx_codec.h:219
int alt_fb_idx[5]
Definition: vp8cx.h:735
const void * vpx_codec_iter_t
Iterator.
Definition: vpx_codec.h:187
Definition: vpx_encoder.h:153
unsigned int rc_2pass_vbr_maxsection_pct
Two-pass mode per-GOP maximum bitrate.
Definition: vpx_encoder.h:596
vpx_codec_er_flags_t g_error_resilient
Enable error resilient modes.
Definition: vpx_encoder.h:365
#define VP8_EFLAG_NO_UPD_ARF
Don&#39;t update the alternate reference frame.
Definition: vp8cx.h:95
unsigned int rc_2pass_vbr_minsection_pct
Two-pass mode per-GOP minimum bitrate.
Definition: vpx_encoder.h:589
int gld_fb_idx[5]
Definition: vp8cx.h:734
Codec control function to set svc layer for spatial and temporal.
Definition: vp8cx.h:441
enum vpx_rc_mode rc_end_usage
Rate control algorithm to use.
Definition: vpx_encoder.h:457
Definition: vpx_encoder.h:236
Codec context structure.
Definition: vpx_codec.h:197