examples: png_sizeof no longer available (since libpng 1.6)
[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
295   unsigned char *yuv_y;
296   unsigned char *yuv_u;
297   unsigned char *yuv_v;
298
299   yuv_w = ycbcr[0].width;
300
301   yuv_y = ycbcr[0].data;
302   yuv_u = ycbcr[1].data;
303   yuv_v = ycbcr[2].data;
304
305   /*This ignores gamma and RGB primary/whitepoint differences.
306     It also isn't terribly fast (though a decent compiler will
307     strength-reduce the division to a multiplication).*/
308
309   if (chroma_format == TH_PF_420) {
310     for(y = 0; y < h; y += 2) {
311       y1=y+(y+1<h);
312       for(x = 0; x < w; x += 2) {
313         x1=x+(x+1<w);
314         png_byte r0 = png[y][3 * x + 0];
315         png_byte g0 = png[y][3 * x + 1];
316         png_byte b0 = png[y][3 * x + 2];
317         png_byte r1 = png[y][3 * x1 + 0];
318         png_byte g1 = png[y][3 * x1 + 1];
319         png_byte b1 = png[y][3 * x1 + 2];
320         png_byte r2 = png[y1][3 * x + 0];
321         png_byte g2 = png[y1][3 * x + 1];
322         png_byte b2 = png[y1][3 * x + 2];
323         png_byte r3 = png[y1][3 * x1 + 0];
324         png_byte g3 = png[y1][3 * x1 + 1];
325         png_byte b3 = png[y1][3 * x1 + 2];
326
327         yuv_y[x  + y * yuv_w]  = clamp((65481*r0+128553*g0+24966*b0+4207500)/255000);
328         yuv_y[x1 + y * yuv_w]  = clamp((65481*r1+128553*g1+24966*b1+4207500)/255000);
329         yuv_y[x  + y1 * yuv_w] = clamp((65481*r2+128553*g2+24966*b2+4207500)/255000);
330         yuv_y[x1 + y1 * yuv_w] = clamp((65481*r3+128553*g3+24966*b3+4207500)/255000);
331
332         yuv_u[(x >> 1) + (y >> 1) * ycbcr[1].stride] =
333           clamp( ((-33488*r0-65744*g0+99232*b0+29032005)/4 +
334                   (-33488*r0-65744*g0+99232*b0+29032005)/4 +
335                   (-33488*r2-65744*g2+99232*b2+29032005)/4 +
336                   (-33488*r3-65744*g3+99232*b3+29032005)/4)/225930);
337         yuv_v[(x >> 1) + (y >> 1) * ycbcr[2].stride] =
338           clamp( ((157024*r0-131488*g0-25536*b0+45940035)/4 +
339                   (157024*r1-131488*g1-25536*b1+45940035)/4 +
340                   (157024*r2-131488*g2-25536*b2+45940035)/4 +
341                   (157024*r3-131488*g3-25536*b3+45940035)/4)/357510);
342       }
343     }
344   } else if (chroma_format == TH_PF_444) {
345     for(y = 0; y < h; y++) {
346       for(x = 0; x < w; x++) {
347         png_byte r = png[y][3 * x + 0];
348         png_byte g = png[y][3 * x + 1];
349         png_byte b = png[y][3 * x + 2];
350
351         yuv_y[x + y * yuv_w] = clamp((65481*r+128553*g+24966*b+4207500)/255000);
352         yuv_u[x + y * yuv_w] = clamp((-33488*r-65744*g+99232*b+29032005)/225930);
353         yuv_v[x + y * yuv_w] = clamp((157024*r-131488*g-25536*b+45940035)/357510);
354       }
355     }
356   } else {  /* TH_PF_422 */
357     for(y = 0; y < h; y += 1) {
358       for(x = 0; x < w; x += 2) {
359         x1=x+(x+1<w);
360         png_byte r0 = png[y][3 * x + 0];
361         png_byte g0 = png[y][3 * x + 1];
362         png_byte b0 = png[y][3 * x + 2];
363         png_byte r1 = png[y][3 * x1 + 0];
364         png_byte g1 = png[y][3 * x1 + 1];
365         png_byte b1 = png[y][3 * x1 + 2];
366
367         yuv_y[x  + y * yuv_w] = clamp((65481*r0+128553*g0+24966*b0+4207500)/255000);
368         yuv_y[x1 + y * yuv_w] = clamp((65481*r1+128553*g1+24966*b1+4207500)/255000);
369
370         yuv_u[(x >> 1) + y * ycbcr[1].stride] =
371           clamp( ((-33488*r0-65744*g0+99232*b0+29032005)/2 +
372                   (-33488*r1-65744*g1+99232*b1+29032005)/2)/225930);
373         yuv_v[(x >> 1) + y * ycbcr[2].stride] =
374           clamp( ((157024*r0-131488*g0-25536*b0+45940035)/2 +
375                   (157024*r1-131488*g1-25536*b1+45940035)/2)/357510);
376       }
377     }
378   }
379
380 }
381
382 static int
383 png_read(const char *pathname, unsigned int *w, unsigned int *h, th_ycbcr_buffer ycbcr)
384 {
385   FILE *fp;
386   unsigned char header[8];
387   png_structp png_ptr;
388   png_infop info_ptr;
389   png_infop end_ptr;
390   png_bytep row_data;
391   png_bytep *row_pointers;
392   png_color_16p bkgd;
393   png_uint_32 width;
394   png_uint_32 height;
395   unsigned long yuv_w;
396   unsigned long yuv_h;
397   int bit_depth;
398   int color_type;
399   int interlace_type;
400   int compression_type;
401   int filter_method;
402   png_uint_32 y;
403
404   fp = fopen(pathname, "rb");
405   if(!fp) {
406     fprintf(stderr, "%s: error: %s\n",
407       pathname, strerror(errno));
408     return 1;
409   }
410
411   fread(header, 1, 8, fp);
412   if(png_sig_cmp(header, 0, 8)) {
413     fprintf(stderr, "%s: error: %s\n",
414       pathname, "not a PNG");
415     fclose(fp);
416     return 1;
417   }
418
419   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
420     NULL, NULL, NULL);
421   if(!png_ptr) {
422     fprintf(stderr, "%s: error: %s\n",
423       pathname, "couldn't create png read structure");
424     fclose(fp);
425     return 1;
426   }
427
428   info_ptr = png_create_info_struct(png_ptr);
429   if(!info_ptr) {
430     fprintf(stderr, "%s: error: %s\n",
431       pathname, "couldn't create png info structure");
432     png_destroy_read_struct(&png_ptr, NULL, NULL);
433     fclose(fp);
434     return 1;
435   }
436
437   end_ptr = png_create_info_struct(png_ptr);
438   if(!end_ptr) {
439     fprintf(stderr, "%s: error: %s\n",
440       pathname, "couldn't create png info structure");
441     png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
442     fclose(fp);
443     return 1;
444   }
445
446   png_init_io(png_ptr, fp);
447   png_set_sig_bytes(png_ptr, 8);
448   png_read_info(png_ptr, info_ptr);
449   png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
450    &interlace_type, &compression_type, &filter_method);
451   png_set_expand(png_ptr);
452   if(bit_depth<8)png_set_packing(png_ptr);
453   if(bit_depth==16)png_set_strip_16(png_ptr);
454   if(!(color_type&PNG_COLOR_MASK_COLOR))png_set_gray_to_rgb(png_ptr);
455   if(png_get_bKGD(png_ptr, info_ptr, &bkgd)){
456     png_set_background(png_ptr, bkgd, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
457   }
458   /*Note that color_type 2 and 3 can also have alpha, despite not setting the
459      PNG_COLOR_MASK_ALPHA bit.
460     We always strip it to prevent libpng from overrunning our buffer.*/
461   png_set_strip_alpha(png_ptr);
462
463   row_data = (png_bytep)png_malloc(png_ptr,
464     3*height*width*sizeof(*row_data));
465   row_pointers = (png_bytep *)png_malloc(png_ptr,
466     height*sizeof(*row_pointers));
467   for(y = 0; y < height; y++) {
468     row_pointers[y] = row_data + y*(3*width);
469   }
470   png_read_image(png_ptr, row_pointers);
471   png_read_end(png_ptr, end_ptr);
472
473   *w = width;
474   *h = height;
475   /* Must hold: yuv_w >= w */
476   yuv_w = (*w + 15) & ~15;
477   /* Must hold: yuv_h >= h */
478   yuv_h = (*h + 15) & ~15;
479
480   /* Do we need to allocate a buffer */
481   if (!ycbcr[0].data){
482     ycbcr[0].width = yuv_w;
483     ycbcr[0].height = yuv_h;
484     ycbcr[0].stride = yuv_w;
485     ycbcr[1].width = (chroma_format == TH_PF_444) ? yuv_w : (yuv_w >> 1);
486     ycbcr[1].stride = ycbcr[1].width;
487     ycbcr[1].height = (chroma_format == TH_PF_420) ? (yuv_h >> 1) : yuv_h;
488     ycbcr[2].width = ycbcr[1].width;
489     ycbcr[2].stride = ycbcr[1].stride;
490     ycbcr[2].height = ycbcr[1].height;
491
492     ycbcr[0].data = malloc(ycbcr[0].stride * ycbcr[0].height);
493     ycbcr[1].data = malloc(ycbcr[1].stride * ycbcr[1].height);
494     ycbcr[2].data = malloc(ycbcr[2].stride * ycbcr[2].height);
495   } else {
496     if ((ycbcr[0].width != yuv_w) || (ycbcr[0].height != yuv_h)){
497       fprintf(stderr, "Input size %lux%lu does not match %dx%d\n", yuv_w,yuv_h,ycbcr[0].width,ycbcr[0].height);
498       exit(1);
499     }
500   }
501
502   rgb_to_yuv(row_pointers, ycbcr, *w, *h);
503
504   png_free(png_ptr, row_pointers);
505   png_free(png_ptr, row_data);
506   png_destroy_read_struct(&png_ptr, &info_ptr, &end_ptr);
507
508   fclose(fp);
509   return 0;
510 }
511
512 static int include_files (const struct dirent *de)
513 {
514   char name[1024];
515   int number = -1;
516   sscanf(de->d_name, input_filter, &number);
517   sprintf(name, input_filter, number);
518   return !strcmp(name, de->d_name);
519 }
520
521 static int ilog(unsigned _v){
522   int ret;
523   for(ret=0;_v;ret++)_v>>=1;
524   return ret;
525 }
526
527 int
528 main(int argc, char *argv[])
529 {
530   int c,long_option_index;
531   int i, n;
532   char *input_mask;
533   char *input_directory;
534   char *scratch;
535   th_comment       tc;
536   struct dirent **png_files;
537   int soft_target=0;
538   int ret;
539
540   while(1) {
541
542     c=getopt_long(argc,argv,optstring,options,&long_option_index);
543     if(c == EOF)
544       break;
545
546     switch(c) {
547       case 'h':
548         usage();
549         break;
550       case 'o':
551         option_output = optarg;
552         break;;
553       case 'v':
554         video_quality=rint(atof(optarg)*6.3);
555         if(video_quality<0 || video_quality>63){
556           fprintf(stderr,"Illegal video quality (choose 0 through 10)\n");
557           exit(1);
558         }
559         video_rate=0;
560         break;
561       case 'V':
562         video_rate=rint(atof(optarg)*1000);
563         if(video_rate<1){
564           fprintf(stderr,"Illegal video bitrate (choose > 0 please)\n");
565           exit(1);
566         }
567         video_quality=0;
568        break;
569     case '\1':
570       soft_target=1;
571       break;
572     case 'c':
573       vp3_compatible=1;
574       break;
575     case 'k':
576       keyframe_frequency=rint(atof(optarg));
577       if(keyframe_frequency<1 || keyframe_frequency>2147483647){
578         fprintf(stderr,"Illegal keyframe frequency\n");
579         exit(1);
580       }
581       break;
582
583     case 'd':
584       buf_delay=atoi(optarg);
585       if(buf_delay<=0){
586         fprintf(stderr,"Illegal buffer delay\n");
587         exit(1);
588       }
589       break;
590      case 's':
591        video_aspect_numerator=rint(atof(optarg));
592        break;
593      case 'S':
594        video_aspect_denominator=rint(atof(optarg));
595        break;
596      case 'f':
597        video_fps_numerator=rint(atof(optarg));
598        break;
599      case 'F':
600        video_fps_denominator=rint(atof(optarg));
601        break;
602      case '\5':
603        chroma_format=TH_PF_444;
604        break;
605      case '\6':
606        chroma_format=TH_PF_422;
607        break;
608     case '\2':
609       twopass=3; /* perform both passes */
610       twopass_file=tmpfile();
611       if(!twopass_file){
612         fprintf(stderr,"Unable to open temporary file for twopass data\n");
613         exit(1);
614       }
615       break;
616     case '\3':
617       twopass=1; /* perform first pass */
618       twopass_file=fopen(optarg,"wb");
619       if(!twopass_file){
620         fprintf(stderr,"Unable to open \'%s\' for twopass data\n",optarg);
621         exit(1);
622       }
623       break;
624     case '\4':
625       twopass=2; /* perform second pass */
626       twopass_file=fopen(optarg,"rb");
627       if(!twopass_file){
628         fprintf(stderr,"Unable to open twopass data file \'%s\'",optarg);
629         exit(1);
630       }
631       break;
632      default:
633         usage();
634         break;
635       }
636   }
637
638   if(argc < 3) {
639     usage();
640   }
641
642   if(soft_target){
643     if(video_rate<=0){
644       fprintf(stderr,"Soft rate target (--soft-target) requested without a bitrate (-V).\n");
645       exit(1);
646     }
647     if(video_quality==-1)
648       video_quality=0;
649   }else{
650     if(video_rate>0)
651       video_quality=0;
652     if(video_quality==-1)
653       video_quality=48;
654   }
655
656   if(keyframe_frequency<=0){
657     /*Use a default keyframe frequency of 64 for 1-pass (streaming) mode, and
658        256 for two-pass mode.*/
659     keyframe_frequency=twopass?256:64;
660   }
661
662   input_mask = argv[optind];
663   if (!input_mask) {
664     fprintf(stderr, "no input files specified; run with -h for help.\n");
665     exit(1);
666   }
667   /* dirname and basename must operate on scratch strings */
668   scratch = strdup(input_mask);
669   input_directory = strdup(dirname(scratch));
670   free(scratch);
671   scratch = strdup(input_mask);
672   input_filter = strdup(basename(scratch));
673   free(scratch);
674
675 #ifdef DEBUG
676   fprintf(stderr, "scanning %s with filter '%s'\n",
677   input_directory, input_filter);
678 #endif
679   n = scandir (input_directory, &png_files, include_files, alphasort);
680
681   if (!n) {
682     fprintf(stderr, "no input files found; run with -h for help.\n");
683     exit(1);
684   }
685
686   ogg_fp = fopen(option_output, "wb");
687   if(!ogg_fp) {
688     fprintf(stderr, "%s: error: %s\n",
689       option_output, "couldn't open output file");
690     return 1;
691   }
692
693   srand(time(NULL));
694   if(ogg_stream_init(&ogg_os, rand())) {
695     fprintf(stderr, "%s: error: %s\n",
696       option_output, "couldn't create ogg stream state");
697     return 1;
698   }
699
700   for(passno=(twopass==3?1:twopass);passno<=(twopass==3?2:twopass);passno++){
701     unsigned int w;
702     unsigned int h;
703     char input_png[1024];
704     th_ycbcr_buffer ycbcr;
705
706     ycbcr[0].data = 0;
707     int last = 0;
708
709     snprintf(input_png, 1023,"%s/%s", input_directory, png_files[0]->d_name);
710     if(png_read(input_png, &w, &h, ycbcr)) {
711       fprintf(stderr, "could not read %s\n", input_png);
712       exit(1);
713     }
714
715     if (passno!=2) fprintf(stderr,"%d frames, %dx%d\n",n,w,h);
716
717     /* setup complete.  Raw processing loop */
718     switch(passno){
719     case 0: case 2:
720       fprintf(stderr,"\rCompressing....                                          \n");
721       break;
722     case 1:
723       fprintf(stderr,"\rScanning first pass....                                  \n");
724       break;
725     }
726
727     fprintf(stderr, "%s\n", input_png);
728
729     th_info_init(&ti);
730     ti.frame_width = ((w + 15) >>4)<<4;
731     ti.frame_height = ((h + 15)>>4)<<4;
732     ti.pic_width = w;
733     ti.pic_height = h;
734     ti.pic_x = 0;
735     ti.pic_y = 0;
736     ti.fps_numerator = video_fps_numerator;
737     ti.fps_denominator = video_fps_denominator;
738     ti.aspect_numerator = video_aspect_numerator;
739     ti.aspect_denominator = video_aspect_denominator;
740     ti.colorspace = TH_CS_UNSPECIFIED;
741     ti.pixel_fmt = chroma_format;
742     ti.target_bitrate = video_rate;
743     ti.quality = video_quality;
744     ti.keyframe_granule_shift=ilog(keyframe_frequency-1);
745
746     td=th_encode_alloc(&ti);
747     th_info_clear(&ti);
748     /* setting just the granule shift only allows power-of-two keyframe
749        spacing.  Set the actual requested spacing. */
750     ret=th_encode_ctl(td,TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE,
751      &keyframe_frequency,sizeof(keyframe_frequency-1));
752     if(ret<0){
753       fprintf(stderr,"Could not set keyframe interval to %d.\n",(int)keyframe_frequency);
754     }
755     if(vp3_compatible){
756       ret=th_encode_ctl(td,TH_ENCCTL_SET_VP3_COMPATIBLE,&vp3_compatible,
757        sizeof(vp3_compatible));
758       if(ret<0||!vp3_compatible){
759         fprintf(stderr,"Could not enable strict VP3 compatibility.\n");
760         if(ret>=0){
761           fprintf(stderr,"Ensure your source format is supported by VP3.\n");
762           fprintf(stderr,
763            "(4:2:0 pixel format, width and height multiples of 16).\n");
764         }
765       }
766     }
767     if(soft_target){
768       /* reverse the rate control flags to favor a 'long time' strategy */
769       int arg = TH_RATECTL_CAP_UNDERFLOW;
770       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_FLAGS,&arg,sizeof(arg));
771       if(ret<0)
772         fprintf(stderr,"Could not set encoder flags for --soft-target\n");
773       /* Default buffer control is overridden on two-pass */
774       if(!twopass&&buf_delay<0){
775         if((keyframe_frequency*7>>1) > 5*video_fps_numerator/video_fps_denominator)
776           arg=keyframe_frequency*7>>1;
777         else
778           arg=5*video_fps_numerator/video_fps_denominator;
779         ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,&arg,sizeof(arg));
780         if(ret<0)
781           fprintf(stderr,"Could not set rate control buffer for --soft-target\n");
782       }
783     }
784     /* set up two-pass if needed */
785     if(passno==1){
786       unsigned char *buffer;
787       int bytes;
788       bytes=th_encode_ctl(td,TH_ENCCTL_2PASS_OUT,&buffer,sizeof(buffer));
789       if(bytes<0){
790         fprintf(stderr,"Could not set up the first pass of two-pass mode.\n");
791         fprintf(stderr,"Did you remember to specify an estimated bitrate?\n");
792         exit(1);
793       }
794       /*Perform a seek test to ensure we can overwrite this placeholder data at
795          the end; this is better than letting the user sit through a whole
796          encode only to find out their pass 1 file is useless at the end.*/
797       if(fseek(twopass_file,0,SEEK_SET)<0){
798         fprintf(stderr,"Unable to seek in two-pass data file.\n");
799         exit(1);
800       }
801       if(fwrite(buffer,1,bytes,twopass_file)<bytes){
802         fprintf(stderr,"Unable to write to two-pass data file.\n");
803         exit(1);
804       }
805       fflush(twopass_file);
806     }
807     if(passno==2){
808       /*Enable the second pass here.
809         We make this call just to set the encoder into 2-pass mode, because
810          by default enabling two-pass sets the buffer delay to the whole file
811          (because there's no way to explicitly request that behavior).
812         If we waited until we were actually encoding, it would overwite our
813          settings.*/
814       if(th_encode_ctl(td,TH_ENCCTL_2PASS_IN,NULL,0)<0){
815         fprintf(stderr,"Could not set up the second pass of two-pass mode.\n");
816         exit(1);
817       }
818       if(twopass==3){
819         if(fseek(twopass_file,0,SEEK_SET)<0){
820           fprintf(stderr,"Unable to seek in two-pass data file.\n");
821           exit(1);
822         }
823       }
824     }
825     /*Now we can set the buffer delay if the user requested a non-default one
826        (this has to be done after two-pass is enabled).*/
827     if(passno!=1&&buf_delay>=0){
828       ret=th_encode_ctl(td,TH_ENCCTL_SET_RATE_BUFFER,
829        &buf_delay,sizeof(buf_delay));
830       if(ret<0){
831         fprintf(stderr,"Warning: could not set desired buffer delay.\n");
832       }
833     }
834     /* write the bitstream header packets with proper page interleave */
835     th_comment_init(&tc);
836     /* first packet will get its own page automatically */
837     if(th_encode_flushheader(td,&tc,&op)<=0){
838       fprintf(stderr,"Internal Theora library error.\n");
839       exit(1);
840     }
841     th_comment_clear(&tc);
842     if(passno!=1){
843       ogg_stream_packetin(&ogg_os,&op);
844       if(ogg_stream_pageout(&ogg_os,&og)!=1){
845         fprintf(stderr,"Internal Ogg library error.\n");
846         exit(1);
847       }
848       fwrite(og.header,1,og.header_len,ogg_fp);
849       fwrite(og.body,1,og.body_len,ogg_fp);
850     }
851     /* create the remaining theora headers */
852     for(;;){
853       ret=th_encode_flushheader(td,&tc,&op);
854       if(ret<0){
855         fprintf(stderr,"Internal Theora library error.\n");
856         exit(1);
857       }
858       else if(!ret)break;
859       if(passno!=1)ogg_stream_packetin(&ogg_os,&op);
860     }
861     /* Flush the rest of our headers. This ensures
862        the actual data in each stream will start
863        on a new page, as per spec. */
864     if(passno!=1){
865       for(;;){
866         int result = ogg_stream_flush(&ogg_os,&og);
867         if(result<0){
868           /* can't get here */
869           fprintf(stderr,"Internal Ogg library error.\n");
870           exit(1);
871         }
872         if(result==0)break;
873         fwrite(og.header,1,og.header_len,ogg_fp);
874         fwrite(og.body,1,og.body_len,ogg_fp);
875       }
876     }
877
878     i=0; last=0;
879     do {
880       if(i >= n-1) last = 1;
881       if(theora_write_frame(ycbcr, last)) {
882           fprintf(stderr,"Encoding error.\n");
883         exit(1);
884       }
885
886       i++;
887       if (!last) {
888         snprintf(input_png, 1023,"%s/%s", input_directory, png_files[i]->d_name);
889         if(png_read(input_png, &w, &h, ycbcr)) {
890           fprintf(stderr, "could not read %s\n", input_png);
891           exit(1);
892         }
893        fprintf(stderr, "%s\n", input_png);
894       }
895     } while (!last);
896
897     if(passno==1){
898       /* need to read the final (summary) packet */
899       unsigned char *buffer;
900       int bytes = th_encode_ctl(td, TH_ENCCTL_2PASS_OUT, &buffer, sizeof(buffer));
901       if(bytes<0){
902         fprintf(stderr,"Could not read two-pass summary data from encoder.\n");
903         exit(1);
904       }
905       if(fseek(twopass_file,0,SEEK_SET)<0){
906         fprintf(stderr,"Unable to seek in two-pass data file.\n");
907         exit(1);
908       }
909       if(fwrite(buffer,1,bytes,twopass_file)<bytes){
910         fprintf(stderr,"Unable to write to two-pass data file.\n");
911         exit(1);
912       }
913       fflush(twopass_file);
914     }
915     th_encode_free(td);
916     free(ycbcr[0].data);
917     free(ycbcr[1].data);
918     free(ycbcr[2].data);
919   }
920
921   if(ogg_stream_flush(&ogg_os, &og)) {
922     fwrite(og.header, og.header_len, 1, ogg_fp);
923     fwrite(og.body, og.body_len, 1, ogg_fp);
924   }
925
926   free(input_directory);
927   free(input_filter);
928
929   while (n--) free(png_files[n]);
930   free(png_files);
931
932   if(ogg_fp){
933     fflush(ogg_fp);
934     if(ogg_fp!=stdout)fclose(ogg_fp);
935   }
936
937   ogg_stream_clear(&ogg_os);
938   if(twopass_file)fclose(twopass_file);
939   fprintf(stderr,"\r   \ndone.\n\n");
940
941   return 0;
942 }