mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
glstereosplit: support gl display changes
This commit is contained in:
parent
de58d23b5c
commit
4e12363cb7
2 changed files with 97 additions and 23 deletions
|
@ -85,6 +85,7 @@ static gboolean stereosplit_src_query (GstPad * pad, GstObject * parent,
|
||||||
static gboolean stereosplit_src_event (GstPad * pad, GstObject * parent,
|
static gboolean stereosplit_src_event (GstPad * pad, GstObject * parent,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static gboolean ensure_context (GstGLStereoSplit * self);
|
static gboolean ensure_context (GstGLStereoSplit * self);
|
||||||
|
static gboolean ensure_context_unlocked (GstGLStereoSplit * self);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gl_stereosplit_class_init (GstGLStereoSplitClass * klass)
|
gst_gl_stereosplit_class_init (GstGLStereoSplitClass * klass)
|
||||||
|
@ -136,6 +137,8 @@ gst_gl_stereosplit_init (GstGLStereoSplit * self)
|
||||||
gst_element_add_pad (GST_ELEMENT (self), self->right_pad);
|
gst_element_add_pad (GST_ELEMENT (self), self->right_pad);
|
||||||
|
|
||||||
self->viewconvert = gst_gl_view_convert_new ();
|
self->viewconvert = gst_gl_view_convert_new ();
|
||||||
|
|
||||||
|
g_rec_mutex_init (&self->context_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -155,6 +158,8 @@ stereosplit_finalize (GstGLStereoSplit * self)
|
||||||
if (self->viewconvert)
|
if (self->viewconvert)
|
||||||
gst_object_replace ((GstObject **) & self->viewconvert, NULL);
|
gst_object_replace ((GstObject **) & self->viewconvert, NULL);
|
||||||
|
|
||||||
|
g_rec_mutex_clear (&self->context_lock);
|
||||||
|
|
||||||
klass->finalize ((GObject *) (self));
|
klass->finalize ((GObject *) (self));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,13 +167,37 @@ static void
|
||||||
stereosplit_set_context (GstElement * element, GstContext * context)
|
stereosplit_set_context (GstElement * element, GstContext * context)
|
||||||
{
|
{
|
||||||
GstGLStereoSplit *stereosplit = GST_GL_STEREOSPLIT (element);
|
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,
|
gst_gl_handle_set_context (element, context, &stereosplit->display,
|
||||||
&stereosplit->other_context);
|
&stereosplit->other_context);
|
||||||
|
|
||||||
if (stereosplit->display)
|
if (stereosplit->display)
|
||||||
gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
|
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,
|
GST_ELEMENT_CLASS (gst_gl_stereosplit_parent_class)->set_context (element,
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
|
@ -181,11 +210,13 @@ stereosplit_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
|
g_rec_mutex_lock (&stereosplit->context_lock);
|
||||||
if (!gst_gl_ensure_element_data (element, &stereosplit->display,
|
if (!gst_gl_ensure_element_data (element, &stereosplit->display,
|
||||||
&stereosplit->other_context))
|
&stereosplit->other_context))
|
||||||
return GST_STATE_CHANGE_FAILURE;
|
return GST_STATE_CHANGE_FAILURE;
|
||||||
|
|
||||||
gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
|
gst_gl_display_filter_gl_api (stereosplit->display, SUPPORTED_GL_APIS);
|
||||||
|
g_rec_mutex_unlock (&stereosplit->context_lock);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -197,15 +228,10 @@ stereosplit_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
if (stereosplit->other_context) {
|
g_rec_mutex_lock (&stereosplit->context_lock);
|
||||||
gst_object_unref (stereosplit->other_context);
|
gst_clear_object (&stereosplit->other_context);
|
||||||
stereosplit->other_context = NULL;
|
gst_clear_object (&stereosplit->display);
|
||||||
}
|
g_rec_mutex_unlock (&stereosplit->context_lock);
|
||||||
|
|
||||||
if (stereosplit->display) {
|
|
||||||
gst_object_unref (stereosplit->display);
|
|
||||||
stereosplit->display = NULL;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
stereosplit_reset (stereosplit);
|
stereosplit_reset (stereosplit);
|
||||||
|
@ -223,10 +249,6 @@ stereosplit_transform_caps (GstGLStereoSplit * self, GstPadDirection direction,
|
||||||
{
|
{
|
||||||
GstCaps *next_caps;
|
GstCaps *next_caps;
|
||||||
|
|
||||||
/* FIXME: Is this the right way to ensure a context here ? */
|
|
||||||
if (!ensure_context (self))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
next_caps =
|
next_caps =
|
||||||
gst_gl_view_convert_transform_caps (self->viewconvert, direction, caps,
|
gst_gl_view_convert_transform_caps (self->viewconvert, direction, caps,
|
||||||
NULL);
|
NULL);
|
||||||
|
@ -317,6 +339,11 @@ stereosplit_set_output_caps (GstGLStereoSplit * split, GstCaps * sinkcaps)
|
||||||
* left right pad to either left/mono and right/mono, as they prefer
|
* 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 */
|
/* Calculate what downstream can collectively support */
|
||||||
left =
|
left =
|
||||||
stereosplit_get_src_caps (split, split->left_pad,
|
stereosplit_get_src_caps (split, split->left_pad,
|
||||||
|
@ -384,6 +411,7 @@ stereosplit_set_output_caps (GstGLStereoSplit * split, GstCaps * sinkcaps)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_rec_mutex_lock (&split->context_lock);
|
||||||
gst_gl_view_convert_set_context (split->viewconvert, split->context);
|
gst_gl_view_convert_set_context (split->viewconvert, split->context);
|
||||||
|
|
||||||
tridcaps = gst_caps_make_writable (tridcaps);
|
tridcaps = gst_caps_make_writable (tridcaps);
|
||||||
|
@ -392,12 +420,14 @@ stereosplit_set_output_caps (GstGLStereoSplit * split, GstCaps * sinkcaps)
|
||||||
tridcaps = gst_caps_fixate (tridcaps);
|
tridcaps = gst_caps_fixate (tridcaps);
|
||||||
|
|
||||||
if (!gst_gl_view_convert_set_caps (split->viewconvert, sinkcaps, 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");
|
GST_ERROR_OBJECT (split, "Failed to set caps on converter");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Provide left and right caps to do_bufferpool */
|
/* FIXME: Provide left and right caps to do_bufferpool */
|
||||||
stereosplit_do_bufferpool (split, left);
|
stereosplit_do_bufferpool (split, left);
|
||||||
|
g_rec_mutex_unlock (&split->context_lock);
|
||||||
|
|
||||||
res = TRUE;
|
res = TRUE;
|
||||||
|
|
||||||
|
@ -412,28 +442,46 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
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,
|
if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SRC,
|
||||||
&split->context))
|
&context)) {
|
||||||
return TRUE;
|
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,
|
if (gst_gl_query_local_gl_context (GST_ELEMENT (split), GST_PAD_SINK,
|
||||||
&split->context))
|
&context)) {
|
||||||
return TRUE;
|
if (context->display == split->display) {
|
||||||
|
split->context = context;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
if (context != split->context)
|
||||||
|
gst_clear_object (&context);
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
ensure_context (GstGLStereoSplit * self)
|
ensure_context_unlocked (GstGLStereoSplit * self)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
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))
|
if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
gst_gl_display_filter_gl_api (self->display, SUPPORTED_GL_APIS);
|
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) {
|
if (!self->context) {
|
||||||
GST_OBJECT_LOCK (self->display);
|
GST_OBJECT_LOCK (self->display);
|
||||||
|
@ -460,6 +508,9 @@ ensure_context (GstGLStereoSplit * self)
|
||||||
goto unsupported_gl_api;
|
goto unsupported_gl_api;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (self, "found OpenGL context %" GST_PTR_FORMAT,
|
||||||
|
self->context);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
unsupported_gl_api:
|
unsupported_gl_api:
|
||||||
|
@ -484,10 +535,20 @@ context_error:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
static gboolean
|
||||||
stereosplit_decide_allocation (GstGLStereoSplit * self, GstQuery * query)
|
stereosplit_decide_allocation (GstGLStereoSplit * self, GstQuery * query)
|
||||||
{
|
{
|
||||||
if (!ensure_context (self))
|
if (!ensure_context_unlocked (self))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -497,7 +558,6 @@ stereosplit_decide_allocation (GstGLStereoSplit * self, GstQuery * query)
|
||||||
static gboolean
|
static gboolean
|
||||||
stereosplit_propose_allocation (GstGLStereoSplit * self, GstQuery * query)
|
stereosplit_propose_allocation (GstGLStereoSplit * self, GstQuery * query)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
|
if (!gst_gl_ensure_element_data (self, &self->display, &self->other_context))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
@ -537,22 +597,32 @@ stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf)
|
||||||
|
|
||||||
GST_LOG_OBJECT (split, "chaining buffer %" GST_PTR_FORMAT, buf);
|
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,
|
if (gst_gl_view_convert_submit_input_buffer (split->viewconvert,
|
||||||
GST_BUFFER_IS_DISCONT (buf), buf) != GST_FLOW_OK) {
|
GST_BUFFER_IS_DISCONT (buf), buf) != GST_FLOW_OK) {
|
||||||
|
g_rec_mutex_unlock (&split->context_lock);
|
||||||
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
|
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
|
||||||
"Failed to 3d convert buffer"),
|
"Failed to 3d convert buffer"),
|
||||||
("Could not get submit input buffer"));
|
("Could not get submit input buffer"));
|
||||||
|
gst_buffer_unref (buf);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer);
|
ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer);
|
||||||
|
g_rec_mutex_unlock (&split->context_lock);
|
||||||
if (ret != GST_FLOW_OK) {
|
if (ret != GST_FLOW_OK) {
|
||||||
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
|
GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
|
||||||
"Failed to 3d convert buffer"), ("Could not get output buffer"));
|
"Failed to 3d convert buffer"), ("Could not get output buffer"));
|
||||||
|
gst_buffer_unref (buf);
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
}
|
}
|
||||||
if (split_buffer == NULL)
|
if (split_buffer == NULL) {
|
||||||
|
gst_buffer_unref (buf);
|
||||||
return GST_FLOW_OK; /* Need another input buffer */
|
return GST_FLOW_OK; /* Need another input buffer */
|
||||||
|
}
|
||||||
|
|
||||||
left = gst_buffer_new ();
|
left = gst_buffer_new ();
|
||||||
gst_buffer_copy_into (left, buf,
|
gst_buffer_copy_into (left, buf,
|
||||||
|
@ -571,6 +641,7 @@ stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf)
|
||||||
gst_buffer_unref (left);
|
gst_buffer_unref (left);
|
||||||
if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) {
|
if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) {
|
||||||
gst_buffer_unref (split_buffer);
|
gst_buffer_unref (split_buffer);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -587,6 +658,7 @@ stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf)
|
||||||
ret = gst_pad_push (split->right_pad, gst_buffer_ref (right));
|
ret = gst_pad_push (split->right_pad, gst_buffer_ref (right));
|
||||||
gst_buffer_unref (right);
|
gst_buffer_unref (right);
|
||||||
gst_buffer_unref (split_buffer);
|
gst_buffer_unref (split_buffer);
|
||||||
|
gst_buffer_unref (buf);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,8 @@ struct _GstGLStereoSplit
|
||||||
GstGLContext *other_context;
|
GstGLContext *other_context;
|
||||||
|
|
||||||
GstGLViewConvert *viewconvert;
|
GstGLViewConvert *viewconvert;
|
||||||
|
|
||||||
|
GRecMutex context_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstGLStereoSplitClass
|
struct _GstGLStereoSplitClass
|
||||||
|
|
Loading…
Reference in a new issue