[Mesa-dev] [PATCH kmscube v2 08/10] gst-decoder.c: use a custom appsink subclass to make sure videometa exists

Carlos Rafael Giani dv at pseudoterminal.org
Tue Apr 11 08:27:49 UTC 2017


Signed-off-by: Carlos Rafael Giani <dv at pseudoterminal.org>
---
 Makefile.am         |   2 +-
 gst-decoder.c       |  20 ++++++++-
 gst-video-appsink.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 gst-video-appsink.h |  31 +++++++++++++
 kmscube.c           |   2 +
 5 files changed, 178 insertions(+), 3 deletions(-)
 create mode 100644 gst-video-appsink.c
 create mode 100644 gst-video-appsink.h

diff --git a/Makefile.am b/Makefile.am
index a36087d..0407e89 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -57,5 +57,5 @@ kmscube_SOURCES = \
 if ENABLE_GST
 kmscube_LDADD += $(GST_LIBS)
 kmscube_CFLAGS += $(GST_CFLAGS)
-kmscube_SOURCES += cube-video.c gst-decoder.c
+kmscube_SOURCES += cube-video.c gst-decoder.c gst-video-appsink.c
 endif
diff --git a/gst-decoder.c b/gst-decoder.c
index 768aa1b..188fe4b 100644
--- a/gst-decoder.c
+++ b/gst-decoder.c
@@ -246,9 +246,25 @@ video_init(const struct egl *egl, const struct gbm *gbm, const char *filename)
 	dec->gbm = gbm;
 	dec->egl = egl;
 
-	/* Setup pipeline: */
+	/* Setup pipeline. Note that we use video_appsink here, not appsink.
+	 * video_appsink is an appsink subclass that adds the videometa to
+	 * the allocation query's list of metas supported by the sink.
+	 *
+	 * In some cases, sinks that do not declare videometa as supported
+	 * can trigger unexpected behavior when used with video decoders.
+	 * For example, with the v4l2videoNdec decoder, if the sink did not
+	 * declare videometa as supported, and if the decoder detects that
+	 * video frames have padding rows/columns (for example, a 1920x1088
+	 * frame whose last 8 rows are padding rows), then it will perform
+	 * an internal CPU-based copy that does not have these padding pixels.
+	 *
+	 * To avoid such CPU-based copies, make sure the sink declares
+	 * videometa as supported. This has the side benefit that the code
+	 * inside buffer_to_image() can also make use of the videmeta
+	 * information.
+	 */
 	static const char *pipeline =
-		"filesrc name=\"src\" ! decodebin name=\"decode\" ! video/x-raw ! appsink sync=false name=\"sink\"";
+		"filesrc name=\"src\" ! decodebin name=\"decode\" ! video/x-raw ! video_appsink name=\"sink\"";
 	dec->pipeline = gst_parse_launch(pipeline, NULL);
 
 	dec->sink = gst_bin_get_by_name(GST_BIN(dec->pipeline), "sink");
