[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