From: Matthew Waters Date: Wed, 25 Sep 2013 02:26:57 +0000 (+1000) Subject: [818/906] window: add send_message_async vmethod X-Git-Tag: 1.19.3~511^2~1989^2~1736 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3b1ec77cf8a3e5da3adf328ddeb5e93bf3b294db;p=platform%2Fupstream%2Fgstreamer.git [818/906] window: add send_message_async vmethod - provide a default synchronous send_message - make context creation threadsafe again --- diff --git a/gst-libs/gst/gl/android/gstglwindow_android_egl.c b/gst-libs/gst/gl/android/gstglwindow_android_egl.c index f1bdf66..a918127 100644 --- a/gst-libs/gst/gl/android/gstglwindow_android_egl.c +++ b/gst-libs/gst/gl/android/gstglwindow_android_egl.c @@ -48,8 +48,8 @@ static void gst_gl_window_android_egl_draw (GstGLWindow * window, guint width, static void gst_gl_window_android_egl_run (GstGLWindow * window); static void gst_gl_window_android_egl_quit (GstGLWindow * window, GstGLWindowCB callback, gpointer data); -static void gst_gl_window_android_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +static void gst_gl_window_android_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); static gboolean gst_gl_window_android_egl_open (GstGLWindow * window, GError ** error); static void gst_gl_window_android_egl_close (GstGLWindow * window); @@ -68,8 +68,8 @@ gst_gl_window_android_egl_class_init (GstGLWindowAndroidEGLClass * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_send_message_async); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_open); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_android_egl_close); } @@ -150,51 +150,41 @@ gst_gl_window_android_egl_quit (GstGLWindow * window, GstGLWindowCB callback, typedef struct _GstGLMessage { - GMutex lock; - GCond cond; - gboolean fired; - GstGLWindowCB callback; gpointer data; + GDestroyNotify destroy; } GstGLMessage; static gboolean _run_message (GstGLMessage * message) { - g_mutex_lock (&message->lock); - if (message->callback) message->callback (message->data); - message->fired = TRUE; - g_cond_signal (&message->cond); - g_mutex_unlock (&message->lock); + if (message->destroy) + message->destroy (message->data); + + g_slice_free (GstGLMessage, message); return FALSE; } static void -gst_gl_window_android_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data) +gst_gl_window_android_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowAndroidEGL *window_egl; - GstGLMessage message; + GstGLMessage *message; window_egl = GST_GL_WINDOW_ANDROID_EGL (window); - message.callback = callback; - message.data = data; - message.fired = FALSE; - g_mutex_init (&message.lock); - g_cond_init (&message.cond); + message = g_slice_new (GstGLMessage); - g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, - &message); - - g_mutex_lock (&message.lock); + message->callback = callback; + message->data = data; + message->destroy = destroy; - while (!message.fired) - g_cond_wait (&message.cond, &message.lock); - g_mutex_unlock (&message.lock); + g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, + message); } static void diff --git a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h index 07b2b14..13577e3 100644 --- a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h +++ b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h @@ -54,6 +54,7 @@ struct _GstGLContextCocoaPrivate NSOpenGLContext *gl_context; NSOpenGLContext *external_gl_context; NSRect rect; + gint source_id; }; diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index e808f37..631d2ab 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -29,6 +29,7 @@ static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, GstGLContext * other_context, GError **error); +static void gst_gl_context_cocoa_destroy_context (GstGLContext *context); static guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window); static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate); static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context); @@ -38,6 +39,30 @@ static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context); G_DEFINE_TYPE (GstGLContextCocoa, gst_gl_context_cocoa, GST_GL_TYPE_CONTEXT); +#ifndef GNUSTEP +static gboolean +gst_gl_window_cocoa_nsapp_iteration (gpointer data) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSEvent *event = nil; + + if ([NSThread isMainThread]) { + + while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask + untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5] + inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) { + + [NSApp sendEvent:event]; + } + } + + [pool release]; + + return TRUE; +} +#endif + static void gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) { @@ -51,6 +76,8 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate)); + context_class->destroy_context = + GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_destroy_context); context_class->create_context = GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_create_context); context_class->get_gl_context = @@ -193,6 +220,11 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, return TRUE; } +static void +gst_gl_context_cocoa_destroy_context (GstGLContext *context) +{ +} + static guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * context) { diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 038df34..93357ec 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -75,8 +75,8 @@ static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, static void gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height); static void gst_gl_window_cocoa_run (GstGLWindow * window); static void gst_gl_window_cocoa_quit (GstGLWindow * window); -static void gst_gl_window_cocoa_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); struct _GstGLWindowCocoaPrivate { @@ -85,31 +85,8 @@ struct _GstGLWindowCocoaPrivate NSWindow *parent; NSThread *thread; gboolean running; - guint source_id; }; -gboolean -gst_gl_window_cocoa_nsapp_iteration (gpointer data) -{ - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSEvent *event = nil; - - if ([NSThread isMainThread]) { - - while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask - untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5] - inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) { - - [NSApp sendEvent:event]; - } - } - - [pool release]; - - return TRUE; -} - static void gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) { @@ -131,8 +108,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async); #ifndef GNUSTEP pool = [[NSAutoreleasePool alloc] init]; @@ -201,21 +178,22 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) priv->parent = (NSWindow*) handle; if (priv->internal_win_id) { - g_source_remove (priv->source_id); - - if (GSRegisterCurrentThread()) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window); + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; - AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; - [app_thread_performer performSelectorOnMainThread:@selector(setWindow) - withObject:0 waitUntilDone:YES]; - [pool release]; + GSRegisterCurrentThread(); - GSUnregisterCurrentThread(); - } else { - GST_DEBUG ("failed to register current thread, cannot set external window id\n"); + if (context) { + g_source_remove (context->priv->source_id); + gst_object_unref (context); } + + [app_thread_performer performSelectorOnMainThread:@selector(setWindow) + withObject:0 waitUntilDone:YES]; + + [pool release]; } } @@ -225,56 +203,54 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height) { GstGLWindowCocoa *window_cocoa; GstGLWindowCocoaPrivate *priv; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + AppThreadPerformer* app_thread_performer; window_cocoa = GST_GL_WINDOW_COCOA (window); priv = window_cocoa->priv; - if (GSRegisterCurrentThread()) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + GSRegisterCurrentThread(); - AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; - [app_thread_performer performSelector:@selector(updateWindow) + app_thread_performer = [[AppThreadPerformer alloc] init:window_cocoa]; + [app_thread_performer performSelector:@selector(updateWindow) onThread:priv->thread withObject:nil waitUntilDone:YES]; - - if (!priv->parent && !priv->visible) { - static gint x = 0; - static gint y = 0; - NSRect mainRect = [[NSScreen mainScreen] visibleFrame]; - NSRect windowRect = [priv->internal_win_id frame]; + if (!priv->parent && !priv->visible) { + static gint x = 0; + static gint y = 0; + + NSRect mainRect = [[NSScreen mainScreen] visibleFrame]; + NSRect windowRect = [priv->internal_win_id frame]; - GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x, (int) mainRect.origin.y, - (int) mainRect.size.width, (int) mainRect.size.height); + GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x, + (int) mainRect.origin.y, (int) mainRect.size.width, + (int) mainRect.size.height); - windowRect.origin.x += x; - windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y; - windowRect.size.width = width; - windowRect.size.height = height; + windowRect.origin.x += x; + windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y; + windowRect.size.width = width; + windowRect.size.height = height; - GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x, (int) windowRect.origin.y, - (int) windowRect.size.width, (int) windowRect.size.height); + GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x, + (int) windowRect.origin.y, (int) windowRect.size.width, + (int) windowRect.size.height); - x += 20; - y += 20; + x += 20; + y += 20; #ifndef GNUSTEP - [priv->internal_win_id setFrame:windowRect display:NO]; - GST_DEBUG ("make the window available\n"); - [priv->internal_win_id makeMainWindow]; + [priv->internal_win_id setFrame:windowRect display:NO]; + GST_DEBUG ("make the window available\n"); + [priv->internal_win_id makeMainWindow]; #endif - [app_thread_performer performSelector:@selector(orderFront) - onThread:priv->thread withObject:nil waitUntilDone:YES]; + [app_thread_performer performSelector:@selector(orderFront) + onThread:priv->thread withObject:nil waitUntilDone:YES]; - /*[priv->internal_win_id setViewsNeedDisplay:YES]; */ - priv->visible = TRUE; - } - - [pool release]; - - GSUnregisterCurrentThread(); + /*[priv->internal_win_id setViewsNeedDisplay:YES]; */ + priv->visible = TRUE; } - else - GST_DEBUG ("failed to register current thread, cannot draw\n"); + + [pool release]; } static void @@ -283,23 +259,19 @@ gst_gl_window_cocoa_run (GstGLWindow * window) GstGLWindowCocoa *window_cocoa; GstGLWindowCocoaPrivate *priv; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; -#ifndef GNUSTEP NSRunLoop *run_loop = [NSRunLoop currentRunLoop]; -#endif window_cocoa = GST_GL_WINDOW_COCOA (window); priv = window_cocoa->priv; + [run_loop addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; + GST_DEBUG ("begin loop\n"); - + if (priv->internal_win_id != nil) { priv->running = TRUE; -#ifndef GNUSTEP while (priv->running) [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; -#else - [NSApp run]; -#endif [priv->internal_win_id release]; priv->internal_win_id = nil; @@ -340,8 +312,8 @@ gst_gl_window_cocoa_quit (GstGLWindow * window) /* Thread safe */ static void -gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, - gpointer data) +gst_gl_window_cocoa_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowCocoa *window_cocoa; GstGLWindowCocoaPrivate *priv; @@ -349,22 +321,18 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, window_cocoa = GST_GL_WINDOW_COCOA (window); priv = window_cocoa->priv; + GSRegisterCurrentThread (); + if (window) { - if (GSRegisterCurrentThread()) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] - initWithAll:window_cocoa callback:callback userData:data]; - - [app_thread_performer performSelector:@selector(sendToApp) onThread:priv->thread - withObject:nil waitUntilDone:YES]; + AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] + initWithAll:window_cocoa callback:callback userData:data]; - [pool release]; + [app_thread_performer performSelector:@selector(sendToApp) onThread:priv->thread + withObject:nil waitUntilDone:NO]; - GSUnregisterCurrentThread(); - } - else - GST_DEBUG ("failed to register current thread, cannot send message\n"); + [pool release]; } } @@ -394,9 +362,9 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, GST_DEBUG ("initializing GstGLNSWindow\n"); [self setTitle:@"OpenGL renderer"]; - + [self setBackgroundColor:[NSColor clearColor]]; - + [self orderOut:m_cocoa->priv->internal_win_id]; if (m_cocoa->priv->parent) { @@ -596,7 +564,7 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, } - (void) sendToApp { - if (m_cocoa->priv->running && ![m_cocoa->priv->internal_win_id isClosed]) + if (m_callback) m_callback (m_data); } diff --git a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c index a3648e8..488c34b 100644 --- a/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c +++ b/gst-libs/gst/gl/dispmanx/gstglwindow_dispmanx_egl.c @@ -43,8 +43,8 @@ static void gst_gl_window_dispmanx_egl_draw (GstGLWindow * window, guint width, guint height); static void gst_gl_window_dispmanx_egl_run (GstGLWindow * window); static void gst_gl_window_dispmanx_egl_quit (GstGLWindow * window); -static void gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +static void gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); static void gst_gl_window_dispmanx_egl_close (GstGLWindow * window); static gboolean gst_gl_window_dispmanx_egl_open (GstGLWindow * window, GError ** error); @@ -68,8 +68,8 @@ gst_gl_window_dispmanx_egl_class_init (GstGLWindowDispmanxEGLClass * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_send_message_async); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_close); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_dispmanx_egl_open); window_class->get_display = @@ -180,51 +180,41 @@ gst_gl_window_dispmanx_egl_quit (GstGLWindow * window) typedef struct _GstGLMessage { - GMutex lock; - GCond cond; - gboolean fired; - GstGLWindowCB callback; gpointer data; + GDestroyNotify destroy; } GstGLMessage; static gboolean _run_message (GstGLMessage * message) { - g_mutex_lock (&message->lock); - if (message->callback) message->callback (message->data); - message->fired = TRUE; - g_cond_signal (&message->cond); - g_mutex_unlock (&message->lock); + if (message->destroy) + message->destroy (message->data); + + g_slice_free (GstGLMessage, message); return FALSE; } static void -gst_gl_window_dispmanx_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data) +gst_gl_window_dispmanx_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowDispmanxEGL *window_egl; - GstGLMessage message; + GstGLMessage *message; window_egl = GST_GL_WINDOW_DISPMANX_EGL (window); - message.callback = callback; - message.data = data; - message.fired = FALSE; - g_mutex_init (&message.lock); - g_cond_init (&message.cond); + message = g_slice_new (GstGLMessage); - g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, - &message); - - g_mutex_lock (&message.lock); + message->callback = callback; + message->data = data; + message->destroy = destroy; - while (!message.fired) - g_cond_wait (&message.cond, &message.lock); - g_mutex_unlock (&message.lock); + g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, + message); } static guintptr @@ -283,8 +273,8 @@ window_resize (GstGLWindowDispmanxEGL * window_egl, guint width, guint height) vc_dispmanx_update_submit_sync (dispman_update); if (GST_GL_WINDOW (window_egl)->resize) - GST_GL_WINDOW (window_egl)-> - resize (GST_GL_WINDOW (window_egl)->resize_data, width, height); + GST_GL_WINDOW (window_egl)->resize (GST_GL_WINDOW (window_egl)-> + resize_data, width, height); } window_egl->native.width = width; diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index ae89168..4b85327 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -513,6 +513,12 @@ _parse_gl_api (const gchar * apis_s) return ret; } +static void +_unlock_create_thread (GstGLContext * context) +{ + g_mutex_unlock (&context->priv->render_lock); +} + //gboolean //gst_gl_context_create (GstGLContext * context, GstGLContext * other_context, GError ** error) static gpointer @@ -637,7 +643,10 @@ gst_gl_context_create_thread (GstGLContext * context) context->priv->alive = TRUE; g_cond_signal (&context->priv->create_cond); - g_mutex_unlock (&context->priv->render_lock); + +// g_mutex_unlock (&context->priv->render_lock); + gst_gl_window_send_message_async (context->window, + (GstGLWindowCB) _unlock_create_thread, context, NULL); gst_gl_window_run (context->window); diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 929745a..d4f57a5 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -64,6 +64,9 @@ G_DEFINE_ABSTRACT_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT); #define GST_GL_WINDOW_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate)) +static void gst_gl_window_default_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data); + struct _GstGLWindowPrivate { GstGLDisplay *display; @@ -112,6 +115,8 @@ gst_gl_window_class_init (GstGLWindowClass * klass) { g_type_class_add_private (klass, sizeof (GstGLWindowPrivate)); + klass->send_message = GST_DEBUG_FUNCPTR (gst_gl_window_default_send_message); + G_OBJECT_CLASS (klass)->finalize = gst_gl_window_finalize; } @@ -257,6 +262,55 @@ gst_gl_window_quit (GstGLWindow * window) GST_INFO ("quit received from gl window"); } +typedef struct _GstGLSyncMessage +{ + GMutex lock; + GCond cond; + gboolean fired; + + GstGLWindowCB callback; + gpointer data; +} GstGLSyncMessage; + +static void +_run_message_sync (GstGLSyncMessage * message) +{ + g_mutex_lock (&message->lock); + + if (message->callback) + message->callback (message->data); + + message->fired = TRUE; + g_cond_signal (&message->cond); + g_mutex_unlock (&message->lock); +} + +void +gst_gl_window_default_send_message (GstGLWindow * window, + GstGLWindowCB callback, gpointer data) +{ + GstGLSyncMessage message; + + message.callback = callback; + message.data = data; + message.fired = FALSE; + g_mutex_init (&message.lock); + g_cond_init (&message.cond); + + gst_gl_window_send_message_async (window, (GstGLWindowCB) _run_message_sync, + &message, NULL); + + g_mutex_lock (&message.lock); + + /* block until opengl calls have been executed in the gl thread */ + while (!message.fired) + g_cond_wait (&message.cond, &message.lock); + g_mutex_unlock (&message.lock); + + g_mutex_clear (&message.lock); + g_cond_clear (&message.cond); +} + void gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data) @@ -266,13 +320,27 @@ gst_gl_window_send_message (GstGLWindow * window, GstGLWindowCB callback, g_return_if_fail (GST_GL_IS_WINDOW (window)); g_return_if_fail (callback != NULL); window_class = GST_GL_WINDOW_GET_CLASS (window); - g_return_if_fail (window_class->quit != NULL); + g_return_if_fail (window_class->send_message != NULL); GST_GL_WINDOW_LOCK (window); window_class->send_message (window, callback, data); GST_GL_WINDOW_UNLOCK (window); } +void +gst_gl_window_send_message_async (GstGLWindow * window, GstGLWindowCB callback, + gpointer data, GDestroyNotify destroy) +{ + GstGLWindowClass *window_class; + + g_return_if_fail (GST_GL_IS_WINDOW (window)); + g_return_if_fail (callback != NULL); + window_class = GST_GL_WINDOW_GET_CLASS (window); + g_return_if_fail (window_class->send_message_async != NULL); + + window_class->send_message_async (window, callback, data, destroy); +} + /** * gst_gl_window_set_need_lock: * diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index 1d2137d..ba2f103 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -104,6 +104,7 @@ struct _GstGLWindowClass { void (*run) (GstGLWindow *window); void (*quit) (GstGLWindow *window); void (*send_message) (GstGLWindow *window, GstGLWindowCB callback, gpointer data); + void (*send_message_async) (GstGLWindow *window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); gboolean (*open) (GstGLWindow *window, GError **error); void (*close) (GstGLWindow *window); @@ -131,6 +132,7 @@ void gst_gl_window_draw (GstGLWindow *window, guint width, g void gst_gl_window_run (GstGLWindow *window); void gst_gl_window_quit (GstGLWindow *window); void gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data); +void gst_gl_window_send_message_async (GstGLWindow *window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); guintptr gst_gl_window_get_display (GstGLWindow *window); GstGLContext * gst_gl_window_get_context (GstGLWindow *window); diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index 32f82f6..1c7e3e6 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -48,8 +48,8 @@ static void gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, guint height); static void gst_gl_window_wayland_egl_run (GstGLWindow * window); static void gst_gl_window_wayland_egl_quit (GstGLWindow * window); -static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +static void gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); static void gst_gl_window_wayland_egl_close (GstGLWindow * window); static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error); @@ -258,8 +258,8 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message_async); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_close); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open); window_class->get_display = @@ -379,51 +379,41 @@ gst_gl_window_wayland_egl_quit (GstGLWindow * window) typedef struct _GstGLMessage { - GMutex lock; - GCond cond; - gboolean fired; - GstGLWindowCB callback; gpointer data; + GDestroyNotify destroy; } GstGLMessage; static gboolean _run_message (GstGLMessage * message) { - g_mutex_lock (&message->lock); - if (message->callback) message->callback (message->data); - message->fired = TRUE; - g_cond_signal (&message->cond); - g_mutex_unlock (&message->lock); + if (message->destroy) + message->destroy (message->data); + + g_slice_free (GstGLMessage, message); return FALSE; } static void -gst_gl_window_wayland_egl_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data) +gst_gl_window_wayland_egl_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowWaylandEGL *window_egl; - GstGLMessage message; + GstGLMessage *message; window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - message.callback = callback; - message.data = data; - message.fired = FALSE; - g_mutex_init (&message.lock); - g_cond_init (&message.cond); + message = g_slice_new (GstGLMessage); - g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, - &message); - - g_mutex_lock (&message.lock); + message->callback = callback; + message->data = data; + message->destroy = destroy; - while (!message.fired) - g_cond_wait (&message.cond, &message.lock); - g_mutex_unlock (&message.lock); + g_main_context_invoke (window_egl->main_context, (GSourceFunc) _run_message, + message); } static guintptr diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.c b/gst-libs/gst/gl/win32/gstglwindow_win32.c index 94c32fe..f50bc3d 100644 --- a/gst-libs/gst/gl/win32/gstglwindow_win32.c +++ b/gst-libs/gst/gl/win32/gstglwindow_win32.c @@ -62,8 +62,8 @@ static void gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height); static void gst_gl_window_win32_run (GstGLWindow * window); static void gst_gl_window_win32_quit (GstGLWindow * window); -static void gst_gl_window_win32_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +static void gst_gl_window_win32_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); static void gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) @@ -78,8 +78,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_win32_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_win32_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message_async); window_class->get_display = GST_DEBUG_FUNCPTR (gst_gl_window_win32_get_display); } @@ -330,19 +330,47 @@ gst_gl_window_win32_quit (GstGLWindow * window) } } +typedef struct _GstGLMessage +{ + GstGLWindowCB callback; + gpointer data; + GDestroyNotify destroy; +} GstGLMessage; + +static gboolean +_run_message (GstGLMessage * message) +{ + if (message->callback) + message->callback (message->data); + + if (message->destroy) + message->destroy (message->data); + + g_slice_free (GstGLMessage, message); + + return FALSE; +} + /* Thread safe */ static void -gst_gl_window_win32_send_message (GstGLWindow * window, GstGLWindowCB callback, - gpointer data) +gst_gl_window_win32_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) { GstGLWindowWin32 *window_win32; + GstGLMessage *message; window_win32 = GST_GL_WINDOW_WIN32 (window); + message = g_slice_new (GstGLMessage); if (window_win32) { - LRESULT res = - SendMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM, - (WPARAM) data, (LPARAM) callback); + LRESULT res; + + message->callback = callback; + message->data = data; + message->destroy = destroy; + + res = PostMessage (window_win32->internal_win_id, WM_GST_GL_WINDOW_CUSTOM, + (WPARAM) message, (LPARAM) NULL); g_return_if_fail (SUCCEEDED (res)); } } @@ -449,8 +477,8 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_GST_GL_WINDOW_CUSTOM: { if (!window_win32->is_closed) { - GstGLWindowCB custom_cb = (GstGLWindowCB) lParam; - custom_cb ((gpointer) wParam); + GstGLMessage *message = (GstGLMessage *) wParam; + _run_message (message); } break; } diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.c b/gst-libs/gst/gl/x11/gstglwindow_x11.c index d3659a4..3a79aa3 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.c +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.c @@ -66,8 +66,8 @@ void gst_gl_window_x11_draw_unlocked (GstGLWindow * window, guint width, void gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height); void gst_gl_window_x11_run (GstGLWindow * window); void gst_gl_window_x11_quit (GstGLWindow * window); -void gst_gl_window_x11_send_message (GstGLWindow * window, - GstGLWindowCB callback, gpointer data); +void gst_gl_window_x11_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy); gboolean gst_gl_window_x11_create_context (GstGLWindow * window, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); gboolean gst_gl_window_x11_open (GstGLWindow * window, GError ** error); @@ -153,8 +153,8 @@ gst_gl_window_x11_class_init (GstGLWindowX11Class * klass) window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw); window_class->run = GST_DEBUG_FUNCPTR (gst_gl_window_x11_run); window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_x11_quit); - window_class->send_message = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message); + window_class->send_message_async = + GST_DEBUG_FUNCPTR (gst_gl_window_x11_send_message_async); window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_x11_open); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_x11_close); } @@ -397,7 +397,7 @@ gst_gl_window_x11_activate (GstGLWindow * window, gboolean activate) priv = window_x11->priv; priv->activate = activate; - gst_gl_window_x11_send_message (window, GST_GL_WINDOW_CB (callback_activate), + gst_gl_window_send_message (window, GST_GL_WINDOW_CB (callback_activate), window_x11); return priv->activate_result; @@ -541,32 +541,6 @@ gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height) } } -typedef struct _GstGLMessage -{ - GstGLWindow *window; - GMutex lock; - GCond cond; - gboolean fired; - - GstGLWindowCB callback; - gpointer data; -} GstGLMessage; - -static gboolean -_run_message (GstGLMessage * message) -{ - g_mutex_lock (&message->lock); - - if (message->callback) - message->callback (message->data); - - message->fired = TRUE; - g_cond_signal (&message->cond); - g_mutex_unlock (&message->lock); - - return FALSE; -} - void gst_gl_window_x11_run (GstGLWindow * window) { @@ -726,35 +700,43 @@ gst_gl_window_x11_quit (GstGLWindow * window) GST_LOG ("quit sent"); } -/* Not called by the gl thread */ -void -gst_gl_window_x11_send_message (GstGLWindow * window, GstGLWindowCB callback, - gpointer data) +typedef struct _GstGLMessage { - GstGLWindowX11 *window_x11; + GstGLWindowCB callback; + gpointer data; + GDestroyNotify destroy; +} GstGLMessage; - window_x11 = GST_GL_WINDOW_X11 (window); +static gboolean +_run_message (GstGLMessage * message) +{ + if (message->callback) + message->callback (message->data); - if (g_main_loop_is_running (window_x11->loop)) { - GstGLMessage message; + if (message->destroy) + message->destroy (message->data); + + g_slice_free (GstGLMessage, message); + + return FALSE; +} - message.window = window; - message.callback = callback; - message.data = data; - message.fired = FALSE; - g_mutex_init (&message.lock); - g_cond_init (&message.cond); +void +gst_gl_window_x11_send_message_async (GstGLWindow * window, + GstGLWindowCB callback, gpointer data, GDestroyNotify destroy) +{ + GstGLWindowX11 *window_x11; + GstGLMessage *message; - g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message, - &message); + window_x11 = GST_GL_WINDOW_X11 (window); + message = g_slice_new (GstGLMessage); - g_mutex_lock (&message.lock); + message->callback = callback; + message->data = data; + message->destroy = destroy; - /* block until opengl calls have been executed in the gl thread */ - while (!message.fired) - g_cond_wait (&message.cond, &message.lock); - g_mutex_unlock (&message.lock); - } + g_main_context_invoke (window_x11->main_context, (GSourceFunc) _run_message, + message); } static int