[xiph-commits] r16301 - in branches/theora-gumboot: . examples include/theora lib/dec lib/dec/x86 lib/dec/x86_vc

gumboot at svn.xiph.org gumboot at svn.xiph.org
Sat Jul 18 08:06:53 PDT 2009


Author: gumboot
Date: 2009-07-18 08:06:53 -0700 (Sat, 18 Jul 2009)
New Revision: 16301

Added:
   branches/theora-gumboot/examples/dump_video.c
Removed:
   branches/theora-gumboot/examples/dump_video.c
Modified:
   branches/theora-gumboot/
   branches/theora-gumboot/examples/Makefile.am
   branches/theora-gumboot/include/theora/theora.h
   branches/theora-gumboot/include/theora/theoradec.h
   branches/theora-gumboot/lib/dec/bitpack.c
   branches/theora-gumboot/lib/dec/decint.h
   branches/theora-gumboot/lib/dec/decode.c
   branches/theora-gumboot/lib/dec/huffdec.c
   branches/theora-gumboot/lib/dec/x86/mmxstate.c
   branches/theora-gumboot/lib/dec/x86_vc/mmxstate.c
Log:
Update theora-gumboot with latest theora-thusnelda changes.



Property changes on: branches/theora-gumboot
___________________________________________________________________
Modified: svn:mergeinfo
   - /trunk/theora:14138-15320,15741
   + /branches/theora-thusnelda:16256-16300
/trunk/theora:14138-15320,15741

Modified: branches/theora-gumboot/examples/Makefile.am
===================================================================
--- branches/theora-gumboot/examples/Makefile.am	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/examples/Makefile.am	2009-07-18 15:06:53 UTC (rev 16301)
@@ -14,7 +14,7 @@
 
 dump_video_SOURCES = dump_video.c
 EXTRA_dump_video_SOURCES = getopt.c getopt1.c getopt.h
-dump_video_LDADD = $(GETOPT_OBJS) $(LDADD)
+dump_video_LDADD = $(GETOPT_OBJS) $(LDADDDEC)
 dump_video_DEPENDENCIES = $(GETOPT_OBJS)
 
 dump_psnr_SOURCES = dump_psnr.c

