diff --git a/dlls/winegstreamer/gst_cbs.c b/dlls/winegstreamer/gst_cbs.c index 71c8180098f..a0618798d89 100644 --- a/dlls/winegstreamer/gst_cbs.c +++ b/dlls/winegstreamer/gst_cbs.c @@ -20,10 +20,76 @@ #include +#include "objbase.h" + #include "wine/list.h" #include "gst_cbs.h" +static pthread_key_t wine_gst_key; + +void mark_wine_thread(void) +{ + /* set it to non-NULL to indicate that this is a Wine thread */ + pthread_setspecific(wine_gst_key, &wine_gst_key); +} + +static BOOL is_wine_thread(void) +{ + return pthread_getspecific(wine_gst_key) != NULL; +} + +static pthread_mutex_t cb_list_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t cb_list_cond = PTHREAD_COND_INITIALIZER; +static struct list cb_list = LIST_INIT(cb_list); + +static void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user) +{ + struct cb_data *cbdata = user; + + if (cbdata->type < GSTDEMUX_MAX) + perform_cb_gstdemux(cbdata); + + pthread_mutex_lock(&cbdata->lock); + cbdata->finished = 1; + pthread_cond_broadcast(&cbdata->cond); + pthread_mutex_unlock(&cbdata->lock); +} + +static DWORD WINAPI dispatch_thread(void *user) +{ + struct cb_data *cbdata; + + CoInitializeEx(NULL, COINIT_MULTITHREADED); + + pthread_mutex_lock(&cb_list_lock); + + while (1) + { + pthread_cond_wait(&cb_list_cond, &cb_list_lock); + + while (!list_empty(&cb_list)) + { + cbdata = LIST_ENTRY(list_head(&cb_list), struct cb_data, entry); + list_remove(&cbdata->entry); + + TrySubmitThreadpoolCallback(&perform_cb, cbdata, NULL); + } + } + + pthread_mutex_unlock(&cb_list_lock); + + CoUninitialize(); + + return 0; +} + +void start_dispatch_thread(void) +{ + pthread_key_create(&wine_gst_key, NULL); + CloseHandle(CreateThread(NULL, 0, &dispatch_thread, NULL, 0, NULL)); +} + /* gstreamer calls our callbacks from threads that Wine did not create. Some * callbacks execute code which requires Wine to have created the thread * (critical sections, debug logging, dshow client code). Since gstreamer can't @@ -31,7 +97,7 @@ * callbacks in code which avoids the Wine thread requirement, and then * dispatch those callbacks on a thread that is known to be created by Wine. * - * This file must not contain any code that depends on the Wine TEB! + * This thread must not run any code that depends on the Wine TEB! */ static void call_cb(struct cb_data *cbdata) diff --git a/dlls/winegstreamer/gst_cbs.h b/dlls/winegstreamer/gst_cbs.h index b3e2b237bb1..4725f23ad1a 100644 --- a/dlls/winegstreamer/gst_cbs.h +++ b/dlls/winegstreamer/gst_cbs.h @@ -42,7 +42,8 @@ enum CB_TYPE { REMOVED_DECODED_PAD, AUTOPLUG_BLACKLIST, UNKNOWN_TYPE, - QUERY_SINK + QUERY_SINK, + GSTDEMUX_MAX }; struct cb_data { @@ -135,12 +136,8 @@ struct cb_data { struct list entry; }; -extern pthread_mutex_t cb_list_lock DECLSPEC_HIDDEN; -extern pthread_cond_t cb_list_cond DECLSPEC_HIDDEN; -extern struct list cb_list DECLSPEC_HIDDEN; -void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user) DECLSPEC_HIDDEN; -BOOL is_wine_thread(void) DECLSPEC_HIDDEN; void mark_wine_thread(void) DECLSPEC_HIDDEN; +void perform_cb_gstdemux(struct cb_data *data) DECLSPEC_HIDDEN; GstBusSyncReply watch_bus_wrapper(GstBus *bus, GstMessage *msg, gpointer user) DECLSPEC_HIDDEN; void existing_new_pad_wrapper(GstElement *bin, GstPad *pad, gpointer user) DECLSPEC_HIDDEN; diff --git a/dlls/winegstreamer/gstdemux.c b/dlls/winegstreamer/gstdemux.c index 65cf6186552..412aab2a3bc 100644 --- a/dlls/winegstreamer/gstdemux.c +++ b/dlls/winegstreamer/gstdemux.c @@ -43,8 +43,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(gstreamer); static const GUID MEDIASUBTYPE_CVID = {mmioFOURCC('c','v','i','d'), 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; -static pthread_key_t wine_gst_key; - struct gstdemux { struct strmbase_filter filter; @@ -100,17 +98,6 @@ static HRESULT WINAPI GST_ChangeCurrent(IMediaSeeking *iface); static HRESULT WINAPI GST_ChangeStop(IMediaSeeking *iface); static HRESULT WINAPI GST_ChangeRate(IMediaSeeking *iface); -void mark_wine_thread(void) -{ - /* set it to non-NULL to indicate that this is a Wine thread */ - pthread_setspecific(wine_gst_key, &wine_gst_key); -} - -BOOL is_wine_thread(void) -{ - return pthread_getspecific(wine_gst_key) != NULL; -} - static gboolean amt_from_gst_caps_audio_raw(const GstCaps *caps, AM_MEDIA_TYPE *amt) { WAVEFORMATEXTENSIBLE *wfe; @@ -2183,14 +2170,8 @@ static HRESULT GST_RemoveOutputPins(struct gstdemux *This) return S_OK; } -pthread_mutex_t cb_list_lock = PTHREAD_MUTEX_INITIALIZER; -pthread_cond_t cb_list_cond = PTHREAD_COND_INITIALIZER; -struct list cb_list = LIST_INIT(cb_list); - -void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user) +void perform_cb_gstdemux(struct cb_data *cbdata) { - struct cb_data *cbdata = user; - switch(cbdata->type) { case WATCH_BUS: @@ -2274,44 +2255,11 @@ void CALLBACK perform_cb(TP_CALLBACK_INSTANCE *instance, void *user) data->query); break; } - } - - pthread_mutex_lock(&cbdata->lock); - cbdata->finished = 1; - pthread_cond_broadcast(&cbdata->cond); - pthread_mutex_unlock(&cbdata->lock); -} - -static DWORD WINAPI dispatch_thread(void *user) -{ - struct cb_data *cbdata; - - CoInitializeEx(NULL, COINIT_MULTITHREADED); - - pthread_mutex_lock(&cb_list_lock); - - while(1){ - pthread_cond_wait(&cb_list_cond, &cb_list_lock); - - while(!list_empty(&cb_list)){ - cbdata = LIST_ENTRY(list_head(&cb_list), struct cb_data, entry); - list_remove(&cbdata->entry); - - TrySubmitThreadpoolCallback(&perform_cb, cbdata, NULL); + default: + { + assert(0); } } - - pthread_mutex_unlock(&cb_list_lock); - - CoUninitialize(); - - return 0; -} - -void start_dispatch_thread(void) -{ - pthread_key_create(&wine_gst_key, NULL); - CloseHandle(CreateThread(NULL, 0, &dispatch_thread, NULL, 0, NULL)); } static BOOL compare_media_types(const AM_MEDIA_TYPE *a, const AM_MEDIA_TYPE *b)