[xiph-commits] r13878 - trunk/theora/examples

tterribe at svn.xiph.org tterribe at svn.xiph.org
Fri Sep 21 19:02:59 PDT 2007


Author: tterribe
Date: 2007-09-21 19:02:59 -0700 (Fri, 21 Sep 2007)
New Revision: 13878

Modified:
   trunk/theora/examples/dump_video.c
   trunk/theora/examples/player_example.c
Log:
Revert the examples back to the old API temporarily for beta1; also restore a
 bunch of the comments from the old versions and clean up the tabs and EOL WS.
Note that player_example uses the new theora_control for configuring
 post-processing, which currently requires theoradec.h.



Modified: trunk/theora/examples/dump_video.c
===================================================================
--- trunk/theora/examples/dump_video.c	2007-09-22 01:21:17 UTC (rev 13877)
+++ trunk/theora/examples/dump_video.c	2007-09-22 02:02:59 UTC (rev 13878)
@@ -5,7 +5,7 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2006                *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007                *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
@@ -50,7 +50,7 @@
 #include <fcntl.h>
 #include <math.h>
 #include <signal.h>
-#include "theora/theoradec.h"
+#include "theora/theora.h"
 
 const char *optstring = "o:rf";
 struct option options [] = {
@@ -71,17 +71,15 @@
 
 /* never forget that globals are a one-way ticket to Hell */
 /* Ogg and codec state for demux/decode */
-ogg_sync_state     oy;
-ogg_page           og;
-ogg_stream_state   vo;
-ogg_stream_state   to;
-th_info        ti;
-th_comment     tc;
-th_setup_info *ts;
-th_dec_ctx    *td;
+ogg_sync_state    oy;
+ogg_page          og;
+ogg_stream_state  vo;
+ogg_stream_state  to;
+theora_info       ti;
+theora_comment    tc;
+theora_state      td;
 
 int              theora_p=0;
-int              theora_processing_headers;
 int              stateflag=0;
 
 /* single frame video buffering */
@@ -97,70 +95,56 @@
   got_sigint = 1;
 }
 
-static th_ycbcr_buffer ycbcr;
-
-static void stripe_decoded(th_ycbcr_buffer _dst,th_ycbcr_buffer _src,
- int _fragy0,int _fragy_end){
-  int pli;
-  for(pli=0;pli<3;pli++){
-    int yshift;
-    int y_end;
-    int y;
-    yshift=pli!=0&&!(ti.pixel_fmt&2);
-    y_end=_fragy_end<<3-yshift;
-    for(y=_fragy0<<3-yshift;y<y_end;y++){
-      memcpy(_dst[pli].data+y*_dst[pli].ystride,
-       _src[pli].data+y*_src[pli].ystride,_src[pli].width);
-    }
-  }
-}
-
+/* this is a nop in the current implementation. we could
+   open a file here or something if so moved. */
 static void open_video(void){
-  th_stripe_callback cb;
-  int                    pli;
-  /*Here we allocate a buffer so we can use the striped decode feature.
-    There's no real reason to do this in this application, because we want to
-     write to the file top-down, but the frame gets decoded bottom up, so we
-     have to buffer it all anyway.
-    But this illustrates how the API works.*/
-  for(pli=0;pli<3;pli++){
-    int xshift;
-    int yshift;
-    xshift=pli!=0&&!(ti.pixel_fmt&1);
-    yshift=pli!=0&&!(ti.pixel_fmt&2);
-    ycbcr[pli].data=(unsigned char *)malloc(
-     (ti.frame_width>>xshift)*(ti.frame_height>>yshift)*sizeof(char));
-    ycbcr[pli].ystride=ti.frame_width>>xshift;
-    ycbcr[pli].width=ti.frame_width>>xshift;
-    ycbcr[pli].height=ti.frame_height>>yshift;
-  }
-  /*Similarly, since ycbcr is a global, there's no real reason to pass it as
-     the context.
-    In a more object-oriented decoder, we could pass the "this" pointer
-     instead (though in C++ platform-dependent calling convention differences
-     prevent us from using a real member function pointer).*/
-  cb.ctx=ycbcr;
-  cb.stripe_decoded=(th_stripe_decoded_func)stripe_decoded;
-  th_decode_ctl(td,TH_DECCTL_SET_STRIPE_CB,&cb,sizeof(cb));
+  return;
 }
 