Deleted: branches/theora-gumboot/examples/dump_video.c
===================================================================
--- branches/theora-gumboot/examples/dump_video.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/examples/dump_video.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -1,496 +0,0 @@
-/********************************************************************
- *                                                                  *
- * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
- * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
- * 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                *
- * by the Xiph.Org Foundation http://www.xiph.org/                  *
- *                                                                  *
- ********************************************************************
-
-  function: example dumpvid application; dumps  Theora streams
-  last mod: $Id: dump_video.c,v 1.2 2004/03/24 19:12:42 derf Exp $
-
- ********************************************************************/
-
-/* By Mauricio Piacentini (mauricio at xiph.org) */
-/*  simply dump decoded YUV data, for verification of theora bitstream */
-
-#if !defined(_REENTRANT)
-#define _REENTRANT
-#endif
-#if !defined(_GNU_SOURCE)
-#define _GNU_SOURCE
-#endif
-#if !defined(_LARGEFILE_SOURCE)
-#define _LARGEFILE_SOURCE
-#endif
-#if !defined(_LARGEFILE64_SOURCE)
-#define _LARGEFILE64_SOURCE
-#endif
-#if !defined(_FILE_OFFSET_BITS)
-#define _FILE_OFFSET_BITS 64
-#endif
-
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/timeb.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-/*Yes, yes, we're going to hell.*/
-#if defined(_WIN32)
-#include <io.h>
-#endif
-#include <fcntl.h>
-#include <limits.h>
-#include <math.h>
-#include <signal.h>
-#include "getopt.h"
-#include "theora/theoradec.h"
-
-const char *optstring = "o:rf";
-struct option options [] = {
-  {"output",required_argument,NULL,'o'},
-  {"raw",no_argument, NULL,'r'}, /*Disable YUV4MPEG2 headers:*/
-  {"fps-only",no_argument, NULL, 'f'}, /* Only interested in fps of decode loop */
-  {NULL,0,NULL,0}
-};
-
-/* Helper; just grab some more compressed bitstream and sync it for
-   page extraction */
-int buffer_data(FILE *in,ogg_sync_state *oy){
-  char *buffer=ogg_sync_buffer(oy,4096);
-  int bytes=fread(buffer,1,4096,in);
-  ogg_sync_wrote(oy,bytes);
-  return(bytes);
-}
-
-/* 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;
-
-int              theora_p=0;
-int              theora_processing_headers;
-int              stateflag=0;
-
-/* single frame video buffering */
-int          videobuf_ready=0;
-ogg_int64_t  videobuf_granulepos=-1;
-double       videobuf_time=0;
-int          raw=0;
-
-FILE* outfile = NULL;
-
-int got_sigint=0;
-static void sigint_handler (int signal) {
-  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;
-    /*An implemention intending to display this data would need to check the
-       crop rectangle before proceeding.*/
-    for(y=_fragy0<<3-yshift;y<y_end;y++){
-      memcpy(_dst[pli].data+y*_dst[pli].stride,
-       _src[pli].data+y*_src[pli].stride,_src[pli].width);
-    }
-  }
-}
-
-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].stride=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));
-}
-
-/*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);*/
-  if(outfile){
-    if(!raw)fprintf(outfile, "FRAME\n");
-    for(pli=0;pli<3;pli++){
-      for(i=0;i<ycbcr[pli].height;i++){
-        fwrite(ycbcr[pli].data+ycbcr[pli].stride*i, 1,
-         ycbcr[pli].width, outfile);
-      }
-    }
-  }
-}
-
-/* dump the theora comment header */
-static int dump_comments(th_comment *_tc){
-  int   i;
-  int   len;
-  FILE *out;
-  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]<INT_MAX?_tc->comment_lengths[i]:INT_MAX;
-        fprintf(out,"\t%.*s\n",len,_tc->user_comments[i]);
-      }
-    }
-  }
-  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 */
-static int queue_page(ogg_page *page){
-  if(theora_p)ogg_stream_pagein(&to,page);
-  return 0;
-}
-
-static void usage(void){
-  fprintf(stderr,
-          "Usage: dumpvid <file.ogv> > outfile\n"
-          "input is read from stdin if no file is passed on the command line\n"
-          "\n"
-  );
-}
-
-int main(int argc,char *argv[]){
-
-  ogg_packet op;
-
-  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;
-
-#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. */
-  _setmode( _fileno( stdin ), _O_BINARY );
-  _setmode( _fileno( stdout ), _O_BINARY );
-#endif
-
-  /* Process option arguments. */
-  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
-    switch(c){
-    case 'o':
-      if(strcmp(optarg,"-")!=0){
-        outfile=fopen(optarg,"wb");
-        if(outfile==NULL){
-          fprintf(stderr,"Unable to open output file '%s'\n", optarg);
-          exit(1);
-        }
-      }else{
-        outfile=stdout;
-      }
-      break;
-
-    case 'r':
-      raw=1;
-      break;
-
-    case 'f':
-      fps_only = 1;
-      outfile = NULL;
-      break;
-
-    default:
-      usage();
-    }
-  }
-  if(optind<argc){
-    infile=fopen(argv[optind],"rb");
-    if(infile==NULL){
-      fprintf(stderr,"Unable to open '%s' for extraction.\n", argv[optind]);
-      exit(1);
-    }
-    if(++optind<argc){
-      usage();
-      exit(1);
-    }
-  }
-  /*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);
-
-  /* init supporting Theora structures needed in header parsing */
-  th_comment_init(&tc);
-  th_info_init(&ti);
-
-  /*Ogg file open; parse the headers.
-    Theora (like Vorbis) depends 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;
-    while(ogg_sync_pageout(&oy,&og)>0){
-      ogg_stream_state test;
-
-      /* is this a mandated initial header? If not, stop parsing */
-      if(!ogg_page_bos(&og)){
-        /* don't leak the page; get it into the appropriate stream */
-        queue_page(&og);
-        stateflag=1;
-        break;
-      }
-
-      ogg_stream_init(&test,ogg_page_serialno(&og));
-      ogg_stream_pagein(&test,&og);
-      ogg_stream_packetpeek(&test,&op);
-
-      /* identify the codec: try theora */
-      if(!theora_p && (theora_processing_headers=
-       th_decode_headerin(&ti,&tc,&ts,&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);
-      }
-    }
-    /* fall through to non-bos page parsing */
-  }
-
-  /* we're expecting more header packets. */
-  while(theora_p && theora_processing_headers){
-    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){
-        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);
-      }
-      theora_p++;
-    }
-
-    /*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 */
-
-    if(ogg_sync_pageout(&oy,&og)>0){
-      queue_page(&og); /* demux into the appropriate stream */
-    }else{
-      int ret=buffer_data(infile,&oy); /* someone needs more data */
-      if(ret==0){
-        fprintf(stderr,"End of file while searching for codec headers.\n");
-        exit(1);
-      }
-    }
-  }
-
-  /* and now we have it all.  initialize decoders */
-  if(theora_p){
-    dump_comments(&tc);
-    td=th_decode_alloc(&ti,ts);
-    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.frame_width,ti.frame_height,
-     (double)ti.fps_numerator/ti.fps_denominator,
-     ti.pic_width,ti.pic_height,ti.pic_x,ti.pic_y);
-  }else{
-    /* tear down the partial theora setup */
-    th_info_clear(&ti);
-    th_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){
-    static const char *CHROMA_TYPES[4]={"420jpeg",NULL,"422","444"};
-    if(ti.pixel_fmt>=4||ti.pixel_fmt==TH_PF_RSVD){
-      fprintf(stderr,"Unknown pixel format: %i\n",ti.pixel_fmt);
-      exit(1);
-    }
-    fprintf(outfile,"YUV4MPEG2 C%s W%d H%d F%d:%d I%c A%d:%d\n",
-     CHROMA_TYPES[ti.pixel_fmt],ti.frame_width,ti.frame_height,
-     ti.fps_numerator,ti.fps_denominator,'p',
-     ti.aspect_numerator,ti.aspect_denominator);
-  }
-
-  /* install signal handler */
-  signal (SIGINT, sigint_handler);
-
-  /*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 where
-     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 */
-  while(ogg_sync_pageout(&oy,&og)>0){
-    queue_page(&og);
-  }
-
-  if(fps_only){
-    ftime(&start);
-    ftime(&last);
-  }
-
-  while(!got_sigint){
-
-    while(theora_p && !videobuf_ready){
-      /* 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);
-        }
-
-      }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));
-      }
-    }
-
-    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){
-        queue_page(&og);
-      }
-    }
-    /* dumpvideo frame, and get new one */
-    else if(outfile)video_write();
-
-    videobuf_ready=0;
-  }
-
-  /* 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);
-  }
-  ogg_sync_clear(&oy);
-
-  if(infile && infile!=stdin)fclose(infile);
-  if(outfile && outfile!=stdout)fclose(outfile);
-
-  fprintf(stderr, "\n\n%d frames\n", frames);
-  fprintf(stderr, "\nDone.\n");
-
-  return(0);
-
-}

Copied: branches/theora-gumboot/examples/dump_video.c (from rev 16300, branches/theora-thusnelda/examples/dump_video.c)
===================================================================
--- branches/theora-gumboot/examples/dump_video.c	                        (rev 0)
+++ branches/theora-gumboot/examples/dump_video.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -0,0 +1,495 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE.   *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
+ * 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                *
+ * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ *                                                                  *
+ ********************************************************************
+
+  function: example dumpvid application; dumps  Theora streams
+  last mod: $Id: dump_video.c,v 1.2 2004/03/24 19:12:42 derf Exp $
+
+ ********************************************************************/
+
+/* By Mauricio Piacentini (mauricio at xiph.org) */
+/*  simply dump decoded YUV data, for verification of theora bitstream */
+
+#if !defined(_REENTRANT)
+#define _REENTRANT
+#endif
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+#if !defined(_LARGEFILE_SOURCE)
+#define _LARGEFILE_SOURCE
+#endif
+#if !defined(_LARGEFILE64_SOURCE)
+#define _LARGEFILE64_SOURCE
+#endif
+#if !defined(_FILE_OFFSET_BITS)
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/timeb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/*Yes, yes, we're going to hell.*/
+#if defined(_WIN32)
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include <limits.h>
+#include <math.h>
+#include <signal.h>
+#include "getopt.h"
+#include "theora/theoradec.h"
+
+const char *optstring = "o:rf";
+struct option options [] = {
+  {"output",required_argument,NULL,'o'},
+  {"raw",no_argument, NULL,'r'}, /*Disable YUV4MPEG2 headers:*/
+  {"fps-only",no_argument, NULL, 'f'}, /* Only interested in fps of decode loop */
+  {NULL,0,NULL,0}
+};
+
+/* Helper; just grab some more compressed bitstream and sync it for
+   page extraction */
+int buffer_data(FILE *in,ogg_sync_state *oy){
+  char *buffer=ogg_sync_buffer(oy,4096);
+  int bytes=fread(buffer,1,4096,in);
+  ogg_sync_wrote(oy,bytes);
+  return(bytes);
+}
+
+/* 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;
+
+int              theora_p=0;
+int              theora_processing_headers;
+int              stateflag=0;
+
+/* single frame video buffering */
+int          videobuf_ready=0;
+ogg_int64_t  videobuf_granulepos=-1;
+double       videobuf_time=0;
+int          raw=0;
+
+FILE* outfile = NULL;
+
+int got_sigint=0;
+static void sigint_handler (int signal) {
+  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;
+    /*An implemention intending to display this data would need to check the
+       crop rectangle before proceeding.*/
+    for(y=_fragy0<<3-yshift;y<y_end;y++){
+      memcpy(_dst[pli].data+y*_dst[pli].stride,
+       _src[pli].data+y*_src[pli].stride,_src[pli].width);
+    }
+  }
+}
+
+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].stride=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));
+}
+
+/*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);*/
+  if(outfile){
+    if(!raw)fprintf(outfile, "FRAME\n");
+    for(pli=0;pli<3;pli++){
+      for(i=0;i<ycbcr[pli].height;i++){
+        fwrite(ycbcr[pli].data+ycbcr[pli].stride*i, 1,
+         ycbcr[pli].width, outfile);
+      }
+    }
+  }
+}
+
+/* dump the theora comment header */
+static int dump_comments(th_comment *_tc){
+  int   i;
+  int   len;
+  FILE *out;
+  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]<INT_MAX?_tc->comment_lengths[i]:INT_MAX;
+        fprintf(out,"\t%.*s\n",len,_tc->user_comments[i]);
+      }
+    }
+  }
+  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 */
+static int queue_page(ogg_page *page){
+  if(theora_p)ogg_stream_pagein(&to,page);
+  return 0;
+}
+
+static void usage(void){
+  fprintf(stderr,
+          "Usage: dumpvid <file.ogv> > outfile\n"
+          "input is read from stdin if no file is passed on the command line\n"
+          "\n"
+  );
+}
+
+int main(int argc,char *argv[]){
+
+  ogg_packet op;
+
+  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;
+
+#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. */
+  _setmode( _fileno( stdin ), _O_BINARY );
+  _setmode( _fileno( stdout ), _O_BINARY );
+#endif
+
+  /* Process option arguments. */
+  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
+    switch(c){
+    case 'o':
+      if(strcmp(optarg,"-")!=0){
+        outfile=fopen(optarg,"wb");
+        if(outfile==NULL){
+          fprintf(stderr,"Unable to open output file '%s'\n", optarg);
+          exit(1);
+        }
+      }else{
+        outfile=stdout;
+      }
+      break;
+
+    case 'r':
+      raw=1;
+      break;
+
+    case 'f':
+      fps_only = 1;
+      outfile = NULL;
+      break;
+
+    default:
+      usage();
+    }
+  }
+  if(optind<argc){
+    infile=fopen(argv[optind],"rb");
+    if(infile==NULL){
+      fprintf(stderr,"Unable to open '%s' for extraction.\n", argv[optind]);
+      exit(1);
+    }
+    if(++optind<argc){
+      usage();
+      exit(1);
+    }
+  }
+  /*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);
+
+  /* init supporting Theora structures needed in header parsing */
+  th_comment_init(&tc);
+  th_info_init(&ti);
+
+  /*Ogg file open; parse the headers.
+    Theora (like Vorbis) depends 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;
+    while(ogg_sync_pageout(&oy,&og)>0){
+      ogg_stream_state test;
+
+      /* is this a mandated initial header? If not, stop parsing */
+      if(!ogg_page_bos(&og)){
+        /* don't leak the page; get it into the appropriate stream */
+        queue_page(&og);
+        stateflag=1;
+        break;
+      }
+
+      ogg_stream_init(&test,ogg_page_serialno(&og));
+      ogg_stream_pagein(&test,&og);
+      ogg_stream_packetpeek(&test,&op);
+
+      /* identify the codec: try theora */
+      if(!theora_p && (theora_processing_headers=
+       th_decode_headerin(&ti,&tc,&ts,&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);
+      }
+    }
+    /* fall through to non-bos page parsing */
+  }
+
+  /* we're expecting more header packets. */
+  while(theora_p && theora_processing_headers){
+    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){
+        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);
+      }
+      theora_p++;
+    }
+
+    /*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 */
+
+    if(ogg_sync_pageout(&oy,&og)>0){
+      queue_page(&og); /* demux into the appropriate stream */
+    }else{
+      int ret=buffer_data(infile,&oy); /* someone needs more data */
+      if(ret==0){
+        fprintf(stderr,"End of file while searching for codec headers.\n");
+        exit(1);
+      }
+    }
+  }
+
+  /* and now we have it all.  initialize decoders */
+  if(theora_p){
+    dump_comments(&tc);
+    td=th_decode_alloc(&ti,ts);
+    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.frame_width,ti.frame_height,
+     (double)ti.fps_numerator/ti.fps_denominator,
+     ti.pic_width,ti.pic_height,ti.pic_x,ti.pic_y);
+  }else{
+    /* tear down the partial theora setup */
+    th_info_clear(&ti);
+    th_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){
+    static const char *CHROMA_TYPES[4]={"420jpeg",NULL,"422","444"};
+    if(ti.pixel_fmt>=4||ti.pixel_fmt==TH_PF_RSVD){
+      fprintf(stderr,"Unknown pixel format: %i\n",ti.pixel_fmt);
+      exit(1);
+    }
+    fprintf(outfile,"YUV4MPEG2 C%s W%d H%d F%d:%d I%c A%d:%d\n",
+     CHROMA_TYPES[ti.pixel_fmt],ti.frame_width,ti.frame_height,
+     ti.fps_numerator,ti.fps_denominator,'p',
+     ti.aspect_numerator,ti.aspect_denominator);
+  }
+
+  /* install signal handler */
+  signal (SIGINT, sigint_handler);
+
+  /*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 where
+     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 */
+  while(ogg_sync_pageout(&oy,&og)>0){
+    queue_page(&og);
+  }
+
+  if(fps_only){
+    ftime(&start);
+    ftime(&last);
+  }
+
+  while(!got_sigint){
+
+    while(theora_p && !videobuf_ready){
+      /* 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);
+        }
+
+      }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));
+      }
+    }
+
+    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){
+        queue_page(&og);
+      }
+    }
+    /* dumpvideo frame, and get new one */
+    else if(outfile)video_write();
+
+    videobuf_ready=0;
+  }
+
+  /* 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);
+  }
+  ogg_sync_clear(&oy);
+
+  if(infile && infile!=stdin)fclose(infile);
+  if(outfile && outfile!=stdout)fclose(outfile);
+
+  fprintf(stderr, "\n\n%d frames\n", frames);
+  fprintf(stderr, "\nDone.\n");
+
+  return(0);
+
+}

Modified: branches/theora-gumboot/include/theora/theora.h
===================================================================
--- branches/theora-gumboot/include/theora/theora.h	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/include/theora/theora.h	2009-07-18 15:06:53 UTC (rev 16301)
@@ -340,6 +340,8 @@
 
 #define TH_DECCTL_SET_TELEMETRY_MBMODE (9)
 #define TH_DECCTL_SET_TELEMETRY_MV (11)
+#define TH_DECCTL_SET_TELEMETRY_QI (13)
+#define TH_DECCTL_SET_TELEMETRY_BITS (15)
 
 /**\anchor encctlcodes
  * These are the available request codes for theora_control()

Modified: branches/theora-gumboot/include/theora/theoradec.h
===================================================================
--- branches/theora-gumboot/include/theora/theoradec.h	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/include/theora/theoradec.h	2009-07-18 15:06:53 UTC (rev 16301)
@@ -87,6 +87,8 @@
 
 #define TH_DECCTL_SET_TELEMETRY_MBMODE (9)
 #define TH_DECCTL_SET_TELEMETRY_MV (11)
+#define TH_DECCTL_SET_TELEMETRY_QI (13)
+#define TH_DECCTL_SET_TELEMETRY_BITS (15)
 
 
 

Modified: branches/theora-gumboot/lib/dec/bitpack.c
===================================================================
--- branches/theora-gumboot/lib/dec/bitpack.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/bitpack.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -74,7 +74,7 @@
   window=_b->window;
   available=_b->bits;
   if(_bits==0)return 0;
-  if(_bits>available){
+  if(available<_bits){
     window=oc_pack_refill(_b,_bits);
     available=_b->bits;
   }

Modified: branches/theora-gumboot/lib/dec/decint.h
===================================================================
--- branches/theora-gumboot/lib/dec/decint.h	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/decint.h	2009-07-18 15:06:53 UTC (rev 16301)
@@ -92,6 +92,16 @@
   int                  telemetry;
   int                  telemetry_mbmode;
   int                  telemetry_mv;
+  int                  telemetry_qi;
+  int                  telemetry_bits;
+
+  int                  telemetry_frame_bytes;
+  int                  telemetry_coding_bytes;
+  int                  telemetry_mode_bytes;
+  int                  telemetry_mv_bytes;
+  int                  telemetry_qi_bytes;
+  int                  telemetry_dc_bytes;
+
   unsigned char       *telemetry_frame_data;
 # endif
 };

Modified: branches/theora-gumboot/lib/dec/decode.c
===================================================================
--- branches/theora-gumboot/lib/dec/decode.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/decode.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -327,6 +327,8 @@
   _dec->stripe_cb.stripe_decoded=NULL;
 #if defined(HAVE_CAIRO)
   _dec->telemetry=0;
+  _dec->telemetry_bits=0;
+  _dec->telemetry_qi=0;
   _dec->telemetry_mbmode=0;
   _dec->telemetry_mv=0;
   _dec->telemetry_frame_data=NULL;
@@ -424,6 +426,7 @@
     _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis;
     prev_ncoded_fragis=ncoded_fragis;
   }
+  _dec->state.ntotal_coded_fragis=ncoded_fragis;
 }
 
 /*Decodes the bit flags indicating whether each super block is partially coded
@@ -441,7 +444,7 @@
   flag=(int)val;
   sb_flags=_dec->state.sb_flags;
   nsbs=_dec->state.nsbs;
-  sbi=run_count=npartial=0;
+  sbi=npartial=0;
   while(sbi<nsbs){
     int full_run;
     run_count=oc_sb_run_unpack(&_dec->opb);
@@ -563,6 +566,7 @@
     _dec->state.ncoded_fragis[pli]=ncoded_fragis-prev_ncoded_fragis;
     prev_ncoded_fragis=ncoded_fragis;
   }
+  _dec->state.ntotal_coded_fragis=ncoded_fragis;
   /*TODO: run_count should be 0 here.
     If it's not, we should issue a warning of some kind.*/
 }
