c88839ead9df458a39ce2d0b29450bd9dc8699b8
[theora.git] / examples / encoder_example.c
1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2009                *
9  * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
10  *                                                                  *
11  ********************************************************************
12
13   function: example encoder application; makes an Ogg Theora/Vorbis
14             file from YUV4MPEG2 and WAV input
15   last mod: $Id$
16
17  ********************************************************************/
18
19 #if !defined(_REENTRANT)
20 #define _REENTRANT
21 #endif
22 #if !defined(_GNU_SOURCE)
23 #define _GNU_SOURCE
24 #endif
25 #if !defined(_LARGEFILE_SOURCE)
26 #define _LARGEFILE_SOURCE
27 #endif
28 #if !defined(_LARGEFILE64_SOURCE)
29 #define _LARGEFILE64_SOURCE
30 #endif
31 #if !defined(_FILE_OFFSET_BITS)
32 #define _FILE_OFFSET_BITS 64
33 #endif
34
35 #include <stdio.h>
36 #if !defined(_WIN32)
37 #include <getopt.h>
38 #include <unistd.h>
39 #else
40 #include "getopt.h"
41 #endif
42 #include <stdlib.h>
43 #include <string.h>
44 #include <time.h>
45 #include <math.h>
46 #include "theora/theoraenc.h"
47 #include "vorbis/codec.h"
48 #include "vorbis/vorbisenc.h"
49
50 #ifdef _WIN32
51 /*supply missing headers and functions to Win32. going to hell, I know*/
52 #include <fcntl.h>
53 #include <io.h>
54
55 static double rint(double x)
56 {
57   if (x < 0.0)
58     return (double)(int)(x - 0.5);
59   else
60     return (double)(int)(x + 0.5);
61 }
62 #endif
63
64 const char *optstring = "b:e:o:a:A:v:V:s:S:f:F:ck:d:z:\1\2\3\4";
65 struct option options [] = {
66   {"begin-time",required_argument,NULL,'b'},
67   {"end-time",required_argument,NULL,'e'},
68   {"output",required_argument,NULL,'o'},
69   {"audio-rate-target",required_argument,NULL,'A'},
70   {"video-rate-target",required_argument,NULL,'V'},
71   {"audio-quality",required_argument,NULL,'a'},
72   {"video-quality",required_argument,NULL,'v'},
73   {"aspect-numerator",required_argument,NULL,'s'},
74   {"aspect-denominator",required_argument,NULL,'S'},
75   {"framerate-numerator",required_argument,NULL,'f'},
76   {"framerate-denominator",required_argument,NULL,'F'},
77   {"vp3-compatible",no_argument,NULL,'c'},
78   {"speed",required_argument,NULL,'z'},
79   {"soft-target",no_argument,NULL,'\1'},
80   {"keyframe-freq",required_argument,NULL,'k'},
81   {"buf-delay",required_argument,NULL,'d'},
82   {"two-pass",no_argument,NULL,'\2'},
83   {"first-pass",required_argument,NULL,'\3'},
84   {"second-pass",required_argument,NULL,'\4'},
85   {NULL,0,NULL,0}
86 };
87
88 /* You'll go to Hell for using globals. */
89
90 FILE *audio=NULL;
91 FILE *video=NULL;
92
93 int audio_ch=0;
94 int audio_hz=0;
95
96 float audio_q=.1f;
97 int audio_r=-1;
98 int vp3_compatible=0;
99
100 int frame_w=0;
101 int frame_h=0;
102 int pic_w=0;
103 int pic_h=0;
104 int pic_x=0;
105 int pic_y=0;
106 int video_fps_n=-1;
107 int video_fps_d=-1;
108 int video_par_n=-1;
109 int video_par_d=-1;
110 char interlace;
111 int src_c_dec_h=2;
112 int src_c_dec_v=2;
113 int dst_c_dec_h=2;
114 int dst_c_dec_v=2;
115 char chroma_type[16];
116
117 /*The size of each converted frame buffer.*/
118 size_t y4m_dst_buf_sz;
119 /*The amount to read directly into the converted frame buffer.*/
120 size_t y4m_dst_buf_read_sz;
121 /*The size of the auxilliary buffer.*/
122 size_t y4m_aux_buf_sz;
123 /*The amount to read into the auxilliary buffer.*/
124 size_t y4m_aux_buf_read_sz;
125
126 /*The function used to perform chroma conversion.*/
127 typedef void (*y4m_convert_func)(unsigned char *_dst,unsigned char *_aux);
128
129 y4m_convert_func y4m_convert=NULL;
130
131 int video_r=-1;
132 int video_q=-1;
133 ogg_uint32_t keyframe_frequency=0;
134 int buf_delay=-1;
135
136 long begin_sec=-1;
137 long begin_usec=0;
138 long end_sec=-1;
139 long end_usec=0;
140
141 static void usage(void){
142   fprintf(stderr,
143           "Usage: encoder_example [options] [audio_file] video_file\n\n"
144           "Options: \n\n"
145           "  -o --output <filename.ogv>      file name for encoded output;\n"
146           "                                  If this option is not given, the\n"
147           "                                  compressed data is sent to stdout.\n\n"
148           "  -A --audio-rate-target <n>      bitrate target for Vorbis audio;\n"
149           "                                  use -a and not -A if at all possible,\n"
150           "                                  as -a gives higher quality for a given\n"
151           "                                  bitrate.\n\n"
152           "  -V --video-rate-target <n>      bitrate target for Theora video\n\n"
153           "     --soft-target                Use a large reservoir and treat the rate\n"
154           "                                  as a soft target; rate control is less\n"
155           "                                  strict but resulting quality is usually\n"
156           "                                  higher/smoother overall. Soft target also\n"
157           "                                  allows an optional -v setting to specify\n"
158           "                                  a minimum allowed quality.\n\n"
159           "     --two-pass                   Compress input using two-pass rate control\n"
160           "                                  This option requires that the input to the\n"
161           "                                  to the encoder is seekable and performs\n"
162           "                                  both passes automatically.\n\n"
163           "     --first-pass <filename>      Perform first-pass of a two-pass rate\n"
164           "                                  controlled encoding, saving pass data to\n"
165           "                                  <filename> for a later second pass\n\n"
166           "     --second-pass <filename>     Perform second-pass of a two-pass rate\n"
167           "                                  controlled encoding, reading first-pass\n"
168           "                                  data from <filename>.  The first pass\n"
169           "                                  data must come from a first encoding pass\n"
170           "                                  using identical input video to work\n"
171           "                                  properly.\n\n"
172           "  -a --audio-quality <n>          Vorbis quality selector from -1 to 10\n"
173           "                                  (-1 yields smallest files but lowest\n"
174           "                                  fidelity; 10 yields highest fidelity\n"
175           "                                  but large files. '2' is a reasonable\n"
176           "                                  default).\n\n"
177           "   -v --video-quality <n>         Theora quality selector from 0 to 10\n"
178           "                                  (0 yields smallest files but lowest\n"
179           "                                  video quality. 10 yields highest\n"
180           "                                  fidelity but large files).\n\n"
181           "   -s --aspect-numerator <n>      Aspect ratio numerator, default is 0\n"
182           "                                  or extracted from YUV input file\n"
183           "   -S --aspect-denominator <n>    Aspect ratio denominator, default is 0\n"
184           "                                  or extracted from YUV input file\n"
185           "   -f --framerate-numerator <n>   Frame rate numerator, can be extracted\n"
186           "                                  from YUV input file. ex: 30000000\n"
187           "   -F --framerate-denominator <n> Frame rate denominator, can be extracted\n"
188           "                                  from YUV input file. ex: 1000000\n"
189           "                                  The frame rate nominator divided by this\n"
190           "                                  determinates the frame rate in units per tick\n"
191           "   -k --keyframe-freq <n>         Keyframe frequency\n"
192           "   -z --speed <n>                 Sets the encoder speed level. Higher speed\n"
193           "                                  levels favor quicker encoding over better\n"
194           "                                  quality per bit. Depending on the encoding\n"
195           "                                  mode, and the internal algorithms used,\n"
196           "                                  quality may actually improve with higher\n"
197           "                                  speeds, but in this case bitrate will also\n"
198           "                                  likely increase. The maximum value, and the\n"
199           "                                  meaning of each value, are implementation-\n"
200           "                                  specific and may change depending on the\n"
201           "                                  current encoding mode (rate constrained,\n"
202           "                                  two-pass, etc.).\n"
203           "   -d --buf-delay <n>             Buffer delay (in frames). Longer delays\n"
204           "                                  allow smoother rate adaptation and provide\n"
205           "                                  better overall quality, but require more\n"
206           "                                  client side buffering and add latency. The\n"
207           "                                  default value is the keyframe interval for\n"
208           "                                  one-pass encoding (or somewhat larger if\n"
209           "                                  --soft-target is used) and infinite for\n"
210           "                                  two-pass encoding.\n"
211           "   -b --begin-time <h:m:s.d>      Begin encoding at offset into input\n"
212           "   -e --end-time <h:m:s.d>        End encoding at offset into input\n"
213           "encoder_example accepts only uncompressed RIFF WAV format audio and\n"
214           "YUV4MPEG2 uncompressed video.\n\n");
215   exit(1);
216 }
217
218 static int y4m_parse_tags(char *_tags){
219   int   got_w;
220   int   got_h;
221   int   got_fps;
222   int   got_interlace;
223   int   got_par;
224   int   got_chroma;
225   int   tmp_video_fps_n;
226   int   tmp_video_fps_d;
227   int   tmp_video_par_n;
228   int   tmp_video_par_d;
229   char *p;
230   char *q;
231   got_w=got_h=got_fps=got_interlace=got_par=got_chroma=0;
232   for(p=_tags;;p=q){
233     /*Skip any leading spaces.*/
234     while(*p==' ')p++;
235     /*If that's all we have, stop.*/
236     if(p[0]=='\0')break;
237     /*Find the end of this tag.*/
238     for(q=p+1;*q!='\0'&&*q!=' ';q++);
239     /*Process the tag.*/
240     switch(p[0]){
241       case 'W':{
242         if(sscanf(p+1,"%d",&pic_w)!=1)return -1;
243         got_w=1;
244       }break;
245       case 'H':{
246         if(sscanf(p+1,"%d",&pic_h)!=1)return -1;
247         got_h=1;
248       }break;
249       case 'F':{
250         if(sscanf(p+1,"%d:%d",&tmp_video_fps_n,&tmp_video_fps_d)!=2)return -1;
251         got_fps=1;
252       }break;
253       case 'I':{
254         interlace=p[1];
255         got_interlace=1;
256       }break;
257       case 'A':{
258         if(sscanf(p+1,"%d:%d",&tmp_video_par_n,&tmp_video_par_d)!=2)return -1;
259         got_par=1;
260       }break;
261       case 'C':{
262         if(q-p>16)return -1;
263         memcpy(chroma_type,p+1,q-p-1);
264         chroma_type[q-p-1]='\0';
265         got_chroma=1;
266       }break;
267       /*Ignore unknown tags.*/
268     }
269   }
270   if(!got_w||!got_h||!got_fps||!got_interlace||!got_par)return -1;
271   /*Chroma-type is not specified in older files, e.g., those generated by
272      mplayer.*/
273   if(!got_chroma)strcpy(chroma_type,"420");
274   /*Update fps and aspect ratio globals if not specified in the command line.*/
275   if(video_fps_n==-1)video_fps_n=tmp_video_fps_n;
276   if(video_fps_d==-1)video_fps_d=tmp_video_fps_d;
277   if(video_par_n==-1)video_par_n=tmp_video_par_n;
278   if(video_par_d==-1)video_par_d=tmp_video_par_d;
279   return 0;
280 }
281
282 /*All anti-aliasing filters in the following conversion functions are based on
283    one of two window functions:
284   The 6-tap Lanczos window (for down-sampling and shifts):
285    sinc(\pi*t)*sinc(\pi*t/3), |t|<3  (sinc(t)==sin(t)/t)
286    0,                         |t|>=3
287   The 4-tap Mitchell window (for up-sampling):
288    7|t|^3-12|t|^2+16/3,             |t|<1
289    -(7/3)|x|^3+12|x|^2-20|x|+32/3,  |t|<2
290    0,                               |t|>=2
291   The number of taps is intentionally kept small to reduce computational
292    overhead and limit ringing.
293
294   The taps from these filters are scaled so that their sum is 1, and the result
295    is scaled by 128 and rounded to integers to create a filter whose
296    intermediate values fit inside 16 bits.
297   Coefficients are rounded in such a way as to ensure their sum is still 128,
298    which is usually equivalent to normal rounding.*/
299
300 #define OC_MINI(_a,_b)      ((_a)>(_b)?(_b):(_a))
301 #define OC_MAXI(_a,_b)      ((_a)<(_b)?(_b):(_a))
302 #define OC_CLAMPI(_a,_b,_c) (OC_MAXI(_a,OC_MINI(_b,_c)))
303
304 /*420jpeg chroma samples are sited like:
305   Y-------Y-------Y-------Y-------
306   |       |       |       |
307   |   BR  |       |   BR  |
308   |       |       |       |
309   Y-------Y-------Y-------Y-------
310   |       |       |       |
311   |       |       |       |
312   |       |       |       |
313   Y-------Y-------Y-------Y-------
314   |       |       |       |
315   |   BR  |       |   BR  |
316   |       |       |       |
317   Y-------Y-------Y-------Y-------
318   |       |       |       |
319   |       |       |       |
320   |       |       |       |
321
322   420mpeg2 chroma samples are sited like:
323   Y-------Y-------Y-------Y-------
324   |       |       |       |
325   BR      |       BR      |
326   |       |       |       |
327   Y-------Y-------Y-------Y-------
328   |       |       |       |
329   |       |       |       |
330   |       |       |       |
331   Y-------Y-------Y-------Y-------
332   |       |       |       |
333   BR      |       BR      |
334   |       |       |       |
335   Y-------Y-------Y-------Y-------
336   |       |       |       |
337   |       |       |       |
338   |       |       |       |
339
340   We use a resampling filter to shift the site locations one quarter pixel (at
341    the chroma plane's resolution) to the right.
342   The 4:2:2 modes look exactly the same, except there are twice as many chroma
343    lines, and they are vertically co-sited with the luma samples in both the
344    mpeg2 and jpeg cases (thus requiring no vertical resampling).*/
345 static void y4m_convert_42xmpeg2_42xjpeg(unsigned char *_dst,
346  unsigned char *_aux){
347   int c_w;
348   int c_h;
349   int pli;
350   int y;
351   int x;
352   /*Skip past the luma data.*/
353   _dst+=pic_w*pic_h;
354   /*Compute the size of each chroma plane.*/
355   c_w=(pic_w+dst_c_dec_h-1)/dst_c_dec_h;
356   c_h=(pic_h+dst_c_dec_v-1)/dst_c_dec_v;
357   for(pli=1;pli<3;pli++){
358     for(y=0;y<c_h;y++){
359       /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
360          window.*/
361       for(x=0;x<OC_MINI(c_w,2);x++){
362         _dst[x]=(unsigned char)OC_CLAMPI(0,4*_aux[0]-17*_aux[OC_MAXI(x-1,0)]+
363          114*_aux[x]+35*_aux[OC_MINI(x+1,c_w-1)]-9*_aux[OC_MINI(x+2,c_w-1)]+
364          _aux[OC_MINI(x+3,c_w-1)]+64>>7,255);
365       }
366       for(;x<c_w-3;x++){
367         _dst[x]=(unsigned char)OC_CLAMPI(0,4*_aux[x-2]-17*_aux[x-1]+
368          114*_aux[x]+35*_aux[x+1]-9*_aux[x+2]+_aux[x+3]+64>>7,255);
369       }
370       for(;x<c_w;x++){
371         _dst[x]=(unsigned char)OC_CLAMPI(0,4*_aux[x-2]-17*_aux[x-1]+
372          114*_aux[x]+35*_aux[OC_MINI(x+1,c_w-1)]-9*_aux[OC_MINI(x+2,c_w-1)]+
373          _aux[c_w-1]+64>>7,255);
374       }
375       _dst+=c_w;
376       _aux+=c_w;
377     }
378   }
379 }
380
381 /*This format is only used for interlaced content, but is included for
382    completeness.
383
384   420jpeg chroma samples are sited like:
385   Y-------Y-------Y-------Y-------
386   |       |       |       |
387   |   BR  |       |   BR  |
388   |       |       |       |
389   Y-------Y-------Y-------Y-------
390   |       |       |       |
391   |       |       |       |
392   |       |       |       |
393   Y-------Y-------Y-------Y-------
394   |       |       |       |
395   |   BR  |       |   BR  |
396   |       |       |       |
397   Y-------Y-------Y-------Y-------
398   |       |       |       |
399   |       |       |       |
400   |       |       |       |
401
402   420paldv chroma samples are sited like:
403   YR------Y-------YR------Y-------
404   |       |       |       |
405   |       |       |       |
406   |       |       |       |
407   YB------Y-------YB------Y-------
408   |       |       |       |
409   |       |       |       |
410   |       |       |       |
411   YR------Y-------YR------Y-------
412   |       |       |       |
413   |       |       |       |
414   |       |       |       |
415   YB------Y-------YB------Y-------
416   |       |       |       |
417   |       |       |       |
418   |       |       |       |
419
420   We use a resampling filter to shift the site locations one quarter pixel (at
421    the chroma plane's resolution) to the right.
422   Then we use another filter to move the C_r location down one quarter pixel,
423    and the C_b location up one quarter pixel.*/
424 static void y4m_convert_42xpaldv_42xjpeg(unsigned char *_dst,
425  unsigned char *_aux){
426   unsigned char *tmp;
427   int            c_w;
428   int            c_h;
429   int            c_sz;
430   int            pli;
431   int            y;
432   int            x;
433   /*Skip past the luma data.*/
434   _dst+=pic_w*pic_h;
435   /*Compute the size of each chroma plane.*/
436   c_w=(pic_w+1)/2;
437   c_h=(pic_h+dst_c_dec_h-1)/dst_c_dec_h;
438   c_sz=c_w*c_h;
439   /*First do the horizontal re-sampling.
440     This is the same as the mpeg2 case, except that after the horizontal case,
441      we need to apply a second vertical filter.*/
442   tmp=_aux+2*c_sz;
443   for(pli=1;pli<3;pli++){
444     for(y=0;y<c_h;y++){
445       /*Filter: [4 -17 114 35 -9 1]/128, derived from a 6-tap Lanczos
446          window.*/
447       for(x=0;x<OC_MINI(c_w,2);x++){
448         tmp[x]=(unsigned char)OC_CLAMPI(0,4*_aux[0]-17*_aux[OC_MAXI(x-1,0)]+
449          114*_aux[x]+35*_aux[OC_MINI(x+1,c_w-1)]-9*_aux[OC_MINI(x+2,c_w-1)]+
450          _aux[OC_MINI(x+3,c_w-1)]+64>>7,255);
451       }
452       for(;x<c_w-3;x++){
453         tmp[x]=(unsigned char)OC_CLAMPI(0,4*_aux[x-2]-17*_aux[x-1]+
454          114*_aux[x]+35*_aux[x+1]-9*_aux[x+2]+_aux[x+3]+64>>7,255);
455       }
456       for(;x<c_w;x++){
457         tmp[x]=(unsigned char)OC_CLAMPI(0,4*_aux[x-2]-17*_aux[x-1]+
458          114*_aux[x]+35*_aux[OC_MINI(x+1,c_w-1)]-9*_aux[OC_MINI(x+2,c_w-1)]+
459          _aux[c_w-1]+64>>7,255);
460       }
461       tmp+=c_w;
462       _aux+=c_w;
463     }
464     switch(pli){
465       case 1:{
466         tmp-=c_sz;
467         /*Slide C_b up a quarter-pel.
468           This is the same filter used above, but in the other order.*/
469         for(x=0;x<c_w;x++){
470           for(y=0;y<OC_MINI(c_h,3);y++){
471             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,tmp[0]-
472              9*tmp[OC_MAXI(y-2,0)*c_w]+35*tmp[OC_MAXI(y-1,0)*c_w]+
473              114*tmp[y*c_w]-17*tmp[OC_MINI(y+1,c_h-1)*c_w]+
474              4*tmp[OC_MINI(y+2,c_h-1)*c_w]+64>>7,255);
475           }
476           for(;y<c_h-2;y++){
477             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,tmp[(y-3)*c_w]-
478              9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]-
479              17*tmp[(y+1)*c_w]+4*tmp[(y+2)*c_w]+64>>7,255);
480           }
481           for(;y<c_h;y++){
482             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,tmp[(y-3)*c_w]-
483              9*tmp[(y-2)*c_w]+35*tmp[(y-1)*c_w]+114*tmp[y*c_w]-
484              17*tmp[OC_MINI(y+1,c_h-1)*c_w]+4*tmp[(c_h-1)*c_w]+64>>7,255);
485           }
486           _dst++;
487           tmp++;
488         }
489         _dst+=c_sz-c_w;
490         tmp-=c_w;
491       }break;
492       case 2:{
493         tmp-=c_sz;
494         /*Slide C_r down a quarter-pel.
495           This is the same as the horizontal filter.*/
496         for(x=0;x<c_w;x++){
497           for(y=0;y<OC_MINI(c_h,2);y++){
498             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,4*tmp[0]-
499              17*tmp[OC_MAXI(y-1,0)*c_w]+114*tmp[y*c_w]+
500              35*tmp[OC_MINI(y+1,c_h-1)*c_w]-9*tmp[OC_MINI(y+2,c_h-1)*c_w]+
501              tmp[OC_MINI(y+3,c_h-1)*c_w]+64>>7,255);
502           }
503           for(;y<c_h-3;y++){
504             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,4*tmp[(y-2)*c_w]-
505              17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[(y+1)*c_w]-
506              9*tmp[(y+2)*c_w]+tmp[(y+3)*c_w]+64>>7,255);
507           }
508           for(;y<c_h;y++){
509             _dst[y*c_w]=(unsigned char)OC_CLAMPI(0,4*tmp[(y-2)*c_w]-
510              17*tmp[(y-1)*c_w]+114*tmp[y*c_w]+35*tmp[OC_MINI(y+1,c_h-1)*c_w]-
511              9*tmp[OC_MINI(y+2,c_h-1)*c_w]+tmp[(c_h-1)*c_w]+64>>7,255);
512           }
513           _dst++;
514           tmp++;
515         }
516       }break;
517     }
518     /*For actual interlaced material, this would have to be done separately on
519        each field, and the shift amounts would be different.
520       C_r moves down 1/8, C_b up 3/8 in the top field, and C_r moves down 3/8,
521        C_b up 1/8 in the bottom field.
522       The corresponding filters would be:
523        Down 1/8 (reverse order for up): [3 -11 125 15 -4 0]/128
524        Down 3/8 (reverse order for up): [4 -19 98 56 -13 2]/128*/
525   }
526 }
527
528 /*422jpeg chroma samples are sited like:
529   Y---BR--Y-------Y---BR--Y-------
530   |       |       |       |
531   |       |       |       |
532   |       |       |       |
533   Y---BR--Y-------Y---BR--Y-------
534   |       |       |       |
535   |       |       |       |
536   |       |       |       |
537   Y---BR--Y-------Y---BR--Y-------
538   |       |       |       |
539   |       |       |       |
540   |       |       |       |
541   Y---BR--Y-------Y---BR--Y-------
542   |       |       |       |
543   |       |       |       |
544   |       |       |       |
545
546   411 chroma samples are sited like:
547   YBR-----Y-------Y-------Y-------
548   |       |       |       |
549   |       |       |       |
550   |       |       |       |
551   YBR-----Y-------Y-------Y-------
552   |       |       |       |
553   |       |       |       |
554   |       |       |       |
555   YBR-----Y-------Y-------Y-------
556   |       |       |       |
557   |       |       |       |
558   |       |       |       |
559   YBR-----Y-------Y-------Y-------
560   |       |       |       |
561   |       |       |       |
562   |       |       |       |
563
564   We use a filter to resample at site locations one eighth pixel (at the source
565    chroma plane's horizontal resolution) and five eighths of a pixel to the
566    right.*/
567 static void y4m_convert_411_422jpeg(unsigned char *_dst,
568  unsigned char *_aux){
569   int c_w;
570   int dst_c_w;
571   int c_h;
572   int pli;
573   int y;
574   int x;
575   /*Skip past the luma data.*/
576   _dst+=pic_w*pic_h;
577   /*Compute the size of each chroma plane.*/
578   c_w=(pic_w+src_c_dec_h-1)/src_c_dec_h;
579   dst_c_w=(pic_w+dst_c_dec_h-1)/dst_c_dec_h;
580   c_h=(pic_h+dst_c_dec_v-1)/dst_c_dec_v;
581   for(pli=1;pli<3;pli++){
582     for(y=0;y<c_h;y++){
583       /*Filters: [1 110 18 -1]/128 and [-3 50 86 -5]/128, both derived from a
584          4-tap Mitchell window.*/
585       for(x=0;x<OC_MINI(c_w,1);x++){
586         _dst[x<<1]=(unsigned char)OC_CLAMPI(0,111*_aux[0]+
587          18*_aux[OC_MINI(1,c_w-1)]-_aux[OC_MINI(2,c_w-1)]+64>>7,255);
588         _dst[x<<1|1]=(unsigned char)OC_CLAMPI(0,47*_aux[0]+
589          86*_aux[OC_MINI(1,c_w-1)]-5*_aux[OC_MINI(2,c_w-1)]+64>>7,255);
590       }
591       for(;x<c_w-2;x++){
592         _dst[x<<1]=(unsigned char)OC_CLAMPI(0,_aux[x-1]+110*_aux[x]+
593          18*_aux[x+1]-_aux[x+2]+64>>7,255);
594         _dst[x<<1|1]=(unsigned char)OC_CLAMPI(0,-3*_aux[x-1]+50*_aux[x]+
595          86*_aux[x+1]-5*_aux[x+2]+64>>7,255);
596       }
597       for(;x<c_w;x++){
598         _dst[x<<1]=(unsigned char)OC_CLAMPI(0,_aux[x-1]+110*_aux[x]+
599          18*_aux[OC_MINI(x+1,c_w-1)]-_aux[c_w-1]+64>>7,255);
600         if((x<<1|1)<dst_c_w){
601           _dst[x<<1|1]=(unsigned char)OC_CLAMPI(0,-3*_aux[x-1]+50*_aux[x]+
602            86*_aux[OC_MINI(x+1,c_w-1)]-5*_aux[c_w-1]+64>>7,255);
603         }
604       }
605       _dst+=dst_c_w;
606       _aux+=c_w;
607     }
608   }
609 }
610
611 /*The image is padded with empty chroma components at 4:2:0.
612   This costs about 17 bits a frame to code.*/
613 static void y4m_convert_mono_420jpeg(unsigned char *_dst,
614  unsigned char *_aux){
615   int c_sz;
616   _dst+=pic_w*pic_h;
617   c_sz=((pic_w+dst_c_dec_h-1)/dst_c_dec_h)*((pic_h+dst_c_dec_v-1)/dst_c_dec_v);
618   memset(_dst,128,c_sz*2);
619 }
620
621 #if 0
622 /*Right now just 444 to 420.
623   Not too hard to generalize.*/
624 static void y4m_convert_4xxjpeg_42xjpeg(unsigned char *_dst,
625  unsigned char *_aux){
626   unsigned char *tmp;
627   int            c_w;
628   int            c_h;
629   int            pic_sz;
630   int            tmp_sz;
631   int            c_sz;
632   int            pli;
633   int            y;
634   int            x;
635   /*Compute the size of each chroma plane.*/
636   c_w=(pic_w+dst_c_dec_h-1)/dst_c_dec_h;
637   c_h=(pic_h+dst_c_dec_v-1)/dst_c_dec_v;
638   pic_sz=pic_w*pic_h;
639   tmp_sz=c_w*pic_h;
640   c_sz=c_w*c_h;
641   _dst+=pic_sz;
642   for(pli=1;pli<3;pli++){
643     tmp=_aux+pic_sz;
644     /*In reality, the horizontal and vertical steps could be pipelined, for
645        less memory consumption and better cache performance, but we do them
646        separately for simplicity.*/
647     /*First do horizontal filtering (convert to 4:2:2)*/
648     /*Filter: [3 -17 78 78 -17 3]/128, derived from a 6-tap Lanczos window.*/
649     for(y=0;y<pic_h;y++){
650       for(x=0;x<OC_MINI(pic_w,2);x+=2){
651         tmp[x>>1]=OC_CLAMPI(0,64*_aux[0]+78*_aux[OC_MINI(1,pic_w-1)]-
652          17*_aux[OC_MINI(2,pic_w-1)]+3*_aux[OC_MINI(3,pic_w-1)]+64>>7,255);
653       }
654       for(;x<pic_w-3;x+=2){
655         tmp[x>>1]=OC_CLAMPI(0,3*(_aux[x-2]+_aux[x+3])-17*(_aux[x-1]+_aux[x+2])+
656          78*(_aux[x]+_aux[x+1])+64>>7,255);
657       }
658       for(;x<pic_w;x+=2){
659         tmp[x>>1]=OC_CLAMPI(0,3*(_aux[x-2]+_aux[pic_w-1])-
660          17*(_aux[x-1]+_aux[OC_MINI(x+2,pic_w-1)])+
661          78*(_aux[x]+_aux[OC_MINI(x+1,pic_w-1)])+64>>7,255);
662       }
663       tmp+=c_w;
664       _aux+=pic_w;
665     }
666     _aux-=pic_sz;
667     tmp-=tmp_sz;
668     /*Now do the vertical filtering.*/
669     for(x=0;x<c_w;x++){
670       for(y=0;y<OC_MINI(pic_h,2);y+=2){
671         _dst[(y>>1)*c_w]=OC_CLAMPI(0,64*tmp[0]+78*tmp[OC_MINI(1,pic_h-1)*c_w]-
672          17*tmp[OC_MINI(2,pic_h-1)*c_w]+3*tmp[OC_MINI(3,pic_h-1)*c_w]+
673          64>>7,255);
674       }
675       for(;y<pic_h-3;y+=2){
676         _dst[(y>>1)*c_w]=OC_CLAMPI(0,3*(tmp[(y-2)*c_w]+tmp[(y+3)*c_w])-
677          17*(tmp[(y-1)*c_w]+tmp[(y+2)*c_w])+78*(tmp[y*c_w]+tmp[(y+1)*c_w])+
678          64>>7,255);
679       }
680       for(;y<pic_h;y+=2){
681         _dst[(y>>1)*c_w]=OC_CLAMPI(0,3*(tmp[(y-2)*c_w]+tmp[(pic_h-1)*c_w])-
682          17*(tmp[(y-1)*c_w]+tmp[OC_MINI(y+2,pic_h-1)*c_w])+
683          78*(tmp[y*c_w]+tmp[OC_MINI(y+1,pic_h-1)*c_w])+64>>7,255);
684       }
685       tmp++;
686       _dst++;
687     }
688     _dst-=c_w;
689   }
690 }
691 #endif
692
693
694 /*No conversion function needed.*/
695 static void y4m_convert_null(unsigned char *_dst,
696  unsigned char *_aux){
697 }
698
699 static void id_file(char *f){
700   FILE *test;
701   unsigned char buffer[80];
702   int ret;
703
704   /* open it, look for magic */
705
706   if(!strcmp(f,"-")){
707     /* stdin */
708     test=stdin;
709   }else{
710     test=fopen(f,"rb");
711     if(!test){
712       fprintf(stderr,"Unable to open file %s.\n",f);
713       exit(1);
714     }
715   }
716
717   ret=fread(buffer,1,4,test);
718   if(ret<4){
719     fprintf(stderr,"EOF determining file type of file %s.\n",f);
720     exit(1);
721   }
722
723   if(!memcmp(buffer,"RIFF",4)){
724     /* possible WAV file */
725
726     if(audio){
727       /* umm, we already have one */
728       fprintf(stderr,"Multiple RIFF WAVE files specified on command line.\n");
729       exit(1);
730     }
731
732     /* Parse the rest of the header */
733
734     ret=fread(buffer,1,4,test);
735     ret=fread(buffer,1,4,test);
736     if(ret<4)goto riff_err;
737     if(!memcmp(buffer,"WAVE",4)){
738
739       while(!feof(test)){
740         ret=fread(buffer,1,4,test);
741         if(ret<4)goto riff_err;
742         if(!memcmp("fmt",buffer,3)){
743
744           /* OK, this is our audio specs chunk.  Slurp it up. */
745
746           ret=fread(buffer,1,20,test);
747           if(ret<20)goto riff_err;
748
749           if(memcmp(buffer+4,"\001\000",2)){
750             fprintf(stderr,"The WAV file %s is in a compressed format; "
751                     "can't read it.\n",f);
752             exit(1);
753           }
754
755           audio=test;
756           audio_ch=buffer[6]+(buffer[7]<<8);
757           audio_hz=buffer[8]+(buffer[9]<<8)+
758             (buffer[10]<<16)+(buffer[11]<<24);
759
760           if(buffer[18]+(buffer[19]<<8)!=16){
761             fprintf(stderr,"Can only read 16 bit WAV files for now.\n");
762             exit(1);
763           }
764
765           /* Now, align things to the beginning of the data */
766           /* Look for 'dataxxxx' */
767           while(!feof(test)){
768             ret=fread(buffer,1,4,test);
769             if(ret<4)goto riff_err;
770             if(!memcmp("data",buffer,4)){
771               /* We're there.  Ignore the declared size for now. */
772               ret=fread(buffer,1,4,test);
773               if(ret<4)goto riff_err;
774
775               fprintf(stderr,"File %s is 16 bit %d channel %d Hz RIFF WAV audio.\n",
776                       f,audio_ch,audio_hz);
777
778               return;
779             }
780           }
781         }
782       }
783     }
784
785     fprintf(stderr,"Couldn't find WAVE data in RIFF file %s.\n",f);
786     exit(1);
787
788   }
789   if(!memcmp(buffer,"YUV4",4)){
790     /* possible YUV2MPEG2 format file */
791     /* read until newline, or 80 cols, whichever happens first */
792     int i;
793     for(i=0;i<79;i++){
794       ret=fread(buffer+i,1,1,test);
795       if(ret<1)goto yuv_err;
796       if(buffer[i]=='\n')break;
797     }
798     if(i==79){
799       fprintf(stderr,"Error parsing %s header; not a YUV2MPEG2 file?\n",f);
800     }
801     buffer[i]='\0';
802
803     if(!memcmp(buffer,"MPEG",4)){
804
805       if(video){
806         /* umm, we already have one */
807         fprintf(stderr,"Multiple video files specified on command line.\n");
808         exit(1);
809       }
810
811       if(buffer[4]!='2'){
812         fprintf(stderr,"Incorrect YUV input file version; YUV4MPEG2 required.\n");
813       }
814
815       ret=y4m_parse_tags((char *)buffer+5);
816       if(ret<0){
817         fprintf(stderr,"Error parsing YUV4MPEG2 header in file %s.\n",f);
818         exit(1);
819       }
820
821       if(interlace!='p'){
822         fprintf(stderr,"Input video is interlaced; Theora handles only progressive scan\n");
823         exit(1);
824       }
825
826       if(strcmp(chroma_type,"420")==0||strcmp(chroma_type,"420jpeg")==0){
827         src_c_dec_h=dst_c_dec_h=src_c_dec_v=dst_c_dec_v=2;
828         y4m_dst_buf_read_sz=pic_w*pic_h+2*((pic_w+1)/2)*((pic_h+1)/2);
829         y4m_aux_buf_sz=y4m_aux_buf_read_sz=0;
830         y4m_convert=y4m_convert_null;
831       }
832       else if(strcmp(chroma_type,"420mpeg2")==0){
833         src_c_dec_h=dst_c_dec_h=src_c_dec_v=dst_c_dec_v=2;
834         y4m_dst_buf_read_sz=pic_w*pic_h;
835         /*Chroma filter required: read into the aux buf first.*/
836         y4m_aux_buf_sz=y4m_aux_buf_read_sz=2*((pic_w+1)/2)*((pic_h+1)/2);
837         y4m_convert=y4m_convert_42xmpeg2_42xjpeg;
838       }
839       else if(strcmp(chroma_type,"420paldv")==0){
840         src_c_dec_h=dst_c_dec_h=src_c_dec_v=dst_c_dec_v=2;
841         y4m_dst_buf_read_sz=pic_w*pic_h;
842         /*Chroma filter required: read into the aux buf first.
843           We need to make two filter passes, so we need some extra space in the
844            aux buffer.*/
845         y4m_aux_buf_sz=3*((pic_w+1)/2)*((pic_h+1)/2);
846         y4m_aux_buf_read_sz=2*((pic_w+1)/2)*((pic_h+1)/2);
847         y4m_convert=y4m_convert_42xpaldv_42xjpeg;
848       }
849       else if(strcmp(chroma_type,"422")==0){
850         src_c_dec_h=dst_c_dec_h=2;
851         src_c_dec_v=dst_c_dec_v=1;
852         y4m_dst_buf_read_sz=pic_w*pic_h;
853         /*Chroma filter required: read into the aux buf first.*/
854         y4m_aux_buf_sz=y4m_aux_buf_read_sz=2*((pic_w+1)/2)*pic_h;
855         y4m_convert=y4m_convert_42xmpeg2_42xjpeg;
856       }
857       else if(strcmp(chroma_type,"411")==0){
858         src_c_dec_h=4;
859         /*We don't want to introduce any additional sub-sampling, so we
860            promote 4:1:1 material to 4:2:2, as the closest format Theora can
861            handle.*/
862         dst_c_dec_h=2;
863         src_c_dec_v=dst_c_dec_v=1;
864         y4m_dst_buf_read_sz=pic_w*pic_h;
865         /*Chroma filter required: read into the aux buf first.*/
866         y4m_aux_buf_sz=y4m_aux_buf_read_sz=2*((pic_w+3)/4)*pic_h;
867         y4m_convert=y4m_convert_411_422jpeg;
868       }
869       else if(strcmp(chroma_type,"444")==0){
870         src_c_dec_h=dst_c_dec_h=src_c_dec_v=dst_c_dec_v=1;
871         y4m_dst_buf_read_sz=pic_w*pic_h*3;
872         y4m_aux_buf_sz=y4m_aux_buf_read_sz=0;
873         y4m_convert=y4m_convert_null;
874       }
875       else if(strcmp(chroma_type,"444alpha")==0){
876         src_c_dec_h=dst_c_dec_h=src_c_dec_v=dst_c_dec_v=1;
877         y4m_dst_buf_read_sz=pic_w*pic_h*3;
878         /*Read the extra alpha plane into the aux buf.
879           It will be discarded.*/
880         y4m_aux_buf_sz=y4m_aux_buf_read_sz=pic_w*pic_h;
881         y4m_convert=y4m_convert_null;
882       }
883       else if(strcmp(chroma_type,"mono")==0){
884         src_c_dec_h=src_c_dec_v=0;
885         dst_c_dec_h=dst_c_dec_v=2;
886         y4m_dst_buf_read_sz=pic_w*pic_h;
887         y4m_aux_buf_sz=y4m_aux_buf_read_sz=0;
888         y4m_convert=y4m_convert_mono_420jpeg;
889       }
890       else{
891         fprintf(stderr,"Unknown chroma sampling type: %s\n",chroma_type);
892         exit(1);
893       }
894       /*The size of the final frame buffers is always computed from the
895          destination chroma decimation type.*/
896       y4m_dst_buf_sz=pic_w*pic_h+2*((pic_w+dst_c_dec_h-1)/dst_c_dec_h)*
897        ((pic_h+dst_c_dec_v-1)/dst_c_dec_v);
898
899       video=test;
900
901       fprintf(stderr,"File %s is %dx%d %.02f fps %s video.\n",
902               f,pic_w,pic_h,(double)video_fps_n/video_fps_d,chroma_type);
903
904       return;
905     }
906   }
907   fprintf(stderr,"Input file %s is neither a WAV nor YUV4MPEG2 file.\n",f);
908   exit(1);
909
910  riff_err:
911   fprintf(stderr,"EOF parsing RIFF file %s.\n",f);
912   exit(1);
913  yuv_err:
914   fprintf(stderr,"EOF parsing YUV4MPEG2 file %s.\n",f);
915   exit(1);
916
917 }
918
919 int spinner=0;
920 char *spinascii="|/-\\";
921 void spinnit(void){
922   spinner++;
923   if(spinner==4)spinner=0;
924   fprintf(stderr,"\r%c",spinascii[spinner]);
925 }
926
927 int fetch_and_process_audio(FILE *audio,ogg_page *audiopage,
928                             ogg_stream_state *vo,
929                             vorbis_dsp_state *vd,
930                             vorbis_block *vb,
931                             int audioflag){
932   static ogg_int64_t samples_sofar=0;
933   ogg_packet op;
934   int i,j;
935   ogg_int64_t beginsample = audio_hz*begin_sec + audio_hz*begin_usec*.000001;
936   ogg_int64_t endsample = audio_hz*end_sec + audio_hz*end_usec*.000001;
937
938   while(audio && !audioflag){
939     /* process any audio already buffered */
940     spinnit();
941     if(ogg_stream_pageout(vo,audiopage)>0) return 1;
942     if(ogg_stream_eos(vo))return 0;
943
944     {
945       /* read and process more audio */
946       signed char readbuffer[4096];
947       signed char *readptr=readbuffer;
948       int toread=4096/2/audio_ch;
949       int bytesread=fread(readbuffer,1,toread*2*audio_ch,audio);
950       int sampread=bytesread/2/audio_ch;
951       float **vorbis_buffer;
952       int count=0;
953
954       if(bytesread<=0 ||
955          (samples_sofar>=endsample && endsample>0)){
956         /* end of file.  this can be done implicitly, but it's
957            easier to see here in non-clever fashion.  Tell the
958            library we're at end of stream so that it can handle the
959            last frame and mark end of stream in the output properly */
960         vorbis_analysis_wrote(vd,0);
961       }else{
962         if(samples_sofar < beginsample){
963           if(samples_sofar+sampread > beginsample){
964             readptr += (beginsample-samples_sofar)*2*audio_ch;
965             sampread += samples_sofar-beginsample;
966             samples_sofar = sampread+beginsample;
967           }else{
968             samples_sofar += sampread;
969             sampread = 0;
970           }
971         }else{
972           samples_sofar += sampread;
973         }
974
975         if(samples_sofar > endsample && endsample > 0)
976           sampread-= (samples_sofar - endsample);
977
978         if(sampread>0){
979
980           vorbis_buffer=vorbis_analysis_buffer(vd,sampread);
981           /* uninterleave samples */
982           for(i=0;i<sampread;i++){
983             for(j=0;j<audio_ch;j++){
984               vorbis_buffer[j][i]=((readptr[count+1]<<8)|
985                                    (0x00ff&(int)readptr[count]))/32768.f;
986               count+=2;
987             }
988           }
989
990           vorbis_analysis_wrote(vd,sampread);
991         }
992       }
993
994       while(vorbis_analysis_blockout(vd,vb)==1){
995
996         /* analysis, assume we want to use bitrate management */
997         vorbis_analysis(vb,NULL);
998         vorbis_bitrate_addblock(vb);
999
1000         /* weld packets into the bitstream */
1001         while(vorbis_bitrate_flushpacket(vd,&op))
1002           ogg_stream_packetin(vo,&op);
1003
1004       }
1005     }
1006   }
1007
1008   return audioflag;
1009 }
1010
1011 static int                 frame_state=-1;
1012 static ogg_int64_t         frames=0;
1013 static unsigned char      *yuvframe[3];
1014 static th_ycbcr_buffer     ycbcr;
1015
1016 int fetch_and_process_video_packet(FILE *video,FILE *twopass_file,int passno,
1017  th_enc_ctx *td,ogg_packet *op){
1018   int                        ret;
1019   int                        pic_sz;
1020   int                        frame_c_w;
1021   int                        frame_c_h;
1022   int                        c_w;
1023   int                        c_h;
1024   int                        c_sz;
1025   ogg_int64_t                beginframe;
1026   ogg_int64_t                endframe;
1027   spinnit();
1028   beginframe=(video_fps_n*begin_sec+video_fps_n*begin_usec*.000001)/video_fps_d;
1029   endframe=(video_fps_n*end_sec+video_fps_n*end_usec*.000001)/video_fps_d;
1030   if(frame_state==-1){
1031     /* initialize the double frame buffer */
1032     yuvframe[0]=(unsigned char *)malloc(y4m_dst_buf_sz);
1033     yuvframe[1]=(unsigned char *)malloc(y4m_dst_buf_sz);
1034     yuvframe[2]=(unsigned char *)malloc(y4m_aux_buf_sz);
1035     frame_state=0;
1036   }
1037   pic_sz=pic_w*pic_h;
1038   frame_c_w=frame_w/dst_c_dec_h;
1039   frame_c_h=frame_h/dst_c_dec_v;
1040   c_w=(pic_w+dst_c_dec_h-1)/dst_c_dec_h;
1041   c_h=(pic_h+dst_c_dec_v-1)/dst_c_dec_v;
1042   c_sz=c_w*c_h;
1043   /* read and process more video */
1044   /* video strategy reads one frame ahead so we know when we're
1045      at end of stream and can mark last video frame as such
1046      (vorbis audio has to flush one frame past last video frame
1047      due to overlap and thus doesn't need this extra work */
1048
1049   /* have two frame buffers full (if possible) before
1050      proceeding.  after first pass and until eos, one will
1051      always be full when we get here */
1052   for(;frame_state<2 && (frames<endframe || endframe<0);){
1053     char c,frame[6];
1054     int ret=fread(frame,1,6,video);
1055     /* match and skip the frame header */
1056     if(ret<6)break;
1057     if(memcmp(frame,"FRAME",5)){
1058       fprintf(stderr,"Loss of framing in YUV input data\n");
1059       exit(1);
1060     }
1061     if(frame[5]!='\n'){
1062       int j;
1063       for(j=0;j<79;j++)
1064         if(fread(&c,1,1,video)&&c=='\n')break;
1065       if(j==79){
1066         fprintf(stderr,"Error parsing YUV frame header\n");
1067         exit(1);
1068       }
1069     }
1070     /*Read the frame data that needs no conversion.*/
1071     if(fread(yuvframe[frame_state],1,y4m_dst_buf_read_sz,video)!=
1072      y4m_dst_buf_read_sz){
1073       fprintf(stderr,"Error reading YUV frame data.\n");
1074       exit(1);
1075     }
1076     /*Read the frame data that does need conversion.*/
1077     if(fread(yuvframe[2],1,y4m_aux_buf_read_sz,video)!=y4m_aux_buf_read_sz){
1078       fprintf(stderr,"Error reading YUV frame data.\n");
1079       exit(1);
1080     }
1081     /*Now convert the just read frame.*/
1082     (*y4m_convert)(yuvframe[frame_state],yuvframe[2]);
1083     frames++;
1084     if(frames>=beginframe)
1085     frame_state++;
1086   }
1087   /* check to see if there are dupes to flush */
1088   if(th_encode_packetout(td,frame_state<1,op)>0)return 1;
1089   if(frame_state<1){
1090     /* can't get here unless YUV4MPEG stream has no video */
1091     fprintf(stderr,"Video input contains no frames.\n");
1092     exit(1);
1093   }
1094   /* Theora is a one-frame-in,one-frame-out system; submit a frame
1095      for compression and pull out the packet */
1096   /* in two-pass mode's second pass, we need to submit first-pass data */
1097   if(passno==2){
1098     for(;;){
1099       static unsigned char buffer[80];
1100       static int buf_pos;
1101       int bytes;
1102       /*Ask the encoder how many bytes it would like.*/
1103       bytes=th_encode_ctl(td,TH_ENCCTL_2PASS_IN,NULL,0);
1104       if(bytes<0){
1105         fprintf(stderr,"Error submitting pass data in second pass.\n");
1106         exit(1);
1107       }
1108       /*If it's got enough, stop.*/
1109       if(bytes==0)break;
1110       /*Read in some more bytes, if necessary.*/
1111       if(bytes>80-buf_pos)bytes=80-buf_pos;
1112       if(bytes>0&&fread(buffer+buf_pos,1,bytes,twopass_file)<bytes){
1113         fprintf(stderr,"Could not read frame data from two-pass data file!\n");
1114         exit(1);
1115       }
1116       /*And pass them off.*/
1117       ret=th_encode_ctl(td,TH_ENCCTL_2PASS_IN,buffer,bytes);
1118       if(ret<0){
1119         fprintf(stderr,"Error submitting pass data in second pass.\n");
1120         exit(1);
1121       }
1122       /*If the encoder consumed the whole buffer, reset it.*/
1123       if(ret>=bytes)buf_pos=0;
1124       /*Otherwise remember how much it used.*/
1125       else buf_pos+=ret;
1126     }
1127   }
1128   /*We submit the buffer to the library as if it were padded, but we do not
1129      actually allocate space for the padding.
1130     This is okay, because with the 1.0 API the library will never read data from the padded
1131      region.*/
1132   ycbcr[0].width=frame_w;
1133   ycbcr[0].height=frame_h;
1134   ycbcr[0].stride=pic_w;
1135   ycbcr[0].data=yuvframe[0]-pic_x-pic_y*pic_w;
1136   ycbcr[1].width=frame_c_w;
1137   ycbcr[1].height=frame_c_h;
1138   ycbcr[1].stride=c_w;
1139   ycbcr[1].data=yuvframe[0]+pic_sz-(pic_x/dst_c_dec_h)-(pic_y/dst_c_dec_v)*c_w;
1140   ycbcr[2].width=frame_c_w;
1141   ycbcr[2].height=frame_c_h;
1142   ycbcr[2].stride=c_w;
1143   ycbcr[2].data=ycbcr[1].data+c_sz;
1144   th_encode_ycbcr_in(td,ycbcr);
1145   {
1146     unsigned char *temp=yuvframe[0];
1147     yuvframe[0]=yuvframe[1];
1148     yuvframe[1]=temp;
1149     frame_state--;
1150   }
1151   /* in two-pass mode's first pass we need to extract and save the pass data */
1152   if(passno==1){
1153     unsigned char *buffer;
1154     int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
1155     if(bytes<0){
1156       fprintf(stderr,"Could not read two-pass data from encoder.\n");
1157       exit(1);
1158     }
1159     if(fwrite(buffer,1,bytes,twopass_file)<bytes){
1160       fprintf(stderr,"Unable to write to two-pass data file.\n");
1161       exit(1);
1162     }
1163     fflush(twopass_file);
1164   }
1165   /* if there was only one frame, it's the last in the stream */
1166   ret = th_encode_packetout(td,frame_state<1,op);
1167   if(passno==1 && frame_state<1){
1168     /* need to read the final (summary) packet */
1169     unsigned char *buffer;
1170     int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
1171     if(bytes<0){
1172       fprintf(stderr,"Could not read two-pass summary data from encoder.\n");
1173       exit(1);
1174     }
1175     if(fseek(twopass_file,0,SEEK_SET)<0){
1176       fprintf(stderr,"Unable to seek in two-pass data file.\n");
1177       exit(1);
1178     }
1179     if(fwrite(buffer,1,bytes,twopass_file)<bytes){
1180       fprintf(stderr,"Unable to write to two-pass data file.\n");
1181       exit(1);
1182     }
1183     fflush(twopass_file);
1184   }
1185   return ret;
1186 }
1187
1188
1189 int fetch_and_process_video(FILE *video,ogg_page *videopage,
1190  ogg_stream_state *to,th_enc_ctx *td,FILE *twopass_file,int passno,
1191  int videoflag){
1192   ogg_packet op;
1193   int ret;
1194   /* is there a video page flushed?  If not, work until there is. */
1195   while(!videoflag){
1196     if(ogg_stream_pageout(to,videopage)>0) return 1;
1197     if(ogg_stream_eos(to)) return 0;
1198     ret=fetch_and_process_video_packet(video,twopass_file,passno,td,&op);
1199     if(ret<=0)return 0;
1200     ogg_stream_packetin(to,&op);
1201   }
1202   return videoflag;
1203 }
1204
1205 static int ilog(unsigned _v){
1206   int ret;
1207   for(ret=0;_v;ret++)_v>>=1;
1208   return ret;
1209 }
1210
1211 int main(int argc,char *argv[]){
1212   int c,long_option_index,ret;
1213
1214   ogg_stream_state to; /* take physical pages, weld into a logical
1215                            stream of packets */
1216   ogg_stream_state vo; /* take physical pages, weld into a logical
1217                            stream of packets */
1218   ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
1219   ogg_packet       op; /* one raw packet of data for decode */
1220
1221   th_enc_ctx      *td;
1222   th_info          ti;
1223   th_comment       tc;
1224
1225   vorbis_info      vi; /* struct that stores all the static vorbis bitstream
1226                           settings */
1227   vorbis_comment   vc; /* struct that stores all the user comments */
1228
1229   vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
1230   vorbis_block     vb; /* local working space for packet->PCM decode */
1231
1232   int speed=-1;
1233   int audioflag=0;
1234   int videoflag=0;
1235   int akbps=0;
1236   int vkbps=0;
1237   int soft_target=0;
1238
1239   ogg_int64_t audio_bytesout=0;
1240   ogg_int64_t video_bytesout=0;
1241   double timebase;
1242
1243   FILE *outfile = stdout;
1244
1245   FILE *twopass_file = NULL;
1246   fpos_t video_rewind_pos;
1247   int twopass=0;
1248   int passno;
1249
1250 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
1251   /* if we were reading/writing a file, it would also need to in
1252      binary mode, eg, fopen("file.wav","wb"); */
1253   /* Beware the evil ifdef. We avoid these where we can, but this one we
1254      cannot. Don't add any more, you'll probably go to hell if you do. */
1255   _setmode( _fileno( stdin ), _O_BINARY );
1256   _setmode( _fileno( stdout ), _O_BINARY );
1257 #endif
1258
1259   while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
1260     switch(c){
1261     case 'o':
1262       outfile=fopen(optarg,"wb");
1263       if(outfile==NULL){
1264         fprintf(stderr,"Unable to open output file '%s'\n", optarg);
1265         exit(1);
1266       }
1267       break;;
1268
1269     case 'a':
1270       audio_q=(float)(atof(optarg)*.099);
1271       if(audio_q<-.1 || audio_q>1){
1272         fprintf(stderr,"Illegal audio quality (choose -1 through 10)\n");
1273         exit(1);
1274       }
1275       audio_r=-1;
1276       break;
1277
1278     case 'v':
1279       video_q=(int)rint(6.3*atof(optarg));
1280       if(video_q<0 || video_q>63){
1281         fprintf(stderr,"Illegal video quality (choose 0 through 10)\n");
1282         exit(1);
1283       }
1284       break;
1285
1286     case 'A':
1287       audio_r=(int)(atof(optarg)*1000);
1288       if(audio_q<0){
1289         fprintf(stderr,"Illegal audio quality (choose > 0 please)\n");
1290         exit(1);
1291       }
1292       audio_q=-99;
1293       break;
1294
1295     case 'V':
1296       video_r=(int)rint(atof(optarg)*1000);
1297       if(video_r<1){
1298         fprintf(stderr,"Illegal video bitrate (choose > 0 please)\n");
1299         exit(1);
1300       }
1301      break;
1302
1303     case '\1':
1304       soft_target=1;
1305       break;
1306
1307     case 's':
1308       video_par_n=(int)rint(atof(optarg));
1309       break;
1310
1311     case 'S':
1312       video_par_d=(int)rint(atof(optarg));
1313       break;
1314
1315     case 'f':
1316       video_fps_n=(int)rint(atof(optarg));
1317       break;
1318
1319     case 'F':
1320       video_fps_d=(int)rint(atof(optarg));
1321       break;
1322
1323     case 'c':
1324       vp3_compatible=1;
1325       break;
1326
1327     case 'k':
1328       keyframe_frequency=rint(atof(optarg));
1329       if(keyframe_frequency<1 || keyframe_frequency>2147483647){
1330         fprintf(stderr,"Illegal keyframe frequency\n");
1331         exit(1);
1332       }
1333       break;
1334
1335     case 'd':
1336       buf_delay=atoi(optarg);
1337       if(buf_delay<=0){
1338         fprintf(stderr,"Illegal buffer delay\n");
1339         exit(1);
1340       }
1341       break;
1342
1343     case 'z':
1344       speed=atoi(optarg);
1345       if(speed<0){
1346         fprintf(stderr,"Illegal speed level\n");
1347         exit(1);
1348       }
1349       break;
1350
1351     case 'b':
1352       {
1353         char *pos=strchr(optarg,':');
1354         begin_sec=atol(optarg);
1355         if(pos){
1356           char *pos2=strchr(++pos,':');
1357           begin_sec*=60;
1358           begin_sec+=atol(pos);
1359           if(pos2){
1360             pos2++;
1361             begin_sec*=60;
1362             begin_sec+=atol(pos2);
1363             pos=pos2;
1364           }
1365         }else
1366           pos=optarg;
1367         pos=strchr(pos,'.');
1368         if(pos){
1369           int digits = strlen(++pos);
1370           begin_usec=atol(pos);
1371           while(digits++ < 6)
1372             begin_usec*=10;
1373         }
1374       }
1375       break;
1376     case 'e':
1377       {
1378         char *pos=strchr(optarg,':');
1379         end_sec=atol(optarg);
1380         if(pos){
1381           char *pos2=strchr(++pos,':');
1382           end_sec*=60;
1383           end_sec+=atol(pos);
1384           if(pos2){
1385             pos2++;
1386             end_sec*=60;
1387             end_sec+=atol(pos2);
1388             pos=pos2;
1389           }
1390         }else
1391           pos=optarg;
1392         pos=strchr(pos,'.');
1393         if(pos){
1394           int digits = strlen(++pos);
1395           end_usec=atol(pos);
1396           while(digits++ < 6)
1397             end_usec*=10;
1398         }
1399       }
1400       break;
1401     case '\2':
1402       twopass=3; /* perform both passes */
1403       twopass_file=tmpfile();
1404       if(!twopass_file){
1405         fprintf(stderr,"Unable to open temporary file for twopass data\n");
1406         exit(1);
1407       }
1408       break;
1409     case '\3':
1410       twopass=1; /* perform first pass */
1411       twopass_file=fopen(optarg,"wb");
1412       if(!twopass_file){
1413         fprintf(stderr,"Unable to open \'%s\' for twopass data\n",optarg);
1414         exit(1);
1415       }
1416       break;
1417     case '\4':
1418       twopass=2; /* perform second pass */
1419       twopass_file=fopen(optarg,"rb");
1420       if(!twopass_file){
1421         fprintf(stderr,"Unable to open twopass data file \'%s\'",optarg);
1422         exit(1);
1423       }
1424       break;
1425
1426     default:
1427       usage();
1428     }
1429   }
1430
1431   if(soft_target){
1432     if(video_r<=0){
1433       fprintf(stderr,"Soft rate target (--soft-target) requested without a bitrate (-V).\n");
1434       exit(1);
1435     }
1436     if(video_q==-1)
1437       video_q=0;
1438   }else{
1439     if(video_r>0)
1440       video_q=0;
1441     if(video_q==-1)
1442       video_q=48;
1443   }
1444
1445   if(keyframe_frequency<=0){
1446     /*Use a default keyframe frequency of 64 for 1-pass (streaming) mode, and
1447        256 for two-pass mode.*/
1448     keyframe_frequency=twopass?256:64;
1449   }
1450
1451   while(optind<argc){
1452     /* assume that anything following the options must be a filename */
1453     id_file(argv[optind]);
1454     optind++;
1455   }
1456
1457   if(twopass==3){
1458     /* verify that the input is seekable! */
1459     if(video){
1460       if(fseek(video,0,SEEK_CUR)){
1461         fprintf(stderr,"--two-pass (automatic two-pass) requires the video input\n"
1462                 "to be seekable.  For non-seekable input, encoder_example\n"
1463                 "must be run twice, first with the --first-pass option, then\n"
1464                 "with the --second-pass option.\n\n");
1465         exit(1);
1466       }
1467       if(fgetpos(video,&video_rewind_pos)<0){
1468         fprintf(stderr,"Unable to determine start position of video data.\n");
1469         exit(1);
1470       }
1471     }
1472   }
1473
1474   /* Set up Ogg output stream */
1475   srand(time(NULL));
1476   if(audio)ogg_stream_init(&vo,rand());
1477   ogg_stream_init(&to,rand()); /* oops, add one ot the above */
1478
1479   /* initialize Vorbis assuming we have audio to compress. */
1480   if(audio && twopass!=1){
1481     vorbis_info_init(&vi);
1482     if(audio_q>-99)
1483       ret = vorbis_encode_init_vbr(&vi,audio_ch,audio_hz,audio_q);
1484     else
1485       ret = vorbis_encode_init(&vi,audio_ch,audio_hz,-1,
1486                                (int)(64870*(ogg_int64_t)audio_r>>16),-1);
1487     if(ret){
1488       fprintf(stderr,"The Vorbis encoder could not set up a mode according to\n"
1489               "the requested quality or bitrate.\n\n");
1490       exit(1);
1491     }
1492
1493     vorbis_comment_init(&vc);
1494     vorbis_analysis_init(&vd,&vi);
1495     vorbis_block_init(&vd,&vb);
1496   }
1497
1498   for(passno=(twopass==3?1:twopass);passno<=(twopass==3?2:twopass);passno++){
1499     /* Set up Theora encoder */
1500     if(!video){
1501       fprintf(stderr,"No video files submitted for compression?\n");
1502       exit(1);
1503     }
1504     /* Theora has a divisible-by-sixteen restriction for the encoded frame size */
1505     /* scale the picture size up to the nearest /16 and calculate offsets */
1506     frame_w=pic_w+15&~0xF;
1507     frame_h=pic_h+15&~0xF;
1508     /*Force the offsets to be even so that chroma samples line up like we
1509        expect.*/
1510     pic_x=frame_w-pic_w>>1&~1;
1511     pic_y=frame_h-pic_h>>1&~1;
1512     th_info_init(&ti);
1513     ti.frame_width=frame_w;
1514     ti.frame_height=frame_h;
1515     ti.pic_width=pic_w;
1516     ti.pic_height=pic_h;
1517     ti.pic_x=pic_x;
1518     ti.pic_y=pic_y;
1519     ti.fps_numerator=video_fps_n;
1520     ti.fps_denominator=video_fps_d;
1521     ti.aspect_numerator=video_par_n;
1522     ti.aspect_denominator=video_par_d;
1523     ti.colorspace=TH_CS_UNSPECIFIED;
1524     /*Account for the Ogg page overhead.
1525       This is 1 byte per 255 for lacing values, plus 26 bytes per 4096 bytes for
1526        the page header, plus approximately 1/2 byte per packet (not accounted for
1527        here).*/
1528     ti.target_bitrate=(int)(64870*(ogg_int64_t)video_r>>16);
1529     ti.quality=video_q;
1530     ti.keyframe_granule_shift=ilog(keyframe_frequency-1);
1531     if(dst_c_dec_h==2){
1532       if(dst_c_dec_v==2)ti.pixel_fmt=TH_PF_420;
1533       else ti.pixel_fmt=TH_PF_422;
1534     }
1535     else ti.pixel_fmt=TH_PF_444;
1536     td=th_encode_alloc(&ti);
1537     th_info_clear(&ti);
1538     /* setting just the granule shift only allows power-of-two keyframe
1539        spacing.  Set the actual requested spacing. */
1540     ret=th_encode_ctl(td,TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
1541      &keyframe_frequency,sizeof(keyframe_frequency-1));
1542     if(ret<0){
1543       fprintf(stderr,"Could not set keyframe interval to %d.\n",(int)keyframe_frequency);
1544     }
1545     if(vp3_compatible){
1546       ret=th_encode_ctl(td,TH_ENCCTL_SET_VP3_COMPATIBLE,&vp3_compatible,
1547        sizeof(vp3_compatible));
1548       if(ret<0||!vp3_compatible){
1549         fprintf(stderr,"Could not enable strict VP3 compatibility.\n");
1550         if(ret>=0){
1551           fprintf(stderr,"Ensure your source format is supported by VP3.\n");
1552           fprintf(stderr,
1553            "(4:2:0 pixel format, width and height multiples of 16).\n");
1554         }
1555       }
1556     }
1557     if(soft_target){
1558       /* reverse the rate control flags to favor a 'long time' strategy */
1559       int arg = TH_RATECTL_CAP_UNDERFLOW;
1560       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_FLAGS,&arg,sizeof(arg));
1561       if(ret<0)
1562         fprintf(stderr,"Could not set encoder flags for --soft-target\n");
1563       /* Default buffer control is overridden on two-pass */
1564       if(!twopass&&buf_delay<0){
1565         if((keyframe_frequency*7>>1) > 5*video_fps_n/video_fps_d)
1566           arg=keyframe_frequency*7>>1;
1567         else
1568           arg=5*video_fps_n/video_fps_d;
1569         ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,&arg,sizeof(arg));
1570         if(ret<0)
1571           fprintf(stderr,"Could not set rate control buffer for --soft-target\n");
1572       }
1573     }
1574     /* set up two-pass if needed */
1575     if(passno==1){
1576       unsigned char *buffer;
1577       int bytes;
1578       bytes=th_encode_ctl(td,TH_ENCCTL_2PASS_OUT,&buffer,sizeof(buffer));
1579       if(bytes<0){
1580         fprintf(stderr,"Could not set up the first pass of two-pass mode.\n");
1581         fprintf(stderr,"Did you remember to specify an estimated bitrate?\n");
1582         exit(1);
1583       }
1584       /*Perform a seek test to ensure we can overwrite this placeholder data at
1585          the end; this is better than letting the user sit through a whole
1586          encode only to find out their pass 1 file is useless at the end.*/
1587       if(fseek(twopass_file,0,SEEK_SET)<0){
1588         fprintf(stderr,"Unable to seek in two-pass data file.\n");
1589         exit(1);
1590       }
1591       if(fwrite(buffer,1,bytes,twopass_file)<bytes){
1592         fprintf(stderr,"Unable to write to two-pass data file.\n");
1593         exit(1);
1594       }
1595       fflush(twopass_file);
1596     }
1597     if(passno==2){
1598       /*Enable the second pass here.
1599         We make this call just to set the encoder into 2-pass mode, because
1600          by default enabling two-pass sets the buffer delay to the whole file
1601          (because there's no way to explicitly request that behavior).
1602         If we waited until we were actually encoding, it would overwite our
1603          settings.*/
1604       if(th_encode_ctl(td,TH_ENCCTL_2PASS_IN,NULL,0)<0){
1605         fprintf(stderr,"Could not set up the second pass of two-pass mode.\n");
1606         exit(1);
1607       }
1608       if(twopass==3){
1609         /* 'automatic' second pass */
1610         if(fsetpos(video,&video_rewind_pos)<0){
1611           fprintf(stderr,"Could not rewind video input file for second pass!\n");
1612           exit(1);
1613         }
1614         if(fseek(twopass_file,0,SEEK_SET)<0){
1615           fprintf(stderr,"Unable to seek in two-pass data file.\n");
1616           exit(1);
1617         }
1618         frame_state=0;
1619         frames=0;
1620       }
1621     }
1622     /*Now we can set the buffer delay if the user requested a non-default one
1623        (this has to be done after two-pass is enabled).*/
1624     if(passno!=1&&buf_delay>=0){
1625       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,
1626        &buf_delay,sizeof(buf_delay));
1627       if(ret<0){
1628         fprintf(stderr,"Warning: could not set desired buffer delay.\n");
1629       }
1630     }
1631     /*Speed should also be set after the current encoder mode is established,
1632        since the available speed levels may change depending.*/
1633     if(speed>=0){
1634       int speed_max;
1635       int ret;
1636       ret=th_encode_ctl(td,TH_ENCCTL_GET_SPLEVEL_MAX,
1637        &speed_max,sizeof(speed_max));
1638       if(ret<0){
1639         fprintf(stderr,"Warning: could not determine maximum speed level.\n");
1640         speed_max=0;
1641       }
1642       ret=th_encode_ctl(td,TH_ENCCTL_SET_SPLEVEL,&speed,sizeof(speed));
1643       if(ret<0){
1644         fprintf(stderr,"Warning: could not set speed level to %i of %i\n",
1645          speed,speed_max);
1646         if(speed>speed_max){
1647           fprintf(stderr,"Setting it to %i instead\n",speed_max);
1648         }
1649         ret=th_encode_ctl(td,TH_ENCCTL_SET_SPLEVEL,
1650          &speed_max,sizeof(speed_max));
1651         if(ret<0){
1652           fprintf(stderr,"Warning: could not set speed level to %i of %i\n",
1653            speed_max,speed_max);
1654         }
1655       }
1656     }
1657     /* write the bitstream header packets with proper page interleave */
1658     th_comment_init(&tc);
1659     /* first packet will get its own page automatically */
1660     if(th_encode_flushheader(td,&tc,&op)<=0){
1661       fprintf(stderr,"Internal Theora library error.\n");
1662       exit(1);
1663     }
1664     if(passno!=1){
1665       ogg_stream_packetin(&to,&op);
1666       if(ogg_stream_pageout(&to,&og)!=1){
1667         fprintf(stderr,"Internal Ogg library error.\n");
1668         exit(1);
1669       }
1670       fwrite(og.header,1,og.header_len,outfile);
1671       fwrite(og.body,1,og.body_len,outfile);
1672     }
1673     /* create the remaining theora headers */
1674     for(;;){
1675       ret=th_encode_flushheader(td,&tc,&op);
1676       if(ret<0){
1677         fprintf(stderr,"Internal Theora library error.\n");
1678         exit(1);
1679       }
1680       else if(!ret)break;
1681       if(passno!=1)ogg_stream_packetin(&to,&op);
1682     }
1683     if(audio && passno!=1){
1684       ogg_packet header;
1685       ogg_packet header_comm;
1686       ogg_packet header_code;
1687       vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
1688       ogg_stream_packetin(&vo,&header); /* automatically placed in its own
1689                                            page */
1690       if(ogg_stream_pageout(&vo,&og)!=1){
1691         fprintf(stderr,"Internal Ogg library error.\n");
1692         exit(1);
1693       }
1694       fwrite(og.header,1,og.header_len,outfile);
1695       fwrite(og.body,1,og.body_len,outfile);
1696       /* remaining vorbis header packets */
1697       ogg_stream_packetin(&vo,&header_comm);
1698       ogg_stream_packetin(&vo,&header_code);
1699     }
1700     /* Flush the rest of our headers. This ensures
1701        the actual data in each stream will start
1702        on a new page, as per spec. */
1703     if(passno!=1){
1704       for(;;){
1705         int result = ogg_stream_flush(&to,&og);
1706         if(result<0){
1707           /* can't get here */
1708           fprintf(stderr,"Internal Ogg library error.\n");
1709           exit(1);
1710         }
1711         if(result==0)break;
1712         fwrite(og.header,1,og.header_len,outfile);
1713         fwrite(og.body,1,og.body_len,outfile);
1714       }
1715     }
1716     if(audio && passno!=1){
1717       for(;;){
1718         int result=ogg_stream_flush(&vo,&og);
1719         if(result<0){
1720           /* can't get here */
1721           fprintf(stderr,"Internal Ogg library error.\n");
1722           exit(1);
1723         }
1724         if(result==0)break;
1725         fwrite(og.header,1,og.header_len,outfile);
1726         fwrite(og.body,1,og.body_len,outfile);
1727       }
1728     }
1729     /* setup complete.  Raw processing loop */
1730       switch(passno){
1731       case 0: case 2:
1732         fprintf(stderr,"\rCompressing....                                          \n");
1733         break;
1734       case 1:
1735         fprintf(stderr,"\rScanning first pass....                                  \n");
1736         break;
1737       }
1738     for(;;){
1739       int audio_or_video=-1;
1740       if(passno==1){
1741         ogg_packet op;
1742         int ret=fetch_and_process_video_packet(video,twopass_file,passno,td,&op);
1743         if(ret<0)break;
1744         if(op.e_o_s)break; /* end of stream */
1745         timebase=th_granule_time(td,op.granulepos);
1746         audio_or_video=1;
1747       }else{
1748         double audiotime;
1749         double videotime;
1750         ogg_page audiopage;
1751         ogg_page videopage;
1752         /* is there an audio page flushed?  If not, fetch one if possible */
1753         audioflag=fetch_and_process_audio(audio,&audiopage,&vo,&vd,&vb,audioflag);
1754         /* is there a video page flushed?  If not, fetch one if possible */
1755         videoflag=fetch_and_process_video(video,&videopage,&to,td,twopass_file,passno,videoflag);
1756         /* no pages of either?  Must be end of stream. */
1757         if(!audioflag && !videoflag)break;
1758         /* which is earlier; the end of the audio page or the end of the
1759            video page? Flush the earlier to stream */
1760         audiotime=
1761         audioflag?vorbis_granule_time(&vd,ogg_page_granulepos(&audiopage)):-1;
1762         videotime=
1763         videoflag?th_granule_time(td,ogg_page_granulepos(&videopage)):-1;
1764         if(!audioflag){
1765           audio_or_video=1;
1766         } else if(!videoflag) {
1767           audio_or_video=0;
1768         } else {
1769           if(audiotime<videotime)
1770             audio_or_video=0;
1771           else
1772             audio_or_video=1;
1773         }
1774         if(audio_or_video==1){
1775           /* flush a video page */
1776           video_bytesout+=fwrite(videopage.header,1,videopage.header_len,outfile);
1777           video_bytesout+=fwrite(videopage.body,1,videopage.body_len,outfile);
1778           videoflag=0;
1779           timebase=videotime;
1780         }else{
1781           /* flush an audio page */
1782           audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,outfile);
1783           audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,outfile);
1784           audioflag=0;
1785           timebase=audiotime;
1786         }
1787       }
1788       if(timebase > 0){
1789         int hundredths=(int)(timebase*100-(long)timebase*100);
1790         int seconds=(long)timebase%60;
1791         int minutes=((long)timebase/60)%60;
1792         int hours=(long)timebase/3600;
1793         if(audio_or_video)vkbps=(int)rint(video_bytesout*8./timebase*.001);
1794         else akbps=(int)rint(audio_bytesout*8./timebase*.001);
1795         fprintf(stderr,
1796                 "\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps                 ",
1797                 hours,minutes,seconds,hundredths,akbps,vkbps);
1798       }
1799     }
1800     if(video)th_encode_free(td);
1801   }
1802
1803   /* clear out state */
1804   if(audio){
1805     ogg_stream_clear(&vo);
1806     vorbis_block_clear(&vb);
1807     vorbis_dsp_clear(&vd);
1808     vorbis_comment_clear(&vc);
1809     vorbis_info_clear(&vi);
1810     if(audio!=stdin)fclose(audio);
1811   }
1812   if(video){
1813     ogg_stream_clear(&to);
1814     th_comment_clear(&tc);
1815     if(video!=stdin)fclose(video);
1816   }
1817
1818   if(outfile && outfile!=stdout)fclose(outfile);
1819   if(twopass_file)fclose(twopass_file);
1820
1821   fprintf(stderr,"\r   \ndone.\n\n");
1822
1823   return(0);
1824
1825 }