[xiph-commits] r9135 - experimental/giles/theora-exp-mt/examples

giles at motherfish-iii.xiph.org giles at motherfish-iii.xiph.org
Wed Apr 13 19:44:23 PDT 2005


Author: giles
Date: 2005-04-13 19:44:22 -0700 (Wed, 13 Apr 2005)
New Revision: 9135

Modified:
   experimental/giles/theora-exp-mt/examples/player_example.c
Log:
Add stripe-decode callback support and optional multithreaded video
playback to the example player.


Modified: experimental/giles/theora-exp-mt/examples/player_example.c
===================================================================
--- experimental/giles/theora-exp-mt/examples/player_example.c	2005-04-14 02:41:42 UTC (rev 9134)
+++ experimental/giles/theora-exp-mt/examples/player_example.c	2005-04-14 02:44:22 UTC (rev 9135)
@@ -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-2003                *
+ * THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2005                *
  * by the Xiph.Org Foundation http://www.xiph.org/                  *
  *                                                                  *
  ********************************************************************
@@ -48,6 +48,9 @@
 #include <fcntl.h>
 #include <math.h>
 #include <signal.h>
+#ifdef HAVE_PTHREAD 
+# include <pthread.h> /* should use SDL threads instead? */
+#endif
 #include "theora/theora.h"
 #include "vorbis/codec.h"
 #include <SDL.h>
@@ -106,6 +109,9 @@
 int          videobuf_ready=0;
 ogg_int64_t  videobuf_granulepos=-1;
 double       videobuf_time=0;
+#ifdef HAVE_PTHREAD
+pthread_mutex_t videobuf_mutex; /* clear when ready to show a frame */
+#endif
 
 /* single audio fragment audio buffering */
 int          audiobuf_fill=0;
@@ -297,7 +303,61 @@
   got_sigint = 1;
 }
 
+static void video_stripe_copy(void *_ctx, theora_ycbcr_buffer _src,
+ int _fragy0, int _fragy_end){
+  static const int planemap[3] = {0,2,1};
+  int pli;
+  int wscale, hscale;
+  int crop_offset;
+  int y, ystart, yend;
+
+  /* Lock SDL overlay */
+  if (SDL_LockYUVOverlay(yuv_overlay) < 0) return;
+
+  /* copy the stripe into the SDL buffer */
+  for(pli=0;pli<3;pli++){
+    wscale = _src[0].width / _src[pli].width;
+    hscale = _src[0].height / _src[pli].height;
+    ystart = _fragy0*8/hscale;
+    yend = _fragy_end*8/hscale;
+    crop_offset = (ti.pic_x / wscale)
+                + (_src[pli].ystride)
+                * (ti.pic_y / hscale);
+    for(y=ystart;y<yend;y++)
+      memcpy(yuv_overlay->pixels[planemap[pli]]
+                      + yuv_overlay->pitches[planemap[pli]]*y,
+             _src[pli].data+crop_offset+_src[pli].ystride*y,
+             yuv_overlay->w / wscale); 
+  }
+
+  /* Unlock SDL overlay */
+  SDL_UnlockYUVOverlay(yuv_overlay);
+
+}
+
+#ifdef HAVE_PTHREAD
+static void *video_write_loop(void *arg){
+  int min_delay = 1000.0 * ti.fps_denominator/ti.fps_numerator;
+  while(1){
+    /* wait until a frame is ready */
+    pthread_mutex_lock(&videobuf_mutex);
+    if(videobuf_ready){
+      /* Show, baby, show! */
+      SDL_DisplayYUVOverlay(yuv_overlay, &rect);
+      videobuf_ready=0;
+      pthread_mutex_unlock(&videobuf_mutex);
+    }else{
+      pthread_mutex_unlock(&videobuf_mutex);
+      SDL_Delay(min_delay);
+    }
+  }
+  return NULL;
+}
+#endif
+
 static void open_video(void){
+  theora_stripe_callback cb;
+
   if ( SDL_Init(SDL_INIT_VIDEO) < 0 ) {
     fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
     exit(1);
@@ -323,6 +383,11 @@
   rect.w = ti.pic_width;
   rect.h = ti.pic_height;
 
+  /* install stripe callback */
+  cb.ctx = yuv_overlay;
+  cb.stripe_decoded=(theora_stripe_decoded_func)video_stripe_copy;
+  theora_decode_ctl(td,OC_DECCTL_SET_STRIPE_CB,&cb,sizeof(cb));
+
   SDL_DisplayYUVOverlay(yuv_overlay, &rect);
 }
 
@@ -444,6 +509,13 @@
 
   FILE *infile = stdin;
 
+  int frames = 0;
+  int dropped = 0;
+
+#ifdef HAVE_PTHREAD
+  pthread_t video_thread;
+#endif
+
 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn 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. */
@@ -601,6 +673,17 @@
     vorbis_comment_clear(&vc);
   }
 
+  /* initialize video playback thread */
+#ifdef HAVE_PTHREAD
+  pthread_mutex_init(&videobuf_mutex, NULL);
+  /* hold for a video frame */
+  pthread_mutex_lock(&videobuf_mutex);
+  videobuf_ready = 0;
+  /* spawn the display loop */
+  pthread_create(&video_thread, NULL, video_write_loop, NULL);
+  pthread_mutex_unlock(&videobuf_mutex);
+#endif
+
   /* open audio */
   if(vorbis_p)open_audio();
 
@@ -678,6 +761,7 @@
         }
         if(theora_decode_packetin(td,&op,&videobuf_granulepos)>=0){
           videobuf_time=theora_granule_time(td,videobuf_granulepos);
+	  frames++;
 
           /* is it already too old to be useful?  This is only actually
              useful cosmetically after a SIGSTOP.  Note that we have to
@@ -685,10 +769,16 @@
              keyframing.  Soon enough libtheora will be able to deal
              with non-keyframe seeks.  */
 
-          if(videobuf_time>=get_time())
+          if(videobuf_time-get_time()>=0){
+#ifdef HAVE_PTHREAD
+	    pthread_mutex_lock(&videobuf_mutex);
+#endif
             videobuf_ready=1;
-          /*If we are too slow, reduce the pp level.*/
-          else pp_inc=pp_level>0?-1:0;
+          }else{
+            /*If we are too slow, reduce the pp level.*/
+            pp_inc=pp_level>0?-1:0;
+	    dropped++;
+          }
         }
 
       }else
@@ -710,8 +800,12 @@
 
     /* are we at or past time for this video frame? */
     if(stateflag && videobuf_ready && videobuf_time<=get_time()){
-      video_write();
+#ifdef HAVE_PTHREAD
+      pthread_mutex_unlock(&videobuf_mutex);
+#else
+      SDL_DisplayYUVOverlay(yuv_overlay, &rect);
       videobuf_ready=0;
+#endif
     }
 
     if(stateflag &&
@@ -792,8 +886,12 @@
   if(infile && infile!=stdin)fclose(infile);
 
   fprintf(stderr,
-          "\r                                                              "
-          "\nDone.\n");
+          "\r                                                              \r");
+  fprintf(stderr, "%d frames", frames);
+  if (dropped) fprintf(stderr, " (%d dropped)", dropped);
+  fprintf(stderr, "\n");
+  fprintf(stderr, "\nDone.\n");
+
   return(0);
 
 }



More information about the commits mailing list