From d75eb628d65e17c8d2f0b1605b74ad4992e5c93e Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Sun, 16 Jul 2017 01:17:04 +1000 Subject: [PATCH] gl/cocoa: keep refs over async operations Avoids dereferencing dead objects What happens in the autovideosink case is that context 1 is created and destroyed before all the async operations hae executed on the associated window. When the delayed operations execute, they then reference dead objects and crash. We fix this by keeping refs over all async operations so the object cannot be deleted while async operations are in flight. https://bugzilla.gnome.org/show_bug.cgi?id=782379 --- gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h | 2 +- gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 2 +- gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 22 ++++++++++++++++----- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h index ae7abc8a6e..9a9bef25be 100644 --- a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h +++ b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h @@ -59,7 +59,7 @@ struct _GstGLContextCocoaPrivate gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa); -void _invoke_on_main (GstGLWindowCB func, gpointer data); +void _invoke_on_main (GstGLWindowCB func, gpointer data, GDestroyNotify notify); G_END_DECLS diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m index 9e2f1e4f53..b3ba59e9c2 100644 --- a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -259,7 +259,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, context_cocoa->priv->gl_context = glContext; _invoke_on_main ((GstGLWindowCB) gst_gl_window_cocoa_create_window, - window_cocoa); + gst_object_ref (window_cocoa), (GDestroyNotify) gst_object_unref); if (!context_cocoa->priv->gl_context) { goto error; diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 7c01702f4a..40d6bc2815 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -175,9 +175,16 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa) NSRect rect = NSMakeRect (0, y, priv->preferred_width, priv->preferred_height); NSRect windowRect = NSMakeRect (0, y, priv->preferred_width, priv->preferred_height); GstGLContext *context = gst_gl_window_get_context (window); - GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context); - GstGLCAOpenGLLayer *layer = [[GstGLCAOpenGLLayer alloc] initWithGstGLContext:context_cocoa]; - GstGLNSView *glView = [[GstGLNSView alloc] initWithFrameLayer:window_cocoa rect:windowRect layer:layer]; + GstGLContextCocoa *context_cocoa; + GstGLCAOpenGLLayer *layer; + GstGLNSView *glView; + + if (!context) + return FALSE; + + context_cocoa = GST_GL_CONTEXT_COCOA (context); + layer = [[GstGLCAOpenGLLayer alloc] initWithGstGLContext:context_cocoa]; + glView = [[GstGLNSView alloc] initWithFrameLayer:window_cocoa rect:windowRect layer:layer]; gst_object_unref (context); @@ -296,7 +303,8 @@ gst_gl_window_cocoa_show (GstGLWindow * window) } if (!priv->external_view && !priv->visible) - _invoke_on_main ((GstGLWindowCB) _show_window, window); + _invoke_on_main ((GstGLWindowCB) _show_window, gst_object_ref (window), + (GDestroyNotify) gst_object_unref); } } @@ -575,13 +583,17 @@ close_window_cb (gpointer data) @end void -_invoke_on_main (GstGLWindowCB func, gpointer data) +_invoke_on_main (GstGLWindowCB func, gpointer data, GDestroyNotify notify) { if ([NSThread isMainThread]) { func (data); + if (notify) + notify (data); } else { dispatch_async (dispatch_get_main_queue (), ^{ func (data); + if (notify) + notify (data); }); } }