Commit 9e208ba0 authored by Nicolas Dufresne's avatar Nicolas Dufresne Committed by Tim-Philipp Müller
Browse files

sdlshare2: Fix race conditions

The client-draw callback is running on the GL Thread, which will
be required to map the buffer. Map early, and pass the mapped
frame instead. On top of that, make sure to signal any pending
draw before trying to push EOS, as some pad locks might be taken.
This is the cost of using the same thread to control GStreamer and
to render GL.
parent dea918a8
...@@ -66,13 +66,9 @@ InitGL (int Width, int Height) // We call this right after our OpenGL window is ...@@ -66,13 +66,9 @@ InitGL (int Width, int Height) // We call this right after our OpenGL window is
/* The main drawing function. */ /* The main drawing function. */
static void static void
DrawGLScene (GstSample * sample) DrawGLScene (GstVideoFrame * v_frame)
{ {
GstVideoFrame v_frame;
GstVideoInfo v_info;
guint texture = 0; guint texture = 0;
GstBuffer *buf = gst_sample_get_buffer (sample);
GstCaps *caps = gst_sample_get_caps (sample);
#ifdef WIN32 #ifdef WIN32
if (!wglGetCurrentContext ()) if (!wglGetCurrentContext ())
...@@ -82,14 +78,7 @@ DrawGLScene (GstSample * sample) ...@@ -82,14 +78,7 @@ DrawGLScene (GstSample * sample)
return; return;
#endif #endif
gst_video_info_from_caps (&v_info, caps); texture = *(guint *) v_frame->data[0];
if (!gst_video_frame_map (&v_frame, &v_info, buf, GST_MAP_READ | GST_MAP_GL)) {
g_warning ("Failed to map the video buffer");
return;
}
texture = *(guint *) v_frame.data[0];
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity (); // Reset The View glLoadIdentity (); // Reset The View
...@@ -139,8 +128,21 @@ DrawGLScene (GstSample * sample) ...@@ -139,8 +128,21 @@ DrawGLScene (GstSample * sample)
// swap buffers to display, since we're double buffered. // swap buffers to display, since we're double buffered.
SDL_GL_SwapBuffers (); SDL_GL_SwapBuffers ();
}
gst_video_frame_unmap (&v_frame); static GMutex app_lock;
static GCond app_cond;
static gboolean app_rendered = FALSE;
static gboolean app_quit = FALSE;
static void
stop_pipeline (GstElement * pipeline)
{
g_mutex_lock (&app_lock);
app_quit = TRUE;
g_cond_signal (&app_cond);
g_mutex_unlock (&app_lock);
gst_element_send_event (pipeline, gst_event_new_eos ());
} }
static gboolean static gboolean
...@@ -151,12 +153,12 @@ update_sdl_scene (gpointer data) ...@@ -151,12 +153,12 @@ update_sdl_scene (gpointer data)
while (SDL_PollEvent (&event)) { while (SDL_PollEvent (&event)) {
if (event.type == SDL_QUIT) { if (event.type == SDL_QUIT) {
gst_element_send_event (GST_ELEMENT (pipeline), gst_event_new_eos ()); stop_pipeline (pipeline);
return FALSE; return FALSE;
} }
if (event.type == SDL_KEYDOWN) { if (event.type == SDL_KEYDOWN) {
if (event.key.keysym.sym == SDLK_ESCAPE) { if (event.key.keysym.sym == SDLK_ESCAPE) {
gst_element_send_event (GST_ELEMENT (pipeline), gst_event_new_eos ()); stop_pipeline (pipeline);
return FALSE; return FALSE;
} }
} }
...@@ -165,18 +167,15 @@ update_sdl_scene (gpointer data) ...@@ -165,18 +167,15 @@ update_sdl_scene (gpointer data)
return TRUE; return TRUE;
} }
static GMutex app_lock;
static GCond app_cond;
static gboolean static gboolean
executeCallback (gpointer data) executeCallback (gpointer data)
{ {
GstSample *sample = (GstSample *) data;
g_mutex_lock (&app_lock); g_mutex_lock (&app_lock);
DrawGLScene (sample); if (!app_quit)
DrawGLScene (data);
app_rendered = TRUE;
g_cond_signal (&app_cond); g_cond_signal (&app_cond);
g_mutex_unlock (&app_lock); g_mutex_unlock (&app_lock);
...@@ -187,12 +186,31 @@ static gboolean ...@@ -187,12 +186,31 @@ static gboolean
on_client_draw (GstElement * glsink, GstGLContext * context, GstSample * sample, on_client_draw (GstElement * glsink, GstGLContext * context, GstSample * sample,
gpointer data) gpointer data)
{ {
GstBuffer *buf = gst_sample_get_buffer (sample);
GstCaps *caps = gst_sample_get_caps (sample);
GstVideoFrame v_frame;
GstVideoInfo v_info;
/* FIXME don't do that every frame */
gst_video_info_from_caps (&v_info, caps);
if (!gst_video_frame_map (&v_frame, &v_info, buf, GST_MAP_READ | GST_MAP_GL)) {
g_warning ("Failed to map the video buffer");
return TRUE;
}
g_mutex_lock (&app_lock); g_mutex_lock (&app_lock);
g_idle_add_full (G_PRIORITY_HIGH, executeCallback, sample, NULL); app_rendered = FALSE;
g_cond_wait (&app_cond, &app_lock); g_idle_add_full (G_PRIORITY_HIGH, executeCallback, &v_frame, NULL);
while (!app_rendered && !app_quit)
g_cond_wait (&app_cond, &app_lock);
g_mutex_unlock (&app_lock); g_mutex_unlock (&app_lock);
gst_video_frame_unmap (&v_frame);
return TRUE; return TRUE;
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment