From 3438b7a88085bf37dfd25ffcae941cdf7617e9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 27 Sep 2023 17:47:25 +0200 Subject: [PATCH] kate: remove plugin Bitrotten and not really used in the wild. The actual render library (libtiger) is not just unmaintained but the upstream location has disappeared, and it's also not even packaged by e.g. debian/ubuntu. Closes #3071 Part-of: --- subprojects/gst-plugins-bad/REQUIREMENTS | 2 - .../docs/plugins/gst_plugins_cache.json | 367 ----- subprojects/gst-plugins-bad/ext/kate/README | 20 - .../gst-plugins-bad/ext/kate/gstkate.c | 75 - .../gst-plugins-bad/ext/kate/gstkatedec.c | 561 ------- .../gst-plugins-bad/ext/kate/gstkatedec.h | 90 -- .../gst-plugins-bad/ext/kate/gstkateelement.c | 72 - .../ext/kate/gstkateelements.h | 62 - .../gst-plugins-bad/ext/kate/gstkateenc.c | 1401 ----------------- .../gst-plugins-bad/ext/kate/gstkateenc.h | 129 -- .../gst-plugins-bad/ext/kate/gstkateparse.c | 634 -------- .../gst-plugins-bad/ext/kate/gstkateparse.h | 78 - .../gst-plugins-bad/ext/kate/gstkatespu.c | 916 ----------- .../gst-plugins-bad/ext/kate/gstkatespu.h | 65 - .../gst-plugins-bad/ext/kate/gstkatetag.c | 346 ---- .../gst-plugins-bad/ext/kate/gstkatetag.h | 65 - .../gst-plugins-bad/ext/kate/gstkatetiger.c | 1221 -------------- .../gst-plugins-bad/ext/kate/gstkatetiger.h | 118 -- .../gst-plugins-bad/ext/kate/gstkateutil.c | 702 --------- .../gst-plugins-bad/ext/kate/gstkateutil.h | 123 -- .../gst-plugins-bad/ext/kate/meson.build | 26 - subprojects/gst-plugins-bad/ext/meson.build | 1 - .../gst/inter/gstintersubsrc.c | 2 +- subprojects/gst-plugins-bad/meson_options.txt | 1 - .../tests/check/elements/kate.c | 881 ----------- .../gst-plugins-bad/tests/check/meson.build | 2 - 26 files changed, 1 insertion(+), 7959 deletions(-) delete mode 100644 subprojects/gst-plugins-bad/ext/kate/README delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkate.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatedec.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatedec.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateelement.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateelements.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateenc.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateenc.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateparse.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateparse.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatespu.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatespu.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatetag.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatetag.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatetiger.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkatetiger.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateutil.c delete mode 100644 subprojects/gst-plugins-bad/ext/kate/gstkateutil.h delete mode 100644 subprojects/gst-plugins-bad/ext/kate/meson.build delete mode 100644 subprojects/gst-plugins-bad/tests/check/elements/kate.c diff --git a/subprojects/gst-plugins-bad/REQUIREMENTS b/subprojects/gst-plugins-bad/REQUIREMENTS index 2a44da0a91..2bd02266fb 100644 --- a/subprojects/gst-plugins-bad/REQUIREMENTS +++ b/subprojects/gst-plugins-bad/REQUIREMENTS @@ -49,8 +49,6 @@ libamrnb (for AMR-NB support) (http://www.penguin.cz/~utx/amr) libamrwb (for AMR-WB support) (http://www.penguin.cz/~utx/amr) -libkate (for Kate support) - (http://libkate.googlecode.com/) librtmp (for RTMP support) (http://rtmpdump.mplayerhq.hu/) diff --git a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json index 15a52bec68..8da20133ec 100644 --- a/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json +++ b/subprojects/gst-plugins-bad/docs/plugins/gst_plugins_cache.json @@ -34228,373 +34228,6 @@ "tracers": {}, "url": "Unknown package origin" }, - "kate": { - "description": "Kate plugin", - "elements": { - "katedec": { - "author": "Vincent Penquerc'h ", - "description": "Decodes Kate text streams", - "hierarchy": [ - "GstKateDec", - "GstElement", - "GstObject", - "GInitiallyUnowned", - "GObject" - ], - "klass": "Codec/Decoder/Subtitle", - "long-name": "Kate stream text decoder", - "pad-templates": { - "sink": { - "caps": "subtitle/x-kate:\n", - "direction": "sink", - "presence": "always" - }, - "src": { - "caps": "text/x-raw:\n format: { pango-markup, utf8 }\nsubpicture/x-dvd:\n", - "direction": "src", - "presence": "always" - } - }, - "properties": { - "category": { - "blurb": "The category of the stream", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "NULL", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": false - }, - "language": { - "blurb": "The language of the stream", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "NULL", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": false - }, - "original-canvas-height": { - "blurb": "The canvas height this stream was authored for (0 is unspecified)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "0", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": false - }, - "original-canvas-width": { - "blurb": "The canvas width this stream was authored for", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "0", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": false - }, - "remove-markup": { - "blurb": "Remove markup from decoded text ?", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "false", - "mutable": "null", - "readable": true, - "type": "gboolean", - "writable": true - } - }, - "rank": "primary" - }, - "kateenc": { - "author": "Vincent Penquerc'h ", - "description": "Encodes Kate streams from text or subpictures", - "hierarchy": [ - "GstKateEnc", - "GstElement", - "GstObject", - "GInitiallyUnowned", - "GObject" - ], - "interfaces": [ - "GstTagSetter" - ], - "klass": "Codec/Encoder/Subtitle", - "long-name": "Kate stream encoder", - "pad-templates": { - "sink": { - "caps": "text/x-raw:\n format: { pango-markup, utf8 }\nsubpicture/x-dvd:\n", - "direction": "sink", - "presence": "always" - }, - "src": { - "caps": "subtitle/x-kate:\napplication/x-kate:\n", - "direction": "src", - "presence": "always" - } - }, - "properties": { - "category": { - "blurb": "The category of the stream", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": true - }, - "default-spu-duration": { - "blurb": "The assumed max duration (in seconds) of SPUs with no duration specified", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "1.5", - "max": "3.40282e+38", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gfloat", - "writable": true - }, - "granule-rate-denominator": { - "blurb": "The denominator of the granule rate", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "1", - "max": "2147483647", - "min": "1", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - }, - "granule-rate-numerator": { - "blurb": "The numerator of the granule rate", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "1000", - "max": "2147483647", - "min": "1", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - }, - "granule-shift": { - "blurb": "The granule shift", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "32", - "max": "64", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - }, - "keepalive-min-time": { - "blurb": "Minimum time to emit keepalive packets (0 disables keepalive packets)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "2.5", - "max": "3.40282e+38", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gfloat", - "writable": true - }, - "language": { - "blurb": "The language of the stream (e.g. \"fr\" or \"fr_FR\" for French)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": true - }, - "original-canvas-height": { - "blurb": "The height of the canvas this stream was authored for (0 is unspecified)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "0", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - }, - "original-canvas-width": { - "blurb": "The width of the canvas this stream was authored for (0 is unspecified)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "0", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - } - }, - "rank": "none" - }, - "kateparse": { - "author": "Vincent Penquerc'h ", - "description": "parse raw kate streams", - "hierarchy": [ - "GstKateParse", - "GstElement", - "GstObject", - "GInitiallyUnowned", - "GObject" - ], - "klass": "Codec/Parser/Subtitle", - "long-name": "Kate stream parser", - "pad-templates": { - "sink": { - "caps": "subtitle/x-kate:\napplication/x-kate:\n", - "direction": "sink", - "presence": "always" - }, - "src": { - "caps": "subtitle/x-kate:\napplication/x-kate:\n", - "direction": "src", - "presence": "always" - } - }, - "rank": "none" - }, - "katetag": { - "author": "Vincent Penquerc'h ", - "description": "Retags kate streams", - "hierarchy": [ - "GstKateTag", - "GstKateParse", - "GstElement", - "GstObject", - "GInitiallyUnowned", - "GObject" - ], - "interfaces": [ - "GstTagSetter" - ], - "klass": "Formatter/Metadata", - "long-name": "Kate stream tagger", - "pad-templates": { - "sink": { - "caps": "subtitle/x-kate:\napplication/x-kate:\n", - "direction": "sink", - "presence": "always" - }, - "src": { - "caps": "subtitle/x-kate:\napplication/x-kate:\n", - "direction": "src", - "presence": "always" - } - }, - "properties": { - "category": { - "blurb": "Set the category of the stream", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": true - }, - "language": { - "blurb": "Set the language of the stream", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "", - "mutable": "null", - "readable": true, - "type": "gchararray", - "writable": true - }, - "original-canvas-height": { - "blurb": "Set the height of the canvas this stream was authored for (0 is unspecified)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "-1", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - }, - "original-canvas-width": { - "blurb": "Set the width of the canvas this stream was authored for (0 is unspecified)", - "conditionally-available": false, - "construct": false, - "construct-only": false, - "controllable": false, - "default": "-1", - "max": "2147483647", - "min": "0", - "mutable": "null", - "readable": true, - "type": "gint", - "writable": true - } - }, - "rank": "none" - } - }, - "filename": "gstkate", - "license": "LGPL", - "other-types": {}, - "package": "GStreamer Bad Plug-ins", - "source": "gst-plugins-bad", - "tracers": {}, - "url": "Unknown package origin" - }, "kms": { "description": "Video sink using the Linux kernel mode setting API", "elements": { diff --git a/subprojects/gst-plugins-bad/ext/kate/README b/subprojects/gst-plugins-bad/ext/kate/README deleted file mode 100644 index 498a79e209..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/README +++ /dev/null @@ -1,20 +0,0 @@ -Kate is a free codec for text based data, which can also carry images. -It is typically used to create overlays on a video. - -libkate, a codec for Kate streams, is required to build this plugin: -http://libkate.googlecode.com/ - -libtiger, a rendering library for Kate streams, is optional: -http://libtiger.googlecode.com/ - -The Kate plugin contains various elements to manipulate Kate streams: - - - katedec: decodes Kate streams to text and SPU images - - kateenc: encodes Kate streams from text and SPU images - - kateparse: parses Kate streams - - katetag: allows changing metadata in Kate streams - - tiger: decodes and renders Kate streams using libtiger (needs libtiger) - -More information about Kate can be found at: -http://wiki.xiph.org/index.php/OggKate - diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkate.c b/subprojects/gst-plugins-bad/ext/kate/gstkate.c deleted file mode 100644 index 356e06519d..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkate.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstkateelements.h" - - -static gboolean -plugin_init (GstPlugin * plugin) -{ - gboolean ret = FALSE; - - ret |= GST_ELEMENT_REGISTER (katedec, plugin); - ret |= GST_ELEMENT_REGISTER (kateenc, plugin); - ret |= GST_ELEMENT_REGISTER (kateparse, plugin); - ret |= GST_ELEMENT_REGISTER (katetag, plugin); -#ifdef HAVE_TIGER - ret |= GST_ELEMENT_REGISTER (tiger, plugin); -#endif - - return ret; -} - -/* this is the structure that gstreamer looks for to register plugins - */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - kate, - "Kate plugin", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatedec.c b/subprojects/gst-plugins-bad/ext/kate/gstkatedec.c deleted file mode 100644 index aabb4e541a..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatedec.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008, 2009 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-katedec - * @title: katedec - * @see_also: oggdemux - * - * This element decodes Kate streams. - * - * [Kate](http://libkate.googlecode.com/) is a free codec - * for text based data, such as subtitles. Any number of kate streams can be - * embedded in an Ogg stream. - * - * libkate (see above url) is needed to build this plugin. - * - * ## Example pipeline - * - * This explicitly decodes a Kate stream: - * |[ - * gst-launch-1.0 filesrc location=test.ogg ! oggdemux ! katedec ! fakesink silent=TRUE - * ]| - * - * This will automatically detect and use any Kate streams multiplexed - * in an Ogg stream: - * |[ - * gst-launch-1.0 playbin uri=file:///tmp/test.ogg - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include - -#include "gstkateelements.h" -#include "gstkatespu.h" -#include "gstkatedec.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_katedec_debug); -#define GST_CAT_DEFAULT gst_katedec_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_REMOVE_MARKUP = DECODER_BASE_ARG_COUNT -}; - -/* We don't accept application/x-kate here on purpose for now, since we're - * only really interested in subtitle-like things for playback purposes, not - * cracktastic complex overlays or presentation images etc. - those should be - * fed into a tiger overlay plugin directly */ -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("subtitle/x-kate") - ); - -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("text/x-raw, format = { pango-markup, utf8 }; " - GST_KATE_SPU_MIME_TYPE) - ); - -GST_DEBUG_CATEGORY (gst_katedec_debug); - -#define gst_kate_dec_parent_class parent_class -G_DEFINE_TYPE (GstKateDec, gst_kate_dec, GST_TYPE_ELEMENT); -#define _do_init \ - kate_element_init (plugin); \ - GST_DEBUG_CATEGORY_INIT (gst_katedec_debug, "katedec", 0, "Kate decoder"); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (katedec, "katedec", GST_RANK_PRIMARY, - GST_TYPE_KATE_DEC, _do_init); - -static void gst_kate_dec_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_kate_dec_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_kate_dec_chain (GstPad * pad, GstObject * parent, - GstBuffer * buf); -static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element, - GstStateChange transition); -static gboolean gst_kate_dec_sink_query (GstPad * pad, GstObject * parent, - GstQuery * query); -static gboolean gst_kate_dec_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean gst_kate_dec_sink_handle_event (GstPad * pad, - GstObject * parent, GstEvent * event); -static gboolean gst_kate_dec_src_query (GstPad * pad, GstObject * parent, - GstQuery * query); - -/* initialize the plugin's class */ -static void -gst_kate_dec_class_init (GstKateDecClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->set_property = gst_kate_dec_set_property; - gobject_class->get_property = gst_kate_dec_get_property; - - gst_kate_util_install_decoder_base_properties (gobject_class); - - g_object_class_install_property (gobject_class, ARG_REMOVE_MARKUP, - g_param_spec_boolean ("remove-markup", "Remove markup", - "Remove markup from decoded text ?", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_kate_dec_change_state); - - gst_element_class_add_static_pad_template (gstelement_class, &src_factory); - gst_element_class_add_static_pad_template (gstelement_class, &sink_factory); - - gst_element_class_set_static_metadata (gstelement_class, - "Kate stream text decoder", "Codec/Decoder/Subtitle", - "Decodes Kate text streams", - "Vincent Penquerc'h "); -} - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_kate_dec_init (GstKateDec * dec) -{ - GST_DEBUG_OBJECT (dec, "gst_kate_dec_init"); - - dec->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); - gst_pad_set_chain_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_dec_chain)); - gst_pad_set_query_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_dec_sink_query)); - gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_dec_sink_event)); - gst_pad_use_fixed_caps (dec->sinkpad); - gst_pad_set_caps (dec->sinkpad, - gst_static_pad_template_get_caps (&sink_factory)); - gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - - dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); - gst_pad_set_query_function (dec->srcpad, - GST_DEBUG_FUNCPTR (gst_kate_dec_src_query)); - gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); - - gst_kate_util_decode_base_init (&dec->decoder, TRUE); - - dec->src_caps = NULL; - dec->output_format = GST_KATE_FORMAT_UNDEFINED; - dec->remove_markup = FALSE; -} - -static void -gst_kate_dec_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_kate_dec_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstKateDec *kd = GST_KATE_DEC (object); - - switch (prop_id) { - case ARG_REMOVE_MARKUP: - g_value_set_boolean (value, kd->remove_markup); - break; - default: - if (!gst_kate_util_decoder_base_get_property (&kd->decoder, object, - prop_id, value, pspec)) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } - break; - } -} - -static GstFlowReturn -gst_kate_dec_handle_kate_event (GstKateDec * kd, const kate_event * ev) -{ - GstFlowReturn rflow = GST_FLOW_OK; - GstKateFormat format = GST_KATE_FORMAT_UNDEFINED; - gchar *escaped; - GstBuffer *buffer; - size_t len; - gboolean plain = TRUE; - - if (kd->remove_markup && ev->text_markup_type != kate_markup_none) { - size_t len0 = ev->len + 1; - escaped = g_strdup (ev->text); - if (escaped) { - kate_text_remove_markup (ev->text_encoding, escaped, &len0); - } - plain = TRUE; - } else if (ev->text_markup_type == kate_markup_none) { - /* no pango markup yet, escape text */ - /* TODO: actually do the pango thing */ - escaped = g_strdup (ev->text); - plain = TRUE; - } else { - escaped = g_strdup (ev->text); - plain = FALSE; - } - - if (G_LIKELY (escaped)) { - len = strlen (escaped); - if (len > 0) { - GST_DEBUG_OBJECT (kd, "kate event: %s, escaped %s", ev->text, escaped); - buffer = gst_buffer_new_and_alloc (len + 1); - if (G_LIKELY (buffer)) { - GstCaps *caps; - if (plain) - format = GST_KATE_FORMAT_TEXT_UTF8; - else - format = GST_KATE_FORMAT_TEXT_PANGO_MARKUP; - if (format != kd->output_format) { - caps = gst_caps_new_simple ("text/x-raw", "format", G_TYPE_STRING, - (format == GST_KATE_FORMAT_TEXT_UTF8) ? "utf8" : "pango-markup", - NULL); - gst_pad_push_event (kd->srcpad, gst_event_new_caps (caps)); - gst_caps_unref (caps); - kd->output_format = format; - } - /* allocate and copy the NULs, but don't include them in passed size */ - gst_buffer_fill (buffer, 0, escaped, len + 1); - gst_buffer_resize (buffer, 0, len); - GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND; - GST_BUFFER_DURATION (buffer) = - (ev->end_time - ev->start_time) * GST_SECOND; - rflow = gst_pad_push (kd->srcpad, buffer); - if (rflow == GST_FLOW_NOT_LINKED) { - GST_DEBUG_OBJECT (kd, "source pad not linked, ignored"); - } else if (rflow != GST_FLOW_OK) { - GST_WARNING_OBJECT (kd, "failed to push buffer: %s", - gst_flow_get_name (rflow)); - } - } else { - GST_ELEMENT_ERROR (kd, STREAM, DECODE, (NULL), - ("Failed to create buffer")); - rflow = GST_FLOW_ERROR; - } - } else { - GST_WARNING_OBJECT (kd, "Empty string, nothing to do"); - rflow = GST_FLOW_OK; - } - g_free (escaped); - } else { - GST_ELEMENT_ERROR (kd, STREAM, DECODE, (NULL), - ("Failed to allocate string")); - rflow = GST_FLOW_ERROR; - } - - /* if there's a background paletted bitmap, construct a DVD SPU for it */ - if (ev->bitmap && ev->palette) { - GstBuffer *buffer = gst_kate_spu_encode_spu (kd, ev); - if (buffer) { - GstCaps *caps; - - GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND; - GST_BUFFER_DURATION (buffer) = - (ev->end_time - ev->start_time) * GST_SECOND; - - if (kd->output_format != GST_KATE_FORMAT_SPU) { - caps = gst_caps_new_empty_simple (GST_KATE_SPU_MIME_TYPE); - gst_pad_push_event (kd->srcpad, gst_event_new_caps (caps)); - gst_caps_unref (caps); - kd->output_format = GST_KATE_FORMAT_SPU; - } - - rflow = gst_pad_push (kd->srcpad, buffer); - if (rflow == GST_FLOW_NOT_LINKED) { - GST_DEBUG_OBJECT (kd, "source pad not linked, ignored"); - } else if (rflow != GST_FLOW_OK) { - GST_WARNING_OBJECT (kd, "failed to push buffer: %s", - gst_flow_get_name (rflow)); - } - } else { - GST_ELEMENT_ERROR (kd, STREAM, DECODE, (NULL), - ("failed to create SPU from paletted bitmap")); - rflow = GST_FLOW_ERROR; - } - } - return rflow; -} - -/* GstElement vmethod implementations */ - -/* chain function - * this function does the actual processing - */ - -static GstFlowReturn -gst_kate_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) -{ - GstKateDec *kd = GST_KATE_DEC (parent); - const kate_event *ev = NULL; - GstFlowReturn rflow = GST_FLOW_OK; - - if (!gst_kate_util_decoder_base_update_segment (&kd->decoder, - GST_ELEMENT_CAST (kd), buf)) { - GST_WARNING_OBJECT (kd, "Out of segment!"); - goto not_in_seg; - } - - rflow = - gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder, - GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps, - &ev); - if (G_UNLIKELY (rflow != GST_FLOW_OK)) { - gst_buffer_unref (buf); - return rflow; - } - - if (ev) { - rflow = gst_kate_dec_handle_kate_event (kd, ev); - } - -not_in_seg: - gst_buffer_unref (buf); - return rflow; -} - -static GstStateChangeReturn -gst_kate_dec_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret; - GstKateDec *kd = GST_KATE_DEC (element); - - ret = gst_kate_decoder_base_change_state (&kd->decoder, element, - parent_class, transition); - - if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) { - gst_caps_replace (&kd->src_caps, NULL); - } - - return ret; -} - -gboolean -gst_kate_dec_sink_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstKateDec *kd = GST_KATE_DEC (parent); - gboolean res = - gst_kate_decoder_base_sink_query (&kd->decoder, GST_ELEMENT_CAST (kd), - pad, parent, query); - return res; -} - -static gboolean -gst_kate_dec_set_caps (GstKateDec * kd, GstCaps * caps) -{ - GstStructure *structure = gst_caps_get_structure (caps, 0); - GstFlowReturn rflow = GST_FLOW_OK; - - if (gst_structure_has_field (structure, "streamheader")) { - const GValue *value; - GstBuffer *buf; - const kate_event *ev; - - value = gst_structure_get_value (structure, "streamheader"); - - if (GST_VALUE_HOLDS_BUFFER (value)) { - buf = gst_value_get_buffer (value); - - gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder, - GST_ELEMENT_CAST (kd), kd->sinkpad, buf, kd->srcpad, kd->srcpad, - &kd->src_caps, &ev); - - if (ev) { - rflow = gst_kate_dec_handle_kate_event (kd, ev); - } - } else if (GST_VALUE_HOLDS_ARRAY (value)) { - gint i, size = gst_value_array_get_size (value); - - for (i = 0; i < size; i++) { - const GValue *v = gst_value_array_get_value (value, i); - - buf = gst_value_get_buffer (v); - gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder, - GST_ELEMENT_CAST (kd), kd->sinkpad, buf, kd->srcpad, kd->srcpad, - &kd->src_caps, &ev); - - if (ev) { - rflow = gst_kate_dec_handle_kate_event (kd, ev); - if (rflow != GST_FLOW_OK && rflow != GST_FLOW_NOT_LINKED) - break; - } - } - } else { - GST_WARNING_OBJECT (kd, "Unhandled streamheader type: %s", - G_VALUE_TYPE_NAME (value)); - } - } - - return rflow == GST_FLOW_OK || rflow == GST_FLOW_NOT_LINKED; -} - -static gboolean -gst_kate_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstKateDec *kd = GST_KATE_DEC (parent); - gboolean res = TRUE; - - GST_LOG_OBJECT (pad, "Event on sink pad: %" GST_PTR_FORMAT, event); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS:{ - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - gst_kate_dec_set_caps (kd, caps); - break; - } - default: - break; - } - - /* Delay events till we've set caps */ - if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event, - &gst_kate_dec_sink_handle_event, parent, pad)) { - return TRUE; - } - - res = gst_kate_dec_sink_handle_event (pad, parent, event); - - return res; -} - -static gboolean -gst_kate_dec_sink_handle_event (GstPad * pad, GstObject * parent, - GstEvent * event) -{ - GstKateDec *kd = GST_KATE_DEC (parent); - - GST_LOG_OBJECT (pad, "Handling event on sink pad: %s", - GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEGMENT: - break; - - case GST_EVENT_FLUSH_START: - gst_kate_util_decoder_base_set_flushing (&kd->decoder, TRUE); - break; - - case GST_EVENT_FLUSH_STOP: - gst_kate_util_decoder_base_set_flushing (&kd->decoder, FALSE); - break; - - case GST_EVENT_TAG:{ - GstTagList *tags; - gst_event_parse_tag (event, &tags); - gst_kate_util_decoder_base_add_tags (&kd->decoder, tags, FALSE); - gst_event_unref (event); - event = gst_kate_util_decoder_base_get_tag_event (&kd->decoder); - break; - } - default: - break; - } - - return gst_pad_event_default (pad, parent, event); -} - -static gboolean -gst_kate_dec_src_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstKateDec *kd = GST_KATE_DEC (parent); - gboolean res = TRUE; - - GST_LOG_OBJECT (pad, "Handling query on src pad: %s", - GST_QUERY_TYPE_NAME (query)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CAPS:{ - GstCaps *caps; - - if (kd->src_caps) { - GST_DEBUG_OBJECT (kd, "We have src caps %" GST_PTR_FORMAT, - kd->src_caps); - caps = gst_caps_copy (kd->src_caps); - } else { - GST_DEBUG_OBJECT (kd, "We have no src caps, using template caps"); - caps = gst_static_pad_template_get_caps (&src_factory); - } - - gst_query_set_caps_result (query, caps); - gst_caps_unref (caps); - break; - } - default: - res = gst_pad_query_default (pad, parent, query); - break; - } - - return res; -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatedec.h b/subprojects/gst-plugins-bad/ext/kate/gstkatedec.h deleted file mode 100644 index 2222811f13..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatedec.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_KATE_DEC_H__ -#define __GST_KATE_DEC_H__ - -#include -#include -#include "gstkateutil.h" - -G_BEGIN_DECLS -/* #defines don't like whitespacey bits */ -#define GST_TYPE_KATE_DEC \ - (gst_kate_dec_get_type()) -#define GST_KATE_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KATE_DEC,GstKateDec)) -#define GST_KATE_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE,GstKateDecClass)) -#define GST_IS_KATE_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_DEC)) -#define GST_IS_KATE_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_DEC)) -typedef struct _GstKateDec GstKateDec; -typedef struct _GstKateDecClass GstKateDecClass; - -struct _GstKateDec -{ - GstKateDecoderBase decoder; - - GstPad *sinkpad; - GstPad *srcpad; - - GstCaps *src_caps; - - GstKateFormat output_format; - - gboolean remove_markup; -}; - -struct _GstKateDecClass -{ - GstElementClass parent_class; -}; - -GType gst_kate_dec_get_type (void); - -G_END_DECLS -#endif /* __GST_KATE_DEC_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateelement.c b/subprojects/gst-plugins-bad/ext/kate/gstkateelement.c deleted file mode 100644 index b66719a9a9..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateelement.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include - -#include "gstkateelements.h" - -#undef HAVE_TIGER -#ifdef HAVE_TIGER -#include "gstkatetiger.h" -#endif - -GST_DEBUG_CATEGORY (gst_kateutil_debug); - -void -kate_element_init (GstPlugin * plugin) -{ - static gsize res = FALSE; - if (g_once_init_enter (&res)) { - GST_DEBUG_CATEGORY_INIT (gst_kateutil_debug, "kateutil", 0, - "Kate utility functions"); - g_once_init_leave (&res, TRUE); - } -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateelements.h b/subprojects/gst-plugins-bad/ext/kate/gstkateelements.h deleted file mode 100644 index 589b1520b7..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateelements.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_KATE_ELEMENT_H__ -#define __GST_KATE_ELEMENT_H__ - -#include - -G_BEGIN_DECLS - -void kate_element_init (GstPlugin * plugin); - -GST_ELEMENT_REGISTER_DECLARE (katedec); -GST_ELEMENT_REGISTER_DECLARE (kateenc); -GST_ELEMENT_REGISTER_DECLARE (kateparse); -GST_ELEMENT_REGISTER_DECLARE (tiger); -GST_ELEMENT_REGISTER_DECLARE (katetag); - - -G_END_DECLS - -#endif /* __GST_KATE_ELEMENT_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateenc.c b/subprojects/gst-plugins-bad/ext/kate/gstkateenc.c deleted file mode 100644 index 73ac49c893..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateenc.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright (C) 2007 Fluendo S.A. - * Copyright 2008, 2009 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-kateenc - * @title: kateenc - * @see_also: oggmux - * - * This element encodes Kate streams. - * - * [Kate](http://libkate.googlecode.com/) is a free codec for text based data, - * such as subtitles. Any number of kate streams can be embedded in an Ogg - * stream. - * - * libkate (see above url) is needed to build this plugin. - * - * ## Example pipeline - * - * This encodes a DVD SPU track to a Kate stream: - * |[ - * gst-launch-1.0 dvdreadsrc ! dvddemux ! dvdsubparse ! kateenc category=spu-subtitles ! oggmux ! filesink location=test.ogg - * ]| - * - */ - -/* FIXME: - * - should we automatically pick up the language code from the - * upstream event tags if none was set via the property? - * - turn category property into an enum (freestyle text property in - * combination with supposedly strictly defined known values that - * aren't even particularly human-readable is just not very nice)? */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include -#include - -#include "gstkateelements.h" -#include "gstkateutil.h" -#include "gstkatespu.h" -#include "gstkateenc.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_kateenc_debug); -#define GST_CAT_DEFAULT gst_kateenc_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_LANGUAGE, - ARG_CATEGORY, - ARG_GRANULE_RATE_NUM, - ARG_GRANULE_RATE_DEN, - ARG_GRANULE_SHIFT, - ARG_KEEPALIVE_MIN_TIME, - ARG_ORIGINAL_CANVAS_WIDTH, - ARG_ORIGINAL_CANVAS_HEIGHT, - ARG_DEFAULT_SPU_DURATION, -}; - -#define DEFAULT_KEEPALIVE_MIN_TIME 2.5f -#define DEFAULT_DEFAULT_SPU_DURATION 1.5f - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("text/x-raw, format={ pango-markup, utf8 }; " - GST_KATE_SPU_MIME_TYPE) - ); - -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") - ); - -static void gst_kate_enc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_kate_enc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_kate_enc_dispose (GObject * object); - -static gboolean gst_kate_enc_setcaps (GstKateEnc * ke, GstCaps * caps); -static GstFlowReturn gst_kate_enc_chain (GstPad * pad, GstObject * parent, - GstBuffer * buf); -static GstStateChangeReturn gst_kate_enc_change_state (GstElement * element, - GstStateChange transition); -static gboolean gst_kate_enc_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean gst_kate_enc_source_query (GstPad * pad, GstObject * parent, - GstQuery * query); - -GST_DEBUG_CATEGORY (gst_kateenc_debug); - -#define gst_kate_enc_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstKateEnc, gst_kate_enc, GST_TYPE_ELEMENT, - G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL)); -#define _do_init \ - kate_element_init (plugin); \ - GST_DEBUG_CATEGORY_INIT (gst_kateenc_debug, "kateenc", 0, "Kate encoder"); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (kateenc, "kateenc", GST_RANK_NONE, - GST_TYPE_KATE_ENC, _do_init); - -/* initialize the plugin's class */ -static void -gst_kate_enc_class_init (GstKateEncClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_enc_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_enc_get_property); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_enc_dispose); - - g_object_class_install_property (gobject_class, ARG_LANGUAGE, - g_param_spec_string ("language", "Language", - "The language of the stream (e.g. \"fr\" or \"fr_FR\" for French)", - "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_CATEGORY, - g_param_spec_string ("category", "Category", - "The category of the stream", "", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_GRANULE_RATE_NUM, - g_param_spec_int ("granule-rate-numerator", "Granule rate numerator", - "The numerator of the granule rate", - 1, G_MAXINT, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_GRANULE_RATE_DEN, - g_param_spec_int ("granule-rate-denominator", "Granule rate denominator", - "The denominator of the granule rate", - 1, G_MAXINT, 1000, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_GRANULE_SHIFT, - g_param_spec_int ("granule-shift", "Granule shift", - "The granule shift", 0, 64, 32, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_WIDTH, - g_param_spec_int ("original-canvas-width", "Original canvas width", - "The width of the canvas this stream was authored for (0 is unspecified)", - 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_HEIGHT, - g_param_spec_int ("original-canvas-height", "Original canvas height", - "The height of the canvas this stream was authored for (0 is unspecified)", - 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_KEEPALIVE_MIN_TIME, - g_param_spec_float ("keepalive-min-time", "Keepalive minimum time", - "Minimum time to emit keepalive packets (0 disables keepalive packets)", - 0.0f, FLT_MAX, DEFAULT_KEEPALIVE_MIN_TIME, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_SPU_DURATION, - g_param_spec_float ("default-spu-duration", "Default SPU duration", - "The assumed max duration (in seconds) of SPUs with no duration specified", - 0.0f, FLT_MAX, DEFAULT_DEFAULT_SPU_DURATION, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_kate_enc_change_state); - - gst_element_class_add_static_pad_template (gstelement_class, &src_factory); - gst_element_class_add_static_pad_template (gstelement_class, &sink_factory); - - gst_element_class_set_static_metadata (gstelement_class, - "Kate stream encoder", "Codec/Encoder/Subtitle", - "Encodes Kate streams from text or subpictures", - "Vincent Penquerc'h "); -} - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_kate_enc_init (GstKateEnc * ke) -{ - GST_DEBUG_OBJECT (ke, "gst_kate_enc_init"); - - ke->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink"); - gst_pad_set_chain_function (ke->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_enc_chain)); - gst_pad_set_event_function (ke->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_enc_sink_event)); - gst_element_add_pad (GST_ELEMENT (ke), ke->sinkpad); - - ke->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); - gst_pad_set_query_function (ke->srcpad, - GST_DEBUG_FUNCPTR (gst_kate_enc_source_query)); - gst_element_add_pad (GST_ELEMENT (ke), ke->srcpad); - - ke->initialized = FALSE; - ke->headers_sent = FALSE; - ke->last_timestamp = 0; - ke->latest_end_time = 0; - ke->language = NULL; - ke->category = NULL; - ke->format = GST_KATE_FORMAT_UNDEFINED; - ke->granule_rate_numerator = 1000; - ke->granule_rate_denominator = 1; - ke->granule_shift = 32; - ke->original_canvas_width = 0; - ke->original_canvas_height = 0; - ke->keepalive_min_time = DEFAULT_KEEPALIVE_MIN_TIME; - ke->default_spu_duration = DEFAULT_DEFAULT_SPU_DURATION; - memcpy (ke->spu_clut, gst_kate_spu_default_clut, - sizeof (gst_kate_spu_default_clut)); - ke->delayed_spu = FALSE; - ke->delayed_bitmap = NULL; - ke->delayed_palette = NULL; - ke->delayed_region = NULL; -} - -static void -gst_kate_enc_dispose (GObject * object) -{ - GstKateEnc *ke = GST_KATE_ENC (object); - - GST_LOG_OBJECT (ke, "disposing"); - - if (ke->language) { - g_free (ke->language); - ke->language = NULL; - } - if (ke->category) { - g_free (ke->category); - ke->category = NULL; - } - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); -} - -static void -gst_kate_enc_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstKateEnc *ke = GST_KATE_ENC (object); - const char *str; - - switch (prop_id) { - case ARG_LANGUAGE: - if (ke->language) { - g_free (ke->language); - ke->language = NULL; - } - str = g_value_get_string (value); - if (str) - ke->language = g_strdup (str); - break; - case ARG_CATEGORY: - if (ke->category) { - g_free (ke->category); - ke->category = NULL; - } - str = g_value_get_string (value); - if (str) - ke->category = g_strdup (str); - break; - case ARG_GRANULE_RATE_NUM: - ke->granule_rate_numerator = g_value_get_int (value); - break; - case ARG_GRANULE_RATE_DEN: - ke->granule_rate_denominator = g_value_get_int (value); - break; - case ARG_GRANULE_SHIFT: - ke->granule_rate_denominator = g_value_get_int (value); - break; - case ARG_KEEPALIVE_MIN_TIME: - ke->keepalive_min_time = g_value_get_float (value); - break; - case ARG_ORIGINAL_CANVAS_WIDTH: - ke->original_canvas_width = g_value_get_int (value); - break; - case ARG_ORIGINAL_CANVAS_HEIGHT: - ke->original_canvas_height = g_value_get_int (value); - break; - case ARG_DEFAULT_SPU_DURATION: - ke->default_spu_duration = g_value_get_float (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_kate_enc_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstKateEnc *ke = GST_KATE_ENC (object); - - switch (prop_id) { - case ARG_LANGUAGE: - g_value_set_string (value, ke->language ? ke->language : ""); - break; - case ARG_CATEGORY: - g_value_set_string (value, ke->category ? ke->category : ""); - break; - case ARG_GRANULE_RATE_NUM: - g_value_set_int (value, ke->granule_rate_numerator); - break; - case ARG_GRANULE_RATE_DEN: - g_value_set_int (value, ke->granule_rate_denominator); - break; - case ARG_GRANULE_SHIFT: - g_value_set_int (value, ke->granule_shift); - break; - case ARG_KEEPALIVE_MIN_TIME: - g_value_set_float (value, ke->keepalive_min_time); - break; - case ARG_ORIGINAL_CANVAS_WIDTH: - g_value_set_int (value, ke->original_canvas_width); - break; - case ARG_ORIGINAL_CANVAS_HEIGHT: - g_value_set_int (value, ke->original_canvas_height); - break; - case ARG_DEFAULT_SPU_DURATION: - g_value_set_float (value, ke->default_spu_duration); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* GstElement vmethod implementations */ - -static GstBuffer * -gst_kate_enc_create_buffer (GstKateEnc * ke, kate_packet * kp, - kate_int64_t granpos, GstClockTime timestamp, GstClockTime duration, - gboolean header) -{ - GstBuffer *buffer; - - g_return_val_if_fail (kp != NULL, NULL); - g_return_val_if_fail (kp->data != NULL, NULL); - - buffer = gst_buffer_new_allocate (NULL, kp->nbytes, NULL); - if (G_UNLIKELY (!buffer)) { - GST_WARNING_OBJECT (ke, "Failed to allocate buffer for %u bytes", - (guint) kp->nbytes); - return NULL; - } - - gst_buffer_fill (buffer, 0, kp->data, kp->nbytes); - - /* same system as other Ogg codecs, as per ext/ogg/README: - OFFSET_END is the granulepos - OFFSET is its time representation - */ - GST_BUFFER_OFFSET_END (buffer) = granpos; - GST_BUFFER_OFFSET (buffer) = timestamp; - GST_BUFFER_TIMESTAMP (buffer) = timestamp; - GST_BUFFER_DURATION (buffer) = duration; - - return buffer; -} - -static GstFlowReturn -gst_kate_enc_push_buffer (GstKateEnc * ke, GstBuffer * buffer) -{ - GstFlowReturn flow; - - ke->last_timestamp = GST_BUFFER_TIMESTAMP (buffer); - if (GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) > - ke->latest_end_time) { - ke->latest_end_time = - GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); - } - - flow = gst_pad_push (ke->srcpad, buffer); - if (G_UNLIKELY (flow != GST_FLOW_OK)) { - GST_WARNING_OBJECT (ke->srcpad, "push flow: %s", gst_flow_get_name (flow)); - } - - return flow; -} - -static GstFlowReturn -gst_kate_enc_push_and_free_kate_packet (GstKateEnc * ke, kate_packet * kp, - kate_int64_t granpos, GstClockTime timestamp, GstClockTime duration, - gboolean header) -{ - GstBuffer *buffer; - - GST_LOG_OBJECT (ke, "Creating buffer, %u bytes", (guint) kp->nbytes); - buffer = - gst_kate_enc_create_buffer (ke, kp, granpos, timestamp, duration, header); - if (G_UNLIKELY (!buffer)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to create buffer, %u bytes", (guint) kp->nbytes)); - kate_packet_clear (kp); - return GST_FLOW_ERROR; - } - - kate_packet_clear (kp); - - return gst_kate_enc_push_buffer (ke, buffer); -} - -static void -gst_kate_enc_metadata_set1 (const GstTagList * list, const gchar * tag, - gpointer kateenc) -{ - GstKateEnc *ke = GST_KATE_ENC (kateenc); - GList *vc_list, *l; - - vc_list = gst_tag_to_vorbis_comments (list, tag); - - for (l = vc_list; l != NULL; l = l->next) { - const gchar *vc_string = (const gchar *) l->data; - gchar *key = NULL, *val = NULL; - - GST_LOG_OBJECT (ke, "Kate comment: %s", vc_string); - if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) { - kate_comment_add_tag (&ke->kc, key, val); - g_free (key); - g_free (val); - } - } - - g_list_foreach (vc_list, (GFunc) g_free, NULL); - g_list_free (vc_list); -} - -static void -gst_kate_enc_set_metadata (GstKateEnc * ke) -{ - GstTagList *merged_tags; - const GstTagList *user_tags; - - user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (ke)); - - GST_DEBUG_OBJECT (ke, "upstream tags = %" GST_PTR_FORMAT, ke->tags); - GST_DEBUG_OBJECT (ke, "user-set tags = %" GST_PTR_FORMAT, user_tags); - - /* gst_tag_list_merge() will handle NULL for either or both lists fine */ - merged_tags = gst_tag_list_merge (user_tags, ke->tags, - gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke))); - - if (merged_tags) { - GST_DEBUG_OBJECT (ke, "merged tags = %" GST_PTR_FORMAT, merged_tags); - gst_tag_list_foreach (merged_tags, gst_kate_enc_metadata_set1, ke); - gst_tag_list_unref (merged_tags); - } -} - -static gboolean -gst_kate_enc_setcaps (GstKateEnc * ke, GstCaps * caps) -{ - GST_LOG_OBJECT (ke, "input caps: %" GST_PTR_FORMAT, caps); - - /* One day we could try to automatically set the category based on the - * input format, assuming that the input is subtitles. Currently that - * doesn't work yet though, because we send the header packets already from - * the sink event handler when receiving the newsegment event, so before - * the first buffer (might be tricky to change too, given that there could - * be no data at the beginning for a long time). So for now we just try to - * make sure people didn't set the category to something obviously wrong. */ - if (ke->category != NULL) { - GstStructure *s = gst_caps_get_structure (caps, 0); - - if (gst_structure_has_name (s, "text/x-raw")) { - const gchar *format; - - format = gst_structure_get_string (s, "format"); - if (strcmp (format, "utf8") == 0) { - ke->format = GST_KATE_FORMAT_TEXT_UTF8; - } else if (strcmp (format, "pango-markup") == 0) { - ke->format = GST_KATE_FORMAT_TEXT_PANGO_MARKUP; - } - - if (strcmp (ke->category, "K-SPU") == 0 || - strcmp (ke->category, "spu-subtitles") == 0) { - GST_ELEMENT_WARNING (ke, LIBRARY, SETTINGS, (NULL), - ("Category set to '%s', but input is text-based.", ke->category)); - } - } else if (gst_structure_has_name (s, "subpicture/x-dvd")) { - ke->format = GST_KATE_FORMAT_SPU; - if (strcmp (ke->category, "SUB") == 0 || - strcmp (ke->category, "subtitles") == 0) { - GST_ELEMENT_WARNING (ke, LIBRARY, SETTINGS, (NULL), - ("Category set to '%s', but input is subpictures.", ke->category)); - } - } else { - GST_ERROR_OBJECT (ke, "unexpected input caps %" GST_PTR_FORMAT, caps); - return FALSE; - } - } - - return TRUE; -} - -static gboolean -gst_kate_enc_is_simple_subtitle_category (GstKateEnc * ke, const char *category) -{ - static const char *const simple[] = { - "subtitles", - "SUB", - "spu-subtitles", - "K-SPU", - }; - int n; - - if (!category) - return FALSE; - for (n = 0; n < G_N_ELEMENTS (simple); ++n) { - if (!strcmp (category, simple[n])) - return TRUE; - } - return FALSE; -} - -static GstFlowReturn -gst_kate_enc_send_headers (GstKateEnc * ke) -{ - GstFlowReturn rflow = GST_FLOW_OK; - GstCaps *caps; - GList *headers = NULL, *item; - - if (G_UNLIKELY (ke->category == NULL || *ke->category == '\0')) { - /* The error code is a bit of a lie, but seems most appropriate. */ - GST_ELEMENT_ERROR (ke, LIBRARY, SETTINGS, (NULL), - ("The 'category' property must be set. For subtitles, set it to " - "either 'SUB' (text subtitles) or 'K-SPU' (dvd-style subtitles)")); - return GST_FLOW_ERROR; - } - - gst_kate_enc_set_metadata (ke); - - /* encode headers and store them in a list */ - while (1) { - kate_packet kp; - int ret = kate_encode_headers (&ke->k, &ke->kc, &kp); - if (ret == 0) { - GstBuffer *buffer; - - buffer = gst_kate_enc_create_buffer (ke, &kp, 0, 0, 0, TRUE); - if (!buffer) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to create buffer, %u bytes", (guint) kp.nbytes)); - rflow = GST_FLOW_ERROR; - break; - } - kate_packet_clear (&kp); - - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER); - headers = g_list_append (headers, buffer); - } else if (ret > 0) { - GST_LOG_OBJECT (ke, "Last header encoded"); - break; - } else { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed encoding headers: %s", - gst_kate_util_get_error_message (ret))); - rflow = GST_FLOW_ERROR; - break; - } - } - - if (rflow == GST_FLOW_OK) { - if (gst_kate_enc_is_simple_subtitle_category (ke, ke->category)) { - caps = gst_kate_util_set_header_on_caps (&ke->element, - gst_caps_from_string ("subtitle/x-kate"), headers); - } else { - caps = gst_kate_util_set_header_on_caps (&ke->element, - gst_caps_from_string ("application/x-kate"), headers); - } - if (caps) { - GST_DEBUG_OBJECT (ke, "here are the caps: %" GST_PTR_FORMAT, caps); - gst_pad_set_caps (ke->srcpad, caps); - gst_caps_unref (caps); - - if (ke->pending_segment) - gst_pad_push_event (ke->srcpad, ke->pending_segment); - ke->pending_segment = NULL; - - GST_LOG_OBJECT (ke, "pushing headers"); - item = headers; - while (item) { - GstBuffer *buffer = item->data; - GST_LOG_OBJECT (ke, "pushing header %p", buffer); - gst_kate_enc_push_buffer (ke, buffer); - item = item->next; - } - } else { - GST_ERROR_OBJECT (ke, "Failed to set headers on caps"); - } - } - - g_list_free (headers); - - return rflow; -} - -static GstFlowReturn -gst_kate_enc_flush_headers (GstKateEnc * ke) -{ - GstFlowReturn rflow = GST_FLOW_OK; - if (!ke->headers_sent) { - GST_INFO_OBJECT (ke, "headers not yet sent, flushing"); - rflow = gst_kate_enc_send_headers (ke); - if (rflow == GST_FLOW_OK) { - ke->headers_sent = TRUE; - GST_INFO_OBJECT (ke, "headers flushed"); - } else { - GST_WARNING_OBJECT (ke, "Failed to flush headers: %s", - gst_flow_get_name (rflow)); - } - } - return rflow; -} - -static GstFlowReturn -gst_kate_enc_chain_push_packet (GstKateEnc * ke, kate_packet * kp, - GstClockTime start, GstClockTime duration) -{ - kate_int64_t granpos; - GstFlowReturn rflow; - - granpos = kate_encode_get_granule (&ke->k); - if (G_UNLIKELY (granpos < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Negative granpos for packet")); - kate_packet_clear (kp); - return GST_FLOW_ERROR; - } - rflow = - gst_kate_enc_push_and_free_kate_packet (ke, kp, granpos, start, duration, - FALSE); - if (G_UNLIKELY (rflow != GST_FLOW_OK)) { - GST_WARNING_OBJECT (ke, "Failed to push Kate packet"); - } - return rflow; -} - -static void -gst_kate_enc_generate_keepalive (GstKateEnc * ke, GstClockTime timestamp) -{ - kate_packet kp; - int ret; - kate_float t = timestamp / (double) GST_SECOND; - GST_DEBUG_OBJECT (ke, "keepalive at %f", t); - ret = kate_encode_keepalive (&ke->k, t, &kp); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "Failed to encode keepalive packet: %s", - gst_kate_util_get_error_message (ret)); - } else { - kate_int64_t granpos = kate_encode_get_granule (&ke->k); - GST_LOG_OBJECT (ke, "Keepalive packet encoded"); - if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos, timestamp, 0, - FALSE)) { - GST_WARNING_OBJECT (ke, "Failed to push keepalive packet"); - } - } -} - -static GstFlowReturn -gst_kate_enc_flush_waiting (GstKateEnc * ke, GstClockTime now) -{ - GstFlowReturn rflow = GST_FLOW_OK; - if (ke->delayed_spu) { - int ret; - kate_packet kp; - GstClockTime keepalive_time; - - kate_float t0 = ke->delayed_start / (double) GST_SECOND; - kate_float t1 = now / (double) GST_SECOND; - - GST_INFO_OBJECT (ke, - "We had a delayed SPU packet starting at %f, flushing at %f (assumed duration %f)", - t0, t1, t1 - t0); - - ret = kate_encode_text (&ke->k, t0, t1, "", 0, &kp); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to encode text packet: %s", - gst_kate_util_get_error_message (ret))); - rflow = GST_FLOW_ERROR; - } else { - rflow = - gst_kate_enc_chain_push_packet (ke, &kp, ke->delayed_start, - now - ke->delayed_start + 1); - } - - if (rflow == GST_FLOW_OK) { - GST_DEBUG_OBJECT (ke, "delayed SPU packet flushed"); - } else { - GST_WARNING_OBJECT (ke, "Failed to flush delayed SPU packet: %s", - gst_flow_get_name (rflow)); - } - - /* forget it even if we couldn't flush it */ - ke->delayed_spu = FALSE; - - /* free the delayed data */ - g_free (ke->delayed_bitmap->pixels); - g_free (ke->delayed_bitmap); - ke->delayed_bitmap = NULL; - g_free (ke->delayed_palette->colors); - g_free (ke->delayed_palette); - ke->delayed_palette = NULL; - g_free (ke->delayed_region); - ke->delayed_region = NULL; - - /* now that we've flushed the packet, we want to insert keepalives as requested */ - if (ke->keepalive_min_time > 0.0f && t1 > t0) { - GST_INFO_OBJECT (ke, "generating keepalives at %f from %f to %f", - ke->keepalive_min_time, t0, t1); - for (keepalive_time = ke->delayed_start; - (keepalive_time += ke->keepalive_min_time * GST_SECOND) < now;) { - GST_INFO_OBJECT (ke, "generating keepalive at %f", - keepalive_time / (double) GST_SECOND); - gst_kate_enc_generate_keepalive (ke, keepalive_time); - } - } - } - return rflow; -} - -static GstFlowReturn -gst_kate_enc_chain_spu (GstKateEnc * ke, GstBuffer * buf) -{ - kate_packet kp; - kate_region *kregion; - kate_bitmap *kbitmap; - kate_palette *kpalette; - GstFlowReturn rflow; - int ret = 0; - GstClockTime start, stop; - kate_float t0, t1; - - /* allocate region, bitmap, and palette, in case we have to delay encoding them */ - kregion = (kate_region *) g_malloc (sizeof (kate_region)); - kbitmap = (kate_bitmap *) g_malloc (sizeof (kate_bitmap)); - kpalette = (kate_palette *) g_malloc (sizeof (kate_palette)); - if (!kregion || !kpalette || !kbitmap) { - g_free (kregion); - g_free (kbitmap); - g_free (kpalette); - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Out of memory")); - return GST_FLOW_ERROR; - } - - rflow = gst_kate_spu_decode_spu (ke, buf, kregion, kbitmap, kpalette); - if (G_UNLIKELY (rflow != GST_FLOW_OK)) { - GST_ERROR_OBJECT (ke, "Failed to decode incoming SPU"); -#if 0 - { - static int spu_count = 0; - FILE *f; - char name[32]; - snprintf (name, sizeof (name), "/tmp/bad_spu_%04d", spu_count++); - name[sizeof (name) - 1] = 0; - f = fopen (name, "w"); - if (f) { - fwrite (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 1, f); - fclose (f); - } - } -#endif - goto beach; - } - - if (G_UNLIKELY (kbitmap->width == 0 || kbitmap->height == 0)) { - /* there are some DVDs (well, at least one) where some dimwits put in a wholly transparent full screen 720x576 SPU !!!!?! */ - GST_WARNING_OBJECT (ke, "SPU is totally invisible - dimwits"); - rflow = GST_FLOW_OK; - goto beach; - } - - /* timestamp offsets are hidden in the SPU packets */ - start = GST_BUFFER_TIMESTAMP (buf) + GST_KATE_STM_TO_GST (ke->show_time); - stop = GST_BUFFER_TIMESTAMP (buf) + GST_KATE_STM_TO_GST (ke->hide_time); - t0 = start / (double) GST_SECOND; - t1 = stop / (double) GST_SECOND; - GST_DEBUG_OBJECT (ke, "buf ts %f, start/show %hu/%hu", - GST_BUFFER_TIMESTAMP (buf) / (double) GST_SECOND, ke->show_time, - ke->hide_time); - -#if 0 - { - static int spu_count = 0; - FILE *f; - char name[32]; - snprintf (name, sizeof (name), "/tmp/spu_%04d", spu_count++); - name[sizeof (name) - 1] = 0; - f = fopen (name, "w"); - if (f) { - fwrite (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf), 1, f); - fclose (f); - } - } -#endif - GST_DEBUG_OBJECT (ke, "Encoding %" G_GSIZE_FORMAT "x%" G_GSIZE_FORMAT - " SPU: (%" G_GSIZE_FORMAT " bytes) from %f to %f", - kbitmap->width, kbitmap->height, gst_buffer_get_size (buf), t0, t1); - - ret = kate_encode_set_region (&ke->k, kregion); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to set region: %s", gst_kate_util_get_error_message (ret))); - goto error_return; - } - - ret = kate_encode_set_palette (&ke->k, kpalette); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to set palette: %s", gst_kate_util_get_error_message (ret))); - goto error_return; - } - - ret = kate_encode_set_bitmap (&ke->k, kbitmap); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to set bitmap: %s", gst_kate_util_get_error_message (ret))); - goto error_return; - } - - /* Some SPUs have no hide time - so I'm going to delay the encoding of the packet - till either a suitable event happens, and the time of this event will be used - as the end time of this SPU, which will then be encoded and sent off. Suitable - events are the arrival of a subsequent SPU (eg, this SPU will replace the one - with no end), EOS, a new segment event, or a time threshold being reached */ - if (ke->hide_time <= ke->show_time) { - GST_INFO_OBJECT (ke, - "Cannot encode SPU packet now, hide time is now known (starting at %f) - delaying", - t0); - ke->delayed_spu = TRUE; - ke->delayed_start = start; - ke->delayed_bitmap = kbitmap; - ke->delayed_palette = kpalette; - ke->delayed_region = kregion; - rflow = GST_FLOW_OK; - goto beach; - } - - ret = kate_encode_text (&ke->k, t0, t1, "", 0, &kp); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to encode empty text for SPU buffer: %s", - gst_kate_util_get_error_message (ret))); - goto error_return; - } - - rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); - -beach: - /* Cleanup data if we're not keeping it around */ - if (!ke->delayed_spu) { - g_free (kpalette->colors); - g_free (kpalette); - g_free (kbitmap->pixels); - g_free (kbitmap); - g_free (kregion); - } - - return rflow; - -error_return: - { - rflow = GST_FLOW_ERROR; - goto beach; - } -} - -static GstFlowReturn -gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf) -{ - kate_packet kp = { 0 }; - int ret = 0; - GstFlowReturn rflow; - GstClockTime start = GST_BUFFER_TIMESTAMP (buf); - GstClockTime stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf); - - if (ke->format == GST_KATE_FORMAT_TEXT_PANGO_MARKUP) { - ret = kate_encode_set_markup_type (&ke->k, kate_markup_simple); - } else if (ke->format == GST_KATE_FORMAT_TEXT_UTF8) { - ret = kate_encode_set_markup_type (&ke->k, kate_markup_none); - } else { - return GST_FLOW_ERROR; - } - - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to set markup type: %s", - gst_kate_util_get_error_message (ret))); - rflow = GST_FLOW_ERROR; - } else { - GstMapInfo info; - gboolean need_unmap = TRUE; - kate_float t0 = start / (double) GST_SECOND; - kate_float t1 = stop / (double) GST_SECOND; - - if (!gst_buffer_map (buf, &info, GST_MAP_READ)) { - info.data = NULL; - info.size = 0; - need_unmap = FALSE; - GST_WARNING_OBJECT (buf, "Failed to map buffer"); - } - - GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", - (int) info.size, (int) info.size, info.data, (int) info.size, t0, t1); - ret = kate_encode_text (&ke->k, t0, t1, (const char *) info.data, info.size, - &kp); - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to encode text: %s", gst_kate_util_get_error_message (ret))); - rflow = GST_FLOW_ERROR; - } else { - rflow = gst_kate_enc_chain_push_packet (ke, &kp, start, stop - start + 1); - } - if (need_unmap) - gst_buffer_unmap (buf, &info); - } - - return rflow; -} - -/* chain function - * this function does the actual processing - */ -static GstFlowReturn -gst_kate_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) -{ - GstKateEnc *ke = GST_KATE_ENC (parent); - GstFlowReturn rflow; - - GST_DEBUG_OBJECT (ke, "got packet, %" G_GSIZE_FORMAT " bytes", - gst_buffer_get_size (buf)); - - /* first push headers if we haven't done that yet */ - rflow = gst_kate_enc_flush_headers (ke); - - if (G_LIKELY (rflow == GST_FLOW_OK)) { - /* flush any packet we had waiting */ - rflow = gst_kate_enc_flush_waiting (ke, GST_BUFFER_TIMESTAMP (buf)); - - if (G_LIKELY (rflow == GST_FLOW_OK)) { - if (ke->format == GST_KATE_FORMAT_SPU) { - /* encode a kate_bitmap */ - rflow = gst_kate_enc_chain_spu (ke, buf); - } else { - /* encode text */ - rflow = gst_kate_enc_chain_text (ke, buf); - } - } - } - - gst_buffer_unref (buf); - - return rflow; -} - -static GstStateChangeReturn -gst_kate_enc_change_state (GstElement * element, GstStateChange transition) -{ - GstKateEnc *ke = GST_KATE_ENC (element); - GstStateChangeReturn res; - int ret; - - GST_INFO_OBJECT (ke, "gst_kate_enc_change_state"); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - ke->tags = gst_tag_list_new_empty (); - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG_OBJECT (ke, "READY -> PAUSED, initializing kate state"); - ret = kate_info_init (&ke->ki); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "failed to initialize kate info structure: %s", - gst_kate_util_get_error_message (ret)); - break; - } - if (ke->language) { - ret = kate_info_set_language (&ke->ki, ke->language); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "failed to set stream language: %s", - gst_kate_util_get_error_message (ret)); - break; - } - } - if (ke->category) { - ret = kate_info_set_category (&ke->ki, ke->category); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "failed to set stream category: %s", - gst_kate_util_get_error_message (ret)); - break; - } - } - ret = - kate_info_set_original_canvas_size (&ke->ki, - ke->original_canvas_width, ke->original_canvas_height); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "failed to set original canvas size: %s", - gst_kate_util_get_error_message (ret)); - break; - } - ret = kate_comment_init (&ke->kc); - if (ret < 0) { - GST_WARNING_OBJECT (ke, - "failed to initialize kate comment structure: %s", - gst_kate_util_get_error_message (ret)); - break; - } - ret = kate_encode_init (&ke->k, &ke->ki); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "failed to initialize kate state: %s", - gst_kate_util_get_error_message (ret)); - break; - } - ke->headers_sent = FALSE; - ke->initialized = TRUE; - ke->last_timestamp = 0; - ke->latest_end_time = 0; - ke->format = GST_KATE_FORMAT_UNDEFINED; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_tag_list_unref (ke->tags); - ke->tags = NULL; - break; - default: - break; - } - - res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (res == GST_STATE_CHANGE_FAILURE) { - GST_WARNING_OBJECT (ke, "Parent failed to change state"); - return res; - } - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG_OBJECT (ke, "PAUSED -> READY, clearing kate state"); - if (ke->initialized) { - kate_clear (&ke->k); - kate_info_clear (&ke->ki); - kate_comment_clear (&ke->kc); - ke->initialized = FALSE; - ke->last_timestamp = 0; - ke->latest_end_time = 0; - } - gst_event_replace (&ke->pending_segment, NULL); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - GST_DEBUG_OBJECT (ke, "State change done"); - - return res; -} - -static GstClockTime -gst_kate_enc_granule_time (kate_state * k, gint64 granulepos) -{ - float t; - - if (granulepos == -1) - return -1; - - t = kate_granule_time (k->ki, granulepos); - return t * GST_SECOND; -} - -/* -conversions on the sink: - - nothing -conversions on the source: - - default is granules at num/den rate - - default -> time is possible - - bytes do not mean anything, packets can be any number of bytes, and we - have no way to know the number of bytes emitted without decoding -*/ - -static gboolean -gst_kate_enc_convert (GstPad * pad, GstFormat src_fmt, gint64 src_val, - GstFormat * dest_fmt, gint64 * dest_val) -{ - GstKateEnc *ke; - gboolean res = FALSE; - - if (src_fmt == *dest_fmt) { - *dest_val = src_val; - return TRUE; - } - - ke = GST_KATE_ENC (gst_pad_get_parent (pad)); - - if (!ke->initialized) { - GST_WARNING_OBJECT (ke, "not initialized yet"); - gst_object_unref (ke); - return FALSE; - } - - if (src_fmt == GST_FORMAT_BYTES || *dest_fmt == GST_FORMAT_BYTES) { - GST_WARNING_OBJECT (ke, "unsupported format"); - gst_object_unref (ke); - return FALSE; - } - - switch (src_fmt) { - case GST_FORMAT_DEFAULT: - switch (*dest_fmt) { - case GST_FORMAT_TIME: - *dest_val = gst_kate_enc_granule_time (&ke->k, src_val); - res = TRUE; - break; - default: - res = FALSE; - break; - } - break; - default: - res = FALSE; - break; - } - - if (!res) { - GST_WARNING_OBJECT (ke, "unsupported format"); - } - - gst_object_unref (ke); - return res; -} - -static gboolean -gst_kate_enc_source_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - gboolean res = FALSE; - - GST_DEBUG ("source query %d", GST_QUERY_TYPE (query)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - if (!gst_kate_enc_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)) { - return gst_pad_query_default (pad, parent, query); - } - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - res = TRUE; - } - break; - default: - res = gst_pad_query_default (pad, parent, query); - break; - } - - return res; -} - -static gboolean -gst_kate_enc_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstKateEnc *ke = GST_KATE_ENC (parent); - const GstStructure *structure; - gboolean ret; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_CAPS: - { - GstCaps *caps; - - gst_event_parse_caps (event, &caps); - ret = gst_kate_enc_setcaps (ke, caps); - gst_event_unref (event); - break; - } - case GST_EVENT_SEGMENT:{ - GstSegment seg; - - GST_LOG_OBJECT (ke, "Got newsegment event"); - - gst_event_copy_segment (event, &seg); - - if (!ke->headers_sent) { - if (ke->pending_segment) - gst_event_unref (ke->pending_segment); - ke->pending_segment = event; - event = NULL; - } - - if (ke->initialized) { - GST_LOG_OBJECT (ke, "ensuring all headers are in"); - if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { - GST_WARNING_OBJECT (ke, "Failed to flush headers"); - } else { - if (seg.format != GST_FORMAT_TIME - || !GST_CLOCK_TIME_IS_VALID (seg.start)) { - GST_WARNING_OBJECT (ke, - "No time in newsegment event %p, format %d, timestamp %" - G_GINT64_FORMAT, event, (int) seg.format, seg.start); - /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a - good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a - timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we - run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */ - } else { - float t = seg.start / (double) GST_SECOND; - - if (ke->delayed_spu - && t - ke->delayed_start / (double) GST_SECOND >= - ke->default_spu_duration) { - if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, - seg.start) != GST_FLOW_OK)) { - GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); - /* continue with new segment handling anyway */ - } - } - - GST_LOG_OBJECT (ke, "ts %f, last %f (min %f)", t, - ke->last_timestamp / (double) GST_SECOND, - ke->keepalive_min_time); - if (ke->keepalive_min_time > 0.0f - && t - ke->last_timestamp / (double) GST_SECOND >= - ke->keepalive_min_time) { - /* we only generate a keepalive if there is no SPU waiting, as it would - mean out of sequence start times - and granulepos */ - if (!ke->delayed_spu) { - gst_kate_enc_generate_keepalive (ke, seg.start); - } - } - } - } - } - if (event) - ret = gst_pad_push_event (ke->srcpad, event); - else - ret = TRUE; - break; - } - case GST_EVENT_CUSTOM_DOWNSTREAM: - GST_LOG_OBJECT (ke, "Got custom downstream event"); - /* adapted from the dvdsubdec element */ - structure = gst_event_get_structure (event); - if (structure != NULL - && gst_structure_has_name (structure, "application/x-gst-dvd")) { - if (ke->initialized) { - GST_LOG_OBJECT (ke, "ensuring all headers are in"); - if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { - GST_WARNING_OBJECT (ke, "Failed to flush headers"); - } else { - const gchar *event_name = - gst_structure_get_string (structure, "event"); - if (event_name) { - if (!strcmp (event_name, "dvd-spu-clut-change")) { - gchar name[16]; - int idx; - gboolean found; - gint value; - GST_INFO_OBJECT (ke, "New CLUT received"); - for (idx = 0; idx < 16; ++idx) { - g_snprintf (name, sizeof (name), "clut%02d", idx); - found = gst_structure_get_int (structure, name, &value); - if (found) { - ke->spu_clut[idx] = value; - } else { - GST_WARNING_OBJECT (ke, - "DVD CLUT event did not contain %s field", name); - } - } - } else if (!strcmp (event_name, "dvd-lang-codes")) { - /* we can't know which stream corresponds to us */ - } - } else { - GST_WARNING_OBJECT (ke, "custom downstream event with no name"); - } - } - } - } - ret = gst_pad_push_event (ke->srcpad, event); - break; - - case GST_EVENT_TAG: - GST_LOG_OBJECT (ke, "Got tag event"); - if (ke->tags) { - GstTagList *list; - - gst_event_parse_tag (event, &list); - gst_tag_list_insert (ke->tags, list, - gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (ke))); - } else { - g_assert_not_reached (); - } - ret = gst_pad_event_default (pad, parent, event); - break; - - case GST_EVENT_EOS: - GST_INFO_OBJECT (ke, "Got EOS event"); - if (ke->initialized) { - GST_LOG_OBJECT (ke, "ensuring all headers are in"); - if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { - GST_WARNING_OBJECT (ke, "Failed to flush headers"); - } else { - kate_packet kp; - int ret; - GstClockTime delayed_end = - ke->delayed_start + ke->default_spu_duration * GST_SECOND; - - if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, - delayed_end) != GST_FLOW_OK)) { - GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); - /* continue with EOS handling anyway */ - } - - ret = kate_encode_finish (&ke->k, -1, &kp); - if (ret < 0) { - GST_WARNING_OBJECT (ke, "Failed to encode EOS packet: %s", - gst_kate_util_get_error_message (ret)); - } else { - kate_int64_t granpos = kate_encode_get_granule (&ke->k); - GST_LOG_OBJECT (ke, "EOS packet encoded"); - if (gst_kate_enc_push_and_free_kate_packet (ke, &kp, granpos, - ke->latest_end_time, 0, FALSE)) { - GST_WARNING_OBJECT (ke, "Failed to push EOS packet"); - } - } - } - } - ret = gst_pad_event_default (pad, parent, event); - break; - - default: - GST_LOG_OBJECT (ke, "Got unhandled event"); - ret = gst_pad_event_default (pad, parent, event); - break; - } - - return ret; -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateenc.h b/subprojects/gst-plugins-bad/ext/kate/gstkateenc.h deleted file mode 100644 index ff4dc5f1f2..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateenc.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_KATE_ENC_H__ -#define __GST_KATE_ENC_H__ - -#include -#include - -#include "gstkateutil.h" - -G_BEGIN_DECLS -/* #defines don't like whitespacey bits */ -#define GST_TYPE_KATE_ENC \ - (gst_kate_enc_get_type()) -#define GST_KATE_ENC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KATE_ENC,GstKateEnc)) -#define GST_KATE_ENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE,GstKateEncClass)) -#define GST_IS_KATE_ENC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_ENC)) -#define GST_IS_KATE_ENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_ENC)) -typedef struct _GstKateEnc GstKateEnc; -typedef struct _GstKateEncClass GstKateEncClass; - -struct _GstKateEnc -{ - GstElement element; - - GstPad *sinkpad, *srcpad; - - kate_info ki; - kate_comment kc; - kate_state k; - - GstTagList *tags; - - GstClockTime last_timestamp; - GstClockTime latest_end_time; - - GstEvent *pending_segment; - - gboolean headers_sent; - gboolean initialized; - gboolean delayed_spu; - GstClockTime delayed_start; - kate_bitmap *delayed_bitmap; - kate_palette *delayed_palette; - kate_region *delayed_region; - gchar *language; - gchar *category; - - GstKateFormat format; - - int granule_rate_numerator; - int granule_rate_denominator; - int granule_shift; - - float keepalive_min_time; - float default_spu_duration; - - size_t original_canvas_width; - size_t original_canvas_height; - - /* SPU decoding */ - guint8 spu_colormap[4]; - guint32 spu_clut[16]; - guint8 spu_alpha[4]; - guint16 spu_top; - guint16 spu_left; - guint16 spu_right; - guint16 spu_bottom; - guint16 spu_pix_data[2]; - guint16 show_time; - guint16 hide_time; -}; - -struct _GstKateEncClass -{ - GstElementClass parent_class; -}; - -GType gst_kate_enc_get_type (void); - -G_END_DECLS -#endif /* __GST_KATE_ENC_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateparse.c b/subprojects/gst-plugins-bad/ext/kate/gstkateparse.c deleted file mode 100644 index 6adc10c758..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateparse.c +++ /dev/null @@ -1,634 +0,0 @@ -/* GStreamer - * Copyright (C) <2004> Thomas Vander Stichele - * Copyright (C) 2006 Andy Wingo - * Copyright (C) 2008 Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-kateparse - * @title: kateparse - * @short_description: parses kate streams - * @see_also: katedec, vorbisparse, oggdemux, theoraparse - * - * The kateparse element will parse the header packets of the Kate - * stream and put them as the streamheader in the caps. This is used in the - * multifdsink case where you want to stream live kate streams to multiple - * clients, each client has to receive the streamheaders first before they can - * consume the kate packets. - * - * This element also makes sure that the buffers that it pushes out are properly - * timestamped and that their offset and offset_end are set. The buffers that - * kateparse outputs have all of the metadata that oggmux expects to receive, - * which allows you to (for example) remux an ogg/kate file. - * - * ## Example pipelines - * - * |[ - * gst-launch-1.0 -v filesrc location=kate.ogg ! oggdemux ! kateparse ! fakesink - * ]| - * This pipeline shows that the streamheader is set in the caps, and that each - * buffer has the timestamp, duration, offset, and offset_end set. - * - * |[ - * gst-launch-1.0 filesrc location=kate.ogg ! oggdemux ! kateparse \ - * ! oggmux ! filesink location=kate-remuxed.ogg - * ]| - * This pipeline shows remuxing. kate-remuxed.ogg might not be exactly the same - * as kate.ogg, but they should produce exactly the same decoded data. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "gstkateelements.h" -#include "gstkateutil.h" -#include "gstkateparse.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_kateparse_debug); -#define GST_CAT_DEFAULT gst_kateparse_debug - -static GstStaticPadTemplate gst_kate_parse_sink_factory = - GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") - ); - -static GstStaticPadTemplate gst_kate_parse_src_factory = - GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") - ); - -GST_DEBUG_CATEGORY (gst_kateparse_debug); - -#define gst_kate_parse_parent_class parent_class -G_DEFINE_TYPE (GstKateParse, gst_kate_parse, GST_TYPE_ELEMENT); -#define _do_init \ - kate_element_init (plugin); \ - GST_DEBUG_CATEGORY_INIT (gst_kateparse_debug, "kateparse", 0, "Kate parser"); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (kateparse, "kateparse", GST_RANK_NONE, - GST_TYPE_KATE_PARSE, _do_init); - -static GstFlowReturn gst_kate_parse_chain (GstPad * pad, GstObject * parent, - GstBuffer * buffer); -static GstStateChangeReturn gst_kate_parse_change_state (GstElement * element, - GstStateChange transition); -static gboolean gst_kate_parse_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean gst_kate_parse_src_query (GstPad * pad, GstObject * parent, - GstQuery * query); -#if 0 -static gboolean gst_kate_parse_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value); -#endif -static GstFlowReturn gst_kate_parse_parse_packet (GstKateParse * parse, - GstBuffer * buf); - -static void -gst_kate_parse_class_init (GstKateParseClass * klass) -{ - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - gstelement_class->change_state = gst_kate_parse_change_state; - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_kate_parse_src_factory); - gst_element_class_add_static_pad_template (gstelement_class, - &gst_kate_parse_sink_factory); - - gst_element_class_set_static_metadata (gstelement_class, "Kate stream parser", - "Codec/Parser/Subtitle", - "parse raw kate streams", - "Vincent Penquerc'h "); - - klass->parse_packet = GST_DEBUG_FUNCPTR (gst_kate_parse_parse_packet); -} - -static void -gst_kate_parse_init (GstKateParse * parse) -{ - parse->sinkpad = - gst_pad_new_from_static_template (&gst_kate_parse_sink_factory, "sink"); - gst_pad_set_chain_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_parse_chain)); - gst_pad_set_event_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_kate_parse_sink_event)); - gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); - - parse->srcpad = - gst_pad_new_from_static_template (&gst_kate_parse_src_factory, "src"); - gst_pad_set_query_function (parse->srcpad, - GST_DEBUG_FUNCPTR (gst_kate_parse_src_query)); - gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); -} - -static void -gst_kate_parse_drain_event_queue (GstKateParse * parse) -{ - while (parse->event_queue->length) { - GstEvent *event; - - event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); - gst_pad_event_default (parse->sinkpad, NULL, event); - } -} - -static GstFlowReturn -gst_kate_parse_push_headers (GstKateParse * parse) -{ - /* mark and put on caps */ - GstCaps *caps; - GstBuffer *outbuf; - kate_packet packet; - GList *headers, *outbuf_list = NULL; - int ret; - gboolean res; - - /* get the headers into the caps, passing them to kate as we go */ - caps = - gst_kate_util_set_header_on_caps (&parse->element, - gst_pad_get_current_caps (parse->sinkpad), parse->streamheader); - - if (G_UNLIKELY (!caps)) { - GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), - ("Failed to set headers on caps")); - return GST_FLOW_ERROR; - } - - GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps); - res = gst_pad_set_caps (parse->srcpad, caps); - gst_caps_unref (caps); - if (G_UNLIKELY (!res)) { - GST_WARNING_OBJECT (parse->srcpad, "Failed to set caps on source pad"); - return GST_FLOW_NOT_NEGOTIATED; - } - - headers = parse->streamheader; - while (headers) { - GstMapInfo info; - - outbuf = GST_BUFFER_CAST (headers->data); - - if (!gst_buffer_map (outbuf, &info, GST_MAP_READ)) { - GST_WARNING_OBJECT (outbuf, "Failed to map buffer"); - continue; - } - - kate_packet_wrap (&packet, info.size, info.data); - ret = kate_decode_headerin (&parse->ki, &parse->kc, &packet); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (parse, "Failed to decode header: %s", - gst_kate_util_get_error_message (ret)); - } - gst_buffer_unmap (outbuf, &info); - /* takes ownership of outbuf, which was previously in parse->streamheader */ - GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_HEADER); - outbuf_list = g_list_append (outbuf_list, outbuf); - headers = headers->next; - } - - /* first process queued events */ - gst_kate_parse_drain_event_queue (parse); - - /* push out buffers, ignoring return value... */ - headers = outbuf_list; - while (headers) { - outbuf = GST_BUFFER_CAST (headers->data); - gst_pad_push (parse->srcpad, outbuf); - headers = headers->next; - } - - g_list_free (outbuf_list); - g_list_free (parse->streamheader); - parse->streamheader = NULL; - - parse->streamheader_sent = TRUE; - - return GST_FLOW_OK; -} - -static void -gst_kate_parse_clear_queue (GstKateParse * parse) -{ - GST_DEBUG_OBJECT (parse, "Clearing queue"); - while (parse->buffer_queue->length) { - GstBuffer *buf; - - buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); - gst_buffer_unref (buf); - } - while (parse->event_queue->length) { - GstEvent *event; - - event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); - gst_event_unref (event); - } -} - -static GstFlowReturn -gst_kate_parse_push_buffer (GstKateParse * parse, GstBuffer * buf, - gint64 granulepos) -{ - GST_LOG_OBJECT (parse, "granulepos %16" G_GINT64_MODIFIER "x", granulepos); - if (granulepos < 0) { - /* packets coming not from Ogg won't have a granpos in the offset end, - so we have to synthesize one here - only problem is we don't know - the backlink - pretend there's none for now */ - GST_INFO_OBJECT (parse, "No granulepos on buffer, synthesizing one"); - granulepos = - kate_duration_granule (&parse->ki, - GST_BUFFER_TIMESTAMP (buf) / - (double) GST_SECOND) << kate_granule_shift (&parse->ki); - } - GST_BUFFER_OFFSET (buf) = - kate_granule_time (&parse->ki, granulepos) * GST_SECOND; - GST_BUFFER_OFFSET_END (buf) = granulepos; - GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf); - - return gst_pad_push (parse->srcpad, buf); -} - -static GstFlowReturn -gst_kate_parse_drain_queue_prematurely (GstKateParse * parse) -{ - GstFlowReturn ret = GST_FLOW_OK; - - /* got an EOS event, make sure to push out any buffers that were in the queue - * -- won't normally be the case, but this catches the - * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous - * stream. */ - - /* if we got EOS before any buffers came, go ahead and push the other events - * first */ - gst_kate_parse_drain_event_queue (parse); - - while (!g_queue_is_empty (parse->buffer_queue)) { - GstBuffer *buf; - gint64 granpos; - - buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); - - granpos = GST_BUFFER_OFFSET_END (buf); - ret = gst_kate_parse_push_buffer (parse, buf, granpos); - - if (ret != GST_FLOW_OK) - goto done; - } - - g_assert (g_queue_is_empty (parse->buffer_queue)); - -done: - return ret; -} - -static GstFlowReturn -gst_kate_parse_drain_queue (GstKateParse * parse, gint64 granulepos) -{ - GstFlowReturn ret = GST_FLOW_OK; - - if (!g_queue_is_empty (parse->buffer_queue)) { - GstBuffer *buf; - buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); - ret = gst_kate_parse_push_buffer (parse, buf, granulepos); - - if (ret != GST_FLOW_OK) - goto done; - } - g_assert (g_queue_is_empty (parse->buffer_queue)); - -done: - return ret; -} - -static GstFlowReturn -gst_kate_parse_queue_buffer (GstKateParse * parse, GstBuffer * buf) -{ - GstFlowReturn ret = GST_FLOW_OK; - gint64 granpos; - - buf = gst_buffer_make_writable (buf); - - /* oggdemux stores the granule pos in the offset end */ - granpos = GST_BUFFER_OFFSET_END (buf); - GST_LOG_OBJECT (parse, "granpos %16" G_GINT64_MODIFIER "x", granpos); - g_queue_push_tail (parse->buffer_queue, buf); - -#if 1 - /* if getting buffers from matroska, we won't have a granpos here... */ - //if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) { - ret = gst_kate_parse_drain_queue (parse, granpos); - //} -#else - if (granpos >= 0) { - ret = gst_kate_parse_drain_queue (parse, granpos); - } else { - GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), - ("Bad granulepos %" G_GINT64_FORMAT, granpos)); - ret = GST_FLOW_ERROR; - } -#endif - - return ret; -} - -static GstFlowReturn -gst_kate_parse_parse_packet (GstKateParse * parse, GstBuffer * buf) -{ - GstFlowReturn ret = GST_FLOW_OK; - guint8 header[1]; - gsize size; - - g_assert (parse); - - parse->packetno++; - - size = gst_buffer_extract (buf, 0, header, 1); - - GST_LOG_OBJECT (parse, "Got packet %02x, %" G_GSIZE_FORMAT " bytes", - size ? header[0] : -1, gst_buffer_get_size (buf)); - - if (size > 0 && header[0] & 0x80) { - GST_DEBUG_OBJECT (parse, "Found header %02x", header[0]); - /* if 0x80 is set, it's streamheader, - * so put it on the streamheader list and return */ - parse->streamheader = g_list_append (parse->streamheader, buf); - ret = GST_FLOW_OK; - } else { - if (!parse->streamheader_sent) { - GST_DEBUG_OBJECT (parse, "Found non header, pushing headers seen so far"); - ret = gst_kate_parse_push_headers (parse); - } - - if (ret == GST_FLOW_OK) { - ret = gst_kate_parse_queue_buffer (parse, buf); - } - } - - return ret; -} - -static GstFlowReturn -gst_kate_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) -{ - GstKateParseClass *klass; - GstKateParse *parse; - - parse = GST_KATE_PARSE (parent); - klass = GST_KATE_PARSE_CLASS (G_OBJECT_GET_CLASS (parse)); - - g_assert (klass->parse_packet != NULL); - - if (G_UNLIKELY (!gst_pad_has_current_caps (pad))) - return GST_FLOW_NOT_NEGOTIATED; - - return klass->parse_packet (parse, buffer); -} - -static gboolean -gst_kate_parse_queue_event (GstKateParse * parse, GstEvent * event) -{ - GstFlowReturn ret = TRUE; - - g_queue_push_tail (parse->event_queue, event); - - return ret; -} - -static gboolean -gst_kate_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - gboolean ret; - GstKateParse *parse; - - parse = GST_KATE_PARSE (parent); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - gst_kate_parse_clear_queue (parse); - ret = gst_pad_event_default (pad, parent, event); - break; - case GST_EVENT_EOS: - if (!parse->streamheader_sent) { - GST_DEBUG_OBJECT (parse, "Got EOS, pushing headers seen so far"); - ret = gst_kate_parse_push_headers (parse); - if (ret != GST_FLOW_OK) - break; - } - gst_kate_parse_drain_queue_prematurely (parse); - ret = gst_pad_event_default (pad, parent, event); - break; - default: - if (!parse->streamheader_sent && GST_EVENT_IS_SERIALIZED (event) - && GST_EVENT_TYPE (event) > GST_EVENT_CAPS) - ret = gst_kate_parse_queue_event (parse, event); - else - ret = gst_pad_event_default (pad, parent, event); - break; - } - - return ret; -} - -#if 0 -static gboolean -gst_kate_parse_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - GstKateParse *parse; - - parse = GST_KATE_PARSE (GST_PAD_PARENT (pad)); - - /* fixme: assumes atomic access to lots of instance variables modified from - * the streaming thread, including 64-bit variables */ - - if (!parse->streamheader_sent) - return FALSE; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - if (parse->sinkpad == pad && - (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) - return FALSE; - - switch (src_format) { - case GST_FORMAT_TIME: - switch (*dest_format) { - default: - res = FALSE; - } - break; - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = kate_granule_time (&parse->ki, src_value) * GST_SECOND; - break; - default: - res = FALSE; - } - break; - default: - res = FALSE; - } - - return res; -} -#endif - -static gboolean -gst_kate_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ -#if 1 - // TODO - GST_WARNING ("gst_kate_parse_src_query"); - return FALSE; -#else - gint64 granulepos; - GstKateParse *parse; - gboolean res = FALSE; - - parse = GST_KATE_PARSE (parent); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - GstFormat format; - gint64 value; - - granulepos = parse->prev_granulepos; - - gst_query_parse_position (query, &format, NULL); - - /* and convert to the final format */ - if (!(res = - gst_kate_parse_convert (pad, GST_FORMAT_DEFAULT, granulepos, - &format, &value))) - goto error; - - /* fixme: support segments - value = (value - parse->segment_start) + parse->segment_time; - */ - - gst_query_set_position (query, format, value); - - GST_LOG_OBJECT (parse, "query %p: peer returned granulepos: %" - G_GUINT64_FORMAT " - we return %" G_GUINT64_FORMAT " (format %u)", - query, granulepos, value, format); - - break; - } - case GST_QUERY_DURATION: - { - /* fixme: not threadsafe */ - /* query peer for total length */ - if (!gst_pad_is_linked (parse->sinkpad)) { - GST_WARNING_OBJECT (parse, "sink pad %" GST_PTR_FORMAT " is not linked", - parse->sinkpad); - goto error; - } - if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query))) - goto error; - break; - } - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - if (!(res = - gst_kate_parse_convert (pad, src_fmt, src_val, &dest_fmt, - &dest_val))) - goto error; - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } - return res; - -error: - { - GST_WARNING_OBJECT (parse, "error handling query"); - return res; - } -#endif -} - -static void -gst_kate_parse_free_stream_headers (GstKateParse * parse) -{ - while (parse->streamheader != NULL) { - gst_buffer_unref (GST_BUFFER (parse->streamheader->data)); - parse->streamheader = g_list_delete_link (parse->streamheader, - parse->streamheader); - } -} - -static GstStateChangeReturn -gst_kate_parse_change_state (GstElement * element, GstStateChange transition) -{ - GstKateParse *parse = GST_KATE_PARSE (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - kate_info_init (&parse->ki); - kate_comment_init (&parse->kc); - parse->packetno = 0; - parse->streamheader_sent = FALSE; - parse->streamheader = NULL; - parse->buffer_queue = g_queue_new (); - parse->event_queue = g_queue_new (); - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - kate_info_clear (&parse->ki); - kate_comment_clear (&parse->kc); - - gst_kate_parse_clear_queue (parse); - g_queue_free (parse->buffer_queue); - parse->buffer_queue = NULL; - g_queue_free (parse->event_queue); - parse->event_queue = NULL; - gst_kate_parse_free_stream_headers (parse); - break; - - default: - break; - } - - return ret; -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateparse.h b/subprojects/gst-plugins-bad/ext/kate/gstkateparse.h deleted file mode 100644 index 29db2b5a24..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateparse.h +++ /dev/null @@ -1,78 +0,0 @@ -/* -*- c-basic-offset: 2 -*- - * GStreamer - * Copyright (C) <2004> Thomas Vander Stichele - * Copyright (C) <2008> Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef __GST_KATE_PARSE_H__ -#define __GST_KATE_PARSE_H__ - - -#include -#include - -G_BEGIN_DECLS -#define GST_TYPE_KATE_PARSE \ - (gst_kate_parse_get_type()) -#define GST_KATE_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KATE_PARSE,GstKateParse)) -#define GST_KATE_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE_PARSE,GstKateParseClass)) -#define GST_IS_KATE_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_PARSE)) -#define GST_IS_KATE_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_PARSE)) -typedef struct _GstKateParse GstKateParse; -typedef struct _GstKateParseClass GstKateParseClass; - -/** - * GstKateParse: - * - * Opaque data structure. - */ -struct _GstKateParse -{ - GstElement element; - - GstPad *sinkpad; - GstPad *srcpad; - - guint packetno; - gboolean streamheader_sent; - GList *streamheader; - - GQueue *event_queue; - GQueue *buffer_queue; - - kate_info ki; - kate_comment kc; -}; - -struct _GstKateParseClass -{ - GstElementClass parent_class; - - /* virtual functions */ - GstFlowReturn (*parse_packet) (GstKateParse * parse, GstBuffer * buf); -}; - -GType gst_kate_parse_get_type (void); - -G_END_DECLS -#endif /* __GST_KATE_PARSE_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatespu.c b/subprojects/gst-plugins-bad/ext/kate/gstkatespu.c deleted file mode 100644 index 6a782048b2..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatespu.c +++ /dev/null @@ -1,916 +0,0 @@ -/* GStreamer - * Copyright (C) 2009 Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include -#include -#include -#include -#include "gstkatespu.h" - -#define MAX_SPU_SIZE 53220 - -GST_DEBUG_CATEGORY_EXTERN (gst_kateenc_debug); -GST_DEBUG_CATEGORY_EXTERN (gst_katedec_debug); - -/* taken off the dvdsubdec element */ -const guint32 gst_kate_spu_default_clut[16] = { - 0xb48080, 0x248080, 0x628080, 0xd78080, - 0x808080, 0x808080, 0x808080, 0x808080, - 0x808080, 0x808080, 0x808080, 0x808080, - 0x808080, 0x808080, 0x808080, 0x808080 -}; - -#define GST_CAT_DEFAULT gst_kateenc_debug - -static void -gst_kate_spu_decode_colormap (GstKateEnc * ke, const guint8 * ptr) -{ - ke->spu_colormap[3] = ptr[0] >> 4; - ke->spu_colormap[2] = ptr[0] & 0x0f; - ke->spu_colormap[1] = ptr[1] >> 4; - ke->spu_colormap[0] = ptr[1] & 0x0f; -} - -static void -gst_kate_spu_decode_alpha (GstKateEnc * ke, const guint8 * ptr) -{ - ke->spu_alpha[3] = ptr[0] >> 4; - ke->spu_alpha[2] = ptr[0] & 0x0f; - ke->spu_alpha[1] = ptr[1] >> 4; - ke->spu_alpha[0] = ptr[1] & 0x0f; -} - -static void -gst_kate_spu_decode_area (GstKateEnc * ke, const guint8 * ptr) -{ - ke->spu_left = ((((guint16) ptr[0]) & 0xff) << 4) | (ptr[1] >> 4); - ke->spu_top = ((((guint16) ptr[3]) & 0xff) << 4) | (ptr[4] >> 4); - ke->spu_right = ((((guint16) ptr[1]) & 0x0f) << 8) | ptr[2]; - ke->spu_bottom = ((((guint16) ptr[4]) & 0x0f) << 8) | ptr[5]; - GST_DEBUG_OBJECT (ke, "SPU area %u %u -> %u %d", ke->spu_left, ke->spu_top, - ke->spu_right, ke->spu_bottom); -} - -static void -gst_kate_spu_decode_pixaddr (GstKateEnc * ke, const guint8 * ptr) -{ - ke->spu_pix_data[0] = GST_KATE_UINT16_BE (ptr + 0); - ke->spu_pix_data[1] = GST_KATE_UINT16_BE (ptr + 2); -} - -/* heavily inspired from dvdspudec */ -static guint16 -gst_kate_spu_decode_colcon (GstKateEnc * ke, const guint8 * ptr, guint16 sz) -{ - guint16 nbytes = GST_KATE_UINT16_BE (ptr + 0); - guint16 nbytes_left = nbytes; - - GST_LOG_OBJECT (ke, "Number of bytes in color/contrast change command is %u", - nbytes); - if (G_UNLIKELY (nbytes < 2)) { - GST_WARNING_OBJECT (ke, - "Number of bytes in color/contrast change command is %u, should be at least 2", - nbytes); - return 0; - } - if (G_UNLIKELY (nbytes > sz)) { - GST_WARNING_OBJECT (ke, - "Number of bytes in color/contrast change command is %u, but the buffer " - "only contains %u byte(s)", nbytes, sz); - return 0; - } - - ptr += 2; - nbytes_left -= 2; - - /* we will just skip that data for now */ - while (nbytes_left > 0) { - guint32 entry, nchanges, sz; - GST_LOG_OBJECT (ke, "Reading a color/contrast change entry, %u bytes left", - nbytes_left); - if (G_UNLIKELY (nbytes_left < 4)) { - GST_WARNING_OBJECT (ke, - "Not enough bytes to read a full color/contrast entry header"); - break; - } - entry = GST_READ_UINT32_BE (ptr); - GST_LOG_OBJECT (ke, "Color/contrast change entry header is %08x", entry); - nchanges = CLAMP ((ptr[2] >> 4), 1, 8); - ptr += 4; - nbytes_left -= 4; - if (entry == 0x0fffffff) { - GST_LOG_OBJECT (ke, - "Encountered color/contrast change termination code, breaking, %u bytes left", - nbytes_left); - break; - } - GST_LOG_OBJECT (ke, "Color/contrast change entry has %u changes", nchanges); - sz = 6 * nchanges; - if (G_UNLIKELY (sz > nbytes_left)) { - GST_WARNING_OBJECT (ke, - "Not enough bytes to read a full color/contrast entry"); - break; - } - ptr += sz; - nbytes_left -= sz; - } - return nbytes - nbytes_left; -} - -static inline guint8 -gst_kate_spu_get_nybble (const guint8 * nybbles, size_t *nybble_offset) -{ - guint8 ret; - - ret = nybbles[(*nybble_offset) / 2]; - - /* If the offset is even, we shift the answer down 4 bits, otherwise not */ - if ((*nybble_offset) & 0x01) - ret &= 0x0f; - else - ret = ret >> 4; - - (*nybble_offset)++; - - return ret; -} - -static guint16 -gst_kate_spu_get_rle_code (const guint8 * nybbles, size_t *nybble_offset) -{ - guint16 code; - - code = gst_kate_spu_get_nybble (nybbles, nybble_offset); - if (code < 0x4) { /* 4 .. f */ - code = (code << 4) | gst_kate_spu_get_nybble (nybbles, nybble_offset); - if (code < 0x10) { /* 1x .. 3x */ - code = (code << 4) | gst_kate_spu_get_nybble (nybbles, nybble_offset); - if (code < 0x40) { /* 04x .. 0fx */ - code = (code << 4) | gst_kate_spu_get_nybble (nybbles, nybble_offset); - } - } - } - return code; -} - -static void -gst_kate_spu_crop_bitmap (GstKateEnc * ke, kate_bitmap * kb, guint16 * dx, - guint16 * dy) -{ - int top, bottom, left, right; - guint8 zero = 0; - size_t n, x, y, w, h; - -#if 0 - /* find the zero */ - zero = kb->pixels[0]; - for (x = 0; x < kb->width; ++x) { - if (kb->pixels[x] != zero) { - GST_LOG_OBJECT (ke, "top line at %u is not zero: %u", x, kb->pixels[x]); - return; - } - } -#endif - - /* top */ - for (top = 0; top < kb->height; ++top) { - int empty = 1; - for (x = 0; x < kb->width; ++x) { - if (G_UNLIKELY (kb->pixels[x + top * kb->width] != zero)) { - empty = 0; - break; - } - } - if (!empty) - break; - } - - /* bottom */ - for (bottom = kb->height - 1; bottom >= top; --bottom) { - int empty = 1; - for (x = 0; x < kb->width; ++x) { - if (G_UNLIKELY (kb->pixels[x + bottom * kb->width] != zero)) { - empty = 0; - break; - } - } - if (!empty) - break; - } - - /* left */ - for (left = 0; left < kb->width; ++left) { - int empty = 1; - for (y = top; y <= bottom; ++y) { - if (G_UNLIKELY (kb->pixels[left + y * kb->width] != zero)) { - empty = 0; - break; - } - } - if (!empty) - break; - } - - /* right */ - for (right = kb->width - 1; right >= left; --right) { - int empty = 1; - for (y = top; y <= bottom; ++y) { - if (G_UNLIKELY (kb->pixels[right + y * kb->width] != zero)) { - empty = 0; - break; - } - } - if (!empty) - break; - } - - - w = right - left + 1; - h = bottom - top + 1; - GST_LOG_OBJECT (ke, "cropped from %" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT - " to %" G_GSIZE_FORMAT " %" G_GSIZE_FORMAT, kb->width, kb->height, w, h); - *dx += left; - *dy += top; - n = 0; - for (y = 0; y < h; ++y) { - memmove (kb->pixels + n, kb->pixels + kb->width * (y + top) + left, w); - n += w; - } - kb->width = w; - kb->height = h; -} - -#define CHECK(x) G_STMT_START { \ - guint16 _ = (x); \ - if (G_UNLIKELY((_) > sz)) { \ - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Read outside buffer")); \ - return GST_FLOW_ERROR; \ - } \ - } G_STMT_END -#define ADVANCE(x) G_STMT_START { \ - guint16 _ = (x); ptr += (_); sz -= (_); \ - } G_STMT_END -#define IGNORE(x) G_STMT_START { \ - guint16 __ = (x); \ - CHECK (__); \ - ADVANCE (__); \ - } G_STMT_END - -static GstFlowReturn -gst_kate_spu_decode_command_sequence (GstKateEnc * ke, GstBuffer * buf, - guint16 command_sequence_offset) -{ - guint16 date; - guint16 next_command_sequence; - const guint8 *ptr; - GstMapInfo info; - guint16 sz; - - if (!gst_buffer_map (buf, &info, GST_MAP_READ)) { - GST_ERROR_OBJECT (ke, "Failed to map buffer"); - return GST_FLOW_ERROR; - } - - if (command_sequence_offset >= info.size) - goto out_of_range; - - ptr = info.data + command_sequence_offset; - sz = info.size - command_sequence_offset; - - GST_DEBUG_OBJECT (ke, "Decoding command sequence at %u (%u bytes)", - command_sequence_offset, sz); - - CHECK (2); - date = GST_KATE_UINT16_BE (ptr); - ADVANCE (2); - GST_DEBUG_OBJECT (ke, "date %u", date); - - CHECK (2); - next_command_sequence = GST_KATE_UINT16_BE (ptr); - ADVANCE (2); - GST_DEBUG_OBJECT (ke, "next command sequence at %u", next_command_sequence); - - while (sz) { - guint8 cmd = *ptr++; - switch (cmd) { - case SPU_CMD_FSTA_DSP: /* 0x00 */ - GST_DEBUG_OBJECT (ke, "[0] DISPLAY"); - break; - case SPU_CMD_DSP: /* 0x01 */ - GST_DEBUG_OBJECT (ke, "[1] SHOW"); - ke->show_time = date; - break; - case SPU_CMD_STP_DSP: /* 0x02 */ - GST_DEBUG_OBJECT (ke, "[2] HIDE"); - ke->hide_time = date; - break; - case SPU_CMD_SET_COLOR: /* 0x03 */ - GST_DEBUG_OBJECT (ke, "[3] SET COLOR"); - CHECK (2); - gst_kate_spu_decode_colormap (ke, ptr); - ADVANCE (2); - break; - case SPU_CMD_SET_ALPHA: /* 0x04 */ - GST_DEBUG_OBJECT (ke, "[4] SET ALPHA"); - CHECK (2); - gst_kate_spu_decode_alpha (ke, ptr); - ADVANCE (2); - break; - case SPU_CMD_SET_DAREA: /* 0x05 */ - GST_DEBUG_OBJECT (ke, "[5] SET DISPLAY AREA"); - CHECK (6); - gst_kate_spu_decode_area (ke, ptr); - ADVANCE (6); - break; - case SPU_CMD_DSPXA: /* 0x06 */ - GST_DEBUG_OBJECT (ke, "[6] SET PIXEL ADDRESSES"); - CHECK (4); - gst_kate_spu_decode_pixaddr (ke, ptr); - GST_DEBUG_OBJECT (ke, " -> first pixel address %u", - ke->spu_pix_data[0]); - GST_DEBUG_OBJECT (ke, " -> second pixel address %u", - ke->spu_pix_data[1]); - ADVANCE (4); - break; - case SPU_CMD_CHG_COLCON: /* 0x07 */ - GST_DEBUG_OBJECT (ke, "[7] CHANGE COLOR/CONTRAST"); - CHECK (2); - ADVANCE (gst_kate_spu_decode_colcon (ke, ptr, sz)); - break; - case SPU_CMD_END: /* 0xff */ - GST_DEBUG_OBJECT (ke, "[0xff] END"); - if (next_command_sequence != command_sequence_offset) { - GST_DEBUG_OBJECT (ke, "Jumping to next sequence at offset %u", - next_command_sequence); - gst_buffer_unmap (buf, &info); - return gst_kate_spu_decode_command_sequence (ke, buf, - next_command_sequence); - } else { - gst_buffer_unmap (buf, &info); - GST_DEBUG_OBJECT (ke, "No more sequences to decode"); - return GST_FLOW_OK; - } - break; - default: - gst_buffer_unmap (buf, &info); - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Invalid SPU command: %u", cmd)); - return GST_FLOW_ERROR; - } - } - gst_buffer_unmap (buf, &info); - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Error parsing SPU")); - return GST_FLOW_ERROR; - - /* ERRORS */ -out_of_range: - { - gst_buffer_unmap (buf, &info); - GST_ELEMENT_ERROR (ke, STREAM, DECODE, (NULL), - ("Command sequence offset %u is out of range %" G_GSIZE_FORMAT, - command_sequence_offset, info.size)); - return GST_FLOW_ERROR; - } -} - -static inline int -gst_kate_spu_clamp (int value) -{ - if (value < 0) - return 0; - if (value > 255) - return 255; - return value; -} - -static void -gst_kate_spu_yuv2rgb (int y, int u, int v, int *r, int *g, int *b) -{ -#if 0 - *r = gst_kate_spu_clamp (y + 1.371 * v); - *g = gst_kate_spu_clamp (y - 0.698 * v - 0.336 * u); - *b = gst_kate_spu_clamp (y + 1.732 * u); -#elif 0 - *r = gst_kate_spu_clamp (y + u); - *g = gst_kate_spu_clamp (y - (76 * u - 26 * v) / 256); - *b = gst_kate_spu_clamp (y + v); -#else - y = (y - 16) * 255 / 219; - u = (u - 128) * 255 / 224; - v = (v - 128) * 255 / 224; - - *r = gst_kate_spu_clamp (y + 1.402 * v); - *g = gst_kate_spu_clamp (y - 0.34414 * u - 0.71414 * v); - *b = gst_kate_spu_clamp (y + 1.772 * u); -#endif -} - -static GstFlowReturn -gst_kate_spu_create_spu_palette (GstKateEnc * ke, kate_palette * kp) -{ - size_t n; - - kate_palette_init (kp); - kp->ncolors = 4; - kp->colors = (kate_color *) g_malloc (kp->ncolors * sizeof (kate_color)); - if (G_UNLIKELY (!kp->colors)) { - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Out of memory")); - return GST_FLOW_ERROR; - } -#if 1 - for (n = 0; n < kp->ncolors; ++n) { - int idx = ke->spu_colormap[n]; - guint32 color = ke->spu_clut[idx]; - int y = (color >> 16) & 0xff; - int v = (color >> 8) & 0xff; - int u = color & 0xff; - int r, g, b; - gst_kate_spu_yuv2rgb (y, u, v, &r, &g, &b); - kp->colors[n].r = r; - kp->colors[n].g = g; - kp->colors[n].b = b; - kp->colors[n].a = ke->spu_alpha[n] * 17; - } -#else - /* just make a ramp from 0 to 255 for those non transparent colors */ - for (n = 0; n < kp->ncolors; ++n) - if (ke->spu_alpha[n] == 0) - ++ntrans; - - for (n = 0; n < kp->ncolors; ++n) { - kp->colors[n].r = luma; - kp->colors[n].g = luma; - kp->colors[n].b = luma; - kp->colors[n].a = ke->spu_alpha[n] * 17; - if (ke->spu_alpha[n]) - luma /= 2; - } -#endif - - return GST_FLOW_OK; -} - -GstFlowReturn -gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr, - kate_bitmap * kb, kate_palette * kp) -{ - GstMapInfo info; - const guint8 *ptr; - size_t sz; - guint16 packet_size; - guint16 x, y; - size_t n; - guint8 *pixptr[2]; - size_t nybble_offset[2]; - size_t max_nybbles[2]; - GstFlowReturn rflow; - guint16 next_command_sequence; - guint16 code; - - if (!gst_buffer_map (buf, &info, GST_MAP_READ)) { - GST_ERROR_OBJECT (ke, "Failed to map buffer"); - } - - ptr = info.data; - sz = info.size; - - /* before decoding anything, initialize to sensible defaults */ - memset (ke->spu_colormap, 0, sizeof (ke->spu_colormap)); - memset (ke->spu_alpha, 0, sizeof (ke->spu_alpha)); - ke->spu_top = ke->spu_left = 1; - ke->spu_bottom = ke->spu_right = 0; - ke->spu_pix_data[0] = ke->spu_pix_data[1] = 0; - ke->show_time = ke->hide_time = 0; - - /* read sizes and get to the start of the data */ - CHECK (2); - packet_size = GST_KATE_UINT16_BE (ptr); - ADVANCE (2); - GST_DEBUG_OBJECT (ke, "packet size %d (GstBuffer size %" G_GSIZE_FORMAT ")", - packet_size, info.size); - - CHECK (2); - next_command_sequence = GST_KATE_UINT16_BE (ptr); - ADVANCE (2); - ptr = info.data + next_command_sequence; - sz = info.size - next_command_sequence; - GST_DEBUG_OBJECT (ke, "next command sequence at %u for %u", - next_command_sequence, (guint) sz); - - rflow = gst_kate_spu_decode_command_sequence (ke, buf, next_command_sequence); - if (G_UNLIKELY (rflow != GST_FLOW_OK)) { - gst_buffer_unmap (buf, &info); - return rflow; - } - - /* if no addresses or sizes were given, or if they define an empty SPU, nothing more to do */ - if (G_UNLIKELY (ke->spu_right - ke->spu_left < 0 - || ke->spu_bottom - ke->spu_top < 0 || ke->spu_pix_data[0] == 0 - || ke->spu_pix_data[1] == 0)) { - GST_DEBUG_OBJECT (ke, - "left %d, right %d, top %d, bottom %d, pix data %d %d", ke->spu_left, - ke->spu_right, ke->spu_top, ke->spu_bottom, ke->spu_pix_data[0], - ke->spu_pix_data[1]); - GST_WARNING_OBJECT (ke, "SPU area is empty, nothing to encode"); - kate_bitmap_init (kb); - kb->width = kb->height = 0; - gst_buffer_unmap (buf, &info); - return GST_FLOW_OK; - } - - /* create the palette */ - rflow = gst_kate_spu_create_spu_palette (ke, kp); - if (G_UNLIKELY (rflow != GST_FLOW_OK)) { - gst_buffer_unmap (buf, &info); - return rflow; - } - - /* create the bitmap */ - kate_bitmap_init (kb); - kb->width = ke->spu_right - ke->spu_left + 1; - kb->height = ke->spu_bottom - ke->spu_top + 1; - kb->bpp = 2; - kb->type = kate_bitmap_type_paletted; - kb->pixels = (unsigned char *) g_malloc (kb->width * kb->height); - if (G_UNLIKELY (!kb->pixels)) { - gst_buffer_unmap (buf, &info); - GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), - ("Failed to allocate memory for pixel data")); - return GST_FLOW_ERROR; - } - - n = 0; - pixptr[0] = info.data + ke->spu_pix_data[0]; - pixptr[1] = info.data + ke->spu_pix_data[1]; - nybble_offset[0] = 0; - nybble_offset[1] = 0; - max_nybbles[0] = 2 * (packet_size - ke->spu_pix_data[0]); - max_nybbles[1] = 2 * (packet_size - ke->spu_pix_data[1]); - for (y = 0; y < kb->height; ++y) { - nybble_offset[y & 1] = GST_ROUND_UP_2 (nybble_offset[y & 1]); - for (x = 0; x < kb->width;) { - if (G_UNLIKELY (nybble_offset[y & 1] >= max_nybbles[y & 1])) { - GST_DEBUG_OBJECT (ke, "RLE overflow, clearing the remainder"); - memset (kb->pixels + n, 0, kb->width - x); - n += kb->width - x; - break; - } - code = gst_kate_spu_get_rle_code (pixptr[y & 1], &nybble_offset[y & 1]); - if (code == 0) { - memset (kb->pixels + n, 0, kb->width - x); - n += kb->width - x; - break; - } else { - guint16 npixels = code >> 2; - guint16 pixel = code & 3; - if (npixels > kb->width - x) { - npixels = kb->width - x; - } - memset (kb->pixels + n, pixel, npixels); - n += npixels; - x += npixels; - } - } - } - - GST_LOG_OBJECT (ke, "%u/%u bytes left in the data packet", - (guint) (max_nybbles[0] - nybble_offset[0]), - (guint) (max_nybbles[1] - nybble_offset[1])); - - /* some streams seem to have huge uncropped SPUs, fix those up */ - x = ke->spu_left; - y = ke->spu_top; - gst_kate_spu_crop_bitmap (ke, kb, &x, &y); - - /* create the region */ - kate_region_init (kr); - if (ke->original_canvas_width > 0 && ke->original_canvas_height > 0) { - /* prefer relative sizes in case we're encoding for a different resolution - that what the SPU was created for */ - kr->metric = kate_millionths; - kr->x = 1000000 * (size_t) x / ke->original_canvas_width; - kr->y = 1000000 * (size_t) y / ke->original_canvas_height; - kr->w = 1000000 * kb->width / ke->original_canvas_width; - kr->h = 1000000 * kb->height / ke->original_canvas_height; - } else { - kr->metric = kate_pixel; - kr->x = x; - kr->y = y; - kr->w = kb->width; - kr->h = kb->height; - } - - /* some SPUs have no hide time */ - if (ke->hide_time == 0) { - GST_INFO_OBJECT (ke, "SPU has no hide time"); - /* now, we don't know when the next SPU is scheduled to go, since we probably - haven't received it yet, so we'll just make it a 1 second delay, which is - probably going to end before the next one while being readable */ - //ke->hide_time = ke->show_time + (1000 * 90 / 1024); - } - gst_buffer_unmap (buf, &info); - - return GST_FLOW_OK; -} - -#undef IGNORE -#undef ADVANCE -#undef CHECK - -#undef GST_CAT_DEFAULT -#define GST_CAT_DEFAULT gst_katedec_debug - -static void -gst_kate_spu_add_nybble (unsigned char *bytes, size_t nbytes, int nybble_offset, - unsigned char nybble) -{ - unsigned char *ptr = bytes + nbytes + nybble_offset / 2; - if (!(nybble_offset & 1)) { - *ptr = nybble << 4; - } else { - *ptr |= nybble; - } -} - -static void -gst_kate_spu_rgb2yuv (int r, int g, int b, int *y, int *u, int *v) -{ - *y = gst_kate_spu_clamp (r * 0.299 * 219 / 255 + g * 0.587 * 219 / 255 + - b * 0.114 * 219 / 255 + 16); - *u = gst_kate_spu_clamp (-r * 0.16874 * 224 / 255 - g * 0.33126 * 224 / 255 + - b * 0.5 * 224 / 255 + 128); - *v = gst_kate_spu_clamp (r * 0.5 * 224 / 255 - g * 0.41869 * 224 / 255 - - b * 0.08131 * 224 / 255 + 128); -} - -static void -gst_kate_spu_make_palette (GstKateDec * kd, int palette[4], - const kate_palette * kp) -{ - int n; - GstStructure *structure; - GstEvent *event; - char name[16]; - int y, u, v; - - palette[0] = 0; - palette[1] = 1; - palette[2] = 2; - palette[3] = 3; - - structure = gst_structure_new ("application/x-gst-dvd", - "event", G_TYPE_STRING, "dvd-spu-clut-change", NULL); - - /* Create a separate field for each value in the table. */ - for (n = 0; n < 16; n++) { - guint32 color = 0; - if (n < 4) { - gst_kate_spu_rgb2yuv (kp->colors[n].r, kp->colors[n].g, kp->colors[n].b, - &y, &u, &v); - color = (y << 16) | (v << 8) | u; - } - g_snprintf (name, sizeof (name), "clut%02d", n); - gst_structure_set (structure, name, G_TYPE_INT, (int) color, NULL); - } - - /* Create the DVD event and put the structure into it. */ - event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, structure); - - GST_LOG_OBJECT (kd, "preparing clut change event %" GST_PTR_FORMAT, event); - gst_pad_push_event (kd->srcpad, event); -} - -GstBuffer * -gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev) -{ - kate_tracker kin; - unsigned char *bytes = NULL; - size_t nbytes = 0; - GstBuffer *buffer = NULL; - int ret; - int ocw, och; - int top, left, right, bottom; - int pass, line, row; - int lines_offset[2]; - int first_commands_offset, second_commands_offset; - int nybble_count; - const kate_bitmap *kb; - const kate_palette *kp; - int palette[4]; - int delay; - - /* we need a region, a bitmap, and a palette */ - if (!ev || !ev->region || !ev->bitmap || !ev->palette) - return NULL; - - kb = ev->bitmap; - kp = ev->palette; - - /* these need particular properties */ - if (kb->type != kate_bitmap_type_paletted || kb->bpp != 2) - return NULL; - if (kp->ncolors != 4) - return NULL; - - ret = kate_tracker_init (&kin, ev->ki, ev); - if (ret < 0) { - GST_WARNING_OBJECT (kd, "Failed to initialize kate tracker"); - return NULL; - } - - ocw = ev->ki->original_canvas_width; - och = ev->ki->original_canvas_height; - ret = kate_tracker_update (&kin, (kate_float) 0, ocw, och, 0, 0, ocw, och); - if (ret < 0) - goto error; - - if (kin.has.region) { - top = (int) (kin.region_y + (kate_float) 0.5); - left = (int) (kin.region_x + (kate_float) 0.5); - } else { - GST_WARNING_OBJECT (kd, - "No region information to place SPU, placing at 0 0"); - top = left = 0; - } - right = left + kb->width - 1; - bottom = top + kb->height - 1; - - /* Allocate space to build the SPU */ - bytes = g_malloc (MAX_SPU_SIZE); - if (G_UNLIKELY (!bytes)) { - GST_WARNING_OBJECT (kd, - "Failed to allocate %" G_GSIZE_FORMAT " byte buffer", nbytes); - goto error; - } - nbytes = 4; - nybble_count = 0; - -#define CHKBUFSPC(nybbles) \ - do { \ - if ((nbytes + (nybbles + nybble_count + 1) / 2) > MAX_SPU_SIZE) { \ - GST_WARNING_OBJECT (kd, "Not enough space in SPU buffer"); \ - goto error; \ - } \ - } while(0) - - /* encode lines */ - for (pass = 0; pass <= 1; ++pass) { - lines_offset[pass] = nbytes; - for (line = pass; line < bottom - top + 1; line += 2) { - const unsigned char *ptr = kb->pixels + line * kb->width; - for (row = 0; row < kb->width;) { - int run = 1; - while (row + run < kb->width && run < 255 && ptr[row + run] == ptr[row]) - ++run; - if (run >= 63 && row + run == kb->width) { - /* special end of line marker */ - CHKBUFSPC (4); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, ptr[row]); - } else if (run >= 1 && run <= 3) { - CHKBUFSPC (1); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, - (run << 2) | ptr[row]); - } else if (run <= 15) { - CHKBUFSPC (2); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, run >> 2); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, - ((run & 3) << 2) | ptr[row]); - } else if (run <= 63) { - CHKBUFSPC (3); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, run >> 2); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, - ((run & 3) << 2) | ptr[row]); - } else { - CHKBUFSPC (4); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, (run >> 6)); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, - (run >> 2) & 0xf); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, - ((run & 3) << 2) | ptr[row]); - } - row += run; - } - if (nybble_count & 1) { - CHKBUFSPC (1); - gst_kate_spu_add_nybble (bytes, nbytes, nybble_count++, 0); - } - nbytes += nybble_count / 2; - nybble_count = 0; - } - } - first_commands_offset = nbytes; - - gst_kate_spu_make_palette (kd, palette, kp); - - /* Commands header */ - CHKBUFSPC (4 * 2); - bytes[nbytes++] = 0; - bytes[nbytes++] = 0; - /* link to next command chunk will be filled later, when we know where it is */ - bytes[nbytes++] = 0; - bytes[nbytes++] = 0; - - CHKBUFSPC (3 * 2); - bytes[nbytes++] = SPU_CMD_SET_COLOR; - bytes[nbytes++] = (palette[3] << 4) | palette[2]; - bytes[nbytes++] = (palette[1] << 4) | palette[0]; - - CHKBUFSPC (3 * 2); - bytes[nbytes++] = SPU_CMD_SET_ALPHA; - bytes[nbytes++] = - ((kp->colors[palette[3]].a / 17) << 4) | (kp->colors[palette[2]].a / 17); - bytes[nbytes++] = - ((kp->colors[palette[1]].a / 17) << 4) | (kp->colors[palette[0]].a / 17); - - CHKBUFSPC (7 * 2); - bytes[nbytes++] = SPU_CMD_SET_DAREA; - bytes[nbytes++] = left >> 4; - bytes[nbytes++] = ((left & 0xf) << 4) | (right >> 8); - bytes[nbytes++] = right & 0xff; - bytes[nbytes++] = top >> 4; - bytes[nbytes++] = ((top & 0xf) << 4) | (bottom >> 8); - bytes[nbytes++] = bottom & 0xff; - - CHKBUFSPC (5 * 2); - bytes[nbytes++] = SPU_CMD_DSPXA; - bytes[nbytes++] = (lines_offset[0] >> 8) & 0xff; - bytes[nbytes++] = lines_offset[0] & 0xff; - bytes[nbytes++] = (lines_offset[1] >> 8) & 0xff; - bytes[nbytes++] = lines_offset[1] & 0xff; - - CHKBUFSPC (1 * 2); - bytes[nbytes++] = SPU_CMD_DSP; - - CHKBUFSPC (1 * 2); - bytes[nbytes++] = SPU_CMD_END; - - /* stop display chunk */ - CHKBUFSPC (4 * 2); - second_commands_offset = nbytes; - bytes[first_commands_offset + 2] = (second_commands_offset >> 8) & 0xff; - bytes[first_commands_offset + 3] = second_commands_offset & 0xff; - delay = GST_KATE_GST_TO_STM (ev->end_time - ev->start_time); - bytes[nbytes++] = (delay >> 8) & 0xff; - bytes[nbytes++] = delay & 0xff; - /* close the loop by linking back to self */ - bytes[nbytes++] = (second_commands_offset >> 8) & 0xff; - bytes[nbytes++] = second_commands_offset & 0xff; - - CHKBUFSPC (1 * 2); - bytes[nbytes++] = SPU_CMD_STP_DSP; - - CHKBUFSPC (1 * 2); - bytes[nbytes++] = SPU_CMD_END; - - /* Now that we know the size of the SPU, update the size and pointers */ - bytes[0] = (nbytes >> 8) & 0xff; - bytes[1] = nbytes & 0xff; - bytes[2] = (first_commands_offset >> 8) & 0xff; - bytes[3] = first_commands_offset & 0xff; - - /* Create a buffer with those values */ - buffer = gst_buffer_new_wrapped (bytes, nbytes); - if (G_UNLIKELY (!buffer)) { - GST_WARNING_OBJECT (kd, - "Failed to allocate %" G_GSIZE_FORMAT " byte buffer", nbytes); - goto error; - } - GST_BUFFER_OFFSET_END (buffer) = GST_SECOND * (ev->end_time); - GST_BUFFER_OFFSET (buffer) = GST_SECOND * (ev->start_time); - GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND * (ev->start_time); - GST_BUFFER_DURATION (buffer) = GST_SECOND * (ev->end_time - ev->start_time); - - GST_DEBUG_OBJECT (kd, "SPU uses %" G_GSIZE_FORMAT " bytes", nbytes); - - kate_tracker_clear (&kin); - return buffer; - -error: - kate_tracker_clear (&kin); - g_free (bytes); - return NULL; -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatespu.h b/subprojects/gst-plugins-bad/ext/kate/gstkatespu.h deleted file mode 100644 index beb8728d7e..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatespu.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c-basic-offset: 2 -*- - * GStreamer - * Copyright (C) <2009> ogg.k.ogg.k - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef __GST_KATE_SPU_H__ -#define __GST_KATE_SPU_H__ - -#include -#include -#include "gstkateenc.h" -#include "gstkatedec.h" - -#define GST_KATE_UINT16_BE(ptr) ( ( ((guint16)((ptr)[0])) <<8) | ((ptr)[1]) ) - -/* taken off the DVD SPU decoder - now is time for today's WTF ???? */ -#define GST_KATE_STM_TO_GST(stm) ((GST_MSECOND * 1024 * (stm)) / 90) -#define GST_KATE_GST_TO_STM(gst) ((int)(((gst) * 90000 ) / 1024)) - -#define GST_KATE_SPU_MIME_TYPE "subpicture/x-dvd" - -G_BEGIN_DECLS - -enum GstKateSpuCmd -{ - SPU_CMD_FSTA_DSP = 0x00, /* Forced Display */ - SPU_CMD_DSP = 0x01, /* Display Start */ - SPU_CMD_STP_DSP = 0x02, /* Display Off */ - SPU_CMD_SET_COLOR = 0x03, /* Set the color indexes for the palette */ - SPU_CMD_SET_ALPHA = 0x04, /* Set the alpha indexes for the palette */ - SPU_CMD_SET_DAREA = 0x05, /* Set the display area for the SPU */ - SPU_CMD_DSPXA = 0x06, /* Pixel data addresses */ - SPU_CMD_CHG_COLCON = 0x07, /* Change Color & Contrast */ - SPU_CMD_END = 0xff -}; - - -extern const guint32 gst_kate_spu_default_clut[16]; - -extern GstFlowReturn -gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr, - kate_bitmap * kb, kate_palette * kp); - -extern GstBuffer* -gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev); - -G_END_DECLS - -#endif /* __GST_KATE_SPU_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatetag.c b/subprojects/gst-plugins-bad/ext/kate/gstkatetag.c deleted file mode 100644 index 80c2680638..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatetag.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2006 James Livingston - * Copyright (C) 2008 Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-katetag - * @title: katetag - * @see_also: #oggdemux, #oggmux, #kateparse, #GstTagSetter - * @short_description: retags kate streams - * - * The katetag element can change the tag contained within a raw - * kate stream. Specifically, it modifies the comments header packet - * of the kate stream, as well as the language and category of the - * kate stream. - * - * The element will also process the stream as the #kateparse element does - * so it can be used when remuxing an Ogg Kate stream, without additional - * elements. - * - * Applications can set the tags to write using the #GstTagSetter interface. - * Tags contained within the kate stream will be picked up - * automatically (and merged according to the merge mode set via the tag - * setter interface). - * - * ## Example pipelines - * - * This element is only useful with gst-launch-1.0 for modifying the language - * and/or category (which are properties of the stream located in the kate - * beginning of stream header), because it does not support setting the tags - * on a #GstTagSetter interface. Conceptually, the element will usually be - * used like: - * |[ - * gst-launch-1.0 -v filesrc location=foo.ogg ! oggdemux ! katetag ! oggmux ! filesink location=bar.ogg - * ]| - * - * This pipeline will set the language and category of the stream to the - * given values: - * |[ - * gst-launch-1.0 -v filesrc location=foo.ogg ! oggdemux ! katetag language=pt_BR category=subtitles ! oggmux ! filesink location=bar.ogg - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include -#include -#include - -#include - -#include "gstkateelements.h" -#include "gstkatetag.h" - - -GST_DEBUG_CATEGORY_EXTERN (gst_katetag_debug); -#define GST_CAT_DEFAULT gst_katetag_debug - -enum -{ - ARG_0, - ARG_LANGUAGE, - ARG_CATEGORY, - ARG_ORIGINAL_CANVAS_WIDTH, - ARG_ORIGINAL_CANVAS_HEIGHT, -}; - -static GstFlowReturn gst_kate_tag_parse_packet (GstKateParse * parse, - GstBuffer * buffer); -static void gst_kate_tag_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_kate_tag_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_kate_tag_dispose (GObject * object); - -GST_DEBUG_CATEGORY (gst_katetag_debug); -#define gst_kate_tag_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstKateTag, gst_kate_tag, GST_TYPE_KATE_PARSE, - G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL)); -#define _do_init \ - kate_element_init (plugin); \ - GST_DEBUG_CATEGORY_INIT (gst_katetag_debug, "katetag", 0, "Kate tagger"); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (katetag, "katetag", GST_RANK_NONE, - GST_TYPE_KATE_TAG, _do_init); - -static void -gst_kate_tag_class_init (GstKateTagClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstKateParseClass *gstkateparse_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstkateparse_class = GST_KATE_PARSE_CLASS (klass); - - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_tag_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_tag_get_property); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_tag_dispose); - - g_object_class_install_property (gobject_class, ARG_LANGUAGE, - g_param_spec_string ("language", "Language", - "Set the language of the stream", "", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_CATEGORY, - g_param_spec_string ("category", "Category", - "Set the category of the stream", "", - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_WIDTH, - g_param_spec_int ("original-canvas-width", "Original canvas width", - "Set the width of the canvas this stream was authored for (0 is unspecified)", - 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_ORIGINAL_CANVAS_HEIGHT, - g_param_spec_int ("original-canvas-height", "Original canvas height", - "Set the height of the canvas this stream was authored for (0 is unspecified)", - 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_static_metadata (gstelement_class, "Kate stream tagger", - "Formatter/Metadata", - "Retags kate streams", "Vincent Penquerc'h "); - - gstkateparse_class->parse_packet = - GST_DEBUG_FUNCPTR (gst_kate_tag_parse_packet); -} - -static void -gst_kate_tag_init (GstKateTag * kt) -{ - kt->language = NULL; - kt->category = NULL; - kt->original_canvas_width = -1; - kt->original_canvas_height = -1; -} - -static void -gst_kate_tag_dispose (GObject * object) -{ - GstKateTag *kt = GST_KATE_TAG (object); - - GST_LOG_OBJECT (kt, "disposing"); - - if (kt->language) { - g_free (kt->language); - kt->language = NULL; - } - if (kt->category) { - g_free (kt->category); - kt->category = NULL; - } - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); -} - -static void -gst_kate_tag_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstKateTag *kt = GST_KATE_TAG (object); - const char *str; - - switch (prop_id) { - case ARG_LANGUAGE: - if (kt->language) { - g_free (kt->language); - kt->language = NULL; - } - str = g_value_get_string (value); - if (str) - kt->language = g_strdup (str); - break; - case ARG_CATEGORY: - if (kt->category) { - g_free (kt->category); - kt->category = NULL; - } - str = g_value_get_string (value); - if (str) - kt->category = g_strdup (str); - break; - case ARG_ORIGINAL_CANVAS_WIDTH: - kt->original_canvas_width = g_value_get_int (value); - break; - case ARG_ORIGINAL_CANVAS_HEIGHT: - kt->original_canvas_height = g_value_get_int (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_kate_tag_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstKateTag *kt = GST_KATE_TAG (object); - - switch (prop_id) { - case ARG_LANGUAGE: - g_value_set_string (value, kt->language ? kt->language : ""); - break; - case ARG_CATEGORY: - g_value_set_string (value, kt->category ? kt->category : ""); - break; - case ARG_ORIGINAL_CANVAS_WIDTH: - g_value_set_int (value, kt->original_canvas_width); - break; - case ARG_ORIGINAL_CANVAS_HEIGHT: - g_value_set_int (value, kt->original_canvas_height); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static guint16 -encode_canvas_size (size_t size) -{ - size_t base = size; - size_t shift = 0; - int value; - - while (base & ~((1 << 12) - 1)) { - /* we have a high bit we can't fit, increase shift if we wouldn't lose low bits */ - if ((size >> shift) & 1) - return 0; - ++shift; - base >>= 1; - } - if (G_UNLIKELY (shift >= 16)) - return 0; - - /* the size can be represented in our encoding */ - value = (base << 4) | shift; - - return (guint16) value; -} - -static GstFlowReturn -gst_kate_tag_parse_packet (GstKateParse * parse, GstBuffer * buffer) -{ - GstTagList *old_tags, *new_tags; - const GstTagList *user_tags; - GstKateTag *kt; - gchar *encoder = NULL; - GstBuffer *new_buf; - GstMapInfo info; - - kt = GST_KATE_TAG (parse); - - if (!gst_buffer_map (buffer, &info, GST_MAP_READ)) { - GST_ERROR_OBJECT (parse, "Failed to map buffer"); - return GST_FLOW_ERROR; - } - - /* rewrite the language and category */ - if (info.size >= 64 && info.data[0] == 0x80) { - GstBuffer *new_buffer; - - gst_buffer_unmap (buffer, &info); - new_buffer = gst_buffer_copy (buffer); - gst_buffer_unref (buffer); - buffer = new_buffer; - - if (!gst_buffer_map (buffer, &info, GST_MAP_READWRITE)) { - GST_ERROR_OBJECT (parse, "Failed to map copied buffer READWRITE"); - return GST_FLOW_ERROR; - } - /* language is at offset 32, 16 bytes, zero terminated */ - if (kt->language) { - strncpy ((char *) info.data + 32, kt->language, 15); - info.data[47] = 0; - } - /* category is at offset 48, 16 bytes, zero terminated */ - if (kt->category) { - strncpy ((char *) info.data + 48, kt->category, 15); - info.data[63] = 0; - } - if (kt->original_canvas_width >= 0) { - guint16 v = encode_canvas_size (kt->original_canvas_width); - info.data[16] = v & 0xff; - info.data[17] = (v >> 8) & 0xff; - } - if (kt->original_canvas_height >= 0) { - guint16 v = encode_canvas_size (kt->original_canvas_height); - info.data[18] = v & 0xff; - info.data[19] = (v >> 8) & 0xff; - } - } - - /* rewrite the comments packet */ - if (info.size >= 9 && info.data[0] == 0x81) { - old_tags = - gst_tag_list_from_vorbiscomment (info.data, info.size, - (const guint8 *) "\201kate\0\0\0\0", 9, &encoder); - user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (kt)); - gst_buffer_unmap (buffer, &info); - - /* build new tag list */ - new_tags = gst_tag_list_merge (user_tags, old_tags, - gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (kt))); - gst_tag_list_unref (old_tags); - - new_buf = - gst_tag_list_to_vorbiscomment_buffer (new_tags, - (const guint8 *) "\201kate\0\0\0\0", 9, encoder); - gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1); - - gst_tag_list_unref (new_tags); - g_free (encoder); - gst_buffer_unref (buffer); - - /* the buffer will have the framing bit used by Vorbis, but we don't use it */ - gst_buffer_resize (new_buf, 0, gst_buffer_get_size (new_buf) - 1); - - buffer = new_buf; - } else { - gst_buffer_unmap (buffer, &info); - } - - return GST_KATE_PARSE_CLASS (parent_class)->parse_packet (parse, buffer); -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatetag.h b/subprojects/gst-plugins-bad/ext/kate/gstkatetag.h deleted file mode 100644 index f2f24641f3..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatetag.h +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- c-basic-offset: 2 -*- - * GStreamer - * Copyright (C) <2006> James Livingston - * Copyright (C) <2008> Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef __GST_KATE_TAG_H__ -#define __GST_KATE_TAG_H__ - -#include "gstkateparse.h" - -G_BEGIN_DECLS -#define GST_TYPE_KATE_TAG \ - (gst_kate_tag_get_type()) -#define GST_KATE_TAG(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KATE_TAG,GstKateTag)) -#define GST_KATE_TAG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE_TAG,GstKateTagClass)) -#define GST_IS_KATE_TAG(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_TAG)) -#define GST_IS_KATE_TAG_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_TAG)) -typedef struct _GstKateTag GstKateTag; -typedef struct _GstKateTagClass GstKateTagClass; - -/** - * GstKateTag: - * - * Opaque data structure. - */ -struct _GstKateTag -{ - GstKateParse parse; - - gchar *language; - gchar *category; - gint original_canvas_width; - gint original_canvas_height; -}; - -struct _GstKateTagClass -{ - GstKateParseClass parent_class; -}; - -GType gst_kate_tag_get_type (void); - -G_END_DECLS -#endif /* __GST_KATE_TAG_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.c b/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.c deleted file mode 100644 index d2b70f9214..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.c +++ /dev/null @@ -1,1221 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:element-tiger - * @title: tiger - * @see_also: katedec - * - * This element decodes and renders Kate streams. - * [Kate](http://libkate.googlecode.com/) is a free codec for text based data, - * such as subtitles. Any number of kate streams can be embedded in an Ogg - * stream. - * - * libkate (see above url) and [libtiger](http://libtiger.googlecode.com/) - * are needed to build this element. - * - * ## Example pipeline - * - * This pipeline renders a Kate stream on top of a Theora video multiplexed - * in the same stream: - * |[ - * gst-launch-1.0 \ - * filesrc location=video.ogg ! oggdemux name=demux \ - * demux. ! queue ! theoradec ! videoconvert ! tiger name=tiger \ - * demux. ! queue ! kateparse ! tiger. \ - * tiger. ! videoconvert ! autovideosink - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include -#include -#include - -#include "gstkateelements.h" -#include "gstkatetiger.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_katetiger_debug); -#define GST_CAT_DEFAULT gst_katetiger_debug - -#define GST_KATE_TIGER_MUTEX_LOCK(element) \ - do { \ - /*GST_LOG_OBJECT ((element), "locking from %s:%d",__FILE__,__LINE__);*/ \ - g_mutex_lock ((element)->mutex); \ - /*GST_LOG_OBJECT ((element), "ready from %s:%d",__FILE__,__LINE__);*/ \ - } while(0) - -#define GST_KATE_TIGER_MUTEX_UNLOCK(element) \ - do { \ - /*GST_LOG_OBJECT ((element), "unlocking from %s:%d",__FILE__,__LINE__);*/ \ - g_mutex_unlock ((element)->mutex); \ - } while(0) - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_DEFAULT_FONT_DESC = DECODER_BASE_ARG_COUNT, - ARG_QUALITY, - ARG_DEFAULT_FONT_EFFECT, - ARG_DEFAULT_FONT_EFFECT_STRENGTH, - ARG_DEFAULT_FONT_RED, - ARG_DEFAULT_FONT_GREEN, - ARG_DEFAULT_FONT_BLUE, - ARG_DEFAULT_FONT_ALPHA, - ARG_DEFAULT_BACKGROUND_RED, - ARG_DEFAULT_BACKGROUND_GREEN, - ARG_DEFAULT_BACKGROUND_BLUE, - ARG_DEFAULT_BACKGROUND_ALPHA, - ARG_SILENT -}; - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -# define TIGER_ARGB_A 3 -# define TIGER_ARGB_R 2 -# define TIGER_ARGB_G 1 -# define TIGER_ARGB_B 0 -#else -# define TIGER_ARGB_A 0 -# define TIGER_ARGB_R 1 -# define TIGER_ARGB_G 2 -# define TIGER_ARGB_B 3 -#endif - -#define TIGER_UNPREMULTIPLY(a,r,g,b) G_STMT_START { \ - b = (a > 0) ? MIN ((b * 255 + a / 2) / a, 255) : 0; \ - g = (a > 0) ? MIN ((g * 255 + a / 2) / a, 255) : 0; \ - r = (a > 0) ? MIN ((r * 255 + a / 2) / a, 255) : 0; \ -} G_STMT_END - -static GstStaticPadTemplate kate_sink_factory = - GST_STATIC_PAD_TEMPLATE ("subtitle_sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") - ); - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -#define TIGER_VIDEO_CAPS \ - GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_BGRx ";" \ - GST_VIDEO_CAPS_YUV ("{I420, YV12, AYUV, YUY2, UYVY, v308, v210," \ - " v216, Y41B, Y42B, Y444, Y800, Y16, NV12, NV21, UYVP, A420," \ - " YUV9, IYU1}") - -#else -#define TIGER_VIDEO_CAPS \ - GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xRGB ";" \ - GST_VIDEO_CAPS_YUV ("{I420, YV12, AYUV, YUY2, UYVY, v308, v210," \ - " v216, Y41B, Y42B, Y444, Y800, Y16, NV12, NV21, UYVP, A420," \ - " YUV9, IYU1}") -#endif - -static GstStaticPadTemplate video_sink_factory = -GST_STATIC_PAD_TEMPLATE ("video_sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (TIGER_VIDEO_CAPS)); - -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (TIGER_VIDEO_CAPS)); - -GST_DEBUG_CATEGORY (gst_katetiger_debug); - -GST_BOILERPLATE (GstKateTiger, gst_kate_tiger, GstElement, GST_TYPE_ELEMENT); -#define _do_init \ - kate_element_init (plugin); \ - GST_DEBUG_CATEGORY_INIT (gst_katetiger_debug, "tiger", 0, \ - "Kate Tiger renderer"); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (tiger, "tiger", GST_RANK_NONE, - GST_TYPE_KATE_TIGER, _do_init); - -static GType -gst_kate_tiger_font_effect_get_type (void) -{ - static GType font_effect_type = 0; - - if (!font_effect_type) { - static const GEnumValue font_effects[] = { - {tiger_font_plain, "none", "none"}, - {tiger_font_shadow, "shadow", "shadow"}, - {tiger_font_outline, "outline", "outline"}, - {0, NULL, NULL} - }; - font_effect_type = g_enum_register_static ("GstFontEffect", font_effects); - } - - return font_effect_type; -} - -static void gst_kate_tiger_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_kate_tiger_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); -static void gst_kate_tiger_dispose (GObject * object); - -static GstFlowReturn gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf); -static GstFlowReturn gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf); -static GstStateChangeReturn gst_kate_tiger_change_state (GstElement * element, - GstStateChange transition); -static gboolean gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query); -static gboolean gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event); -static gboolean gst_kate_tiger_video_event (GstPad * pad, GstEvent * event); -static gboolean gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps); -static gboolean gst_kate_tiger_source_event (GstPad * pad, GstEvent * event); - -static void -gst_kate_tiger_base_init (gpointer gclass) -{ - - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_static_pad_template (element_class, &src_factory); - gst_element_class_add_static_pad_template (element_class, &kate_sink_factory); - gst_element_class_add_static_pad_template (element_class, - &video_sink_factory); - gst_element_class_set_static_metadata (element_class, "Kate stream renderer", - "Mixer/Video/Overlay/Subtitle", - "Decodes and renders Kate streams on top of a video", - "Vincent Penquerc'h "); -} - -/* initialize the plugin's class */ -static void -gst_kate_tiger_class_init (GstKateTigerClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_tiger_get_property); - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_tiger_set_property); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_tiger_dispose); - - gst_kate_util_install_decoder_base_properties (gobject_class); - - g_object_class_install_property (gobject_class, ARG_QUALITY, - g_param_spec_double ("quality", "Rendering quality", - "Rendering quality (0 is faster, 1 is best and slower)", - 0.0, 1.0, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_DESC, - g_param_spec_string ("default-font-desc", "Default font description", - "Default font description (Pango style) to render text with", - "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_EFFECT, - g_param_spec_enum ("default-font-effect", "Default font effect", - "Whether to apply an effect to text by default, for increased readability", - gst_kate_tiger_font_effect_get_type (), - tiger_font_outline, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - ARG_DEFAULT_FONT_EFFECT_STRENGTH, - g_param_spec_double ("default-font-effect-strength", - "Default font effect strength", - "How pronounced should the font effect be (effect dependent)", 0.0, - 1.0, 0.5, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_RED, - g_param_spec_int ("default-font-red", - "Default font color (red component)", - "Default font color (red component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_GREEN, - g_param_spec_int ("default-font-green", - "Default font color (green component)", - "Default font color (green component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_BLUE, - g_param_spec_int ("default-font-blue", - "Default font color (blue component)", - "Default font color (blue component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_FONT_ALPHA, - g_param_spec_int ("default-font-alpha", - "Default font color (alpha component)", - "Default font color (alpha component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_BACKGROUND_RED, - g_param_spec_int ("default-background-red", - "Default background color (red component)", - "Default background color (red component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_BACKGROUND_GREEN, - g_param_spec_int ("default-background-green", - "Default background color (green component)", - "Default background color (green component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_BACKGROUND_BLUE, - g_param_spec_int ("default-background-blue", - "Default background color (blue component)", - "Default background color (blue component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEFAULT_BACKGROUND_ALPHA, - g_param_spec_int ("default-background-alpha", - "Default background color (alpha component)", - "Default background color (alpha component, between 0 and 255) to render text with", - 0, 255, 255, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* FIXME 0.11: rename to "visible" or "text-visible" or "render-text" */ - g_object_class_install_property (gobject_class, ARG_SILENT, - g_param_spec_boolean ("silent", "silent", - "Whether to render the stream", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_kate_tiger_change_state); -} - -/* initialize the new element - * instantiate pads and add them to element - * set functions - * initialize structure - */ -static void -gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) -{ - GST_DEBUG_OBJECT (tiger, "gst_kate_tiger_init"); - - tiger->mutex = g_mutex_new (); - tiger->cond = g_cond_new (); - - tiger->katesinkpad = - gst_pad_new_from_static_template (&kate_sink_factory, "subtitle_sink"); - gst_pad_set_chain_function (tiger->katesinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_kate_chain)); - gst_pad_set_query_function (tiger->katesinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_kate_sink_query)); - gst_pad_set_event_function (tiger->katesinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_kate_event)); - gst_element_add_pad (GST_ELEMENT (tiger), tiger->katesinkpad); - - tiger->videosinkpad = - gst_pad_new_from_static_template (&video_sink_factory, "video_sink"); - gst_pad_set_chain_function (tiger->videosinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_video_chain)); - gst_pad_use_fixed_caps (tiger->videosinkpad); - gst_pad_set_setcaps_function (tiger->videosinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_video_set_caps)); - gst_pad_set_event_function (tiger->videosinkpad, - GST_DEBUG_FUNCPTR (gst_kate_tiger_video_event)); - gst_element_add_pad (GST_ELEMENT (tiger), tiger->videosinkpad); - - tiger->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); - gst_pad_set_event_function (tiger->srcpad, gst_kate_tiger_source_event); - gst_pad_use_fixed_caps (tiger->srcpad); - gst_element_add_pad (GST_ELEMENT (tiger), tiger->srcpad); - - gst_kate_util_decode_base_init (&tiger->decoder, FALSE); - - tiger->tr = NULL; - - tiger->default_font_desc = NULL; - tiger->quality = -1.0; - tiger->default_font_effect = tiger_font_outline; - tiger->default_font_effect_strength = 0.5; - tiger->default_font_r = 255; - tiger->default_font_g = 255; - tiger->default_font_b = 255; - tiger->default_font_a = 255; - tiger->default_background_r = 0; - tiger->default_background_g = 0; - tiger->default_background_b = 0; - tiger->default_background_a = 0; - tiger->silent = FALSE; - - tiger->video_width = 0; - tiger->video_height = 0; - - tiger->composition = NULL; - - tiger->seen_header = FALSE; -} - -static void -gst_kate_tiger_dispose (GObject * object) -{ - GstKateTiger *tiger = GST_KATE_TIGER (object); - - GST_LOG_OBJECT (tiger, "disposing"); - - if (tiger->default_font_desc) { - g_free (tiger->default_font_desc); - tiger->default_font_desc = NULL; - } - - if (tiger->render_buffer) { - gst_buffer_unref (tiger->render_buffer); - tiger->render_buffer = NULL; - } - - g_cond_free (tiger->cond); - tiger->cond = NULL; - - g_mutex_free (tiger->mutex); - tiger->mutex = NULL; - - if (tiger->composition) { - gst_video_overlay_composition_unref (tiger->composition); - tiger->composition = NULL; - } - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); -} - -static void -gst_kate_tiger_update_quality (GstKateTiger * tiger) -{ - if (tiger->tr && tiger->quality >= 0.0) { - tiger_renderer_set_quality (tiger->tr, tiger->quality); - } -} - -static void -gst_kate_tiger_update_default_font_effect (GstKateTiger * tiger) -{ - if (tiger->tr) { - tiger_renderer_set_default_font_effect (tiger->tr, - tiger->default_font_effect, tiger->default_font_effect_strength); - } -} - -static void -gst_kate_tiger_update_default_font_color (GstKateTiger * tiger) -{ - if (tiger->tr) { - tiger_renderer_set_default_font_color (tiger->tr, - tiger->default_font_r / 255.0, - tiger->default_font_g / 255.0, - tiger->default_font_b / 255.0, tiger->default_font_a / 255.0); - } -} - -static void -gst_kate_tiger_update_default_background_color (GstKateTiger * tiger) -{ - if (tiger->tr) { - tiger_renderer_set_default_background_fill_color (tiger->tr, - tiger->default_background_r / 255.0, - tiger->default_background_g / 255.0, - tiger->default_background_b / 255.0, - tiger->default_background_a / 255.0); - } -} - -static void -gst_kate_tiger_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstKateTiger *tiger = GST_KATE_TIGER (object); - const char *str; - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - - switch (prop_id) { - case ARG_DEFAULT_FONT_DESC: - if (tiger->default_font_desc) { - g_free (tiger->default_font_desc); - tiger->default_font_desc = NULL; - } - str = g_value_get_string (value); - if (str) { - tiger->default_font_desc = g_strdup (str); - if (tiger->tr) - tiger_renderer_set_default_font_description (tiger->tr, - tiger->default_font_desc); - } - break; - case ARG_QUALITY: - tiger->quality = g_value_get_double (value); - gst_kate_tiger_update_quality (tiger); - break; - case ARG_DEFAULT_FONT_EFFECT: - tiger->default_font_effect = g_value_get_enum (value); - gst_kate_tiger_update_default_font_effect (tiger); - break; - case ARG_DEFAULT_FONT_EFFECT_STRENGTH: - tiger->default_font_effect_strength = g_value_get_double (value); - gst_kate_tiger_update_default_font_effect (tiger); - break; - case ARG_DEFAULT_FONT_RED: - tiger->default_font_r = g_value_get_int (value); - gst_kate_tiger_update_default_font_color (tiger); - break; - case ARG_DEFAULT_FONT_GREEN: - tiger->default_font_g = g_value_get_int (value); - gst_kate_tiger_update_default_font_color (tiger); - break; - case ARG_DEFAULT_FONT_BLUE: - tiger->default_font_b = g_value_get_int (value); - gst_kate_tiger_update_default_font_color (tiger); - break; - case ARG_DEFAULT_FONT_ALPHA: - tiger->default_font_a = g_value_get_int (value); - gst_kate_tiger_update_default_font_color (tiger); - break; - case ARG_DEFAULT_BACKGROUND_RED: - tiger->default_background_r = g_value_get_int (value); - gst_kate_tiger_update_default_background_color (tiger); - break; - case ARG_DEFAULT_BACKGROUND_GREEN: - tiger->default_background_g = g_value_get_int (value); - gst_kate_tiger_update_default_background_color (tiger); - break; - case ARG_DEFAULT_BACKGROUND_BLUE: - tiger->default_background_b = g_value_get_int (value); - gst_kate_tiger_update_default_background_color (tiger); - break; - case ARG_DEFAULT_BACKGROUND_ALPHA: - tiger->default_background_a = g_value_get_int (value); - gst_kate_tiger_update_default_background_color (tiger); - break; - case ARG_SILENT: - tiger->silent = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); -} - -static void -gst_kate_tiger_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstKateTiger *tiger = GST_KATE_TIGER (object); - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - - switch (prop_id) { - case ARG_DEFAULT_FONT_DESC: - g_value_set_string (value, - tiger->default_font_desc ? tiger->default_font_desc : ""); - break; - case ARG_QUALITY: - g_value_set_double (value, tiger->quality); - break; - case ARG_DEFAULT_FONT_EFFECT: - g_value_set_enum (value, tiger->default_font_effect); - break; - case ARG_DEFAULT_FONT_EFFECT_STRENGTH: - g_value_set_double (value, tiger->default_font_effect_strength); - break; - case ARG_DEFAULT_FONT_RED: - g_value_set_int (value, tiger->default_font_r); - break; - case ARG_DEFAULT_FONT_GREEN: - g_value_set_int (value, tiger->default_font_g); - break; - case ARG_DEFAULT_FONT_BLUE: - g_value_set_int (value, tiger->default_font_b); - break; - case ARG_DEFAULT_FONT_ALPHA: - g_value_set_int (value, tiger->default_font_a); - break; - case ARG_DEFAULT_BACKGROUND_RED: - g_value_set_int (value, tiger->default_background_r); - break; - case ARG_DEFAULT_BACKGROUND_GREEN: - g_value_set_int (value, tiger->default_background_g); - break; - case ARG_DEFAULT_BACKGROUND_BLUE: - g_value_set_int (value, tiger->default_background_b); - break; - case ARG_DEFAULT_BACKGROUND_ALPHA: - g_value_set_int (value, tiger->default_background_a); - break; - case ARG_SILENT: - g_value_set_boolean (value, tiger->silent); - break; - default: - if (!gst_kate_util_decoder_base_get_property (&tiger->decoder, object, - prop_id, value, pspec)) { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - } - break; - } - - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); -} - -/* GstElement vmethod implementations */ - -/* chain function - * this function does the actual processing - */ - -static GstFlowReturn -gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) -{ - GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); - const kate_event *ev = NULL; - GstFlowReturn rflow = GST_FLOW_OK; - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - - GST_LOG_OBJECT (tiger, "Got kate buffer, caps %" GST_PTR_FORMAT, - GST_BUFFER_CAPS (buf)); - - /* Now that we have the lock, check if we're flushing */ - if (tiger->decoder.kate_flushing) { - GST_DEBUG_OBJECT (tiger, "Flushing, disregarding buffer"); - goto done; - } - - /* Unfortunately, it can happen that the start of the stream is not sent, - for instance if there's a stream selector upstream, which is switched - from another Kate stream. If this happens, then we can fallback on the - headers stored in the caps (if any). */ - if (!tiger->seen_header) { - if (GST_BUFFER_SIZE (buf) == 0 || (GST_BUFFER_DATA (buf)[0] & 0x80) == 0) { - /* Not a header, try to fall back on caps */ - GstStructure *s; - const GValue *streamheader; - - GST_INFO_OBJECT (tiger, "Headers not seen, start of stream is cut off"); - s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); - streamheader = gst_structure_get_value (s, "streamheader"); - if (streamheader && G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) { - GstPad *tagpad = gst_pad_get_peer (pad); - GArray *array; - gint i; - - GST_INFO_OBJECT (tiger, "Falling back on caps to initialize decoder"); - array = g_value_peek_pointer (streamheader); - for (i = 0; i < array->len; i++) { - GValue *value = &g_array_index (array, GValue, i); - if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) { - GstBuffer *hbuf = g_value_peek_pointer (value); - gst_buffer_ref (hbuf); - rflow = - gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder, - GST_ELEMENT_CAST (tiger), pad, hbuf, tiger->srcpad, tagpad, - NULL, NULL); - } else { - GST_WARNING_OBJECT (tiger, - "Streamheader index %d does not hold a buffer", i); - } - } - gst_object_unref (tagpad); - tiger->seen_header = TRUE; - } else { - GST_WARNING_OBJECT (tiger, "No headers seen, and no headers on caps"); - } - } else { - tiger->seen_header = TRUE; - } - } - - if (gst_kate_util_decoder_base_update_segment (&tiger->decoder, - GST_ELEMENT_CAST (tiger), buf)) { - GstPad *tagpad = gst_pad_get_peer (pad); - rflow = - gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder, - GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, tagpad, NULL, &ev); - if (G_LIKELY (rflow == GST_FLOW_OK)) { - if (ev) { - int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev); - GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"", - ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "failed to add Kate event to Tiger renderer: %s", - gst_kate_util_get_error_message (ret)); - } - } - } - gst_object_unref (tagpad); - } - - /* we want to avoid shooting ahead of the video stream, or we will - get segment updates which will place us ahead of it, and we won't - be able to convert a video timestamp back into a kate timestamp */ - if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { - while (1) { - gint64 kate_time, video_time; - kate_time = - gst_segment_to_running_time (&tiger->decoder.kate_segment, - GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); - video_time = - gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, - tiger->video_segment.last_stop); - GST_DEBUG_OBJECT (tiger, "Kate time %.2f, video time %.2f (kts %ld)", - kate_time / (float) GST_SECOND, video_time / (float) GST_SECOND, - (long) GST_BUFFER_TIMESTAMP (buf)); - if (kate_time <= video_time) { - break; - } - GST_LOG_OBJECT (tiger, "Waiting to return from chain function"); - g_cond_wait (tiger->cond, tiger->mutex); - if (tiger->decoder.kate_flushing) { - GST_DEBUG_OBJECT (tiger, "Flushing while waiting"); - break; - } - GST_LOG_OBJECT (tiger, "Woken up, checking time again"); - } - } - -done: - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - - gst_object_unref (tiger); - gst_buffer_unref (buf); - - return rflow; -} - -static gboolean -gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps) -{ - GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); - GstVideoFormat format; - gint w, h; - gboolean ret; - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - - /* Cairo expects ARGB in native endianness, and that's what we get - as we've forced it in the caps. We might allow swapped red/blue - at some point, and get tiger to swap, to make some cases faster */ - tiger->swap_rgb = FALSE; - - if (gst_video_format_parse_caps (caps, &format, &w, &h)) { - tiger->video_format = format; - tiger->video_width = w; - tiger->video_height = h; - } - - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - - ret = gst_pad_set_caps (tiger->srcpad, caps); - - gst_object_unref (tiger); - return ret; -} - -static gdouble -gst_kate_tiger_get_time (GstKateTiger * tiger) -{ - gint64 rt = - gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, - tiger->video_segment.last_stop); - gint64 pos = - gst_segment_to_position (&tiger->decoder.kate_segment, GST_FORMAT_TIME, - rt); - return pos / (gdouble) GST_SECOND; -} - -static inline void -gst_kate_tiger_set_composition (GstKateTiger * tiger) -{ - GstVideoOverlayRectangle *rectangle; - - if (tiger->render_buffer) { - rectangle = gst_video_overlay_rectangle_new_argb (tiger->render_buffer, - tiger->video_width, tiger->video_height, 4 * tiger->video_width, - 0, 0, tiger->video_width, tiger->video_height, - GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA); - - if (tiger->composition) - gst_video_overlay_composition_unref (tiger->composition); - tiger->composition = gst_video_overlay_composition_new (rectangle); - gst_video_overlay_rectangle_unref (rectangle); - - } else if (tiger->composition) { - gst_video_overlay_composition_unref (tiger->composition); - tiger->composition = NULL; - } -} - -static GstFlowReturn -gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) -{ - GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); - GstFlowReturn rflow = GST_FLOW_OK; - unsigned char *ptr; - int ret; - kate_float t; - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - - GST_LOG_OBJECT (tiger, "got video frame, %u bytes", GST_BUFFER_SIZE (buf)); - - if (G_UNLIKELY (tiger->video_flushing)) { - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - gst_object_unref (tiger); - gst_buffer_unref (buf); - return GST_FLOW_FLUSHING; - } - - if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { - gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buf)); - g_cond_broadcast (tiger->cond); - } - - /* Update first with a dummy buffer pointer we cannot write to, but with the - right dimensions. If there is nothing to draw, we will not have to make - it writeable. */ - ptr = GST_BUFFER_DATA (buf); - ret = - tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, - tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "Tiger renderer failed to set buffer to video frame: %s", - gst_kate_util_get_error_message (ret)); - goto pass; - } - - /* update the renderer at the time of the video frame */ - t = gst_kate_tiger_get_time (tiger); - GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f", - (long) tiger->video_segment.last_stop, t); - ret = tiger_renderer_update (tiger->tr, t, 1); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %s", - gst_kate_util_get_error_message (ret)); - goto pass; - } - - /* if there nothing to draw, we can just push the video buffer as is */ - if (ret > 0 || tiger->silent) - goto pass; - - /* there is something to draw, so first make the buffer writable */ - buf = gst_buffer_make_writable (buf); - if (G_UNLIKELY (!buf)) { - GST_WARNING_OBJECT (tiger, "Failed to make video buffer writable"); - goto pass; - } - - /* and setup that buffer before rendering */ - if (gst_video_format_is_yuv (tiger->video_format)) { - if (!tiger->render_buffer) { - tiger->render_buffer = - gst_buffer_new_and_alloc (tiger->video_width * tiger->video_height * - 4); - } - ptr = GST_BUFFER_DATA (tiger->render_buffer); - tiger_renderer_set_surface_clear_color (tiger->tr, 1, 0.0, 0.0, 0.0, 0.0); - } else { - ptr = GST_BUFFER_DATA (buf); - } - ret = - tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, - tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "Tiger renderer failed to set buffer to video frame: %s", - gst_kate_util_get_error_message (ret)); - goto pass; - } - ret = tiger_renderer_render (tiger->tr); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "Tiger renderer failed to render to video frame: %s", - gst_kate_util_get_error_message (ret)); - } else { - GST_LOG_OBJECT (tiger, "Tiger renderer rendered on video frame at %f", t); - } - - if (gst_video_format_is_yuv (tiger->video_format)) { - gst_kate_tiger_set_composition (tiger); - if (tiger->composition) - gst_video_overlay_composition_blend (tiger->composition, buf); - } - -pass: - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - - rflow = gst_pad_push (tiger->srcpad, buf); - - gst_object_unref (tiger); - - return rflow; -} - -static GstStateChangeReturn -gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) -{ - GstKateTiger *tiger = GST_KATE_TIGER (element); - GstStateChangeReturn res; - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state"); - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); - g_cond_broadcast (tiger->cond); - if (tiger->tr) { - tiger_renderer_destroy (tiger->tr); - tiger->tr = NULL; - } - gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); - tiger->video_flushing = TRUE; - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - break; - default: - break; - } - - res = - gst_kate_decoder_base_change_state (&tiger->decoder, element, - parent_class, transition); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG_OBJECT (tiger, "READY -> PAUSED, initializing kate state"); - GST_KATE_TIGER_MUTEX_LOCK (tiger); - if (tiger->decoder.initialized) { - int ret = tiger_renderer_create (&tiger->tr); - if (ret < 0) { - GST_WARNING_OBJECT (tiger, "failed to create tiger renderer: %s", - gst_kate_util_get_error_message (ret)); - } else { - ret = - tiger_renderer_set_default_font_description (tiger->tr, - tiger->default_font_desc); - if (ret < 0) { - GST_WARNING_OBJECT (tiger, - "failed to set tiger default font description: %s", - gst_kate_util_get_error_message (ret)); - } - gst_kate_tiger_update_default_font_color (tiger); - gst_kate_tiger_update_default_background_color (tiger); - gst_kate_tiger_update_default_font_effect (tiger); - gst_kate_tiger_update_quality (tiger); - } - } - gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); - tiger->video_flushing = FALSE; - tiger->seen_header = FALSE; - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - break; - default: - break; - } - - return res; -} - -static gboolean -gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event) -{ - GstFormat format; - gdouble rate; - GstSeekFlags flags; - GstSeekType cur_type, stop_type; - gint64 cur, stop; - - gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, - &stop_type, &stop); - - if (flags & GST_SEEK_FLAG_FLUSH) - gst_pad_push_event (tiger->srcpad, gst_event_new_flush_start ()); - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - tiger->video_flushing = TRUE; - gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); - g_cond_broadcast (tiger->cond); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - - if (format == GST_FORMAT_TIME) { - /* if seeking in time, we can update tiger to remove any appropriate events */ - kate_float target; - switch (cur_type) { - case GST_SEEK_TYPE_SET: - target = cur / (float) GST_SECOND; - break; - case GST_SEEK_TYPE_CUR: - GST_WARNING_OBJECT (tiger, - "Seeking from the current segment, cannot work out target so flushing everything"); - target = (kate_float) 0; - break; - case GST_SEEK_TYPE_END: - GST_WARNING_OBJECT (tiger, - "Seeking from the end, cannot work out target so flushing everything"); - target = (kate_float) 0; - break; - default: - GST_WARNING_OBJECT (tiger, "Unexpected seek type"); - target = (kate_float) 0; - break; - } - GST_INFO_OBJECT (tiger, "Seeking in time to %f", target); - GST_KATE_TIGER_MUTEX_LOCK (tiger); - tiger_renderer_seek (tiger->tr, target); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - } - - /* forward to both sinks */ - gst_event_ref (event); - if (gst_pad_push_event (tiger->videosinkpad, event)) { - int ret = gst_pad_push_event (tiger->katesinkpad, event); - if (ret) { - return TRUE; - } else { - return FALSE; - } - } else { - gst_event_unref (event); - return FALSE; - } -} - -static gboolean -gst_kate_tiger_source_event (GstPad * pad, GstEvent * event) -{ - GstKateTiger *tiger = - (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); - gboolean res = TRUE; - - g_return_val_if_fail (tiger != NULL, FALSE); - - GST_LOG_OBJECT (tiger, "Event on source pad: %s", - GST_EVENT_TYPE_NAME (event)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - GST_INFO_OBJECT (tiger, "Seek on source pad"); - res = gst_kate_tiger_seek (tiger, pad, event); - break; - default: - res = gst_pad_event_default (pad, event); - break; - } - - gst_object_unref (tiger); - - return res; -} - -static gboolean -gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) -{ - GstKateTiger *tiger = - (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); - gboolean res = TRUE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - GST_INFO_OBJECT (tiger, "New segment on Kate pad"); - GST_KATE_TIGER_MUTEX_LOCK (tiger); - g_cond_broadcast (tiger->cond); - gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - gst_event_unref (event); - break; - case GST_EVENT_FLUSH_START: - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - g_cond_broadcast (tiger->cond); - gst_event_unref (event); - break; - case GST_EVENT_FLUSH_STOP: - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_kate_util_decoder_base_set_flushing (&tiger->decoder, FALSE); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - gst_event_unref (event); - break; - case GST_EVENT_EOS: - /* we ignore this, it just means we don't have anymore Kate packets, but - the Tiger renderer will still draw (if appropriate) on incoming video */ - GST_INFO_OBJECT (tiger, "EOS on Kate pad"); - GST_KATE_TIGER_MUTEX_LOCK (tiger); - g_cond_broadcast (tiger->cond); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - gst_event_unref (event); - break; - default: - res = gst_pad_event_default (pad, event); - break; - } - - gst_object_unref (tiger); - - return res; -} - -static gboolean -gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event) -{ - GstKateTiger *tiger = - (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); - gboolean res = TRUE; - - g_return_val_if_fail (tiger != NULL, FALSE); - - GST_LOG_OBJECT (tiger, "Event on Kate pad: %s", GST_EVENT_TYPE_NAME (event)); - - /* Delay events till we've set caps */ - if (gst_kate_util_decoder_base_queue_event (&tiger->decoder, event, - &gst_kate_tiger_handle_kate_event, pad)) { - gst_object_unref (tiger); - return TRUE; - } - - res = gst_kate_tiger_handle_kate_event (pad, event); - - gst_object_unref (tiger); - - return res; -} - -static gboolean -gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event) -{ - GstKateTiger *tiger = - (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); - gboolean res = TRUE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate, arate; - GstFormat format; - gint64 start, stop, time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - if (format == GST_FORMAT_TIME) { - GST_DEBUG_OBJECT (tiger, "video pad segment:" - " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT - " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, - update, rate, arate, format, GST_TIME_ARGS (start), - GST_TIME_ARGS (stop), GST_TIME_ARGS (time)); - - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_segment_set_newsegment_full (&tiger->video_segment, update, rate, - arate, format, start, stop, time); - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - } - - res = gst_pad_event_default (pad, event); - break; - } - case GST_EVENT_FLUSH_START: - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); - tiger->video_flushing = TRUE; - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - g_cond_broadcast (tiger->cond); - res = gst_pad_event_default (pad, event); - break; - case GST_EVENT_FLUSH_STOP: - GST_KATE_TIGER_MUTEX_LOCK (tiger); - gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); - tiger->video_flushing = FALSE; - GST_KATE_TIGER_MUTEX_UNLOCK (tiger); - res = gst_pad_event_default (pad, event); - break; - default: - res = gst_pad_event_default (pad, event); - break; - } - - gst_object_unref (tiger); - - return res; -} - -static gboolean -gst_kate_tiger_video_event (GstPad * pad, GstEvent * event) -{ - GstKateTiger *tiger = - (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); - gboolean res = TRUE; - - g_return_val_if_fail (tiger != NULL, FALSE); - - GST_INFO_OBJECT (tiger, "Event on video pad: %s", - GST_EVENT_TYPE_NAME (event)); - - res = gst_kate_tiger_handle_video_event (pad, event); - - gst_object_unref (tiger); - - return res; -} - -gboolean -gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query) -{ - GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); - gboolean res = gst_kate_decoder_base_sink_query (&tiger->decoder, - GST_ELEMENT_CAST (tiger), pad, query); - GST_INFO_OBJECT (tiger, "Query on Kate pad"); - gst_object_unref (tiger); - return res; -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.h b/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.h deleted file mode 100644 index d9ee639d24..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkatetiger.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * GStreamer - * Copyright 2005 Thomas Vander Stichele - * Copyright 2005 Ronald S. Bultje - * Copyright 2008 Vincent Penquerc'h - * - * 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, sublicense, - * 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 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 NONINFRINGEMENT. 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. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_KATE_TIGER_H__ -#define __GST_KATE_TIGER_H__ - -#include -#include -#include -#include -#include -#include "gstkateutil.h" - -G_BEGIN_DECLS -/* #defines don't like whitespacey bits */ -#define GST_TYPE_KATE_TIGER \ - (gst_kate_tiger_get_type()) -#define GST_KATE_TIGER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_KATE_TIGER,GstKateTiger)) -#define GST_KATE_TIGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE,GstKateTigerClass)) -#define GST_IS_KATE_TIGER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_TIGER)) -#define GST_IS_KATE_TIGER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_TIGER)) -typedef struct _GstKateTiger GstKateTiger; -typedef struct _GstKateTigerClass GstKateTigerClass; - -struct _GstKateTiger -{ - GstKateDecoderBase decoder; - - GstPad *katesinkpad; - GstPad *videosinkpad; - GstPad *srcpad; - - tiger_renderer *tr; - - gdouble quality; - gchar *default_font_desc; - gboolean default_font_effect; - gdouble default_font_effect_strength; - guchar default_font_r; - guchar default_font_g; - guchar default_font_b; - guchar default_font_a; - guchar default_background_r; - guchar default_background_g; - guchar default_background_b; - guchar default_background_a; - gboolean silent; - - GstVideoFormat video_format; - gint video_width; - gint video_height; - gboolean swap_rgb; - GstBuffer *render_buffer; - GstVideoOverlayComposition *composition; - - GMutex *mutex; - GCond *cond; - - GstSegment video_segment; - gboolean video_flushing; - gboolean seen_header; -}; - -struct _GstKateTigerClass -{ - GstElementClass parent_class; -}; - -GType gst_kate_tiger_get_type (void); - -G_END_DECLS -#endif /* __GST_KATE_TIGER_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateutil.c b/subprojects/gst-plugins-bad/ext/kate/gstkateutil.c deleted file mode 100644 index 9702c025e8..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateutil.c +++ /dev/null @@ -1,702 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* FIXME: shouldn't all this GstKateDecoderBase stuff really be a base class? */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#ifdef HAVE_TIGER -#include -#endif -#include -#include "gstkateutil.h" - -GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug); -#define GST_CAT_DEFAULT gst_kateutil_debug - -static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * - decoder); - -GstCaps * -gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps, - GList * headers) -{ - GstStructure *structure; - GValue array = { 0 }; - - GST_LOG_OBJECT (element, "caps: %" GST_PTR_FORMAT, caps); - - if (G_UNLIKELY (!caps)) - return NULL; - if (G_UNLIKELY (!headers)) - return NULL; - - caps = gst_caps_make_writable (caps); - structure = gst_caps_get_structure (caps, 0); - - g_value_init (&array, GST_TYPE_ARRAY); - - while (headers) { - GValue value = { 0 }; - GstBuffer *buffer = headers->data; - g_assert (buffer); - g_value_init (&value, GST_TYPE_BUFFER); - buffer = gst_buffer_copy (buffer); - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_HEADER); - gst_value_take_buffer (&value, buffer); - gst_value_array_append_value (&array, &value); - g_value_unset (&value); - headers = headers->next; - } - - gst_structure_take_value (structure, "streamheader", &array); - - GST_LOG_OBJECT (element, "here are the newly set caps: %" GST_PTR_FORMAT, - caps); - - return caps; -} - -void -gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class) -{ - g_object_class_install_property (gobject_class, ARG_DEC_BASE_LANGUAGE, - g_param_spec_string ("language", "Language", "The language of the stream", - "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, ARG_DEC_BASE_CATEGORY, - g_param_spec_string ("category", "Category", "The category of the stream", - "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH, - g_param_spec_int ("original-canvas-width", - "Original canvas width (0 is unspecified)", - "The canvas width this stream was authored for", 0, G_MAXINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT, - g_param_spec_int ("original-canvas-height", "Original canvas height", - "The canvas height this stream was authored for (0 is unspecified)", - 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); -} - -void -gst_kate_util_decode_base_init (GstKateDecoderBase * decoder, - gboolean delay_events) -{ - if (G_UNLIKELY (!decoder)) - return; - - decoder->language = NULL; - decoder->category = NULL; - decoder->original_canvas_width = 0; - decoder->original_canvas_height = 0; - decoder->tags = NULL; - decoder->tags_changed = FALSE; - decoder->initialized = FALSE; - decoder->delay_events = delay_events; - decoder->event_queue = NULL; -} - -static void -gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder) -{ - g_free (decoder->language); - decoder->language = NULL; - g_free (decoder->category); - decoder->category = NULL; - if (decoder->tags) { - gst_tag_list_unref (decoder->tags); - decoder->tags = NULL; - } - decoder->tags_changed = FALSE; - decoder->original_canvas_width = 0; - decoder->original_canvas_height = 0; - if (decoder->event_queue) { - gst_kate_util_decoder_base_free_event_queue (decoder); - } - decoder->initialized = FALSE; -} - -gboolean -gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, - GstEvent * event, gboolean (*handler) (GstPad *, GstObject *, GstEvent *), - GstObject * parent, GstPad * pad) -{ - gboolean can_be_queued; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - case GST_EVENT_FLUSH_STOP: - case GST_EVENT_EOS: - can_be_queued = FALSE; - break; - case GST_EVENT_SEGMENT: - gst_kate_util_decoder_base_segment_event (decoder, event); - can_be_queued = TRUE; - break; - default: - can_be_queued = TRUE; - break; - } - - if (GST_EVENT_IS_STICKY (event) && GST_EVENT_TYPE (event) < GST_EVENT_CAPS) - can_be_queued = FALSE; - - if (decoder->delay_events && can_be_queued) { - GstKateDecoderBaseQueuedEvent *item; - GST_DEBUG_OBJECT (decoder, "We have to delay the event"); - item = g_new (GstKateDecoderBaseQueuedEvent, 1); - if (item) { - item->event = event; - item->parent = parent; - item->pad = pad; - item->handler = handler; - g_queue_push_tail (decoder->event_queue, item); - return TRUE; - } else { - return FALSE; - } - } else { - return FALSE; - } -} - -static void -gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder) -{ - while (decoder->event_queue->length) { - GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *) - g_queue_pop_head (decoder->event_queue); - gst_event_unref (item->event); - g_free (item); - } - g_queue_free (decoder->event_queue); - decoder->event_queue = NULL; -} - -static void -gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder) -{ - decoder->delay_events = FALSE; - - if (decoder->event_queue->length == 0) - return; - - GST_DEBUG_OBJECT (decoder, "We can now drain all events!"); - while (decoder->event_queue->length) { - GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *) - g_queue_pop_head (decoder->event_queue); - (*item->handler) (item->pad, item->parent, item->event); - g_free (item); - } -} - -void -gst_kate_util_decoder_base_add_tags (GstKateDecoderBase * decoder, - GstTagList * tags, gboolean take_ownership_of_tags) -{ - if (!decoder->tags) { - if (!take_ownership_of_tags) - tags = gst_tag_list_ref (tags); - decoder->tags = tags; - } else { - GstTagList *old = decoder->tags; - decoder->tags = gst_tag_list_merge (old, tags, GST_TAG_MERGE_REPLACE); - gst_tag_list_unref (old); - if (take_ownership_of_tags) - gst_tag_list_unref (tags); - } - decoder->tags_changed = TRUE; -} - -GstEvent * -gst_kate_util_decoder_base_get_tag_event (GstKateDecoderBase * decoder) -{ - if (!decoder->tags) - return NULL; - decoder->tags_changed = FALSE; - return gst_event_new_tag (gst_tag_list_ref (decoder->tags)); -} - -gboolean -gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder, - GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) -{ - gboolean res = TRUE; - switch (prop_id) { - case ARG_DEC_BASE_LANGUAGE: - g_value_set_string (value, decoder->language); - break; - case ARG_DEC_BASE_CATEGORY: - g_value_set_string (value, decoder->category); - break; - case ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH: - g_value_set_int (value, decoder->original_canvas_width); - break; - case ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT: - g_value_set_int (value, decoder->original_canvas_height); - break; - default: - res = FALSE; - break; - } - return res; -} - -static inline gboolean -gst_kate_util_is_utf8_string (const char *value, size_t len) -{ - if (len == 0) - return FALSE; - if (memchr (value, 0, len - 1)) - return FALSE; - if (value[len - 1]) - return FALSE; - return (kate_text_validate (kate_utf8, value, len) >= 0); -} - -GstFlowReturn -gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad, - GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev) -{ - kate_packet kp; - int ret; - GstFlowReturn rflow = GST_FLOW_OK; - gboolean is_header; - GstMapInfo info; - gsize header_size; - guint8 header[1]; - - header_size = gst_buffer_extract (buf, 0, header, 1); - - GST_DEBUG_OBJECT (element, - "got kate packet, %" G_GSIZE_FORMAT " bytes, type %02x", - gst_buffer_get_size (buf), header_size == 0 ? -1 : header[0]); - - is_header = header_size > 0 && (header[0] & 0x80); - - if (!is_header && decoder->tags_changed) { - /* after we've processed headers, send any tags before processing the data packet */ - GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s", - GST_DEBUG_PAD_NAME (tagpad)); - gst_pad_push_event (tagpad, - gst_kate_util_decoder_base_get_tag_event (decoder)); - } - - if (gst_buffer_map (buf, &info, GST_MAP_READ)) { - kate_packet_wrap (&kp, info.size, info.data); - ret = kate_high_decode_packetin (&decoder->k, &kp, ev); - gst_buffer_unmap (buf, &info); - } else { - GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), - ("Failed to map buffer")); - return GST_FLOW_ERROR; - } - - if (G_UNLIKELY (ret < 0)) { - GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), - ("Failed to decode Kate packet: %s", - gst_kate_util_get_error_message (ret))); - return GST_FLOW_ERROR; - } - - if (G_UNLIKELY (ret > 0)) { - GST_DEBUG_OBJECT (element, - "kate_high_decode_packetin has received EOS packet"); - } - - /* headers may be interesting to retrieve information from */ - if (G_UNLIKELY (is_header)) { - switch (header[0]) { - case 0x80: /* ID header */ - GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s", - decoder->k.ki->language, decoder->k.ki->category); - if (src_caps) { - if (*src_caps) { - gst_caps_unref (*src_caps); - *src_caps = NULL; - } - if (strcmp (decoder->k.ki->category, "K-SPU") == 0 || - strcmp (decoder->k.ki->category, "spu-subtitles") == 0) { - *src_caps = gst_caps_new_empty_simple ("subpicture/x-dvd"); - } else if (decoder->k.ki->text_markup_type == kate_markup_none) { - *src_caps = gst_caps_new_simple ("text/x-raw", "format", - G_TYPE_STRING, "utf8", NULL); - } else { - *src_caps = gst_caps_new_simple ("text/x-raw", "format", - G_TYPE_STRING, "pango-markup", NULL); - } - GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps); - if (!gst_pad_set_caps (srcpad, *src_caps)) { - GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT, - *src_caps); - } - } - if (decoder->k.ki->language && *decoder->k.ki->language) { - GstTagList *tags = gst_tag_list_new_empty (); - gchar *lang_code; - - /* en_GB -> en */ - lang_code = g_ascii_strdown (decoder->k.ki->language, -1); - g_strdelimit (lang_code, NULL, '\0'); - gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE, - lang_code, NULL); - g_free (lang_code); - /* TODO: category - where should it go ? */ - gst_kate_util_decoder_base_add_tags (decoder, tags, TRUE); - } - - /* update properties */ - g_free (decoder->language); - decoder->language = g_strdup (decoder->k.ki->language); - g_free (decoder->category); - decoder->category = g_strdup (decoder->k.ki->category); - decoder->original_canvas_width = decoder->k.ki->original_canvas_width; - decoder->original_canvas_height = decoder->k.ki->original_canvas_height; - - /* we can now send away any event we've delayed, as the src pad now has caps */ - gst_kate_util_decoder_base_drain_event_queue (decoder); - - break; - - case 0x81: /* Vorbis comments header */ - GST_INFO_OBJECT (element, "Parsed comments header"); - { - gchar *encoder = NULL; - GstTagList *list = gst_tag_list_from_vorbiscomment_buffer (buf, - (const guint8 *) "\201kate\0\0\0\0", 9, &encoder); - if (!list) { - GST_ERROR_OBJECT (element, "failed to decode comment header"); - list = gst_tag_list_new_empty (); - } - if (encoder) { - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_ENCODER, encoder, NULL); - g_free (encoder); - } - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_SUBTITLE_CODEC, "Kate", NULL); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major, - NULL); - - gst_kate_util_decoder_base_add_tags (decoder, list, TRUE); - - if (decoder->initialized) { - gst_pad_push_event (tagpad, - gst_event_new_tag (gst_tag_list_ref (decoder->tags))); - } - } - break; - - default: - break; - } - } -#if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400 - else if (*ev && (*ev)->meta) { - int count = kate_meta_query_count ((*ev)->meta); - if (count > 0) { - GstTagList *evtags = gst_tag_list_new_empty (); - int idx; - GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count); - for (idx = 0; idx < count; ++idx) { - const char *tag, *value; - size_t len; - if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) { - GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx); - } else { - if (gst_kate_util_is_utf8_string (value, len)) { - gchar *compound = g_strdup_printf ("%s=%s", tag, value); - GST_DEBUG_OBJECT (decoder, - "Metadata %d: %s=%s (%" G_GSIZE_FORMAT " bytes)", idx, tag, - value, len); - gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND, - GST_TAG_EXTENDED_COMMENT, compound, NULL); - g_free (compound); - } else { - GST_INFO_OBJECT (decoder, - "Metadata %d, (%s, %" G_GSIZE_FORMAT - " bytes) is binary, ignored", idx, tag, len); - } - } - } - gst_kate_util_decoder_base_add_tags (decoder, evtags, TRUE); - gst_pad_push_event (tagpad, - gst_kate_util_decoder_base_get_tag_event (decoder)); - } - } -#endif - - return rflow; -} - -GstStateChangeReturn -gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, - GstElement * element, GstElementClass * parent_class, - GstStateChange transition) -{ - GstStateChangeReturn res; - int ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_DEBUG_OBJECT (element, "READY -> PAUSED, initializing kate state"); - ret = kate_high_decode_init (&decoder->k); - if (ret < 0) { - GST_WARNING_OBJECT (element, "failed to initialize kate state: %s", - gst_kate_util_get_error_message (ret)); - } - gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); - decoder->kate_flushing = FALSE; - decoder->initialized = TRUE; - decoder->event_queue = g_queue_new (); - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - res = parent_class->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_DEBUG_OBJECT (element, "PAUSED -> READY, clearing kate state"); - if (decoder->initialized) { - kate_high_decode_clear (&decoder->k); - decoder->initialized = FALSE; - } - gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); - decoder->kate_flushing = TRUE; - gst_kate_util_decode_base_reset (decoder); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_kate_util_decode_base_reset (decoder); - break; - default: - break; - } - - return res; -} - -void -gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder, - gboolean flushing) -{ - decoder->kate_flushing = flushing; - gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); -} - -void -gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder, - GstEvent * event) -{ - GstSegment seg; - - gst_event_copy_segment (event, &seg); - - GST_DEBUG_OBJECT (decoder, "kate pad segment: %" GST_SEGMENT_FORMAT, &seg); - - decoder->kate_segment = seg; -} - -gboolean -gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, - GstElement * element, GstBuffer * buf) -{ - guint64 clip_start = 0, clip_stop = 0; - gboolean in_seg; - - if (decoder->kate_flushing) { - GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored"); - return FALSE; - } - - if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { - GstClockTime stop; - - if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf))) - stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf); - else - stop = GST_CLOCK_TIME_NONE; - - in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop); - } else { - in_seg = TRUE; - } - - if (in_seg) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - decoder->kate_segment.position = clip_start; - } - } else { - GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored"); - } - - return in_seg; -} - -static GstClockTime -gst_kate_util_granule_time (kate_state * k, gint64 granulepos) -{ - if (G_UNLIKELY (granulepos == -1)) - return -1; - - return kate_granule_time (k->ki, granulepos) * GST_SECOND; -} - -/* -conversions on the sink: - - default is granules at num/den rate (subject to the granule shift) - - default -> time is possible - - bytes do not mean anything, packets can be any number of bytes, and we - have no way to know the number of bytes emitted without decoding -conversions on the source: - - nothing -*/ - -gboolean -gst_kate_decoder_base_convert (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstFormat src_fmt, gint64 src_val, - GstFormat * dest_fmt, gint64 * dest_val) -{ - gboolean res = FALSE; - - if (src_fmt == *dest_fmt) { - *dest_val = src_val; - return TRUE; - } - - if (!decoder->initialized) { - GST_WARNING_OBJECT (element, "not initialized yet"); - return FALSE; - } - - if (src_fmt == GST_FORMAT_BYTES || *dest_fmt == GST_FORMAT_BYTES) { - GST_WARNING_OBJECT (element, "unsupported format"); - return FALSE; - } - - switch (src_fmt) { - case GST_FORMAT_DEFAULT: - switch (*dest_fmt) { - case GST_FORMAT_TIME: - *dest_val = gst_kate_util_granule_time (&decoder->k, src_val); - res = TRUE; - break; - default: - res = FALSE; - break; - } - break; - default: - res = FALSE; - break; - } - - if (!res) { - GST_WARNING_OBJECT (element, "unsupported format"); - } - - return res; -} - -gboolean -gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstObject * parent, GstQuery * query) -{ - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - if (!gst_kate_decoder_base_convert (decoder, element, pad, src_fmt, - src_val, &dest_fmt, &dest_val)) { - return gst_pad_query_default (pad, parent, query); - } - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - return TRUE; - } - default: - return gst_pad_query_default (pad, parent, query); - } -} - -const char * -gst_kate_util_get_error_message (int ret) -{ - switch (ret) { - case KATE_E_NOT_FOUND: - return "value not found"; - case KATE_E_INVALID_PARAMETER: - return "invalid parameter"; - case KATE_E_OUT_OF_MEMORY: - return "out of memory"; - case KATE_E_BAD_GRANULE: - return "bad granule"; - case KATE_E_INIT: - return "initialization error"; - case KATE_E_BAD_PACKET: - return "bad packet"; - case KATE_E_TEXT: - return "invalid/truncated text"; - case KATE_E_LIMIT: - return "a limit was exceeded"; - case KATE_E_VERSION: - return "unsupported bitstream version"; - case KATE_E_NOT_KATE: - return "not a kate bitstream"; - case KATE_E_BAD_TAG: - return "bad tag"; - case KATE_E_IMPL: - return "not implemented"; - -#ifdef HAVE_TIGER - case TIGER_E_NOT_FOUND: - return "value not found"; - case TIGER_E_INVALID_PARAMETER: - return "invalid parameter"; - case TIGER_E_OUT_OF_MEMORY: - return "out of memory"; - case TIGER_E_CAIRO_ERROR: - return "Cairo error"; - case TIGER_E_BAD_SURFACE_TYPE: - return "bad surface type"; -#endif - - default: - return "unknown error"; - } -} diff --git a/subprojects/gst-plugins-bad/ext/kate/gstkateutil.h b/subprojects/gst-plugins-bad/ext/kate/gstkateutil.h deleted file mode 100644 index 599b90d346..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/gstkateutil.h +++ /dev/null @@ -1,123 +0,0 @@ -/* -*- c-basic-offset: 2 -*- - * GStreamer - * Copyright (C) <2008> Vincent Penquerc'h - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#ifndef __GST_KATE_UTIL_H__ -#define __GST_KATE_UTIL_H__ - -#include -#include - -G_BEGIN_DECLS - -typedef enum { - GST_KATE_FORMAT_UNDEFINED, - GST_KATE_FORMAT_SPU, - GST_KATE_FORMAT_TEXT_UTF8, - GST_KATE_FORMAT_TEXT_PANGO_MARKUP -} GstKateFormat; - -enum -{ - ARG_DEC_BASE_0, - ARG_DEC_BASE_LANGUAGE, - ARG_DEC_BASE_CATEGORY, - ARG_DEC_BASE_ORIGINAL_CANVAS_WIDTH, - ARG_DEC_BASE_ORIGINAL_CANVAS_HEIGHT, - DECODER_BASE_ARG_COUNT -}; - -typedef struct -{ - GstEvent * event; - gboolean (*handler)(GstPad *, GstObject*, GstEvent *); - GstObject * parent; - GstPad *pad; -} GstKateDecoderBaseQueuedEvent; - -typedef struct -{ - GstElement element; - - kate_state k; - - gboolean initialized; - - GstTagList *tags; - gboolean tags_changed; - - gchar *language; - gchar *category; - - gint original_canvas_width; - gint original_canvas_height; - - GstSegment kate_segment; - gboolean kate_flushing; - - gboolean delay_events; - GQueue *event_queue; -} GstKateDecoderBase; - -extern GstCaps *gst_kate_util_set_header_on_caps (GstElement * element, - GstCaps * caps, GList * headers); -extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder, - gboolean delay_events); -extern void gst_kate_util_install_decoder_base_properties (GObjectClass * - gobject_class); -extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase * - decoder, GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec); -extern GstFlowReturn -gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstBuffer * buffer, GstPad * srcpad, - GstPad * tagpad, GstCaps **src_caps, const kate_event ** ev); -extern void -gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder, - gboolean flushing); -extern void -gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder, - GstEvent * event); -extern gboolean -gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, - GstElement * element, GstBuffer * buf); -extern GstStateChangeReturn -gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, - GstElement * element, GstElementClass * parent_class, - GstStateChange transition); -extern gboolean gst_kate_decoder_base_convert (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstFormat src_fmt, gint64 src_val, - GstFormat * dest_fmt, gint64 * dest_val); -extern gboolean gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder, - GstElement * element, GstPad * pad, GstObject * parent, GstQuery * query); -extern gboolean -gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, - GstEvent * event, gboolean (*handler)(GstPad *, GstObject *, GstEvent *), - GstObject * parent, GstPad * pad); -extern void -gst_kate_util_decoder_base_add_tags (GstKateDecoderBase * decoder, - GstTagList * tags, gboolean take_ownership_of_tags); -extern GstEvent * -gst_kate_util_decoder_base_get_tag_event (GstKateDecoderBase * decoder); -extern const char * -gst_kate_util_get_error_message (int ret); - -G_END_DECLS -#endif /* __GST_KATE_UTIL_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/kate/meson.build b/subprojects/gst-plugins-bad/ext/kate/meson.build deleted file mode 100644 index 840fa9e58a..0000000000 --- a/subprojects/gst-plugins-bad/ext/kate/meson.build +++ /dev/null @@ -1,26 +0,0 @@ -kate_sources = [ - 'gstkate.c', - 'gstkateelement.c', - 'gstkatedec.c', - 'gstkateenc.c', - 'gstkateparse.c', - 'gstkatetag.c', - 'gstkateutil.c', - 'gstkatespu.c', -] - -kate_dep = dependency('kate', version : '>=0.1.7', required : get_option('kate')) -# Not used -#tiger_dep = dependency('tiger', version : '>=0.3.2', required : get_option('kate')) - -if kate_dep.found() - gstkate = library('gstkate', - kate_sources, - c_args : gst_plugins_bad_args, - link_args : noseh_link_args, - include_directories : [configinc, libsinc], - dependencies : [gstbase_dep, gstvideo_dep, gsttag_dep, kate_dep], - install : true, - install_dir : plugins_install_dir) - plugins += [gstkate] -endif diff --git a/subprojects/gst-plugins-bad/ext/meson.build b/subprojects/gst-plugins-bad/ext/meson.build index 0ca81c79c1..9305493a2a 100644 --- a/subprojects/gst-plugins-bad/ext/meson.build +++ b/subprojects/gst-plugins-bad/ext/meson.build @@ -26,7 +26,6 @@ subdir('gtk') subdir('hls') subdir('iqa') subdir('isac') -subdir('kate') subdir('ladspa') subdir('lc3') subdir('ldac') diff --git a/subprojects/gst-plugins-bad/gst/inter/gstintersubsrc.c b/subprojects/gst-plugins-bad/gst/inter/gstintersubsrc.c index 801a962893..8fb11937c1 100644 --- a/subprojects/gst-plugins-bad/gst/inter/gstintersubsrc.c +++ b/subprojects/gst-plugins-bad/gst/inter/gstintersubsrc.c @@ -26,7 +26,7 @@ * * ## Example launch line * |[ - * gst-launch-1.0 -v intersubsrc ! kateenc ! oggmux ! filesink location=out.ogv + * gst-launch-1.0 -v intersubsrc ! srtenc ! filesink location=subtitles.srt * ]| * * The intersubsrc element cannot be used effectively with gst-launch-1.0, diff --git a/subprojects/gst-plugins-bad/meson_options.txt b/subprojects/gst-plugins-bad/meson_options.txt index 3ac02da33a..ba2b0cea5d 100644 --- a/subprojects/gst-plugins-bad/meson_options.txt +++ b/subprojects/gst-plugins-bad/meson_options.txt @@ -126,7 +126,6 @@ option('gsm', type : 'feature', value : 'auto', description : 'GSM encoder/decod option('gtk3', type : 'feature', value : 'auto', description : 'GTK+ video sink plugin') option('ipcpipeline', type : 'feature', value : 'auto', description : 'Inter-process communication plugin') option('iqa', type : 'feature', value : 'auto', description : 'Image quality assessment plugin (AGPL - only built if gpl option is also enabled!)') -option('kate', type : 'feature', value : 'auto', description : 'Kate subtitle parser, tagger, and codec plugin') option('kms', type : 'feature', value : 'auto', description : 'KMS video sink plugin') option('ladspa', type : 'feature', value : 'auto', description : 'LADSPA plugin bridge') option('lc3', type : 'feature', value : 'auto', description : 'LC3 (Bluetooth) LE audio codec plugin') diff --git a/subprojects/gst-plugins-bad/tests/check/elements/kate.c b/subprojects/gst-plugins-bad/tests/check/elements/kate.c deleted file mode 100644 index cf56db5059..0000000000 --- a/subprojects/gst-plugins-bad/tests/check/elements/kate.c +++ /dev/null @@ -1,881 +0,0 @@ -/* GStreamer - * - * unit test for kate - * - * Copyright (C) <2007> Stefan Kost - * Copyright (C) <2008> ogg.k.ogg.k - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -#include -#include - - -static const guint8 kate_header_0x80[64] = { - 0x80, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00, 0x00, 0x20, /* .kate...... ... */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, /* ................ */ - 0x65, 0x6e, 0x5f, 0x47, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* en_GB........... */ - 0x6e, 0x6f, 0x6e, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* none............ */ -}; - -static const guint8 kate_header_0x81[53] = { - 0x81, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x6c, 0x69, 0x62, /* .kate........lib */ - 0x6b, 0x61, 0x74, 0x65, 0x20, 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x20, 0x28, 0x54, 0x69, 0x67, 0x65, /* kate 0.1.0 (Tige */ - 0x72, 0x29, 0x01, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x54, 0x49, 0x54, 0x4c, 0x45, 0x3d, /* r)........TITLE= */ - 0x54, 0x69, 0x67, 0x65, 0x72, /* Tiger */ -}; - -static const guint8 kate_header_0x8x[10] = { - 0x80, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00 -}; - -static const guint8 kate_header_0x88[11] = { - 0x88, 0x6b, 0x61, 0x74, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static const guint8 kate_header_0x00[45] = { - 0x00, 0xe8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, /* ................ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x70, 0x6c, 0x61, /* .............pla */ - 0x69, 0x6e, 0x20, 0x6f, 0x6c, 0x64, 0x20, 0x74, 0x65, 0x78, 0x74, 0x08, 0x00 /* in old text.. */ -}; - -static const guint8 kate_header_0x7f[1] = { - 0x7f -}; - -static const unsigned char kate_spu[] = { - 0x00, 0x1b, /* size */ - 0x00, 0x06, /* commands at offset 6 */ - 0x45, /* first line data - 2 pixels of colors 0 and 1 */ - 0x76, /* first line data - 2 pixels of colors 3 and 2 */ - 0x00, 0x00, /* timestamp */ - 0x00, 0x06, /* link to next command sequence - points back to the current one to mark no more */ - 0x06, 0x00, 0x04, 0x00, 0x05, /* pointers to data */ - 0x05, 0x00, 0x30, 0x04, 0x00, 0x10, 0x02, /* area: 3x1 -> 4x2 */ - 0x04, 0x0f, 0xff, /* alpha: color 0 transparent, all others opaque */ - 0x01, /* show */ - 0xff /* end */ -}; - -/* A lot of these taken from the vorbisdec test */ - -/* For ease of programming we use globals to keep refs for our floating - * src and sink pads we create; otherwise we always have to do get_pad, - * get_peer, and then remove references in every test function */ -static GstPad *mydecsrcpad, *mydecsinkpad; -static GstPad *myencsrcpad, *myencsinkpad; -static GstPad *myparsesrcpad, *myparsesinkpad; -static GstPad *mytagsrcpad, *mytagsinkpad; - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GList *events = NULL; - -static gboolean -collect_events_func (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GST_LOG ("event: %" GST_PTR_FORMAT, event); - events = g_list_append (events, gst_event_ref (event)); - return gst_pad_event_default (pad, parent, event); -} - -static GstElement * -setup_katedec (void) -{ - GstElement *katedec; - - GST_DEBUG ("setup_katedec"); - katedec = gst_check_setup_element ("katedec"); - mydecsrcpad = gst_check_setup_src_pad (katedec, &srctemplate); - mydecsinkpad = gst_check_setup_sink_pad (katedec, &sinktemplate); - gst_pad_set_event_function (mydecsinkpad, collect_events_func); - gst_pad_set_active (mydecsrcpad, TRUE); - gst_pad_set_active (mydecsinkpad, TRUE); - - return katedec; -} - -static void -cleanup_katedec (GstElement * katedec) -{ - GList *l; - - GST_DEBUG ("cleanup_katedec"); - gst_element_set_state (katedec, GST_STATE_NULL); - - for (l = events; l != NULL; l = l->next) - gst_event_unref (GST_EVENT (l->data)); - g_list_free (events); - events = NULL; - - gst_pad_set_active (mydecsrcpad, FALSE); - gst_pad_set_active (mydecsinkpad, FALSE); - gst_check_teardown_src_pad (katedec); - gst_check_teardown_sink_pad (katedec); - gst_check_teardown_element (katedec); -} - -static GstElement * -setup_kateenc (void) -{ - GstElement *kateenc; - - GST_DEBUG ("setup_kateenc"); - kateenc = gst_check_setup_element ("kateenc"); - myencsrcpad = gst_check_setup_src_pad (kateenc, &srctemplate); - myencsinkpad = gst_check_setup_sink_pad (kateenc, &sinktemplate); - gst_pad_set_active (myencsrcpad, TRUE); - gst_pad_set_active (myencsinkpad, TRUE); - - return kateenc; -} - -static void -cleanup_kateenc (GstElement * kateenc) -{ - GST_DEBUG ("cleanup_kateenc"); - gst_element_set_state (kateenc, GST_STATE_NULL); - - gst_pad_set_active (myencsrcpad, FALSE); - gst_pad_set_active (myencsinkpad, FALSE); - gst_check_teardown_src_pad (kateenc); - gst_check_teardown_sink_pad (kateenc); - gst_check_teardown_element (kateenc); -} - -static GstElement * -setup_kateparse (void) -{ - GstElement *kateparse; - - GST_DEBUG ("setup_kateparse"); - kateparse = gst_check_setup_element ("kateparse"); - myparsesrcpad = gst_check_setup_src_pad (kateparse, &srctemplate); - myparsesinkpad = gst_check_setup_sink_pad (kateparse, &sinktemplate); - gst_pad_set_active (myparsesrcpad, TRUE); - gst_pad_set_active (myparsesinkpad, TRUE); - - return kateparse; -} - -static void -cleanup_kateparse (GstElement * kateparse) -{ - GST_DEBUG ("cleanup_kateparse"); - gst_element_set_state (kateparse, GST_STATE_NULL); - - gst_pad_set_active (myparsesrcpad, FALSE); - gst_pad_set_active (myparsesinkpad, FALSE); - gst_check_teardown_src_pad (kateparse); - gst_check_teardown_sink_pad (kateparse); - gst_check_teardown_element (kateparse); -} - -static GstElement * -setup_katetag (void) -{ - GstElement *katetag; - - GST_DEBUG ("setup_katetag"); - katetag = gst_check_setup_element ("katetag"); - mytagsrcpad = gst_check_setup_src_pad (katetag, &srctemplate); - mytagsinkpad = gst_check_setup_sink_pad (katetag, &sinktemplate); - gst_pad_set_active (mytagsrcpad, TRUE); - gst_pad_set_active (mytagsinkpad, TRUE); - - return katetag; -} - -static void -cleanup_katetag (GstElement * katetag) -{ - GST_DEBUG ("cleanup_katetag"); - gst_element_set_state (katetag, GST_STATE_NULL); - - gst_pad_set_active (mytagsrcpad, FALSE); - gst_pad_set_active (mytagsinkpad, FALSE); - gst_check_teardown_src_pad (katetag); - gst_check_teardown_sink_pad (katetag); - gst_check_teardown_element (katetag); -} - -static void -check_buffers (guint expected, gboolean headers_in_caps) -{ - GstBuffer *outbuffer; - GstMapInfo info; - guint i, num_buffers; - const int num_headers = 9; - unsigned char packet_type; - - /* check buffers are the type we expect */ - num_buffers = g_list_length (buffers); - fail_unless (num_buffers >= num_headers + expected); /* at least 9 headers, plus a variable number of data packets */ - for (i = 0; i < num_buffers; ++i) { - outbuffer = GST_BUFFER (buffers->data); - fail_if (outbuffer == NULL); - fail_if (gst_buffer_get_size (outbuffer) == 0); - - assert_equals_int (gst_buffer_map (outbuffer, &info, GST_MAP_READ), TRUE); - if (i < num_headers) { - /* different headers packets */ - packet_type = (0x80 | i); - fail_unless (info.data[0] == packet_type); - /* headers could be in caps, so would have an extra ref */ - } else if (i == num_buffers - 1) { - /* eos data packet */ - packet_type = 0x7f; - fail_unless (info.data[0] == packet_type); - } else { - /* data packet */ - packet_type = 0; - fail_unless (info.data[0] >= 0 && info.data[0] < 0x7f); - } - gst_buffer_unmap (outbuffer, &info); - - buffers = g_list_remove (buffers, outbuffer); - - ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); - gst_buffer_unref (outbuffer); - outbuffer = NULL; - } -} - -GST_START_TEST (test_kate_typefind) -{ - GstTypeFindProbability prob; - const gchar *type; - GstBuffer *buf; - GstCaps *caps = NULL; - - buf = gst_buffer_new_memdup (kate_header_0x80, sizeof (kate_header_0x80)); - GST_BUFFER_OFFSET (buf) = 0; - - caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); - fail_unless (caps != NULL); - GST_LOG ("Found type: %" GST_PTR_FORMAT, caps); - - type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); - fail_unless_equals_string (type, "application/x-kate"); - fail_unless (prob > GST_TYPE_FIND_MINIMUM && prob <= GST_TYPE_FIND_MAXIMUM); - - gst_buffer_unref (buf); - gst_caps_unref (caps); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_empty_identification_header) -{ - GstElement *katedec; - GstBuffer *inbuffer; - GstBus *bus; - GstCaps *caps; - - katedec = setup_katedec (); - bus = gst_bus_new (); - - fail_unless (gst_element_set_state (katedec, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - - caps = gst_caps_new_empty_simple ("subtitle/x-kate"); - gst_check_setup_events (mydecsrcpad, katedec, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - - inbuffer = gst_buffer_new_and_alloc (0); - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - - /* set a bus here so we avoid getting state change messages */ - gst_element_set_bus (katedec, bus); - - fail_unless_equals_int (gst_pad_push (mydecsrcpad, inbuffer), GST_FLOW_ERROR); - /* ... but it ends up being collected on the global buffer list */ - fail_unless_equals_int (g_list_length (buffers), 0); - - gst_element_set_bus (katedec, NULL); - - /* cleanup */ - gst_object_unref (GST_OBJECT (bus)); - cleanup_katedec (katedec); -} - -GST_END_TEST; - -/* FIXME: also tests comment header */ -GST_START_TEST (test_kate_identification_header) -{ - GstElement *katedec; - GstBuffer *inbuffer; - GstBus *bus; - GstCaps *caps; - - katedec = setup_katedec (); - fail_unless (gst_element_set_state (katedec, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - caps = gst_caps_new_empty_simple ("subtitle/x-kate"); - gst_check_setup_events (mydecsrcpad, katedec, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - - inbuffer = - gst_buffer_new_memdup (kate_header_0x80, sizeof (kate_header_0x80)); - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_ref (inbuffer); - - gst_element_set_bus (katedec, bus); - /* pushing gives away my reference ... */ - fail_unless (gst_pad_push (mydecsrcpad, inbuffer) == GST_FLOW_OK); - /* ... and nothing ends up on the global buffer list */ - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_unref (inbuffer); - fail_unless (g_list_length (buffers) == 0); - - inbuffer = - gst_buffer_new_memdup (kate_header_0x81, sizeof (kate_header_0x81)); - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_ref (inbuffer); - - /* pushing gives away my reference ... */ - fail_unless (gst_pad_push (mydecsrcpad, inbuffer) == GST_FLOW_OK); - /* ... and nothing ends up on the global buffer list */ - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_unref (inbuffer); - fail_unless (g_list_length (buffers) == 0); - - /* there should've been a tag event */ - { - gboolean found_tags = FALSE; - GList *l; - - for (l = events; l != NULL; l = l->next) { - GstEvent *event = GST_EVENT (l->data); - - if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) { - GstTagList *tags = NULL; - gchar *language; - gchar *title; - - found_tags = TRUE; - gst_event_parse_tag (event, &tags); - fail_unless (tags != NULL); - fail_unless (gst_tag_list_get_scope (tags) == GST_TAG_SCOPE_STREAM); - fail_unless_equals_int (gst_tag_list_get_tag_size (tags, - GST_TAG_LANGUAGE_CODE), 1); - fail_unless (gst_tag_list_get_string (tags, GST_TAG_LANGUAGE_CODE, - &language)); - fail_unless_equals_string (language, "en"); - g_free (language); - fail_unless_equals_int (gst_tag_list_get_tag_size (tags, "title"), 1); - fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &title)); - fail_unless_equals_string (title, "Tiger"); - g_free (title); - } - } - fail_unless (found_tags); - } - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (katedec, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_katedec (katedec); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_encode_nothing) -{ - GstElement *kateenc; - - kateenc = setup_kateenc (); - fail_unless (gst_element_set_state (kateenc, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - - fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* cleanup */ - cleanup_kateenc (kateenc); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_encode_empty) -{ - GstElement *kateenc; - GstBuffer *inbuffer; - GstBus *bus; - GstCaps *caps; - - kateenc = setup_kateenc (); - fail_unless (gst_element_set_state (kateenc, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - inbuffer = gst_buffer_new_and_alloc (0); - GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = - 1 * GST_SECOND; - GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND; - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - - caps = gst_caps_from_string ("text/x-raw, format=utf8"); - fail_unless (caps != NULL); - gst_check_setup_events (myencsrcpad, kateenc, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - - gst_element_set_bus (kateenc, bus); - /* pushing gives away my reference ... */ - fail_unless (gst_pad_push (myencsrcpad, inbuffer) == GST_FLOW_ERROR); - - fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - gst_element_set_bus (kateenc, NULL); - - /* cleanup */ - gst_object_unref (GST_OBJECT (bus)); - cleanup_kateenc (kateenc); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_encode_simple) -{ - GstElement *kateenc; - GstBuffer *inbuffer; - GstBus *bus; - const gchar *test_string = ""; - GstCaps *caps; - - kateenc = setup_kateenc (); - g_object_set (kateenc, "category", "subtitles", NULL); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - inbuffer = gst_buffer_new_memdup (test_string, strlen (test_string) + 1); - - GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = - 1 * GST_SECOND; - GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND; - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - - caps = gst_caps_from_string ("text/x-raw, format=utf8"); - fail_unless (caps != NULL); - gst_check_setup_events (myencsrcpad, kateenc, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - gst_buffer_ref (inbuffer); - - gst_element_set_bus (kateenc, bus); - /* pushing gives away my reference ... */ - fail_unless_equals_int (gst_pad_push (myencsrcpad, inbuffer), GST_FLOW_OK); - /* ... and nothing ends up on the global buffer list */ - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_unref (inbuffer); - fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* at least one data packet and one EOS packet should have been emitted */ - check_buffers (1 + 1, FALSE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (kateenc, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_kateenc (kateenc); - gst_check_drop_buffers (); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_encode_spu) -{ - GstElement *kateenc; - GstBuffer *inbuffer; - GstBus *bus; - GstCaps *caps; - - kateenc = setup_kateenc (); - g_object_set (kateenc, "category", "spu-subtitles", NULL); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - inbuffer = gst_buffer_new_memdup (kate_spu, sizeof (kate_spu)); - - GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = - 1 * GST_SECOND; - GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND; - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - - caps = gst_caps_from_string ("subpicture/x-dvd"); - fail_unless (caps != NULL); - gst_check_setup_events (myencsrcpad, kateenc, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - gst_buffer_ref (inbuffer); - - gst_element_set_bus (kateenc, bus); - /* pushing gives away my reference ... */ - fail_unless_equals_int (gst_pad_push (myencsrcpad, inbuffer), GST_FLOW_OK); - /* ... and nothing ends up on the global buffer list */ - ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); - gst_buffer_unref (inbuffer); - fail_unless (gst_pad_push_event (myencsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* at least one data packet and one EOS packet should have been emitted */ - check_buffers (2, FALSE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (kateenc, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_kateenc (kateenc); - gst_check_drop_buffers (); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_encode_keepalives) -{ - GstElement *kateenc; - GstBus *bus; - guint i, round; - GstSegment segment; - enum - { n_keepalives = 1000 }; - static const struct - { - gdouble keepalive_min_time; - gint packets; - } cfg[3] = { - { - 0.5, n_keepalives}, { - 2.0, n_keepalives / 2}, { - 5.0, n_keepalives / 5}, - }; - - for (round = 0; round < 3; ++round) { - kateenc = setup_kateenc (); - /* doesn't matter here, since we never send a packet */ - g_object_set (kateenc, "category", "subtitles", NULL); - fail_unless (gst_element_set_state (kateenc, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - gst_element_set_bus (kateenc, bus); - - g_object_set (kateenc, "keepalive-min-time", cfg[round].keepalive_min_time, - NULL); - - gst_pad_push_event (myencsrcpad, gst_event_new_stream_start ("test")); - - /* the second one here should not emit a keepalive since the time since last packet - is less than the keepalive delay */ - for (i = 1; i <= n_keepalives; ++i) { - gint64 t = i * GST_SECOND; - gst_segment_init (&segment, GST_FORMAT_TIME); - segment.start = t; - segment.position = 0; - fail_unless (gst_pad_push_event (myencsrcpad, - gst_event_new_segment (&segment)) == TRUE); - } - - fail_unless (gst_pad_push_event (myencsrcpad, - gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateenc, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* at least a number data packet and an EOS packet should have been emitted */ - check_buffers (cfg[round].packets + 1, FALSE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (kateenc, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_kateenc (kateenc); - gst_check_drop_buffers (); - } -} - -GST_END_TEST; - -static void -test_kate_send_headers (GstElement * element, GstPad * pad) -{ - GstBuffer *inbuffer; - GstCaps *caps; - GstMapInfo info; - int i; - - caps = gst_caps_new_simple ("subtitle/x-kate", NULL, NULL); - gst_check_setup_events (pad, element, caps, GST_FORMAT_TIME); - gst_caps_unref (caps); - - /* push headers */ - inbuffer = - gst_buffer_new_memdup (kate_header_0x80, sizeof (kate_header_0x80)); - GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0; - fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK); - - inbuffer = - gst_buffer_new_memdup (kate_header_0x81, sizeof (kate_header_0x81)); - GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0; - fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK); - - for (i = 2; i < 8; ++i) { - inbuffer = - gst_buffer_new_memdup (kate_header_0x8x, sizeof (kate_header_0x8x)); - fail_if (gst_buffer_map (inbuffer, &info, GST_MAP_WRITE) != TRUE); - info.data[0] = 0x80 | i; - gst_buffer_unmap (inbuffer, &info); - GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0; - fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK); - } - - inbuffer = - gst_buffer_new_memdup (kate_header_0x88, sizeof (kate_header_0x88)); - GST_BUFFER_OFFSET (inbuffer) = GST_BUFFER_OFFSET_END (inbuffer) = 0; - fail_unless_equals_int (gst_pad_push (pad, inbuffer), GST_FLOW_OK); -} - -GST_START_TEST (test_kate_parse) -{ - GstElement *kateparse; - GstBuffer *inbuffer; - GstBus *bus; - - kateparse = setup_kateparse (); - fail_unless (gst_element_set_state (kateparse, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - gst_element_set_bus (kateparse, bus); - - test_kate_send_headers (kateparse, myparsesrcpad); - - /* push a text packet */ - inbuffer = - gst_buffer_new_memdup (kate_header_0x00, sizeof (kate_header_0x00)); - GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = - 1 * GST_SECOND; - GST_BUFFER_DURATION (inbuffer) = 5 * GST_SECOND; - GST_BUFFER_OFFSET_END (inbuffer) = (GST_BUFFER_TIMESTAMP (inbuffer) << 32); /* granpos */ - fail_unless_equals_int (gst_pad_push (myparsesrcpad, inbuffer), GST_FLOW_OK); - - /* push a eos packet */ - inbuffer = - gst_buffer_new_memdup (kate_header_0x7f, sizeof (kate_header_0x7f)); - GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_OFFSET (inbuffer) = - 6 * GST_SECOND; - GST_BUFFER_DURATION (inbuffer) = 0; - GST_BUFFER_OFFSET_END (inbuffer) = (GST_BUFFER_TIMESTAMP (inbuffer) << 32); /* granpos */ - fail_unless_equals_int (gst_pad_push (myparsesrcpad, inbuffer), GST_FLOW_OK); - - /* signal eos */ - fail_unless (gst_pad_push_event (myparsesrcpad, - gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (kateparse, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* at least one data packet and one EOS packet should have been emitted */ - check_buffers (2, TRUE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (kateparse, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_kateparse (kateparse); - g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL); - gst_check_drop_buffers (); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_tag_passthrough) -{ - GstElement *katetag; - GstBus *bus; - GstBuffer *outbuffer; - GList *list; - GstMapInfo info; - - katetag = setup_katetag (); - fail_unless (gst_element_set_state (katetag, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - gst_element_set_bus (katetag, bus); - - test_kate_send_headers (katetag, mytagsrcpad); - - /* signal eos */ - fail_unless (gst_pad_push_event (mytagsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (katetag, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* get the first buffer and check language/category */ - fail_unless (g_list_length (buffers) >= 2); /* ID header, Vorbis comments header */ - outbuffer = GST_BUFFER (buffers->data); - fail_if (outbuffer == NULL); - - /* check identification header is unchanged */ - list = g_list_nth (buffers, 0); - fail_unless (list != NULL); - outbuffer = list->data; - fail_if (gst_buffer_map (outbuffer, &info, GST_MAP_READ) != TRUE); - fail_unless_equals_int (info.size, sizeof (kate_header_0x80)); - fail_unless_equals_int (memcmp (info.data, kate_header_0x80, - sizeof (kate_header_0x80)), 0); - gst_buffer_unmap (outbuffer, &info); - - /* check comment header is unchanged */ - list = g_list_nth (buffers, 1); - fail_unless (list != NULL); - outbuffer = list->data; - fail_if (gst_buffer_map (outbuffer, &info, GST_MAP_READ) != TRUE); - fail_unless_equals_int (info.size, sizeof (kate_header_0x81)); - fail_unless_equals_int (memcmp (info.data, kate_header_0x81, - sizeof (kate_header_0x81)), 0); - gst_buffer_unmap (outbuffer, &info); - - /* all headers should have been emitted, but no particular packets */ - check_buffers (0, TRUE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (katetag, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_katetag (katetag); - gst_check_drop_buffers (); -} - -GST_END_TEST; - -GST_START_TEST (test_kate_tag) -{ - GstElement *katetag; - GstBus *bus; - GstBuffer *outbuffer; - GstMapInfo info; - - katetag = setup_katetag (); - fail_unless (gst_element_set_state (katetag, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - bus = gst_bus_new (); - - gst_element_set_bus (katetag, bus); - - g_object_set (katetag, "language", "cy", NULL); - g_object_set (katetag, "category", "subtitles", NULL); - - test_kate_send_headers (katetag, mytagsrcpad); - - /* signal eos */ - fail_unless (gst_pad_push_event (mytagsrcpad, gst_event_new_eos ()) == TRUE); - - fail_unless (gst_element_set_state (katetag, - GST_STATE_READY) == GST_STATE_CHANGE_SUCCESS, - "could not set to ready"); - - /* get the first buffer and check language/category */ - fail_unless (g_list_length (buffers) >= 1); - outbuffer = GST_BUFFER (buffers->data); - fail_if (outbuffer == NULL); - assert_equals_int (gst_buffer_map (outbuffer, &info, GST_MAP_READ), TRUE); - fail_if (info.size != 64); - fail_if (strcmp ((const char *) info.data + 32, "cy")); - fail_if (strcmp ((const char *) info.data + 48, "subtitles")); - gst_buffer_unmap (outbuffer, &info); - - /* all headers should have been emitted, but no particular packets */ - check_buffers (0, TRUE); - - /* cleanup */ - gst_bus_set_flushing (bus, TRUE); - gst_element_set_bus (katetag, NULL); - gst_object_unref (GST_OBJECT (bus)); - cleanup_katetag (katetag); - gst_check_drop_buffers (); -} - -GST_END_TEST; - -static Suite * -kate_suite (void) -{ - Suite *s = suite_create ("kate"); - TCase *tc_chain = tcase_create ("general"); - - suite_add_tcase (s, tc_chain); - - tcase_add_test (tc_chain, test_kate_typefind); - tcase_add_test (tc_chain, test_kate_empty_identification_header); - tcase_add_test (tc_chain, test_kate_identification_header); - tcase_add_test (tc_chain, test_kate_encode_nothing); - tcase_add_test (tc_chain, test_kate_encode_empty); - tcase_add_test (tc_chain, test_kate_encode_simple); - tcase_add_test (tc_chain, test_kate_encode_spu); - tcase_add_test (tc_chain, test_kate_encode_keepalives); - tcase_add_test (tc_chain, test_kate_parse); - tcase_add_test (tc_chain, test_kate_tag_passthrough); - tcase_add_test (tc_chain, test_kate_tag); - - return s; -} - -GST_CHECK_MAIN (kate); diff --git a/subprojects/gst-plugins-bad/tests/check/meson.build b/subprojects/gst-plugins-bad/tests/check/meson.build index bcd7c4d0de..522a4884cc 100644 --- a/subprojects/gst-plugins-bad/tests/check/meson.build +++ b/subprojects/gst-plugins-bad/tests/check/meson.build @@ -140,8 +140,6 @@ if host_machine.system() != 'windows' [['elements/jifmux.c'], not exif_dep.found() or not cdata.has('HAVE_UNISTD_H'), [exif_dep]], [['elements/jpegparse.c'], not cdata.has('HAVE_UNISTD_H')], - [['elements/kate.c'], - not kate_dep.found() or not cdata.has('HAVE_UNISTD_H'), [kate_dep]], [['elements/netsim.c']], [['elements/shm.c'], not shm_enabled, shm_deps], [['elements/voaacenc.c'],