spec: Use %license macro to copy license
[platform/upstream/libtheora.git] / examples / player_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 SDL player application; plays Ogg Theora files (with
14             optional Vorbis audio second stream)
15   last mod: $Id: player_example.c 16551 2009-09-09 17:53:13Z gmaxwell $
16
17  ********************************************************************/
18
19 /* far more complex than most Ogg 'example' programs.  The complexity
20    of maintaining A/V sync is pretty much unavoidable.  It's necessary
21    to actually have audio/video playback to make the hard audio clock
22    sync actually work.  If there's audio playback, there might as well
23    be simple video playback as well...
24
25    A simple 'demux and write back streams' would have been easier,
26    it's true. */
27
28 #if !defined(_GNU_SOURCE)
29 #define _GNU_SOURCE
30 #endif
31 #if !defined(_LARGEFILE_SOURCE)
32 #define _LARGEFILE_SOURCE
33 #endif
34 #if !defined(_LARGEFILE64_SOURCE)
35 #define _LARGEFILE64_SOURCE
36 #endif
37 #if !defined(_FILE_OFFSET_BITS)
38 #define _FILE_OFFSET_BITS 64
39 #endif
40
41 #ifdef HAVE_CONFIG_H
42 # include <config.h>
43 #endif
44
45 #ifndef _REENTRANT
46 # define _REENTRANT
47 #endif
48
49 #include <stdio.h>
50 #include <unistd.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <sys/time.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 #include <fcntl.h>
57 #include <math.h>
58 #include <signal.h>
59 #include "theora/theoradec.h"
60 #include "vorbis/codec.h"
61 #include <SDL.h>
62
63 /* yes, this makes us OSS-specific for now. None of SDL, libao, libao2
64    give us any way to determine hardware timing, and since the
65    hard/kernel buffer is going to be most of or > a second, that's
66    just a little bit important */
67 #if defined(__FreeBSD__)
68 #include <machine/soundcard.h>
69 #define AUDIO_DEVICE "/dev/audio"
70 #elif defined(__NetBSD__) || defined(__OpenBSD__)
71 #include <soundcard.h>
72 #define AUDIO_DEVICE "/dev/audio"
73 #else
74 #include <sys/soundcard.h>
75 #define AUDIO_DEVICE "/dev/dsp"
76 #endif
77 #include <sys/ioctl.h>
78
79 /* Helper; just grab some more compressed bitstream and sync it for
80    page extraction */
81 int buffer_data(FILE *in,ogg_sync_state *oy){
82   char *buffer=ogg_sync_buffer(oy,4096);
83   int bytes=fread(buffer,1,4096,in);
84   ogg_sync_wrote(oy,bytes);
85   return(bytes);
86 }
87
88 /* never forget that globals are a one-way ticket to Hell */
89 /* Ogg and codec state for demux/decode */
90 ogg_sync_state   oy;
91 ogg_page         og;
92 ogg_stream_state vo;
93 ogg_stream_state to;
94 th_info      ti;
95 th_comment   tc;
96 th_dec_ctx       *td;
97 th_setup_info    *ts;
98 vorbis_info      vi;
99 vorbis_dsp_state vd;
100 vorbis_block     vb;
101 vorbis_comment   vc;
102 th_pixel_fmt     px_fmt;
103
104 int              theora_p=0;
105 int              vorbis_p=0;
106 int              stateflag=0;
107
108 /* SDL Video playback structures */
109 SDL_Surface *screen;
110 SDL_Overlay *yuv_overlay;
111 SDL_Rect rect;
112
113 /* single frame video buffering */
114 int          videobuf_ready=0;
115 ogg_int64_t  videobuf_granulepos=-1;
116 double       videobuf_time=0;
117
118 /* single audio fragment audio buffering */
119 int          audiobuf_fill=0;
120 int          audiobuf_ready=0;
121 ogg_int16_t *audiobuf;
122 ogg_int64_t  audiobuf_granulepos=0; /* time position of last sample */
123
124 /* audio / video synchronization tracking:
125
126 Since this will make it to Google at some point and lots of people
127 search for how to do this, a quick rundown of a practical A/V sync
128 strategy under Linux [the UNIX where Everything Is Hard].  Naturally,
129 this works on other platforms using OSS for sound as well.
130
131 In OSS, we don't have reliable access to any precise information on
132 the exact current playback position (that, of course would have been
133 too easy; the kernel folks like to keep us app people working hard
134 doing simple things that should have been solved once and abstracted
135 long ago).  Hopefully ALSA solves this a little better; we'll probably
136 use that once ALSA is the standard in the stable kernel.
137
138 We can't use the system clock for a/v sync because audio is hard
139 synced to its own clock, and both the system and audio clocks suffer
140 from wobble, drift, and a lack of accuracy that can be guaranteed to
141 add a reliable percent or so of error.  After ten seconds, that's
142 100ms.  We can't drift by half a second every minute.
143
144 Although OSS can't generally tell us where the audio playback pointer
145 is, we do know that if we work in complete audio fragments and keep
146 the kernel buffer full, a blocking select on the audio buffer will
147 give us a writable fragment immediately after playback finishes with
148 it.  We assume at that point that we know the exact number of bytes in
149 the kernel buffer that have not been played (total fragments minus
150 one) and calculate clock drift between audio and system then (and only
151 then).  Damp the sync correction fraction, apply, and walla: A
152 reliable A/V clock that even works if it's interrupted. */
153
154 long         audiofd_totalsize=-1;
155 int          audiofd_fragsize;      /* read and write only complete fragments
156                                        so that SNDCTL_DSP_GETOSPACE is
157                                        accurate immediately after a bank
158                                        switch */
159 int          audiofd=-1;
160 ogg_int64_t  audiofd_timer_calibrate=-1;
161
162 static void open_audio(){
163   audio_buf_info info;
164   int format=AFMT_S16_NE; /* host endian */
165   int channels=vi.channels;
166   int rate=vi.rate;
167   int ret;
168
169   audiofd=open(AUDIO_DEVICE,O_RDWR);
170   if(audiofd<0){
171     fprintf(stderr,"Could not open audio device " AUDIO_DEVICE ".\n");
172     exit(1);
173   }
174
175   ret=ioctl(audiofd,SNDCTL_DSP_SETFMT,&format);
176   if(ret){
177     fprintf(stderr,"Could not set 16 bit host-endian playback\n");
178     exit(1);
179   }
180
181   ret=ioctl(audiofd,SNDCTL_DSP_CHANNELS,&channels);
182   if(ret){
183     fprintf(stderr,"Could not set %d channel playback\n",channels);
184     exit(1);
185   }
186
187   ret=ioctl(audiofd,SNDCTL_DSP_SPEED,&rate);
188   if(ret){
189     fprintf(stderr,"Could not set %d Hz playback\n",rate);
190     exit(1);
191   }
192
193   ioctl(audiofd,SNDCTL_DSP_GETOSPACE,&info);
194   audiofd_fragsize=info.fragsize;
195   audiofd_totalsize=info.fragstotal*info.fragsize;
196
197   audiobuf=malloc(audiofd_fragsize);
198 }
199
200 static void audio_close(void){
201   if(audiofd>-1){
202     ioctl(audiofd,SNDCTL_DSP_RESET,NULL);
203     close(audiofd);
204     free(audiobuf);
205   }
206 }
207
208 /* call this only immediately after unblocking from a full kernel
209    having a newly empty fragment or at the point of DMA restart */
210 void audio_calibrate_timer(int restart){
211   struct timeval tv;
212   ogg_int64_t current_sample;
213   ogg_int64_t new_time;
214
215   gettimeofday(&tv,0);
216   new_time=tv.tv_sec*1000+tv.tv_usec/1000;
217
218   if(restart){
219     current_sample=audiobuf_granulepos-audiobuf_fill/2/vi.channels;
220   }else
221     current_sample=audiobuf_granulepos-
222       (audiobuf_fill+audiofd_totalsize-audiofd_fragsize)/2/vi.channels;
223
224   new_time-=1000*current_sample/vi.rate;
225
226   audiofd_timer_calibrate=new_time;
227 }
228
229 /* get relative time since beginning playback, compensating for A/V
230    drift */
231 double get_time(){
232   static ogg_int64_t last=0;
233   static ogg_int64_t up=0;
234   ogg_int64_t now;
235   struct timeval tv;
236
237   gettimeofday(&tv,0);
238   now=tv.tv_sec*1000+tv.tv_usec/1000;
239
240   if(audiofd_timer_calibrate==-1)audiofd_timer_calibrate=last=now;
241
242   if(audiofd<0){
243     /* no audio timer to worry about, we can just use the system clock */
244     /* only one complication: If the process is suspended, we should
245        reset timing to account for the gap in play time.  Do it the
246        easy/hack way */
247     if(now-last>1000)audiofd_timer_calibrate+=(now-last);
248     last=now;
249   }
250
251   if(now-up>200){
252     double timebase=(now-audiofd_timer_calibrate)*.001;
253     int hundredths=timebase*100-(long)timebase*100;
254     int seconds=(long)timebase%60;
255     int minutes=((long)timebase/60)%60;
256     int hours=(long)timebase/3600;
257
258     fprintf(stderr,"   Playing: %d:%02d:%02d.%02d                       \r",
259             hours,minutes,seconds,hundredths);
260     up=now;
261   }
262
263   return (now-audiofd_timer_calibrate)*.001;
264
265 }
266
267 /* write a fragment to the OSS kernel audio API, but only if we can
268    stuff in a whole fragment without blocking */
269 void audio_write_nonblocking(void){
270
271   if(audiobuf_ready){
272     audio_buf_info info;
273     long bytes;
274
275     ioctl(audiofd,SNDCTL_DSP_GETOSPACE,&info);
276     bytes=info.bytes;
277     if(bytes>=audiofd_fragsize){
278       if(bytes==audiofd_totalsize)audio_calibrate_timer(1);
279
280       while(1){
281         bytes=write(audiofd,audiobuf+(audiofd_fragsize-audiobuf_fill),
282                     audiofd_fragsize);
283
284         if(bytes>0){
285
286           if(bytes!=audiobuf_fill){
287             /* shouldn't actually be possible... but eh */
288             audiobuf_fill-=bytes;
289           }else
290             break;
291         }
292       }
293
294       audiobuf_fill=0;
295       audiobuf_ready=0;
296
297     }
298   }
299 }
300
301 /* clean quit on Ctrl-C for SDL and thread shutdown as per SDL example
302    (we don't use any threads, but libSDL does) */
303 int got_sigint=0;
304 static void sigint_handler (int signal) {
305   got_sigint = 1;
306 }
307
308 static void open_video(void){
309   int w;
310   int h;
311   w=(ti.pic_x+ti.frame_width+1&~1)-(ti.pic_x&~1);
312   h=(ti.pic_y+ti.frame_height+1&~1)-(ti.pic_y&~1);
313   if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
314     fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
315     exit(1);
316   }
317
318   screen = SDL_SetVideoMode(w, h, 0, SDL_SWSURFACE);
319   if ( screen == NULL ) {
320     fprintf(stderr, "Unable to set %dx%d video: %s\n",
321             w,h,SDL_GetError());
322     exit(1);
323   }
324
325   if (px_fmt==TH_PF_422)
326     yuv_overlay = SDL_CreateYUVOverlay(w, h,
327                                      SDL_YUY2_OVERLAY,
328                                      screen);
329   else
330     yuv_overlay = SDL_CreateYUVOverlay(w, h,
331                                      SDL_YV12_OVERLAY,
332                                      screen);
333   
334   if ( yuv_overlay == NULL ) {
335     fprintf(stderr, "SDL: Couldn't create SDL_yuv_overlay: %s\n",
336             SDL_GetError());
337     exit(1);
338   }
339   rect.x = 0;
340   rect.y = 0;
341   rect.w = w;
342   rect.h = h;
343
344   SDL_DisplayYUVOverlay(yuv_overlay, &rect);
345 }
346
347 static void video_write(void){
348   int i;
349   th_ycbcr_buffer yuv;
350   int y_offset, uv_offset;
351   th_decode_ycbcr_out(td,yuv);
352   /* Lock SDL_yuv_overlay */
353   if ( SDL_MUSTLOCK(screen) ) {
354     if ( SDL_LockSurface(screen) < 0 ) return;
355   }
356   if (SDL_LockYUVOverlay(yuv_overlay) < 0) return;
357
358   /* let's draw the data on a SDL screen (*screen) */
359   /* deal with border stride */
360   /* reverse u and v for SDL */
361   /* and crop input properly, respecting the encoded frame rect */
362   /* problems may exist for odd frame rect for some encodings */
363
364   y_offset=(ti.pic_x&~1)+yuv[0].stride*(ti.pic_y&~1);
365
366   if (px_fmt==TH_PF_422) {
367     uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y);
368     /* SDL doesn't have a planar 4:2:2 */ 
369     for(i=0;i<yuv_overlay->h;i++) {
370       int j;
371       char *in_y  = (char *)yuv[0].data+y_offset+yuv[0].stride*i;
372       char *out = (char *)(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i);
373       for (j=0;j<yuv_overlay->w;j++)
374         out[j*2] = in_y[j];
375       char *in_u  = (char *)yuv[1].data+uv_offset+yuv[1].stride*i;
376       char *in_v  = (char *)yuv[2].data+uv_offset+yuv[2].stride*i;
377       for (j=0;j<yuv_overlay->w>>1;j++) {
378         out[j*4+1] = in_u[j];
379         out[j*4+3] = in_v[j];
380       }
381     }
382   } else {
383     uv_offset=(ti.pic_x/2)+(yuv[1].stride)*(ti.pic_y/2);
384     for(i=0;i<yuv_overlay->h;i++)
385       memcpy(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i,
386            yuv[0].data+y_offset+yuv[0].stride*i,
387            yuv_overlay->w);
388     for(i=0;i<yuv_overlay->h/2;i++){
389       memcpy(yuv_overlay->pixels[1]+yuv_overlay->pitches[1]*i,
390            yuv[2].data+uv_offset+yuv[2].stride*i,
391            yuv_overlay->w/2);
392       memcpy(yuv_overlay->pixels[2]+yuv_overlay->pitches[2]*i,
393            yuv[1].data+uv_offset+yuv[1].stride*i,
394            yuv_overlay->w/2);
395     }
396   }
397
398   /* Unlock SDL_yuv_overlay */
399   if ( SDL_MUSTLOCK(screen) ) {
400     SDL_UnlockSurface(screen);
401   }
402   SDL_UnlockYUVOverlay(yuv_overlay);
403
404
405   /* Show, baby, show! */
406   SDL_DisplayYUVOverlay(yuv_overlay, &rect);
407
408 }
409 /* dump the theora (or vorbis) comment header */
410 static int dump_comments(th_comment *tc){
411   int i, len;
412   char *value;
413   FILE *out=stdout;
414
415   fprintf(out,"Encoded by %s\n",tc->vendor);
416   if(tc->comments){
417     fprintf(out, "theora comment header:\n");
418     for(i=0;i<tc->comments;i++){
419       if(tc->user_comments[i]){
420         len=tc->comment_lengths[i];
421         value=malloc(len+1);
422         memcpy(value,tc->user_comments[i],len);
423         value[len]='\0';
424         fprintf(out, "\t%s\n", value);
425         free(value);
426       }
427     }
428   }
429   return(0);
430 }
431
432 /* Report the encoder-specified colorspace for the video, if any.
433    We don't actually make use of the information in this example;
434    a real player should attempt to perform color correction for
435    whatever display device it supports. */
436 static void report_colorspace(th_info *ti)
437 {
438     switch(ti->colorspace){
439       case TH_CS_UNSPECIFIED:
440         /* nothing to report */
441         break;;
442       case TH_CS_ITU_REC_470M:
443         fprintf(stderr,"  encoder specified ITU Rec 470M (NTSC) color.\n");
444         break;;
445       case TH_CS_ITU_REC_470BG:
446         fprintf(stderr,"  encoder specified ITU Rec 470BG (PAL) color.\n");
447         break;;
448       default:
449         fprintf(stderr,"warning: encoder specified unknown colorspace (%d).\n",
450             ti->colorspace);
451         break;;
452     }
453 }
454
455 /* helper: push a page into the appropriate steam */
456 /* this can be done blindly; a stream won't accept a page
457                 that doesn't belong to it */
458 static int queue_page(ogg_page *page){
459   if(theora_p)ogg_stream_pagein(&to,page);
460   if(vorbis_p)ogg_stream_pagein(&vo,page);
461   return 0;
462 }
463
464 static void usage(void){
465   fprintf(stderr,
466           "Usage: player_example <file.ogv>\n"
467           "input is read from stdin if no file is passed on the command line\n"
468           "\n"
469   );
470 }
471
472 int main(int argc,char *const *argv){
473
474   int pp_level_max;
475   int pp_level;
476   int pp_inc;
477   int i,j;
478   ogg_packet op;
479
480   FILE *infile = stdin;
481
482   int frames = 0;
483   int dropped = 0;
484
485 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
486   /* Beware the evil ifdef. We avoid these where we can, but this one we
487      cannot. Don't add any more, you'll probably go to hell if you do. */
488   _setmode( _fileno( stdin ), _O_BINARY );
489 #endif
490
491   /* open the input file if any */
492   if(argc==2){
493     infile=fopen(argv[1],"rb");
494     if(infile==NULL){
495       fprintf(stderr,"Unable to open '%s' for playback.\n", argv[1]);
496       exit(1);
497     }
498   }
499   if(argc>2){
500       usage();
501       exit(1);
502   }
503
504   /* start up Ogg stream synchronization layer */
505   ogg_sync_init(&oy);
506
507   /* init supporting Vorbis structures needed in header parsing */
508   vorbis_info_init(&vi);
509   vorbis_comment_init(&vc);
510
511   /* init supporting Theora structures needed in header parsing */
512   th_comment_init(&tc);
513   th_info_init(&ti);
514
515   /* Ogg file open; parse the headers */
516   /* Only interested in Vorbis/Theora streams */
517   while(!stateflag){
518     int ret=buffer_data(infile,&oy);
519     if(ret==0)break;
520     while(ogg_sync_pageout(&oy,&og)>0){
521       ogg_stream_state test;
522
523       /* is this a mandated initial header? If not, stop parsing */
524       if(!ogg_page_bos(&og)){
525         /* don't leak the page; get it into the appropriate stream */
526         queue_page(&og);
527         stateflag=1;
528         break;
529       }
530
531       ogg_stream_init(&test,ogg_page_serialno(&og));
532       ogg_stream_pagein(&test,&og);
533       ogg_stream_packetout(&test,&op);
534
535
536       /* identify the codec: try theora */
537       if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){
538         /* it is theora */
539         memcpy(&to,&test,sizeof(test));
540         theora_p=1;
541       }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
542         /* it is vorbis */
543         memcpy(&vo,&test,sizeof(test));
544         vorbis_p=1;
545       }else{
546         /* whatever it is, we don't care about it */
547         ogg_stream_clear(&test);
548       }
549     }
550     /* fall through to non-bos page parsing */
551   }
552
553   /* we're expecting more header packets. */
554   while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
555     int ret;
556
557     /* look for further theora headers */
558     while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
559       if(ret<0){
560         fprintf(stderr,"Error parsing Theora stream headers; "
561          "corrupt stream?\n");
562         exit(1);
563       }
564       if(!th_decode_headerin(&ti,&tc,&ts,&op)){
565         fprintf(stderr,"Error parsing Theora stream headers; "
566          "corrupt stream?\n");
567         exit(1);
568       }
569       theora_p++;
570     }
571
572     /* look for more vorbis header packets */
573     while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){
574       if(ret<0){
575         fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
576         exit(1);
577       }
578       if(vorbis_synthesis_headerin(&vi,&vc,&op)){
579         fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
580         exit(1);
581       }
582       vorbis_p++;
583       if(vorbis_p==3)break;
584     }
585
586     /* The header pages/packets will arrive before anything else we
587        care about, or the stream is not obeying spec */
588
589     if(ogg_sync_pageout(&oy,&og)>0){
590       queue_page(&og); /* demux into the appropriate stream */
591     }else{
592       int ret=buffer_data(infile,&oy); /* someone needs more data */
593       if(ret==0){
594         fprintf(stderr,"End of file while searching for codec headers.\n");
595         exit(1);
596       }
597     }
598   }
599
600   /* and now we have it all.  initialize decoders */
601   if(theora_p){
602     td=th_decode_alloc(&ti,ts);
603     printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
604            to.serialno,ti.pic_width,ti.pic_height,
605            (double)ti.fps_numerator/ti.fps_denominator);
606     px_fmt=ti.pixel_fmt;
607     switch(ti.pixel_fmt){
608       case TH_PF_420: printf(" 4:2:0 video\n"); break;
609       case TH_PF_422: printf(" 4:2:2 video\n"); break;
610       case TH_PF_444: printf(" 4:4:4 video\n"); break;
611       case TH_PF_RSVD:
612       default:
613        printf(" video\n  (UNKNOWN Chroma sampling!)\n");
614        break;
615     }
616     if(ti.pic_width!=ti.frame_width || ti.pic_height!=ti.frame_height)
617       printf("  Frame content is %dx%d with offset (%d,%d).\n",
618            ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y);
619     report_colorspace(&ti);
620     dump_comments(&tc);
621     th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
622      sizeof(pp_level_max));
623     pp_level=pp_level_max;
624     th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
625     pp_inc=0;
626
627     /*{
628       int arg = 0xffff;
629       th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
630       th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
631       th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg));
632       arg=10;
633       th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg));
634     }*/
635   }else{
636     /* tear down the partial theora setup */
637     th_info_clear(&ti);
638     th_comment_clear(&tc);
639   }
640   
641   th_setup_free(ts);
642   
643   if(vorbis_p){
644     vorbis_synthesis_init(&vd,&vi);
645     vorbis_block_init(&vd,&vb);
646     fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
647             vo.serialno,vi.channels,vi.rate);
648   }else{
649     /* tear down the partial vorbis setup */
650     vorbis_info_clear(&vi);
651     vorbis_comment_clear(&vc);
652   }
653
654   /* open audio */
655   if(vorbis_p)open_audio();
656
657   /* open video */
658   if(theora_p)open_video();
659
660   /* install signal handler as SDL clobbered the default */
661   signal (SIGINT, sigint_handler);
662
663   /* on to the main decode loop.  We assume in this example that audio
664      and video start roughly together, and don't begin playback until
665      we have a start frame for both.  This is not necessarily a valid
666      assumption in Ogg A/V streams! It will always be true of the
667      example_encoder (and most streams) though. */
668
669   stateflag=0; /* playback has not begun */
670   while(!got_sigint){
671
672     /* we want a video and audio frame ready to go at all times.  If
673        we have to buffer incoming, buffer the compressed data (ie, let
674        ogg do the buffering) */
675     while(vorbis_p && !audiobuf_ready){
676       int ret;
677       float **pcm;
678
679       /* if there's pending, decoded audio, grab it */
680       if((ret=vorbis_synthesis_pcmout(&vd,&pcm))>0){
681         int count=audiobuf_fill/2;
682         int maxsamples=(audiofd_fragsize-audiobuf_fill)/2/vi.channels;
683         for(i=0;i<ret && i<maxsamples;i++)
684           for(j=0;j<vi.channels;j++){
685             int val=rint(pcm[j][i]*32767.f);
686             if(val>32767)val=32767;
687             if(val<-32768)val=-32768;
688             audiobuf[count++]=val;
689           }
690         vorbis_synthesis_read(&vd,i);
691         audiobuf_fill+=i*vi.channels*2;
692         if(audiobuf_fill==audiofd_fragsize)audiobuf_ready=1;
693         if(vd.granulepos>=0)
694           audiobuf_granulepos=vd.granulepos-ret+i;
695         else
696           audiobuf_granulepos+=i;
697
698       }else{
699
700         /* no pending audio; is there a pending packet to decode? */
701         if(ogg_stream_packetout(&vo,&op)>0){
702           if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
703             vorbis_synthesis_blockin(&vd,&vb);
704         }else   /* we need more data; break out to suck in another page */
705           break;
706       }
707     }
708
709     while(theora_p && !videobuf_ready){
710       /* theora is one in, one out... */
711       if(ogg_stream_packetout(&to,&op)>0){
712
713         if(pp_inc){
714           pp_level+=pp_inc;
715           th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,
716            sizeof(pp_level));
717           pp_inc=0;
718         }
719         /*HACK: This should be set after a seek or a gap, but we might not have
720            a granulepos for the first packet (we only have them for the last
721            packet on a page), so we just set it as often as we get it.
722           To do this right, we should back-track from the last packet on the
723            page and compute the correct granulepos for the first packet after
724            a seek or a gap.*/
725         if(op.granulepos>=0){
726           th_decode_ctl(td,TH_DECCTL_SET_GRANPOS,&op.granulepos,
727            sizeof(op.granulepos));
728         }
729         if(th_decode_packetin(td,&op,&videobuf_granulepos)==0){
730           videobuf_time=th_granule_time(td,videobuf_granulepos);
731           frames++;
732
733           /* is it already too old to be useful?  This is only actually
734              useful cosmetically after a SIGSTOP.  Note that we have to
735              decode the frame even if we don't show it (for now) due to
736              keyframing.  Soon enough libtheora will be able to deal
737              with non-keyframe seeks.  */
738
739           if(videobuf_time>=get_time())
740             videobuf_ready=1;
741           else{
742             /*If we are too slow, reduce the pp level.*/
743             pp_inc=pp_level>0?-1:0;
744             dropped++;
745           }
746         }
747
748       }else
749         break;
750     }
751
752     if(!videobuf_ready && !audiobuf_ready && feof(infile))break;
753
754     if(!videobuf_ready || !audiobuf_ready){
755       /* no data yet for somebody.  Grab another page */
756       buffer_data(infile,&oy);
757       while(ogg_sync_pageout(&oy,&og)>0){
758         queue_page(&og);
759       }
760     }
761
762     /* If playback has begun, top audio buffer off immediately. */
763     if(stateflag) audio_write_nonblocking();
764
765     /* are we at or past time for this video frame? */
766     if(stateflag && videobuf_ready && videobuf_time<=get_time()){
767       video_write();
768       videobuf_ready=0;
769     }
770
771     if(stateflag &&
772        (audiobuf_ready || !vorbis_p) &&
773        (videobuf_ready || !theora_p) &&
774        !got_sigint){
775       /* we have an audio frame ready (which means the audio buffer is
776          full), it's not time to play video, so wait until one of the
777          audio buffer is ready or it's near time to play video */
778
779       /* set up select wait on the audiobuffer and a timeout for video */
780       struct timeval timeout;
781       fd_set writefs;
782       fd_set empty;
783       int n=0;
784
785       FD_ZERO(&writefs);
786       FD_ZERO(&empty);
787       if(audiofd>=0){
788         FD_SET(audiofd,&writefs);
789         n=audiofd+1;
790       }
791
792       if(theora_p){
793         double tdiff;
794         long milliseconds;
795         tdiff=videobuf_time-get_time();
796         /*If we have lots of extra time, increase the post-processing level.*/
797         if(tdiff>ti.fps_denominator*0.25/ti.fps_numerator){
798           pp_inc=pp_level<pp_level_max?1:0;
799         }
800         else if(tdiff<ti.fps_denominator*0.05/ti.fps_numerator){
801           pp_inc=pp_level>0?-1:0;
802         }
803         milliseconds=tdiff*1000-5;
804         if(milliseconds>500)milliseconds=500;
805         if(milliseconds>0){
806           timeout.tv_sec=milliseconds/1000;
807           timeout.tv_usec=(milliseconds%1000)*1000;
808
809           n=select(n,&empty,&writefs,&empty,&timeout);
810           if(n)audio_calibrate_timer(0);
811         }
812       }else{
813         select(n,&empty,&writefs,&empty,NULL);
814       }
815     }
816
817     /* if our buffers either don't exist or are ready to go,
818        we can begin playback */
819     if((!theora_p || videobuf_ready) &&
820        (!vorbis_p || audiobuf_ready))stateflag=1;
821     /* same if we've run out of input */
822     if(feof(infile))stateflag=1;
823
824   }
825
826   /* tear it all down */
827
828   audio_close();
829   SDL_Quit();
830
831   if(vorbis_p){
832     ogg_stream_clear(&vo);
833     vorbis_block_clear(&vb);
834     vorbis_dsp_clear(&vd);
835     vorbis_comment_clear(&vc);
836     vorbis_info_clear(&vi);
837   }
838   if(theora_p){
839     ogg_stream_clear(&to);
840     th_decode_free(td);
841     th_comment_clear(&tc);
842     th_info_clear(&ti);
843   }
844   ogg_sync_clear(&oy);
845
846   if(infile && infile!=stdin)fclose(infile);
847
848   fprintf(stderr,
849           "\r                                                             \r");
850   fprintf(stderr, "%d frames", frames);
851   if (dropped) fprintf(stderr, " (%d dropped)", dropped);
852   fprintf(stderr, "\n");
853   fprintf(stderr, "\nDone.\n");
854
855   return(0);
856
857 }