From f20cdcd36b398d92dba5240dddb948cc49465180 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Sat, 26 May 2012 12:21:18 +0200 Subject: [PATCH] osxvideosink: fix race in starting the runloop thread Block gst_osx_video_sink_run_cocoa_loop until the loop thread has started and finished initializing NSApp. Fixes occasional warnings/crashes due to two threads going inside NSApp before finishLaunching had completed. --- sys/osxvideo/osxvideosink.h | 4 +++- sys/osxvideo/osxvideosink.m | 40 +++++++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/sys/osxvideo/osxvideosink.h b/sys/osxvideo/osxvideosink.h index 2d18f13..5d32f5c 100644 --- a/sys/osxvideo/osxvideosink.h +++ b/sys/osxvideo/osxvideosink.h @@ -77,10 +77,12 @@ struct _GstOSXVideoSink { NSView *superview; #ifdef RUN_NS_APP_THREAD NSThread *ns_app_thread; + GMutex *loop_thread_lock; + GCond *loop_thread_cond; #else guint cocoa_timeout; - gboolean app_started; #endif + gboolean app_started; gboolean keep_par; gboolean embed; }; diff --git a/sys/osxvideo/osxvideosink.m b/sys/osxvideo/osxvideosink.m index d4f3330..a444223 100644 --- a/sys/osxvideo/osxvideosink.m +++ b/sys/osxvideo/osxvideosink.m @@ -115,7 +115,7 @@ run_ns_app_loop (void) { } static void -gst_osx_video_sink_run_cocoa_loop (GstOSXVideoSink * osxvideosink ) +gst_osx_video_sink_run_cocoa_loop (GstOSXVideoSink * sink ) { /* Cocoa applications require a main runloop running to dispatch UI * events and process deferred calls to the main thread through @@ -138,14 +138,19 @@ gst_osx_video_sink_run_cocoa_loop (GstOSXVideoSink * osxvideosink ) method_exchangeImplementations(origIsMainThread, ourIsMainThread); - osxvideosink->ns_app_thread = [[NSThread alloc] - initWithTarget:osxvideosink->osxvideosinkobject + sink->ns_app_thread = [[NSThread alloc] + initWithTarget:sink->osxvideosinkobject selector:@selector(nsAppThread) object:nil]; - [osxvideosink->ns_app_thread start]; + [sink->ns_app_thread start]; + + g_mutex_lock (sink->loop_thread_lock); + while (!sink->app_started) + g_cond_wait (sink->loop_thread_cond, sink->loop_thread_lock); + g_mutex_unlock (sink->loop_thread_lock); #else /* assume that there is a GMainLoop and iterate the main runloop from there */ - osxvideosink->cocoa_timeout = g_timeout_add (10, + sink->cocoa_timeout = g_timeout_add (10, (GSourceFunc) run_ns_app_loop, NULL); #endif } @@ -356,9 +361,7 @@ gst_osx_video_sink_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_READY: GST_VIDEO_SINK_WIDTH (osxvideosink) = 0; GST_VIDEO_SINK_HEIGHT (osxvideosink) = 0; -#ifndef RUN_NS_APP_THREAD osxvideosink->app_started = FALSE; -#endif gst_osx_video_sink_osxwindow_destroy (osxvideosink); break; case GST_STATE_CHANGE_READY_TO_NULL: @@ -450,16 +453,17 @@ gst_osx_video_sink_get_property (GObject * object, guint prop_id, static void -gst_osx_video_sink_init (GstOSXVideoSink * osxvideosink) +gst_osx_video_sink_init (GstOSXVideoSink * sink) { - osxvideosink->osxwindow = NULL; - osxvideosink->superview = NULL; - osxvideosink->osxvideosinkobject = [[GstOSXVideoSinkObject alloc] - initWithSink:osxvideosink]; -#ifndef RUN_NS_APP_THREAD - osxvideosink->app_started = FALSE; + sink->osxwindow = NULL; + sink->superview = NULL; + sink->osxvideosinkobject = [[GstOSXVideoSinkObject alloc] initWithSink:sink]; +#ifdef RUN_NS_APP_THREAD + sink->loop_thread_lock = g_mutex_new (); + sink->loop_thread_cond = g_cond_new (); #endif - osxvideosink->keep_par = FALSE; + sink->app_started = FALSE; + sink->keep_par = FALSE; } static void @@ -857,6 +861,7 @@ gst_osx_video_sink_get_type (void) -(void) nsAppThread { NSAutoreleasePool *pool; + GstOSXVideoSink *sink = osxvideosink; /* set the main runloop as the runloop for the current thread. This has the * effect that calling NSApp nextEventMatchingMask:untilDate:inMode:dequeue @@ -874,6 +879,11 @@ gst_osx_video_sink_get_type (void) [NSApplication sharedApplication]; [NSApp finishLaunching]; + g_mutex_lock (sink->loop_thread_lock); + sink->app_started = TRUE; + g_cond_signal (sink->loop_thread_cond); + g_mutex_unlock (sink->loop_thread_lock); + /* run the loop */ run_ns_app_loop (); -- 2.7.4