gen_asm_deps.sh: regex fix
[platform/upstream/libvpx.git] / vpxenc.c
1 /*
2  *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10
11
12 /* This is a simple program that encodes YV12 files and generates ivf
13  * files using the new interface.
14  */
15 #if defined(_WIN32) || !CONFIG_OS_SUPPORT
16 #define USE_POSIX_MMAP 0
17 #else
18 #define USE_POSIX_MMAP 1
19 #endif
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdarg.h>
24 #include <string.h>
25 #include <limits.h>
26 #include <assert.h>
27 #include "vpx/vpx_encoder.h"
28 #if USE_POSIX_MMAP
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <sys/mman.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #endif
35 #include "vpx/vp8cx.h"
36 #include "vpx_ports/mem_ops.h"
37 #include "vpx_ports/vpx_timer.h"
38 #include "tools_common.h"
39 #include "y4minput.h"
40 #include "libmkv/EbmlWriter.h"
41 #include "libmkv/EbmlIDs.h"
42
43 /* Need special handling of these functions on Windows */
44 #if defined(_MSC_VER)
45 /* MSVS doesn't define off_t, and uses _f{seek,tell}i64 */
46 typedef __int64 off_t;
47 #define fseeko _fseeki64
48 #define ftello _ftelli64
49 #elif defined(_WIN32)
50 /* MinGW defines off_t as long
51    and uses f{seek,tell}o64/off64_t for large files */
52 #define fseeko fseeko64
53 #define ftello ftello64
54 #define off_t off64_t
55 #endif
56
57 #define LITERALU64(hi,lo) ((((uint64_t)hi)<<32)|lo)
58
59 /* We should use 32-bit file operations in WebM file format
60  * when building ARM executable file (.axf) with RVCT */
61 #if !CONFIG_OS_SUPPORT
62 typedef long off_t;
63 #define fseeko fseek
64 #define ftello ftell
65 #endif
66
67 /* Swallow warnings about unused results of fread/fwrite */
68 static size_t wrap_fread(void *ptr, size_t size, size_t nmemb,
69                          FILE *stream)
70 {
71     return fread(ptr, size, nmemb, stream);
72 }
73 #define fread wrap_fread
74
75 static size_t wrap_fwrite(const void *ptr, size_t size, size_t nmemb,
76                           FILE *stream)
77 {
78     return fwrite(ptr, size, nmemb, stream);
79 }
80 #define fwrite wrap_fwrite
81
82
83 static const char *exec_name;
84
85 static const struct codec_item
86 {
87     char const              *name;
88     vpx_codec_iface_t       *iface;
89     unsigned int             fourcc;
90 } codecs[] =
91 {
92 #if CONFIG_VP8_ENCODER
93     {"vp8",  &vpx_codec_vp8_cx_algo, 0x30385056},
94 #endif
95 };
96
97 static void usage_exit();
98
99 #define LOG_ERROR(label) do \
100 {\
101     const char *l=label;\
102     va_list ap;\
103     va_start(ap, fmt);\
104     if(l)\
105         fprintf(stderr, "%s: ", l);\
106     vfprintf(stderr, fmt, ap);\
107     fprintf(stderr, "\n");\
108     va_end(ap);\
109 } while(0)
110
111 void die(const char *fmt, ...)
112 {
113     LOG_ERROR(NULL);
114     usage_exit();
115 }
116
117
118 void fatal(const char *fmt, ...)
119 {
120     LOG_ERROR("Fatal");
121     exit(EXIT_FAILURE);
122 }
123
124
125 void warn(const char *fmt, ...)
126 {
127     LOG_ERROR("Warning");
128 }
129
130
131 static void ctx_exit_on_error(vpx_codec_ctx_t *ctx, const char *s, ...)
132 {
133     va_list ap;
134
135     va_start(ap, s);
136     if (ctx->err)
137     {
138         const char *detail = vpx_codec_error_detail(ctx);
139
140         vfprintf(stderr, s, ap);
141         fprintf(stderr, ": %s\n", vpx_codec_error(ctx));
142
143         if (detail)
144             fprintf(stderr, "    %s\n", detail);
145
146         exit(EXIT_FAILURE);
147     }
148 }
149
150 /* This structure is used to abstract the different ways of handling
151  * first pass statistics.
152  */
153 typedef struct
154 {
155     vpx_fixed_buf_t buf;
156     int             pass;
157     FILE           *file;
158     char           *buf_ptr;
159     size_t          buf_alloc_sz;
160 } stats_io_t;
161
162 int stats_open_file(stats_io_t *stats, const char *fpf, int pass)
163 {
164     int res;
165
166     stats->pass = pass;
167
168     if (pass == 0)
169     {
170         stats->file = fopen(fpf, "wb");
171         stats->buf.sz = 0;
172         stats->buf.buf = NULL,
173                    res = (stats->file != NULL);
174     }
175     else
176     {
177 #if 0
178 #elif USE_POSIX_MMAP
179         struct stat stat_buf;
180         int fd;
181
182         fd = open(fpf, O_RDONLY);
183         stats->file = fdopen(fd, "rb");
184         fstat(fd, &stat_buf);
185         stats->buf.sz = stat_buf.st_size;
186         stats->buf.buf = mmap(NULL, stats->buf.sz, PROT_READ, MAP_PRIVATE,
187                               fd, 0);
188         res = (stats->buf.buf != NULL);
189 #else
190         size_t nbytes;
191
192         stats->file = fopen(fpf, "rb");
193
194         if (fseek(stats->file, 0, SEEK_END))
195             fatal("First-pass stats file must be seekable!");
196
197         stats->buf.sz = stats->buf_alloc_sz = ftell(stats->file);
198         rewind(stats->file);
199
200         stats->buf.buf = malloc(stats->buf_alloc_sz);
201
202         if (!stats->buf.buf)
203             fatal("Failed to allocate first-pass stats buffer (%lu bytes)",
204                   (unsigned long)stats->buf_alloc_sz);
205
206         nbytes = fread(stats->buf.buf, 1, stats->buf.sz, stats->file);
207         res = (nbytes == stats->buf.sz);
208 #endif
209     }
210
211     return res;
212 }
213
214 int stats_open_mem(stats_io_t *stats, int pass)
215 {
216     int res;
217     stats->pass = pass;
218
219     if (!pass)
220     {
221         stats->buf.sz = 0;
222         stats->buf_alloc_sz = 64 * 1024;
223         stats->buf.buf = malloc(stats->buf_alloc_sz);
224     }
225
226     stats->buf_ptr = stats->buf.buf;
227     res = (stats->buf.buf != NULL);
228     return res;
229 }
230
231
232 void stats_close(stats_io_t *stats, int last_pass)
233 {
234     if (stats->file)
235     {
236         if (stats->pass == last_pass)
237         {
238 #if 0
239 #elif USE_POSIX_MMAP
240             munmap(stats->buf.buf, stats->buf.sz);
241 #else
242             free(stats->buf.buf);
243 #endif
244         }
245
246         fclose(stats->file);
247         stats->file = NULL;
248     }
249     else
250     {
251         if (stats->pass == last_pass)
252             free(stats->buf.buf);
253     }
254 }
255
256 void stats_write(stats_io_t *stats, const void *pkt, size_t len)
257 {
258     if (stats->file)
259     {
260         (void) fwrite(pkt, 1, len, stats->file);
261     }
262     else
263     {
264         if (stats->buf.sz + len > stats->buf_alloc_sz)
265         {
266             size_t  new_sz = stats->buf_alloc_sz + 64 * 1024;
267             char   *new_ptr = realloc(stats->buf.buf, new_sz);
268
269             if (new_ptr)
270             {
271                 stats->buf_ptr = new_ptr + (stats->buf_ptr - (char *)stats->buf.buf);
272                 stats->buf.buf = new_ptr;
273                 stats->buf_alloc_sz = new_sz;
274             }
275             else
276                 fatal("Failed to realloc firstpass stats buffer.");
277         }
278
279         memcpy(stats->buf_ptr, pkt, len);
280         stats->buf.sz += len;
281         stats->buf_ptr += len;
282     }
283 }
284
285 vpx_fixed_buf_t stats_get(stats_io_t *stats)
286 {
287     return stats->buf;
288 }
289
290 /* Stereo 3D packed frame format */
291 typedef enum stereo_format
292 {
293     STEREO_FORMAT_MONO       = 0,
294     STEREO_FORMAT_LEFT_RIGHT = 1,
295     STEREO_FORMAT_BOTTOM_TOP = 2,
296     STEREO_FORMAT_TOP_BOTTOM = 3,
297     STEREO_FORMAT_RIGHT_LEFT = 11
298 } stereo_format_t;
299
300 enum video_file_type
301 {
302     FILE_TYPE_RAW,
303     FILE_TYPE_IVF,
304     FILE_TYPE_Y4M
305 };
306
307 struct detect_buffer {
308     char buf[4];
309     size_t buf_read;
310     size_t position;
311 };
312
313
314 struct input_state
315 {
316     char                 *fn;
317     FILE                 *file;
318     y4m_input             y4m;
319     struct detect_buffer  detect;
320     enum video_file_type  file_type;
321     unsigned int          w;
322     unsigned int          h;
323     struct vpx_rational   framerate;
324     int                   use_i420;
325 };
326
327
328 #define IVF_FRAME_HDR_SZ (4+8) /* 4 byte size + 8 byte timestamp */
329 static int read_frame(struct input_state *input, vpx_image_t *img)
330 {
331     FILE *f = input->file;
332     enum video_file_type file_type = input->file_type;
333     y4m_input *y4m = &input->y4m;
334     struct detect_buffer *detect = &input->detect;
335     int plane = 0;
336     int shortread = 0;
337
338     if (file_type == FILE_TYPE_Y4M)
339     {
340         if (y4m_input_fetch_frame(y4m, f, img) < 1)
341            return 0;
342     }
343     else
344     {
345         if (file_type == FILE_TYPE_IVF)
346         {
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         {
358             unsigned char *ptr;
359             int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
360             int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
361             int r;
362
363             /* Determine the correct plane based on the image format. The for-loop
364              * always counts in Y,U,V order, but this may not match the order of
365              * the data on disk.
366              */
367             switch (plane)
368             {
369             case 1:
370                 ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
371                 break;
372             case 2:
373                 ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
374                 break;
375             default:
376                 ptr = img->planes[plane];
377             }
378
379             for (r = 0; r < h; r++)
380             {
381                 size_t needed = w;
382                 size_t buf_position = 0;
383                 const size_t left = detect->buf_read - detect->position;
384                 if (left > 0)
385                 {
386                     const size_t more = (left < needed) ? left : needed;
387                     memcpy(ptr, detect->buf + detect->position, more);
388                     buf_position = more;
389                     needed -= more;
390                     detect->position += more;
391                 }
392                 if (needed > 0)
393                 {
394                     shortread |= (fread(ptr + buf_position, 1, needed, f) < needed);
395                 }
396
397                 ptr += img->stride[plane];
398             }
399         }
400     }
401
402     return !shortread;
403 }
404
405
406 unsigned int file_is_y4m(FILE      *infile,
407                          y4m_input *y4m,
408                          char       detect[4])
409 {
410     if(memcmp(detect, "YUV4", 4) == 0)
411     {
412         return 1;
413     }
414     return 0;
415 }
416
417 #define IVF_FILE_HDR_SZ (32)
418 unsigned int file_is_ivf(struct input_state *input,
419                          unsigned int *fourcc)
420 {
421     char raw_hdr[IVF_FILE_HDR_SZ];
422     int is_ivf = 0;
423     FILE *infile = input->file;
424     unsigned int *width = &input->w;
425     unsigned int *height = &input->h;
426     struct detect_buffer *detect = &input->detect;
427
428     if(memcmp(detect->buf, "DKIF", 4) != 0)
429         return 0;
430
431     /* See write_ivf_file_header() for more documentation on the file header
432      * layout.
433      */
434     if (fread(raw_hdr + 4, 1, IVF_FILE_HDR_SZ - 4, infile)
435         == IVF_FILE_HDR_SZ - 4)
436     {
437         {
438             is_ivf = 1;
439
440             if (mem_get_le16(raw_hdr + 4) != 0)
441                 warn("Unrecognized IVF version! This file may not decode "
442                      "properly.");
443
444             *fourcc = mem_get_le32(raw_hdr + 8);
445         }
446     }
447
448     if (is_ivf)
449     {
450         *width = mem_get_le16(raw_hdr + 12);
451         *height = mem_get_le16(raw_hdr + 14);
452         detect->position = 4;
453     }
454
455     return is_ivf;
456 }
457
458
459 static void write_ivf_file_header(FILE *outfile,
460                                   const vpx_codec_enc_cfg_t *cfg,
461                                   unsigned int fourcc,
462                                   int frame_cnt)
463 {
464     char header[32];
465
466     if (cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
467         return;
468
469     header[0] = 'D';
470     header[1] = 'K';
471     header[2] = 'I';
472     header[3] = 'F';
473     mem_put_le16(header + 4,  0);                 /* version */
474     mem_put_le16(header + 6,  32);                /* headersize */
475     mem_put_le32(header + 8,  fourcc);            /* headersize */
476     mem_put_le16(header + 12, cfg->g_w);          /* width */
477     mem_put_le16(header + 14, cfg->g_h);          /* height */
478     mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
479     mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
480     mem_put_le32(header + 24, frame_cnt);         /* length */
481     mem_put_le32(header + 28, 0);                 /* unused */
482
483     (void) fwrite(header, 1, 32, outfile);
484 }
485
486
487 static void write_ivf_frame_header(FILE *outfile,
488                                    const vpx_codec_cx_pkt_t *pkt)
489 {
490     char             header[12];
491     vpx_codec_pts_t  pts;
492
493     if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
494         return;
495
496     pts = pkt->data.frame.pts;
497     mem_put_le32(header, pkt->data.frame.sz);
498     mem_put_le32(header + 4, pts & 0xFFFFFFFF);
499     mem_put_le32(header + 8, pts >> 32);
500
501     (void) fwrite(header, 1, 12, outfile);
502 }
503
504 static void write_ivf_frame_size(FILE *outfile, size_t size)
505 {
506     char             header[4];
507     mem_put_le32(header, size);
508     (void) fwrite(header, 1, 4, outfile);
509 }
510
511
512 typedef off_t EbmlLoc;
513
514
515 struct cue_entry
516 {
517     unsigned int time;
518     uint64_t     loc;
519 };
520
521
522 struct EbmlGlobal
523 {
524     int debug;
525
526     FILE    *stream;
527     int64_t last_pts_ms;
528     vpx_rational_t  framerate;
529
530     /* These pointers are to the start of an element */
531     off_t    position_reference;
532     off_t    seek_info_pos;
533     off_t    segment_info_pos;
534     off_t    track_pos;
535     off_t    cue_pos;
536     off_t    cluster_pos;
537
538     /* This pointer is to a specific element to be serialized */
539     off_t    track_id_pos;
540
541     /* These pointers are to the size field of the element */
542     EbmlLoc  startSegment;
543     EbmlLoc  startCluster;
544
545     uint32_t cluster_timecode;
546     int      cluster_open;
547
548     struct cue_entry *cue_list;
549     unsigned int      cues;
550
551 };
552
553
554 void Ebml_Write(EbmlGlobal *glob, const void *buffer_in, unsigned long len)
555 {
556     (void) fwrite(buffer_in, 1, len, glob->stream);
557 }
558
559 #define WRITE_BUFFER(s) \
560 for(i = len-1; i>=0; i--)\
561 { \
562     x = *(const s *)buffer_in >> (i * CHAR_BIT); \
563     Ebml_Write(glob, &x, 1); \
564 }
565 void Ebml_Serialize(EbmlGlobal *glob, const void *buffer_in, int buffer_size, unsigned long len)
566 {
567     char x;
568     int i;
569
570     /* buffer_size:
571      * 1 - int8_t;
572      * 2 - int16_t;
573      * 3 - int32_t;
574      * 4 - int64_t;
575      */
576     switch (buffer_size)
577     {
578         case 1:
579             WRITE_BUFFER(int8_t)
580             break;
581         case 2:
582             WRITE_BUFFER(int16_t)
583             break;
584         case 4:
585             WRITE_BUFFER(int32_t)
586             break;
587         case 8:
588             WRITE_BUFFER(int64_t)
589             break;
590         default:
591             break;
592     }
593 }
594 #undef WRITE_BUFFER
595
596 /* Need a fixed size serializer for the track ID. libmkv provides a 64 bit
597  * one, but not a 32 bit one.
598  */
599 static void Ebml_SerializeUnsigned32(EbmlGlobal *glob, unsigned long class_id, uint64_t ui)
600 {
601     unsigned char sizeSerialized = 4 | 0x80;
602     Ebml_WriteID(glob, class_id);
603     Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1);
604     Ebml_Serialize(glob, &ui, sizeof(ui), 4);
605 }
606
607
608 static void
609 Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc,
610                           unsigned long class_id)
611 {
612     /* todo this is always taking 8 bytes, this may need later optimization */
613     /* this is a key that says length unknown */
614     uint64_t unknownLen = LITERALU64(0x01FFFFFF, 0xFFFFFFFF);
615
616     Ebml_WriteID(glob, class_id);
617     *ebmlLoc = ftello(glob->stream);
618     Ebml_Serialize(glob, &unknownLen, sizeof(unknownLen), 8);
619 }
620
621 static void
622 Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc)
623 {
624     off_t pos;
625     uint64_t size;
626
627     /* Save the current stream pointer */
628     pos = ftello(glob->stream);
629
630     /* Calculate the size of this element */
631     size = pos - *ebmlLoc - 8;
632     size |= LITERALU64(0x01000000,0x00000000);
633
634     /* Seek back to the beginning of the element and write the new size */
635     fseeko(glob->stream, *ebmlLoc, SEEK_SET);
636     Ebml_Serialize(glob, &size, sizeof(size), 8);
637
638     /* Reset the stream pointer */
639     fseeko(glob->stream, pos, SEEK_SET);
640 }
641
642
643 static void
644 write_webm_seek_element(EbmlGlobal *ebml, unsigned long id, off_t pos)
645 {
646     uint64_t offset = pos - ebml->position_reference;
647     EbmlLoc start;
648     Ebml_StartSubElement(ebml, &start, Seek);
649     Ebml_SerializeBinary(ebml, SeekID, id);
650     Ebml_SerializeUnsigned64(ebml, SeekPosition, offset);
651     Ebml_EndSubElement(ebml, &start);
652 }
653
654
655 static void
656 write_webm_seek_info(EbmlGlobal *ebml)
657 {
658
659     off_t pos;
660
661     /* Save the current stream pointer */
662     pos = ftello(ebml->stream);
663
664     if(ebml->seek_info_pos)
665         fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET);
666     else
667         ebml->seek_info_pos = pos;
668
669     {
670         EbmlLoc start;
671
672         Ebml_StartSubElement(ebml, &start, SeekHead);
673         write_webm_seek_element(ebml, Tracks, ebml->track_pos);
674         write_webm_seek_element(ebml, Cues,   ebml->cue_pos);
675         write_webm_seek_element(ebml, Info,   ebml->segment_info_pos);
676         Ebml_EndSubElement(ebml, &start);
677     }
678     {
679         /* segment info */
680         EbmlLoc startInfo;
681         uint64_t frame_time;
682         char version_string[64];
683
684         /* Assemble version string */
685         if(ebml->debug)
686             strcpy(version_string, "vpxenc");
687         else
688         {
689             strcpy(version_string, "vpxenc ");
690             strncat(version_string,
691                     vpx_codec_version_str(),
692                     sizeof(version_string) - 1 - strlen(version_string));
693         }
694
695         frame_time = (uint64_t)1000 * ebml->framerate.den
696                      / ebml->framerate.num;
697         ebml->segment_info_pos = ftello(ebml->stream);
698         Ebml_StartSubElement(ebml, &startInfo, Info);
699         Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000);
700         Ebml_SerializeFloat(ebml, Segment_Duration,
701                             ebml->last_pts_ms + frame_time);
702         Ebml_SerializeString(ebml, 0x4D80, version_string);
703         Ebml_SerializeString(ebml, 0x5741, version_string);
704         Ebml_EndSubElement(ebml, &startInfo);
705     }
706 }
707
708
709 static void
710 write_webm_file_header(EbmlGlobal                *glob,
711                        const vpx_codec_enc_cfg_t *cfg,
712                        const struct vpx_rational *fps,
713                        stereo_format_t            stereo_fmt)
714 {
715     {
716         EbmlLoc start;
717         Ebml_StartSubElement(glob, &start, EBML);
718         Ebml_SerializeUnsigned(glob, EBMLVersion, 1);
719         Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1);
720         Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4);
721         Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8);
722         Ebml_SerializeString(glob, DocType, "webm");
723         Ebml_SerializeUnsigned(glob, DocTypeVersion, 2);
724         Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2);
725         Ebml_EndSubElement(glob, &start);
726     }
727     {
728         Ebml_StartSubElement(glob, &glob->startSegment, Segment);
729         glob->position_reference = ftello(glob->stream);
730         glob->framerate = *fps;
731         write_webm_seek_info(glob);
732
733         {
734             EbmlLoc trackStart;
735             glob->track_pos = ftello(glob->stream);
736             Ebml_StartSubElement(glob, &trackStart, Tracks);
737             {
738                 unsigned int trackNumber = 1;
739                 uint64_t     trackID = 0;
740
741                 EbmlLoc start;
742                 Ebml_StartSubElement(glob, &start, TrackEntry);
743                 Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber);
744                 glob->track_id_pos = ftello(glob->stream);
745                 Ebml_SerializeUnsigned32(glob, TrackUID, trackID);
746                 Ebml_SerializeUnsigned(glob, TrackType, 1);
747                 Ebml_SerializeString(glob, CodecID, "V_VP8");
748                 {
749                     unsigned int pixelWidth = cfg->g_w;
750                     unsigned int pixelHeight = cfg->g_h;
751                     float        frameRate   = (float)fps->num/(float)fps->den;
752
753                     EbmlLoc videoStart;
754                     Ebml_StartSubElement(glob, &videoStart, Video);
755                     Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth);
756                     Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight);
757                     Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt);
758                     Ebml_SerializeFloat(glob, FrameRate, frameRate);
759                     Ebml_EndSubElement(glob, &videoStart);
760                 }
761                 Ebml_EndSubElement(glob, &start); /* Track Entry */
762             }
763             Ebml_EndSubElement(glob, &trackStart);
764         }
765         /* segment element is open */
766     }
767 }
768
769
770 static void
771 write_webm_block(EbmlGlobal                *glob,
772                  const vpx_codec_enc_cfg_t *cfg,
773                  const vpx_codec_cx_pkt_t  *pkt)
774 {
775     unsigned long  block_length;
776     unsigned char  track_number;
777     unsigned short block_timecode = 0;
778     unsigned char  flags;
779     int64_t        pts_ms;
780     int            start_cluster = 0, is_keyframe;
781
782     /* Calculate the PTS of this frame in milliseconds */
783     pts_ms = pkt->data.frame.pts * 1000
784              * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
785     if(pts_ms <= glob->last_pts_ms)
786         pts_ms = glob->last_pts_ms + 1;
787     glob->last_pts_ms = pts_ms;
788
789     /* Calculate the relative time of this block */
790     if(pts_ms - glob->cluster_timecode > SHRT_MAX)
791         start_cluster = 1;
792     else
793         block_timecode = pts_ms - glob->cluster_timecode;
794
795     is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY);
796     if(start_cluster || is_keyframe)
797     {
798         if(glob->cluster_open)
799             Ebml_EndSubElement(glob, &glob->startCluster);
800
801         /* Open the new cluster */
802         block_timecode = 0;
803         glob->cluster_open = 1;
804         glob->cluster_timecode = pts_ms;
805         glob->cluster_pos = ftello(glob->stream);
806         Ebml_StartSubElement(glob, &glob->startCluster, Cluster); /* cluster */
807         Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode);
808
809         /* Save a cue point if this is a keyframe. */
810         if(is_keyframe)
811         {
812             struct cue_entry *cue, *new_cue_list;
813
814             new_cue_list = realloc(glob->cue_list,
815                                    (glob->cues+1) * sizeof(struct cue_entry));
816             if(new_cue_list)
817                 glob->cue_list = new_cue_list;
818             else
819                 fatal("Failed to realloc cue list.");
820
821             cue = &glob->cue_list[glob->cues];
822             cue->time = glob->cluster_timecode;
823             cue->loc = glob->cluster_pos;
824             glob->cues++;
825         }
826     }
827
828     /* Write the Simple Block */
829     Ebml_WriteID(glob, SimpleBlock);
830
831     block_length = pkt->data.frame.sz + 4;
832     block_length |= 0x10000000;
833     Ebml_Serialize(glob, &block_length, sizeof(block_length), 4);
834
835     track_number = 1;
836     track_number |= 0x80;
837     Ebml_Write(glob, &track_number, 1);
838
839     Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2);
840
841     flags = 0;
842     if(is_keyframe)
843         flags |= 0x80;
844     if(pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE)
845         flags |= 0x08;
846     Ebml_Write(glob, &flags, 1);
847
848     Ebml_Write(glob, pkt->data.frame.buf, pkt->data.frame.sz);
849 }
850
851
852 static void
853 write_webm_file_footer(EbmlGlobal *glob, long hash)
854 {
855
856     if(glob->cluster_open)
857         Ebml_EndSubElement(glob, &glob->startCluster);
858
859     {
860         EbmlLoc start;
861         unsigned int i;
862
863         glob->cue_pos = ftello(glob->stream);
864         Ebml_StartSubElement(glob, &start, Cues);
865         for(i=0; i<glob->cues; i++)
866         {
867             struct cue_entry *cue = &glob->cue_list[i];
868             EbmlLoc start;
869
870             Ebml_StartSubElement(glob, &start, CuePoint);
871             {
872                 EbmlLoc start;
873
874                 Ebml_SerializeUnsigned(glob, CueTime, cue->time);
875
876                 Ebml_StartSubElement(glob, &start, CueTrackPositions);
877                 Ebml_SerializeUnsigned(glob, CueTrack, 1);
878                 Ebml_SerializeUnsigned64(glob, CueClusterPosition,
879                                          cue->loc - glob->position_reference);
880                 Ebml_EndSubElement(glob, &start);
881             }
882             Ebml_EndSubElement(glob, &start);
883         }
884         Ebml_EndSubElement(glob, &start);
885     }
886
887     Ebml_EndSubElement(glob, &glob->startSegment);
888
889     /* Patch up the seek info block */
890     write_webm_seek_info(glob);
891
892     /* Patch up the track id */
893     fseeko(glob->stream, glob->track_id_pos, SEEK_SET);
894     Ebml_SerializeUnsigned32(glob, TrackUID, glob->debug ? 0xDEADBEEF : hash);
895
896     fseeko(glob->stream, 0, SEEK_END);
897 }
898
899
900 /* Murmur hash derived from public domain reference implementation at
901  *   http://sites.google.com/site/murmurhash/
902  */
903 static unsigned int murmur ( const void * key, int len, unsigned int seed )
904 {
905     const unsigned int m = 0x5bd1e995;
906     const int r = 24;
907
908     unsigned int h = seed ^ len;
909
910     const unsigned char * data = (const unsigned char *)key;
911
912     while(len >= 4)
913     {
914         unsigned int k;
915
916         k  = data[0];
917         k |= data[1] << 8;
918         k |= data[2] << 16;
919         k |= data[3] << 24;
920
921         k *= m;
922         k ^= k >> r;
923         k *= m;
924
925         h *= m;
926         h ^= k;
927
928         data += 4;
929         len -= 4;
930     }
931
932     switch(len)
933     {
934     case 3: h ^= data[2] << 16;
935     case 2: h ^= data[1] << 8;
936     case 1: h ^= data[0];
937             h *= m;
938     };
939
940     h ^= h >> 13;
941     h *= m;
942     h ^= h >> 15;
943
944     return h;
945 }
946
947 #include "math.h"
948
949 static double vp8_mse2psnr(double Samples, double Peak, double Mse)
950 {
951     double psnr;
952
953     if ((double)Mse > 0.0)
954         psnr = 10.0 * log10(Peak * Peak * Samples / Mse);
955     else
956         psnr = 60;      /* Limit to prevent / 0 */
957
958     if (psnr > 60)
959         psnr = 60;
960
961     return psnr;
962 }
963
964
965 #include "args.h"
966 static const arg_def_t debugmode = ARG_DEF("D", "debug", 0,
967         "Debug mode (makes output deterministic)");
968 static const arg_def_t outputfile = ARG_DEF("o", "output", 1,
969         "Output filename");
970 static const arg_def_t use_yv12 = ARG_DEF(NULL, "yv12", 0,
971                                   "Input file is YV12 ");
972 static const arg_def_t use_i420 = ARG_DEF(NULL, "i420", 0,
973                                   "Input file is I420 (default)");
974 static const arg_def_t codecarg = ARG_DEF(NULL, "codec", 1,
975                                   "Codec to use");
976 static const arg_def_t passes           = ARG_DEF("p", "passes", 1,
977         "Number of passes (1/2)");
978 static const arg_def_t pass_arg         = ARG_DEF(NULL, "pass", 1,
979         "Pass to execute (1/2)");
980 static const arg_def_t fpf_name         = ARG_DEF(NULL, "fpf", 1,
981         "First pass statistics file name");
982 static const arg_def_t limit = ARG_DEF(NULL, "limit", 1,
983                                        "Stop encoding after n input frames");
984 static const arg_def_t deadline         = ARG_DEF("d", "deadline", 1,
985         "Deadline per frame (usec)");
986 static const arg_def_t best_dl          = ARG_DEF(NULL, "best", 0,
987         "Use Best Quality Deadline");
988 static const arg_def_t good_dl          = ARG_DEF(NULL, "good", 0,
989         "Use Good Quality Deadline");
990 static const arg_def_t rt_dl            = ARG_DEF(NULL, "rt", 0,
991         "Use Realtime Quality Deadline");
992 static const arg_def_t verbosearg       = ARG_DEF("v", "verbose", 0,
993         "Show encoder parameters");
994 static const arg_def_t psnrarg          = ARG_DEF(NULL, "psnr", 0,
995         "Show PSNR in status line");
996 static const arg_def_t framerate        = ARG_DEF(NULL, "fps", 1,
997         "Stream frame rate (rate/scale)");
998 static const arg_def_t use_ivf          = ARG_DEF(NULL, "ivf", 0,
999         "Output IVF (default is WebM)");
1000 static const arg_def_t out_part = ARG_DEF("P", "output-partitions", 0,
1001         "Makes encoder output partitions. Requires IVF output!");
1002 static const arg_def_t q_hist_n         = ARG_DEF(NULL, "q-hist", 1,
1003         "Show quantizer histogram (n-buckets)");
1004 static const arg_def_t rate_hist_n         = ARG_DEF(NULL, "rate-hist", 1,
1005         "Show rate histogram (n-buckets)");
1006 static const arg_def_t *main_args[] =
1007 {
1008     &debugmode,
1009     &outputfile, &codecarg, &passes, &pass_arg, &fpf_name, &limit, &deadline,
1010     &best_dl, &good_dl, &rt_dl,
1011     &verbosearg, &psnrarg, &use_ivf, &out_part, &q_hist_n, &rate_hist_n,
1012     NULL
1013 };
1014
1015 static const arg_def_t usage            = ARG_DEF("u", "usage", 1,
1016         "Usage profile number to use");
1017 static const arg_def_t threads          = ARG_DEF("t", "threads", 1,
1018         "Max number of threads to use");
1019 static const arg_def_t profile          = ARG_DEF(NULL, "profile", 1,
1020         "Bitstream profile number to use");
1021 static const arg_def_t width            = ARG_DEF("w", "width", 1,
1022         "Frame width");
1023 static const arg_def_t height           = ARG_DEF("h", "height", 1,
1024         "Frame height");
1025 static const struct arg_enum_list stereo_mode_enum[] = {
1026     {"mono"      , STEREO_FORMAT_MONO},
1027     {"left-right", STEREO_FORMAT_LEFT_RIGHT},
1028     {"bottom-top", STEREO_FORMAT_BOTTOM_TOP},
1029     {"top-bottom", STEREO_FORMAT_TOP_BOTTOM},
1030     {"right-left", STEREO_FORMAT_RIGHT_LEFT},
1031     {NULL, 0}
1032 };
1033 static const arg_def_t stereo_mode      = ARG_DEF_ENUM(NULL, "stereo-mode", 1,
1034         "Stereo 3D video format", stereo_mode_enum);
1035 static const arg_def_t timebase         = ARG_DEF(NULL, "timebase", 1,
1036         "Output timestamp precision (fractional seconds)");
1037 static const arg_def_t error_resilient  = ARG_DEF(NULL, "error-resilient", 1,
1038         "Enable error resiliency features");
1039 static const arg_def_t lag_in_frames    = ARG_DEF(NULL, "lag-in-frames", 1,
1040         "Max number of frames to lag");
1041
1042 static const arg_def_t *global_args[] =
1043 {
1044     &use_yv12, &use_i420, &usage, &threads, &profile,
1045     &width, &height, &stereo_mode, &timebase, &framerate, &error_resilient,
1046     &lag_in_frames, NULL
1047 };
1048
1049 static const arg_def_t dropframe_thresh   = ARG_DEF(NULL, "drop-frame", 1,
1050         "Temporal resampling threshold (buf %)");
1051 static const arg_def_t resize_allowed     = ARG_DEF(NULL, "resize-allowed", 1,
1052         "Spatial resampling enabled (bool)");
1053 static const arg_def_t resize_up_thresh   = ARG_DEF(NULL, "resize-up", 1,
1054         "Upscale threshold (buf %)");
1055 static const arg_def_t resize_down_thresh = ARG_DEF(NULL, "resize-down", 1,
1056         "Downscale threshold (buf %)");
1057 static const struct arg_enum_list end_usage_enum[] = {
1058     {"vbr", VPX_VBR},
1059     {"cbr", VPX_CBR},
1060     {"cq",  VPX_CQ},
1061     {NULL, 0}
1062 };
1063 static const arg_def_t end_usage          = ARG_DEF_ENUM(NULL, "end-usage", 1,
1064         "Rate control mode", end_usage_enum);
1065 static const arg_def_t target_bitrate     = ARG_DEF(NULL, "target-bitrate", 1,
1066         "Bitrate (kbps)");
1067 static const arg_def_t min_quantizer      = ARG_DEF(NULL, "min-q", 1,
1068         "Minimum (best) quantizer");
1069 static const arg_def_t max_quantizer      = ARG_DEF(NULL, "max-q", 1,
1070         "Maximum (worst) quantizer");
1071 static const arg_def_t undershoot_pct     = ARG_DEF(NULL, "undershoot-pct", 1,
1072         "Datarate undershoot (min) target (%)");
1073 static const arg_def_t overshoot_pct      = ARG_DEF(NULL, "overshoot-pct", 1,
1074         "Datarate overshoot (max) target (%)");
1075 static const arg_def_t buf_sz             = ARG_DEF(NULL, "buf-sz", 1,
1076         "Client buffer size (ms)");
1077 static const arg_def_t buf_initial_sz     = ARG_DEF(NULL, "buf-initial-sz", 1,
1078         "Client initial buffer size (ms)");
1079 static const arg_def_t buf_optimal_sz     = ARG_DEF(NULL, "buf-optimal-sz", 1,
1080         "Client optimal buffer size (ms)");
1081 static const arg_def_t *rc_args[] =
1082 {
1083     &dropframe_thresh, &resize_allowed, &resize_up_thresh, &resize_down_thresh,
1084     &end_usage, &target_bitrate, &min_quantizer, &max_quantizer,
1085     &undershoot_pct, &overshoot_pct, &buf_sz, &buf_initial_sz, &buf_optimal_sz,
1086     NULL
1087 };
1088
1089
1090 static const arg_def_t bias_pct = ARG_DEF(NULL, "bias-pct", 1,
1091                                   "CBR/VBR bias (0=CBR, 100=VBR)");
1092 static const arg_def_t minsection_pct = ARG_DEF(NULL, "minsection-pct", 1,
1093                                         "GOP min bitrate (% of target)");
1094 static const arg_def_t maxsection_pct = ARG_DEF(NULL, "maxsection-pct", 1,
1095                                         "GOP max bitrate (% of target)");
1096 static const arg_def_t *rc_twopass_args[] =
1097 {
1098     &bias_pct, &minsection_pct, &maxsection_pct, NULL
1099 };
1100
1101
1102 static const arg_def_t kf_min_dist = ARG_DEF(NULL, "kf-min-dist", 1,
1103                                      "Minimum keyframe interval (frames)");
1104 static const arg_def_t kf_max_dist = ARG_DEF(NULL, "kf-max-dist", 1,
1105                                      "Maximum keyframe interval (frames)");
1106 static const arg_def_t kf_disabled = ARG_DEF(NULL, "disable-kf", 0,
1107                                      "Disable keyframe placement");
1108 static const arg_def_t *kf_args[] =
1109 {
1110     &kf_min_dist, &kf_max_dist, &kf_disabled, NULL
1111 };
1112
1113
1114 #if CONFIG_VP8_ENCODER
1115 static const arg_def_t noise_sens = ARG_DEF(NULL, "noise-sensitivity", 1,
1116                                     "Noise sensitivity (frames to blur)");
1117 static const arg_def_t sharpness = ARG_DEF(NULL, "sharpness", 1,
1118                                    "Filter sharpness (0-7)");
1119 static const arg_def_t static_thresh = ARG_DEF(NULL, "static-thresh", 1,
1120                                        "Motion detection threshold");
1121 #endif
1122
1123 #if CONFIG_VP8_ENCODER
1124 static const arg_def_t cpu_used = ARG_DEF(NULL, "cpu-used", 1,
1125                                   "CPU Used (-16..16)");
1126 #endif
1127
1128
1129 #if CONFIG_VP8_ENCODER
1130 static const arg_def_t token_parts = ARG_DEF(NULL, "token-parts", 1,
1131                                      "Number of token partitions to use, log2");
1132 static const arg_def_t auto_altref = ARG_DEF(NULL, "auto-alt-ref", 1,
1133                                      "Enable automatic alt reference frames");
1134 static const arg_def_t arnr_maxframes = ARG_DEF(NULL, "arnr-maxframes", 1,
1135                                         "AltRef Max Frames");
1136 static const arg_def_t arnr_strength = ARG_DEF(NULL, "arnr-strength", 1,
1137                                        "AltRef Strength");
1138 static const arg_def_t arnr_type = ARG_DEF(NULL, "arnr-type", 1,
1139                                    "AltRef Type");
1140 static const struct arg_enum_list tuning_enum[] = {
1141     {"psnr", VP8_TUNE_PSNR},
1142     {"ssim", VP8_TUNE_SSIM},
1143     {NULL, 0}
1144 };
1145 static const arg_def_t tune_ssim = ARG_DEF_ENUM(NULL, "tune", 1,
1146                                    "Material to favor", tuning_enum);
1147 static const arg_def_t cq_level = ARG_DEF(NULL, "cq-level", 1,
1148                                    "Constrained Quality Level");
1149 static const arg_def_t max_intra_rate_pct = ARG_DEF(NULL, "max-intra-rate", 1,
1150         "Max I-frame bitrate (pct)");
1151
1152 static const arg_def_t *vp8_args[] =
1153 {
1154     &cpu_used, &auto_altref, &noise_sens, &sharpness, &static_thresh,
1155     &token_parts, &arnr_maxframes, &arnr_strength, &arnr_type,
1156     &tune_ssim, &cq_level, &max_intra_rate_pct, NULL
1157 };
1158 static const int vp8_arg_ctrl_map[] =
1159 {
1160     VP8E_SET_CPUUSED, VP8E_SET_ENABLEAUTOALTREF,
1161     VP8E_SET_NOISE_SENSITIVITY, VP8E_SET_SHARPNESS, VP8E_SET_STATIC_THRESHOLD,
1162     VP8E_SET_TOKEN_PARTITIONS,
1163     VP8E_SET_ARNR_MAXFRAMES, VP8E_SET_ARNR_STRENGTH , VP8E_SET_ARNR_TYPE,
1164     VP8E_SET_TUNING, VP8E_SET_CQ_LEVEL, VP8E_SET_MAX_INTRA_BITRATE_PCT, 0
1165 };
1166 #endif
1167
1168 static const arg_def_t *no_args[] = { NULL };
1169
1170 static void usage_exit()
1171 {
1172     int i;
1173
1174     fprintf(stderr, "Usage: %s <options> -o dst_filename src_filename \n",
1175             exec_name);
1176
1177     fprintf(stderr, "\nOptions:\n");
1178     arg_show_usage(stdout, main_args);
1179     fprintf(stderr, "\nEncoder Global Options:\n");
1180     arg_show_usage(stdout, global_args);
1181     fprintf(stderr, "\nRate Control Options:\n");
1182     arg_show_usage(stdout, rc_args);
1183     fprintf(stderr, "\nTwopass Rate Control Options:\n");
1184     arg_show_usage(stdout, rc_twopass_args);
1185     fprintf(stderr, "\nKeyframe Placement Options:\n");
1186     arg_show_usage(stdout, kf_args);
1187 #if CONFIG_VP8_ENCODER
1188     fprintf(stderr, "\nVP8 Specific Options:\n");
1189     arg_show_usage(stdout, vp8_args);
1190 #endif
1191     fprintf(stderr, "\nStream timebase (--timebase):\n"
1192             "  The desired precision of timestamps in the output, expressed\n"
1193             "  in fractional seconds. Default is 1/1000.\n");
1194     fprintf(stderr, "\n"
1195            "Included encoders:\n"
1196            "\n");
1197
1198     for (i = 0; i < sizeof(codecs) / sizeof(codecs[0]); i++)
1199         fprintf(stderr, "    %-6s - %s\n",
1200                codecs[i].name,
1201                vpx_codec_iface_name(codecs[i].iface));
1202
1203     exit(EXIT_FAILURE);
1204 }
1205
1206
1207 #define HIST_BAR_MAX 40
1208 struct hist_bucket
1209 {
1210     int low, high, count;
1211 };
1212
1213
1214 static int merge_hist_buckets(struct hist_bucket *bucket,
1215                               int *buckets_,
1216                               int max_buckets)
1217 {
1218     int small_bucket = 0, merge_bucket = INT_MAX, big_bucket=0;
1219     int buckets = *buckets_;
1220     int i;
1221
1222     /* Find the extrema for this list of buckets */
1223     big_bucket = small_bucket = 0;
1224     for(i=0; i < buckets; i++)
1225     {
1226         if(bucket[i].count < bucket[small_bucket].count)
1227             small_bucket = i;
1228         if(bucket[i].count > bucket[big_bucket].count)
1229             big_bucket = i;
1230     }
1231
1232     /* If we have too many buckets, merge the smallest with an adjacent
1233      * bucket.
1234      */
1235     while(buckets > max_buckets)
1236     {
1237         int last_bucket = buckets - 1;
1238
1239         /* merge the small bucket with an adjacent one. */
1240         if(small_bucket == 0)
1241             merge_bucket = 1;
1242         else if(small_bucket == last_bucket)
1243             merge_bucket = last_bucket - 1;
1244         else if(bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
1245             merge_bucket = small_bucket - 1;
1246         else
1247             merge_bucket = small_bucket + 1;
1248
1249         assert(abs(merge_bucket - small_bucket) <= 1);
1250         assert(small_bucket < buckets);
1251         assert(big_bucket < buckets);
1252         assert(merge_bucket < buckets);
1253
1254         if(merge_bucket < small_bucket)
1255         {
1256             bucket[merge_bucket].high = bucket[small_bucket].high;
1257             bucket[merge_bucket].count += bucket[small_bucket].count;
1258         }
1259         else
1260         {
1261             bucket[small_bucket].high = bucket[merge_bucket].high;
1262             bucket[small_bucket].count += bucket[merge_bucket].count;
1263             merge_bucket = small_bucket;
1264         }
1265
1266         assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
1267
1268         buckets--;
1269
1270         /* Remove the merge_bucket from the list, and find the new small
1271          * and big buckets while we're at it
1272          */
1273         big_bucket = small_bucket = 0;
1274         for(i=0; i < buckets; i++)
1275         {
1276             if(i > merge_bucket)
1277                 bucket[i] = bucket[i+1];
1278
1279             if(bucket[i].count < bucket[small_bucket].count)
1280                 small_bucket = i;
1281             if(bucket[i].count > bucket[big_bucket].count)
1282                 big_bucket = i;
1283         }
1284
1285     }
1286
1287     *buckets_ = buckets;
1288     return bucket[big_bucket].count;
1289 }
1290
1291
1292 static void show_histogram(const struct hist_bucket *bucket,
1293                            int                       buckets,
1294                            int                       total,
1295                            int                       scale)
1296 {
1297     const char *pat1, *pat2;
1298     int i;
1299
1300     switch((int)(log(bucket[buckets-1].high)/log(10))+1)
1301     {
1302         case 1:
1303         case 2:
1304             pat1 = "%4d %2s: ";
1305             pat2 = "%4d-%2d: ";
1306             break;
1307         case 3:
1308             pat1 = "%5d %3s: ";
1309             pat2 = "%5d-%3d: ";
1310             break;
1311         case 4:
1312             pat1 = "%6d %4s: ";
1313             pat2 = "%6d-%4d: ";
1314             break;
1315         case 5:
1316             pat1 = "%7d %5s: ";
1317             pat2 = "%7d-%5d: ";
1318             break;
1319         case 6:
1320             pat1 = "%8d %6s: ";
1321             pat2 = "%8d-%6d: ";
1322             break;
1323         case 7:
1324             pat1 = "%9d %7s: ";
1325             pat2 = "%9d-%7d: ";
1326             break;
1327         default:
1328             pat1 = "%12d %10s: ";
1329             pat2 = "%12d-%10d: ";
1330             break;
1331     }
1332
1333     for(i=0; i<buckets; i++)
1334     {
1335         int len;
1336         int j;
1337         float pct;
1338
1339         pct = 100.0 * (float)bucket[i].count / (float)total;
1340         len = HIST_BAR_MAX * bucket[i].count / scale;
1341         if(len < 1)
1342             len = 1;
1343         assert(len <= HIST_BAR_MAX);
1344
1345         if(bucket[i].low == bucket[i].high)
1346             fprintf(stderr, pat1, bucket[i].low, "");
1347         else
1348             fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
1349
1350         for(j=0; j<HIST_BAR_MAX; j++)
1351             fprintf(stderr, j<len?"=":" ");
1352         fprintf(stderr, "\t%5d (%6.2f%%)\n",bucket[i].count,pct);
1353     }
1354 }
1355
1356
1357 static void show_q_histogram(const int counts[64], int max_buckets)
1358 {
1359     struct hist_bucket bucket[64];
1360     int buckets = 0;
1361     int total = 0;
1362     int scale;
1363     int i;
1364
1365
1366     for(i=0; i<64; i++)
1367     {
1368         if(counts[i])
1369         {
1370             bucket[buckets].low = bucket[buckets].high = i;
1371             bucket[buckets].count = counts[i];
1372             buckets++;
1373             total += counts[i];
1374         }
1375     }
1376
1377     fprintf(stderr, "\nQuantizer Selection:\n");
1378     scale = merge_hist_buckets(bucket, &buckets, max_buckets);
1379     show_histogram(bucket, buckets, total, scale);
1380 }
1381
1382
1383 #define RATE_BINS (100)
1384 struct rate_hist
1385 {
1386     int64_t            *pts;
1387     int                *sz;
1388     int                 samples;
1389     int                 frames;
1390     struct hist_bucket  bucket[RATE_BINS];
1391     int                 total;
1392 };
1393
1394
1395 static void init_rate_histogram(struct rate_hist          *hist,
1396                                 const vpx_codec_enc_cfg_t *cfg,
1397                                 const vpx_rational_t      *fps)
1398 {
1399     int i;
1400
1401     /* Determine the number of samples in the buffer. Use the file's framerate
1402      * to determine the number of frames in rc_buf_sz milliseconds, with an
1403      * adjustment (5/4) to account for alt-refs
1404      */
1405     hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
1406
1407     /* prevent division by zero */
1408     if (hist->samples == 0)
1409       hist->samples=1;
1410
1411     hist->pts = calloc(hist->samples, sizeof(*hist->pts));
1412     hist->sz = calloc(hist->samples, sizeof(*hist->sz));
1413     for(i=0; i<RATE_BINS; i++)
1414     {
1415         hist->bucket[i].low = INT_MAX;
1416         hist->bucket[i].high = 0;
1417         hist->bucket[i].count = 0;
1418     }
1419 }
1420
1421
1422 static void destroy_rate_histogram(struct rate_hist *hist)
1423 {
1424     free(hist->pts);
1425     free(hist->sz);
1426 }
1427
1428
1429 static void update_rate_histogram(struct rate_hist          *hist,
1430                                   const vpx_codec_enc_cfg_t *cfg,
1431                                   const vpx_codec_cx_pkt_t  *pkt)
1432 {
1433     int i, idx;
1434     int64_t now, then, sum_sz = 0, avg_bitrate;
1435
1436     now = pkt->data.frame.pts * 1000
1437           * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den;
1438
1439     idx = hist->frames++ % hist->samples;
1440     hist->pts[idx] = now;
1441     hist->sz[idx] = pkt->data.frame.sz;
1442
1443     if(now < cfg->rc_buf_initial_sz)
1444         return;
1445
1446     then = now;
1447
1448     /* Sum the size over the past rc_buf_sz ms */
1449     for(i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--)
1450     {
1451         int i_idx = (i-1) % hist->samples;
1452
1453         then = hist->pts[i_idx];
1454         if(now - then > cfg->rc_buf_sz)
1455             break;
1456         sum_sz += hist->sz[i_idx];
1457     }
1458
1459     if (now == then)
1460         return;
1461
1462     avg_bitrate = sum_sz * 8 * 1000 / (now - then);
1463     idx = avg_bitrate * (RATE_BINS/2) / (cfg->rc_target_bitrate * 1000);
1464     if(idx < 0)
1465         idx = 0;
1466     if(idx > RATE_BINS-1)
1467         idx = RATE_BINS-1;
1468     if(hist->bucket[idx].low > avg_bitrate)
1469         hist->bucket[idx].low = avg_bitrate;
1470     if(hist->bucket[idx].high < avg_bitrate)
1471         hist->bucket[idx].high = avg_bitrate;
1472     hist->bucket[idx].count++;
1473     hist->total++;
1474 }
1475
1476
1477 static void show_rate_histogram(struct rate_hist          *hist,
1478                                 const vpx_codec_enc_cfg_t *cfg,
1479                                 int                        max_buckets)
1480 {
1481     int i, scale;
1482     int buckets = 0;
1483
1484     for(i = 0; i < RATE_BINS; i++)
1485     {
1486         if(hist->bucket[i].low == INT_MAX)
1487             continue;
1488         hist->bucket[buckets++] = hist->bucket[i];
1489     }
1490
1491     fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
1492     scale = merge_hist_buckets(hist->bucket, &buckets, max_buckets);
1493     show_histogram(hist->bucket, buckets, hist->total, scale);
1494 }
1495
1496 #define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
1497 #define ARG_CTRL_CNT_MAX NELEMENTS(vp8_arg_ctrl_map)
1498
1499
1500 /* Configuration elements common to all streams */
1501 struct global_config
1502 {
1503     const struct codec_item  *codec;
1504     int                       passes;
1505     int                       pass;
1506     int                       usage;
1507     int                       deadline;
1508     int                       use_i420;
1509     int                       verbose;
1510     int                       limit;
1511     int                       show_psnr;
1512     int                       have_framerate;
1513     struct vpx_rational       framerate;
1514     int                       out_part;
1515     int                       debug;
1516     int                       show_q_hist_buckets;
1517     int                       show_rate_hist_buckets;
1518 };
1519
1520
1521 /* Per-stream configuration */
1522 struct stream_config
1523 {
1524     struct vpx_codec_enc_cfg  cfg;
1525     const char               *out_fn;
1526     const char               *stats_fn;
1527     stereo_format_t           stereo_fmt;
1528     int                       arg_ctrls[ARG_CTRL_CNT_MAX][2];
1529     int                       arg_ctrl_cnt;
1530     int                       write_webm;
1531     int                       have_kf_max_dist;
1532 };
1533
1534
1535 struct stream_state
1536 {
1537     int                       index;
1538     struct stream_state      *next;
1539     struct stream_config      config;
1540     FILE                     *file;
1541     struct rate_hist          rate_hist;
1542     EbmlGlobal                ebml;
1543     uint32_t                  hash;
1544     uint64_t                  psnr_sse_total;
1545     uint64_t                  psnr_samples_total;
1546     double                    psnr_totals[4];
1547     int                       psnr_count;
1548     int                       counts[64];
1549     vpx_codec_ctx_t           encoder;
1550     unsigned int              frames_out;
1551     uint64_t                  cx_time;
1552     size_t                    nbytes;
1553     stats_io_t                stats;
1554 };
1555
1556
1557 void validate_positive_rational(const char          *msg,
1558                                 struct vpx_rational *rat)
1559 {
1560     if (rat->den < 0)
1561     {
1562         rat->num *= -1;
1563         rat->den *= -1;
1564     }
1565
1566     if (rat->num < 0)
1567         die("Error: %s must be positive\n", msg);
1568
1569     if (!rat->den)
1570         die("Error: %s has zero denominator\n", msg);
1571 }
1572
1573
1574 static void parse_global_config(struct global_config *global, char **argv)
1575 {
1576     char       **argi, **argj;
1577     struct arg   arg;
1578
1579     /* Initialize default parameters */
1580     memset(global, 0, sizeof(*global));
1581     global->codec = codecs;
1582     global->passes = 1;
1583     global->use_i420 = 1;
1584
1585     for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
1586     {
1587         arg.argv_step = 1;
1588
1589         if (arg_match(&arg, &codecarg, argi))
1590         {
1591             int j, k = -1;
1592
1593             for (j = 0; j < sizeof(codecs) / sizeof(codecs[0]); j++)
1594                 if (!strcmp(codecs[j].name, arg.val))
1595                     k = j;
1596
1597             if (k >= 0)
1598                 global->codec = codecs + k;
1599             else
1600                 die("Error: Unrecognized argument (%s) to --codec\n",
1601                     arg.val);
1602
1603         }
1604         else if (arg_match(&arg, &passes, argi))
1605         {
1606             global->passes = arg_parse_uint(&arg);
1607
1608             if (global->passes < 1 || global->passes > 2)
1609                 die("Error: Invalid number of passes (%d)\n", global->passes);
1610         }
1611         else if (arg_match(&arg, &pass_arg, argi))
1612         {
1613             global->pass = arg_parse_uint(&arg);
1614
1615             if (global->pass < 1 || global->pass > 2)
1616                 die("Error: Invalid pass selected (%d)\n",
1617                     global->pass);
1618         }
1619         else if (arg_match(&arg, &usage, argi))
1620             global->usage = arg_parse_uint(&arg);
1621         else if (arg_match(&arg, &deadline, argi))
1622             global->deadline = arg_parse_uint(&arg);
1623         else if (arg_match(&arg, &best_dl, argi))
1624             global->deadline = VPX_DL_BEST_QUALITY;
1625         else if (arg_match(&arg, &good_dl, argi))
1626             global->deadline = VPX_DL_GOOD_QUALITY;
1627         else if (arg_match(&arg, &rt_dl, argi))
1628             global->deadline = VPX_DL_REALTIME;
1629         else if (arg_match(&arg, &use_yv12, argi))
1630             global->use_i420 = 0;
1631         else if (arg_match(&arg, &use_i420, argi))
1632             global->use_i420 = 1;
1633         else if (arg_match(&arg, &verbosearg, argi))
1634             global->verbose = 1;
1635         else if (arg_match(&arg, &limit, argi))
1636             global->limit = arg_parse_uint(&arg);
1637         else if (arg_match(&arg, &psnrarg, argi))
1638             global->show_psnr = 1;
1639         else if (arg_match(&arg, &framerate, argi))
1640         {
1641             global->framerate = arg_parse_rational(&arg);
1642             validate_positive_rational(arg.name, &global->framerate);
1643             global->have_framerate = 1;
1644         }
1645         else if (arg_match(&arg,&out_part, argi))
1646             global->out_part = 1;
1647         else if (arg_match(&arg, &debugmode, argi))
1648             global->debug = 1;
1649         else if (arg_match(&arg, &q_hist_n, argi))
1650             global->show_q_hist_buckets = arg_parse_uint(&arg);
1651         else if (arg_match(&arg, &rate_hist_n, argi))
1652             global->show_rate_hist_buckets = arg_parse_uint(&arg);
1653         else
1654             argj++;
1655     }
1656
1657     /* Validate global config */
1658
1659     if (global->pass)
1660     {
1661         /* DWIM: Assume the user meant passes=2 if pass=2 is specified */
1662         if (global->pass > global->passes)
1663         {
1664             warn("Assuming --pass=%d implies --passes=%d\n",
1665                  global->pass, global->pass);
1666             global->passes = global->pass;
1667         }
1668     }
1669 }
1670
1671
1672 void open_input_file(struct input_state *input)
1673 {
1674     unsigned int fourcc;
1675
1676     /* Parse certain options from the input file, if possible */
1677     input->file = strcmp(input->fn, "-") ? fopen(input->fn, "rb")
1678                                          : set_binary_mode(stdin);
1679
1680     if (!input->file)
1681         fatal("Failed to open input file");
1682
1683     /* For RAW input sources, these bytes will applied on the first frame
1684      *  in read_frame().
1685      */
1686     input->detect.buf_read = fread(input->detect.buf, 1, 4, input->file);
1687     input->detect.position = 0;
1688
1689     if (input->detect.buf_read == 4
1690         && file_is_y4m(input->file, &input->y4m, input->detect.buf))
1691     {
1692         if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4) >= 0)
1693         {
1694             input->file_type = FILE_TYPE_Y4M;
1695             input->w = input->y4m.pic_w;
1696             input->h = input->y4m.pic_h;
1697             input->framerate.num = input->y4m.fps_n;
1698             input->framerate.den = input->y4m.fps_d;
1699             input->use_i420 = 0;
1700         }
1701         else
1702             fatal("Unsupported Y4M stream.");
1703     }
1704     else if (input->detect.buf_read == 4 && file_is_ivf(input, &fourcc))
1705     {
1706         input->file_type = FILE_TYPE_IVF;
1707         switch (fourcc)
1708         {
1709         case 0x32315659:
1710             input->use_i420 = 0;
1711             break;
1712         case 0x30323449:
1713             input->use_i420 = 1;
1714             break;
1715         default:
1716             fatal("Unsupported fourcc (%08x) in IVF", fourcc);
1717         }
1718     }
1719     else
1720     {
1721         input->file_type = FILE_TYPE_RAW;
1722     }
1723 }
1724
1725
1726 static void close_input_file(struct input_state *input)
1727 {
1728     fclose(input->file);
1729     if (input->file_type == FILE_TYPE_Y4M)
1730         y4m_input_close(&input->y4m);
1731 }
1732
1733 static struct stream_state *new_stream(struct global_config *global,
1734                                        struct stream_state  *prev)
1735 {
1736     struct stream_state *stream;
1737
1738     stream = calloc(1, sizeof(*stream));
1739     if(!stream)
1740         fatal("Failed to allocate new stream.");
1741     if(prev)
1742     {
1743         memcpy(stream, prev, sizeof(*stream));
1744         stream->index++;
1745         prev->next = stream;
1746     }
1747     else
1748     {
1749         vpx_codec_err_t  res;
1750
1751         /* Populate encoder configuration */
1752         res = vpx_codec_enc_config_default(global->codec->iface,
1753                                            &stream->config.cfg,
1754                                            global->usage);
1755         if (res)
1756             fatal("Failed to get config: %s\n", vpx_codec_err_to_string(res));
1757
1758         /* Change the default timebase to a high enough value so that the
1759          * encoder will always create strictly increasing timestamps.
1760          */
1761         stream->config.cfg.g_timebase.den = 1000;
1762
1763         /* Never use the library's default resolution, require it be parsed
1764          * from the file or set on the command line.
1765          */
1766         stream->config.cfg.g_w = 0;
1767         stream->config.cfg.g_h = 0;
1768
1769         /* Initialize remaining stream parameters */
1770         stream->config.stereo_fmt = STEREO_FORMAT_MONO;
1771         stream->config.write_webm = 1;
1772         stream->ebml.last_pts_ms = -1;
1773
1774         /* Allows removal of the application version from the EBML tags */
1775         stream->ebml.debug = global->debug;
1776     }
1777
1778     /* Output files must be specified for each stream */
1779     stream->config.out_fn = NULL;
1780
1781     stream->next = NULL;
1782     return stream;
1783 }
1784
1785
1786 static int parse_stream_params(struct global_config *global,
1787                                struct stream_state  *stream,
1788                                char **argv)
1789 {
1790     char                   **argi, **argj;
1791     struct arg               arg;
1792     static const arg_def_t **ctrl_args = no_args;
1793     static const int        *ctrl_args_map = NULL;
1794     struct stream_config    *config = &stream->config;
1795     int                      eos_mark_found = 0;
1796
1797     /* Handle codec specific options */
1798     if (global->codec->iface == &vpx_codec_vp8_cx_algo)
1799     {
1800         ctrl_args = vp8_args;
1801         ctrl_args_map = vp8_arg_ctrl_map;
1802     }
1803
1804     for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step)
1805     {
1806         arg.argv_step = 1;
1807
1808         /* Once we've found an end-of-stream marker (--) we want to continue
1809          * shifting arguments but not consuming them.
1810          */
1811         if (eos_mark_found)
1812         {
1813             argj++;
1814             continue;
1815         }
1816         else if (!strcmp(*argj, "--"))
1817         {
1818             eos_mark_found = 1;
1819             continue;
1820         }
1821
1822         if (0);
1823         else if (arg_match(&arg, &outputfile, argi))
1824             config->out_fn = arg.val;
1825         else if (arg_match(&arg, &fpf_name, argi))
1826             config->stats_fn = arg.val;
1827         else if (arg_match(&arg, &use_ivf, argi))
1828             config->write_webm = 0;
1829         else if (arg_match(&arg, &threads, argi))
1830             config->cfg.g_threads = arg_parse_uint(&arg);
1831         else if (arg_match(&arg, &profile, argi))
1832             config->cfg.g_profile = arg_parse_uint(&arg);
1833         else if (arg_match(&arg, &width, argi))
1834             config->cfg.g_w = arg_parse_uint(&arg);
1835         else if (arg_match(&arg, &height, argi))
1836             config->cfg.g_h = arg_parse_uint(&arg);
1837         else if (arg_match(&arg, &stereo_mode, argi))
1838             config->stereo_fmt = arg_parse_enum_or_int(&arg);
1839         else if (arg_match(&arg, &timebase, argi))
1840         {
1841             config->cfg.g_timebase = arg_parse_rational(&arg);
1842             validate_positive_rational(arg.name, &config->cfg.g_timebase);
1843         }
1844         else if (arg_match(&arg, &error_resilient, argi))
1845             config->cfg.g_error_resilient = arg_parse_uint(&arg);
1846         else if (arg_match(&arg, &lag_in_frames, argi))
1847             config->cfg.g_lag_in_frames = arg_parse_uint(&arg);
1848         else if (arg_match(&arg, &dropframe_thresh, argi))
1849             config->cfg.rc_dropframe_thresh = arg_parse_uint(&arg);
1850         else if (arg_match(&arg, &resize_allowed, argi))
1851             config->cfg.rc_resize_allowed = arg_parse_uint(&arg);
1852         else if (arg_match(&arg, &resize_up_thresh, argi))
1853             config->cfg.rc_resize_up_thresh = arg_parse_uint(&arg);
1854         else if (arg_match(&arg, &resize_down_thresh, argi))
1855             config->cfg.rc_resize_down_thresh = arg_parse_uint(&arg);
1856         else if (arg_match(&arg, &end_usage, argi))
1857             config->cfg.rc_end_usage = arg_parse_enum_or_int(&arg);
1858         else if (arg_match(&arg, &target_bitrate, argi))
1859             config->cfg.rc_target_bitrate = arg_parse_uint(&arg);
1860         else if (arg_match(&arg, &min_quantizer, argi))
1861             config->cfg.rc_min_quantizer = arg_parse_uint(&arg);
1862         else if (arg_match(&arg, &max_quantizer, argi))
1863             config->cfg.rc_max_quantizer = arg_parse_uint(&arg);
1864         else if (arg_match(&arg, &undershoot_pct, argi))
1865             config->cfg.rc_undershoot_pct = arg_parse_uint(&arg);
1866         else if (arg_match(&arg, &overshoot_pct, argi))
1867             config->cfg.rc_overshoot_pct = arg_parse_uint(&arg);
1868         else if (arg_match(&arg, &buf_sz, argi))
1869             config->cfg.rc_buf_sz = arg_parse_uint(&arg);
1870         else if (arg_match(&arg, &buf_initial_sz, argi))
1871             config->cfg.rc_buf_initial_sz = arg_parse_uint(&arg);
1872         else if (arg_match(&arg, &buf_optimal_sz, argi))
1873             config->cfg.rc_buf_optimal_sz = arg_parse_uint(&arg);
1874         else if (arg_match(&arg, &bias_pct, argi))
1875         {
1876             config->cfg.rc_2pass_vbr_bias_pct = arg_parse_uint(&arg);
1877
1878             if (global->passes < 2)
1879                 warn("option %s ignored in one-pass mode.\n", arg.name);
1880         }
1881         else if (arg_match(&arg, &minsection_pct, argi))
1882         {
1883             config->cfg.rc_2pass_vbr_minsection_pct = arg_parse_uint(&arg);
1884
1885             if (global->passes < 2)
1886                 warn("option %s ignored in one-pass mode.\n", arg.name);
1887         }
1888         else if (arg_match(&arg, &maxsection_pct, argi))
1889         {
1890             config->cfg.rc_2pass_vbr_maxsection_pct = arg_parse_uint(&arg);
1891
1892             if (global->passes < 2)
1893                 warn("option %s ignored in one-pass mode.\n", arg.name);
1894         }
1895         else if (arg_match(&arg, &kf_min_dist, argi))
1896             config->cfg.kf_min_dist = arg_parse_uint(&arg);
1897         else if (arg_match(&arg, &kf_max_dist, argi))
1898         {
1899             config->cfg.kf_max_dist = arg_parse_uint(&arg);
1900             config->have_kf_max_dist = 1;
1901         }
1902         else if (arg_match(&arg, &kf_disabled, argi))
1903             config->cfg.kf_mode = VPX_KF_DISABLED;
1904         else
1905         {
1906             int i, match = 0;
1907
1908             for (i = 0; ctrl_args[i]; i++)
1909             {
1910                 if (arg_match(&arg, ctrl_args[i], argi))
1911                 {
1912                     int j;
1913                     match = 1;
1914
1915                     /* Point either to the next free element or the first
1916                     * instance of this control.
1917                     */
1918                     for(j=0; j<config->arg_ctrl_cnt; j++)
1919                         if(config->arg_ctrls[j][0] == ctrl_args_map[i])
1920                             break;
1921
1922                     /* Update/insert */
1923                     assert(j < ARG_CTRL_CNT_MAX);
1924                     if (j < ARG_CTRL_CNT_MAX)
1925                     {
1926                         config->arg_ctrls[j][0] = ctrl_args_map[i];
1927                         config->arg_ctrls[j][1] = arg_parse_enum_or_int(&arg);
1928                         if(j == config->arg_ctrl_cnt)
1929                             config->arg_ctrl_cnt++;
1930                     }
1931
1932                 }
1933             }
1934
1935             if (!match)
1936                 argj++;
1937         }
1938     }
1939
1940     return eos_mark_found;
1941 }
1942
1943
1944 #define FOREACH_STREAM(func)\
1945 do\
1946 {\
1947     struct stream_state  *stream;\
1948 \
1949     for(stream = streams; stream; stream = stream->next)\
1950         func;\
1951 }while(0)
1952
1953
1954 static void validate_stream_config(struct stream_state *stream)
1955 {
1956     struct stream_state *streami;
1957
1958     if(!stream->config.cfg.g_w || !stream->config.cfg.g_h)
1959         fatal("Stream %d: Specify stream dimensions with --width (-w) "
1960               " and --height (-h)", stream->index);
1961
1962     for(streami = stream; streami; streami = streami->next)
1963     {
1964         /* All streams require output files */
1965         if(!streami->config.out_fn)
1966             fatal("Stream %d: Output file is required (specify with -o)",
1967                   streami->index);
1968
1969         /* Check for two streams outputting to the same file */
1970         if(streami != stream)
1971         {
1972             const char *a = stream->config.out_fn;
1973             const char *b = streami->config.out_fn;
1974             if(!strcmp(a,b) && strcmp(a, "/dev/null") && strcmp(a, ":nul"))
1975                 fatal("Stream %d: duplicate output file (from stream %d)",
1976                       streami->index, stream->index);
1977         }
1978
1979         /* Check for two streams sharing a stats file. */
1980         if(streami != stream)
1981         {
1982             const char *a = stream->config.stats_fn;
1983             const char *b = streami->config.stats_fn;
1984             if(a && b && !strcmp(a,b))
1985                 fatal("Stream %d: duplicate stats file (from stream %d)",
1986                       streami->index, stream->index);
1987         }
1988     }
1989 }
1990
1991
1992 static void set_stream_dimensions(struct stream_state *stream,
1993                                   unsigned int w,
1994                                   unsigned int h)
1995 {
1996     if ((stream->config.cfg.g_w && stream->config.cfg.g_w != w)
1997         ||(stream->config.cfg.g_h && stream->config.cfg.g_h != h))
1998         fatal("Stream %d: Resizing not yet supported", stream->index);
1999     stream->config.cfg.g_w = w;
2000     stream->config.cfg.g_h = h;
2001 }
2002
2003
2004 static void set_default_kf_interval(struct stream_state  *stream,
2005                                     struct global_config *global)
2006 {
2007     /* Use a max keyframe interval of 5 seconds, if none was
2008      * specified on the command line.
2009      */
2010     if (!stream->config.have_kf_max_dist)
2011     {
2012         double framerate = (double)global->framerate.num/global->framerate.den;
2013         if (framerate > 0.0)
2014             stream->config.cfg.kf_max_dist = 5.0*framerate;
2015     }
2016 }
2017
2018
2019 static void show_stream_config(struct stream_state  *stream,
2020                                struct global_config *global,
2021                                struct input_state   *input)
2022 {
2023
2024 #define SHOW(field) \
2025     fprintf(stderr, "    %-28s = %d\n", #field, stream->config.cfg.field)
2026
2027     if(stream->index == 0)
2028     {
2029         fprintf(stderr, "Codec: %s\n",
2030                 vpx_codec_iface_name(global->codec->iface));
2031         fprintf(stderr, "Source file: %s Format: %s\n", input->fn,
2032                 input->use_i420 ? "I420" : "YV12");
2033     }
2034     if(stream->next || stream->index)
2035         fprintf(stderr, "\nStream Index: %d\n", stream->index);
2036     fprintf(stderr, "Destination file: %s\n", stream->config.out_fn);
2037     fprintf(stderr, "Encoder parameters:\n");
2038
2039     SHOW(g_usage);
2040     SHOW(g_threads);
2041     SHOW(g_profile);
2042     SHOW(g_w);
2043     SHOW(g_h);
2044     SHOW(g_timebase.num);
2045     SHOW(g_timebase.den);
2046     SHOW(g_error_resilient);
2047     SHOW(g_pass);
2048     SHOW(g_lag_in_frames);
2049     SHOW(rc_dropframe_thresh);
2050     SHOW(rc_resize_allowed);
2051     SHOW(rc_resize_up_thresh);
2052     SHOW(rc_resize_down_thresh);
2053     SHOW(rc_end_usage);
2054     SHOW(rc_target_bitrate);
2055     SHOW(rc_min_quantizer);
2056     SHOW(rc_max_quantizer);
2057     SHOW(rc_undershoot_pct);
2058     SHOW(rc_overshoot_pct);
2059     SHOW(rc_buf_sz);
2060     SHOW(rc_buf_initial_sz);
2061     SHOW(rc_buf_optimal_sz);
2062     SHOW(rc_2pass_vbr_bias_pct);
2063     SHOW(rc_2pass_vbr_minsection_pct);
2064     SHOW(rc_2pass_vbr_maxsection_pct);
2065     SHOW(kf_mode);
2066     SHOW(kf_min_dist);
2067     SHOW(kf_max_dist);
2068 }
2069
2070
2071 static void open_output_file(struct stream_state *stream,
2072                              struct global_config *global)
2073 {
2074     const char *fn = stream->config.out_fn;
2075
2076     stream->file = strcmp(fn, "-") ? fopen(fn, "wb") : set_binary_mode(stdout);
2077
2078     if (!stream->file)
2079         fatal("Failed to open output file");
2080
2081     if(stream->config.write_webm && fseek(stream->file, 0, SEEK_CUR))
2082         fatal("WebM output to pipes not supported.");
2083
2084     if(stream->config.write_webm)
2085     {
2086         stream->ebml.stream = stream->file;
2087         write_webm_file_header(&stream->ebml, &stream->config.cfg,
2088                                &global->framerate,
2089                                stream->config.stereo_fmt);
2090     }
2091     else
2092         write_ivf_file_header(stream->file, &stream->config.cfg,
2093                               global->codec->fourcc, 0);
2094 }
2095
2096
2097 static void close_output_file(struct stream_state *stream,
2098                               unsigned int         fourcc)
2099 {
2100     if(stream->config.write_webm)
2101     {
2102         write_webm_file_footer(&stream->ebml, stream->hash);
2103         free(stream->ebml.cue_list);
2104         stream->ebml.cue_list = NULL;
2105     }
2106     else
2107     {
2108         if (!fseek(stream->file, 0, SEEK_SET))
2109             write_ivf_file_header(stream->file, &stream->config.cfg,
2110                                   fourcc,
2111                                   stream->frames_out);
2112     }
2113
2114     fclose(stream->file);
2115 }
2116
2117
2118 static void setup_pass(struct stream_state  *stream,
2119                        struct global_config *global,
2120                        int                   pass)
2121 {
2122     if (stream->config.stats_fn)
2123     {
2124         if (!stats_open_file(&stream->stats, stream->config.stats_fn,
2125                              pass))
2126             fatal("Failed to open statistics store");
2127     }
2128     else
2129     {
2130         if (!stats_open_mem(&stream->stats, pass))
2131             fatal("Failed to open statistics store");
2132     }
2133
2134     stream->config.cfg.g_pass = global->passes == 2
2135         ? pass ? VPX_RC_LAST_PASS : VPX_RC_FIRST_PASS
2136         : VPX_RC_ONE_PASS;
2137     if (pass)
2138         stream->config.cfg.rc_twopass_stats_in = stats_get(&stream->stats);
2139
2140     stream->cx_time = 0;
2141     stream->nbytes = 0;
2142     stream->frames_out = 0;
2143 }
2144
2145
2146 static void initialize_encoder(struct stream_state  *stream,
2147                                struct global_config *global)
2148 {
2149     int i;
2150     int flags = 0;
2151
2152     flags |= global->show_psnr ? VPX_CODEC_USE_PSNR : 0;
2153     flags |= global->out_part ? VPX_CODEC_USE_OUTPUT_PARTITION : 0;
2154
2155     /* Construct Encoder Context */
2156     vpx_codec_enc_init(&stream->encoder, global->codec->iface,
2157                         &stream->config.cfg, flags);
2158     ctx_exit_on_error(&stream->encoder, "Failed to initialize encoder");
2159
2160     /* Note that we bypass the vpx_codec_control wrapper macro because
2161      * we're being clever to store the control IDs in an array. Real
2162      * applications will want to make use of the enumerations directly
2163      */
2164     for (i = 0; i < stream->config.arg_ctrl_cnt; i++)
2165     {
2166         int ctrl = stream->config.arg_ctrls[i][0];
2167         int value = stream->config.arg_ctrls[i][1];
2168         if (vpx_codec_control_(&stream->encoder, ctrl, value))
2169             fprintf(stderr, "Error: Tried to set control %d = %d\n",
2170                     ctrl, value);
2171
2172         ctx_exit_on_error(&stream->encoder, "Failed to control codec");
2173     }
2174 }
2175
2176
2177 static void encode_frame(struct stream_state  *stream,
2178                          struct global_config *global,
2179                          struct vpx_image     *img,
2180                          unsigned int          frames_in)
2181 {
2182     vpx_codec_pts_t frame_start, next_frame_start;
2183     struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
2184     struct vpx_usec_timer timer;
2185
2186     frame_start = (cfg->g_timebase.den * (int64_t)(frames_in - 1)
2187                   * global->framerate.den)
2188                   / cfg->g_timebase.num / global->framerate.num;
2189     next_frame_start = (cfg->g_timebase.den * (int64_t)(frames_in)
2190                         * global->framerate.den)
2191                         / cfg->g_timebase.num / global->framerate.num;
2192     vpx_usec_timer_start(&timer);
2193     vpx_codec_encode(&stream->encoder, img, frame_start,
2194                      next_frame_start - frame_start,
2195                      0, global->deadline);
2196     vpx_usec_timer_mark(&timer);
2197     stream->cx_time += vpx_usec_timer_elapsed(&timer);
2198     ctx_exit_on_error(&stream->encoder, "Stream %d: Failed to encode frame",
2199                       stream->index);
2200 }
2201
2202
2203 static void update_quantizer_histogram(struct stream_state *stream)
2204 {
2205     if(stream->config.cfg.g_pass != VPX_RC_FIRST_PASS)
2206     {
2207         int q;
2208
2209         vpx_codec_control(&stream->encoder, VP8E_GET_LAST_QUANTIZER_64, &q);
2210         ctx_exit_on_error(&stream->encoder, "Failed to read quantizer");
2211         stream->counts[q]++;
2212     }
2213 }
2214
2215
2216 static void get_cx_data(struct stream_state  *stream,
2217                         struct global_config *global,
2218                         int                  *got_data)
2219 {
2220     const vpx_codec_cx_pkt_t *pkt;
2221     const struct vpx_codec_enc_cfg *cfg = &stream->config.cfg;
2222     vpx_codec_iter_t iter = NULL;
2223
2224     while ((pkt = vpx_codec_get_cx_data(&stream->encoder, &iter)))
2225     {
2226         static size_t fsize = 0;
2227         static off_t ivf_header_pos = 0;
2228
2229         *got_data = 1;
2230
2231         switch (pkt->kind)
2232         {
2233         case VPX_CODEC_CX_FRAME_PKT:
2234             if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
2235             {
2236                 stream->frames_out++;
2237             }
2238             fprintf(stderr, " %6luF",
2239                     (unsigned long)pkt->data.frame.sz);
2240
2241             update_rate_histogram(&stream->rate_hist, cfg, pkt);
2242             if(stream->config.write_webm)
2243             {
2244                 /* Update the hash */
2245                 if(!stream->ebml.debug)
2246                     stream->hash = murmur(pkt->data.frame.buf,
2247                                           pkt->data.frame.sz, stream->hash);
2248
2249                 write_webm_block(&stream->ebml, cfg, pkt);
2250             }
2251             else
2252             {
2253                 if (pkt->data.frame.partition_id <= 0)
2254                 {
2255                     ivf_header_pos = ftello(stream->file);
2256                     fsize = pkt->data.frame.sz;
2257
2258                     write_ivf_frame_header(stream->file, pkt);
2259                 }
2260                 else
2261                 {
2262                     fsize += pkt->data.frame.sz;
2263
2264                     if (!(pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT))
2265                     {
2266                         off_t currpos = ftello(stream->file);
2267                         fseeko(stream->file, ivf_header_pos, SEEK_SET);
2268                         write_ivf_frame_size(stream->file, fsize);
2269                         fseeko(stream->file, currpos, SEEK_SET);
2270                     }
2271                 }
2272
2273                 (void) fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
2274                               stream->file);
2275             }
2276             stream->nbytes += pkt->data.raw.sz;
2277             break;
2278         case VPX_CODEC_STATS_PKT:
2279             stream->frames_out++;
2280             fprintf(stderr, " %6luS",
2281                    (unsigned long)pkt->data.twopass_stats.sz);
2282             stats_write(&stream->stats,
2283                         pkt->data.twopass_stats.buf,
2284                         pkt->data.twopass_stats.sz);
2285             stream->nbytes += pkt->data.raw.sz;
2286             break;
2287         case VPX_CODEC_PSNR_PKT:
2288
2289             if (global->show_psnr)
2290             {
2291                 int i;
2292
2293                 stream->psnr_sse_total += pkt->data.psnr.sse[0];
2294                 stream->psnr_samples_total += pkt->data.psnr.samples[0];
2295                 for (i = 0; i < 4; i++)
2296                 {
2297                     fprintf(stderr, "%.3f ", pkt->data.psnr.psnr[i]);
2298                     stream->psnr_totals[i] += pkt->data.psnr.psnr[i];
2299                 }
2300                 stream->psnr_count++;
2301             }
2302
2303             break;
2304         default:
2305             break;
2306         }
2307     }
2308 }
2309
2310
2311 static void show_psnr(struct stream_state  *stream)
2312 {
2313     int i;
2314     double ovpsnr;
2315
2316     if (!stream->psnr_count)
2317         return;
2318
2319     fprintf(stderr, "Stream %d PSNR (Overall/Avg/Y/U/V)", stream->index);
2320     ovpsnr = vp8_mse2psnr(stream->psnr_samples_total, 255.0,
2321                           stream->psnr_sse_total);
2322     fprintf(stderr, " %.3f", ovpsnr);
2323
2324     for (i = 0; i < 4; i++)
2325     {
2326         fprintf(stderr, " %.3f", stream->psnr_totals[i]/stream->psnr_count);
2327     }
2328     fprintf(stderr, "\n");
2329 }
2330
2331
2332 float usec_to_fps(uint64_t usec, unsigned int frames)
2333 {
2334     return usec > 0 ? (float)frames * 1000000.0 / (float)usec : 0;
2335 }
2336
2337
2338 int main(int argc, const char **argv_)
2339 {
2340     int                    pass;
2341     vpx_image_t            raw;
2342     int                    frame_avail, got_data;
2343
2344     struct input_state       input = {0};
2345     struct global_config     global;
2346     struct stream_state     *streams = NULL;
2347     char                   **argv, **argi;
2348     unsigned long            cx_time = 0;
2349     int                      stream_cnt = 0;
2350
2351     exec_name = argv_[0];
2352
2353     if (argc < 3)
2354         usage_exit();
2355
2356     /* Setup default input stream settings */
2357     input.framerate.num = 30;
2358     input.framerate.den = 1;
2359     input.use_i420 = 1;
2360
2361     /* First parse the global configuration values, because we want to apply
2362      * other parameters on top of the default configuration provided by the
2363      * codec.
2364      */
2365     argv = argv_dup(argc - 1, argv_ + 1);
2366     parse_global_config(&global, argv);
2367
2368     {
2369         /* Now parse each stream's parameters. Using a local scope here
2370          * due to the use of 'stream' as loop variable in FOREACH_STREAM
2371          * loops
2372          */
2373         struct stream_state *stream = NULL;
2374
2375         do
2376         {
2377             stream = new_stream(&global, stream);
2378             stream_cnt++;
2379             if(!streams)
2380                 streams = stream;
2381         } while(parse_stream_params(&global, stream, argv));
2382     }
2383
2384     /* Check for unrecognized options */
2385     for (argi = argv; *argi; argi++)
2386         if (argi[0][0] == '-' && argi[0][1])
2387             die("Error: Unrecognized option %s\n", *argi);
2388
2389     /* Handle non-option arguments */
2390     input.fn = argv[0];
2391
2392     if (!input.fn)
2393         usage_exit();
2394
2395     for (pass = global.pass ? global.pass - 1 : 0; pass < global.passes; pass++)
2396     {
2397         int frames_in = 0;
2398
2399         open_input_file(&input);
2400
2401         /* If the input file doesn't specify its w/h (raw files), try to get
2402          * the data from the first stream's configuration.
2403          */
2404         if(!input.w || !input.h)
2405             FOREACH_STREAM({
2406                 if(stream->config.cfg.g_w && stream->config.cfg.g_h)
2407                 {
2408                     input.w = stream->config.cfg.g_w;
2409                     input.h = stream->config.cfg.g_h;
2410                     break;
2411                 }
2412             });
2413
2414         /* Update stream configurations from the input file's parameters */
2415         FOREACH_STREAM(set_stream_dimensions(stream, input.w, input.h));
2416         FOREACH_STREAM(validate_stream_config(stream));
2417
2418         /* Ensure that --passes and --pass are consistent. If --pass is set and
2419          * --passes=2, ensure --fpf was set.
2420          */
2421         if (global.pass && global.passes == 2)
2422             FOREACH_STREAM({
2423                 if(!stream->config.stats_fn)
2424                     die("Stream %d: Must specify --fpf when --pass=%d"
2425                         " and --passes=2\n", stream->index, global.pass);
2426             });
2427
2428
2429         /* Use the frame rate from the file only if none was specified
2430          * on the command-line.
2431          */
2432         if (!global.have_framerate)
2433             global.framerate = input.framerate;
2434
2435         FOREACH_STREAM(set_default_kf_interval(stream, &global));
2436
2437         /* Show configuration */
2438         if (global.verbose && pass == 0)
2439             FOREACH_STREAM(show_stream_config(stream, &global, &input));
2440
2441         if(pass == (global.pass ? global.pass - 1 : 0)) {
2442             if (input.file_type == FILE_TYPE_Y4M)
2443                 /*The Y4M reader does its own allocation.
2444                   Just initialize this here to avoid problems if we never read any
2445                    frames.*/
2446                 memset(&raw, 0, sizeof(raw));
2447             else
2448                 vpx_img_alloc(&raw,
2449                               input.use_i420 ? VPX_IMG_FMT_I420
2450                                              : VPX_IMG_FMT_YV12,
2451                               input.w, input.h, 32);
2452
2453             FOREACH_STREAM(init_rate_histogram(&stream->rate_hist,
2454                                                &stream->config.cfg,
2455                                                &global.framerate));
2456         }
2457
2458         FOREACH_STREAM(open_output_file(stream, &global));
2459         FOREACH_STREAM(setup_pass(stream, &global, pass));
2460         FOREACH_STREAM(initialize_encoder(stream, &global));
2461
2462         frame_avail = 1;
2463         got_data = 0;
2464
2465         while (frame_avail || got_data)
2466         {
2467             struct vpx_usec_timer timer;
2468
2469             if (!global.limit || frames_in < global.limit)
2470             {
2471                 frame_avail = read_frame(&input, &raw);
2472
2473                 if (frame_avail)
2474                     frames_in++;
2475
2476                 if(stream_cnt == 1)
2477                     fprintf(stderr,
2478                             "\rPass %d/%d frame %4d/%-4d %7"PRId64"B \033[K",
2479                             pass + 1, global.passes, frames_in,
2480                             streams->frames_out, (int64_t)streams->nbytes);
2481                 else
2482                     fprintf(stderr,
2483                             "\rPass %d/%d frame %4d %7lu %s (%.2f fps)\033[K",
2484                             pass + 1, global.passes, frames_in,
2485                             cx_time > 9999999 ? cx_time / 1000 : cx_time,
2486                             cx_time > 9999999 ? "ms" : "us",
2487                             usec_to_fps(cx_time, frames_in));
2488
2489             }
2490             else
2491                 frame_avail = 0;
2492
2493             vpx_usec_timer_start(&timer);
2494             FOREACH_STREAM(encode_frame(stream, &global,
2495                                         frame_avail ? &raw : NULL,
2496                                         frames_in));
2497             vpx_usec_timer_mark(&timer);
2498             cx_time += vpx_usec_timer_elapsed(&timer);
2499
2500             FOREACH_STREAM(update_quantizer_histogram(stream));
2501
2502             got_data = 0;
2503             FOREACH_STREAM(get_cx_data(stream, &global, &got_data));
2504
2505             fflush(stdout);
2506         }
2507
2508         if(stream_cnt > 1)
2509             fprintf(stderr, "\n");
2510
2511         FOREACH_STREAM(fprintf(
2512             stderr,
2513             "\rPass %d/%d frame %4d/%-4d %7"PRId64"B %7lub/f %7"PRId64"b/s"
2514             " %7"PRId64" %s (%.2f fps)\033[K\n", pass + 1,
2515             global.passes, frames_in, stream->frames_out, (int64_t)stream->nbytes,
2516             frames_in ? (unsigned long)(stream->nbytes * 8 / frames_in) : 0,
2517             frames_in ? (int64_t)stream->nbytes * 8
2518                         * (int64_t)global.framerate.num / global.framerate.den
2519                         / frames_in
2520                       : 0,
2521             stream->cx_time > 9999999 ? stream->cx_time / 1000 : stream->cx_time,
2522             stream->cx_time > 9999999 ? "ms" : "us",
2523             usec_to_fps(stream->cx_time, frames_in));
2524         );
2525
2526         if (global.show_psnr)
2527             FOREACH_STREAM(show_psnr(stream));
2528
2529         FOREACH_STREAM(vpx_codec_destroy(&stream->encoder));
2530
2531         close_input_file(&input);
2532
2533         FOREACH_STREAM(close_output_file(stream, global.codec->fourcc));
2534
2535         FOREACH_STREAM(stats_close(&stream->stats, global.passes-1));
2536
2537         if (global.pass)
2538             break;
2539     }
2540
2541     if (global.show_q_hist_buckets)
2542         FOREACH_STREAM(show_q_histogram(stream->counts,
2543                                         global.show_q_hist_buckets));
2544
2545     if (global.show_rate_hist_buckets)
2546         FOREACH_STREAM(show_rate_histogram(&stream->rate_hist,
2547                                            &stream->config.cfg,
2548                                            global.show_rate_hist_buckets));
2549     FOREACH_STREAM(destroy_rate_histogram(&stream->rate_hist));
2550
2551     vpx_img_free(&raw);
2552     free(argv);
2553     free(streams);
2554     return EXIT_SUCCESS;
2555 }