Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(320)

Side by Side Diff: source/libvpx/vpxenc.c

Issue 111463005: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/vpxenc.h ('k') | source/libvpx/vpxstats.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "vpx_config.h" 11 #include "./vpxenc.h"
12 #include "./vpx_config.h"
12 13
13 #if defined(_WIN32) || defined(__OS2__) || !CONFIG_OS_SUPPORT 14 #include <assert.h>
14 #define USE_POSIX_MMAP 0 15 #include <limits.h>
15 #else 16 #include <math.h>
16 #define USE_POSIX_MMAP 1 17 #include <stdarg.h>
17 #endif
18
19 #include <stdio.h> 18 #include <stdio.h>
20 #include <stdlib.h> 19 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <string.h> 20 #include <string.h>
23 #include <limits.h> 21
24 #include <assert.h>
25 #include "vpx/vpx_encoder.h" 22 #include "vpx/vpx_encoder.h"
26 #if CONFIG_DECODERS 23 #if CONFIG_DECODERS
27 #include "vpx/vpx_decoder.h" 24 #include "vpx/vpx_decoder.h"
28 #endif 25 #endif
29 #if USE_POSIX_MMAP 26
30 #include <sys/types.h> 27 #include "third_party/libyuv/include/libyuv/scale.h"
31 #include <sys/stat.h> 28 #include "./args.h"
32 #include <sys/mman.h> 29 #include "./ivfdec.h"
33 #include <fcntl.h> 30 #include "./ivfenc.h"
34 #include <unistd.h>
35 #endif
36 31
37 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER 32 #if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
38 #include "vpx/vp8cx.h" 33 #include "vpx/vp8cx.h"
39 #endif 34 #endif
40 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER 35 #if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER
41 #include "vpx/vp8dx.h" 36 #include "vpx/vp8dx.h"
42 #endif 37 #endif
43 38
39 #include "./tools_common.h"
44 #include "vpx_ports/mem_ops.h" 40 #include "vpx_ports/mem_ops.h"
45 #include "vpx_ports/vpx_timer.h" 41 #include "vpx_ports/vpx_timer.h"
46 #include "tools_common.h" 42 #include "./vpxstats.h"
47 #include "y4minput.h" 43 #include "./warnings.h"
48 #include "third_party/libmkv/EbmlWriter.h" 44 #include "./webmenc.h"
49 #include "third_party/libmkv/EbmlIDs.h" 45 #include "./y4minput.h"
50 #include "third_party/libyuv/include/libyuv/scale.h"
51
52 /* Need special handling of these functions on Windows */
53 #if defined(_MSC_VER)
54 /* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
55 typedef __int64 off_t;
56 #define fseeko _fseeki64
57 #define ftello _ftelli64
58 #elif defined(_WIN32)
59 /* MinGW defines off_t as long
60 and uses f{seek,tell}o64/off64_t for large files */
61 #define fseeko fseeko64
62 #define ftello ftello64
63 #define off_t off64_t
64 #endif
65
66 #define LITERALU64(hi,lo) ((((uint64_t)hi)<<32)|lo)
67
68 /* We should use 32-bit file operations in WebM file format
69 * when building ARM executable file (.axf) with RVCT */
70 #if !CONFIG_OS_SUPPORT
71 typedef long off_t;
72 #define fseeko fseek
73 #define ftello ftell
74 #endif
75 46
76 /* Swallow warnings about unused results of fread/fwrite */ 47 /* Swallow warnings about unused results of fread/fwrite */
77 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb, 48 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
78 FILE *stream) { 49 FILE *stream) {
79 return fread(ptr, size, nmemb, stream); 50 return fread(ptr, size, nmemb, stream);
80 } 51 }
81 #define fread wrap_fread 52 #define fread wrap_fread
82 53
83 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb, 54 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
84 FILE *stream) { 55 FILE *stream) {
85 return fwrite(ptr, size, nmemb, stream); 56 return fwrite(ptr, size, nmemb, stream);
86 } 57 }
87 #define fwrite wrap_fwrite 58 #define fwrite wrap_fwrite
88 59
89 60
90 static const char *exec_name; 61 static const char *exec_name;
91 62
92 #define VP8_FOURCC (0x30385056)
93 #define VP9_FOURCC (0x30395056)
94 static const struct codec_item { 63 static const struct codec_item {
95 char const *name; 64 char const *name;
96 const vpx_codec_iface_t *(*iface)(void); 65 const vpx_codec_iface_t *(*iface)(void);
97 const vpx_codec_iface_t *(*dx_iface)(void); 66 const vpx_codec_iface_t *(*dx_iface)(void);
98 unsigned int fourcc; 67 unsigned int fourcc;
99 } codecs[] = { 68 } codecs[] = {
100 #if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER 69 #if CONFIG_VP8_ENCODER && CONFIG_VP8_DECODER
101 {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC}, 70 {"vp8", &vpx_codec_vp8_cx, &vpx_codec_vp8_dx, VP8_FOURCC},
102 #elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER 71 #elif CONFIG_VP8_ENCODER && !CONFIG_VP8_DECODER
103 {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC}, 72 {"vp8", &vpx_codec_vp8_cx, NULL, VP8_FOURCC},
104 #endif 73 #endif
105 #if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER 74 #if CONFIG_VP9_ENCODER && CONFIG_VP9_DECODER
106 {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC}, 75 {"vp9", &vpx_codec_vp9_cx, &vpx_codec_vp9_dx, VP9_FOURCC},
107 #elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER 76 #elif CONFIG_VP9_ENCODER && !CONFIG_VP9_DECODER
108 {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC}, 77 {"vp9", &vpx_codec_vp9_cx, NULL, VP9_FOURCC},
109 #endif 78 #endif
110 }; 79 };
111 80
112 static void usage_exit();
113
114 #define LOG_ERROR(label) do \
115 {\
116 const char *l=label;\
117 va_list ap;\
118 va_start(ap, fmt);\
119 if(l)\
120 fprintf(stderr, "%s: ", l);\
121 vfprintf(stderr, fmt, ap);\
122 fprintf(stderr, "\n");\
123 va_end(ap);\
124 } while(0)
125
126 void die(const char *fmt, ...) {
127 LOG_ERROR(NULL);
128 usage_exit();
129 }
130
131
132 void fatal(const char *fmt, ...) {
133 LOG_ERROR("Fatal");
134 exit(EXIT_FAILURE);
135 }
136
137
138 void warn(const char *fmt, ...) {
139 LOG_ERROR("Warning");
140 }
141
142
143 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal, 81 static void warn_or_exit_on_errorv(vpx_codec_ctx_t *ctx, int fatal,
144 const char *s, va_list ap) { 82 const char *s, va_list ap) {
145 if (ctx->err) { 83 if (ctx->err) {
146 const char *detail = vpx_codec_error_detail(ctx); 84 const char *detail = vpx_codec_error_detail(ctx);
147 85
148 vfprintf(stderr, s, ap); 86 vfprintf(stderr, s, ap);
149 fprintf(stderr, ": %s\n", vpx_codec_error(ctx)); 87 fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
150 88
151 if (detail) 89 if (detail)
152 fprintf(stderr, " %s\n", detail); 90 fprintf(stderr, " %s\n", detail);
(...skipping 13 matching lines...) Expand all
166 104
167 static void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal, 105 static void warn_or_exit_on_error(vpx_codec_ctx_t *ctx, int fatal,
168 const char *s, ...) { 106 const char *s, ...) {
169 va_list ap; 107 va_list ap;
170 108
171 va_start(ap, s); 109 va_start(ap, s);
172 warn_or_exit_on_errorv(ctx, fatal, s, ap); 110 warn_or_exit_on_errorv(ctx, fatal, s, ap);
173 va_end(ap); 111 va_end(ap);
174 } 112 }
175 113
176 /* This structure is used to abstract the different ways of handling 114 int read_frame(struct VpxInputContext *input_ctx, vpx_image_t *img) {
177 * first pass statistics. 115 FILE *f = input_ctx->file;
178 */ 116 y4m_input *y4m = &input_ctx->y4m;
179 typedef struct {
180 vpx_fixed_buf_t buf;
181 int pass;
182 FILE *file;
183 char *buf_ptr;
184 size_t buf_alloc_sz;
185 } stats_io_t;
186
187 int stats_open_file(stats_io_t *stats, const char *fpf, int pass) {
188 int res;
189
190 stats->pass = pass;
191
192 if (pass == 0) {
193 stats->file = fopen(fpf, "wb");
194 stats->buf.sz = 0;
195 stats->buf.buf = NULL,
196 res = (stats->file != NULL);
197 } else {
198 #if 0
199 #elif USE_POSIX_MMAP
200 struct stat stat_buf;
201 int fd;
202
203 fd = open(fpf, O_RDONLY);
204 stats->file = fdopen(fd, "rb");
205 fstat(fd, &stat_buf);
206 stats->buf.sz = stat_buf.st_size;
207 stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE,
208 fd, 0);
209 res = (stats->buf.buf != NULL);
210 #else
211 size_t nbytes;
212
213 stats->file = fopen(fpf, "rb");
214
215 if (fseek(stats->file, 0, SEEK_END))
216 fatal("First-pass stats file must be seekable!");
217
218 stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
219 rewind(stats->file);
220
221 stats->buf.buf = malloc(stats->buf_alloc_sz);
222
223 if (!stats->buf.buf)
224 fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
225 (unsigned long)stats->buf_alloc_sz);
226
227 nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
228 res = (nbytes == stats->buf.sz);
229 #endif
230 }
231
232 return res;
233 }
234
235 int stats_open_mem(stats_io_t *stats, int pass) {
236 int res;
237 stats->pass = pass;
238
239 if (!pass) {
240 stats->buf.sz = 0;
241 stats->buf_alloc_sz = 64 * 1024;
242 stats->buf.buf = malloc(stats->buf_alloc_sz);
243 }
244
245 stats->buf_ptr = stats->buf.buf;
246 res = (stats->buf.buf != NULL);
247 return res;
248 }
249
250
251 void stats_close(stats_io_t *stats, int last_pass) {
252 if (stats->file) {
253 if (stats->pass == last_pass) {
254 #if 0
255 #elif USE_POSIX_MMAP
256 munmap(stats->buf.buf, stats->buf.sz);
257 #else
258 free(stats->buf.buf);
259 #endif
260 }
261
262 fclose(stats->file);
263 stats->file = NULL;
264 } else {
265 if (stats->pass == last_pass)
266 free(stats->buf.buf);
267 }
268 }
269
270 void stats_write(stats_io_t *stats, const void *pkt, size_t len) {
271 if (stats->file) {
272 (void) fwrite(pkt, 1, len, stats->file);
273 } else {
274 if (stats->buf.sz + len > stats->buf_alloc_sz) {
275 size_t new_sz = stats->buf_alloc_sz + 64 * 1024;
276 char *new_ptr = realloc(stats->buf.buf, new_sz);
277
278 if (new_ptr) {
279 stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
280 stats->buf.buf = new_ptr;
281 stats->buf_alloc_sz = new_sz;
282 } else
283 fatal("Failed to realloc firstpass stats buffer.");
284 }
285
286 memcpy(stats->buf_ptr, pkt, len);
287 stats->buf.sz += len;
288 stats->buf_ptr += len;
289 }
290 }
291
292 vpx_fixed_buf_t stats_get(stats_io_t *stats) {
293 return stats->buf;
294 }
295
296 /* Stereo 3D packed frame format */
297 typedef enum stereo_format {
298 STEREO_FORMAT_MONO = 0,
299 STEREO_FORMAT_LEFT_RIGHT = 1,
300 STEREO_FORMAT_BOTTOM_TOP = 2,
301 STEREO_FORMAT_TOP_BOTTOM = 3,
302 STEREO_FORMAT_RIGHT_LEFT = 11
303 } stereo_format_t;
304
305 enum video_file_type {
306 FILE_TYPE_RAW,
307 FILE_TYPE_IVF,
308 FILE_TYPE_Y4M
309 };
310
311 struct detect_buffer {
312 char buf[4];
313 size_t buf_read;
314 size_t position;
315 };
316
317
318 struct input_state {
319 char *fn;
320 FILE *file;
321 off_t length;
322 y4m_input y4m;
323 struct detect_buffer detect;
324 enum video_file_type file_type;
325 unsigned int w;
326 unsigned int h;
327 struct vpx_rational framerate;
328 int use_i420;
329 int only_i420;
330 };
331
332
333 #define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
334 static int read_frame(struct input_state *input, vpx_image_t *img) {
335 FILE *f = input->file;
336 enum video_file_type file_type = input->file_type;
337 y4m_input *y4m = &input->y4m;
338 struct detect_buffer *detect = &input->detect;
339 int plane = 0;
340 int shortread = 0; 117 int shortread = 0;
341 118
342 if (file_type == FILE_TYPE_Y4M) { 119 if (input_ctx->file_type == FILE_TYPE_Y4M) {
343 if (y4m_input_fetch_frame(y4m, f, img) < 1) 120 if (y4m_input_fetch_frame(y4m, f, img) < 1)
344 return 0; 121 return 0;
345 } else { 122 } else {
346 if (file_type == FILE_TYPE_IVF) { 123 shortread = read_yuv_frame(input_ctx, img);
347 char junk[IVF_FRAME_HDR_SZ];
348
349 /* Skip the frame header. We know how big the frame should be. See
350 * write_ivf_frame_header() for documentation on the frame header
351 * layout.
352 */
353 (void) fread(junk, 1, IVF_FRAME_HDR_SZ, f);
354 }
355
356 for (plane = 0; plane < 3; plane++) {
357 unsigned char *ptr;
358 int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
359 int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
360 int r;
361
362 /* Determine the correct plane based on the image format. The for-loop
363 * always counts in Y,U,V order, but this may not match the order of
364 * the data on disk.
365 */
366 switch (plane) {
367 case 1:
368 ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_V : VPX_PLA NE_U];
369 break;
370 case 2:
371 ptr = img->planes[img->fmt == VPX_IMG_FMT_YV12 ? VPX_PLANE_U : VPX_PLA NE_V];
372 break;
373 default:
374 ptr = img->planes[plane];
375 }
376
377 for (r = 0; r < h; r++) {
378 size_t needed = w;
379 size_t buf_position = 0;
380 const size_t left = detect->buf_read - detect->position;
381 if (left > 0) {
382 const size_t more = (left < needed) ? left : needed;
383 memcpy(ptr, detect->buf + detect->position, more);
384 buf_position = more;
385 needed -= more;
386 detect->position += more;
387 }
388 if (needed > 0) {
389 shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
390 }
391
392 ptr += img->stride[plane];
393 }
394 }
395 } 124 }
396 125
397 return !shortread; 126 return !shortread;
398 } 127 }
399 128
400 129 int file_is_y4m(FILE *infile, y4m_input *y4m, const char detect[4]) {
401 unsigned int file_is_y4m(FILE *infile,
402 y4m_input *y4m,
403 char detect[4]) {
404 if (memcmp(detect, "YUV4", 4) == 0) { 130 if (memcmp(detect, "YUV4", 4) == 0) {
405 return 1; 131 return 1;
406 } 132 }
407 return 0; 133 return 0;
408 } 134 }
409 135
410 #define IVF_FILE_HDR_SZ (32)
411 unsigned int file_is_ivf(struct input_state *input,
412 unsigned int *fourcc) {
413 char raw_hdr[IVF_FILE_HDR_SZ];
414 int is_ivf = 0;
415 FILE *infile = input->file;
416 unsigned int *width = &input->w;
417 unsigned int *height = &input->h;
418 struct detect_buffer *detect = &input->detect;
419
420 if (memcmp(detect->buf, "DKIF", 4) != 0)
421 return 0;
422
423 /* See write_ivf_file_header() for more documentation on the file header
424 * layout.
425 */
426 if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
427 == IVF_FILE_HDR_SZ - 4) {
428 {
429 is_ivf = 1;
430
431 if (mem_get_le16(raw_hdr + 4) != 0)
432 warn("Unrecognized IVF version! This file may not decode "
433 "properly.");
434
435 *fourcc = mem_get_le32(raw_hdr + 8);
436 }
437 }
438
439 if (is_ivf) {
440 *width = mem_get_le16(raw_hdr + 12);
441 *height = mem_get_le16(raw_hdr + 14);
442 detect->position = 4;
443 }
444
445 return is_ivf;
446 }
447
448
449 static void write_ivf_file_header(FILE *outfile,
450 const vpx_codec_enc_cfg_t *cfg,
451 unsigned int fourcc,
452 int frame_cnt) {
453 char header[32];
454
455 if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
456 return;
457
458 header[0] = 'D';
459 header[1] = 'K';
460 header[2] = 'I';
461 header[3] = 'F';
462 mem_put_le16(header + 4, 0); /* version */
463 mem_put_le16(header + 6, 32); /* headersize */
464 mem_put_le32(header + 8, fourcc); /* headersize */
465 mem_put_le16(header + 12, cfg->g_w); /* width */
466 mem_put_le16(header + 14, cfg->g_h); /* height */
467 mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
468 mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
469 mem_put_le32(header + 24, frame_cnt); /* length */
470 mem_put_le32(header + 28, 0); /* unused */
471
472 (void) fwrite(header, 1, 32, outfile);
473 }
474
475
476 static void write_ivf_frame_header(FILE *outfile,
477 const vpx_codec_cx_pkt_t *pkt) {
478 char header[12];
479 vpx_codec_pts_t pts;
480
481 if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
482 return;
483
484 pts = pkt->data.frame.pts;
485 mem_put_le32(header, (int)pkt->data.frame.sz);
486 mem_put_le32(header + 4, pts & 0xFFFFFFFF);
487 mem_put_le32(header + 8, pts >> 32);
488
489 (void) fwrite(header, 1, 12, outfile);
490 }
491
492 static void write_ivf_frame_size(FILE *outfile, size_t size) {
493 char header[4];
494 mem_put_le32(header, (int)size);
495 (void) fwrite(header, 1, 4, outfile);
496 }
497
498
499 typedef off_t EbmlLoc;
500
501
502 struct cue_entry {
503 unsigned int time;
504 uint64_t loc;
505 };
506
507
508 struct EbmlGlobal {
509 int debug;
510
511 FILE *stream;
512 int64_t last_pts_ms;
513 vpx_rational_t framerate;
514
515 /* These pointers are to the start of an element */
516 off_t position_reference;
517 off_t seek_info_pos;
518 off_t segment_info_pos;
519 off_t track_pos;
520 off_t cue_pos;
521 off_t cluster_pos;
522
523 /* This pointer is to a specific element to be serialized */
524 off_t track_id_pos;
525
526 /* These pointers are to the size field of the element */
527 EbmlLoc startSegment;
528 EbmlLoc startCluster;
529
530 uint32_t cluster_timecode;
531 int cluster_open;
532
533 struct cue_entry *cue_list;
534 unsigned int cues;
535
536 };
537
538
539 void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len) {
540 (void) fwrite(buffer_in, 1, len, glob->stream);
541 }
542
543 #define WRITE_BUFFER(s) \
544 for(i = len-1; i>=0; i--)\
545 { \
546 x = (char)(*(const s *)buffer_in >> (i * CHAR_BIT)); \
547 Ebml_Write(glob, &x, 1); \
548 }
549 void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, un signed long len) {
550 char x;
551 int i;
552
553 /* buffer_size:
554 * 1 - int8_t;
555 * 2 - int16_t;
556 * 3 - int32_t;
557 * 4 - int64_t;
558 */
559 switch (buffer_size) {
560 case 1:
561 WRITE_BUFFER(int8_t)
562 break;
563 case 2:
564 WRITE_BUFFER(int16_t)
565 break;
566 case 4:
567 WRITE_BUFFER(int32_t)
568 break;
569 case 8:
570 WRITE_BUFFER(int64_t)
571 break;
572 default:
573 break;
574 }
575 }
576 #undef WRITE_BUFFER
577
578 /* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
579 * one, but not a 32 bit one.
580 */
581 static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, u int64_t ui) {
582 unsigned char sizeSerialized = 4 | 0x80;
583 Ebml_WriteID(glob, class_id);
584 Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
585 Ebml_Serialize(glob, &ui, sizeof(ui), 4);
586 }
587
588
589 static void
590 Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
591 unsigned long class_id) {
592 /* todo this is always taking 8 bytes, this may need later optimization */
593 /* this is a key that says length unknown */
594 uint64_t unknownLen = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
595
596 Ebml_WriteID(glob, class_id);
597 *ebmlLoc = ftello(glob->stream);
598 Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
599 }
600
601 static void
602 Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) {
603 off_t pos;
604 uint64_t size;
605
606 /* Save the current stream pointer */
607 pos = ftello(glob->stream);
608
609 /* Calculate the size of this element */
610 size = pos - *ebmlLoc - 8;
611 size |= LITERALU64(0x01000000, 0x00000000);
612
613 /* Seek back to the beginning of the element and write the new size */
614 fseeko(glob->stream, *ebmlLoc, SEEK_SET);
615 Ebml_Serialize(glob, &size, sizeof(size), 8);
616
617 /* Reset the stream pointer */
618 fseeko(glob->stream, pos, SEEK_SET);
619 }
620
621
622 static void
623 write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos) {
624 uint64_t offset = pos - ebml->position_reference;
625 EbmlLoc start;
626 Ebml_StartSubElement(ebml, &start, Seek);
627 Ebml_SerializeBinary(ebml, SeekID, id);
628 Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
629 Ebml_EndSubElement(ebml, &start);
630 }
631
632
633 static void
634 write_webm_seek_info(EbmlGlobal *ebml) {
635
636 off_t pos;
637
638 /* Save the current stream pointer */
639 pos = ftello(ebml->stream);
640
641 if (ebml->seek_info_pos)
642 fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
643 else
644 ebml->seek_info_pos = pos;
645
646 {
647 EbmlLoc start;
648
649 Ebml_StartSubElement(ebml, &start, SeekHead);
650 write_webm_seek_element(ebml, Tracks, ebml->track_pos);
651 write_webm_seek_element(ebml, Cues, ebml->cue_pos);
652 write_webm_seek_element(ebml, Info, ebml->segment_info_pos);
653 Ebml_EndSubElement(ebml, &start);
654 }
655 {
656 /* segment info */
657 EbmlLoc startInfo;
658 uint64_t frame_time;
659 char version_string[64];
660
661 /* Assemble version string */
662 if (ebml->debug)
663 strcpy(version_string, "vpxenc");
664 else {
665 strcpy(version_string, "vpxenc ");
666 strncat(version_string,
667 vpx_codec_version_str(),
668 sizeof(version_string) - 1 - strlen(version_string));
669 }
670
671 frame_time = (uint64_t)1000 * ebml->framerate.den
672 / ebml->framerate.num;
673 ebml->segment_info_pos = ftello(ebml->stream);
674 Ebml_StartSubElement(ebml, &startInfo, Info);
675 Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
676 Ebml_SerializeFloat(ebml, Segment_Duration,
677 (double)(ebml->last_pts_ms + frame_time));
678 Ebml_SerializeString(ebml, 0x4D80, version_string);
679 Ebml_SerializeString(ebml, 0x5741, version_string);
680 Ebml_EndSubElement(ebml, &startInfo);
681 }
682 }
683
684
685 static void
686 write_webm_file_header(EbmlGlobal *glob,
687 const vpx_codec_enc_cfg_t *cfg,
688 const struct vpx_rational *fps,
689 stereo_format_t stereo_fmt,
690 unsigned int fourcc) {
691 {
692 EbmlLoc start;
693 Ebml_StartSubElement(glob, &start, EBML);
694 Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
695 Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
696 Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
697 Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
698 Ebml_SerializeString(glob, DocType, "webm");
699 Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
700 Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
701 Ebml_EndSubElement(glob, &start);
702 }
703 {
704 Ebml_StartSubElement(glob, &glob->startSegment, Segment);
705 glob->position_reference = ftello(glob->stream);
706 glob->framerate = *fps;
707 write_webm_seek_info(glob);
708
709 {
710 EbmlLoc trackStart;
711 glob->track_pos = ftello(glob->stream);
712 Ebml_StartSubElement(glob, &trackStart, Tracks);
713 {
714 unsigned int trackNumber = 1;
715 uint64_t trackID = 0;
716
717 EbmlLoc start;
718 Ebml_StartSubElement(glob, &start, TrackEntry);
719 Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
720 glob->track_id_pos = ftello(glob->stream);
721 Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
722 Ebml_SerializeUnsigned(glob, TrackType, 1);
723 Ebml_SerializeString(glob, CodecID,
724 fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9");
725 {
726 unsigned int pixelWidth = cfg->g_w;
727 unsigned int pixelHeight = cfg->g_h;
728
729 EbmlLoc videoStart;
730 Ebml_StartSubElement(glob, &videoStart, Video);
731 Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
732 Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
733 Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
734 Ebml_EndSubElement(glob, &videoStart);
735 }
736 Ebml_EndSubElement(glob, &start); /* Track Entry */
737 }
738 Ebml_EndSubElement(glob, &trackStart);
739 }
740 /* segment element is open */
741 }
742 }
743
744
745 static void
746 write_webm_block(EbmlGlobal *glob,
747 const vpx_codec_enc_cfg_t *cfg,
748 const vpx_codec_cx_pkt_t *pkt) {
749 unsigned long block_length;
750 unsigned char track_number;
751 unsigned short block_timecode = 0;
752 unsigned char flags;
753 int64_t pts_ms;
754 int start_cluster = 0, is_keyframe;
755
756 /* Calculate the PTS of this frame in milliseconds */
757 pts_ms = pkt->data.frame.pts * 1000
758 * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
759 if (pts_ms <= glob->last_pts_ms)
760 pts_ms = glob->last_pts_ms + 1;
761 glob->last_pts_ms = pts_ms;
762
763 /* Calculate the relative time of this block */
764 if (pts_ms - glob->cluster_timecode > SHRT_MAX)
765 start_cluster = 1;
766 else
767 block_timecode = (unsigned short)pts_ms - glob->cluster_timecode;
768
769 is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
770 if (start_cluster || is_keyframe) {
771 if (glob->cluster_open)
772 Ebml_EndSubElement(glob, &glob->startCluster);
773
774 /* Open the new cluster */
775 block_timecode = 0;
776 glob->cluster_open = 1;
777 glob->cluster_timecode = (uint32_t)pts_ms;
778 glob->cluster_pos = ftello(glob->stream);
779 Ebml_StartSubElement(glob, &glob->startCluster, Cluster); /* cluster */
780 Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
781
782 /* Save a cue point if this is a keyframe. */
783 if (is_keyframe) {
784 struct cue_entry *cue, *new_cue_list;
785
786 new_cue_list = realloc(glob->cue_list,
787 (glob->cues + 1) * sizeof(struct cue_entry));
788 if (new_cue_list)
789 glob->cue_list = new_cue_list;
790 else
791 fatal("Failed to realloc cue list.");
792
793 cue = &glob->cue_list[glob->cues];
794 cue->time = glob->cluster_timecode;
795 cue->loc = glob->cluster_pos;
796 glob->cues++;
797 }
798 }
799
800 /* Write the Simple Block */
801 Ebml_WriteID(glob, SimpleBlock);
802
803 block_length = (unsigned long)pkt->data.frame.sz + 4;
804 block_length |= 0x10000000;
805 Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
806
807 track_number = 1;
808 track_number |= 0x80;
809 Ebml_Write(glob, &track_number, 1);
810
811 Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
812
813 flags = 0;
814 if (is_keyframe)
815 flags |= 0x80;
816 if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
817 flags |= 0x08;
818 Ebml_Write(glob, &flags, 1);
819
820 Ebml_Write(glob, pkt->data.frame.buf, (unsigned long)pkt->data.frame.sz);
821 }
822
823
824 static void
825 write_webm_file_footer(EbmlGlobal *glob, long hash) {
826
827 if (glob->cluster_open)
828 Ebml_EndSubElement(glob, &glob->startCluster);
829
830 {
831 EbmlLoc start;
832 unsigned int i;
833
834 glob->cue_pos = ftello(glob->stream);
835 Ebml_StartSubElement(glob, &start, Cues);
836 for (i = 0; i < glob->cues; i++) {
837 struct cue_entry *cue = &glob->cue_list[i];
838 EbmlLoc start;
839
840 Ebml_StartSubElement(glob, &start, CuePoint);
841 {
842 EbmlLoc start;
843
844 Ebml_SerializeUnsigned(glob, CueTime, cue->time);
845
846 Ebml_StartSubElement(glob, &start, CueTrackPositions);
847 Ebml_SerializeUnsigned(glob, CueTrack, 1);
848 Ebml_SerializeUnsigned64(glob, CueClusterPosition,
849 cue->loc - glob->position_reference);
850 Ebml_EndSubElement(glob, &start);
851 }
852 Ebml_EndSubElement(glob, &start);
853 }
854 Ebml_EndSubElement(glob, &start);
855 }
856
857 Ebml_EndSubElement(glob, &glob->startSegment);
858
859 /* Patch up the seek info block */
860 write_webm_seek_info(glob);
861
862 /* Patch up the track id */
863 fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
864 Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
865
866 fseeko(glob->stream, 0, SEEK_END);
867 }
868
869 136
870 /* Murmur hash derived from public domain reference implementation at 137 /* Murmur hash derived from public domain reference implementation at
871 * http:// sites.google.com/site/murmurhash/ 138 * http:// sites.google.com/site/murmurhash/
872 */ 139 */
873 static unsigned int murmur(const void *key, int len, unsigned int seed) { 140 static unsigned int murmur(const void *key, int len, unsigned int seed) {
874 const unsigned int m = 0x5bd1e995; 141 const unsigned int m = 0x5bd1e995;
875 const int r = 24; 142 const int r = 24;
876 143
877 unsigned int h = seed ^ len; 144 unsigned int h = seed ^ len;
878 145
(...skipping 28 matching lines...) Expand all
907 h *= m; 174 h *= m;
908 }; 175 };
909 176
910 h ^= h >> 13; 177 h ^= h >> 13;
911 h *= m; 178 h *= m;
912 h ^= h >> 15; 179 h ^= h >> 15;
913 180
914 return h; 181 return h;
915 } 182 }
916 183
917 #include "math.h"
918 #define MAX_PSNR 100
919 static double vp8_mse2psnr(double Samples, double Peak, double Mse) {
920 double psnr;
921 184
922 if ((double)Mse > 0.0)
923 psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
924 else
925 psnr = MAX_PSNR; /* Limit to prevent / 0 */
926
927 if (psnr > MAX_PSNR)
928 psnr = MAX_PSNR;
929
930 return psnr;
931 }
932
933
934 #include "args.h"
935 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0, 185 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
936 "Debug mode (makes output determinist ic)"); 186 "Debug mode (makes output determinist ic)");
937 static const arg_def_t outputfile = ARG_DEF("o", "output", 1, 187 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
938 "Output filename"); 188 "Output filename");
939 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0, 189 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
940 "Input file is YV12 "); 190 "Input file is YV12 ");
941 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0, 191 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
942 "Input file is I420 (default)"); 192 "Input file is I420 (default)");
943 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1, 193 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
944 "Codec to use"); 194 "Codec to use");
(...skipping 14 matching lines...) Expand all
959 static const arg_def_t good_dl = ARG_DEF(NULL, "good", 0, 209 static const arg_def_t good_dl = ARG_DEF(NULL, "good", 0,
960 "Use Good Quality Deadline"); 210 "Use Good Quality Deadline");
961 static const arg_def_t rt_dl = ARG_DEF(NULL, "rt", 0, 211 static const arg_def_t rt_dl = ARG_DEF(NULL, "rt", 0,
962 "Use Realtime Quality Deadline "); 212 "Use Realtime Quality Deadline ");
963 static const arg_def_t quietarg = ARG_DEF("q", "quiet", 0, 213 static const arg_def_t quietarg = ARG_DEF("q", "quiet", 0,
964 "Do not print encode progress" ); 214 "Do not print encode progress" );
965 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0, 215 static const arg_def_t verbosearg = ARG_DEF("v", "verbose", 0,
966 "Show encoder parameters"); 216 "Show encoder parameters");
967 static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0, 217 static const arg_def_t psnrarg = ARG_DEF(NULL, "psnr", 0,
968 "Show PSNR in status line"); 218 "Show PSNR in status line");
969 enum TestDecodeFatality { 219
970 TEST_DECODE_OFF,
971 TEST_DECODE_FATAL,
972 TEST_DECODE_WARN,
973 };
974 static const struct arg_enum_list test_decode_enum[] = { 220 static const struct arg_enum_list test_decode_enum[] = {
975 {"off", TEST_DECODE_OFF}, 221 {"off", TEST_DECODE_OFF},
976 {"fatal", TEST_DECODE_FATAL}, 222 {"fatal", TEST_DECODE_FATAL},
977 {"warn", TEST_DECODE_WARN}, 223 {"warn", TEST_DECODE_WARN},
978 {NULL, 0} 224 {NULL, 0}
979 }; 225 };
980 static const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1, 226 static const arg_def_t recontest = ARG_DEF_ENUM(NULL, "test-decode", 1,
981 "Test encode/decode mismatch", 227 "Test encode/decode mismatch",
982 test_decode_enum); 228 test_decode_enum);
983 static const arg_def_t framerate = ARG_DEF(NULL, "fps", 1, 229 static const arg_def_t framerate = ARG_DEF(NULL, "fps", 1,
984 "Stream frame rate (rate/scale )"); 230 "Stream frame rate (rate/scale )");
985 static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0, 231 static const arg_def_t use_ivf = ARG_DEF(NULL, "ivf", 0,
986 "Output IVF (default is WebM)" ); 232 "Output IVF (default is WebM)" );
987 static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0, 233 static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
988 "Makes encoder output partitions. Requ ires IVF output!"); 234 "Makes encoder output partitions. Requ ires IVF output!");
989 static const arg_def_t q_hist_n = ARG_DEF(NULL, "q-hist", 1, 235 static const arg_def_t q_hist_n = ARG_DEF(NULL, "q-hist", 1,
990 "Show quantizer histogram (n-b uckets)"); 236 "Show quantizer histogram (n-b uckets)");
991 static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1, 237 static const arg_def_t rate_hist_n = ARG_DEF(NULL, "rate-hist", 1,
992 "Show rate histogram (n-buc kets)"); 238 "Show rate histogram (n-buc kets)");
239 static const arg_def_t disable_warnings =
240 ARG_DEF(NULL, "disable-warnings", 0,
241 "Disable warnings about potentially incorrect encode settings.");
242 static const arg_def_t disable_warning_prompt =
243 ARG_DEF("y", "disable-warning-prompt", 0,
244 "Display warnings, but do not prompt user to continue.");
245
993 static const arg_def_t *main_args[] = { 246 static const arg_def_t *main_args[] = {
994 &debugmode, 247 &debugmode,
995 &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip, 248 &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &skip,
996 &deadline, &best_dl, &good_dl, &rt_dl, 249 &deadline, &best_dl, &good_dl, &rt_dl,
997 &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n , 250 &quietarg, &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n,
251 &rate_hist_n, &disable_warnings, &disable_warning_prompt,
998 NULL 252 NULL
999 }; 253 };
1000 254
1001 static const arg_def_t usage = ARG_DEF("u", "usage", 1, 255 static const arg_def_t usage = ARG_DEF("u", "usage", 1,
1002 "Usage profile number to use") ; 256 "Usage profile number to use") ;
1003 static const arg_def_t threads = ARG_DEF("t", "threads", 1, 257 static const arg_def_t threads = ARG_DEF("t", "threads", 1,
1004 "Max number of threads to use" ); 258 "Max number of threads to use" );
1005 static const arg_def_t profile = ARG_DEF(NULL, "profile", 1, 259 static const arg_def_t profile = ARG_DEF(NULL, "profile", 1,
1006 "Bitstream profile number to u se"); 260 "Bitstream profile number to u se");
1007 static const arg_def_t width = ARG_DEF("w", "width", 1, 261 static const arg_def_t width = ARG_DEF("w", "width", 1,
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
1125 static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1, 379 static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
1126 "Material to favor", tuning_enum ); 380 "Material to favor", tuning_enum );
1127 static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1, 381 static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
1128 "Constant/Constrained Quality level"); 382 "Constant/Constrained Quality level");
1129 static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1, 383 static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
1130 "Max I-frame bitrate (pct)") ; 384 "Max I-frame bitrate (pct)") ;
1131 static const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode"); 385 static const arg_def_t lossless = ARG_DEF(NULL, "lossless", 1, "Lossless mode");
1132 #if CONFIG_VP9_ENCODER 386 #if CONFIG_VP9_ENCODER
1133 static const arg_def_t frame_parallel_decoding = ARG_DEF( 387 static const arg_def_t frame_parallel_decoding = ARG_DEF(
1134 NULL, "frame-parallel", 1, "Enable frame parallel decodability features"); 388 NULL, "frame-parallel", 1, "Enable frame parallel decodability features");
389 static const arg_def_t aq_mode = ARG_DEF(
390 NULL, "aq-mode", 1,
391 "Adaptive q mode (0: off (by default), 1: variance 2: complexity)");
1135 #endif 392 #endif
1136 393
1137 #if CONFIG_VP8_ENCODER 394 #if CONFIG_VP8_ENCODER
1138 static const arg_def_t *vp8_args[] = { 395 static const arg_def_t *vp8_args[] = {
1139 &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh, 396 &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
1140 &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type, 397 &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
1141 &tune_ssim, &cq_level, &max_intra_rate_pct, 398 &tune_ssim, &cq_level, &max_intra_rate_pct,
1142 NULL 399 NULL
1143 }; 400 };
1144 static const int vp8_arg_ctrl_map[] = { 401 static const int vp8_arg_ctrl_map[] = {
1145 VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF, 402 VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
1146 VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD, 403 VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
1147 VP8E_SET_TOKEN_PARTITIONS, 404 VP8E_SET_TOKEN_PARTITIONS,
1148 VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE, 405 VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
1149 VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 406 VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
1150 0 407 0
1151 }; 408 };
1152 #endif 409 #endif
1153 410
1154 #if CONFIG_VP9_ENCODER 411 #if CONFIG_VP9_ENCODER
1155 static const arg_def_t *vp9_args[] = { 412 static const arg_def_t *vp9_args[] = {
1156 &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh, 413 &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
1157 &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type, 414 &tile_cols, &tile_rows, &arnr_maxframes, &arnr_strength, &arnr_type,
1158 &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless, 415 &tune_ssim, &cq_level, &max_intra_rate_pct, &lossless,
1159 &frame_parallel_decoding, 416 &frame_parallel_decoding, &aq_mode,
1160 NULL 417 NULL
1161 }; 418 };
1162 static const int vp9_arg_ctrl_map[] = { 419 static const int vp9_arg_ctrl_map[] = {
1163 VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF, 420 VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
1164 VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD, 421 VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
1165 VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS, 422 VP9E_SET_TILE_COLUMNS, VP9E_SET_TILE_ROWS,
1166 VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE, 423 VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH, VP8E_SET_ARNR_TYPE,
1167 VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 424 VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT,
1168 VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, 425 VP9E_SET_LOSSLESS, VP9E_SET_FRAME_PARALLEL_DECODING, VP9E_SET_AQ_MODE,
1169 0 426 0
1170 }; 427 };
1171 #endif 428 #endif
1172 429
1173 static const arg_def_t *no_args[] = { NULL }; 430 static const arg_def_t *no_args[] = { NULL };
1174 431
1175 static void usage_exit() { 432 void usage_exit() {
1176 int i; 433 int i;
1177 434
1178 fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n", 435 fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
1179 exec_name); 436 exec_name);
1180 437
1181 fprintf(stderr, "\nOptions:\n"); 438 fprintf(stderr, "\nOptions:\n");
1182 arg_show_usage(stderr, main_args); 439 arg_show_usage(stderr, main_args);
1183 fprintf(stderr, "\nEncoder Global Options:\n"); 440 fprintf(stderr, "\nEncoder Global Options:\n");
1184 arg_show_usage(stderr, global_args); 441 arg_show_usage(stderr, global_args);
1185 fprintf(stderr, "\nRate Control Options:\n"); 442 fprintf(stderr, "\nRate Control Options:\n");
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
1378 struct rate_hist { 635 struct rate_hist {
1379 int64_t *pts; 636 int64_t *pts;
1380 int *sz; 637 int *sz;
1381 int samples; 638 int samples;
1382 int frames; 639 int frames;
1383 struct hist_bucket bucket[RATE_BINS]; 640 struct hist_bucket bucket[RATE_BINS];
1384 int total; 641 int total;
1385 }; 642 };
1386 643
1387 644
1388 static void init_rate_histogram(struct rate_hist *hist, 645 static void init_rate_histogram(struct rate_hist *hist,
1389 const vpx_codec_enc_cfg_t *cfg, 646 const vpx_codec_enc_cfg_t *cfg,
1390 const vpx_rational_t *fps) { 647 const vpx_rational_t *fps) {
1391 int i; 648 int i;
1392 649
1393 /* Determine the number of samples in the buffer. Use the file's framerate 650 /* Determine the number of samples in the buffer. Use the file's framerate
1394 * to determine the number of frames in rc_buf_sz milliseconds, with an 651 * to determine the number of frames in rc_buf_sz milliseconds, with an
1395 * adjustment (5/4) to account for alt-refs 652 * adjustment (5/4) to account for alt-refs
1396 */ 653 */
1397 hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000; 654 hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
1398 655
1399 /* prevent division by zero */ 656 /* prevent division by zero */
1400 if (hist->samples == 0) 657 if (hist->samples == 0)
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1598 #define MAX(x,y) ((x)>(y)?(x):(y)) 855 #define MAX(x,y) ((x)>(y)?(x):(y))
1599 #if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER 856 #if CONFIG_VP8_ENCODER && !CONFIG_VP9_ENCODER
1600 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map) 857 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
1601 #elif !CONFIG_VP8_ENCODER && CONFIG_VP9_ENCODER 858 #elif !CONFIG_VP8_ENCODER && CONFIG_VP9_ENCODER
1602 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map) 859 #define ARG_CTRL_CNT_MAX NELEMENTS(vp9_arg_ctrl_map)
1603 #else 860 #else
1604 #define ARG_CTRL_CNT_MAX MAX(NELEMENTS(vp8_arg_ctrl_map), \ 861 #define ARG_CTRL_CNT_MAX MAX(NELEMENTS(vp8_arg_ctrl_map), \
1605 NELEMENTS(vp9_arg_ctrl_map)) 862 NELEMENTS(vp9_arg_ctrl_map))
1606 #endif 863 #endif
1607 864
1608 /* Configuration elements common to all streams */
1609 struct global_config {
1610 const struct codec_item *codec;
1611 int passes;
1612 int pass;
1613 int usage;
1614 int deadline;
1615 int use_i420;
1616 int quiet;
1617 int verbose;
1618 int limit;
1619 int skip_frames;
1620 int show_psnr;
1621 enum TestDecodeFatality test_decode;
1622 int have_framerate;
1623 struct vpx_rational framerate;
1624 int out_part;
1625 int debug;
1626 int show_q_hist_buckets;
1627 int show_rate_hist_buckets;
1628 };
1629
1630
1631 /* Per-stream configuration */ 865 /* Per-stream configuration */
1632 struct stream_config { 866 struct stream_config {
1633 struct vpx_codec_enc_cfg cfg; 867 struct vpx_codec_enc_cfg cfg;
1634 const char *out_fn; 868 const char *out_fn;
1635 const char *stats_fn; 869 const char *stats_fn;
1636 stereo_format_t stereo_fmt; 870 stereo_format_t stereo_fmt;
1637 int arg_ctrls[ARG_CTRL_CNT_MAX][2]; 871 int arg_ctrls[ARG_CTRL_CNT_MAX][2];
1638 int arg_ctrl_cnt; 872 int arg_ctrl_cnt;
1639 int write_webm; 873 int write_webm;
1640 int have_kf_max_dist; 874 int have_kf_max_dist;
1641 }; 875 };
1642 876
1643 877
1644 struct stream_state { 878 struct stream_state {
1645 int index; 879 int index;
1646 struct stream_state *next; 880 struct stream_state *next;
1647 struct stream_config config; 881 struct stream_config config;
1648 FILE *file; 882 FILE *file;
1649 struct rate_hist rate_hist; 883 struct rate_hist rate_hist;
1650 EbmlGlobal ebml; 884 struct EbmlGlobal ebml;
1651 uint32_t hash; 885 uint32_t hash;
1652 uint64_t psnr_sse_total; 886 uint64_t psnr_sse_total;
1653 uint64_t psnr_samples_total; 887 uint64_t psnr_samples_total;
1654 double psnr_totals[4]; 888 double psnr_totals[4];
1655 int psnr_count; 889 int psnr_count;
1656 int counts[64]; 890 int counts[64];
1657 vpx_codec_ctx_t encoder; 891 vpx_codec_ctx_t encoder;
1658 unsigned int frames_out; 892 unsigned int frames_out;
1659 uint64_t cx_time; 893 uint64_t cx_time;
1660 size_t nbytes; 894 size_t nbytes;
(...skipping 12 matching lines...) Expand all
1673 } 907 }
1674 908
1675 if (rat->num < 0) 909 if (rat->num < 0)
1676 die("Error: %s must be positive\n", msg); 910 die("Error: %s must be positive\n", msg);
1677 911
1678 if (!rat->den) 912 if (!rat->den)
1679 die("Error: %s has zero denominator\n", msg); 913 die("Error: %s has zero denominator\n", msg);
1680 } 914 }
1681 915
1682 916
1683 static void parse_global_config(struct global_config *global, char **argv) { 917 static void parse_global_config(struct VpxEncoderConfig *global, char **argv) {
1684 char **argi, **argj; 918 char **argi, **argj;
1685 struct arg arg; 919 struct arg arg;
1686 920
1687 /* Initialize default parameters */ 921 /* Initialize default parameters */
1688 memset(global, 0, sizeof(*global)); 922 memset(global, 0, sizeof(*global));
1689 global->codec = codecs; 923 global->codec = codecs;
1690 global->passes = 0; 924 global->passes = 0;
1691 global->use_i420 = 1; 925 global->use_i420 = 1;
1692 /* Assign default deadline to good quality */ 926 /* Assign default deadline to good quality */
1693 global->deadline = VPX_DL_GOOD_QUALITY; 927 global->deadline = VPX_DL_GOOD_QUALITY;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1750 validate_positive_rational(arg.name, &global->framerate); 984 validate_positive_rational(arg.name, &global->framerate);
1751 global->have_framerate = 1; 985 global->have_framerate = 1;
1752 } else if (arg_match(&arg, &out_part, argi)) 986 } else if (arg_match(&arg, &out_part, argi))
1753 global->out_part = 1; 987 global->out_part = 1;
1754 else if (arg_match(&arg, &debugmode, argi)) 988 else if (arg_match(&arg, &debugmode, argi))
1755 global->debug = 1; 989 global->debug = 1;
1756 else if (arg_match(&arg, &q_hist_n, argi)) 990 else if (arg_match(&arg, &q_hist_n, argi))
1757 global->show_q_hist_buckets = arg_parse_uint(&arg); 991 global->show_q_hist_buckets = arg_parse_uint(&arg);
1758 else if (arg_match(&arg, &rate_hist_n, argi)) 992 else if (arg_match(&arg, &rate_hist_n, argi))
1759 global->show_rate_hist_buckets = arg_parse_uint(&arg); 993 global->show_rate_hist_buckets = arg_parse_uint(&arg);
994 else if (arg_match(&arg, &disable_warnings, argi))
995 global->disable_warnings = 1;
996 else if (arg_match(&arg, &disable_warning_prompt, argi))
997 global->disable_warning_prompt = 1;
1760 else 998 else
1761 argj++; 999 argj++;
1762 } 1000 }
1763 1001
1764 /* Validate global config */ 1002 /* Validate global config */
1765 if (global->passes == 0) { 1003 if (global->passes == 0) {
1766 #if CONFIG_VP9_ENCODER 1004 #if CONFIG_VP9_ENCODER
1767 // Make default VP9 passes = 2 until there is a better quality 1-pass 1005 // Make default VP9 passes = 2 until there is a better quality 1-pass
1768 // encoder 1006 // encoder
1769 global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1); 1007 global->passes = (global->codec->iface == vpx_codec_vp9_cx ? 2 : 1);
1770 #else 1008 #else
1771 global->passes = 1; 1009 global->passes = 1;
1772 #endif 1010 #endif
1773 } 1011 }
1774 1012
1775 if (global->pass) { 1013 if (global->pass) {
1776 /* DWIM: Assume the user meant passes=2 if pass=2 is specified */ 1014 /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
1777 if (global->pass > global->passes) { 1015 if (global->pass > global->passes) {
1778 warn("Assuming --pass=%d implies --passes=%d\n", 1016 warn("Assuming --pass=%d implies --passes=%d\n",
1779 global->pass, global->pass); 1017 global->pass, global->pass);
1780 global->passes = global->pass; 1018 global->passes = global->pass;
1781 } 1019 }
1782 } 1020 }
1783 } 1021 }
1784 1022
1785 1023
1786 void open_input_file(struct input_state *input) { 1024 void open_input_file(struct VpxInputContext *input) {
1787 unsigned int fourcc;
1788
1789 /* Parse certain options from the input file, if possible */ 1025 /* Parse certain options from the input file, if possible */
1790 input->file = strcmp(input->fn, "-") ? fopen(input->fn, "rb") 1026 input->file = strcmp(input->filename, "-")
1791 : set_binary_mode(stdin); 1027 ? fopen(input->filename, "rb") : set_binary_mode(stdin);
1792 1028
1793 if (!input->file) 1029 if (!input->file)
1794 fatal("Failed to open input file"); 1030 fatal("Failed to open input file");
1795 1031
1796 if (!fseeko(input->file, 0, SEEK_END)) { 1032 if (!fseeko(input->file, 0, SEEK_END)) {
1797 /* Input file is seekable. Figure out how long it is, so we can get 1033 /* Input file is seekable. Figure out how long it is, so we can get
1798 * progress info. 1034 * progress info.
1799 */ 1035 */
1800 input->length = ftello(input->file); 1036 input->length = ftello(input->file);
1801 rewind(input->file); 1037 rewind(input->file);
1802 } 1038 }
1803 1039
1804 /* For RAW input sources, these bytes will applied on the first frame 1040 /* For RAW input sources, these bytes will applied on the first frame
1805 * in read_frame(). 1041 * in read_frame().
1806 */ 1042 */
1807 input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file); 1043 input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file);
1808 input->detect.position = 0; 1044 input->detect.position = 0;
1809 1045
1810 if (input->detect.buf_read == 4 1046 if (input->detect.buf_read == 4
1811 && file_is_y4m(input->file, &input->y4m, input->detect.buf)) { 1047 && file_is_y4m(input->file, &input->y4m, input->detect.buf)) {
1812 if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4, 1048 if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
1813 input->only_i420) >= 0) { 1049 input->only_i420) >= 0) {
1814 input->file_type = FILE_TYPE_Y4M; 1050 input->file_type = FILE_TYPE_Y4M;
1815 input->w = input->y4m.pic_w; 1051 input->width = input->y4m.pic_w;
1816 input->h = input->y4m.pic_h; 1052 input->height = input->y4m.pic_h;
1817 input->framerate.num = input->y4m.fps_n; 1053 input->framerate.numerator = input->y4m.fps_n;
1818 input->framerate.den = input->y4m.fps_d; 1054 input->framerate.denominator = input->y4m.fps_d;
1819 input->use_i420 = 0; 1055 input->use_i420 = 0;
1820 } else 1056 } else
1821 fatal("Unsupported Y4M stream."); 1057 fatal("Unsupported Y4M stream.");
1822 } else if (input->detect.buf_read == 4 && file_is_ivf(input, &fourcc)) { 1058 } else if (input->detect.buf_read == 4 && file_is_ivf(input)) {
1823 input->file_type = FILE_TYPE_IVF; 1059 fatal("IVF is not supported as input.");
1824 switch (fourcc) {
1825 case 0x32315659:
1826 input->use_i420 = 0;
1827 break;
1828 case 0x30323449:
1829 input->use_i420 = 1;
1830 break;
1831 default:
1832 fatal("Unsupported fourcc (%08x) in IVF", fourcc);
1833 }
1834 } else { 1060 } else {
1835 input->file_type = FILE_TYPE_RAW; 1061 input->file_type = FILE_TYPE_RAW;
1836 } 1062 }
1837 } 1063 }
1838 1064
1839 1065
1840 static void close_input_file(struct input_state *input) { 1066 static void close_input_file(struct VpxInputContext *input) {
1841 fclose(input->file); 1067 fclose(input->file);
1842 if (input->file_type == FILE_TYPE_Y4M) 1068 if (input->file_type == FILE_TYPE_Y4M)
1843 y4m_input_close(&input->y4m); 1069 y4m_input_close(&input->y4m);
1844 } 1070 }
1845 1071
1846 static struct stream_state *new_stream(struct global_config *global, 1072 static struct stream_state *new_stream(struct VpxEncoderConfig *global,
1847 struct stream_state *prev) { 1073 struct stream_state *prev) {
1848 struct stream_state *stream; 1074 struct stream_state *stream;
1849 1075
1850 stream = calloc(1, sizeof(*stream)); 1076 stream = calloc(1, sizeof(*stream));
1851 if (!stream) 1077 if (!stream)
1852 fatal("Failed to allocate new stream."); 1078 fatal("Failed to allocate new stream.");
1853 if (prev) { 1079 if (prev) {
1854 memcpy(stream, prev, sizeof(*stream)); 1080 memcpy(stream, prev, sizeof(*stream));
1855 stream->index++; 1081 stream->index++;
1856 prev->next = stream; 1082 prev->next = stream;
1857 } else { 1083 } else {
(...skipping 27 matching lines...) Expand all
1885 } 1111 }
1886 1112
1887 /* Output files must be specified for each stream */ 1113 /* Output files must be specified for each stream */
1888 stream->config.out_fn = NULL; 1114 stream->config.out_fn = NULL;
1889 1115
1890 stream->next = NULL; 1116 stream->next = NULL;
1891 return stream; 1117 return stream;
1892 } 1118 }
1893 1119
1894 1120
1895 static int parse_stream_params(struct global_config *global, 1121 static int parse_stream_params(struct VpxEncoderConfig *global,
1896 struct stream_state *stream, 1122 struct stream_state *stream,
1897 char **argv) { 1123 char **argv) {
1898 char **argi, **argj; 1124 char **argi, **argj;
1899 struct arg arg; 1125 struct arg arg;
1900 static const arg_def_t **ctrl_args = no_args; 1126 static const arg_def_t **ctrl_args = no_args;
1901 static const int *ctrl_args_map = NULL; 1127 static const int *ctrl_args_map = NULL;
1902 struct stream_config *config = &stream->config; 1128 struct stream_config *config = &stream->config;
1903 int eos_mark_found = 0; 1129 int eos_mark_found = 0;
1904 1130
1905 /* Handle codec specific options */ 1131 /* Handle codec specific options */
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
2031 1257
2032 if (!match) 1258 if (!match)
2033 argj++; 1259 argj++;
2034 } 1260 }
2035 } 1261 }
2036 1262
2037 return eos_mark_found; 1263 return eos_mark_found;
2038 } 1264 }
2039 1265
2040 1266
2041 #define FOREACH_STREAM(func)\ 1267 #define FOREACH_STREAM(func) \
2042 do\ 1268 do { \
2043 {\ 1269 struct stream_state *stream; \
2044 struct stream_state *stream;\ 1270 for (stream = streams; stream; stream = stream->next) { \
2045 \ 1271 func; \
2046 for(stream = streams; stream; stream = stream->next)\ 1272 } \
2047 func;\ 1273 } while (0)
2048 }while(0)
2049 1274
2050 1275
2051 static void validate_stream_config(struct stream_state *stream) { 1276 static void validate_stream_config(struct stream_state *stream) {
2052 struct stream_state *streami; 1277 struct stream_state *streami;
2053 1278
2054 if (!stream->config.cfg.g_w || !stream->config.cfg.g_h) 1279 if (!stream->config.cfg.g_w || !stream->config.cfg.g_h)
2055 fatal("Stream %d: Specify stream dimensions with --width (-w) " 1280 fatal("Stream %d: Specify stream dimensions with --width (-w) "
2056 " and --height (-h)", stream->index); 1281 " and --height (-h)", stream->index);
2057 1282
2058 for (streami = stream; streami; streami = streami->next) { 1283 for (streami = stream; streami; streami = streami->next) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2090 stream->config.cfg.g_w = w; 1315 stream->config.cfg.g_w = w;
2091 else 1316 else
2092 stream->config.cfg.g_w = w * stream->config.cfg.g_h / h; 1317 stream->config.cfg.g_w = w * stream->config.cfg.g_h / h;
2093 } 1318 }
2094 if (!stream->config.cfg.g_h) { 1319 if (!stream->config.cfg.g_h) {
2095 stream->config.cfg.g_h = h * stream->config.cfg.g_w / w; 1320 stream->config.cfg.g_h = h * stream->config.cfg.g_w / w;
2096 } 1321 }
2097 } 1322 }
2098 1323
2099 1324
2100 static void set_default_kf_interval(struct stream_state *stream, 1325 static void set_default_kf_interval(struct stream_state *stream,
2101 struct global_config *global) { 1326 struct VpxEncoderConfig *global) {
2102 /* Use a max keyframe interval of 5 seconds, if none was 1327 /* Use a max keyframe interval of 5 seconds, if none was
2103 * specified on the command line. 1328 * specified on the command line.
2104 */ 1329 */
2105 if (!stream->config.have_kf_max_dist) { 1330 if (!stream->config.have_kf_max_dist) {
2106 double framerate = (double)global->framerate.num / global->framerate.den; 1331 double framerate = (double)global->framerate.num / global->framerate.den;
2107 if (framerate > 0.0) 1332 if (framerate > 0.0)
2108 stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate); 1333 stream->config.cfg.kf_max_dist = (unsigned int)(5.0 * framerate);
2109 } 1334 }
2110 } 1335 }
2111 1336
2112 1337
2113 static void show_stream_config(struct stream_state *stream, 1338 static void show_stream_config(struct stream_state *stream,
2114 struct global_config *global, 1339 struct VpxEncoderConfig *global,
2115 struct input_state *input) { 1340 struct VpxInputContext *input) {
2116 1341
2117 #define SHOW(field) \ 1342 #define SHOW(field) \
2118 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field) 1343 fprintf(stderr, " %-28s = %d\n", #field, stream->config.cfg.field)
2119 1344
2120 if (stream->index == 0) { 1345 if (stream->index == 0) {
2121 fprintf(stderr, "Codec: %s\n", 1346 fprintf(stderr, "Codec: %s\n",
2122 vpx_codec_iface_name(global->codec->iface())); 1347 vpx_codec_iface_name(global->codec->iface()));
2123 fprintf(stderr, "Source file: %s Format: %s\n", input->fn, 1348 fprintf(stderr, "Source file: %s Format: %s\n", input->filename,
2124 input->use_i420 ? "I420" : "YV12"); 1349 input->use_i420 ? "I420" : "YV12");
2125 } 1350 }
2126 if (stream->next || stream->index) 1351 if (stream->next || stream->index)
2127 fprintf(stderr, "\nStream Index: %d\n", stream->index); 1352 fprintf(stderr, "\nStream Index: %d\n", stream->index);
2128 fprintf(stderr, "Destination file: %s\n", stream->config.out_fn); 1353 fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
2129 fprintf(stderr, "Encoder parameters:\n"); 1354 fprintf(stderr, "Encoder parameters:\n");
2130 1355
2131 SHOW(g_usage); 1356 SHOW(g_usage);
2132 SHOW(g_threads); 1357 SHOW(g_threads);
2133 SHOW(g_profile); 1358 SHOW(g_profile);
(...skipping 20 matching lines...) Expand all
2154 SHOW(rc_2pass_vbr_bias_pct); 1379 SHOW(rc_2pass_vbr_bias_pct);
2155 SHOW(rc_2pass_vbr_minsection_pct); 1380 SHOW(rc_2pass_vbr_minsection_pct);
2156 SHOW(rc_2pass_vbr_maxsection_pct); 1381 SHOW(rc_2pass_vbr_maxsection_pct);
2157 SHOW(kf_mode); 1382 SHOW(kf_mode);
2158 SHOW(kf_min_dist); 1383 SHOW(kf_min_dist);
2159 SHOW(kf_max_dist); 1384 SHOW(kf_max_dist);
2160 } 1385 }
2161 1386
2162 1387
2163 static void open_output_file(struct stream_state *stream, 1388 static void open_output_file(struct stream_state *stream,
2164 struct global_config *global) { 1389 struct VpxEncoderConfig *global) {
2165 const char *fn = stream->config.out_fn; 1390 const char *fn = stream->config.out_fn;
2166 1391
2167 stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout); 1392 stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
2168 1393
2169 if (!stream->file) 1394 if (!stream->file)
2170 fatal("Failed to open output file"); 1395 fatal("Failed to open output file");
2171 1396
2172 if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR)) 1397 if (stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
2173 fatal("WebM output to pipes not supported."); 1398 fatal("WebM output to pipes not supported.");
2174 1399
2175 if (stream->config.write_webm) { 1400 if (stream->config.write_webm) {
2176 stream->ebml.stream = stream->file; 1401 stream->ebml.stream = stream->file;
2177 write_webm_file_header(&stream->ebml, &stream->config.cfg, 1402 write_webm_file_header(&stream->ebml, &stream->config.cfg,
2178 &global->framerate, 1403 &global->framerate,
2179 stream->config.stereo_fmt, 1404 stream->config.stereo_fmt,
2180 global->codec->fourcc); 1405 global->codec->fourcc);
2181 } else 1406 } else
2182 write_ivf_file_header(stream->file, &stream->config.cfg, 1407 ivf_write_file_header(stream->file, &stream->config.cfg,
2183 global->codec->fourcc, 0); 1408 global->codec->fourcc, 0);
2184 } 1409 }
2185 1410
2186 1411
2187 static void close_output_file(struct stream_state *stream, 1412 static void close_output_file(struct stream_state *stream,
2188 unsigned int fourcc) { 1413 unsigned int fourcc) {
2189 if (stream->config.write_webm) { 1414 if (stream->config.write_webm) {
2190 write_webm_file_footer(&stream->ebml, stream->hash); 1415 write_webm_file_footer(&stream->ebml, stream->hash);
2191 free(stream->ebml.cue_list); 1416 free(stream->ebml.cue_list);
2192 stream->ebml.cue_list = NULL; 1417 stream->ebml.cue_list = NULL;
2193 } else { 1418 } else {
2194 if (!fseek(stream->file, 0, SEEK_SET)) 1419 if (!fseek(stream->file, 0, SEEK_SET))
2195 write_ivf_file_header(stream->file, &stream->config.cfg, 1420 ivf_write_file_header(stream->file, &stream->config.cfg,
2196 fourcc, 1421 fourcc,
2197 stream->frames_out); 1422 stream->frames_out);
2198 } 1423 }
2199 1424
2200 fclose(stream->file); 1425 fclose(stream->file);
2201 } 1426 }
2202 1427
2203 1428
2204 static void setup_pass(struct stream_state *stream, 1429 static void setup_pass(struct stream_state *stream,
2205 struct global_config *global, 1430 struct VpxEncoderConfig *global,
2206 int pass) { 1431 int pass) {
2207 if (stream->config.stats_fn) { 1432 if (stream->config.stats_fn) {
2208 if (!stats_open_file(&stream->stats, stream->config.stats_fn, 1433 if (!stats_open_file(&stream->stats, stream->config.stats_fn,
2209 pass)) 1434 pass))
2210 fatal("Failed to open statistics store"); 1435 fatal("Failed to open statistics store");
2211 } else { 1436 } else {
2212 if (!stats_open_mem(&stream->stats, pass)) 1437 if (!stats_open_mem(&stream->stats, pass))
2213 fatal("Failed to open statistics store"); 1438 fatal("Failed to open statistics store");
2214 } 1439 }
2215 1440
2216 stream->config.cfg.g_pass = global->passes == 2 1441 stream->config.cfg.g_pass = global->passes == 2
2217 ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS 1442 ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS
2218 : VPX_RC_ONE_PASS; 1443 : VPX_RC_ONE_PASS;
2219 if (pass) 1444 if (pass)
2220 stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats); 1445 stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
2221 1446
2222 stream->cx_time = 0; 1447 stream->cx_time = 0;
2223 stream->nbytes = 0; 1448 stream->nbytes = 0;
2224 stream->frames_out = 0; 1449 stream->frames_out = 0;
2225 } 1450 }
2226 1451
2227 1452
2228 static void initialize_encoder(struct stream_state *stream, 1453 static void initialize_encoder(struct stream_state *stream,
2229 struct global_config *global) { 1454 struct VpxEncoderConfig *global) {
2230 int i; 1455 int i;
2231 int flags = 0; 1456 int flags = 0;
2232 1457
2233 flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0; 1458 flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
2234 flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0; 1459 flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
2235 1460
2236 /* Construct Encoder Context */ 1461 /* Construct Encoder Context */
2237 vpx_codec_enc_init(&stream->encoder, global->codec->iface(), 1462 vpx_codec_enc_init(&stream->encoder, global->codec->iface(),
2238 &stream->config.cfg, flags); 1463 &stream->config.cfg, flags);
2239 ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder"); 1464 ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
(...skipping 13 matching lines...) Expand all
2253 } 1478 }
2254 1479
2255 #if CONFIG_DECODERS 1480 #if CONFIG_DECODERS
2256 if (global->test_decode != TEST_DECODE_OFF) { 1481 if (global->test_decode != TEST_DECODE_OFF) {
2257 vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0); 1482 vpx_codec_dec_init(&stream->decoder, global->codec->dx_iface(), NULL, 0);
2258 } 1483 }
2259 #endif 1484 #endif
2260 } 1485 }
2261 1486
2262 1487
2263 static void encode_frame(struct stream_state *stream, 1488 static void encode_frame(struct stream_state *stream,
2264 struct global_config *global, 1489 struct VpxEncoderConfig *global,
2265 struct vpx_image *img, 1490 struct vpx_image *img,
2266 unsigned int frames_in) { 1491 unsigned int frames_in) {
2267 vpx_codec_pts_t frame_start, next_frame_start; 1492 vpx_codec_pts_t frame_start, next_frame_start;
2268 struct vpx_codec_enc_cfg *cfg = &stream->config.cfg; 1493 struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
2269 struct vpx_usec_timer timer; 1494 struct vpx_usec_timer timer;
2270 1495
2271 frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1) 1496 frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1)
2272 * global->framerate.den) 1497 * global->framerate.den)
2273 / cfg->g_timebase.num / global->framerate.num; 1498 / cfg->g_timebase.num / global->framerate.num;
2274 next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in) 1499 next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
2275 * global->framerate.den) 1500 * global->framerate.den)
2276 / cfg->g_timebase.num / global->framerate.num; 1501 / cfg->g_timebase.num / global->framerate.num;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2311 if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) { 1536 if (stream->config.cfg.g_pass != VPX_RC_FIRST_PASS) {
2312 int q; 1537 int q;
2313 1538
2314 vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q); 1539 vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
2315 ctx_exit_on_error(&stream->encoder, "Failed to read quantizer"); 1540 ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
2316 stream->counts[q]++; 1541 stream->counts[q]++;
2317 } 1542 }
2318 } 1543 }
2319 1544
2320 1545
2321 static void get_cx_data(struct stream_state *stream, 1546 static void get_cx_data(struct stream_state *stream,
2322 struct global_config *global, 1547 struct VpxEncoderConfig *global,
2323 int *got_data) { 1548 int *got_data) {
2324 const vpx_codec_cx_pkt_t *pkt; 1549 const vpx_codec_cx_pkt_t *pkt;
2325 const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg; 1550 const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
2326 vpx_codec_iter_t iter = NULL; 1551 vpx_codec_iter_t iter = NULL;
2327 1552
2328 *got_data = 0; 1553 *got_data = 0;
2329 while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) { 1554 while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter))) {
2330 static size_t fsize = 0; 1555 static size_t fsize = 0;
2331 static off_t ivf_header_pos = 0; 1556 static off_t ivf_header_pos = 0;
2332 1557
2333 switch (pkt->kind) { 1558 switch (pkt->kind) {
(...skipping 11 matching lines...) Expand all
2345 stream->hash = murmur(pkt->data.frame.buf, 1570 stream->hash = murmur(pkt->data.frame.buf,
2346 (int)pkt->data.frame.sz, 1571 (int)pkt->data.frame.sz,
2347 stream->hash); 1572 stream->hash);
2348 1573
2349 write_webm_block(&stream->ebml, cfg, pkt); 1574 write_webm_block(&stream->ebml, cfg, pkt);
2350 } else { 1575 } else {
2351 if (pkt->data.frame.partition_id <= 0) { 1576 if (pkt->data.frame.partition_id <= 0) {
2352 ivf_header_pos = ftello(stream->file); 1577 ivf_header_pos = ftello(stream->file);
2353 fsize = pkt->data.frame.sz; 1578 fsize = pkt->data.frame.sz;
2354 1579
2355 write_ivf_frame_header(stream->file, pkt); 1580 ivf_write_frame_header(stream->file, pkt);
2356 } else { 1581 } else {
2357 fsize += pkt->data.frame.sz; 1582 fsize += pkt->data.frame.sz;
2358 1583
2359 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) { 1584 if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT)) {
2360 off_t currpos = ftello(stream->file); 1585 off_t currpos = ftello(stream->file);
2361 fseeko(stream->file, ivf_header_pos, SEEK_SET); 1586 fseeko(stream->file, ivf_header_pos, SEEK_SET);
2362 write_ivf_frame_size(stream->file, fsize); 1587 ivf_write_frame_size(stream->file, fsize);
2363 fseeko(stream->file, currpos, SEEK_SET); 1588 fseeko(stream->file, currpos, SEEK_SET);
2364 } 1589 }
2365 } 1590 }
2366 1591
2367 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, 1592 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
2368 stream->file); 1593 stream->file);
2369 } 1594 }
2370 stream->nbytes += pkt->data.raw.sz; 1595 stream->nbytes += pkt->data.raw.sz;
2371 1596
2372 *got_data = 1; 1597 *got_data = 1;
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2505 etl -= mins * 60; 1730 etl -= mins * 60;
2506 secs = etl; 1731 secs = etl;
2507 1732
2508 fprintf(stderr, "[%3s %2d:%02d:%02d] ", 1733 fprintf(stderr, "[%3s %2d:%02d:%02d] ",
2509 label, hours, mins, secs); 1734 label, hours, mins, secs);
2510 } else { 1735 } else {
2511 fprintf(stderr, "[%3s unknown] ", label); 1736 fprintf(stderr, "[%3s unknown] ", label);
2512 } 1737 }
2513 } 1738 }
2514 1739
1740
2515 int main(int argc, const char **argv_) { 1741 int main(int argc, const char **argv_) {
2516 int pass; 1742 int pass;
2517 vpx_image_t raw; 1743 vpx_image_t raw;
2518 int frame_avail, got_data; 1744 int frame_avail, got_data;
2519 1745
2520 struct input_state input = {0}; 1746 struct VpxInputContext input = {0};
2521 struct global_config global; 1747 struct VpxEncoderConfig global;
2522 struct stream_state *streams = NULL; 1748 struct stream_state *streams = NULL;
2523 char **argv, **argi; 1749 char **argv, **argi;
2524 uint64_t cx_time = 0; 1750 uint64_t cx_time = 0;
2525 int stream_cnt = 0; 1751 int stream_cnt = 0;
2526 int res = 0; 1752 int res = 0;
2527 1753
2528 exec_name = argv_[0]; 1754 exec_name = argv_[0];
2529 1755
2530 if (argc < 3) 1756 if (argc < 3)
2531 usage_exit(); 1757 usage_exit();
2532 1758
2533 /* Setup default input stream settings */ 1759 /* Setup default input stream settings */
2534 input.framerate.num = 30; 1760 input.framerate.numerator = 30;
2535 input.framerate.den = 1; 1761 input.framerate.denominator = 1;
2536 input.use_i420 = 1; 1762 input.use_i420 = 1;
2537 input.only_i420 = 1; 1763 input.only_i420 = 1;
2538 1764
2539 /* First parse the global configuration values, because we want to apply 1765 /* First parse the global configuration values, because we want to apply
2540 * other parameters on top of the default configuration provided by the 1766 * other parameters on top of the default configuration provided by the
2541 * codec. 1767 * codec.
2542 */ 1768 */
2543 argv = argv_dup(argc - 1, argv_ + 1); 1769 argv = argv_dup(argc - 1, argv_ + 1);
2544 parse_global_config(&global, argv); 1770 parse_global_config(&global, argv);
2545 1771
1772
2546 { 1773 {
2547 /* Now parse each stream's parameters. Using a local scope here 1774 /* Now parse each stream's parameters. Using a local scope here
2548 * due to the use of 'stream' as loop variable in FOREACH_STREAM 1775 * due to the use of 'stream' as loop variable in FOREACH_STREAM
2549 * loops 1776 * loops
2550 */ 1777 */
2551 struct stream_state *stream = NULL; 1778 struct stream_state *stream = NULL;
2552 1779
2553 do { 1780 do {
2554 stream = new_stream(&global, stream); 1781 stream = new_stream(&global, stream);
2555 stream_cnt++; 1782 stream_cnt++;
2556 if (!streams) 1783 if (!streams)
2557 streams = stream; 1784 streams = stream;
2558 } while (parse_stream_params(&global, stream, argv)); 1785 } while (parse_stream_params(&global, stream, argv));
2559 } 1786 }
2560 1787
2561 /* Check for unrecognized options */ 1788 /* Check for unrecognized options */
2562 for (argi = argv; *argi; argi++) 1789 for (argi = argv; *argi; argi++)
2563 if (argi[0][0] == '-' && argi[0][1]) 1790 if (argi[0][0] == '-' && argi[0][1])
2564 die("Error: Unrecognized option %s\n", *argi); 1791 die("Error: Unrecognized option %s\n", *argi);
2565 1792
1793 FOREACH_STREAM(check_encoder_config(global.disable_warning_prompt,
1794 &global, &stream->config.cfg););
1795
2566 /* Handle non-option arguments */ 1796 /* Handle non-option arguments */
2567 input.fn = argv[0]; 1797 input.filename = argv[0];
2568 1798
2569 if (!input.fn) 1799 if (!input.filename)
2570 usage_exit(); 1800 usage_exit();
2571 1801
2572 #if CONFIG_NON420 1802 #if CONFIG_NON420
2573 /* Decide if other chroma subsamplings than 4:2:0 are supported */ 1803 /* Decide if other chroma subsamplings than 4:2:0 are supported */
2574 if (global.codec->fourcc == VP9_FOURCC) 1804 if (global.codec->fourcc == VP9_FOURCC)
2575 input.only_i420 = 0; 1805 input.only_i420 = 0;
2576 #endif 1806 #endif
2577 1807
2578 for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) { 1808 for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++) {
2579 int frames_in = 0, seen_frames = 0; 1809 int frames_in = 0, seen_frames = 0;
2580 int64_t estimated_time_left = -1; 1810 int64_t estimated_time_left = -1;
2581 int64_t average_rate = -1; 1811 int64_t average_rate = -1;
2582 off_t lagged_count = 0; 1812 off_t lagged_count = 0;
2583 1813
2584 open_input_file(&input); 1814 open_input_file(&input);
2585 1815
2586 /* If the input file doesn't specify its w/h (raw files), try to get 1816 /* If the input file doesn't specify its w/h (raw files), try to get
2587 * the data from the first stream's configuration. 1817 * the data from the first stream's configuration.
2588 */ 1818 */
2589 if (!input.w || !input.h) 1819 if (!input.width || !input.height)
2590 FOREACH_STREAM( { 1820 FOREACH_STREAM( {
2591 if (stream->config.cfg.g_w && stream->config.cfg.g_h) { 1821 if (stream->config.cfg.g_w && stream->config.cfg.g_h) {
2592 input.w = stream->config.cfg.g_w; 1822 input.width = stream->config.cfg.g_w;
2593 input.h = stream->config.cfg.g_h; 1823 input.height = stream->config.cfg.g_h;
2594 break; 1824 break;
2595 } 1825 }
2596 }); 1826 });
2597 1827
2598 /* Update stream configurations from the input file's parameters */ 1828 /* Update stream configurations from the input file's parameters */
2599 if (!input.w || !input.h) 1829 if (!input.width || !input.height)
2600 fatal("Specify stream dimensions with --width (-w) " 1830 fatal("Specify stream dimensions with --width (-w) "
2601 " and --height (-h)"); 1831 " and --height (-h)");
2602 FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h)); 1832 FOREACH_STREAM(set_stream_dimensions(stream, input.width, input.height));
2603 FOREACH_STREAM(validate_stream_config(stream)); 1833 FOREACH_STREAM(validate_stream_config(stream));
2604 1834
2605 /* Ensure that --passes and --pass are consistent. If --pass is set and 1835 /* Ensure that --passes and --pass are consistent. If --pass is set and
2606 * --passes=2, ensure --fpf was set. 1836 * --passes=2, ensure --fpf was set.
2607 */ 1837 */
2608 if (global.pass && global.passes == 2) 1838 if (global.pass && global.passes == 2)
2609 FOREACH_STREAM( { 1839 FOREACH_STREAM( {
2610 if (!stream->config.stats_fn) 1840 if (!stream->config.stats_fn)
2611 die("Stream %d: Must specify --fpf when --pass=%d" 1841 die("Stream %d: Must specify --fpf when --pass=%d"
2612 " and --passes=2\n", stream->index, global.pass); 1842 " and --passes=2\n", stream->index, global.pass);
2613 }); 1843 });
2614 1844
2615 /* Use the frame rate from the file only if none was specified 1845 /* Use the frame rate from the file only if none was specified
2616 * on the command-line. 1846 * on the command-line.
2617 */ 1847 */
2618 if (!global.have_framerate) 1848 if (!global.have_framerate) {
2619 global.framerate = input.framerate; 1849 global.framerate.num = input.framerate.numerator;
1850 global.framerate.den = input.framerate.denominator;
1851 }
2620 1852
2621 FOREACH_STREAM(set_default_kf_interval(stream, &global)); 1853 FOREACH_STREAM(set_default_kf_interval(stream, &global));
2622 1854
2623 /* Show configuration */ 1855 /* Show configuration */
2624 if (global.verbose && pass == 0) 1856 if (global.verbose && pass == 0)
2625 FOREACH_STREAM(show_stream_config(stream, &global, &input)); 1857 FOREACH_STREAM(show_stream_config(stream, &global, &input));
2626 1858
2627 if (pass == (global.pass ? global.pass - 1 : 0)) { 1859 if (pass == (global.pass ? global.pass - 1 : 0)) {
2628 if (input.file_type == FILE_TYPE_Y4M) 1860 if (input.file_type == FILE_TYPE_Y4M)
2629 /*The Y4M reader does its own allocation. 1861 /*The Y4M reader does its own allocation.
2630 Just initialize this here to avoid problems if we never read any 1862 Just initialize this here to avoid problems if we never read any
2631 frames.*/ 1863 frames.*/
2632 memset(&raw, 0, sizeof(raw)); 1864 memset(&raw, 0, sizeof(raw));
2633 else 1865 else
2634 vpx_img_alloc(&raw, 1866 vpx_img_alloc(&raw,
2635 input.use_i420 ? VPX_IMG_FMT_I420 1867 input.use_i420 ? VPX_IMG_FMT_I420
2636 : VPX_IMG_FMT_YV12, 1868 : VPX_IMG_FMT_YV12,
2637 input.w, input.h, 32); 1869 input.width, input.height, 32);
2638 1870
2639 FOREACH_STREAM(init_rate_histogram(&stream->rate_hist, 1871 FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
2640 &stream->config.cfg, 1872 &stream->config.cfg,
2641 &global.framerate)); 1873 &global.framerate));
2642 } 1874 }
2643 1875
2644 FOREACH_STREAM(setup_pass(stream, &global, pass)); 1876 FOREACH_STREAM(setup_pass(stream, &global, pass));
2645 FOREACH_STREAM(open_output_file(stream, &global)); 1877 FOREACH_STREAM(open_output_file(stream, &global));
2646 FOREACH_STREAM(initialize_encoder(stream, &global)); 1878 FOREACH_STREAM(initialize_encoder(stream, &global));
2647 1879
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
2795 } 2027 }
2796 fclose(f); 2028 fclose(f);
2797 }); 2029 });
2798 #endif 2030 #endif
2799 2031
2800 vpx_img_free(&raw); 2032 vpx_img_free(&raw);
2801 free(argv); 2033 free(argv);
2802 free(streams); 2034 free(streams);
2803 return res ? EXIT_FAILURE : EXIT_SUCCESS; 2035 return res ? EXIT_FAILURE : EXIT_SUCCESS;
2804 } 2036 }
OLDNEW
« no previous file with comments | « source/libvpx/vpxenc.h ('k') | source/libvpx/vpxstats.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698