@@ -819,7 +823,7 @@
       with the corresponding qi's for this frame.*/
     val=oc_pack_read1(&_dec->opb);
     flag=(int)val;
-    run_count=nqi1=0;
+    nqi1=0;
     fragii=0;
     while(fragii<ncoded_fragis){
       int full_run;
@@ -1071,6 +1075,10 @@
   huff_idxs[1]=(int)val;
   _dec->eob_runs[0][0]=0;
   eobs=oc_dec_dc_coeff_unpack(_dec,huff_idxs,ntoks_left);
+#if defined(HAVE_CAIRO)
+  _dec->telemetry_dc_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
+
   val=oc_pack_read(&_dec->opb,4);
   huff_idxs[0]=(int)val;
   val=oc_pack_read(&_dec->opb,4);
@@ -1083,6 +1091,7 @@
       eobs=oc_dec_ac_coeff_unpack(_dec,zzi,huff_idxs,ntoks_left,eobs);
     }
   }
+
   /*TODO: eobs should be exactly zero, or 4096 or greater.
     The second case occurs when an EOB run of size zero is encountered, which
      gets treated as an infinite EOB run (where infinity is PTRDIFF_MAX).
@@ -1891,6 +1900,20 @@
     _dec->telemetry_mv=*(int *)_buf;
     return 0;
   }break;
+  case TH_DECCTL_SET_TELEMETRY_QI:{
+    if(_dec==NULL||_buf==NULL)return TH_EFAULT;
+    if(_buf_sz!=sizeof(int))return TH_EINVAL;
+    _dec->telemetry=1;
+    _dec->telemetry_qi=*(int *)_buf;
+    return 0;
+  }break;
+  case TH_DECCTL_SET_TELEMETRY_BITS:{
+    if(_dec==NULL||_buf==NULL)return TH_EFAULT;
+    if(_buf_sz!=sizeof(int))return TH_EINVAL;
+    _dec->telemetry=1;
+    _dec->telemetry_bits=*(int *)_buf;
+    return 0;
+  }break;
 #endif
   default:return TH_EIMPL;
   }
@@ -1912,7 +1935,12 @@
     int                   notstart;
     int                   notdone;
     oc_pack_readinit(&_dec->opb,_op->packet,_op->bytes);
+#if defined(HAVE_CAIRO)
+    _dec->telemetry_frame_bytes = _op->bytes;
+#endif
+
     ret=oc_dec_frame_header_unpack(_dec);
+
     if(ret<0)return ret;
     /*Select a free buffer to use for the reconstructed version of this
        frame.*/