+/* write out the planar YUV frame, uncropped */
 static void video_write(void){
-  int pli;
   int i;
 
-  /*Uncomment the following to do normal, non-striped decoding.
-  th_ycbcr_buffer ycbcr;
-  th_decode_ycbcr_out(td,ycbcr);*/
-  fprintf(outfile, "FRAME\n");
+  yuv_buffer yuv;
+  theora_decode_YUVout(&td,&yuv);
 
-  for(pli=0;pli<3;pli++){
-    for(i=0;i<ycbcr[pli].height;i++){
-      fwrite(ycbcr[pli].data+ycbcr[pli].ystride*i, 1,
-       ycbcr[pli].width, outfile);
+  if(outfile){
+    if(!raw)
+      fprintf(outfile, "FRAME\n");
+    for(i=0;i<yuv.y_height;i++)
+      fwrite(yuv.y+yuv.y_stride*i, 1, yuv.y_width, outfile);
+    for(i=0;i<yuv.uv_height;i++)
+      fwrite(yuv.u+yuv.uv_stride*i, 1, yuv.uv_width, outfile);
+    for(i=0;i<yuv.uv_height;i++)
+      fwrite(yuv.v+yuv.uv_stride*i, 1, yuv.uv_width, outfile);
+  }
+}
+
+/* dump the theora comment header */
+static int dump_comments(theora_comment *tc){
+  int i, len;
+  char *value;
+  FILE *out=stderr;
+
+  fprintf(out,"Encoded by %s\n",tc->vendor);
+  if(tc->comments){
+    fprintf(out, "theora comment header:\n");
+    for(i=0;i<tc->comments;i++){
+      if(tc->user_comments[i]){
+        len=tc->comment_lengths[i];
+        value=malloc(len+1);
+        memcpy(value,tc->user_comments[i],len);
+        value[len]='\0';
+        fprintf(out, "\t%s\n", value);
+        free(value);
+      }
     }
   }
+  return(0);
 }
 
+
+
 /* helper: push a page into the appropriate steam */
 /* this can be done blindly; a stream won't accept a page
                 that doesn't belong to it */
@@ -184,16 +168,15 @@
   int long_option_index;
   int c;
 
+  struct timeb start;
+  struct timeb after;
+  struct timeb last;
+  int fps_only=0;
   int frames = 0;
 
   FILE *infile = stdin;
   outfile = stdout;
 
-  struct timeb start;
-  struct timeb after;
-  struct timeb last;
-  int fps_only=0;
-
 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode on windows. */
   /* Beware the evil ifdef. We avoid these where we can, but this one we
      cannot. Don't add any more, you'll probably go to hell if you do. */
@@ -206,25 +189,25 @@
     switch(c){
     case 'o':
       if(!strcmp(optarg,"-")){
-	outfile=fopen(optarg,"wb");
-	if(outfile==NULL){
-	  fprintf(stderr,"Unable to open output file '%s'\n", optarg);
-	  exit(1);
-	}
+        outfile=fopen(optarg,"wb");
+        if(outfile==NULL){
+          fprintf(stderr,"Unable to open output file '%s'\n", optarg);
+          exit(1);
+        }
       }else{
-	outfile=stdout;
+        outfile=stdout;
       }
       break;
-      
+
     case 'r':
-	raw=1;
-	break;
-	
+      raw=1;
+      break;
+
     case 'f':
       fps_only = 1;
       outfile = NULL;
       break;
-      
+
     default:
       usage();
     }
@@ -241,6 +224,19 @@
     }
   }
 
