[Mesa-dev] [Mesa-dev, kmscube 08/10] gst-decoder.c: use a custom appsink subclass to make sure videometa exists
Carlos Rafael Giani
dv at pseudoterminal.org
Fri Apr 7 21:16:06 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..34e5931
--- /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)
+{
+ (void)video_appsink;
+}
+
+
+static gboolean
+gst_video_appsink_sink_propose_allocation (GstBaseSink *bsink, GstQuery *query)
+{
+ (void)bsink;
+
+ gst_query_parse_allocation(query, NULL, NULL);
+
+ 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 2d55b97..ace73e9 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