Add c64x changes for r17563, as they were accidentally omitted.
[theora.git] / examples / png2theora.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,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
14             file from a sequence of png images
15   last mod: $Id$
16              based on code from Vegard Nossum
17
18  ********************************************************************/
19
20 #define _FILE_OFFSET_BITS 64
21
22 #include <errno.h>
23 #include <getopt.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <time.h>
29 #include <math.h>
30 #include <libgen.h>
31 #include <sys/types.h>
32 #include <dirent.h>
33
34 #ifdef HAVE_CONFIG_H
35 # include <config.h>
36 #endif
37
38 #include <png.h>
39 #include <ogg/ogg.h>
40 #include "theora/theoraenc.h"
41
42 #define PROGRAM_NAME  "png2theora"
43 #define PROGRAM_VERSION  "1.1"
44
45 static const char *option_output = NULL;
46 static int video_fps_numerator = 24;
47 static int video_fps_denominator = 1;
48 static int video_aspect_numerator = 0;
49 static int video_aspect_denominator = 0;
50 static int video_rate = -1;
51 static int video_quality = -1;
52 ogg_uint32_t keyframe_frequency=0;
53 int buf_delay=-1;
54 int vp3_compatible=0;
55 static int chroma_format = TH_PF_420;
56
57 static FILE *twopass_file = NULL;
58 static  int twopass=0;
59 static  int passno;
60
61 static FILE *ogg_fp = NULL;
62 static ogg_stream_state ogg_os;
63 static ogg_packet op;   
64 static ogg_page og;
65     
66 static th_enc_ctx      *td;
67 static th_info          ti;
68
69 static char *input_filter;
70
71 const char *optstring = "o:hv:\4:\2:V:s:S:f:F:ck:d:\1\2\3\4\5\6";
72 struct option options [] = {
73  {"output",required_argument,NULL,'o'},
74  {"help",no_argument,NULL,'h'},
75  {"chroma-444",no_argument,NULL,'\5'},
76  {"chroma-422",no_argument,NULL,'\6'},
77  {"video-rate-target",required_argument,NULL,'V'},
78  {"video-quality",required_argument,NULL,'v'},
79  {"aspect-numerator",required_argument,NULL,'s'},
80  {"aspect-denominator",required_argument,NULL,'S'},
81  {"framerate-numerator",required_argument,NULL,'f'},
82  {"framerate-denominator",required_argument,NULL,'F'},
83  {"vp3-compatible",no_argument,NULL,'c'},
84  {"soft-target",no_argument,NULL,'\1'},
85  {"keyframe-freq",required_argument,NULL,'k'},
86  {"buf-delay",required_argument,NULL,'d'},
87  {"two-pass",no_argument,NULL,'\2'},
88  {"first-pass",required_argument,NULL,'\3'}, 
89  {"second-pass",required_argument,NULL,'\4'},  
90  {NULL,0,NULL,0}
91 };
92
93 static void usage(void){
94   fprintf(stderr,
95           "%s %s\n"
96           "Usage: %s [options] <input>\n\n"
97           "The input argument uses C printf format to represent a list of files,\n"
98           "  i.e. file-%%06d.png to look for files file000001.png to file9999999.png \n\n"
99           "Options: \n\n"
100           "  -o --output <filename.ogv>      file name for encoded output (required);\n"
101           "  -v --video-quality <n>          Theora quality selector fro 0 to 10\n"
102           "                                  (0 yields smallest files but lowest\n"
103           "                                  video quality. 10 yields highest\n"
104           "                                  fidelity but large files)\n\n"
105           "  -V --video-rate-target <n>      bitrate target for Theora video\n\n"
106           "     --soft-target                Use a large reservoir and treat the rate\n"
107           "                                  as a soft target; rate control is less\n"
108           "                                  strict but resulting quality is usually\n"
109           "                                  higher/smoother overall. Soft target also\n"
110           "                                  allows an optional -v setting to specify\n"
111           "                                  a minimum allowed quality.\n\n"
112           "     --two-pass                   Compress input using two-pass rate control\n"
113           "                                  This option performs both passes automatically.\n\n"
114           "     --first-pass <filename>      Perform first-pass of a two-pass rate\n"
115           "                                  controlled encoding, saving pass data to\n"
116           "                                  <filename> for a later second pass\n\n"
117           "     --second-pass <filename>     Perform second-pass of a two-pass rate\n"
118           "                                  controlled encoding, reading first-pass\n"
119           "                                  data from <filename>.  The first pass\n"
120           "                                  data must come from a first encoding pass\n"
121           "                                  using identical input video to work\n"
122           "                                  properly.\n\n"
123           "   -k --keyframe-freq <n>         Keyframe frequency\n"
124           "   -d --buf-delay <n>             Buffer delay (in frames). Longer delays\n"
125           "                                  allow smoother rate adaptation and provide\n"
126           "                                  better overall quality, but require more\n"
127           "                                  client side buffering and add latency. The\n"
128           "                                  default value is the keyframe interval for\n"
129           "                                  one-pass encoding (or somewhat larger if\n"
130           "                                  --soft-target is used) and infinite for\n"
131           "                                  two-pass encoding.\n"
132           "  --chroma-444                    Use 4:4:4 chroma subsampling\n"
133           "  --chroma-422                    Use 4:2:2 chroma subsampling\n"
134           "                                  (4:2:0 is default)\n\n" 
135           "  -s --aspect-numerator <n>       Aspect ratio numerator, default is 0\n"
136           "  -S --aspect-denominator <n>     Aspect ratio denominator, default is 0\n"
137           "  -f --framerate-numerator <n>    Frame rate numerator\n"
138           "  -F --framerate-denominator <n>  Frame rate denominator\n"
139           "                                  The frame rate nominator divided by this\n"
140           "                                  determines the frame rate in units per tick\n"
141           ,PROGRAM_NAME, PROGRAM_VERSION, PROGRAM_NAME
142   );
143   exit(0);
144 }
145
146 #ifdef WIN32
147 int
148 alphasort (const void *a, const void *b)
149 {
150   return strcoll ((*(const struct dirent **) a)->d_name,
151                   (*(const struct dirent **) b)->d_name);
152 }
153
154 int
155 scandir (const char *dir, struct dirent ***namelist,
156          int (*select)(const struct dirent *), int (*compar)(const void *, const void *))
157 {
158   DIR *d;
159   struct dirent *entry;
160   register int i=0;
161   size_t entrysize;
162
163   if ((d=opendir(dir)) == NULL)
164     return(-1);
165
166   *namelist=NULL;
167   while ((entry=readdir(d)) != NULL)
168   {
169     if (select == NULL || (select != NULL && (*select)(entry)))
170     {
171       *namelist=(struct dirent **)realloc((void *)(*namelist),
172                  (size_t)((i+1)*sizeof(struct dirent *)));
173       if (*namelist == NULL) return(-1);
174       entrysize=sizeof(struct dirent)-sizeof(entry->d_name)+strlen(entry->d_name)+1;
175       (*namelist)[i]=(struct dirent *)malloc(entrysize);
176       if ((*namelist)[i] == NULL) return(-1);
177         memcpy((*namelist)[i], entry, entrysize);
178       i++;
179     }
180   }
181   if (closedir(d)) return(-1);
182   if (i == 0) return(-1);
183   if (compar != NULL)
184     qsort((void *)(*namelist), (size_t)i, sizeof(struct dirent *), compar);
185     
186   return(i);
187 }
188 #endif
189
190 static int
191 theora_write_frame(th_ycbcr_buffer ycbcr, int last)
192 {
193   ogg_packet op;
194   ogg_page og;
195
196   /* Theora is a one-frame-in,one-frame-out system; submit a frame
197      for compression and pull out the packet */
198   /* in two-pass mode's second pass, we need to submit first-pass data */
199   if(passno==2){
200     int ret;
201     for(;;){
202       static unsigned char buffer[80];
203       static int buf_pos;
204       int bytes;
205       /*Ask the encoder how many bytes it would like.*/
206       bytes=th_encode_ctl(td,TH_ENCCTL_2PASS_IN,NULL,0);
207       if(bytes<0){
208         fprintf(stderr,"Error submitting pass data in second pass.\n");
209         exit(1);
210       }
211       /*If it's got enough, stop.*/
212       if(bytes==0)break;
213       /*Read in some more bytes, if necessary.*/
214       if(bytes>80-buf_pos)bytes=80-buf_pos;
215       if(bytes>0&&fread(buffer+buf_pos,1,bytes,twopass_file)<bytes){
216         fprintf(stderr,"Could not read frame data from two-pass data file!\n");
217         exit(1);
218       }
219       /*And pass them off.*/
220       ret=th_encode_ctl(td,TH_ENCCTL_2PASS_IN,buffer,bytes);
221       if(ret<0){
222         fprintf(stderr,"Error submitting pass data in second pass.\n");
223         exit(1);
224       }
225       /*If the encoder consumed the whole buffer, reset it.*/
226       if(ret>=bytes)buf_pos=0;
227       /*Otherwise remember how much it used.*/
228       else buf_pos+=ret;
229     }
230   }
231
232   if(th_encode_ycbcr_in(td, ycbcr)) {
233     fprintf(stderr, "%s: error: could not encode frame\n",
234       option_output);
235     return 1;
236   }
237
238   /* in two-pass mode's first pass we need to extract and save the pass data */
239   if(passno==1){
240     unsigned char *buffer;
241     int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
242     if(bytes<0){
243       fprintf(stderr,"Could not read two-pass data from encoder.\n");
244       exit(1);
245     }
246     if(fwrite(buffer,1,bytes,twopass_file)<bytes){
247       fprintf(stderr,"Unable to write to two-pass data file.\n");
248       exit(1);
249     }
250     fflush(twopass_file);
251   }
252
253   if(!th_encode_packetout(td, last, &op)) {
254     fprintf(stderr, "%s: error: could not read packets\n",
255       option_output);
256     return 1;
257   }
258
259   if (passno!=1) { 
260     ogg_stream_packetin(&ogg_os, &op);
261     while(ogg_stream_pageout(&ogg_os, &og)) {
262       fwrite(og.header, og.header_len, 1, ogg_fp);
263       fwrite(og.body, og.body_len, 1, ogg_fp);
264     }
265   }  
266
267   return 0;
268 }
269
270 static unsigned char
271 clamp(int d)
272 {
273   if(d < 0)
274     return 0;
275
276   if(d > 255)
277     return 255;
278
279   return d;
280 }
281
282 static void
283 rgb_to_yuv(png_bytep *png,
284            th_ycbcr_buffer ycbcr,
285            unsigned int w, unsigned int h)
286 {
287   unsigned int x;
288   unsigned int y;
289
290   unsigned int x1;
291   unsigned int y1;
292
293   unsigned long yuv_w;
294   unsigned long yuv_h;
295
296   unsigned char *yuv_y;
297   unsigned char *yuv_u;
298   unsigned char *yuv_v;
299
300   yuv_w = ycbcr[0].width;
301   yuv_h = ycbcr[0].height;
302
303   yuv_y = ycbcr[0].data;
304   yuv_u = ycbcr[1].data;
305   yuv_v = ycbcr[2].data;
306   
307   /*This ignores gamma and RGB primary/whitepoint differences.
308     It also isn't terribly fast (though a decent compiler will
309     strength-reduce the division to a multiplication).*/
310
311   if (chroma_format == TH_PF_420) {
312     for(y = 0; y < h; y += 2) {
313       y1=y+(y+1<h);      
314       for(x = 0; x < w; x += 2) {
315         x1=x+(x+1<w);
316         png_byte r0 = png[y][3 * x + 0];
317         png_byte g0 = png[y][3 * x + 1];
318         png_byte b0 = png[y][3 * x + 2];
319         png_byte r1 = png[y][3 * x1 + 0];
320         png_byte g1 = png[y][3 * x1 + 1];
321         png_byte b1 = png[y][3 * x1 + 2];
322         png_byte r2 = png[y1][3 * x + 0];
323         png_byte g2 = png[y1][3 * x + 1];
324         png_byte b2 = png[y1][3 * x + 2];
325         png_byte r3 = png[y1][3 * x1 + 0];
326         png_byte g3 = png[y1][3 * x1 + 1];
327         png_byte b3 = png[y1][3 * x1 + 2];
328         
329         yuv_y[x  + y * yuv_w]  = clamp((65481*r0+128553*g0+24966*b0+4207500)/255000);
330         yuv_y[x1 + y * yuv_w]  = clamp((65481*r1+128553*g1+24966*b1+4207500)/255000);
331         yuv_y[x  + y1 * yuv_w] = clamp((65481*r2+128553*g2+24966*b2+4207500)/255000);
332         yuv_y[x1 + y1 * yuv_w] = clamp((65481*r3+128553*g3+24966*b3+4207500)/255000);
333         
334         yuv_u[(x >> 1) + (y >> 1) * ycbcr[1].stride] =
335           clamp( ((-33488*r0-65744*g0+99232*b0+29032005)/4 +
336                   (-33488*r0-65744*g0+99232*b0+29032005)/4 +
337                   (-33488*r2-65744*g2+99232*b2+29032005)/4 +
338                   (-33488*r3-65744*g3+99232*b3+29032005)/4)/225930);
339         yuv_v[(x >> 1) + (y >> 1) * ycbcr[2].stride] =
340           clamp( ((157024*r0-131488*g0-25536*b0+45940035)/4 +
341                   (157024*r1-131488*g1-25536*b1+45940035)/4 +
342                   (157024*r2-131488*g2-25536*b2+45940035)/4 +
343                   (157024*r3-131488*g3-25536*b3+45940035)/4)/357510);
344       }
345     }
346   } else if (chroma_format == TH_PF_444) {
347     for(y = 0; y < h; y++) {
348       for(x = 0; x < w; x++) {
349         png_byte r = png[y][3 * x + 0];
350         png_byte g = png[y][3 * x + 1];
351         png_byte b = png[y][3 * x + 2];
352
353         yuv_y[x + y * yuv_w] = clamp((65481*r+128553*g+24966*b+4207500)/255000);
354         yuv_u[x + y * yuv_w] = clamp((-33488*r-65744*g+99232*b+29032005)/225930);
355         yuv_v[x + y * yuv_w] = clamp((157024*r-131488*g-25536*b+45940035)/357510);
356       }
357     }
358   } else {  /* TH_PF_422 */
359     for(y = 0; y < h; y += 1) {
360       for(x = 0; x < w; x += 2) {
361         x1=x+(x+1<w);
362         png_byte r0 = png[y][3 * x + 0];
363         png_byte g0 = png[y][3 * x + 1];
364         png_byte b0 = png[y][3 * x + 2];
365         png_byte r1 = png[y][3 * x1 + 0];
366         png_byte g1 = png[y][3 * x1 + 1];
367         png_byte b1 = png[y][3 * x1 + 2];
368         
369         yuv_y[x  + y * yuv_w] = clamp((65481*r0+128553*g0+24966*b0+4207500)/255000);
370         yuv_y[x1 + y * yuv_w] = clamp((65481*r1+128553*g1+24966*b1+4207500)/255000);
371         
372         yuv_u[(x >> 1) + y * ycbcr[1].stride] =
373           clamp( ((-33488*r0-65744*g0+99232*b0+29032005)/2 +
374                   (-33488*r1-65744*g1+99232*b1+29032005)/2)/225930);
375         yuv_v[(x >> 1) + y * ycbcr[2].stride] =
376           clamp( ((157024*r0-131488*g0-25536*b0+45940035)/2 +
377                   (157024*r1-131488*g1-25536*b1+45940035)/2)/357510);
378       }
379     }    
380   }
381
382 }
383
384 static int
385 png_read(const char *pathname, unsigned int *w, unsigned int *h, th_ycbcr_buffer ycbcr)
386 {
387   FILE *fp;
388   unsigned char header[8];
389   png_structp png_ptr;
390   png_infop info_ptr;
391   png_infop end_ptr;
392   png_bytep row_data;
393   png_bytep *row_pointers;
394   png_color_16p bkgd;
395   png_uint_32 width;
396   png_uint_32 height;
397   unsigned long yuv_w;
398   unsigned long yuv_h;
399   int bit_depth;
400   int color_type;
401   int interlace_type;
402   int compression_type;
403   int filter_method;
404   png_uint_32 y;
405
406   fp = fopen(pathname, "rb");
407   if(!fp) {
408     fprintf(stderr, "%s: error: %s\n",
409       pathname, strerror(errno));
410     return 1;
411   }
412
413   fread(header, 1, 8, fp);
414   if(png_sig_cmp(header, 0, 8)) {
415     fprintf(stderr, "%s: error: %s\n",
416       pathname, "not a PNG");
417     fclose(fp);
418     return 1;
419   }
420
421   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
422     NULL, NULL, NULL);
423   if(!png_ptr) {
424     fprintf(stderr, "%s: error: %s\n",
425       pathname, "couldn't create png read structure");
426     fclose(fp);
427     return 1;
428   }
429
430   info_ptr = png_create_info_struct(png_ptr);
431   if(!info_ptr) {
432     fprintf(stderr, "%s: error: %s\n",
433       pathname, "couldn't create png info structure");
434     png_destroy_read_struct(&png_ptr, NULL, NULL);
435     fclose(fp);
436     return 1;
437   }
438
439   end_ptr = png_create_info_struct(png_ptr);
440   if(!end_ptr) {
441     fprintf(stderr, "%s: error: %s\n",
442       pathname, "couldn't create png info structure");
443     png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
444     fclose(fp);
445     return 1;
446   }
447
448   png_init_io(png_ptr, fp);
449   png_set_sig_bytes(png_ptr, 8);
450   png_read_info(png_ptr, info_ptr);
451   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
452    &interlace_type, &compression_type, &filter_method);
453   png_set_expand(png_ptr);
454   if(bit_depth<8)png_set_packing(png_ptr);
455   if(bit_depth==16)png_set_strip_16(png_ptr);
456   if(!(color_type&PNG_COLOR_MASK_COLOR))png_set_gray_to_rgb(png_ptr);
457   if(png_get_bKGD(png_ptr, info_ptr, &bkgd)){
458     png_set_background(png_ptr, bkgd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
459   }
460   /*Note that color_type 2 and 3 can also have alpha, despite not setting the
461      PNG_COLOR_MASK_ALPHA bit.
462     We always strip it to prevent libpng from overrunning our buffer.*/
463   png_set_strip_alpha(png_ptr);
464
465   row_data = (png_bytep)png_malloc(png_ptr,
466     3*height*width*png_sizeof(*row_data));
467   row_pointers = (png_bytep *)png_malloc(png_ptr,
468     height*png_sizeof(*row_pointers));
469   for(y = 0; y < height; y++) {
470     row_pointers[y] = row_data + y*(3*width);
471   }
472   png_read_image(png_ptr, row_pointers);
473   png_read_end(png_ptr, end_ptr);
474
475   *w = width;
476   *h = height;
477   /* Must hold: yuv_w >= w */
478   yuv_w = (*w + 15) & ~15;
479   /* Must hold: yuv_h >= h */
480   yuv_h = (*h + 15) & ~15;
481
482   /* Do we need to allocate a buffer */
483   if (!ycbcr[0].data){
484     ycbcr[0].width = yuv_w;
485     ycbcr[0].height = yuv_h;
486     ycbcr[0].stride = yuv_w;
487     ycbcr[1].width = (chroma_format == TH_PF_444) ? yuv_w : (yuv_w >> 1);
488     ycbcr[1].stride = ycbcr[1].width;
489     ycbcr[1].height = (chroma_format == TH_PF_420) ? (yuv_h >> 1) : yuv_h;
490     ycbcr[2].width = ycbcr[1].width;
491     ycbcr[2].stride = ycbcr[1].stride;
492     ycbcr[2].height = ycbcr[1].height;
493
494     ycbcr[0].data = malloc(ycbcr[0].stride * ycbcr[0].height);
495     ycbcr[1].data = malloc(ycbcr[1].stride * ycbcr[1].height);
496     ycbcr[2].data = malloc(ycbcr[2].stride * ycbcr[2].height);
497   } else {
498     if ((ycbcr[0].width != yuv_w) || (ycbcr[0].height != yuv_h)){
499       fprintf(stderr, "Input size %lux%lu does not match %dx%d\n", yuv_w,yuv_h,ycbcr[0].width,ycbcr[0].height);
500       exit(1);            
501     }
502   }
503
504   rgb_to_yuv(row_pointers, ycbcr, *w, *h);
505
506   png_free(png_ptr, row_pointers);
507   png_free(png_ptr, row_data);
508   png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr);
509
510   fclose(fp);
511   return 0;
512 }
513
514 static int include_files (const struct dirent *de)
515 {
516   char name[1024];
517   int number = -1;
518   sscanf(de->d_name, input_filter, &number);
519   sprintf(name, input_filter, number);
520   return !strcmp(name, de->d_name);
521 }
522
523 static int ilog(unsigned _v){
524   int ret;
525   for(ret=0;_v;ret++)_v>>=1;
526   return ret;
527 }
528       
529 int
530 main(int argc, char *argv[])
531 {
532   int c,long_option_index;
533   int i, n;
534   char *input_mask;
535   char *input_directory;
536   char *scratch;
537   th_comment       tc;
538   struct dirent **png_files;
539   int soft_target=0;
540   int ret;
541       
542   while(1) {
543
544     c=getopt_long(argc,argv,optstring,options,&long_option_index);
545     if(c == EOF)
546       break;
547
548     switch(c) {
549       case 'h':
550         usage();
551         break;
552       case 'o':
553         option_output = optarg;
554         break;;
555       case 'v':
556         video_quality=rint(atof(optarg)*6.3);
557         if(video_quality<0 || video_quality>63){
558           fprintf(stderr,"Illegal video quality (choose 0 through 10)\n");
559           exit(1);
560         }
561         video_rate=0;
562         break;
563       case 'V':
564         video_rate=rint(atof(optarg)*1000);
565         if(video_rate<1){
566           fprintf(stderr,"Illegal video bitrate (choose > 0 please)\n");
567           exit(1);
568         }
569         video_quality=0;
570        break;
571     case '\1':
572       soft_target=1;
573       break;
574     case 'c':
575       vp3_compatible=1;
576       break;
577     case 'k':
578       keyframe_frequency=rint(atof(optarg));
579       if(keyframe_frequency<1 || keyframe_frequency>2147483647){
580         fprintf(stderr,"Illegal keyframe frequency\n");
581         exit(1);
582       }
583       break;
584
585     case 'd':
586       buf_delay=atoi(optarg);
587       if(buf_delay<=0){
588         fprintf(stderr,"Illegal buffer delay\n");
589         exit(1);
590       }
591       break;
592      case 's':
593        video_aspect_numerator=rint(atof(optarg));
594        break;
595      case 'S':
596        video_aspect_denominator=rint(atof(optarg));
597        break;
598      case 'f':
599        video_fps_numerator=rint(atof(optarg));
600        break;
601      case 'F':
602        video_fps_denominator=rint(atof(optarg));
603        break;
604      case '\5':
605        chroma_format=TH_PF_444;
606        break;
607      case '\6':
608        chroma_format=TH_PF_422;
609        break;
610     case '\2':
611       twopass=3; /* perform both passes */
612       twopass_file=tmpfile();
613       if(!twopass_file){
614         fprintf(stderr,"Unable to open temporary file for twopass data\n");
615         exit(1);
616       }
617       break;
618     case '\3':
619       twopass=1; /* perform first pass */
620       twopass_file=fopen(optarg,"wb");
621       if(!twopass_file){
622         fprintf(stderr,"Unable to open \'%s\' for twopass data\n",optarg);
623         exit(1);
624       }
625       break;
626     case '\4':
627       twopass=2; /* perform second pass */
628       twopass_file=fopen(optarg,"rb");
629       if(!twopass_file){
630         fprintf(stderr,"Unable to open twopass data file \'%s\'",optarg);
631         exit(1);
632       }
633       break;
634      default:
635         usage();
636         break;
637       }
638   }
639
640   if(argc < 3) {
641     usage();
642   }
643
644   if(soft_target){
645     if(video_rate<=0){
646       fprintf(stderr,"Soft rate target (--soft-target) requested without a bitrate (-V).\n");
647       exit(1);
648     }
649     if(video_quality==-1)
650       video_quality=0;
651   }else{
652     if(video_rate>0)
653       video_quality=0;
654     if(video_quality==-1)
655       video_quality=48;
656   }
657
658   if(keyframe_frequency<=0){
659     /*Use a default keyframe frequency of 64 for 1-pass (streaming) mode, and
660        256 for two-pass mode.*/
661     keyframe_frequency=twopass?256:64;
662   }
663
664   input_mask = argv[optind];
665   if (!input_mask) {
666     fprintf(stderr, "no input files specified; run with -h for help.\n");
667     exit(1);
668   }
669   /* dirname and basename must operate on scratch strings */
670   scratch = strdup(input_mask);
671   input_directory = strdup(dirname(scratch));
672   free(scratch);
673   scratch = strdup(input_mask);
674   input_filter = strdup(basename(scratch));
675   free(scratch);
676
677 #ifdef DEBUG
678   fprintf(stderr, "scanning %s with filter '%s'\n",
679   input_directory, input_filter);
680 #endif
681   n = scandir (input_directory, &png_files, include_files, alphasort);
682
683   if (!n) {
684     fprintf(stderr, "no input files found; run with -h for help.\n");
685     exit(1);
686   }
687
688   ogg_fp = fopen(option_output, "wb");
689   if(!ogg_fp) {
690     fprintf(stderr, "%s: error: %s\n",
691       option_output, "couldn't open output file");
692     return 1;
693   }
694
695   srand(time(NULL));
696   if(ogg_stream_init(&ogg_os, rand())) {
697     fprintf(stderr, "%s: error: %s\n",
698       option_output, "couldn't create ogg stream state");
699     return 1;
700   }
701
702   for(passno=(twopass==3?1:twopass);passno<=(twopass==3?2:twopass);passno++){
703     unsigned int w;
704     unsigned int h;
705     char input_png[1024];
706     th_ycbcr_buffer ycbcr;
707
708     ycbcr[0].data = 0;
709     int last = 0;
710
711     snprintf(input_png, 1023,"%s/%s", input_directory, png_files[0]->d_name);
712     if(png_read(input_png, &w, &h, ycbcr)) {
713       fprintf(stderr, "could not read %s\n", input_png);
714       exit(1);
715     }
716
717     if (passno!=2) fprintf(stderr,"%d frames, %dx%d\n",n,w,h);    
718
719     /* setup complete.  Raw processing loop */
720     switch(passno){
721     case 0: case 2:
722       fprintf(stderr,"\rCompressing....                                          \n");
723       break;
724     case 1:
725       fprintf(stderr,"\rScanning first pass....                                  \n");
726       break;
727     }
728
729     fprintf(stderr, "%s\n", input_png); 
730
731     th_info_init(&ti);    
732     ti.frame_width = ((w + 15) >>4)<<4;
733     ti.frame_height = ((h + 15)>>4)<<4;
734     ti.pic_width = w;
735     ti.pic_height = h;
736     ti.pic_x = 0;
737     ti.pic_y = 0;
738     ti.fps_numerator = video_fps_numerator;
739     ti.fps_denominator = video_fps_denominator;
740     ti.aspect_numerator = video_aspect_numerator;
741     ti.aspect_denominator = video_aspect_denominator;
742     ti.colorspace = TH_CS_UNSPECIFIED;
743     ti.pixel_fmt = chroma_format;
744     ti.target_bitrate = video_rate;
745     ti.quality = video_quality;
746     ti.keyframe_granule_shift=ilog(keyframe_frequency-1);
747
748     td=th_encode_alloc(&ti);  
749     th_info_clear(&ti);
750     /* setting just the granule shift only allows power-of-two keyframe
751        spacing.  Set the actual requested spacing. */
752     ret=th_encode_ctl(td,TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
753      &keyframe_frequency,sizeof(keyframe_frequency-1));
754     if(ret<0){
755       fprintf(stderr,"Could not set keyframe interval to %d.\n",(int)keyframe_frequency);
756     }
757     if(vp3_compatible){
758       ret=th_encode_ctl(td,TH_ENCCTL_SET_VP3_COMPATIBLE,&vp3_compatible,
759        sizeof(vp3_compatible));
760       if(ret<0||!vp3_compatible){
761         fprintf(stderr,"Could not enable strict VP3 compatibility.\n");
762         if(ret>=0){
763           fprintf(stderr,"Ensure your source format is supported by VP3.\n");
764           fprintf(stderr,
765            "(4:2:0 pixel format, width and height multiples of 16).\n");
766         }
767       }
768     }
769     if(soft_target){
770       /* reverse the rate control flags to favor a 'long time' strategy */
771       int arg = TH_RATECTL_CAP_UNDERFLOW;
772       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_FLAGS,&arg,sizeof(arg));
773       if(ret<0)
774         fprintf(stderr,"Could not set encoder flags for --soft-target\n");
775       /* Default buffer control is overridden on two-pass */
776       if(!twopass&&buf_delay<0){
777         if((keyframe_frequency*7>>1) > 5*video_fps_numerator/video_fps_denominator)
778           arg=keyframe_frequency*7>>1;
779         else
780           arg=5*video_fps_numerator/video_fps_denominator;
781         ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,&arg,sizeof(arg));
782         if(ret<0)
783           fprintf(stderr,"Could not set rate control buffer for --soft-target\n");
784       }
785     }
786     /* set up two-pass if needed */
787     if(passno==1){
788       unsigned char *buffer;
789       int bytes;
790       bytes=th_encode_ctl(td,TH_ENCCTL_2PASS_OUT,&buffer,sizeof(buffer));
791       if(bytes<0){
792         fprintf(stderr,"Could not set up the first pass of two-pass mode.\n");
793         fprintf(stderr,"Did you remember to specify an estimated bitrate?\n");
794         exit(1);
795       }
796       /*Perform a seek test to ensure we can overwrite this placeholder data at
797          the end; this is better than letting the user sit through a whole
798          encode only to find out their pass 1 file is useless at the end.*/
799       if(fseek(twopass_file,0,SEEK_SET)<0){
800         fprintf(stderr,"Unable to seek in two-pass data file.\n");
801         exit(1);
802       }
803       if(fwrite(buffer,1,bytes,twopass_file)<bytes){
804         fprintf(stderr,"Unable to write to two-pass data file.\n");
805         exit(1);
806       }
807       fflush(twopass_file);
808     }
809     if(passno==2){
810       /*Enable the second pass here.
811         We make this call just to set the encoder into 2-pass mode, because
812          by default enabling two-pass sets the buffer delay to the whole file
813          (because there's no way to explicitly request that behavior).
814         If we waited until we were actually encoding, it would overwite our
815          settings.*/
816       if(th_encode_ctl(td,TH_ENCCTL_2PASS_IN,NULL,0)<0){
817         fprintf(stderr,"Could not set up the second pass of two-pass mode.\n");
818         exit(1);
819       }
820       if(twopass==3){
821         if(fseek(twopass_file,0,SEEK_SET)<0){
822           fprintf(stderr,"Unable to seek in two-pass data file.\n");
823           exit(1);
824         }
825       }
826     }
827     /*Now we can set the buffer delay if the user requested a non-default one
828        (this has to be done after two-pass is enabled).*/
829     if(passno!=1&&buf_delay>=0){
830       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,
831        &buf_delay,sizeof(buf_delay));
832       if(ret<0){
833         fprintf(stderr,"Warning: could not set desired buffer delay.\n");
834       }
835     }
836     /* write the bitstream header packets with proper page interleave */
837     th_comment_init(&tc);
838     /* first packet will get its own page automatically */
839     if(th_encode_flushheader(td,&tc,&op)<=0){
840       fprintf(stderr,"Internal Theora library error.\n");
841       exit(1); 
842     }
843     th_comment_clear(&tc);
844     if(passno!=1){
845       ogg_stream_packetin(&ogg_os,&op);
846       if(ogg_stream_pageout(&ogg_os,&og)!=1){
847         fprintf(stderr,"Internal Ogg library error.\n");
848         exit(1);
849       }
850       fwrite(og.header,1,og.header_len,ogg_fp);
851       fwrite(og.body,1,og.body_len,ogg_fp);
852     }
853     /* create the remaining theora headers */
854     for(;;){
855       ret=th_encode_flushheader(td,&tc,&op);
856       if(ret<0){
857         fprintf(stderr,"Internal Theora library error.\n");
858         exit(1);
859       }
860       else if(!ret)break;
861       if(passno!=1)ogg_stream_packetin(&ogg_os,&op);
862     }
863     /* Flush the rest of our headers. This ensures
864        the actual data in each stream will start
865        on a new page, as per spec. */
866     if(passno!=1){
867       for(;;){
868         int result = ogg_stream_flush(&ogg_os,&og);
869         if(result<0){
870           /* can't get here */
871           fprintf(stderr,"Internal Ogg library error.\n");
872           exit(1);
873         }
874         if(result==0)break;
875         fwrite(og.header,1,og.header_len,ogg_fp);
876         fwrite(og.body,1,og.body_len,ogg_fp);
877       }
878     }
879
880     i=0; last=0;
881     do {
882       if(i >= n-1) last = 1;
883       if(theora_write_frame(ycbcr, last)) {
884           fprintf(stderr,"Encoding error.\n");
885         exit(1);
886       }
887
888       i++;
889       if (!last) {
890         snprintf(input_png, 1023,"%s/%s", input_directory, png_files[i]->d_name);
891         if(png_read(input_png, &w, &h, ycbcr)) {
892           fprintf(stderr, "could not read %s\n", input_png);
893           exit(1);
894         }
895        fprintf(stderr, "%s\n", input_png);
896       }      
897     } while (!last);
898
899     if(passno==1){
900       /* need to read the final (summary) packet */
901       unsigned char *buffer;
902       int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
903       if(bytes<0){
904         fprintf(stderr,"Could not read two-pass summary data from encoder.\n");
905         exit(1);
906       }
907       if(fseek(twopass_file,0,SEEK_SET)<0){
908         fprintf(stderr,"Unable to seek in two-pass data file.\n");
909         exit(1);
910       }
911       if(fwrite(buffer,1,bytes,twopass_file)<bytes){
912         fprintf(stderr,"Unable to write to two-pass data file.\n");
913         exit(1);
914       }
915       fflush(twopass_file);
916     }
917     th_encode_free(td);
918     free(ycbcr[0].data);
919     free(ycbcr[1].data);
920     free(ycbcr[2].data);
921   }
922
923   if(ogg_stream_flush(&ogg_os, &og)) {
924     fwrite(og.header, og.header_len, 1, ogg_fp);
925     fwrite(og.body, og.body_len, 1, ogg_fp);
926   }            
927
928   free(input_directory);
929   free(input_filter);
930
931   while (n--) free(png_files[n]);
932   free(png_files);  
933
934   if(ogg_fp){
935     fflush(ogg_fp);
936     if(ogg_fp!=stdout)fclose(ogg_fp);
937   }
938
939   ogg_stream_clear(&ogg_os);
940   if(twopass_file)fclose(twopass_file);
941   fprintf(stderr,"\r   \ndone.\n\n");
942
943   return 0;
944 }