gl: download whenever we have sysmem capsfeatures
authorMatthew Waters <matthew@centricular.com>
Wed, 24 Sep 2014 03:13:19 +0000 (13:13 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:46 +0000 (19:31 +0000)
Otherwise we could pass on a RGBA formatted buffer and downstream would
misinterpret that as some other video format.

Fixes pipelines of the form

    gleffects ! tee ! xvimagesink

ext/gl/gstglmixer.c
ext/gl/gstglmixer.h
ext/gl/gstgltestsrc.c
ext/gl/gstgltestsrc.h
gst-libs/gst/gl/gstglfilter.c
gst-libs/gst/gl/gstglfilter.h

index 3fcd728..04c951f 100644 (file)
@@ -131,6 +131,8 @@ _negotiated_caps (GstVideoAggregator * vagg, GstCaps * caps)
 
   mix->priv->negotiated = ret;
 
+  gst_caps_replace (&mix->out_caps, caps);
+
   return ret;
 }
 
@@ -826,32 +828,37 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
   gboolean res = TRUE;
   guint array_index = 0;
   GstVideoFrame out_frame;
-  gboolean out_gl_wrapped = FALSE;
   GstElement *element = GST_ELEMENT (mix);
   GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
   GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
   GstGLMixerPrivate *priv = mix->priv;
+  gboolean to_download =
+      gst_caps_features_is_equal (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY,
+      gst_caps_get_features (mix->out_caps, 0));
+  GstMapFlags out_map_flags = GST_MAP_WRITE;
 
   GST_TRACE ("Processing buffers");
 
-  if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf,
-          GST_MAP_WRITE | GST_MAP_GL)) {
+  to_download |= !gst_is_gl_memory (gst_buffer_peek_memory (outbuf, 0));
+
+  if (!to_download)
+    out_map_flags |= GST_MAP_GL;
+
+  if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf, out_map_flags)) {
     return FALSE;
   }
 
