OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |