diff options
author | Matthieu Bouron <matthieu.bouron@collabora.com> | 2013-11-18 17:29:08 +0000 |
---|---|---|
committer | Lionel Landwerlin <llandwerlin@gmail.com> | 2013-12-19 12:28:38 +0000 |
commit | 1679946673a9f063fa4485f81baf9515049cfa89 (patch) | |
tree | 0a756b845fb1f3910f663cd8f8813bacd3aa84ba | |
parent | 4a6b396cde0320546ae16a039a743268e2ca022b (diff) | |
download | clutter-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.c | 165 |
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; } |