2 * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
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.
11 // This is an example demonstrating how to implement a multi-layer VP9
12 // encoding scheme based on temporal scalability for video applications
13 // that benefit from a scalable bitstream.
20 #define VPX_CODEC_DISABLE_COMPAT 1
21 #include "vpx/vp8cx.h"
22 #include "vpx/vpx_encoder.h"
24 #include "./tools_common.h"
25 #include "./video_writer.h"
27 static const char *exec_name;
33 static int mode_to_num_layers[12] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3};
35 // For rate control encoding stats.
36 struct RateControlMetrics {
37 // Number of input frames per layer.
38 int layer_input_frames[VPX_TS_MAX_LAYERS];
39 // Total (cumulative) number of encoded frames per layer.
40 int layer_tot_enc_frames[VPX_TS_MAX_LAYERS];
41 // Number of encoded non-key frames per layer.
42 int layer_enc_frames[VPX_TS_MAX_LAYERS];
43 // Framerate per layer layer (cumulative).
44 float layer_framerate[VPX_TS_MAX_LAYERS];
45 // Target average frame size per layer (per-frame-bandwidth per layer).
46 float layer_pfb[VPX_TS_MAX_LAYERS];
47 // Actual average frame size per layer.
48 float layer_avg_frame_size[VPX_TS_MAX_LAYERS];
49 // Average rate mismatch per layer (|target - actual| / target).
50 float layer_avg_rate_mismatch[VPX_TS_MAX_LAYERS];
51 // Actual encoding bitrate per layer (cumulative).
52 float layer_encoding_bitrate[VPX_TS_MAX_LAYERS];
55 static void set_rate_control_metrics(struct RateControlMetrics *rc,
56 vpx_codec_enc_cfg_t *cfg) {
58 // Set the layer (cumulative) framerate and the target layer (non-cumulative)
59 // per-frame-bandwidth, for the rate control encoding stats below.
60 float framerate = cfg->g_timebase.den / cfg->g_timebase.num;
61 rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
62 rc->layer_pfb[0] = 1000.0 * cfg->ts_target_bitrate[0] /
63 rc->layer_framerate[0];
64 for (i = 0; i < cfg->ts_number_layers; ++i) {
66 rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
67 rc->layer_pfb[i] = 1000.0 *
68 (cfg->ts_target_bitrate[i] - cfg->ts_target_bitrate[i - 1]) /
69 (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
71 rc->layer_input_frames[i] = 0;
72 rc->layer_enc_frames[i] = 0;
73 rc->layer_tot_enc_frames[i] = 0;
74 rc->layer_encoding_bitrate[i] = 0.0;
75 rc->layer_avg_frame_size[i] = 0.0;
76 rc->layer_avg_rate_mismatch[i] = 0.0;
80 static void printout_rate_control_summary(struct RateControlMetrics *rc,
81 vpx_codec_enc_cfg_t *cfg,
84 int check_num_frames = 0;
85 printf("Total number of processed frames: %d\n\n", frame_cnt -1);
86 printf("Rate control layer stats for %d layer(s):\n\n",
87 cfg->ts_number_layers);
88 for (i = 0; i < cfg->ts_number_layers; ++i) {
89 const int num_dropped = (i > 0) ?
90 (rc->layer_input_frames[i] - rc->layer_enc_frames[i]) :
91 (rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1);
92 rc->layer_encoding_bitrate[i] = 0.001 * rc->layer_framerate[i] *
93 rc->layer_encoding_bitrate[i] / rc->layer_tot_enc_frames[i];
94 rc->layer_avg_frame_size[i] = rc->layer_avg_frame_size[i] /
95 rc->layer_enc_frames[i];
96 rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
97 rc->layer_enc_frames[i];
98 printf("For layer#: %d \n", i);
99 printf("Bitrate (target vs actual): %d %f \n", cfg->ts_target_bitrate[i],
100 rc->layer_encoding_bitrate[i]);
101 printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
102 rc->layer_avg_frame_size[i]);
103 printf("Average rate_mismatch: %f \n", rc->layer_avg_rate_mismatch[i]);
104 printf("Number of input frames, encoded (non-key) frames, "
105 "and perc dropped frames: %d %d %f \n", rc->layer_input_frames[i],
106 rc->layer_enc_frames[i],
107 100.0 * num_dropped / rc->layer_input_frames[i]);
108 check_num_frames += rc->layer_input_frames[i];
111 if ((frame_cnt - 1) != check_num_frames)
112 die("Error: Number of input frames not equal to output! \n");
115 // Temporal scaling parameters:
116 // NOTE: The 3 prediction frames cannot be used interchangeably due to
117 // differences in the way they are handled throughout the code. The
118 // frames should be allocated to layers in the order LAST, GF, ARF.
119 // Other combinations work, but may produce slightly inferior results.
120 static void set_temporal_layer_pattern(int layering_mode,
121 vpx_codec_enc_cfg_t *cfg,
123 int *flag_periodicity) {
124 switch (layering_mode) {
128 cfg->ts_periodicity = 1;
129 *flag_periodicity = 1;
130 cfg->ts_number_layers = 1;
131 cfg->ts_rate_decimator[0] = 1;
132 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
134 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
135 VP8_EFLAG_NO_UPD_ARF;
139 // 2-layers, 2-frame period.
141 cfg->ts_periodicity = 2;
142 *flag_periodicity = 2;
143 cfg->ts_number_layers = 2;
144 cfg->ts_rate_decimator[0] = 2;
145 cfg->ts_rate_decimator[1] = 1;
146 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
148 // 0=L, 1=GF, Intra-layer prediction enabled.
149 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
150 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
151 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
152 VP8_EFLAG_NO_REF_ARF;
154 // 0=L, 1=GF, Intra-layer prediction disabled.
155 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_GF |
156 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
157 layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
158 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
163 // 2-layers, 3-frame period.
164 int ids[3] = {0, 1, 1};
165 cfg->ts_periodicity = 3;
166 *flag_periodicity = 3;
167 cfg->ts_number_layers = 2;
168 cfg->ts_rate_decimator[0] = 3;
169 cfg->ts_rate_decimator[1] = 1;
170 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
171 // 0=L, 1=GF, Intra-layer prediction enabled.
172 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
173 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
175 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
176 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
180 // 3-layers, 6-frame period.
181 int ids[6] = {0, 2, 2, 1, 2, 2};
182 cfg->ts_periodicity = 6;
183 *flag_periodicity = 6;
184 cfg->ts_number_layers = 3;
185 cfg->ts_rate_decimator[0] = 6;
186 cfg->ts_rate_decimator[1] = 3;
187 cfg->ts_rate_decimator[2] = 1;
188 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
189 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
190 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
191 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
192 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
193 VP8_EFLAG_NO_UPD_LAST;
197 layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
201 // 3-layers, 4-frame period.
202 int ids[4] = {0, 2, 1, 2};
203 cfg->ts_periodicity = 4;
204 *flag_periodicity = 4;
205 cfg->ts_number_layers = 3;
206 cfg->ts_rate_decimator[0] = 4;
207 cfg->ts_rate_decimator[1] = 2;
208 cfg->ts_rate_decimator[2] = 1;
209 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
210 // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
211 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
212 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
213 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
214 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
216 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
217 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
221 // 3-layers, 4-frame period.
222 int ids[4] = {0, 2, 1, 2};
223 cfg->ts_periodicity = 4;
224 *flag_periodicity = 4;
225 cfg->ts_number_layers = 3;
226 cfg->ts_rate_decimator[0] = 4;
227 cfg->ts_rate_decimator[1] = 2;
228 cfg->ts_rate_decimator[2] = 1;
229 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
230 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, disabled
232 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
233 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
234 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
235 VP8_EFLAG_NO_UPD_ARF;
237 layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
238 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
242 // 3-layers, 4-frame period.
243 int ids[4] = {0, 2, 1, 2};
244 cfg->ts_periodicity = 4;
245 *flag_periodicity = 4;
246 cfg->ts_number_layers = 3;
247 cfg->ts_rate_decimator[0] = 4;
248 cfg->ts_rate_decimator[1] = 2;
249 cfg->ts_rate_decimator[2] = 1;
250 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
251 // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
252 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
253 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
254 layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
255 VP8_EFLAG_NO_UPD_ARF;
257 layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
261 // NOTE: Probably of academic interest only.
262 // 5-layers, 16-frame period.
263 int ids[16] = {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4};
264 cfg->ts_periodicity = 16;
265 *flag_periodicity = 16;
266 cfg->ts_number_layers = 5;
267 cfg->ts_rate_decimator[0] = 16;
268 cfg->ts_rate_decimator[1] = 8;
269 cfg->ts_rate_decimator[2] = 4;
270 cfg->ts_rate_decimator[3] = 2;
271 cfg->ts_rate_decimator[4] = 1;
272 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
273 layer_flags[0] = VPX_EFLAG_FORCE_KF;
281 layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
282 VP8_EFLAG_NO_UPD_ARF;
286 layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
288 layer_flags[12] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF;
289 layer_flags[8] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
293 // 2-layers, with sync point at first frame of layer 1.
295 cfg->ts_periodicity = 2;
296 *flag_periodicity = 8;
297 cfg->ts_number_layers = 2;
298 cfg->ts_rate_decimator[0] = 2;
299 cfg->ts_rate_decimator[1] = 1;
300 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
302 // ARF is used as predictor for all frames, and is only updated on
303 // key frame. Sync point every 8 frames.
305 // Layer 0: predict from L and ARF, update L and G.
306 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
307 VP8_EFLAG_NO_UPD_ARF;
308 // Layer 1: sync point: predict from L and ARF, and update G.
309 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST |
310 VP8_EFLAG_NO_UPD_ARF;
311 // Layer 0, predict from L and ARF, update L.
312 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
313 VP8_EFLAG_NO_UPD_ARF;
314 // Layer 1: predict from L, G and ARF, and update G.
315 layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
316 VP8_EFLAG_NO_UPD_ENTROPY;
318 layer_flags[4] = layer_flags[2];
320 layer_flags[5] = layer_flags[3];
322 layer_flags[6] = layer_flags[4];
324 layer_flags[7] = layer_flags[5];
328 // 3-layers: Sync points for layer 1 and 2 every 8 frames.
329 int ids[4] = {0, 2, 1, 2};
330 cfg->ts_periodicity = 4;
331 *flag_periodicity = 8;
332 cfg->ts_number_layers = 3;
333 cfg->ts_rate_decimator[0] = 4;
334 cfg->ts_rate_decimator[1] = 2;
335 cfg->ts_rate_decimator[2] = 1;
336 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
338 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_REF_GF |
339 VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
340 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
341 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
342 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
343 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
345 layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
346 layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
347 VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
348 layer_flags[6] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
349 VP8_EFLAG_NO_UPD_ARF;
350 layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
351 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
355 // 3-layers structure where ARF is used as predictor for all frames,
356 // and is only updated on key frame.
357 // Sync points for layer 1 and 2 every 8 frames.
359 int ids[4] = {0, 2, 1, 2};
360 cfg->ts_periodicity = 4;
361 *flag_periodicity = 8;
362 cfg->ts_number_layers = 3;
363 cfg->ts_rate_decimator[0] = 4;
364 cfg->ts_rate_decimator[1] = 2;
365 cfg->ts_rate_decimator[2] = 1;
366 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
368 // Layer 0: predict from L and ARF; update L and G.
369 layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF |
371 // Layer 2: sync point: predict from L and ARF; update none.
372 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
373 VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
374 VP8_EFLAG_NO_UPD_ENTROPY;
375 // Layer 1: sync point: predict from L and ARF; update G.
376 layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
377 VP8_EFLAG_NO_UPD_LAST;
378 // Layer 2: predict from L, G, ARF; update none.
379 layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
380 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
381 // Layer 0: predict from L and ARF; update L.
382 layer_flags[4] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
384 // Layer 2: predict from L, G, ARF; update none.
385 layer_flags[5] = layer_flags[3];
386 // Layer 1: predict from L, G, ARF; update G.
387 layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
388 // Layer 2: predict from L, G, ARF; update none.
389 layer_flags[7] = layer_flags[3];
394 // 3-layers structure as in case 10, but no sync/refresh points for
396 int ids[4] = {0, 2, 1, 2};
397 cfg->ts_periodicity = 4;
398 *flag_periodicity = 8;
399 cfg->ts_number_layers = 3;
400 cfg->ts_rate_decimator[0] = 4;
401 cfg->ts_rate_decimator[1] = 2;
402 cfg->ts_rate_decimator[2] = 1;
403 memcpy(cfg->ts_layer_id, ids, sizeof(ids));
405 // Layer 0: predict from L and ARF; update L.
406 layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
408 layer_flags[4] = layer_flags[0];
409 // Layer 1: predict from L, G, ARF; update G.
410 layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
411 layer_flags[6] = layer_flags[2];
412 // Layer 2: predict from L, G, ARF; update none.
413 layer_flags[1] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
414 VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
415 layer_flags[3] = layer_flags[1];
416 layer_flags[5] = layer_flags[1];
417 layer_flags[7] = layer_flags[1];
423 int main(int argc, char **argv) {
424 VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS];
425 vpx_codec_ctx_t codec;
426 vpx_codec_enc_cfg_t cfg;
436 int pts = 0; // PTS starts at 0.
437 int frame_duration = 1; // 1 timebase tick per frame.
438 int layering_mode = 0;
439 int layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
440 int flag_periodicity = 1;
441 int max_intra_size_pct;
442 vpx_svc_layer_id_t layer_id = {0, 0};
443 const VpxInterface *encoder = NULL;
445 struct RateControlMetrics rc;
448 // Check usage and arguments.
450 die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
451 "<rate_num> <rate_den> <frame_drop_threshold> <mode> "
452 "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]);
455 encoder = get_vpx_encoder_by_name(argv[3]);
457 die("Unsupported codec.");
459 printf("Using %s\n", vpx_codec_iface_name(encoder->interface()));
461 width = strtol(argv[4], NULL, 0);
462 height = strtol(argv[5], NULL, 0);
463 if (width < 16 || width % 2 || height < 16 || height % 2) {
464 die("Invalid resolution: %d x %d", width, height);
467 layering_mode = strtol(argv[9], NULL, 0);
468 if (layering_mode < 0 || layering_mode > 12) {
469 die("Invalid mode (0..12) %s", argv[9]);
472 if (argc != 10 + mode_to_num_layers[layering_mode]) {
473 die("Invalid number of arguments");
476 if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
477 die("Failed to allocate image", width, height);
480 // Populate encoder configuration.
481 res = vpx_codec_enc_config_default(encoder->interface(), &cfg, 0);
483 printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
487 // Update the default configuration with our settings.
491 // Timebase format e.g. 30fps: numerator=1, demoninator = 30.
492 cfg.g_timebase.num = strtol(argv[6], NULL, 0);
493 cfg.g_timebase.den = strtol(argv[7], NULL, 0);
495 for (i = 10; i < 10 + mode_to_num_layers[layering_mode]; ++i) {
496 cfg.ts_target_bitrate[i - 10] = strtol(argv[i], NULL, 0);
499 // Real time parameters.
500 cfg.rc_dropframe_thresh = strtol(argv[8], NULL, 0);
501 cfg.rc_end_usage = VPX_CBR;
502 cfg.rc_resize_allowed = 0;
503 cfg.rc_min_quantizer = 2;
504 cfg.rc_max_quantizer = 56;
505 cfg.rc_undershoot_pct = 50;
506 cfg.rc_overshoot_pct = 50;
507 cfg.rc_buf_initial_sz = 500;
508 cfg.rc_buf_optimal_sz = 600;
509 cfg.rc_buf_sz = 1000;
511 // Enable error resilient mode.
512 cfg.g_error_resilient = 1;
513 cfg.g_lag_in_frames = 0;
514 cfg.kf_mode = VPX_KF_DISABLED;
516 // Disable automatic keyframe placement.
517 cfg.kf_min_dist = cfg.kf_max_dist = 3000;
519 // Default setting for bitrate: used in special case of 1 layer (case 0).
520 cfg.rc_target_bitrate = cfg.ts_target_bitrate[0];
522 set_temporal_layer_pattern(layering_mode,
527 set_rate_control_metrics(&rc, &cfg);
530 if (!(infile = fopen(argv[1], "rb"))) {
531 die("Failed to open %s for reading", argv[1]);
534 // Open an output file for each stream.
535 for (i = 0; i < cfg.ts_number_layers; ++i) {
536 char file_name[PATH_MAX];
538 info.codec_fourcc = encoder->fourcc;
539 info.frame_width = cfg.g_w;
540 info.frame_height = cfg.g_h;
541 info.time_base.numerator = cfg.g_timebase.num;
542 info.time_base.denominator = cfg.g_timebase.den;
544 snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
545 outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
547 die("Failed to open %s for writing", file_name);
549 // No spatial layers in this encoder.
550 cfg.ss_number_layers = 1;
553 if (vpx_codec_enc_init(&codec, encoder->interface(), &cfg, 0))
554 die_codec(&codec, "Failed to initialize encoder");
556 vpx_codec_control(&codec, VP8E_SET_CPUUSED, -6);
557 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 1);
558 if (strncmp(encoder->name, "vp9", 3) == 0) {
559 vpx_codec_control(&codec, VP8E_SET_CPUUSED, 3);
560 vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, 0);
561 if (vpx_codec_control(&codec, VP9E_SET_SVC, 1)) {
562 die_codec(&codec, "Failed to set SVC");
565 vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
566 vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
567 max_intra_size_pct = (int) (((double)cfg.rc_buf_optimal_sz * 0.5)
568 * ((double) cfg.g_timebase.den / cfg.g_timebase.num) / 10.0);
569 vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT, max_intra_size_pct);
572 while (frame_avail || got_data) {
573 vpx_codec_iter_t iter = NULL;
574 const vpx_codec_cx_pkt_t *pkt;
575 // Update the temporal layer_id. No spatial layers in this test.
576 layer_id.spatial_layer_id = 0;
577 layer_id.temporal_layer_id =
578 cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
579 if (strncmp(encoder->name, "vp9", 3) == 0) {
580 vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
582 flags = layer_flags[frame_cnt % flag_periodicity];
583 frame_avail = vpx_img_read(&raw, infile);
585 ++rc.layer_input_frames[layer_id.temporal_layer_id];
586 if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags,
588 die_codec(&codec, "Failed to encode frame");
591 if (layering_mode != 7) {
592 layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
595 while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
598 case VPX_CODEC_CX_FRAME_PKT:
599 for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
600 i < cfg.ts_number_layers; ++i) {
601 vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
602 pkt->data.frame.sz, pts);
603 ++rc.layer_tot_enc_frames[i];
604 rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
605 // Keep count of rate control stats per layer (for non-key frames).
606 if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
607 !(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
608 rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
609 rc.layer_avg_rate_mismatch[i] +=
610 fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
612 ++rc.layer_enc_frames[i];
621 pts += frame_duration;
624 printout_rate_control_summary(&rc, &cfg, frame_cnt);
626 if (vpx_codec_destroy(&codec))
627 die_codec(&codec, "Failed to destroy codec");
629 // Try to rewrite the output file headers with the actual frame count.
630 for (i = 0; i < cfg.ts_number_layers; ++i)
631 vpx_video_writer_close(outfile[i]);