diff --git a/gst-video-appsink.c b/gst-video-appsink.c
new file mode 100644
index 0000000..2c5c15b
--- /dev/null
+++ b/gst-video-appsink.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017 Carlos Rafael Giani <dv at pseudoterminal.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <gst/gst.h>
+#include <gst/app/app.h>
+#include <gst/video/video.h>
+#include "gst-video-appsink.h"
+
+
+typedef struct _GstVideoAppsink GstVideoAppsink;
+typedef struct _GstVideoAppsinkClass GstVideoAppsinkClass;
+
+
+#define GST_TYPE_VIDEO_APPSINK             (gst_video_appsink_get_type())
+#define GST_VIDEO_APPSINK(obj)             (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_VIDEO_APPSINK,GstVideoAppsink))
+#define GST_VIDEO_APPSINK_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_VIDEO_APPSINK, GstVideoAppsinkClass))
+#define GST_IS_VIDEO_APPSINK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_VIDEO_APPSINK))
+#define GST_IS_VIDEO_APPSINK_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_VIDEO_APPSINK))
+
+
+struct _GstVideoAppsink
+{
+	GstAppSink parent;
+};
+
+
+struct _GstVideoAppsinkClass
+{
+	GstAppSinkClass parent_class;
+};
+
+
+GType gst_video_appsink_get_type(void);
+
+
+static gboolean gst_video_appsink_sink_propose_allocation (GstBaseSink *bsink, GstQuery *query);
+
+
+G_DEFINE_TYPE(GstVideoAppsink, gst_video_appsink, GST_TYPE_APP_SINK);
+
+
+static void
+gst_video_appsink_class_init(GstVideoAppsinkClass *klass)
+{
+	GstElementClass *element_class = GST_ELEMENT_CLASS(klass);
+	GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS(klass);
+
+	base_sink_class->propose_allocation =
+		GST_DEBUG_FUNCPTR(gst_video_appsink_sink_propose_allocation);
+
+	gst_element_class_set_static_metadata(
+		element_class,
+		"video appsink",
+		"Video/Sink",
+		"Appsink subclass for video streams (adds video meta)",
+		"Carlos Rafael Giani <dv at pseudoterminal.org>"
+	);
+}
+
+
+static void
+gst_video_appsink_init(GstVideoAppsink *video_appsink)
+{
+	/* QoS and max-lateness lines taken from gstvideosink.c */
+	gst_base_sink_set_max_lateness(GST_BASE_SINK(video_appsink), 20 * GST_MSECOND);
+	gst_base_sink_set_qos_enabled(GST_BASE_SINK(video_appsink), TRUE);
+}
+
+
+static gboolean
+gst_video_appsink_sink_propose_allocation (GstBaseSink *bsink, GstQuery *query)
+{
+	(void)bsink;
+
+	gst_query_add_allocation_meta(query, GST_VIDEO_META_API_TYPE, NULL);
+
+	return TRUE;
+}
+
+
+
+
+static gboolean
+init_internal_video_appsink_plugin(GstPlugin *plugin)
+{
+	gst_element_register(plugin, "video_appsink", GST_RANK_NONE, gst_video_appsink_get_type());
+	return TRUE;
+}
+
+
+void
+register_gst_video_appsink(void)
+{
+	gst_plugin_register_static(
+		GST_VERSION_MAJOR,
+		GST_VERSION_MINOR,
+		"internal video appsink plugin",
+		"internal video appsink plugin",
+		init_internal_video_appsink_plugin,
+		"1.0",
+		"BSD",
+		"kmscube",
+		"kmscube",
+		"kmscube"
+	);
+}
diff --git a/gst-video-appsink.h b/gst-video-appsink.h
new file mode 100644
index 0000000..d47484a
--- /dev/null
+++ b/gst-video-appsink.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 Carlos Rafael Giani <dv at pseudoterminal.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sub license,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _GST_VIDEO_APPSINK_H
+#define _GST_VIDEO_APPSINK_H
+
+
+void register_gst_video_appsink(void);
+
+
+#endif /* _GST_VIDEO_APPSINK_H */
diff --git a/kmscube.c b/kmscube.c
index 8e2d008..61509ef 100644
--- a/kmscube.c
+++ b/kmscube.c
@@ -33,6 +33,7 @@
 
 #ifdef HAVE_GST
 #include <gst/gst.h>
+#include "gst-video-appsink.h"
 GST_DEBUG_CATEGORY(kmscube_debug);
 #endif
 
@@ -79,6 +80,7 @@ int main(int argc, char *argv[])
 #ifdef HAVE_GST
 	gst_init(&argc, &argv);
 	GST_DEBUG_CATEGORY_INIT(kmscube_debug, "kmscube", 0, "kmscube video pipeline");
+	register_gst_video_appsink();
 #endif
 
 	while ((opt = getopt_long_only(argc, argv, shortopts, longopts, NULL)) != -1) {
-- 
2.7.4



More information about the mesa-dev mailing list