[xiph-commits] r3046 - liboggplay/trunk/plugin

laser13 at svn.annodex.net laser13 at svn.annodex.net
Mon Jun 25 05:15:46 PDT 2007


Author: laser13
Date: 2007-06-25 05:15:46 -0700 (Mon, 25 Jun 2007)
New Revision: 3046

Modified:
   liboggplay/trunk/plugin/plugin_gui_win32.c
Log:
Audio for Win32. Still in some cases hangs...

Modified: liboggplay/trunk/plugin/plugin_gui_win32.c
===================================================================
--- liboggplay/trunk/plugin/plugin_gui_win32.c	2007-06-25 12:10:37 UTC (rev 3045)
+++ liboggplay/trunk/plugin/plugin_gui_win32.c	2007-06-25 12:15:46 UTC (rev 3046)
@@ -44,19 +44,22 @@
 
 #include "plugin_gui.h"
 #include "plugin_oggplay.h"
+#include <oggplay/oggplay_tools.h>
 
+#define OGGPLAY_FRAME_SKIP_OFFSET -30
+#define OGGPLAY_MIN_OFFSET        2
+
 typedef struct {
   // window related data
   int                 width;
   int                 height;
   // video frame
   PluginOggFrame*     frame_data;
-  HWND                window;
-  HWND                parent_window;
+  HWND                window;  
   WNDPROC             old_wnd_proc;
   HANDLE              thread;  
   int                 shutdown_gui;
-  void            *   ogg_handle;
+  void            *   oggplay_handle;
   semaphore           oggplay_replace_sem;
   semaphore           start_stop_sem;
   semaphore           playback_sem;
@@ -65,9 +68,9 @@
   void            *   new_oggplay_handle;
 #ifdef USE_AUDIO
   sa_stream_t     *   audio_handle;
-#endif
-  BOOL        	      audio_opened;
-  unsigned int        playback_target;  
+  BOOL                audio_ok;  
+#endif  
+  BOOL        	      audio_opened;  
   nsPluginInstance *  plugin_instance;
 } PluginWindowInfo;
 
@@ -77,22 +80,58 @@
 
   BOOL rv = FALSE;
   void * old_ogg_handle;
-        
-  if (info->new_oggplay_handle != NULL) {    
+    
+  if (info->new_oggplay_handle != NULL) { 
     SEM_WAIT(info->oggplay_replace_sem);
-    printf("Switch oggplay before!!!\n");      
-    old_ogg_handle = info->ogg_handle;
-    info->ogg_handle = (void *)info->new_oggplay_handle;
-    info->new_oggplay_handle = NULL;      
-    printf("Switch oggplay after!!!\n");
-    SEM_SIGNAL(info->oggplay_replace_sem);     
-    shut_oggplay(old_ogg_handle);      
-    rv = TRUE; 
-  }    
+    if (info->new_oggplay_handle != NULL) {
+      printf("Switch oggplay before!!!\n");      
+      old_ogg_handle = info->oggplay_handle;
+      info->oggplay_handle = (void *)info->new_oggplay_handle;
+      info->new_oggplay_handle = NULL;      
+      printf("Switch oggplay after!!!\n");
+      shut_oggplay(old_ogg_handle);      
+      rv = TRUE;
+    }
+    SEM_SIGNAL(info->oggplay_replace_sem); 
+  }  
   return rv;
 }
 
+#ifdef USE_AUDIO
+static void
+open_audio(PluginWindowInfo *info) {
+  
+  info->audio_opened = TRUE;
 
+  if (sa_stream_create_pcm(&(info->audio_handle), NULL,
+        SA_MODE_WRONLY, SA_PCM_FORMAT_S16_NE,
+        get_audio_rate(info->oggplay_handle),
+        get_audio_channels(info->oggplay_handle)) != SA_SUCCESS
+  ) {
+    info->audio_opened = FALSE;
+    info->audio_handle = NULL;    
+    return;
+  }
+  if (sa_stream_open(info->audio_handle) != SA_SUCCESS) {
+    info->audio_opened = FALSE;
+    info->audio_handle = NULL;    
+    return;
+  }
+  printf("Audio device opened\n");
+  return;
+}
+
+static void 
+close_audio(PluginWindowInfo *info) {
+  if (info->audio_handle != NULL) {
+    sa_stream_destroy(info->audio_handle);
+    info->audio_handle = NULL;
+    info->audio_opened = FALSE;
+    printf("Closed audio device\n");
+  }
+}
+#endif
+
 /**
  * \brief display_thread - main loop do the tread responsible for display 
  * \param [in] _info - PluginWindowInfo stucture 
@@ -100,49 +139,92 @@
 DWORD WINAPI display_thread(void *_info) {  
   HWND                hWnd;  
   RECT                r;  
+  __int64             playback_target;  
+  __int64             ref_time;
+  DWORD               offset;
+#ifdef USE_AUDIO      
+  __int64             bytes;
+#endif
   PluginWindowInfo *  info = (PluginWindowInfo*)_info;    
   
-
+  /* initialise variables */
+  playback_target = 0;
+  ref_time = 0;
   info->shutdown_gui = 0;
   hWnd = (HWND)(info->window);
