2 * Copyright (c) 2010 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.
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.
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
23 #include "./vpx_config.h"
32 #include "vpx_ports/vpx_timer.h"
33 #include "vpx/vpx_encoder.h"
34 #include "vpx/vp8cx.h"
35 #include "vpx_ports/mem_ops.h"
36 #include "../tools_common.h"
37 #define interface (vpx_codec_vp8_cx())
38 #define fourcc 0x30385056
40 void usage_exit(void) {
45 * The input video frame is downsampled several times to generate a multi-level
46 * hierarchical structure. NUM_ENCODERS is defined as the number of encoding
47 * levels required. For example, if the size of input video is 1280x720,
48 * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
49 * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
50 * 320x180(level 2) respectively.
53 /* Number of encoders (spatial resolutions) used in this test. */
54 #define NUM_ENCODERS 3
56 /* Maximum number of temporal layers allowed for this test. */
57 #define MAX_NUM_TEMPORAL_LAYERS 3
59 /* This example uses the scaler function in libyuv. */
60 #include "third_party/libyuv/include/libyuv/basic_types.h"
61 #include "third_party/libyuv/include/libyuv/scale.h"
62 #include "third_party/libyuv/include/libyuv/cpu_id.h"
64 int (*read_frame_p
)(FILE *f
, vpx_image_t
*img
);
66 static int read_frame(FILE *f
, vpx_image_t
*img
) {
67 size_t nbytes
, to_read
;
70 to_read
= img
->w
*img
->h
*3/2;
71 nbytes
= fread(img
->planes
[0], 1, to_read
, f
);
72 if(nbytes
!= to_read
) {
75 printf("Warning: Read partial frame. Check your width & height!\n");
80 static int read_frame_by_row(FILE *f
, vpx_image_t
*img
) {
81 size_t nbytes
, to_read
;
85 for (plane
= 0; plane
< 3; plane
++)
88 int w
= (plane
? (1 + img
->d_w
) / 2 : img
->d_w
);
89 int h
= (plane
? (1 + img
->d_h
) / 2 : img
->d_h
);
92 /* Determine the correct plane based on the image format. The for-loop
93 * always counts in Y,U,V order, but this may not match the order of
99 ptr
= img
->planes
[img
->fmt
==VPX_IMG_FMT_YV12
? VPX_PLANE_V
: VPX_PLANE_U
];
102 ptr
= img
->planes
[img
->fmt
==VPX_IMG_FMT_YV12
?VPX_PLANE_U
: VPX_PLANE_V
];
105 ptr
= img
->planes
[plane
];
108 for (r
= 0; r
< h
; r
++)
112 nbytes
= fread(ptr
, 1, to_read
, f
);
113 if(nbytes
!= to_read
) {
116 printf("Warning: Read partial frame. Check your width & height!\n");
120 ptr
+= img
->stride
[plane
];
129 static void write_ivf_file_header(FILE *outfile
,
130 const vpx_codec_enc_cfg_t
*cfg
,
134 if(cfg
->g_pass
!= VPX_RC_ONE_PASS
&& cfg
->g_pass
!= VPX_RC_LAST_PASS
)
140 mem_put_le16(header
+4, 0); /* version */
141 mem_put_le16(header
+6, 32); /* headersize */
142 mem_put_le32(header
+8, fourcc
); /* headersize */
143 mem_put_le16(header
+12, cfg
->g_w
); /* width */
144 mem_put_le16(header
+14, cfg
->g_h
); /* height */
145 mem_put_le32(header
+16, cfg
->g_timebase
.den
); /* rate */
146 mem_put_le32(header
+20, cfg
->g_timebase
.num
); /* scale */
147 mem_put_le32(header
+24, frame_cnt
); /* length */
148 mem_put_le32(header
+28, 0); /* unused */
150 (void) fwrite(header
, 1, 32, outfile
);
153 static void write_ivf_frame_header(FILE *outfile
,
154 const vpx_codec_cx_pkt_t
*pkt
)
159 if(pkt
->kind
!= VPX_CODEC_CX_FRAME_PKT
)
162 pts
= pkt
->data
.frame
.pts
;
163 mem_put_le32(header
, pkt
->data
.frame
.sz
);
164 mem_put_le32(header
+4, pts
&0xFFFFFFFF);
165 mem_put_le32(header
+8, pts
>> 32);
167 (void) fwrite(header
, 1, 12, outfile
);
170 /* Temporal scaling parameters */
171 /* This sets all the temporal layer parameters given |num_temporal_layers|,
172 * including the target bit allocation across temporal layers. Bit allocation
173 * parameters will be passed in as user parameters in another version.
175 static void set_temporal_layer_pattern(int num_temporal_layers
,
176 vpx_codec_enc_cfg_t
*cfg
,
180 assert(num_temporal_layers
<= MAX_NUM_TEMPORAL_LAYERS
);
181 switch (num_temporal_layers
)
186 cfg
->ts_number_layers
= 1;
187 cfg
->ts_periodicity
= 1;
188 cfg
->ts_rate_decimator
[0] = 1;
189 cfg
->ts_layer_id
[0] = 0;
190 cfg
->ts_target_bitrate
[0] = bitrate
;
193 layer_flags
[0] = VP8_EFLAG_NO_UPD_GF
| VP8_EFLAG_NO_UPD_ARF
;
199 /* 2-layers, with sync point at first frame of layer 1. */
200 cfg
->ts_number_layers
= 2;
201 cfg
->ts_periodicity
= 2;
202 cfg
->ts_rate_decimator
[0] = 2;
203 cfg
->ts_rate_decimator
[1] = 1;
204 cfg
->ts_layer_id
[0] = 0;
205 cfg
->ts_layer_id
[1] = 1;
206 // Use 60/40 bit allocation as example.
207 cfg
->ts_target_bitrate
[0] = 0.6f
* bitrate
;
208 cfg
->ts_target_bitrate
[1] = bitrate
;
211 // ARF is used as predictor for all frames, and is only updated on
212 // key frame. Sync point every 8 frames.
214 // Layer 0: predict from L and ARF, update L and G.
215 layer_flags
[0] = VP8_EFLAG_NO_REF_GF
|
216 VP8_EFLAG_NO_UPD_ARF
;
218 // Layer 1: sync point: predict from L and ARF, and update G.
219 layer_flags
[1] = VP8_EFLAG_NO_REF_GF
|
220 VP8_EFLAG_NO_UPD_LAST
|
221 VP8_EFLAG_NO_UPD_ARF
;
223 // Layer 0, predict from L and ARF, update L.
224 layer_flags
[2] = VP8_EFLAG_NO_REF_GF
|
225 VP8_EFLAG_NO_UPD_GF
|
226 VP8_EFLAG_NO_UPD_ARF
;
228 // Layer 1: predict from L, G and ARF, and update G.
229 layer_flags
[3] = VP8_EFLAG_NO_UPD_ARF
|
230 VP8_EFLAG_NO_UPD_LAST
|
231 VP8_EFLAG_NO_UPD_ENTROPY
;
234 layer_flags
[4] = layer_flags
[2];
237 layer_flags
[5] = layer_flags
[3];
240 layer_flags
[6] = layer_flags
[4];
243 layer_flags
[7] = layer_flags
[5];
250 // 3-layers structure where ARF is used as predictor for all frames,
251 // and is only updated on key frame.
252 // Sync points for layer 1 and 2 every 8 frames.
253 cfg
->ts_number_layers
= 3;
254 cfg
->ts_periodicity
= 4;
255 cfg
->ts_rate_decimator
[0] = 4;
256 cfg
->ts_rate_decimator
[1] = 2;
257 cfg
->ts_rate_decimator
[2] = 1;
258 cfg
->ts_layer_id
[0] = 0;
259 cfg
->ts_layer_id
[1] = 2;
260 cfg
->ts_layer_id
[2] = 1;
261 cfg
->ts_layer_id
[3] = 2;
262 // Use 40/20/40 bit allocation as example.
263 cfg
->ts_target_bitrate
[0] = 0.4f
* bitrate
;
264 cfg
->ts_target_bitrate
[1] = 0.6f
* bitrate
;
265 cfg
->ts_target_bitrate
[2] = bitrate
;
267 /* 0=L, 1=GF, 2=ARF */
269 // Layer 0: predict from L and ARF; update L and G.
270 layer_flags
[0] = VP8_EFLAG_NO_UPD_ARF
|
273 // Layer 2: sync point: predict from L and ARF; update none.
274 layer_flags
[1] = VP8_EFLAG_NO_REF_GF
|
275 VP8_EFLAG_NO_UPD_GF
|
276 VP8_EFLAG_NO_UPD_ARF
|
277 VP8_EFLAG_NO_UPD_LAST
|
278 VP8_EFLAG_NO_UPD_ENTROPY
;
280 // Layer 1: sync point: predict from L and ARF; update G.
281 layer_flags
[2] = VP8_EFLAG_NO_REF_GF
|
282 VP8_EFLAG_NO_UPD_ARF
|
283 VP8_EFLAG_NO_UPD_LAST
;
285 // Layer 2: predict from L, G, ARF; update none.
286 layer_flags
[3] = VP8_EFLAG_NO_UPD_GF
|
287 VP8_EFLAG_NO_UPD_ARF
|
288 VP8_EFLAG_NO_UPD_LAST
|
289 VP8_EFLAG_NO_UPD_ENTROPY
;
291 // Layer 0: predict from L and ARF; update L.
292 layer_flags
[4] = VP8_EFLAG_NO_UPD_GF
|
293 VP8_EFLAG_NO_UPD_ARF
|
296 // Layer 2: predict from L, G, ARF; update none.
297 layer_flags
[5] = layer_flags
[3];
299 // Layer 1: predict from L, G, ARF; update G.
300 layer_flags
[6] = VP8_EFLAG_NO_UPD_ARF
|
301 VP8_EFLAG_NO_UPD_LAST
;
303 // Layer 2: predict from L, G, ARF; update none.
304 layer_flags
[7] = layer_flags
[3];
310 /* The periodicity of the pattern given the number of temporal layers. */
311 static int periodicity_to_num_layers
[MAX_NUM_TEMPORAL_LAYERS
] = {1, 8, 8};
313 int main(int argc
, char **argv
)
315 FILE *infile
, *outfile
[NUM_ENCODERS
];
316 FILE *downsampled_input
[NUM_ENCODERS
- 1];
318 vpx_codec_ctx_t codec
[NUM_ENCODERS
];
319 vpx_codec_enc_cfg_t cfg
[NUM_ENCODERS
];
321 vpx_image_t raw
[NUM_ENCODERS
];
322 vpx_codec_err_t res
[NUM_ENCODERS
];
333 int layer_flags
[VPX_TS_MAX_PERIODICITY
* NUM_ENCODERS
]
335 int flag_periodicity
;
337 /*Currently, only realtime mode is supported in multi-resolution encoding.*/
338 int arg_deadline
= VPX_DL_REALTIME
;
340 /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
341 don't need to know PSNR, which will skip PSNR calculation and save
344 int key_frame_insert
= 0;
345 uint64_t psnr_sse_total
[NUM_ENCODERS
] = {0};
346 uint64_t psnr_samples_total
[NUM_ENCODERS
] = {0};
347 double psnr_totals
[NUM_ENCODERS
][4] = {{0,0}};
348 int psnr_count
[NUM_ENCODERS
] = {0};
352 /* Set the required target bitrates for each resolution level.
353 * If target bitrate for highest-resolution level is set to 0,
354 * (i.e. target_bitrate[0]=0), we skip encoding at that level.
356 unsigned int target_bitrate
[NUM_ENCODERS
]={1000, 500, 100};
358 /* Enter the frame rate of the input video */
361 /* Set down-sampling factor for each resolution level.
362 dsf[0] controls down sampling from level 0 to level 1;
363 dsf[1] controls down sampling from level 1 to level 2;
364 dsf[2] is not used. */
365 vpx_rational_t dsf
[NUM_ENCODERS
] = {{2, 1}, {2, 1}, {1, 1}};
367 /* Set the number of temporal layers for each encoder/resolution level,
368 * starting from highest resoln down to lowest resoln. */
369 unsigned int num_temporal_layers
[NUM_ENCODERS
] = {3, 3, 3};
371 if(argc
!= (7 + 3 * NUM_ENCODERS
))
372 die("Usage: %s <width> <height> <frame_rate> <infile> <outfile(s)> "
373 "<rate_encoder(s)> <temporal_layer(s)> <key_frame_insert> <output psnr?> \n",
376 printf("Using %s\n",vpx_codec_iface_name(interface
));
378 width
= strtol(argv
[1], NULL
, 0);
379 height
= strtol(argv
[2], NULL
, 0);
380 framerate
= strtol(argv
[3], NULL
, 0);
382 if(width
< 16 || width
%2 || height
<16 || height
%2)
383 die("Invalid resolution: %ldx%ld", width
, height
);
385 /* Open input video file for encoding */
386 if(!(infile
= fopen(argv
[4], "rb")))
387 die("Failed to open %s for reading", argv
[4]);
389 /* Open output file for each encoder to output bitstreams */
390 for (i
=0; i
< NUM_ENCODERS
; i
++)
392 if(!target_bitrate
[i
])
398 if(!(outfile
[i
] = fopen(argv
[i
+5], "wb")))
399 die("Failed to open %s for writing", argv
[i
+4]);
402 // Bitrates per spatial layer: overwrite default rates above.
403 for (i
=0; i
< NUM_ENCODERS
; i
++)
405 target_bitrate
[i
] = strtol(argv
[NUM_ENCODERS
+ 5 + i
], NULL
, 0);
408 // Temporal layers per spatial layers: overwrite default settings above.
409 for (i
=0; i
< NUM_ENCODERS
; i
++)
411 num_temporal_layers
[i
] = strtol(argv
[2 * NUM_ENCODERS
+ 5 + i
], NULL
, 0);
412 if (num_temporal_layers
[i
] < 1 || num_temporal_layers
[i
] > 3)
413 die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n",
414 num_temporal_layers
);
417 /* Open file to write out each spatially downsampled input stream. */
418 for (i
=0; i
< NUM_ENCODERS
- 1; i
++)
420 // Highest resoln is encoder 0.
421 if (sprintf(filename
,"ds%d.yuv",NUM_ENCODERS
- i
) < 0)
425 downsampled_input
[i
] = fopen(filename
,"wb");
428 key_frame_insert
= strtol(argv
[3 * NUM_ENCODERS
+ 5], NULL
, 0);
430 show_psnr
= strtol(argv
[3 * NUM_ENCODERS
+ 6], NULL
, 0);
433 /* Populate default encoder configuration */
434 for (i
=0; i
< NUM_ENCODERS
; i
++)
436 res
[i
] = vpx_codec_enc_config_default(interface
, &cfg
[i
], 0);
438 printf("Failed to get config: %s\n", vpx_codec_err_to_string(res
[i
]));
444 * Update the default configuration according to needs of the application.
446 /* Highest-resolution encoder settings */
449 cfg
[0].rc_dropframe_thresh
= 0;
450 cfg
[0].rc_end_usage
= VPX_CBR
;
451 cfg
[0].rc_resize_allowed
= 0;
452 cfg
[0].rc_min_quantizer
= 2;
453 cfg
[0].rc_max_quantizer
= 56;
454 cfg
[0].rc_undershoot_pct
= 100;
455 cfg
[0].rc_overshoot_pct
= 15;
456 cfg
[0].rc_buf_initial_sz
= 500;
457 cfg
[0].rc_buf_optimal_sz
= 600;
458 cfg
[0].rc_buf_sz
= 1000;
459 cfg
[0].g_error_resilient
= 1; /* Enable error resilient mode */
460 cfg
[0].g_lag_in_frames
= 0;
462 /* Disable automatic keyframe placement */
463 /* Note: These 3 settings are copied to all levels. But, except the lowest
464 * resolution level, all other levels are set to VPX_KF_DISABLED internally.
466 cfg
[0].kf_mode
= VPX_KF_AUTO
;
467 cfg
[0].kf_min_dist
= 3000;
468 cfg
[0].kf_max_dist
= 3000;
470 cfg
[0].rc_target_bitrate
= target_bitrate
[0]; /* Set target bitrate */
471 cfg
[0].g_timebase
.num
= 1; /* Set fps */
472 cfg
[0].g_timebase
.den
= framerate
;
474 /* Other-resolution encoder settings */
475 for (i
=1; i
< NUM_ENCODERS
; i
++)
477 memcpy(&cfg
[i
], &cfg
[0], sizeof(vpx_codec_enc_cfg_t
));
479 cfg
[i
].rc_target_bitrate
= target_bitrate
[i
];
481 /* Note: Width & height of other-resolution encoders are calculated
482 * from the highest-resolution encoder's size and the corresponding
483 * down_sampling_factor.
486 unsigned int iw
= cfg
[i
-1].g_w
*dsf
[i
-1].den
+ dsf
[i
-1].num
- 1;
487 unsigned int ih
= cfg
[i
-1].g_h
*dsf
[i
-1].den
+ dsf
[i
-1].num
- 1;
488 cfg
[i
].g_w
= iw
/dsf
[i
-1].num
;
489 cfg
[i
].g_h
= ih
/dsf
[i
-1].num
;
492 /* Make width & height to be multiplier of 2. */
493 // Should support odd size ???
494 if((cfg
[i
].g_w
)%2)cfg
[i
].g_w
++;
495 if((cfg
[i
].g_h
)%2)cfg
[i
].g_h
++;
499 // Set the number of threads per encode/spatial layer.
500 // (1, 1, 1) means no encoder threading.
501 cfg
[0].g_threads
= 2;
502 cfg
[1].g_threads
= 1;
503 cfg
[2].g_threads
= 1;
505 /* Allocate image for each encoder */
506 for (i
=0; i
< NUM_ENCODERS
; i
++)
507 if(!vpx_img_alloc(&raw
[i
], VPX_IMG_FMT_I420
, cfg
[i
].g_w
, cfg
[i
].g_h
, 32))
508 die("Failed to allocate image", cfg
[i
].g_w
, cfg
[i
].g_h
);
510 if (raw
[0].stride
[VPX_PLANE_Y
] == raw
[0].d_w
)
511 read_frame_p
= read_frame
;
513 read_frame_p
= read_frame_by_row
;
515 for (i
=0; i
< NUM_ENCODERS
; i
++)
517 write_ivf_file_header(outfile
[i
], &cfg
[i
], 0);
519 /* Temporal layers settings */
520 for ( i
=0; i
<NUM_ENCODERS
; i
++)
522 set_temporal_layer_pattern(num_temporal_layers
[i
],
524 cfg
[i
].rc_target_bitrate
,
525 &layer_flags
[i
* VPX_TS_MAX_PERIODICITY
]);
528 /* Initialize multi-encoder */
529 if(vpx_codec_enc_init_multi(&codec
[0], interface
, &cfg
[0], NUM_ENCODERS
,
530 (show_psnr
? VPX_CODEC_USE_PSNR
: 0), &dsf
[0]))
531 die_codec(&codec
[0], "Failed to initialize encoder");
533 /* The extra encoding configuration parameters can be set as follows. */
534 /* Set encoding speed */
535 for ( i
=0; i
<NUM_ENCODERS
; i
++)
538 /* Lower speed for the lowest resolution. */
539 if (i
== NUM_ENCODERS
- 1) speed
= -4;
540 if(vpx_codec_control(&codec
[i
], VP8E_SET_CPUUSED
, speed
))
541 die_codec(&codec
[i
], "Failed to set cpu_used");
544 /* Set static threshold = 1 for all encoders */
545 for ( i
=0; i
<NUM_ENCODERS
; i
++)
547 if(vpx_codec_control(&codec
[i
], VP8E_SET_STATIC_THRESHOLD
, 1))
548 die_codec(&codec
[i
], "Failed to set static threshold");
551 /* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
552 /* Enable denoising for the highest-resolution encoder. */
553 if(vpx_codec_control(&codec
[0], VP8E_SET_NOISE_SENSITIVITY
, 1))
554 die_codec(&codec
[0], "Failed to set noise_sensitivity");
555 for ( i
=1; i
< NUM_ENCODERS
; i
++)
557 if(vpx_codec_control(&codec
[i
], VP8E_SET_NOISE_SENSITIVITY
, 0))
558 die_codec(&codec
[i
], "Failed to set noise_sensitivity");
561 /* Set the number of token partitions */
562 for ( i
=0; i
<NUM_ENCODERS
; i
++)
564 if(vpx_codec_control(&codec
[i
], VP8E_SET_TOKEN_PARTITIONS
, 1))
565 die_codec(&codec
[i
], "Failed to set static threshold");
568 /* Set the max intra target bitrate */
569 for ( i
=0; i
<NUM_ENCODERS
; i
++)
571 unsigned int max_intra_size_pct
=
572 (int)(((double)cfg
[0].rc_buf_optimal_sz
* 0.5) * framerate
/ 10);
573 if(vpx_codec_control(&codec
[i
], VP8E_SET_MAX_INTRA_BITRATE_PCT
,
575 die_codec(&codec
[i
], "Failed to set static threshold");
576 //printf("%d %d \n",i,max_intra_size_pct);
582 while(frame_avail
|| got_data
)
584 struct vpx_usec_timer timer
;
585 vpx_codec_iter_t iter
[NUM_ENCODERS
]={NULL
};
586 const vpx_codec_cx_pkt_t
*pkt
[NUM_ENCODERS
];
589 frame_avail
= read_frame_p(infile
, &raw
[0]);
593 for ( i
=1; i
<NUM_ENCODERS
; i
++)
595 /*Scale the image down a number of times by downsampling factor*/
596 /* FilterMode 1 or 2 give better psnr than FilterMode 0. */
597 I420Scale(raw
[i
-1].planes
[VPX_PLANE_Y
], raw
[i
-1].stride
[VPX_PLANE_Y
],
598 raw
[i
-1].planes
[VPX_PLANE_U
], raw
[i
-1].stride
[VPX_PLANE_U
],
599 raw
[i
-1].planes
[VPX_PLANE_V
], raw
[i
-1].stride
[VPX_PLANE_V
],
600 raw
[i
-1].d_w
, raw
[i
-1].d_h
,
601 raw
[i
].planes
[VPX_PLANE_Y
], raw
[i
].stride
[VPX_PLANE_Y
],
602 raw
[i
].planes
[VPX_PLANE_U
], raw
[i
].stride
[VPX_PLANE_U
],
603 raw
[i
].planes
[VPX_PLANE_V
], raw
[i
].stride
[VPX_PLANE_V
],
604 raw
[i
].d_w
, raw
[i
].d_h
, 1);
605 /* Write out down-sampled input. */
606 length_frame
= cfg
[i
].g_w
* cfg
[i
].g_h
*3/2;
607 if (fwrite(raw
[i
].planes
[0], 1, length_frame
,
608 downsampled_input
[NUM_ENCODERS
- i
- 1]) !=
616 /* Set the flags (reference and update) for all the encoders.*/
617 for ( i
=0; i
<NUM_ENCODERS
; i
++)
619 layer_id
= cfg
[i
].ts_layer_id
[frame_cnt
% cfg
[i
].ts_periodicity
];
621 flag_periodicity
= periodicity_to_num_layers
622 [num_temporal_layers
[i
] - 1];
623 flags
= layer_flags
[i
* VPX_TS_MAX_PERIODICITY
+
624 frame_cnt
% flag_periodicity
];
625 // Key frame flag for first frame.
628 flags
|= VPX_EFLAG_FORCE_KF
;
630 if (frame_cnt
> 0 && frame_cnt
== key_frame_insert
)
632 flags
= VPX_EFLAG_FORCE_KF
;
635 vpx_codec_control(&codec
[i
], VP8E_SET_FRAME_FLAGS
, flags
);
636 vpx_codec_control(&codec
[i
], VP8E_SET_TEMPORAL_LAYER_ID
, layer_id
);
639 /* Encode each frame at multi-levels */
640 /* Note the flags must be set to 0 in the encode call if they are set
641 for each frame with the vpx_codec_control(), as done above. */
642 vpx_usec_timer_start(&timer
);
643 if(vpx_codec_encode(&codec
[0], frame_avail
? &raw
[0] : NULL
,
644 frame_cnt
, 1, 0, arg_deadline
))
646 die_codec(&codec
[0], "Failed to encode frame");
648 vpx_usec_timer_mark(&timer
);
649 cx_time
+= vpx_usec_timer_elapsed(&timer
);
651 for (i
=NUM_ENCODERS
-1; i
>=0 ; i
--)
654 while( (pkt
[i
] = vpx_codec_get_cx_data(&codec
[i
], &iter
[i
])) )
657 switch(pkt
[i
]->kind
) {
658 case VPX_CODEC_CX_FRAME_PKT
:
659 write_ivf_frame_header(outfile
[i
], pkt
[i
]);
660 (void) fwrite(pkt
[i
]->data
.frame
.buf
, 1,
661 pkt
[i
]->data
.frame
.sz
, outfile
[i
]);
663 case VPX_CODEC_PSNR_PKT
:
668 psnr_sse_total
[i
] += pkt
[i
]->data
.psnr
.sse
[0];
669 psnr_samples_total
[i
] += pkt
[i
]->data
.psnr
.samples
[0];
670 for (j
= 0; j
< 4; j
++)
672 psnr_totals
[i
][j
] += pkt
[i
]->data
.psnr
.psnr
[j
];
681 printf(pkt
[i
]->kind
== VPX_CODEC_CX_FRAME_PKT
682 && (pkt
[i
]->data
.frame
.flags
& VPX_FRAME_IS_KEY
)? "K":"");
689 printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
691 1000 * (float)cx_time
/ (double)(frame_cnt
* 1000000),
692 1000000 * (double)frame_cnt
/ (double)cx_time
);
696 printf("Processed %ld frames.\n",(long int)frame_cnt
-1);
697 for (i
=0; i
< NUM_ENCODERS
; i
++)
699 /* Calculate PSNR and print it out */
700 if ( (show_psnr
) && (psnr_count
[i
]>0) )
703 double ovpsnr
= sse_to_psnr(psnr_samples_total
[i
], 255.0,
706 fprintf(stderr
, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i
);
708 fprintf(stderr
, " %.3lf", ovpsnr
);
709 for (j
= 0; j
< 4; j
++)
711 fprintf(stderr
, " %.3lf", psnr_totals
[i
][j
]/psnr_count
[i
]);
715 if(vpx_codec_destroy(&codec
[i
]))
716 die_codec(&codec
[i
], "Failed to destroy codec");
718 vpx_img_free(&raw
[i
]);
723 /* Try to rewrite the file header with the actual frame count */
724 if(!fseek(outfile
[i
], 0, SEEK_SET
))
725 write_ivf_file_header(outfile
[i
], &cfg
[i
], frame_cnt
-1);