+  /*
+     Ok, Ogg parsing. The idea here is we have a bitstream
+     that is made up of Ogg pages. The libogg sync layer will
+     find them for us. There may be pages from several logical
+     streams interleaved; we find the first theora stream and
+     ignore any others.
+
+     Then we pass the pages for our stream to the libogg stream
+     layer which assembles our original set of packets out of
+     them. It's the packets that libtheora actually knows how
+     to handle.
+  */
+
   /* start up Ogg stream synchronization layer */
   ogg_sync_init(&oy);
 
@@ -249,11 +245,16 @@
   /*vorbis_comment_init(&vc);*/
 
   /* init supporting Theora structures needed in header parsing */
-  th_comment_init(&tc);
-  th_info_init(&ti);
+  theora_comment_init(&tc);
+  theora_info_init(&ti);
 
   /* Ogg file open; parse the headers */
-  /* Only interested in Vorbis/Theora streams */
+
+  /* Vorbis and Theora both depend on some initial header packets
+     for decoder setup and initialization. We retrieve these first
+     before entering the main decode loop. */
+
+  /* Only interested in Theora streams */
   while(!stateflag){
     int ret=buffer_data(infile,&oy);
     if(ret==0)break;
@@ -270,16 +271,13 @@
 
       ogg_stream_init(&test,ogg_page_serialno(&og));
       ogg_stream_pagein(&test,&og);
-      ogg_stream_packetpeek(&test,&op);
+      ogg_stream_packetout(&test,&op);
 
       /* identify the codec: try theora */
-      if(!theora_p && (theora_processing_headers=
-       th_decode_headerin(&ti,&tc,&ts,&op))>=0){
-        /* it is theora */
+      if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
+        /* it is theora -- save this stream state */
         memcpy(&to,&test,sizeof(test));
         theora_p=1;
-        /*Advance past the successfully processed header.*/
-        if(theora_processing_headers)ogg_stream_packetout(&to,NULL);
       }else{
         /* whatever it is, we don't care about it */
         ogg_stream_clear(&test);
@@ -289,28 +287,25 @@
   }
 
   /* we're expecting more header packets. */
-  while(theora_p && theora_processing_headers){
+  while(theora_p && theora_p<3){
     int ret;
 
     /* look for further theora headers */
-    while(theora_processing_headers&&(ret=ogg_stream_packetpeek(&to,&op))){
-      if(ret<0)continue;
-      theora_processing_headers=th_decode_headerin(&ti,&tc,&ts,&op);
-      if(theora_processing_headers<0){
-        printf("Error parsing Theora stream headers; corrupt stream?\n");
+    while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
+      if(ret<0){
+        fprintf(stderr,"Error parsing Theora stream headers; "
+         "corrupt stream?\n");
         exit(1);
       }
-      else if(theora_processing_headers>0){
-        /*Advance past the successfully processed header.*/
-        ogg_stream_packetout(&to,NULL);
+      if(theora_decode_header(&ti,&tc,&op)){
+        fprintf(stderr,"Error parsing Theora stream headers; "
+         "corrupt stream?\n");
+        exit(1);
       }
       theora_p++;
+      if(theora_p==3)break;
     }
 
-    /*Stop now so we don't fail if there aren't enough pages in a short
-       stream.*/
-    if(!(theora_p && theora_processing_headers))break;
-
     /* The header pages/packets will arrive before anything else we
        care about, or the stream is not obeying spec */
 
@@ -324,36 +319,55 @@
       }
     }
   }
+  dump_comments(&tc);
 
   /* and now we have it all.  initialize decoders */
   if(theora_p){
-    td=th_decode_alloc(&ti,ts);
-    fprintf(stderr,"Ogg logical stream %lx is Theora %dx%d %.02f fps video\nEncoded frame content is %dx%d with %dx%d offset\n",
-            to.serialno,ti.frame_width,ti.frame_height,
-            (double)ti.fps_numerator/ti.fps_denominator,
-            ti.pic_width, ti.pic_height, ti.pic_x, ti.pic_y);
+    theora_decode_init(&td,&ti);
+    fprintf(stderr,"Ogg logical stream %lx is Theora %dx%d %.02f fps video\n"
+     "Encoded frame content is %dx%d with %dx%d offset\n",
+     to.serialno,ti.width,ti.height,
+     (double)ti.fps_numerator/ti.fps_denominator,
+     ti.frame_width,ti.frame_height,ti.offset_x,ti.offset_y);
   }else{
     /* tear down the partial theora setup */
-    th_info_clear(&ti);
-    th_comment_clear(&tc);
+    theora_info_clear(&ti);
+    theora_comment_clear(&tc);
   }
-  /*Either way, we're done with the codec setup data.*/
-  th_setup_free(ts);
 
   /* open video */
   if(theora_p)open_video();
 
   if(!raw && outfile){
-    fprintf(outfile, "YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\n",
-     ti.pic_width,ti.pic_height,ti.fps_numerator,ti.fps_denominator,'p',
+    fprintf(outfile,"YUV4MPEG2 W%d H%d F%d:%d I%c A%d:%d\n",
+     ti.width,ti.height,ti.fps_numerator,ti.fps_denominator,'p',
      ti.aspect_numerator,ti.aspect_denominator);
   }
 
   /* install signal handler */
   signal (SIGINT, sigint_handler);
 
-  /* on to the main decode loop.*/
+  /* Finally the main decode loop. 
 
+     It's one Theora packet per frame, so this is pretty 
+     straightforward if we're not trying to maintain sync
+     with other multiplexed streams.
+
+     the videobuf_ready flag is used to maintain the input
+     buffer in the libogg stream state. If there's no output
+     frame available at the end of the decode step, we must
+     need more input data. We could simplify this by just 
+     using the return code on ogg_page_packetout(), but the
+     flag system extends easily to the case were you care
+     about more than one multiplexed stream (like with audio
+     playback). In that case, just maintain a flag for each
+     decoder you care about, and pull data when any one of
+     them stalls.
+
+     videobuf_time holds the presentation time of the currently
+     buffered video frame. We ignore this value.
+  */
+
   stateflag=0; /* playback has not begun */
   /* queue any remaining pages from data we buffered but that did not
       contain headers */
@@ -372,41 +386,41 @@
       /* theora is one in, one out... */
       if(ogg_stream_packetout(&to,&op)>0){
 
-        if(th_decode_packetin(td,&op,&videobuf_granulepos)>=0){
-          videobuf_time=th_granule_time(td,videobuf_granulepos);
-          videobuf_ready=1;
-          frames++;
-	  if(fps_only)
-	    ftime(&after);
-        }
-	
+        theora_decode_packetin(&td,&op);
+        videobuf_granulepos=td.granulepos;
+        videobuf_time=theora_granule_time(&td,videobuf_granulepos);
+        videobuf_ready=1;
+        frames++;
+        if(fps_only)
+          ftime(&after);
+
       }else
         break;
     }
 
     if(fps_only && (videobuf_ready || fps_only==2)){
-      long ms = 
-	after.time*1000.+after.millitm-
-	(last.time*1000.+last.millitm);
-      
-      if(ms>500 || fps_only==1 || 
-	 (feof(infile) && !videobuf_ready)){
-	float file_fps = (float)ti.fps_numerator/ti.fps_denominator;
-	fps_only=2;
-	
-	ms = after.time*1000.+after.millitm-
-	  (start.time*1000.+start.millitm);
-	
-	fprintf(stderr,"\rframe:%d rate:%.2fx           ",
-		frames, 
-		frames*1000./(ms*file_fps));
-	memcpy(&last,&after,sizeof(last));
+      long ms =
+        after.time*1000.+after.millitm-
+        (last.time*1000.+last.millitm);
+
+      if(ms>500 || fps_only==1 ||
+         (feof(infile) && !videobuf_ready)){
+        float file_fps = (float)ti.fps_numerator/ti.fps_denominator;
+        fps_only=2;
+
+        ms = after.time*1000.+after.millitm-
+          (start.time*1000.+start.millitm);
+
+        fprintf(stderr,"\rframe:%d rate:%.2fx           ",
+                frames,
+                frames*1000./(ms*file_fps));
+        memcpy(&last,&after,sizeof(last));
       }
     }
-    
-    if(!videobuf_ready  && feof(infile))break;
 
-    if(!videobuf_ready ){
+    if(!videobuf_ready && feof(infile))break;
+
+    if(!videobuf_ready){
       /* no data yet for somebody.  Grab another page */
       buffer_data(infile,&oy);
       while(ogg_sync_pageout(&oy,&og)>0){
@@ -414,19 +428,18 @@
       }
     }
     /* dumpvideo frame, and get new one */
-    else 
-      if(outfile)video_write();
+    else if(outfile)video_write();
 
     videobuf_ready=0;
   }
 
-  /* close everything */
+  /* end of decoder loop -- close everything */
 
   if(theora_p){
     ogg_stream_clear(&to);
-    th_decode_free(td);
-    th_comment_clear(&tc);
-    th_info_clear(&ti);
+    theora_clear(&td);
+    theora_comment_clear(&tc);
+    theora_info_clear(&ti);
   }
   ogg_sync_clear(&oy);
 

Modified: trunk/theora/examples/player_example.c
===================================================================
--- trunk/theora/examples/player_example.c	2007-09-22 01:21:17 UTC (rev 13877)
+++ trunk/theora/examples/player_example.c	2007-09-22 02:02:59 UTC (rev 13878)
@@ -56,6 +56,7 @@
 #include <fcntl.h>
 #include <math.h>
 #include <signal.h>
+#include "theora/theora.h"
 #include "theora/theoradec.h"
 #include "vorbis/codec.h"
 #include <SDL.h>
@@ -91,17 +92,15 @@
 ogg_page         og;
 ogg_stream_state vo;
 ogg_stream_state to;
-th_info      ti;
-th_comment   tc;
-th_setup_info *ts;
-th_dec_ctx    *td;
+theora_info      ti;
+theora_comment   tc;
+theora_state     td;
 vorbis_info      vi;
 vorbis_dsp_state vd;
 vorbis_block     vb;
 vorbis_comment   vc;
 
 int              theora_p=0;
-int              theora_processing_headers;
 int              vorbis_p=0;
 int              stateflag=0;
 
@@ -280,9 +279,9 @@
       while(1){
         bytes=write(audiofd,audiobuf+(audiofd_fragsize-audiobuf_fill),
                     audiofd_fragsize);
-        
+
         if(bytes>0){
-        
+
           if(bytes!=audiobuf_fill){
             /* shouldn't actually be possible... but eh */
             audiobuf_fill-=bytes;
@@ -311,14 +310,14 @@
     exit(1);
   }
 
-  screen = SDL_SetVideoMode(ti.pic_width, ti.pic_height, 0, SDL_SWSURFACE);
+  screen = SDL_SetVideoMode(ti.frame_width, ti.frame_height, 0, SDL_SWSURFACE);
   if ( screen == NULL ) {
     fprintf(stderr, "Unable to set %dx%d video: %s\n",
-            ti.pic_width,ti.pic_height,SDL_GetError());
+            ti.frame_width,ti.frame_height,SDL_GetError());
     exit(1);
   }
 
-  yuv_overlay = SDL_CreateYUVOverlay(ti.pic_width, ti.pic_height,
+  yuv_overlay = SDL_CreateYUVOverlay(ti.frame_width, ti.frame_height,
                                      SDL_YV12_OVERLAY,
                                      screen);
   if ( yuv_overlay == NULL ) {
@@ -328,22 +327,18 @@
   }
   rect.x = 0;
   rect.y = 0;
-  rect.w = ti.pic_width;
-  rect.h = ti.pic_height;
+  rect.w = ti.frame_width;
+  rect.h = ti.frame_height;
 
   SDL_DisplayYUVOverlay(yuv_overlay, &rect);
 }
 
 static void video_write(void){
-  static const int planemap[3] = {0,2,1};
-  int pli;
-  int wscale, hscale;
   int i;
-  th_ycbcr_buffer ycbcr;
+  yuv_buffer yuv;
   int crop_offset;
+  theora_decode_YUVout(&td,&yuv);
 
-  th_decode_ycbcr_out(td,ycbcr);
-
   /* Lock SDL_yuv_overlay */
   if ( SDL_MUSTLOCK(screen) ) {
     if ( SDL_LockSurface(screen) < 0 ) return;
@@ -355,17 +350,19 @@
   /* reverse u and v for SDL */
   /* and crop input properly, respecting the encoded frame rect */
   /* problems may exist for odd frame rect for some encodings */
-  for (pli = 0; pli < 3; pli++) {
-    wscale = ycbcr[0].width / ycbcr[pli].width;
-    hscale = ycbcr[0].height / ycbcr[pli].height;
-    crop_offset = (ti.pic_x / wscale)
-                + (ycbcr[pli].ystride)
-                * (ti.pic_y / hscale);
-    for(i=0;i<yuv_overlay->h / hscale;i++)
-      memcpy(yuv_overlay->pixels[planemap[pli]]
-                      + yuv_overlay->pitches[planemap[pli]]*i,
-             ycbcr[pli].data+crop_offset+ycbcr[pli].ystride*i,
-             yuv_overlay->w / wscale);
+  crop_offset=ti.offset_x+yuv.y_stride*ti.offset_y;
+  for(i=0;i<yuv_overlay->h;i++)
+    memcpy(yuv_overlay->pixels[0]+yuv_overlay->pitches[0]*i,
+           yuv.y+crop_offset+yuv.y_stride*i,
+           yuv_overlay->w);
+  crop_offset=(ti.offset_x/2)+(yuv.uv_stride)*(ti.offset_y/2);
+  for(i=0;i<yuv_overlay->h/2;i++){
+    memcpy(yuv_overlay->pixels[1]+yuv_overlay->pitches[1]*i,
+           yuv.v+crop_offset+yuv.uv_stride*i,
+           yuv_overlay->w/2);
+    memcpy(yuv_overlay->pixels[2]+yuv_overlay->pitches[2]*i,
+           yuv.u+crop_offset+yuv.uv_stride*i,
+           yuv_overlay->w/2);
   }
 
   /* Unlock SDL_yuv_overlay */
@@ -380,7 +377,7 @@
 
 }
 /* dump the theora (or vorbis) comment header */
-static int dump_comments(th_comment *tc){
+static int dump_comments(theora_comment *tc){
   int i, len;
   char *value;
   FILE *out=stdout;
@@ -406,16 +403,16 @@
    We don't actually make use of the information in this example;
    a real player should attempt to perform color correction for
    whatever display device it supports. */
-static void report_colorspace(th_info *ti)
+static void report_colorspace(theora_info *ti)
 {
     switch(ti->colorspace){
-      case TH_CS_UNSPECIFIED:
+      case OC_CS_UNSPECIFIED:
         /* nothing to report */
         break;;
-      case TH_CS_ITU_REC_470M:
+      case OC_CS_ITU_REC_470M:
         fprintf(stderr,"  encoder specified ITU Rec 470M (NTSC) color.\n");
         break;;
-      case TH_CS_ITU_REC_470BG:
+      case OC_CS_ITU_REC_470BG:
         fprintf(stderr,"  encoder specified ITU Rec 470BG (PAL) color.\n");
         break;;
       default:
@@ -430,7 +427,7 @@
                 that doesn't belong to it */
 static int queue_page(ogg_page *page){
   if(theora_p)ogg_stream_pagein(&to,page);
-  if(vorbis_p)ogg_stream_pagein(&vo,&og);
+  if(vorbis_p)ogg_stream_pagein(&vo,page);
   return 0;
 }
 
@@ -482,8 +479,8 @@
   vorbis_comment_init(&vc);
 
   /* init supporting Theora structures needed in header parsing */
-  th_comment_init(&tc);
-  th_info_init(&ti);
+  theora_comment_init(&tc);
+  theora_info_init(&ti);
 
   /* Ogg file open; parse the headers */
   /* Only interested in Vorbis/Theora streams */
@@ -503,22 +500,17 @@
 
       ogg_stream_init(&test,ogg_page_serialno(&og));
       ogg_stream_pagein(&test,&og);
-      ogg_stream_packetpeek(&test,&op);
+      ogg_stream_packetout(&test,&op);
 
       /* identify the codec: try theora */
-      if(!theora_p && (theora_processing_headers=
-       th_decode_headerin(&ti,&tc,&ts,&op))>=0){
+      if(!theora_p && theora_decode_header(&ti,&tc,&op)>=0){
         /* it is theora */
         memcpy(&to,&test,sizeof(test));
         theora_p=1;
-        /*Advance past the successfully processed header.*/
-        if(theora_processing_headers)ogg_stream_packetout(&to,NULL);
       }else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){
         /* it is vorbis */
         memcpy(&vo,&test,sizeof(test));
         vorbis_p=1;
-        /*Advance past the successfully processed header.*/
-        ogg_stream_packetout(&vo,NULL);
       }else{
         /* whatever it is, we don't care about it */
         ogg_stream_clear(&test);
@@ -528,20 +520,20 @@
   }
 
   /* we're expecting more header packets. */
-  while((theora_p && theora_processing_headers) || (vorbis_p && vorbis_p<3)){
+  while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
     int ret;
 
     /* look for further theora headers */
-    while(theora_processing_headers&&(ret=ogg_stream_packetpeek(&to,&op))){
-      if(ret<0)continue;
-      theora_processing_headers=th_decode_headerin(&ti,&tc,&ts,&op);
-      if(theora_processing_headers<0){
-        printf("Error parsing Theora stream headers; corrupt stream?\n");
+    while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
+      if(ret<0){
+        fprintf(stderr,"Error parsing Theora stream headers; "
+         "corrupt stream?\n");
         exit(1);
       }
-      else if(theora_processing_headers>0){
-        /*Advance past the successfully processed header.*/
-        ogg_stream_packetout(&to,NULL);
+      if(theora_decode_header(&ti,&tc,&op)){
+        fprintf(stderr,"Error parsing Theora stream headers; "
+         "corrupt stream?\n");
+        exit(1);
       }
       theora_p++;
     }
@@ -560,10 +552,6 @@
       if(vorbis_p==3)break;
     }
 
-    /*Stop now so we don't fail if there aren't enough pages in a short
-       stream.*/
-    if(!(theora_p&&theora_processing_headers)&&!(vorbis_p&&vorbis_p<3))break;
-
     /* The header pages/packets will arrive before anything else we
        care about, or the stream is not obeying spec */
 
@@ -580,27 +568,34 @@
 
   /* and now we have it all.  initialize decoders */
   if(theora_p){
-    td=th_decode_alloc(&ti,ts);
-    printf("Ogg logical stream %lx is Theora %dx%d %.02f fps video\n",
-           to.serialno,ti.frame_width,ti.frame_height, 
+    theora_decode_init(&td,&ti);
+    printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
+           to.serialno,ti.width,ti.height,
            (double)ti.fps_numerator/ti.fps_denominator);
-    if(ti.frame_width!=ti.pic_width || ti.frame_height!=ti.pic_height)
+    switch(ti.pixelformat){
+      case OC_PF_420: printf(" 4:2:0 video\n"); break;
+      case OC_PF_422: printf(" 4:2:2 video\n"); break;
+      case OC_PF_444: printf(" 4:4:4 video\n"); break;
+      case OC_PF_RSVD:
+      default:
+       printf(" video\n  (UNKNOWN Chroma sampling!)\n");
+       break;
+    }
+    if(ti.width!=ti.frame_width || ti.height!=ti.frame_height)
       printf("  Frame content is %dx%d with offset (%d,%d).\n",
-           ti.pic_width, ti.pic_height, ti.pic_x, ti.pic_y);
+           ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
     report_colorspace(&ti);
     dump_comments(&tc);
-    th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
+    theora_control(&td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
      sizeof(pp_level_max));
     pp_level=pp_level_max;
-    th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
+    theora_control(&td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
     pp_inc=0;
   }else{
     /* tear down the partial theora setup */
-    th_info_clear(&ti);
-    th_comment_clear(&tc);
+    theora_info_clear(&ti);
+    theora_comment_clear(&tc);
   }
-  /*Either way, we're done with the codec setup data.*/
-  th_setup_free(ts);
   if(vorbis_p){
     vorbis_synthesis_init(&vd,&vi);
     vorbis_block_init(&vd,&vb);
@@ -655,9 +650,9 @@
           audiobuf_granulepos=vd.granulepos-ret+i;
         else
           audiobuf_granulepos+=i;
-        
+
       }else{
-        
+
         /* no pending audio; is there a pending packet to decode? */
         if(ogg_stream_packetout(&vo,&op)>0){
           if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
@@ -673,7 +668,7 @@
 
         if(pp_inc){
           pp_level+=pp_inc;
-          th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,
+          theora_control(&td,TH_DECCTL_SET_PPLEVEL,&pp_level,
            sizeof(pp_level));
           pp_inc=0;
         }
@@ -684,11 +679,12 @@
            page and compute the correct granulepos for the first packet after
            a seek or a gap.*/
         if(op.granulepos>=0){
-          th_decode_ctl(td,TH_DECCTL_SET_GRANPOS,&op.granulepos,
+          theora_control(&td,TH_DECCTL_SET_GRANPOS,&op.granulepos,
            sizeof(op.granulepos));
         }
-        if(th_decode_packetin(td,&op,&videobuf_granulepos)==0){
-          videobuf_time=th_granule_time(td,videobuf_granulepos);
+        if(theora_decode_packetin(&td,&op)==0){
+          videobuf_granulepos=td.granulepos;
+          videobuf_time=theora_granule_time(&td,videobuf_granulepos);
           frames++;
 
           /* is it already too old to be useful?  This is only actually
@@ -701,7 +697,7 @@
             videobuf_ready=1;
           else{
             /*If we are too slow, reduce the pp level.*/
-	    pp_inc=pp_level>0?-1:0;
+            pp_inc=pp_level>0?-1:0;
             dropped++;
           }
         }
@@ -736,7 +732,7 @@
       /* we have an audio frame ready (which means the audio buffer is
          full), it's not time to play video, so wait until one of the
          audio buffer is ready or it's near time to play video */
-        
+
       /* set up select wait on the audiobuffer and a timeout for video */
       struct timeval timeout;
       fd_set writefs;
@@ -798,9 +794,9 @@
   }
   if(theora_p){
     ogg_stream_clear(&to);
-    th_decode_free(td);
-    th_comment_clear(&tc);
-    th_info_clear(&ti);
+    theora_clear(&td);
+    theora_comment_clear(&tc);
+    theora_info_clear(&ti);
   }
   ogg_sync_clear(&oy);
 



More information about the commits mailing list