+
   /* signal that thread has been started sucessfully */
   SEM_SIGNAL(info->start_stop_sem);  
 
-  while (1) {    
-    
-    // fall through once so we can display first 
-    // frame of a new video
-    if (info->playback_state == PAUSED) {      
-      SEM_WAIT(info->playback_sem);     
+  while (!info->shutdown_gui) {        
+    // check if we should pause display
+    if (info->playback_state == PAUSED) {
+#ifdef USE_AUDIO      
+      sa_stream_pause(info->audio_handle);
+      SEM_WAIT(info->playback_sem);
+      sa_stream_resume(info->audio_handle);
+#else
+      SEM_WAIT(info->playback_sem);
+#endif
     }        
 
     // check if plugin hasn't been shut down
-    if (info->shutdown_gui) {        
-      info->shutdown_gui = 0;        
-      ExitThread(0);
+    if (info->shutdown_gui) {      
+      break;
     }
      
-    /*
-     * Do not send WM_PAINT messages while waiting for GUI to shutdown.
-     * This is asynchronous call so all calls to plugin_oggplay functions are
-     * in the GUI message processing callback.
-     */
-    if (!info->shutdown_gui) {             
-      // force refresh    
-      GetClientRect(hWnd, &r);      
-      InvalidateRect(hWnd, &r, FALSE);     
-      UpdateWindow(hWnd);             
-      SEM_WAIT(info->synch_sem); 
-      // check if we should pause display      
-    }      
+   /*
+    * Do not send WM_PAINT messages while waiting for GUI to shutdown.
+    * This is asynchronous call so all calls to plugin_oggplay functions are
+    * in the GUI message processing callback.
+    */    
+    // force refresh    
+    GetClientRect(hWnd, &r);      
+    InvalidateRect(hWnd, &r, FALSE);     
+    UpdateWindow(hWnd);    
+    SEM_WAIT(info->synch_sem);       
+
+#ifdef USE_AUDIO
+    if ((info->audio_opened == TRUE) && (info->audio_ok == TRUE)) {
+      // calculate audio playback progress based on number of audio samples played    
+      if (sa_stream_get_position(info->audio_handle, 
+              SA_POSITION_WRITE_SOFTWARE, &bytes) != SA_SUCCESS) {
+        ref_time = oggplay_sys_time_in_ms();
+      } else {
+        ref_time = (bytes * 1000 / get_audio_rate(info->oggplay_handle) / 
+                        (sizeof(short) * get_audio_channels(info->oggplay_handle)));
+      }
+    } else 
+#endif
+    {
+      ref_time = oggplay_sys_time_in_ms();
+    }
     
-    Sleep(40);            
-
+    // calculate how long we should wait with processing the next frame
+    playback_target += get_callback_period(info->oggplay_handle) >> 16;
+    offset = (DWORD)(playback_target - ref_time);    
+    offset = (offset > 0) ? offset : OGGPLAY_MIN_OFFSET;
+   
     /* try switching oggplays */
-    switch_oggplays(info);           
+    if (switch_oggplays(info) == TRUE) {
+      offset = 10;
+    }
     
+    // Now just wait...
+    Sleep(40);
+    
   }
   
+  if (info->shutdown_gui) {
+    info->shutdown_gui = 0;
+#ifdef USE_AUDIO      
+    if (info->audio_opened == TRUE) {
+      close_audio(info);
+    }
+#endif
+    ExitThread(0);  
+  }
+     
   return 0;
 }
 /*!
@@ -165,7 +247,7 @@
   info = (PluginWindowInfo*)malloc(sizeof(PluginWindowInfo));
   info->width = np_window->width;
   info->height = np_window->height;  
-  info->ogg_handle = oggplay_handle;
+  info->oggplay_handle = oggplay_handle;
   info->frame_data = (PluginOggFrame*)malloc(sizeof(PluginOggFrame));
   info->frame_data->frame = NULL;
   info->frame_data->samples = NULL;
@@ -174,9 +256,15 @@
   info->window = hWnd;
   info->new_oggplay_handle = NULL;
   info->playback_state = PLAYING;
-  /* calback members initialisation */
+  /* initialisation of callback related variables */
   info->plugin_instance = instance;
-  
+  /* audio and synchronisation related variables */
+  info->audio_opened = FALSE;  
+#ifdef USE_AUDIO
+  info->audio_handle = NULL;
+  info->audio_ok = FALSE;
+#endif
+
   /*
    * create semaphore to lock replacement of oggplay object
    */
@@ -236,14 +324,14 @@
     Sleep(10);
   }  
   
-  shut_oggplay(info->ogg_handle);  
+  shut_oggplay(info->oggplay_handle);  
 
   SEM_CLOSE(info->start_stop_sem);  
   SEM_CLOSE(info->oggplay_replace_sem);  
   SEM_CLOSE(info->playback_sem);  
 
   if (info->frame_data != NULL) {
-    //free(info->frame_data);  
+    free(info->frame_data);  
   }  
   free(info);
   
@@ -334,15 +422,15 @@
   BOOL          has_audio = FALSE;
   BOOL          has_video = FALSE;
   BOOL          has_cmml = FALSE;
-  
+    
   // filter early and random *broken* WM_PAINT messages  
-  if (info == NULL) {
+  if (info == NULL) {        
     SEM_SIGNAL(info->synch_sem);
     return;  
-  }
+  }  
 
-  get_oggplay_frame(info->ogg_handle, info->frame_data);    
-  convert_oggplay_frame(info->ogg_handle, info->frame_data, BGR);
+  get_oggplay_frame(info->oggplay_handle, info->frame_data);    
+  convert_oggplay_frame(info->oggplay_handle, info->frame_data, BGR);
 
   has_video = ((info->frame_data->video_data != NULL) && (info->frame_data->frame != NULL)) ? TRUE : FALSE;
   has_audio = ((info->frame_data->samples != NULL) && (info->frame_data->size > 0)) ? TRUE : FALSE;
@@ -353,12 +441,30 @@
     /* && (has_cmml) */
   ) {
     //SEM_SIGNAL(info->synch_sem);
-    //return;    
+    //return;
     goto cleanup;    
   }
   /* display frame */