-  if (gst_is_gl_memory (out_frame.map[0].memory)) {
+  if (!to_download) {
     out_tex = *(guint *) out_frame.data[0];
   } else {
     GST_INFO ("Output Buffer does not contain correct memory, "
         "attempting to wrap for download");
 
-    out_tex = mix->out_tex_id;;
-
     if (!mix->download)
       mix->download = gst_gl_download_new (mix->context);
 
     gst_gl_download_set_format (mix->download, &out_frame.info);
-    out_gl_wrapped = TRUE;
+    out_tex = mix->out_tex_id;
   }
 
   GST_OBJECT_LOCK (mix);
@@ -910,7 +917,7 @@ gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
 
   g_mutex_unlock (&priv->gl_resource_lock);
 
-  if (out_gl_wrapped) {
+  if (to_download) {
     if (!gst_gl_download_perform_with_data (mix->download, out_tex,
             out_frame.data)) {
       GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s",
index a9e3a3c..d66ef30 100644 (file)
@@ -69,6 +69,8 @@ struct _GstGLMixer
   GstGLContext *context;
   GLuint fbo;
   GLuint depthbuffer;
+
+  GstCaps *out_caps;
 };
 
 struct _GstGLMixerClass
index 3b60f77..c154477 100644 (file)
@@ -415,6 +415,8 @@ gst_gl_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps)
 
   gltestsrc->negotiated = TRUE;
 
+  gst_caps_replace (&gltestsrc->out_caps, caps);
+
   return TRUE;
 
 /* ERRORS */
@@ -543,14 +545,20 @@ gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc)
 static GstFlowReturn
 gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
 {
-  GstGLTestSrc *src;
+  GstGLTestSrc *src = GST_GL_TEST_SRC (psrc);
   GstClockTime next_time;
   gint width, height;
   GstVideoFrame out_frame;
-  gboolean out_gl_wrapped = FALSE;
   guint out_tex;
+  gboolean to_download =
+      gst_caps_features_is_equal (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY,
+      gst_caps_get_features (src->out_caps, 0));
+  GstMapFlags out_map_flags = GST_MAP_WRITE;
 
-  src = GST_GL_TEST_SRC (psrc);
+  to_download |= !gst_is_gl_memory (gst_buffer_peek_memory (buffer, 0));
+
+  if (!to_download)
+    out_map_flags |= GST_MAP_GL;
 
   if (G_UNLIKELY (!src->negotiated || !src->context))
     goto not_negotiated;
@@ -570,29 +578,27 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
       src->make_image = gst_gl_test_src_black;
   }
 
-  if (!gst_video_frame_map (&out_frame, &src->out_info, buffer,
-          GST_MAP_WRITE | GST_MAP_GL)) {
+  if (!gst_video_frame_map (&out_frame, &src->out_info, buffer, out_map_flags)) {
     return GST_FLOW_NOT_NEGOTIATED;
   }
 
-  if (gst_is_gl_memory (out_frame.map[0].memory)) {
+  if (!to_download) {
     out_tex = *(guint *) out_frame.data[0];
   } else {
     GST_INFO ("Output Buffer does not contain correct meta, "
         "attempting to wrap for download");
 
+    if (!src->download)
+      src->download = gst_gl_download_new (src->context);
+
+    gst_gl_download_set_format (src->download, &out_frame.info);
+
     if (!src->out_tex_id) {
       gst_gl_context_gen_texture (src->context, &src->out_tex_id,
           GST_VIDEO_FORMAT_RGBA, GST_VIDEO_FRAME_WIDTH (&out_frame),
           GST_VIDEO_FRAME_HEIGHT (&out_frame));
     }
     out_tex = src->out_tex_id;
-
-    if (!src->download)
-      src->download = gst_gl_download_new (src->context);
-
-    gst_gl_download_set_format (src->download, &out_frame.info);
-    out_gl_wrapped = TRUE;
   }
 
   gst_buffer_replace (&src->buffer, buffer);
@@ -604,7 +610,7 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
     goto not_negotiated;
   }
 
-  if (out_gl_wrapped) {
+  if (to_download) {
     if (!gst_gl_download_perform_with_data (src->download, out_tex,
             out_frame.data)) {
       GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, ("%s",
@@ -665,6 +671,8 @@ gst_gl_test_src_stop (GstBaseSrc * basesrc)
 {
   GstGLTestSrc *src = GST_GL_TEST_SRC (basesrc);
 
+  gst_caps_replace (&src->out_caps, NULL);
+
   if (src->context) {
     if (src->out_tex_id) {
       gst_gl_context_del_texture (src->context, &src->out_tex_id);
index 3e854e8..0e7d71b 100644 (file)
@@ -118,6 +118,8 @@ struct _GstGLTestSrc {
     const gchar *fragment_src;
 
     void (*make_image) (GstGLTestSrc* v, GstBuffer* buffer, gint w, gint h);
+
+    GstCaps *out_caps;
 };
 
 struct _GstGLTestSrcClass {
index 1b68e91..de4a1af 100644 (file)
@@ -244,6 +244,8 @@ gst_gl_filter_reset (GstGLFilter * filter)
 {
   GstGLFilterClass *filter_class = GST_GL_FILTER_GET_CLASS (filter);
 
+  gst_caps_replace (&filter->out_caps, NULL);
+
   if (filter->upload) {
     gst_object_unref (filter->upload);
     filter->upload = NULL;
@@ -822,6 +824,8 @@ gst_gl_filter_set_caps (GstBaseTransform * bt, GstCaps * incaps,
       goto error;
   }
 
+  gst_caps_replace (&filter->out_caps, outcaps);
+
   GST_DEBUG ("set_caps %dx%d", GST_VIDEO_INFO_WIDTH (&filter->out_info),
       GST_VIDEO_INFO_HEIGHT (&filter->out_info));
 
@@ -1169,24 +1173,29 @@ gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf,
   GstGLFilterClass *filter_class;
   guint in_tex, out_tex;
   GstVideoFrame out_frame;
-  gboolean ret, out_gl_mem;
-  GstVideoGLTextureUploadMeta *out_tex_upload_meta;
+  gboolean ret;
+  gboolean to_download =
+      gst_caps_features_is_equal (GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY,
+      gst_caps_get_features (filter->out_caps, 0));
+  GstMapFlags out_map_flags = GST_MAP_WRITE;
 
   filter_class = GST_GL_FILTER_GET_CLASS (filter);
 
   if (!gst_gl_upload_perform_with_buffer (filter->upload, inbuf, &in_tex, NULL))
     return FALSE;
 
+  to_download |= !gst_is_gl_memory (gst_buffer_peek_memory (outbuf, 0));
+
+  if (!to_download)
+    out_map_flags |= GST_MAP_GL;
+
   if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf,
-          GST_MAP_WRITE | GST_MAP_GL)) {
+          out_map_flags)) {
     ret = FALSE;
     goto inbuf_error;
   }
 
-  out_gl_mem = gst_is_gl_memory (out_frame.map[0].memory);
-  out_tex_upload_meta = gst_buffer_get_video_gl_texture_upload_meta (outbuf);
-
-  if (out_gl_mem) {
+  if (!to_download) {
     out_tex = *(guint *) out_frame.data[0];
   } else {
     GST_LOG ("Output Buffer does not contain correct memory, "
@@ -1196,6 +1205,7 @@ gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf,
       filter->download = gst_gl_download_new (filter->context);
 
     gst_gl_download_set_format (filter->download, &out_frame.info);
+
     out_tex = filter->out_tex_id;
   }
 
@@ -1205,7 +1215,7 @@ gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf,
   g_assert (filter_class->filter_texture);
   ret = filter_class->filter_texture (filter, in_tex, out_tex);
 
-  if (!out_gl_mem && !out_tex_upload_meta) {
+  if (to_download) {
     if (!gst_gl_download_perform_with_data (filter->download, out_tex,
             out_frame.data)) {
       GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND,
index 6e77022..c786493 100644 (file)
@@ -68,6 +68,9 @@ struct _GstGLFilter
 
   GstVideoInfo       in_info;
   GstVideoInfo       out_info;
+
+  GstCaps           *out_caps;
+
   GLuint             fbo;
   GLuint             depthbuffer;