@@ -1949,12 +1977,29 @@
     if(_dec->state.frame_type==OC_INTRA_FRAME){
       oc_dec_mark_all_intra(_dec);
       _dec->state.keyframe_num=_dec->state.curframe_num;
+#if defined(HAVE_CAIRO)
+      _dec->telemetry_coding_bytes =
+        _dec->telemetry_mode_bytes =
+        _dec->telemetry_mv_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
     }else{
       oc_dec_coded_flags_unpack(_dec);
+#if defined(HAVE_CAIRO)
+      _dec->telemetry_coding_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
       oc_dec_mb_modes_unpack(_dec);
+#if defined(HAVE_CAIRO)
+      _dec->telemetry_mode_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
       oc_dec_mv_unpack_and_frag_modes_fill(_dec);
+#if defined(HAVE_CAIRO)
+      _dec->telemetry_mv_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
     }
     oc_dec_block_qis_unpack(_dec);
+#if defined(HAVE_CAIRO)
+    _dec->telemetry_qi_bytes = oc_pack_bytes_left(&_dec->opb);
+#endif
     oc_dec_residual_tokens_unpack(_dec);
     /*Update granule position.
       This must be done before the striped decode callbacks so that the
@@ -2105,6 +2150,7 @@
 }
 
 int th_decode_ycbcr_out(th_dec_ctx *_dec,th_ycbcr_buffer _ycbcr){
+  if(_dec==NULL||_ycbcr==NULL)return TH_EFAULT;
   oc_ycbcr_buffer_flip(_ycbcr,_dec->pp_frame_buf);
 #if defined(HAVE_CAIRO)
   /*If telemetry ioctls are active, we need to draw to the output buffer.
@@ -2162,6 +2208,7 @@
       v_row+=_ycbcr[2].stride&-((y&1)|!vdec);
       rgb_row+=cstride;
     }
+
     /*Draw coded identifier for each macroblock (stored in Hilbert order).*/
     {
       cairo_t           *c;
@@ -2173,6 +2220,48 @@
       size_t             mbi;
       int                row2;
       int                col2;
+      int                qim[3]={0,0,0};
+
+      if(_dec->state.nqis==2){
+        int bqi = _dec->state.qis[0];
+        if(_dec->state.qis[1]>bqi)
+          qim[1]=1;
+        if(_dec->state.qis[1]<bqi)
+          qim[1]=-1;
+      }
+      if(_dec->state.nqis==3){
+        int bqi = _dec->state.qis[0];
+        int cqi = _dec->state.qis[1];
+        int dqi = _dec->state.qis[2];
+        if(cqi>bqi && dqi>bqi){
+          if(dqi>cqi){
+            qim[1]=1;
+            qim[2]=2;
+          }else{
+            qim[1]=2;
+            qim[2]=1;
+          }
+        }else if (cqi<bqi && dqi<bqi){
+          if(dqi<cqi){
+            qim[1]=-1;
+            qim[2]=-2;
+          }else{
+            qim[1]=-2;
+            qim[2]=-1;
+          }
+        }else{
+          if(cqi<bqi)
+            qim[1]=-1;
+          else
+            qim[1]=1;
+
+          if(dqi<bqi)
+            qim[2]=-1;
+          else
+            qim[2]=1;
+        }
+      }
+
       c=cairo_create(cs);
       frags=_dec->state.frags;
       frag_mvs=_dec->state.frag_mvs;
@@ -2188,6 +2277,8 @@
         y=h-(row2+((col2+1>>1)&1))*16-16;
         x=(col2>>1)*16;
         cairo_set_line_width(c,1.);
+
+        /* keyframe (all intra) red box */
         if(_dec->state.frame_type==OC_INTRA_FRAME){
           if(_dec->telemetry_mbmode&0x02){
             cairo_set_source_rgba(c,1.,0,0,.5);
@@ -2399,12 +2490,173 @@
             }
           }
         }