-  update_frame(info);
+  update_frame(info);  
 
+#ifdef USE_AUDIO
+  if (has_audio == TRUE) {    
+    /* open audio if not opened */
+    if (info->audio_opened == FALSE) {      
+      open_audio(info);
+    }
+    /* if audio device is opened try writing data */
+    if (info->audio_opened == TRUE) {
+      info->audio_ok = TRUE;
+      if (sa_stream_write(info->audio_handle, 
+            info->frame_data->samples, 
+            info->frame_data->size) != SA_SUCCESS) {
+        info->audio_ok = FALSE;
+      }
+    }
+  }
+#endif
+
   /* call CMML data callback using plugin's main thread call */
   if (has_cmml == TRUE) {    
     onCMMLData(info->plugin_instance, info->frame_data->cmml_strings, info->frame_data->cmml_size);      
@@ -367,7 +473,7 @@
 cleanup:
   SEM_SIGNAL(info->synch_sem);
   // progress with decoding  
-  free_oggplay_frame(info->ogg_handle, info->frame_data);  
+  free_oggplay_frame(info->oggplay_handle, info->frame_data);  
   return;
 }
 
@@ -409,7 +515,7 @@
     printf("early shutting aborted oggplay at %p\n", info->new_oggplay_handle);
     shut_oggplay(info->new_oggplay_handle);
   }
-  info->new_oggplay_handle = oggplay_handle; 
+  info->new_oggplay_handle = oggplay_handle;
   printf("update_gui_with_new_oggplay new handle passed\n");
   SEM_SIGNAL(info->oggplay_replace_sem); 
   
@@ -441,7 +547,7 @@
       break;
     case FINISHED: 
       state = 2;    
-      break;    
+      break;
     default:
       /* error state: should never be returned */
       state = -1;



More information about the commits mailing list