WebM Codec SDK
vp8_multi_resolution_encoder
1/*
2 * Copyright (c) 2010 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 multi-resolution encoding in VP8.
13 * High-resolution input video is down-sampled to lower-resolutions. The
14 * encoder then encodes the video and outputs multiple bitstreams with
15 * different resolutions.
16 *
17 * This test also allows for settings temporal layers for each spatial layer.
18 * Different number of temporal layers per spatial stream may be used.
19 * Currently up to 3 temporal layers per spatial stream (encoder) are supported
20 * in this test.
21 */
22
23#include "./vpx_config.h"
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <stdarg.h>
28#include <math.h>
29#include <assert.h>
30#include <sys/time.h>
31#include "vpx_ports/vpx_timer.h"
32#include "vpx/vpx_encoder.h"
33#include "vpx/vp8cx.h"
34#include "vpx_ports/mem_ops.h"
35#include "../tools_common.h"
36#define interface (vpx_codec_vp8_cx())
37#define fourcc 0x30385056
38
39void usage_exit(void) { exit(EXIT_FAILURE); }
40
41/*
42 * The input video frame is downsampled several times to generate a multi-level
43 * hierarchical structure. NUM_ENCODERS is defined as the number of encoding
44 * levels required. For example, if the size of input video is 1280x720,
45 * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
46 * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
47 * 320x180(level 2) respectively.
48 */
49
50/* Number of encoders (spatial resolutions) used in this test. */
51#define NUM_ENCODERS 3
52
53/* Maximum number of temporal layers allowed for this test. */
54#define MAX_NUM_TEMPORAL_LAYERS 3
55
56/* This example uses the scaler function in libyuv. */
57#include "third_party/libyuv/include/libyuv/basic_types.h"
58#include "third_party/libyuv/include/libyuv/scale.h"
59#include "third_party/libyuv/include/libyuv/cpu_id.h"
60
61int (*read_frame_p)(FILE *f, vpx_image_t *img);
62
63static int mulres_read_frame(FILE *f, vpx_image_t *img) {
64 size_t nbytes, to_read;
65 int res = 1;
66
67 to_read = img->w * img->h * 3 / 2;
68 nbytes = fread(img->planes[0], 1, to_read, f);
69 if (nbytes != to_read) {
70 res = 0;
71 if (nbytes > 0)
72 printf("Warning: Read partial frame. Check your width & height!\n");
73 }
74 return res;
75}
76
77static int mulres_read_frame_by_row(FILE *f, vpx_image_t *img) {
78 size_t nbytes, to_read;
79 int res = 1;
80 int plane;
81
82 for (plane = 0; plane < 3; plane++) {
83 unsigned char *ptr;
84 int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
85 int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
86 int r;
87
88 /* Determine the correct plane based on the image format. The for-loop
89 * always counts in Y,U,V order, but this may not match the order of
90 * the data on disk.
91 */
92 switch (plane) {
93 case 1:
94 ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V
95 : VPX_PLANE_U];
96 break;
97 case 2:
98 ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U
99 : VPX_PLANE_V];
100 break;
101 default: ptr = img->planes[plane];
102 }
103
104 for (r = 0; r < h; r++) {
105 to_read = w;
106
107 nbytes = fread(ptr, 1, to_read, f);
108 if (nbytes != to_read) {
109 res = 0;
110 if (nbytes > 0)
111 printf("Warning: Read partial frame. Check your width & height!\n");
112 break;
113 }
114
115 ptr += img->stride[plane];
116 }
117 if (!res) break;
118 }
119
120 return res;
121}
122
123static void write_ivf_file_header(FILE *outfile, const vpx_codec_enc_cfg_t *cfg,
124 int frame_cnt) {
125 char header[32];
126
127 if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS) return;
128 header[0] = 'D';
129 header[1] = 'K';
130 header[2] = 'I';
131 header[3] = 'F';
132 mem_put_le16(header + 4, 0); /* version */
133 mem_put_le16(header + 6, 32); /* headersize */
134 mem_put_le32(header + 8, fourcc); /* headersize */
135 mem_put_le16(header + 12, cfg->g_w); /* width */
136 mem_put_le16(header + 14, cfg->g_h); /* height */
137 mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
138 mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
139 mem_put_le32(header + 24, frame_cnt); /* length */
140 mem_put_le32(header + 28, 0); /* unused */
141
142 (void)fwrite(header, 1, 32, outfile);
143}
144
145static void write_ivf_frame_header(FILE *outfile,
146 const vpx_codec_cx_pkt_t *pkt) {
147 char header[12];
148 vpx_codec_pts_t pts;
149
150 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) return;
151
152 pts = pkt->data.frame.pts;
153 mem_put_le32(header, (int)pkt->data.frame.sz);
154 mem_put_le32(header + 4, pts & 0xFFFFFFFF);
155 mem_put_le32(header + 8, pts >> 32);
156
157 (void)fwrite(header, 1, 12, outfile);
158}
159
160/* Temporal scaling parameters */
161/* This sets all the temporal layer parameters given |num_temporal_layers|,
162 * including the target bit allocation across temporal layers. Bit allocation
163 * parameters will be passed in as user parameters in another version.
164 */
165static void set_temporal_layer_pattern(int num_temporal_layers,
166 vpx_codec_enc_cfg_t *cfg, int bitrate,
167 int *layer_flags) {
168 assert(num_temporal_layers <= MAX_NUM_TEMPORAL_LAYERS);
169 switch (num_temporal_layers) {
170 case 1: {
171 /* 1-layer */
172 cfg->ts_number_layers = 1;
173 cfg->ts_periodicity = 1;
174 cfg->ts_rate_decimator[0] = 1;
175 cfg->ts_layer_id[0] = 0;
176 cfg->ts_target_bitrate[0] = bitrate;
177
178 // Update L only.
179 layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
180 break;
181 }
182
183 case 2: {
184 /* 2-layers, with sync point at first frame of layer 1. */
185 cfg->ts_number_layers = 2;
186 cfg->ts_periodicity = 2;
187 cfg->ts_rate_decimator[0] = 2;
188 cfg->ts_rate_decimator[1] = 1;
189 cfg->ts_layer_id[0] = 0;
190 cfg->ts_layer_id[1] = 1;
191 // Use 60/40 bit allocation as example.
192 cfg->ts_target_bitrate[0] = (int)(0.6f * bitrate);
193 cfg->ts_target_bitrate[1] = bitrate;
194
195 /* 0=L, 1=GF */
196 // ARF is used as predictor for all frames, and is only updated on
197 // key frame. Sync point every 8 frames.
198
199 // Layer 0: predict from L and ARF, update L and G.
200 layer_flags[0] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF;
201
202 // Layer 1: sync point: predict from L and ARF, and update G.
203 layer_flags[1] =
205
206 // Layer 0, predict from L and ARF, update L.
207 layer_flags[2] =
209
210 // Layer 1: predict from L, G and ARF, and update G.
213
214 // Layer 0
215 layer_flags[4] = layer_flags[2];
216
217 // Layer 1
218 layer_flags[5] = layer_flags[3];
219
220 // Layer 0
221 layer_flags[6] = layer_flags[4];
222
223 // Layer 1
224 layer_flags[7] = layer_flags[5];
225 break;
226 }
227
228 case 3:
229 default: {
230 // 3-layers structure where ARF is used as predictor for all frames,
231 // and is only updated on key frame.
232 // Sync points for layer 1 and 2 every 8 frames.
233 cfg->ts_number_layers = 3;
234 cfg->ts_periodicity = 4;
235 cfg->ts_rate_decimator[0] = 4;
236 cfg->ts_rate_decimator[1] = 2;
237 cfg->ts_rate_decimator[2] = 1;
238 cfg->ts_layer_id[0] = 0;
239 cfg->ts_layer_id[1] = 2;
240 cfg->ts_layer_id[2] = 1;
241 cfg->ts_layer_id[3] = 2;
242 // Use 45/20/35 bit allocation as example.
243 cfg->ts_target_bitrate[0] = (int)(0.45f * bitrate);
244 cfg->ts_target_bitrate[1] = (int)(0.65f * bitrate);
245 cfg->ts_target_bitrate[2] = bitrate;
246
247 /* 0=L, 1=GF, 2=ARF */
248
249 // Layer 0: predict from L and ARF; update L and G.
250 layer_flags[0] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF;
251
252 // Layer 2: sync point: predict from L and ARF; update none.
253 layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
256
257 // Layer 1: sync point: predict from L and ARF; update G.
258 layer_flags[2] =
260
261 // Layer 2: predict from L, G, ARF; update none.
262 layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
264
265 // Layer 0: predict from L and ARF; update L.
266 layer_flags[4] =
268
269 // Layer 2: predict from L, G, ARF; update none.
270 layer_flags[5] = layer_flags[3];
271
272 // Layer 1: predict from L, G, ARF; update G.
274
275 // Layer 2: predict from L, G, ARF; update none.
276 layer_flags[7] = layer_flags[3];
277 break;
278 }
279 }
280}
281
282/* The periodicity of the pattern given the number of temporal layers. */
283static int periodicity_to_num_layers[MAX_NUM_TEMPORAL_LAYERS] = { 1, 8, 8 };
284
285int main(int argc, char **argv) {
286 FILE *infile, *outfile[NUM_ENCODERS];
287 FILE *downsampled_input[NUM_ENCODERS - 1];
288 char filename[50];
289 vpx_codec_ctx_t codec[NUM_ENCODERS];
290 vpx_codec_enc_cfg_t cfg[NUM_ENCODERS];
291 int frame_cnt = 0;
292 vpx_image_t raw[NUM_ENCODERS];
293 vpx_codec_err_t res[NUM_ENCODERS];
294
295 int i;
296 int width;
297 int height;
298 int length_frame;
299 int frame_avail;
300 int got_data;
301 int flags = 0;
302 int layer_id = 0;
303
304 int layer_flags[VPX_TS_MAX_PERIODICITY * NUM_ENCODERS] = { 0 };
305 int flag_periodicity;
306
307 /*Currently, only realtime mode is supported in multi-resolution encoding.*/
308 int arg_deadline = VPX_DL_REALTIME;
309
310 /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
311 don't need to know PSNR, which will skip PSNR calculation and save
312 encoding time. */
313 int show_psnr = 0;
314 int key_frame_insert = 0;
315 uint64_t psnr_sse_total[NUM_ENCODERS] = { 0 };
316 uint64_t psnr_samples_total[NUM_ENCODERS] = { 0 };
317 double psnr_totals[NUM_ENCODERS][4] = { { 0, 0 } };
318 int psnr_count[NUM_ENCODERS] = { 0 };
319
320 int64_t cx_time = 0;
321
322 /* Set the required target bitrates for each resolution level.
323 * If target bitrate for highest-resolution level is set to 0,
324 * (i.e. target_bitrate[0]=0), we skip encoding at that level.
325 */
326 unsigned int target_bitrate[NUM_ENCODERS] = { 1000, 500, 100 };
327
328 /* Enter the frame rate of the input video */
329 int framerate = 30;
330
331 /* Set down-sampling factor for each resolution level.
332 dsf[0] controls down sampling from level 0 to level 1;
333 dsf[1] controls down sampling from level 1 to level 2;
334 dsf[2] is not used. */
335 vpx_rational_t dsf[NUM_ENCODERS] = { { 2, 1 }, { 2, 1 }, { 1, 1 } };
336
337 /* Set the number of temporal layers for each encoder/resolution level,
338 * starting from highest resoln down to lowest resoln. */
339 unsigned int num_temporal_layers[NUM_ENCODERS] = { 3, 3, 3 };
340
341 if (argc != (7 + 3 * NUM_ENCODERS))
342 die("Usage: %s <width> <height> <frame_rate> <infile> <outfile(s)> "
343 "<rate_encoder(s)> <temporal_layer(s)> <key_frame_insert> <output "
344 "psnr?> \n",
345 argv[0]);
346
347 printf("Using %s\n", vpx_codec_iface_name(interface));
348
349 width = (int)strtol(argv[1], NULL, 0);
350 height = (int)strtol(argv[2], NULL, 0);
351 framerate = (int)strtol(argv[3], NULL, 0);
352
353 if (width < 16 || width % 2 || height < 16 || height % 2)
354 die("Invalid resolution: %dx%d", width, height);
355
356 /* Open input video file for encoding */
357 if (!(infile = fopen(argv[4], "rb")))
358 die("Failed to open %s for reading", argv[4]);
359
360 /* Open output file for each encoder to output bitstreams */
361 for (i = 0; i < NUM_ENCODERS; i++) {
362 if (!target_bitrate[i]) {
363 outfile[i] = NULL;
364 continue;
365 }
366
367 if (!(outfile[i] = fopen(argv[i + 5], "wb")))
368 die("Failed to open %s for writing", argv[i + 4]);
369 }
370
371 // Bitrates per spatial layer: overwrite default rates above.
372 for (i = 0; i < NUM_ENCODERS; i++) {
373 target_bitrate[i] = (int)strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0);
374 }
375
376 // Temporal layers per spatial layers: overwrite default settings above.
377 for (i = 0; i < NUM_ENCODERS; i++) {
378 num_temporal_layers[i] =
379 (int)strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0);
380 if (num_temporal_layers[i] < 1 || num_temporal_layers[i] > 3)
381 die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n",
382 num_temporal_layers[i]);
383 }
384
385 /* Open file to write out each spatially downsampled input stream. */
386 for (i = 0; i < NUM_ENCODERS - 1; i++) {
387 // Highest resoln is encoder 0.
388 if (sprintf(filename, "ds%d.yuv", NUM_ENCODERS - i) < 0) {
389 return EXIT_FAILURE;
390 }
391 downsampled_input[i] = fopen(filename, "wb");
392 }
393
394 key_frame_insert = (int)strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0);
395
396 show_psnr = (int)strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0);
397
398 /* Populate default encoder configuration */
399 for (i = 0; i < NUM_ENCODERS; i++) {
400 res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0);
401 if (res[i]) {
402 printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i]));
403 return EXIT_FAILURE;
404 }
405 }
406
407 /*
408 * Update the default configuration according to needs of the application.
409 */
410 /* Highest-resolution encoder settings */
411 cfg[0].g_w = width;
412 cfg[0].g_h = height;
413 cfg[0].rc_dropframe_thresh = 0;
414 cfg[0].rc_end_usage = VPX_CBR;
415 cfg[0].rc_resize_allowed = 0;
416 cfg[0].rc_min_quantizer = 2;
417 cfg[0].rc_max_quantizer = 56;
418 cfg[0].rc_undershoot_pct = 100;
419 cfg[0].rc_overshoot_pct = 15;
420 cfg[0].rc_buf_initial_sz = 500;
421 cfg[0].rc_buf_optimal_sz = 600;
422 cfg[0].rc_buf_sz = 1000;
423 cfg[0].g_error_resilient = 1; /* Enable error resilient mode */
424 cfg[0].g_lag_in_frames = 0;
425
426 /* Disable automatic keyframe placement */
427 /* Note: These 3 settings are copied to all levels. But, except the lowest
428 * resolution level, all other levels are set to VPX_KF_DISABLED internally.
429 */
430 cfg[0].kf_mode = VPX_KF_AUTO;
431 cfg[0].kf_min_dist = 3000;
432 cfg[0].kf_max_dist = 3000;
433
434 cfg[0].rc_target_bitrate = target_bitrate[0]; /* Set target bitrate */
435 cfg[0].g_timebase.num = 1; /* Set fps */
436 cfg[0].g_timebase.den = framerate;
437
438 /* Other-resolution encoder settings */
439 for (i = 1; i < NUM_ENCODERS; i++) {
440 cfg[i] = cfg[0];
441
442 cfg[i].rc_target_bitrate = target_bitrate[i];
443
444 /* Note: Width & height of other-resolution encoders are calculated
445 * from the highest-resolution encoder's size and the corresponding
446 * down_sampling_factor.
447 */
448 {
449 unsigned int iw = cfg[i - 1].g_w * dsf[i - 1].den + dsf[i - 1].num - 1;
450 unsigned int ih = cfg[i - 1].g_h * dsf[i - 1].den + dsf[i - 1].num - 1;
451 cfg[i].g_w = iw / dsf[i - 1].num;
452 cfg[i].g_h = ih / dsf[i - 1].num;
453 }
454
455 /* Make width & height to be multiplier of 2. */
456 // Should support odd size ???
457 if ((cfg[i].g_w) % 2) cfg[i].g_w++;
458 if ((cfg[i].g_h) % 2) cfg[i].g_h++;
459 }
460
461 // Set the number of threads per encode/spatial layer.
462 // (1, 1, 1) means no encoder threading.
463 cfg[0].g_threads = 1;
464 cfg[1].g_threads = 1;
465 cfg[2].g_threads = 1;
466
467 /* Allocate image for each encoder */
468 for (i = 0; i < NUM_ENCODERS; i++)
469 if (!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
470 die("Failed to allocate image (%dx%d)", cfg[i].g_w, cfg[i].g_h);
471
472 if (raw[0].stride[VPX_PLANE_Y] == (int)raw[0].d_w)
473 read_frame_p = mulres_read_frame;
474 else
475 read_frame_p = mulres_read_frame_by_row;
476
477 for (i = 0; i < NUM_ENCODERS; i++)
478 if (outfile[i]) write_ivf_file_header(outfile[i], &cfg[i], 0);
479
480 /* Temporal layers settings */
481 for (i = 0; i < NUM_ENCODERS; i++) {
482 set_temporal_layer_pattern(num_temporal_layers[i], &cfg[i],
483 cfg[i].rc_target_bitrate,
484 &layer_flags[i * VPX_TS_MAX_PERIODICITY]);
485 }
486
487 /* Initialize multi-encoder */
488 if (vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
489 (show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
490 die_codec(&codec[0], "Failed to initialize encoder");
491
492 /* The extra encoding configuration parameters can be set as follows. */
493 /* Set encoding speed */
494 for (i = 0; i < NUM_ENCODERS; i++) {
495 int speed = -6;
496 /* Lower speed for the lowest resolution. */
497 if (i == NUM_ENCODERS - 1) speed = -4;
498 if (vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
499 die_codec(&codec[i], "Failed to set cpu_used");
500 }
501
502 /* Set static threshold = 1 for all encoders */
503 for (i = 0; i < NUM_ENCODERS; i++) {
505 die_codec(&codec[i], "Failed to set static threshold");
506 }
507
508 /* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
509 /* Enable denoising for the highest-resolution encoder. */
511 die_codec(&codec[0], "Failed to set noise_sensitivity");
513 die_codec(&codec[1], "Failed to set noise_sensitivity");
514 for (i = 2; i < NUM_ENCODERS; i++) {
516 die_codec(&codec[i], "Failed to set noise_sensitivity");
517 }
518
519 /* Set the number of token partitions */
520 for (i = 0; i < NUM_ENCODERS; i++) {
522 die_codec(&codec[i], "Failed to set static threshold");
523 }
524
525 /* Set the max intra target bitrate */
526 for (i = 0; i < NUM_ENCODERS; i++) {
527 unsigned int max_intra_size_pct =
528 (int)(((double)cfg[0].rc_buf_optimal_sz * 0.5) * framerate / 10);
530 max_intra_size_pct))
531 die_codec(&codec[i], "Failed to set static threshold");
532 // printf("%d %d \n",i,max_intra_size_pct);
533 }
534
535 frame_avail = 1;
536 got_data = 0;
537
538 while (frame_avail || got_data) {
539 struct vpx_usec_timer timer;
540 vpx_codec_iter_t iter[NUM_ENCODERS] = { NULL };
541 const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS];
542
543 flags = 0;
544 frame_avail = read_frame_p(infile, &raw[0]);
545
546 if (frame_avail) {
547 for (i = 1; i < NUM_ENCODERS; i++) {
548 /*Scale the image down a number of times by downsampling factor*/
549 /* FilterMode 1 or 2 give better psnr than FilterMode 0. */
550 I420Scale(
551 raw[i - 1].planes[VPX_PLANE_Y], raw[i - 1].stride[VPX_PLANE_Y],
552 raw[i - 1].planes[VPX_PLANE_U], raw[i - 1].stride[VPX_PLANE_U],
553 raw[i - 1].planes[VPX_PLANE_V], raw[i - 1].stride[VPX_PLANE_V],
554 raw[i - 1].d_w, raw[i - 1].d_h, raw[i].planes[VPX_PLANE_Y],
555 raw[i].stride[VPX_PLANE_Y], raw[i].planes[VPX_PLANE_U],
556 raw[i].stride[VPX_PLANE_U], raw[i].planes[VPX_PLANE_V],
557 raw[i].stride[VPX_PLANE_V], raw[i].d_w, raw[i].d_h, 1);
558 /* Write out down-sampled input. */
559 length_frame = cfg[i].g_w * cfg[i].g_h * 3 / 2;
560 if (fwrite(raw[i].planes[0], 1, length_frame,
561 downsampled_input[NUM_ENCODERS - i - 1]) !=
562 (unsigned int)length_frame) {
563 return EXIT_FAILURE;
564 }
565 }
566 }
567
568 /* Set the flags (reference and update) for all the encoders.*/
569 for (i = 0; i < NUM_ENCODERS; i++) {
570 layer_id = cfg[i].ts_layer_id[frame_cnt % cfg[i].ts_periodicity];
571 flags = 0;
572 flag_periodicity = periodicity_to_num_layers[num_temporal_layers[i] - 1];
573 flags = layer_flags[i * VPX_TS_MAX_PERIODICITY +
574 frame_cnt % flag_periodicity];
575 // Key frame flag for first frame.
576 if (frame_cnt == 0) {
577 flags |= VPX_EFLAG_FORCE_KF;
578 }
579 if (frame_cnt > 0 && frame_cnt == key_frame_insert) {
580 flags = VPX_EFLAG_FORCE_KF;
581 }
582
583 vpx_codec_control(&codec[i], VP8E_SET_FRAME_FLAGS, flags);
584 vpx_codec_control(&codec[i], VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
585 }
586
587 /* Encode each frame at multi-levels */
588 /* Note the flags must be set to 0 in the encode call if they are set
589 for each frame with the vpx_codec_control(), as done above. */
590 vpx_usec_timer_start(&timer);
591 if (vpx_codec_encode(&codec[0], frame_avail ? &raw[0] : NULL, frame_cnt, 1,
592 0, arg_deadline)) {
593 die_codec(&codec[0], "Failed to encode frame");
594 }
595 vpx_usec_timer_mark(&timer);
596 cx_time += vpx_usec_timer_elapsed(&timer);
597
598 for (i = NUM_ENCODERS - 1; i >= 0; i--) {
599 got_data = 0;
600 while ((pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i]))) {
601 got_data = 1;
602 switch (pkt[i]->kind) {
604 write_ivf_frame_header(outfile[i], pkt[i]);
605 (void)fwrite(pkt[i]->data.frame.buf, 1, pkt[i]->data.frame.sz,
606 outfile[i]);
607 break;
609 if (show_psnr) {
610 int j;
611
612 psnr_sse_total[i] += pkt[i]->data.psnr.sse[0];
613 psnr_samples_total[i] += pkt[i]->data.psnr.samples[0];
614 for (j = 0; j < 4; j++) {
615 psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j];
616 }
617 psnr_count[i]++;
618 }
619
620 break;
621 default: break;
622 }
623 fflush(stdout);
624 }
625 }
626 frame_cnt++;
627 }
628 printf("\n");
629 printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
630 frame_cnt, 1000 * (float)cx_time / (double)(frame_cnt * 1000000),
631 1000000 * (double)frame_cnt / (double)cx_time);
632
633 fclose(infile);
634
635 printf("Processed %ld frames.\n", (long int)frame_cnt - 1);
636 for (i = 0; i < NUM_ENCODERS; i++) {
637 /* Calculate PSNR and print it out */
638 if ((show_psnr) && (psnr_count[i] > 0)) {
639 int j;
640 double ovpsnr =
641 sse_to_psnr(psnr_samples_total[i], 255.0, psnr_sse_total[i]);
642
643 fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i);
644
645 fprintf(stderr, " %.3lf", ovpsnr);
646 for (j = 0; j < 4; j++) {
647 fprintf(stderr, " %.3lf", psnr_totals[i][j] / psnr_count[i]);
648 }
649 }
650
651 if (vpx_codec_destroy(&codec[i]))
652 die_codec(&codec[i], "Failed to destroy codec");
653
654 vpx_img_free(&raw[i]);
655
656 if (!outfile[i]) continue;
657
658 /* Try to rewrite the file header with the actual frame count */
659 if (!fseek(outfile[i], 0, SEEK_SET))
660 write_ivf_file_header(outfile[i], &cfg[i], frame_cnt - 1);
661 fclose(outfile[i]);
662 }
663
664 return EXIT_SUCCESS;
665}
const char * vpx_codec_err_to_string(vpx_codec_err_t err)
Convert error number to printable string.
struct vpx_codec_ctx vpx_codec_ctx_t
Codec context structure.
vpx_codec_err_t vpx_codec_destroy(vpx_codec_ctx_t *ctx)
Destroy a codec instance.
const void * vpx_codec_iter_t
Iterator.
Definition vpx_codec.h:190
const char * vpx_codec_iface_name(vpx_codec_iface_t *iface)
Return the name for a given interface.
#define vpx_codec_control(ctx, id, data)
vpx_codec_control wrapper macro
Definition vpx_codec.h:408
vpx_codec_err_t
Algorithm return codes.
Definition vpx_codec.h:93
#define VPX_DL_REALTIME
deadline parameter analogous to VPx REALTIME mode.
Definition vpx_encoder.h:1012
struct vpx_codec_enc_cfg vpx_codec_enc_cfg_t
Encoder configuration structure.
#define VPX_EFLAG_FORCE_KF
Definition vpx_encoder.h:269
#define VPX_CODEC_USE_PSNR
Initialization-time Feature Enabling.
Definition vpx_encoder.h:94
const vpx_codec_cx_pkt_t * vpx_codec_get_cx_data(vpx_codec_ctx_t *ctx, vpx_codec_iter_t *iter)
Encoded data iterator.
#define VPX_TS_MAX_PERIODICITY
Definition vpx_encoder.h:38
int64_t vpx_codec_pts_t
Time Stamp Type.
Definition vpx_encoder.h:113
vpx_codec_err_t vpx_codec_enc_config_default(vpx_codec_iface_t *iface, vpx_codec_enc_cfg_t *cfg, unsigned int usage)
Get a default configuration.
struct vpx_codec_cx_pkt vpx_codec_cx_pkt_t
Encoder output packet.
#define vpx_codec_enc_init_multi(ctx, iface, cfg, num_enc, flags, dsf)
Convenience macro for vpx_codec_enc_init_multi_ver().
Definition vpx_encoder.h:939
struct vpx_rational vpx_rational_t
Rational Number.
vpx_codec_err_t vpx_codec_encode(vpx_codec_ctx_t *ctx, const vpx_image_t *img, vpx_codec_pts_t pts, unsigned long duration, vpx_enc_frame_flags_t flags, vpx_enc_deadline_t deadline)
Encode a frame.
@ VPX_CODEC_PSNR_PKT
Definition vpx_encoder.h:158
@ VPX_CODEC_CX_FRAME_PKT
Definition vpx_encoder.h:155
@ VPX_RC_LAST_PASS
Definition vpx_encoder.h:236
@ VPX_RC_ONE_PASS
Definition vpx_encoder.h:234
@ VPX_KF_AUTO
Definition vpx_encoder.h:257
@ VPX_CBR
Definition vpx_encoder.h:242
#define VP8_EFLAG_NO_UPD_ARF
Don't update the alternate reference frame.
Definition vp8cx.h:112
#define VP8_EFLAG_NO_UPD_ENTROPY
Disable entropy update.
Definition vp8cx.h:133
#define VP8_EFLAG_NO_UPD_LAST
Don't update the last frame.
Definition vp8cx.h:98
#define VP8_EFLAG_NO_UPD_GF
Don't update the golden frame.
Definition vp8cx.h:105
#define VP8_EFLAG_NO_REF_GF
Don't reference the golden frame.
Definition vp8cx.h:83
@ VP8E_SET_MAX_INTRA_BITRATE_PCT
Codec control function to set Max data rate for Intra frames.
Definition vp8cx.h:275
@ VP8E_SET_NOISE_SENSITIVITY
control function to set noise sensitivity
Definition vp8cx.h:191
@ VP8E_SET_TOKEN_PARTITIONS
Codec control function to set the number of token partitions.
Definition vp8cx.h:212
@ VP8E_SET_CPUUSED
Codec control function to set encoder internal speed settings.
Definition vp8cx.h:173
@ VP8E_SET_TEMPORAL_LAYER_ID
Codec control function to set the temporal layer id.
Definition vp8cx.h:322
@ VP8E_SET_STATIC_THRESHOLD
Codec control function to set the threshold for MBs treated static.
Definition vp8cx.h:206
@ VP8E_SET_FRAME_FLAGS
Codec control function to set reference and update frame flags.
Definition vp8cx.h:281
union vpx_codec_cx_pkt::@105367030154200007005241002351245163342006201240 data
struct vpx_codec_cx_pkt::@105367030154200007005241002351245163342006201240::@337301343345304110063267327113124066016321050157 frame
enum vpx_codec_cx_pkt_kind kind
Definition vpx_encoder.h:168
double psnr[4]
Definition vpx_encoder.h:195
size_t sz
Definition vpx_encoder.h:172
vpx_codec_pts_t pts
time stamp to show frame (in timebase units)
Definition vpx_encoder.h:174
unsigned int rc_resize_allowed
Enable/disable spatial resampling, if supported by the codec.
Definition vpx_encoder.h:411
unsigned int kf_min_dist
Keyframe minimum interval.
Definition vpx_encoder.h:618
unsigned int rc_min_quantizer
Minimum (Best Quality) Quantizer.
Definition vpx_encoder.h:486
unsigned int ts_number_layers
Number of temporal coding layers.
Definition vpx_encoder.h:657
unsigned int g_h
Height of the frame.
Definition vpx_encoder.h:324
enum vpx_kf_mode kf_mode
Keyframe placement mode.
Definition vpx_encoder.h:609
unsigned int ts_layer_id[16]
Template defining the membership of frames to temporal layers.
Definition vpx_encoder.h:689
vpx_codec_er_flags_t g_error_resilient
Enable error resilient modes.
Definition vpx_encoder.h:362
unsigned int ts_periodicity
Length of the sequence defining frame temporal layer membership.
Definition vpx_encoder.h:680
unsigned int rc_overshoot_pct
Rate control adaptation overshoot control.
Definition vpx_encoder.h:529
unsigned int g_w
Width of the frame.
Definition vpx_encoder.h:315
unsigned int rc_buf_sz
Decoder Buffer Size.
Definition vpx_encoder.h:544
unsigned int rc_dropframe_thresh
Temporal resampling configuration, if supported by the codec.
Definition vpx_encoder.h:402
struct vpx_rational g_timebase
Stream timebase units.
Definition vpx_encoder.h:354
enum vpx_enc_pass g_pass
Multi-pass Encoding Mode.
Definition vpx_encoder.h:369
unsigned int rc_max_quantizer
Maximum (Worst Quality) Quantizer.
Definition vpx_encoder.h:495
unsigned int g_lag_in_frames
Allow lagged encoding.
Definition vpx_encoder.h:383
enum vpx_rc_mode rc_end_usage
Rate control algorithm to use.
Definition vpx_encoder.h:451
unsigned int rc_buf_initial_sz
Decoder Buffer Initial Size.
Definition vpx_encoder.h:553
unsigned int rc_buf_optimal_sz
Decoder Buffer Optimal Size.
Definition vpx_encoder.h:562
unsigned int rc_target_bitrate
Target data rate.
Definition vpx_encoder.h:473
unsigned int ts_target_bitrate[5]
Target bitrate for each temporal layer.
Definition vpx_encoder.h:664
unsigned int rc_undershoot_pct
Rate control adaptation undershoot control.
Definition vpx_encoder.h:514
unsigned int ts_rate_decimator[5]
Frame rate decimation factor for each temporal layer.
Definition vpx_encoder.h:671
unsigned int kf_max_dist
Keyframe maximum interval.
Definition vpx_encoder.h:627
unsigned int g_threads
Maximum number of threads to use.
Definition vpx_encoder.h:296
vpx_img_fmt_t fmt
Definition vpx_image.h:77
unsigned int d_h
Definition vpx_image.h:88
unsigned int d_w
Definition vpx_image.h:87
unsigned int h
Definition vpx_image.h:83
unsigned char * planes[4]
Definition vpx_image.h:104
unsigned int w
Definition vpx_image.h:82
int stride[4]
Definition vpx_image.h:105
int den
Definition vpx_encoder.h:229
int num
Definition vpx_encoder.h:228
Provides definitions for using VP8 or VP9 encoder algorithm within the vpx Codec Interface.
Describes the encoder algorithm interface to applications.
#define VPX_PLANE_Y
Definition vpx_image.h:100
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.
#define VPX_PLANE_U
Definition vpx_image.h:101
@ VPX_IMG_FMT_YV12
Definition vpx_image.h:40
@ VPX_IMG_FMT_I420
Definition vpx_image.h:42
#define VPX_PLANE_V
Definition vpx_image.h:102
struct vpx_image vpx_image_t
Image Descriptor.
void vpx_img_free(vpx_image_t *img)
Close an image descriptor.