summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Bouron <matthieu.bouron@collabora.com>2013-11-18 17:29:08 +0000
committerLionel Landwerlin <llandwerlin@gmail.com>2013-12-19 12:28:38 +0000
commit1679946673a9f063fa4485f81baf9515049cfa89 (patch)
tree0a756b845fb1f3910f663cd8f8813bacd3aa84ba
parent4a6b396cde0320546ae16a039a743268e2ca022b (diff)
downloadclutter-gst-1679946673a9f063fa4485f81baf9515049cfa89.tar.gz
video-sink: suport gl texture upload meta api
https://bugzilla.gnome.org/show_bug.cgi?id=712834
-rw-r--r--clutter-gst/clutter-gst-video-sink.c165
1 files changed, 163 insertions, 2 deletions
diff --git a/clutter-gst/clutter-gst-video-sink.c b/clutter-gst/clutter-gst-video-sink.c
index 1c982ad..6c4db99 100644
--- a/clutter-gst/clutter-gst-video-sink.c
+++ b/clutter-gst/clutter-gst-video-sink.c
@@ -140,13 +140,21 @@ static gchar *yv12_to_rgba_shader =
"RGB," \
"BGR }"
+#define BASE_GL_SINK_CAPS "{ RGBA }"
+
+#define GL_SINK_CAPS GST_VIDEO_CAPS_MAKE_WITH_FEATURES( \
+ GST_CAPS_FEATURE_META_GST_VIDEO_GL_TEXTURE_UPLOAD_META, \
+ BASE_GL_SINK_CAPS)
#define SINK_CAPS GST_VIDEO_CAPS_MAKE(BASE_SINK_CAPS)
static GstStaticPadTemplate sinktemplate_all = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (SINK_CAPS));
+ GST_STATIC_CAPS (
+ GL_SINK_CAPS ";"
+ SINK_CAPS
+ ));
GST_DEBUG_CATEGORY_STATIC (clutter_gst_video_sink_debug);
#define GST_CAT_DEFAULT clutter_gst_video_sink_debug
@@ -168,7 +176,8 @@ typedef enum
CLUTTER_GST_YV12,
CLUTTER_GST_NV12,
CLUTTER_GST_I420,
- CLUTTER_GST_SURFACE
+ CLUTTER_GST_SURFACE,
+ CLUTTER_GST_GL_TEXTURE_UPLOAD,
} ClutterGstVideoFormat;
/*
@@ -196,6 +205,7 @@ typedef struct _ClutterGstSource
GstBuffer *buffer;
gboolean has_new_caps;
gboolean stage_lost;
+ gboolean has_gl_texture_upload_meta;
} ClutterGstSource;
/*
@@ -400,6 +410,9 @@ clutter_gst_parse_caps (GstCaps * caps,
goto unhandled_format;
}
+ if (priv->source->has_gl_texture_upload_meta)
+ format = CLUTTER_GST_GL_TEXTURE_UPLOAD;
+
/* find a renderer that can display our format */
renderer = clutter_gst_find_renderer_by_format (sink, format);
@@ -500,6 +513,7 @@ static gboolean
clutter_gst_source_dispatch (GSource * source,
GSourceFunc callback, gpointer user_data)
{
+ GstVideoGLTextureUploadMeta *upload_meta;
ClutterGstSource *gst_source = (ClutterGstSource *) source;
ClutterGstVideoSinkPrivate *priv = gst_source->sink->priv;
GstBuffer *buffer;
@@ -508,6 +522,19 @@ clutter_gst_source_dispatch (GSource * source,
g_mutex_lock (&gst_source->buffer_lock);
+#ifdef CLUTTER_COGL_HAS_GL
+ if (!gst_source->has_gl_texture_upload_meta &&
+ (upload_meta = gst_buffer_get_video_gl_texture_upload_meta (gst_source->buffer))) {
+ if (priv->renderer)
+ priv->renderer->deinit (gst_source->sink);
+
+ priv->renderer = clutter_gst_find_renderer_by_format (gst_source->sink,
+ CLUTTER_GST_GL_TEXTURE_UPLOAD);
+
+ gst_source->has_gl_texture_upload_meta = TRUE;
+ }
+#endif
+
if (G_UNLIKELY (gst_source->has_new_caps)) {
GstCaps *caps =
gst_pad_get_current_caps (GST_BASE_SINK_PAD ((GST_BASE_SINK
@@ -1364,6 +1391,134 @@ static ClutterGstRenderer hw_renderer = {
};
#endif
+#ifdef CLUTTER_COGL_HAS_GL
+
+typedef struct {
+ gboolean is_initialized;
+} GLTextureUploadRendererContext;
+
+static void
+clutter_gst_gl_texture_upload_init (ClutterGstVideoSink * sink)
+{
+ ClutterGstRenderer *renderer = sink->priv->renderer;
+
+ if (renderer->context)
+ return;
+
+ renderer->context = g_new0 (GLTextureUploadRendererContext, 1);
+ if (!renderer->context) {
+ GST_ERROR ("Failed to allocate renderer context");
+ }
+}
+
+static void
+clutter_gst_gl_texture_upload_deinit (ClutterGstVideoSink * sink)
+{
+ ClutterGstRenderer *renderer = sink->priv->renderer;
+
+ if (!renderer->context)
+ return;
+
+ g_free (renderer->context);
+ renderer->context = NULL;
+}
+
+static gboolean
+clutter_gst_gl_texture_upload_init_texture (ClutterGstVideoSink * sink)
+{
+ CoglHandle material;
+ CoglTexture *tex = NULL;
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ ClutterGstRenderer *renderer = sink->priv->renderer;
+ GLTextureUploadRendererContext *context = renderer->context;
+
+ tex = cogl_texture_new_with_size (priv->info.width, priv->info.height,
+ CLUTTER_GST_TEXTURE_FLAGS, COGL_PIXEL_FORMAT_RGBA_8888);
+
+ if (!tex) {
+ GST_WARNING ("Couldn't create cogl texture");
+ return FALSE;
+ }
+
+ material = cogl_material_new ();
+ if (!material) {
+ GST_WARNING ("Couldn't create cogl material");
+ return FALSE;
+ }
+ cogl_material_set_layer (material, 0, tex);
+ clutter_texture_set_cogl_material (priv->texture, material);
+
+ cogl_object_unref (tex);
+ cogl_object_unref (material);
+
+ context->is_initialized = TRUE;
+ return TRUE;
+}
+
+static gboolean
+clutter_gst_gl_texture_upload_upload (ClutterGstVideoSink * sink, GstBuffer * buffer)
+{
+ ClutterGstVideoSinkPrivate *priv = sink->priv;
+ ClutterGstRenderer *renderer = sink->priv->renderer;
+ GLTextureUploadRendererContext *context = renderer->context;
+ GstVideoGLTextureUploadMeta *upload_meta = NULL;
+ CoglTexture *tex;
+ guint gl_handle[4], gl_target[4];
+
+ if (!context) {
+ GST_WARNING ("Couldn't get the renderer context");
+ return FALSE;
+ }
+
+ if (!context->is_initialized) {
+ gboolean ret = clutter_gst_gl_texture_upload_init_texture (sink);
+ if (!ret)
+ return ret;
+ }
+
+ upload_meta = gst_buffer_get_video_gl_texture_upload_meta (buffer);
+ if (!upload_meta) {
+ GST_WARNING ("Buffer does not support GLTextureUploadMeta API");
+ return FALSE;
+ }
+
+ if (upload_meta->n_textures != 1 ||
+ upload_meta->texture_type[0] != GST_VIDEO_GL_TEXTURE_TYPE_RGBA) {
+ GST_WARNING ("clutter-video-sink only supports gl upload in a single RGBA texture");
+ return FALSE;
+ }
+
+ if (!(tex = clutter_texture_get_cogl_texture (priv->texture))) {
+ GST_WARNING ("Couldn't get Cogl texture");
+ return FALSE;
+ }
+
+ if (!cogl_texture_get_gl_texture (tex, gl_handle, gl_target)) {
+ GST_WARNING ("Couldn't get GL texture");
+ return FALSE;
+ }
+
+ if (!gst_video_gl_texture_upload_meta_upload (upload_meta, gl_handle)) {
+ GST_WARNING ("GL texture upload failed");
+ return FALSE;
+ }
+
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->texture));
+ return TRUE;
+}
+
+static ClutterGstRenderer gl_texture_upload_renderer = {
+ "GL Texture upload renderer",
+ CLUTTER_GST_GL_TEXTURE_UPLOAD,
+ 0,
+ GST_STATIC_CAPS (GL_SINK_CAPS),
+ NULL,
+ clutter_gst_gl_texture_upload_init,
+ clutter_gst_gl_texture_upload_deinit,
+ clutter_gst_gl_texture_upload_upload,
+};
+#endif
+
static GSList *
clutter_gst_build_renderers_list (void)
{
@@ -1388,6 +1543,9 @@ clutter_gst_build_renderers_list (void)
#ifdef HAVE_HW_DECODER_SUPPORT
&hw_renderer,
#endif
+#ifdef CLUTTER_COGL_HAS_GL
+ &gl_texture_upload_renderer,
+#endif
NULL
};
@@ -1766,6 +1924,9 @@ clutter_gst_video_sink_propose_allocation (GstBaseSink * base_sink, GstQuery * q
gst_query_add_allocation_meta (query,
GST_VIDEO_META_API_TYPE, NULL);
+ gst_query_add_allocation_meta (query,
+ GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, NULL);
+
return TRUE;
}