[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