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'],