+
+        /* qii illustration */
+        if(_dec->telemetry_qi&0x2){
+          for(bi=0;bi<4;bi++){
+            int qiv,xp=x+(bi&1)*8,yp=y+8-(bi&2)*4;
+            int fragi=mb_maps[mbi][0][bi];
+            if(fragi>=0&&frags[fragi].coded){
+              qiv=qim[frags[fragi].qii];
+
+              switch(qiv){
+              case 2:
+              /* double plus */
+                if((bi&1)^((bi&2)>>1)){
+                  cairo_move_to(c,xp+2.5,yp+1.5);
+                  cairo_line_to(c,xp+2.5,yp+3.5);
+                  cairo_move_to(c,xp+1.5,yp+2.5);
+                  cairo_line_to(c,xp+3.5,yp+2.5);
+                  cairo_move_to(c,xp+5.5,yp+4.5);
+                  cairo_line_to(c,xp+5.5,yp+6.5);
+                  cairo_move_to(c,xp+4.5,yp+5.5);
+                  cairo_line_to(c,xp+6.5,yp+5.5);
+                }else{
+                  cairo_move_to(c,xp+5.5,yp+1.5);
+                  cairo_line_to(c,xp+5.5,yp+3.5);
+                  cairo_move_to(c,xp+4.5,yp+2.5);
+                  cairo_line_to(c,xp+6.5,yp+2.5);
+                  cairo_move_to(c,xp+2.5,yp+4.5);
+                  cairo_line_to(c,xp+2.5,yp+6.5);
+                  cairo_move_to(c,xp+1.5,yp+5.5);
+                  cairo_line_to(c,xp+3.5,yp+5.5);
+                }
+                break;
+
+              case -2:
+                /* double minus */
+                cairo_move_to(c,xp+2.5,yp+2.5);
+                cairo_line_to(c,xp+5.5,yp+2.5);
+                cairo_move_to(c,xp+2.5,yp+5.5);
+                cairo_line_to(c,xp+5.5,yp+5.5);
+                break;
+
+              case 1:
+                /* plus */
+                if(bi&2==0)yp-=2;
+                if(bi&1==0)xp-=2;
+                cairo_move_to(c,xp+4.5,yp+2.5);
+                cairo_line_to(c,xp+4.5,yp+6.5);
+              case -1:
+                cairo_move_to(c,xp+2.5,yp+4.5);
+                cairo_line_to(c,xp+6.5,yp+4.5);
+                break;
+              default:
+                continue;
+              }
+
+              cairo_stroke_preserve(c);
+              cairo_set_source_rgba(c,1.,1.,1.,1.);
+              cairo_set_line_width(c,1.);
+              cairo_stroke(c);
+              cairo_set_line_width(c,3.);
+              cairo_set_source_rgba(c,0.,0.,0.,.5);
+            }
+          }
+        }
+
         col2++;
         if((col2>>1)>=_dec->state.nhmbs){
           col2=0;
           row2+=2;
         }
       }
