static gboolean stereosplit_src_event (GstPad * pad, GstObject * parent,
GstEvent * event);
static gboolean ensure_context (GstGLStereoSplit * self);
+static gboolean ensure_context_unlocked (GstGLStereoSplit * self);
static void
gst_gl_stereosplit_class_init (GstGLStereoSplitClass * klass)
gst_element_add_pad (GST_ELEMENT (self), self->right_pad);
self->viewconvert = gst_gl_view_convert_new ();
+
+ g_rec_mutex_init (&self->context_lock);
}
static void
if (self->viewconvert)
gst_object_replace ((GstObject **) & self->viewconvert, NULL);
+ g_rec_mutex_clear (&self->context_lock);
+
klass->finalize ((GObject *) (self));
}
stereosplit_set_context (GstElement * element, GstContext * context)
{
GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element);
+ GstGLDisplay *old_display, *new_display;
+ g_rec_mutex_lock (&stereosplit->context_lock);
+ GST_DEBUG_OBJECT (element, "set context of %" GST_PTR_FORMAT, context);
+ old_display =
+ stereosplit->display ? gst_object_ref (stereosplit->display) : NULL;
gst_gl_handle_set_context (element, context, &stereosplit->display,
&stereosplit->other_context);
if (stereosplit->display)
gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
+ new_display =
+ stereosplit->display ? gst_object_ref (stereosplit->display) : NULL;
+
+ if (old_display && new_display) {
+ if (old_display != new_display) {
+ gst_clear_object (&stereosplit->context);
+ gst_gl_view_convert_set_context (stereosplit->viewconvert, NULL);
+ GST_INFO_OBJECT (stereosplit, "display changed to %" GST_PTR_FORMAT,
+ new_display);
+ if (ensure_context_unlocked (stereosplit)) {
+ gst_gl_view_convert_set_context (stereosplit->viewconvert,
+ stereosplit->context);
+ }
+ }
+ }
+ gst_clear_object (&old_display);
+ gst_clear_object (&new_display);
+ g_rec_mutex_unlock (&stereosplit->context_lock);
+
GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->set_context (element,
context);
}
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
+ g_rec_mutex_lock (&stereosplit->context_lock);
if (!gst_gl_ensure_element_data (element, &stereosplit->display,
&stereosplit->other_context))
return GST_STATE_CHANGE_FAILURE;
gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
+ g_rec_mutex_unlock (&stereosplit->context_lock);
break;
default:
break;
switch (transition) {
case GST_STATE_CHANGE_READY_TO_NULL:
- if (stereosplit->other_context) {
- gst_object_unref (stereosplit->other_context);
- stereosplit->other_context = NULL;
- }
-
- if (stereosplit->display) {
- gst_object_unref (stereosplit->display);
- stereosplit->display = NULL;
- }
+ g_rec_mutex_lock (&stereosplit->context_lock);
+ gst_clear_object (&stereosplit->other_context);
+ gst_clear_object (&stereosplit->display);
+ g_rec_mutex_unlock (&stereosplit->context_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
stereosplit_reset (stereosplit);
{
GstCaps *next_caps;
- /* FIXME: Is this the right way to ensure a context here ? */
- if (!ensure_context (self))
- return NULL;
-
next_caps =
gst_gl_view_convert_transform_caps (self->viewconvert, direction, caps,
NULL);
* left right pad to either left/mono and right/mono, as they prefer
*/
+ if (!ensure_context (split)) {
+ res = FALSE;
+ goto fail;
+ }
+
/* Calculate what downstream can collectively support */
left =
stereosplit_get_src_caps (split, split->left_pad,
goto fail;
}
+ g_rec_mutex_lock (&split->context_lock);
gst_gl_view_convert_set_context (split->viewconvert, split->context);
tridcaps = gst_caps_make_writable (tridcaps);
tridcaps = gst_caps_fixate (tridcaps);
if (!gst_gl_view_convert_set_caps (split->viewconvert, sinkcaps, tridcaps)) {
+ g_rec_mutex_unlock (&split->context_lock);
GST_ERROR_OBJECT (split, "Failed to set caps on converter");
goto fail;
}
/* FIXME: Provide left and right caps to do_bufferpool */
stereosplit_do_bufferpool (split, left);
+ g_rec_mutex_unlock (&split->context_lock);
res = TRUE;
}
static gboolean
-_find_local_gl_context (GstGLStereoSplit * split)
+_find_local_gl_context_unlocked (GstGLStereoSplit * split)
{
+ GstGLContext *context = split->context;
+
if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SRC,
- &split->context))
- return TRUE;
+ &context)) {
+ if (context->display == split->display) {
+ split->context = context;
+ return TRUE;
+ }
+ if (context != split->context)
+ gst_clear_object (&context);
+ }
+ context = split->context;
if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SINK,
- &split->context))
- return TRUE;
+ &context)) {
+ if (context->display == split->display) {
+ split->context = context;
+ return TRUE;
+ }
+ if (context != split->context)
+ gst_clear_object (&context);
+ }
return FALSE;
}
static gboolean
-ensure_context (GstGLStereoSplit * self)
+ensure_context_unlocked (GstGLStereoSplit * self)
{
GError *error = NULL;
+ GST_DEBUG_OBJECT (self, "attempting to find an OpenGL context, existing %"
+ GST_PTR_FORMAT, self->context);
+
if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
return FALSE;
gst_gl_display_filter_gl_api (self->display, SUPPORTED_GL_APIS);
- _find_local_gl_context (self);
+ _find_local_gl_context_unlocked (self);
if (!self->context) {
GST_OBJECT_LOCK (self->display);
goto unsupported_gl_api;
}
+ GST_INFO_OBJECT (self, "found OpenGL context %" GST_PTR_FORMAT,
+ self->context);
+
return TRUE;
unsupported_gl_api:
}
static gboolean
+ensure_context (GstGLStereoSplit * self)
+{
+ gboolean ret;
+ g_rec_mutex_lock (&self->context_lock);
+ ret = ensure_context_unlocked (self);
+ g_rec_mutex_unlock (&self->context_lock);
+ return ret;
+}
+
+static gboolean
stereosplit_decide_allocation (GstGLStereoSplit * self, GstQuery * query)
{
- if (!ensure_context (self))
+ if (!ensure_context_unlocked (self))
return FALSE;
return TRUE;
static gboolean
stereosplit_propose_allocation (GstGLStereoSplit * self, GstQuery * query)
{
-
if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
return FALSE;
GST_LOG_OBJECT (split, "chaining buffer %" GST_PTR_FORMAT, buf);
+ gst_buffer_ref (buf);
+
+ g_rec_mutex_lock (&split->context_lock);
+
if (gst_gl_view_convert_submit_input_buffer (split->viewconvert,
GST_BUFFER_IS_DISCONT (buf), buf) != GST_FLOW_OK) {
+ g_rec_mutex_unlock (&split->context_lock);
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
"Failed to 3d convert buffer"),
("Could not get submit input buffer"));
+ gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer);
+ g_rec_mutex_unlock (&split->context_lock);
if (ret != GST_FLOW_OK) {
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
"Failed to 3d convert buffer"), ("Could not get output buffer"));
+ gst_buffer_unref (buf);
return GST_FLOW_ERROR;
}
- if (split_buffer == NULL)
+ if (split_buffer == NULL) {
+ gst_buffer_unref (buf);
return GST_FLOW_OK; /* Need another input buffer */
+ }
left = gst_buffer_new ();
gst_buffer_copy_into (left, buf,
gst_buffer_unref (left);
if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) {
gst_buffer_unref (split_buffer);
+ gst_buffer_unref (buf);
return ret;
}
ret = gst_pad_push (split->right_pad, gst_buffer_ref (right));
gst_buffer_unref (right);
gst_buffer_unref (split_buffer);
+ gst_buffer_unref (buf);
return ret;
}