diff --git a/sys/androidmedia/gstamcvideodec.c b/sys/androidmedia/gstamcvideodec.c index 58a438601f..d47fed2e51 100644 --- a/sys/androidmedia/gstamcvideodec.c +++ b/sys/androidmedia/gstamcvideodec.c @@ -105,6 +105,8 @@ static void gst_amc_video_dec_finalize (GObject * object); static GstStateChangeReturn gst_amc_video_dec_change_state (GstElement * element, GstStateChange transition); +static void gst_amc_video_dec_set_context (GstElement * element, + GstContext * context); static gboolean gst_amc_video_dec_open (GstVideoDecoder * decoder); static gboolean gst_amc_video_dec_close (GstVideoDecoder * decoder); @@ -118,6 +120,8 @@ static GstFlowReturn gst_amc_video_dec_handle_frame (GstVideoDecoder * decoder, static GstFlowReturn gst_amc_video_dec_finish (GstVideoDecoder * decoder); static gboolean gst_amc_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query); +static gboolean gst_amc_video_dec_src_query (GstVideoDecoder * bdec, + GstQuery * query); static GstFlowReturn gst_amc_video_dec_drain (GstAmcVideoDec * self); static gboolean gst_amc_video_dec_check_codec_config (GstAmcVideoDec * self); @@ -268,6 +272,8 @@ gst_amc_video_dec_class_init (GstAmcVideoDecClass * klass) element_class->change_state = GST_DEBUG_FUNCPTR (gst_amc_video_dec_change_state); + element_class->set_context = + GST_DEBUG_FUNCPTR (gst_amc_video_dec_set_context); videodec_class->start = GST_DEBUG_FUNCPTR (gst_amc_video_dec_start); videodec_class->stop = GST_DEBUG_FUNCPTR (gst_amc_video_dec_stop); @@ -280,6 +286,7 @@ gst_amc_video_dec_class_init (GstAmcVideoDecClass * klass) videodec_class->finish = GST_DEBUG_FUNCPTR (gst_amc_video_dec_finish); videodec_class->decide_allocation = GST_DEBUG_FUNCPTR (gst_amc_video_dec_decide_allocation); + videodec_class->src_query = GST_DEBUG_FUNCPTR (gst_amc_video_dec_src_query); } static void @@ -364,6 +371,17 @@ gst_amc_video_dec_finalize (GObject * object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gst_amc_video_dec_set_context (GstElement * element, GstContext * context) +{ + GstAmcVideoDec *self = GST_AMC_VIDEO_DEC (element); + + gst_gl_handle_set_context (element, context, &self->gl_display, + &self->other_gl_context); + + GST_ELEMENT_CLASS (parent_class)->set_context (element, context); +} + static GstStateChangeReturn gst_amc_video_dec_change_state (GstElement * element, GstStateChange transition) { @@ -1831,6 +1849,54 @@ gst_amc_video_dec_drain (GstAmcVideoDec * self) return ret; } +static gboolean +gst_amc_video_dec_src_query (GstVideoDecoder * bdec, GstQuery * query) +{ + GstAmcVideoDec *self = GST_AMC_VIDEO_DEC (bdec); + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONTEXT: + { + const gchar *context_type; + GstContext *context, *old_context; + + ret = gst_gl_handle_context_query ((GstElement *) self, query, + &self->gl_display, &self->other_gl_context); + gst_query_parse_context_type (query, &context_type); + + if (g_strcmp0 (context_type, "gst.gl.local_context") == 0) { + GstStructure *s; + + gst_query_parse_context (query, &old_context); + + if (old_context) + context = gst_context_copy (old_context); + else + context = gst_context_new ("gst.gl.local_context", FALSE); + + s = gst_context_writable_structure (context); + gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, self->gl_context, + NULL); + gst_query_set_context (query, context); + gst_context_unref (context); + + ret = self->gl_context != NULL; + } + GST_LOG_OBJECT (self, "context query of type %s %i", context_type, ret); + + if (ret) + return ret; + + break; + } + default: + break; + } + + return GST_VIDEO_DECODER_CLASS (parent_class)->src_query (bdec, query); +} + static gboolean _caps_are_rgba_with_gl_memory (GstCaps * caps) { @@ -1853,12 +1919,43 @@ _caps_are_rgba_with_gl_memory (GstCaps * caps) GST_CAPS_FEATURE_MEMORY_GL_MEMORY); } +static gboolean +_find_local_gl_context (GstAmcVideoDec * self) +{ + GstQuery *query; + GstContext *context; + const GstStructure *s; + + if (self->gl_context) + return TRUE; + + query = gst_query_new_context ("gst.gl.local_context"); + if (!self->gl_context && gst_gl_run_query (GST_ELEMENT (self), query, GST_PAD_SRC)) { + gst_query_parse_context (query, &context); + if (context) { + s = gst_context_get_structure (context); + gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, &self->gl_context, + NULL); + } + } + + GST_DEBUG_OBJECT (self, "found local context %p", self->gl_context); + + gst_query_unref (query); + + if (self->gl_context) + return TRUE; + + return FALSE; +} + static gboolean gst_amc_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) { - GstCaps *caps = NULL; - gboolean need_pool = FALSE; GstAmcVideoDec *self = GST_AMC_VIDEO_DEC (bdec); + gboolean need_pool = FALSE; + GstCaps *caps = NULL; +// GError *error = NULL; if (!GST_VIDEO_DECODER_CLASS (parent_class)->decide_allocation (bdec, query)) return FALSE; @@ -1866,68 +1963,54 @@ gst_amc_video_dec_decide_allocation (GstVideoDecoder * bdec, GstQuery * query) self->downstream_supports_gl = FALSE; gst_query_parse_allocation (query, &caps, &need_pool); if (_caps_are_rgba_with_gl_memory (caps)) { - guint i, n_allocation_pools; - GstGLBufferPool *gl_pool = NULL; - GstGLContext *gl_context = NULL; - GstGLDisplay *gl_display = NULL; - n_allocation_pools = MAX (gst_query_get_n_allocation_pools (query), 1); - for (i = 0; i < n_allocation_pools; i++) { - GstBufferPool *pool = NULL; - GstStructure *config = NULL; - guint min, max, size; - - gst_query_parse_nth_allocation_pool (query, i, &pool, &size, &min, &max); - config = gst_buffer_pool_get_config (pool); - if (!config) { - gst_object_unref (pool); - continue; - } - - if (!GST_IS_GL_BUFFER_POOL (pool)) { - gst_object_unref (pool); - continue; - } - - gl_pool = GST_GL_BUFFER_POOL (pool); - break; - } - - if (!gl_pool) { - GST_WARNING_OBJECT (bdec, "Failed to get gl pool from downstream"); - gst_object_unref (gl_pool); + if (!gst_gl_ensure_element_data (self, &self->gl_display, + &self->other_gl_context)) return FALSE; - } - gl_context = gl_pool->context; - if (!gl_context) { - GST_WARNING_OBJECT (bdec, "Failed to get gl context from downstream"); - gst_object_unref (gl_pool); - return FALSE; + if (!_find_local_gl_context (self)) + goto out; +#if 0 + if (!self->gl_context) { + GST_OBJECT_LOCK (self->gl_display); + do { + if (self->gl_context) { + gst_object_unref (self->gl_context); + self->gl_context = NULL; + } + /* just get a GL context. we don't care */ + self->gl_context = + gst_gl_display_get_gl_context_for_thread (self->gl_display, NULL); + if (!self->gl_context) { + if (!gst_gl_display_create_context (self->gl_display, + self->other_gl_context, &self->gl_context, &error)) { + GST_OBJECT_UNLOCK (mix->display); + goto context_error; + } + } + } while (!gst_gl_display_add_context (self->gl_display, self->gl_context)); + GST_OBJECT_UNLOCK (self->gl_display); } - - if (self->gl_context) { - gst_object_unref (self->gl_context); - } - +#endif if (self->renderer) { gst_amc_2d_texture_renderer_free (self->renderer); self->renderer = NULL; } -// gl_display = gst_gl_context_get_display (gl_context); -// self->gl_context = gst_gl_context_new (gl_display); -// gst_object_unref (gl_display); - self->gl_context = gst_object_ref (gl_context); - -// gst_gl_context_create (self->gl_context, gl_context, NULL); - - gst_object_unref (gl_pool); - self->downstream_supports_gl = TRUE; } +out: return gst_amc_video_dec_check_codec_config (self); +#if 0 +context_error: + { + GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND, ("%s", error->message), + (NULL)); + g_clear_error (&error); + return FALSE; + } +#endif } static void diff --git a/sys/androidmedia/gstamcvideodec.h b/sys/androidmedia/gstamcvideodec.h index 07a2f72048..4490dab40c 100644 --- a/sys/androidmedia/gstamcvideodec.h +++ b/sys/androidmedia/gstamcvideodec.h @@ -94,7 +94,9 @@ struct _GstAmcVideoDec GstAmcSurface *surface; + GstGLDisplay *gl_display; GstGLContext *gl_context; + GstGLContext *other_gl_context; GstAmc2DTextureRenderer *renderer; gboolean downstream_supports_gl;