+
+      /* bit usage indicator[s] */
+      if(_dec->telemetry_bits){
+        int fpsn = _dec->state.info.fps_numerator;
+        int fpsd = _dec->state.info.fps_denominator;
+        int mult = (_dec->telemetry_bits>=0xff?1:_dec->telemetry_bits);
+        int fullw = 250*h*fpsd*mult/fpsn;
+        int widths[6];
+        int i;
+        int padw=w-24;
+
+        /* header and coded block bits */
+        widths[0] = padw * (_dec->telemetry_frame_bytes-_dec->telemetry_coding_bytes) / fullw;
+        widths[1] = padw * (_dec->telemetry_coding_bytes-_dec->telemetry_mode_bytes) / fullw;
+        widths[2] = padw * (_dec->telemetry_mode_bytes-_dec->telemetry_mv_bytes) / fullw;
+        widths[3] = padw * (_dec->telemetry_mv_bytes-_dec->telemetry_qi_bytes) / fullw;
+        widths[4] = padw * (_dec->telemetry_qi_bytes-_dec->telemetry_dc_bytes) / fullw;
+        widths[5] = padw * (_dec->telemetry_dc_bytes) / fullw;
+
+        for(i=0;i<6;i++) if(widths[i]>w) widths[i]=w;
+
+        cairo_set_source_rgba (c, .0,.0,.0,.6);
+        cairo_rectangle(c,10,h-33,widths[0]+1,5);
+        cairo_rectangle(c,10,h-29,widths[1]+1,5);
+        cairo_rectangle(c,10,h-25,widths[2]+1,5);
+        cairo_rectangle(c,10,h-21,widths[3]+1,5);
+        cairo_rectangle(c,10,h-17,widths[4]+1,5);
+        cairo_rectangle(c,10,h-13,widths[5]+1,5);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, 1,0,0);
+        cairo_rectangle(c,10.5,h-32.5,widths[0],4);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, 0,1,0);
+        cairo_rectangle(c,10.5,h-28.5,widths[1],4);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, 0,0,1);
+        cairo_rectangle(c,10.5,h-24.5,widths[2],4);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, .6,.4,.0);
+        cairo_rectangle(c,10.5,h-20.5,widths[3],4);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, .3,.3,.3);
+        cairo_rectangle(c,10.5,h-16.5,widths[4],4);
+        cairo_fill(c);
+
+        cairo_set_source_rgb (c, .5,.5,.8);
+        cairo_rectangle(c,10.5,h-12.5,widths[5],4);
+        cairo_fill(c);
+
+      }
+
+      /* master qi indicator[s] */
+      if(_dec->telemetry_qi&0x1){
+        cairo_text_extents_t extents;
+        char buffer[10];
+        int p=0;
+        int y = h-7.5;
+
+        if(_dec->state.qis[0]>10)
+          buffer[p++]=48+_dec->state.qis[0]/10;
+        buffer[p++]=48+_dec->state.qis[0]%10;
+        if(_dec->state.nqis>=2){
+          buffer[p++]=' ';
+          if(_dec->state.qis[1]>10)
+            buffer[p++]=48+_dec->state.qis[1]/10;
+          buffer[p++]=48+_dec->state.qis[1]%10;
+        }
+        if(_dec->state.nqis==3){
+          buffer[p++]=' ';
+          if(_dec->state.qis[2]>10)
+            buffer[p++]=48+_dec->state.qis[2]/10;
+          buffer[p++]=48+_dec->state.qis[2]%10;
+        }
+        buffer[p++]='\0';
+
+        cairo_select_font_face (c, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
+        cairo_set_font_size(c, 18);
+        cairo_text_extents(c, buffer, &extents);
+
+        cairo_set_source_rgb (c, 1,1,1);
+        cairo_move_to(c, w-extents.x_advance-10, y);
+        cairo_show_text(c, buffer);
+
+        cairo_set_source_rgb (c, 0,0,0);
+        cairo_move_to(c, w-extents.x_advance-10, y);
+        cairo_text_path (c, buffer);
+        cairo_set_line_width(c,.8);
+        cairo_set_line_join(c,CAIRO_LINE_JOIN_ROUND);
+        cairo_stroke(c);
+      }
+
       cairo_destroy(c);
     }
     /*Out of the Cairo plane into the telemetry YUV buffer.*/

Modified: branches/theora-gumboot/lib/dec/huffdec.c
===================================================================
--- branches/theora-gumboot/lib/dec/huffdec.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/huffdec.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -76,7 +76,7 @@
   Declaring local static versions so they can be inlined saves considerable
    function call overhead.*/
 
-static oc_pb_window inline oc_pack_refill(oc_pack_buf *_b,int _bits){
+static oc_pb_window oc_pack_refill(oc_pack_buf *_b,int _bits){
   const unsigned char *ptr;
   const unsigned char *stop;
   oc_pb_window         window;
@@ -116,15 +116,12 @@
 
 /*Advance the bit pointer.*/
 static void oc_pack_adv(oc_pack_buf *_b,int _bits){
-  oc_pb_window window;
-  window=_b->window;
   /*We ignore the special cases for _bits==0 and _bits==32 here, since they are
      never used actually used.
     OC_HUFF_SLUSH (defined below) would have to be at least 27 to actually read
      32 bits in a single go, and would require a 32 GB lookup table (assuming
      8 byte pointers, since 4 byte pointers couldn't fit such a table).*/
-  window<<=_bits;
-  _b->window=window;
+  _b->window<<=_bits;
   _b->bits-=_bits;
 }
 

Modified: branches/theora-gumboot/lib/dec/x86/mmxstate.c
===================================================================
--- branches/theora-gumboot/lib/dec/x86/mmxstate.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/x86/mmxstate.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -114,7 +114,7 @@
   int                  ystride;
   dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
   src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
-  ystride=_state->ref_frame_bufs[0][_pli].stride;
+  ystride=_state->ref_ystride[_pli];
   frag_buf_offs=_state->frag_buf_offs;
   for(fragii=0;fragii<_nfragis;fragii++){
     ptrdiff_t frag_buf_off;

Modified: branches/theora-gumboot/lib/dec/x86_vc/mmxstate.c
===================================================================
--- branches/theora-gumboot/lib/dec/x86_vc/mmxstate.c	2009-07-18 09:38:33 UTC (rev 16300)
+++ branches/theora-gumboot/lib/dec/x86_vc/mmxstate.c	2009-07-18 15:06:53 UTC (rev 16301)
@@ -117,7 +117,7 @@
   int                  ystride;
   dst_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_dst_frame]];
   src_frame_data=_state->ref_frame_data[_state->ref_frame_idx[_src_frame]];
-  ystride=_state->ref_frame_bufs[0][_pli].stride;
+  ystride=_state->ref_ystride[_pli];
   frag_buf_offs=_state->frag_buf_offs;
   for(fragii=0;fragii<_nfragis;fragii++){
     ptrdiff_t frag_buf_off;



More information about the commits mailing list