diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 21 | ||||
-rw-r--r-- | docs/plugins/Makefile.am | 1 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-docs.sgml | 1 | ||||
-rw-r--r-- | docs/plugins/gst-plugins-bad-plugins-sections.txt | 14 | ||||
-rw-r--r-- | docs/plugins/inspect/plugin-tremor.xml | 58 | ||||
-rw-r--r-- | ext/Makefile.am | 6 | ||||
-rw-r--r-- | ext/ivorbis/Makefile.am | 13 | ||||
-rw-r--r-- | ext/ivorbis/vorbis.c | 53 | ||||
-rw-r--r-- | ext/ivorbis/vorbisdec.c | 1249 | ||||
-rw-r--r-- | ext/ivorbis/vorbisdec.h | 89 | ||||
-rw-r--r-- | ext/ivorbis/vorbisenc.h | 100 | ||||
-rw-r--r-- | ext/ivorbis/vorbisfile.c | 1412 |
13 files changed, 2 insertions, 3017 deletions
diff --git a/Makefile.am b/Makefile.am index 9b6bb2049..47cade25c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -45,6 +45,7 @@ CRUFT_FILES = \ $(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} + $(top_builddir)/ext/ivorbis/.libs/*.{so,dll,DLL,dylib} CRUFT_DIRS = \ $(top_srcdir)/gst/aacparse \ @@ -52,6 +53,7 @@ CRUFT_DIRS = \ $(top_srcdir)/gst/flacparse \ $(top_srcdir)/gst/shapewipe \ $(top_srcdir)/tests/examples/shapewipe + $(top_srcdir)/ext/ivorbis include $(top_srcdir)/common/cruft.mak diff --git a/configure.ac b/configure.ac index 825c227a1..804aee198 100644 --- a/configure.ac +++ b/configure.ac @@ -872,25 +872,6 @@ AG_GST_CHECK_FEATURE(GSM, [GSM library], gsmenc gsmdec, [ AC_SUBST(GSM_LIBS) ]) -dnl *** ivorbis *** -dnl AM_PATH_IVORBIS only takes two options -translit(dnm, m, l) AM_CONDITIONAL(USE_IVORBIS, true) -AG_GST_CHECK_FEATURE(IVORBIS, [integer vorbis plug-in], ivorbisdec, [ - IVORBIS_LIBS= - IVORBIS_CFLAGS= - AC_CHECK_LIB(vorbisidec, vorbis_block_init, - [IVORBIS_LIBS=-lvorbisidec - HAVE_IVORBIS=yes - case $host in - arm-*-*) - IVORBIS_CFLAGS="-D_ARM_ASSEM_ $IVORBIS_CFLAGS" - esac - ], - HAVE_IVORBIS=no) - AC_SUBST(IVORBIS_LIBS) - AC_SUBST(IVORBIS_CFLAGS) -]) - dnl *** Jack *** translit(dnm, m, l) AM_CONDITIONAL(USE_JACK, true) AG_GST_CHECK_FEATURE(JACK, Jack, jack, [ @@ -1533,7 +1514,6 @@ AM_CONDITIONAL(USE_FAAC, false) AM_CONDITIONAL(USE_FAAD, false) AM_CONDITIONAL(USE_FBDEV, false) AM_CONDITIONAL(USE_GSM, false) -AM_CONDITIONAL(USE_IVORBIS, false) AM_CONDITIONAL(USE_JACK, false) AM_CONDITIONAL(USE_JP2K, false) AM_CONDITIONAL(USE_KATE, false) @@ -1739,7 +1719,6 @@ ext/faac/Makefile ext/faad/Makefile ext/flite/Makefile ext/gsm/Makefile -ext/ivorbis/Makefile ext/jack/Makefile ext/jp2k/Makefile ext/kate/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index e184fc2c4..32140a2b8 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -96,7 +96,6 @@ EXTRA_HFILES = \ $(top_srcdir)/ext/dc1394/gstdc1394.h \ $(top_srcdir)/ext/directfb/dfbvideosink.h \ $(top_srcdir)/ext/dts/gstdtsdec.h \ - $(top_srcdir)/ext/ivorbis/vorbisdec.h \ $(top_srcdir)/ext/faac/gstfaac.h \ $(top_srcdir)/ext/faad/gstfaad.h \ $(top_srcdir)/ext/jack/gstjackaudiosrc.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index d87ffdcf7..d76de3959 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -48,7 +48,6 @@ <xi:include href="xml/element-flacparse.xml" /> <xi:include href="xml/element-fpsdisplaysink.xml" /> <xi:include href="xml/element-input-selector.xml" /> - <xi:include href="xml/element-ivorbisdec.xml" /> <xi:include href="xml/element-jackaudiosrc.xml" /> <xi:include href="xml/element-jackaudiosink.xml" /> <xi:include href="xml/element-jpegparse.xml" /> diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 508ef718c..3be871dc1 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -499,20 +499,6 @@ GST_INPUT_SELECTOR_WAIT </SECTION> <SECTION> -<FILE>element-ivorbisdec</FILE> -<TITLE>ivorbisdec</TITLE> -GstIVorbisDec -<SUBSECTION Standard> -GstIVorbisDecClass -GST_IVORBIS_DEC -GST_IVORBIS_DEC_CLASS -GST_IS_IVORBIS_DEC -GST_IS_IVORBIS_DEC_CLASS -GST_TYPE_IVORBIS_DEC -gst_ivorbis_dec_get_type -</SECTION> - -<SECTION> <FILE>element-jackaudiosrc</FILE> <TITLE>jackaudiosrc</TITLE> GstJackAudioSrc diff --git a/docs/plugins/inspect/plugin-tremor.xml b/docs/plugins/inspect/plugin-tremor.xml deleted file mode 100644 index 468bc8d0c..000000000 --- a/docs/plugins/inspect/plugin-tremor.xml +++ /dev/null @@ -1,58 +0,0 @@ -<plugin> - <name>tremor</name> - <description>OGG Vorbis Tremor plugins element</description> - <filename>../../ext/ivorbis/.libs/libgstivorbis.so</filename> - <basename>libgstivorbis.so</basename> - <version>0.10.6.1</version> - <license>LGPL</license> - <source>gst-plugins-bad</source> - <package>GStreamer Bad Plug-ins source release</package> - <origin>Unknown package origin</origin> - <elements> - <element> - <name>ivorbisdec</name> - <longname>Vorbis audio decoder</longname> - <class>Codec/Decoder/Audio</class> - <description>decode raw vorbis streams to integer audio</description> - <author>Benjamin Otte <in7y118@public.uni-hamburg.de> - Chris Lord <chris@openedhand.com></author> - <pads> - <caps> - <name>src</name> - <direction>source</direction> - <presence>always</presence> - <details>audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 6 ], endianness=(int)1234, width=(int)32, depth=(int)16, signed=(boolean)true</details> - </caps> - <caps> - <name>sink</name> - <direction>sink</direction> - <presence>always</presence> - <details>audio/x-vorbis</details> - </caps> - </pads> - </element> - <element> - <name>tremor</name> - <longname>Ogg Vorbis audio decoder</longname> - <class>Codec/Decoder/Audio</class> - <description>Decodes OGG Vorbis audio using the Tremor vorbisfile API</description> - <author>Monty <monty@xiph.org> - Wim Taymans <wim.taymans@chello.be> - Amaury Jacquot <sxpert@esitcom.org></author> - <pads> - <caps> - <name>sink</name> - <direction>sink</direction> - <presence>always</presence> - <details>application/ogg</details> - </caps> - <caps> - <name>src</name> - <direction>source</direction> - <presence>always</presence> - <details>audio/x-raw-float, depth=(int)32, endianness=(int)1234, rate=(int)[ 11025, 48000 ], channels=(int)2; audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 11025, 48000 ], channels=(int)[ 1, 2 ]</details> - </caps> - </pads> - </element> - </elements> -</plugin>
\ No newline at end of file diff --git a/ext/Makefile.am b/ext/Makefile.am index 4f3c00a95..1e239464a 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -142,12 +142,6 @@ endif HERMES_DIR= # endif -if USE_IVORBIS - IVORBIS_DIR=ivorbis -else - IVORBIS_DIR= -endif - if USE_JACK JACK_DIR=jack else diff --git a/ext/ivorbis/Makefile.am b/ext/ivorbis/Makefile.am deleted file mode 100644 index 83db5eaba..000000000 --- a/ext/ivorbis/Makefile.am +++ /dev/null @@ -1,13 +0,0 @@ -plugin_LTLIBRARIES = libgstivorbis.la - -libgstivorbis_la_SOURCES = vorbis.c vorbisfile.c vorbisdec.c -libgstivorbis_la_CFLAGS = $(GST_CFLAGS) $(IVORBIS_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -libgstivorbis_la_LIBADD = $(IVORBIS_LIBS) \ - $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE_LIBS) \ - -lgstaudio-@GST_MAJORMINOR@ \ - -lgsttag-@GST_MAJORMINOR@ -libgstivorbis_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstivorbis_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = vorbisdec.h vorbisenc.h diff --git a/ext/ivorbis/vorbis.c b/ext/ivorbis/vorbis.c deleted file mode 100644 index 368b7f398..000000000 --- a/ext/ivorbis/vorbis.c +++ /dev/null @@ -1,53 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gst/gst.h> -#include <tremor/ivorbiscodec.h> -#include "vorbisdec.h" - -GST_DEBUG_CATEGORY (vorbisdec_debug); - -extern GType ivorbisfile_get_type (void); - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "tremor", GST_RANK_SECONDARY, - ivorbisfile_get_type ())) - return FALSE; - - if (!gst_element_register (plugin, "ivorbisdec", GST_RANK_SECONDARY, - gst_ivorbis_dec_get_type ())) - return FALSE; - - GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "ivorbisdec", 0, - "vorbis decoding element (integer decoder)"); - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "tremor", - "OGG Vorbis Tremor plugins element", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/ivorbis/vorbisdec.c b/ext/ivorbis/vorbisdec.c deleted file mode 100644 index 7e6b85343..000000000 --- a/ext/ivorbis/vorbisdec.c +++ /dev/null @@ -1,1249 +0,0 @@ -/* GStreamer - * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de> - * - * Tremor modifications <2006>: - * Chris Lord, OpenedHand Ltd. <chris@openedhand.com>, http://www.o-hand.com/ - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-ivorbisdec - * @see_also: vorbisenc, oggdemux - * - * This element decodes a Vorbis stream to raw int audio. - * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free - * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org - * Foundation</ulink>. The decoder uses integer math to be more suitable for - * embedded devices. - * - * <refsect2> - * <title>Example pipelines</title> - * |[ - * gst-launch -v filesrc location=sine.ogg ! oggdemux ! ivorbisdec ! audioconvert ! alsasink - * ]| Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the - * documentation of vorbisenc. - * </refsect2> - * - * Last reviewed on 2006-03-01 (0.10.4) - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include "vorbisdec.h" -#include <string.h> -#include <gst/audio/audio.h> -#include <gst/tag/tag.h> -#include <gst/audio/multichannel.h> - -GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug); -#define GST_CAT_DEFAULT vorbisdec_debug - -static const GstElementDetails vorbis_dec_details = -GST_ELEMENT_DETAILS ("Vorbis audio decoder", - "Codec/Decoder/Audio", - "decode raw vorbis streams to integer audio", - "Benjamin Otte <in7y118@public.uni-hamburg.de>\n" - "Chris Lord <chris@openedhand.com>"); - -static GstStaticPadTemplate vorbis_dec_src_factory = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int, " - "rate = (int) [ 1, MAX ], " - "channels = (int) [ 1, 6 ], " - "endianness = (int) BYTE_ORDER, " - "width = (int) { 16, 32 }, " - "depth = (int) 16, " "signed = (boolean) true") - ); - -static GstStaticPadTemplate vorbis_dec_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-vorbis") - ); - -GST_BOILERPLATE (GstIVorbisDec, gst_ivorbis_dec, GstElement, GST_TYPE_ELEMENT); - -static void vorbis_dec_finalize (GObject * object); -static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event); -static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer); -static GstStateChangeReturn vorbis_dec_change_state (GstElement * element, - GstStateChange transition); - -static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event); -static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query); -static gboolean vorbis_dec_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value); - -static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query); - -static void -gst_ivorbis_dec_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstPadTemplate *src_template, *sink_template; - - src_template = gst_static_pad_template_get (&vorbis_dec_src_factory); - gst_element_class_add_pad_template (element_class, src_template); - - sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory); - gst_element_class_add_pad_template (element_class, sink_template); - - gst_element_class_set_details (element_class, &vorbis_dec_details); -} - -static void -gst_ivorbis_dec_class_init (GstIVorbisDecClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = vorbis_dec_finalize; - - gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state); -} - -static const GstQueryType * -vorbis_get_query_types (GstPad * pad) -{ - static const GstQueryType vorbis_dec_src_query_types[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_CONVERT, - 0 - }; - - return vorbis_dec_src_query_types; -} - -static void -gst_ivorbis_dec_init (GstIVorbisDec * dec, GstIVorbisDecClass * g_class) -{ - dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory, - "sink"); - - gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (vorbis_dec_sink_event)); - gst_pad_set_chain_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (vorbis_dec_chain)); - gst_pad_set_query_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (vorbis_dec_sink_query)); - gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); - - dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory, - "src"); - - gst_pad_set_event_function (dec->srcpad, - GST_DEBUG_FUNCPTR (vorbis_dec_src_event)); - gst_pad_set_query_type_function (dec->srcpad, - GST_DEBUG_FUNCPTR (vorbis_get_query_types)); - gst_pad_set_query_function (dec->srcpad, - GST_DEBUG_FUNCPTR (vorbis_dec_src_query)); - gst_pad_use_fixed_caps (dec->srcpad); - gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); - - dec->queued = NULL; - dec->pendingevents = NULL; - dec->taglist = NULL; -} - -static void -vorbis_dec_finalize (GObject * object) -{ - /* Release any possibly allocated libvorbis data. - * _clear functions can safely be called multiple times - */ - GstIVorbisDec *vd = GST_IVORBIS_DEC (object); - - vorbis_block_clear (&vd->vb); - vorbis_dsp_clear (&vd->vd); - vorbis_comment_clear (&vd->vc); - vorbis_info_clear (&vd->vi); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_ivorbis_dec_reset (GstIVorbisDec * dec) -{ - GList *walk; - - dec->cur_timestamp = GST_CLOCK_TIME_NONE; - dec->prev_timestamp = GST_CLOCK_TIME_NONE; - dec->granulepos = -1; - dec->discont = TRUE; - gst_segment_init (&dec->segment, GST_FORMAT_TIME); - - for (walk = dec->queued; walk; walk = g_list_next (walk)) { - gst_buffer_unref (GST_BUFFER_CAST (walk->data)); - } - g_list_free (dec->queued); - dec->queued = NULL; - - for (walk = dec->pendingevents; walk; walk = g_list_next (walk)) { - gst_event_unref (GST_EVENT_CAST (walk->data)); - } - g_list_free (dec->pendingevents); - dec->pendingevents = NULL; - - if (dec->taglist) - gst_tag_list_free (dec->taglist); - dec->taglist = NULL; -} - - -static gboolean -vorbis_dec_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - GstIVorbisDec *dec; - guint64 scale = 1; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - if (!dec->initialized) - goto no_header; - - if (dec->sinkpad == pad && - (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) - goto no_format; - - switch (src_format) { - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_BYTES: - scale = dec->width * dec->vi.channels; - case GST_FORMAT_DEFAULT: - *dest_value = - scale * gst_util_uint64_scale_int (src_value, dec->vi.rate, - GST_SECOND); - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_BYTES: - *dest_value = src_value * dec->width * dec->vi.channels; - break; - case GST_FORMAT_TIME: - *dest_value = - gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate); - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_BYTES: - switch (*dest_format) { - case GST_FORMAT_DEFAULT: - *dest_value = src_value / (dec->width * dec->vi.channels); - break; - case GST_FORMAT_TIME: - *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, - dec->vi.rate * dec->width * dec->vi.channels); - break; - default: - res = FALSE; - } - break; - default: - res = FALSE; - } -done: - gst_object_unref (dec); - - return res; - - /* ERRORS */ -no_header: - { - GST_DEBUG_OBJECT (dec, "no header packets received"); - res = FALSE; - goto done; - } -no_format: - { - GST_DEBUG_OBJECT (dec, "formats unsupported"); - res = FALSE; - goto done; - } -} - -static gboolean -vorbis_dec_src_query (GstPad * pad, GstQuery * query) -{ - GstIVorbisDec *dec; - gboolean res = FALSE; - - dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - gint64 granulepos, value; - GstFormat my_format, format; - gint64 time; - - /* we start from the last seen granulepos */ - granulepos = dec->granulepos; - - gst_query_parse_position (query, &format, NULL); - - /* and convert to the final format in two steps with time as the - * intermediate step */ - my_format = GST_FORMAT_TIME; - if (!(res = - vorbis_dec_convert (pad, GST_FORMAT_DEFAULT, granulepos, - &my_format, &time))) - goto error; - - /* correct for the segment values */ - time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time); - - GST_LOG_OBJECT (dec, - "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time)); - - /* and convert to the final format */ - if (!(res = vorbis_dec_convert (pad, my_format, time, &format, &value))) - goto error; - - gst_query_set_position (query, format, value); - - GST_LOG_OBJECT (dec, - "query %p: we return %lld (format %u)", query, value, format); - - break; - } - case GST_QUERY_DURATION: - { - GstPad *peer; - - if (!(peer = gst_pad_get_peer (dec->sinkpad))) { - GST_WARNING_OBJECT (dec, "sink pad %" GST_PTR_FORMAT " is not linked", - dec->sinkpad); - goto error; - } - - res = gst_pad_query (peer, query); - gst_object_unref (peer); - if (!res) - 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 = - vorbis_dec_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; - } -done: - gst_object_unref (dec); - - return res; - - /* ERRORS */ -error: - { - GST_WARNING_OBJECT (dec, "error handling query"); - goto done; - } -} - -static gboolean -vorbis_dec_sink_query (GstPad * pad, GstQuery * query) -{ - GstIVorbisDec *dec; - gboolean res; - - dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - 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 (!(res = - vorbis_dec_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; - } - -done: - gst_object_unref (dec); - - return res; - - /* ERRORS */ -error: - { - GST_DEBUG_OBJECT (dec, "error converting value"); - goto done; - } -} - -static gboolean -vorbis_dec_src_event (GstPad * pad, GstEvent * event) -{ - gboolean res = TRUE; - GstIVorbisDec *dec; - - dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - GstFormat format, tformat; - gdouble rate; - GstEvent *real_seek; - GstSeekFlags flags; - GstSeekType cur_type, stop_type; - gint64 cur, stop; - gint64 tcur, tstop; - - gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, - &stop_type, &stop); - gst_event_unref (event); - - /* we have to ask our peer to seek to time here as we know - * nothing about how to generate a granulepos from the src - * formats or anything. - * - * First bring the requested format to time - */ - tformat = GST_FORMAT_TIME; - if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur))) - goto convert_error; - if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop))) - goto convert_error; - - /* then seek with time on the peer */ - real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, - flags, cur_type, tcur, stop_type, tstop); - - res = gst_pad_push_event (dec->sinkpad, real_seek); - - break; - } - default: - res = gst_pad_push_event (dec->sinkpad, event); - break; - } -done: - gst_object_unref (dec); - - return res; - - /* ERRORS */ -convert_error: - { - GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek"); - goto done; - } -} - -static gboolean -vorbis_dec_sink_event (GstPad * pad, GstEvent * event) -{ - gboolean ret = FALSE; - GstIVorbisDec *dec; - - dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - GST_LOG_OBJECT (dec, "handling event"); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - ret = gst_pad_push_event (dec->srcpad, event); - break; - case GST_EVENT_FLUSH_START: - ret = gst_pad_push_event (dec->srcpad, event); - break; - case GST_EVENT_FLUSH_STOP: - /* here we must clean any state in the decoder */ -#ifdef HAVE_VORBIS_SYNTHESIS_RESTART - vorbis_synthesis_restart (&dec->vd); -#endif - gst_ivorbis_dec_reset (dec); - ret = gst_pad_push_event (dec->srcpad, event); - break; - case GST_EVENT_NEWSEGMENT: - { - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - gboolean update; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - /* we need time and a positive rate for now */ - if (format != GST_FORMAT_TIME) - goto newseg_wrong_format; - - if (rate <= 0.0) - goto newseg_wrong_rate; - - GST_DEBUG_OBJECT (dec, - "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT - ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, - update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), - GST_TIME_ARGS (time)); - - /* now configure the values */ - gst_segment_set_newsegment_full (&dec->segment, update, - rate, arate, format, start, stop, time); - - if (dec->initialized) - /* and forward */ - ret = gst_pad_push_event (dec->srcpad, event); - else { - /* store it to send once we're initialized */ - dec->pendingevents = g_list_append (dec->pendingevents, event); - ret = TRUE; - } - break; - } - default: - ret = gst_pad_push_event (dec->srcpad, event); - break; - } -done: - gst_object_unref (dec); - - return ret; - - /* ERRORS */ -newseg_wrong_format: - { - GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); - goto done; - } -newseg_wrong_rate: - { - GST_DEBUG_OBJECT (dec, "negative rates not supported yet"); - goto done; - } -} - -static GstFlowReturn -vorbis_handle_identification_packet (GstIVorbisDec * vd) -{ - GstCaps *caps; - const GstAudioChannelPosition *pos = NULL; - gint width = 16; - - switch (vd->vi.channels) { - case 1: - case 2: - /* nothing */ - break; - case 3:{ - static const GstAudioChannelPosition pos3[] = { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT - }; - pos = pos3; - break; - } - case 4:{ - static const GstAudioChannelPosition pos4[] = { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT - }; - pos = pos4; - break; - } - case 5:{ - static const GstAudioChannelPosition pos5[] = { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT - }; - pos = pos5; - break; - } - case 6:{ - static const GstAudioChannelPosition pos6[] = { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_LFE - }; - pos = pos6; - break; - } - default: - goto channel_count_error; - } - - /* negotiate with downstream */ - caps = gst_pad_get_allowed_caps (vd->srcpad); - if (caps) { - if (!gst_caps_is_empty (caps)) { - GstStructure *s; - - s = gst_caps_get_structure (caps, 0); - /* template ensures 16 or 32 */ - gst_structure_get_int (s, "width", &width); - } - gst_caps_unref (caps); - } - vd->width = width >> 3; - - caps = gst_caps_new_simple ("audio/x-raw-int", - "rate", G_TYPE_INT, vd->vi.rate, - "channels", G_TYPE_INT, vd->vi.channels, - "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, width, - "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL); - - if (pos) { - gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); - } - gst_pad_set_caps (vd->srcpad, caps); - gst_caps_unref (caps); - - return GST_FLOW_OK; - - /* ERROR */ -channel_count_error: - { - GST_ELEMENT_ERROR (vd, STREAM, NOT_IMPLEMENTED, (NULL), - ("Unsupported channel count %d", vd->vi.channels)); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -vorbis_handle_comment_packet (GstIVorbisDec * vd, ogg_packet * packet) -{ - guint bitrate = 0; - gchar *encoder = NULL; - GstTagList *list, *old_list; - GstBuffer *buf; - - GST_DEBUG_OBJECT (vd, "parsing comment packet"); - - buf = gst_buffer_new (); - GST_BUFFER_DATA (buf) = packet->packet->buffer->data; - GST_BUFFER_SIZE (buf) = packet->packet->buffer->size; - - list = - gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7, - &encoder); - - old_list = vd->taglist; - vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE); - - if (old_list) - gst_tag_list_free (old_list); - gst_tag_list_free (list); - gst_buffer_unref (buf); - - if (!vd->taglist) { - GST_ERROR_OBJECT (vd, "couldn't decode comments"); - vd->taglist = gst_tag_list_new (); - } - if (encoder) { - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_ENCODER, encoder, NULL); - g_free (encoder); - } - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_ENCODER_VERSION, vd->vi.version, - GST_TAG_AUDIO_CODEC, "Vorbis", NULL); - if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) { - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL); - bitrate = vd->vi.bitrate_nominal; - } - if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) { - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL); - if (!bitrate) - bitrate = vd->vi.bitrate_upper; - } - if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) { - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL); - if (!bitrate) - bitrate = vd->vi.bitrate_lower; - } - if (bitrate) { - gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_BITRATE, (guint) bitrate, NULL); - } - - if (vd->initialized) { - gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad, - vd->taglist); - vd->taglist = NULL; - } else { - /* Only post them as messages for the time being. * - * They will be pushed on the pad once the decoder is initialized */ - gst_element_post_message (GST_ELEMENT_CAST (vd), - gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist))); - } - - return GST_FLOW_OK; -} - -static GstFlowReturn -vorbis_handle_type_packet (GstIVorbisDec * vd) -{ - GList *walk; - - g_assert (vd->initialized == FALSE); - - vorbis_synthesis_init (&vd->vd, &vd->vi); - vorbis_block_init (&vd->vd, &vd->vb); - vd->initialized = TRUE; - - if (vd->pendingevents) { - for (walk = vd->pendingevents; walk; walk = g_list_next (walk)) - gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data)); - g_list_free (vd->pendingevents); - vd->pendingevents = NULL; - } - - if (vd->taglist) { - /* The tags have already been sent on the bus as messages. */ - gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist)); - vd->taglist = NULL; - } - - return GST_FLOW_OK; -} - -static GstFlowReturn -vorbis_handle_header_packet (GstIVorbisDec * vd, ogg_packet * packet) -{ - GstFlowReturn res; - - GST_DEBUG_OBJECT (vd, "parsing header packet"); - - /* Packetno = 0 if the first byte is exactly 0x01 */ - packet->b_o_s = packet->packet->length ? - ((packet->packet->buffer->data[0] == 0x1) ? 1 : 0) : 0; - - if (vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet)) - goto header_read_error; - - switch (packet->packet->length ? packet->packet->buffer->data[0] : 0x0) { - case 0x01: - res = vorbis_handle_identification_packet (vd); - break; - case 0x03: - res = vorbis_handle_comment_packet (vd, packet); - break; - case 0x05: - res = vorbis_handle_type_packet (vd); - break; - default: - /* ignore */ - g_warning ("unknown vorbis header packet found"); - res = GST_FLOW_OK; - break; - } - return res; - - /* ERRORS */ -header_read_error: - { - GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, - (NULL), ("couldn't read header packet")); - return GST_FLOW_ERROR; - } -} - -/* Taken from Tremor, misc.h */ -#ifdef _ARM_ASSEM_ -static inline ogg_int32_t -CLIP_TO_15 (ogg_int32_t x) -{ - int tmp; - asm volatile ("subs %1, %0, #32768\n\t" - "movpl %0, #0x7f00\n\t" - "orrpl %0, %0, #0xff\n" - "adds %1, %0, #32768\n\t" - "movmi %0, #0x8000":"+r" (x), "=r" (tmp) - ::"cc"); - - return (x); -} -#else -static inline ogg_int32_t -CLIP_TO_15 (ogg_int32_t x) -{ - int ret = x; - - ret -= ((x <= 32767) - 1) & (x - 32767); - ret -= ((x >= -32768) - 1) & (x + 32768); - return (ret); -} -#endif - -static void -copy_samples (gint32 * out, ogg_int32_t ** in, guint samples, gint channels) -{ - gint i, j; - - for (j = 0; j < samples; j++) { - for (i = 0; i < channels; i++) { - *out++ = CLIP_TO_15 (in[i][j] >> 9); - } - } -} - -static void -copy_samples_16 (gint16 * out, ogg_int32_t ** in, guint samples, gint channels) -{ - gint i, j; - - for (j = 0; j < samples; j++) { - for (i = 0; i < channels; i++) { - *out++ = CLIP_TO_15 (in[i][j] >> 9); - } - } -} - -/* clip output samples to the segment boundaries - */ -static gboolean -vorbis_do_clip (GstIVorbisDec * dec, GstBuffer * buf) -{ - gint64 start, stop, cstart, cstop, diff; - - start = GST_BUFFER_TIMESTAMP (buf); - stop = start + GST_BUFFER_DURATION (buf); - - if (!gst_segment_clip (&dec->segment, GST_FORMAT_TIME, - start, stop, &cstart, &cstop)) - goto clipped; - - /* see if some clipping happened */ - diff = cstart - start; - if (diff > 0) { - GST_BUFFER_TIMESTAMP (buf) = cstart; - GST_BUFFER_DURATION (buf) -= diff; - - /* bring clipped time to samples */ - diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND); - /* samples to bytes */ - diff *= (dec->width * dec->vi.channels); - GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %" - G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff); - GST_BUFFER_DATA (buf) += diff; - GST_BUFFER_SIZE (buf) -= diff; - } - diff = stop - cstop; - if (diff > 0) { - GST_BUFFER_DURATION (buf) -= diff; - - /* bring clipped time to samples and then to bytes */ - diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND); - diff *= (dec->width * dec->vi.channels); - GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %" - G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff); - GST_BUFFER_SIZE (buf) -= diff; - } - - return FALSE; - - /* dropped buffer */ -clipped: - { - GST_DEBUG_OBJECT (dec, "clipped buffer"); - gst_buffer_unref (buf); - return TRUE; - } -} - -static GstFlowReturn -vorbis_dec_push (GstIVorbisDec * dec, GstBuffer * buf) -{ - GstFlowReturn result; - gint64 outoffset = GST_BUFFER_OFFSET (buf); - - if (outoffset == -1) { - dec->queued = g_list_append (dec->queued, buf); - GST_DEBUG_OBJECT (dec, "queued buffer"); - result = GST_FLOW_OK; - } else { - if (G_UNLIKELY (dec->queued)) { - gint64 size; - GList *walk; - - GST_DEBUG_OBJECT (dec, "first buffer with offset %lld", outoffset); - - size = g_list_length (dec->queued); - for (walk = g_list_last (dec->queued); walk; - walk = g_list_previous (walk)) { - GstBuffer *buffer = GST_BUFFER (walk->data); - - outoffset -= GST_BUFFER_SIZE (buffer) / (dec->width * dec->vi.channels); - - GST_BUFFER_OFFSET (buffer) = outoffset; - GST_BUFFER_TIMESTAMP (buffer) = - gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate); - GST_DEBUG_OBJECT (dec, "patch buffer %" G_GUINT64_FORMAT - " offset %" G_GUINT64_FORMAT, size, outoffset); - size--; - } - for (walk = dec->queued; walk; walk = g_list_next (walk)) { - GstBuffer *buffer = GST_BUFFER (walk->data); - - /* clips or returns FALSE with buffer unreffed when completely - * clipped */ - if (vorbis_do_clip (dec, buffer)) - continue; - - if (dec->discont) { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - dec->discont = FALSE; - } - /* ignore the result */ - gst_pad_push (dec->srcpad, buffer); - } - g_list_free (dec->queued); - dec->queued = NULL; - } - - /* clip */ - if (vorbis_do_clip (dec, buf)) - return GST_FLOW_OK; - - if (dec->discont) { - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - dec->discont = FALSE; - } - result = gst_pad_push (dec->srcpad, buf); - } - - return result; -} - -static GstFlowReturn -vorbis_handle_data_packet (GstIVorbisDec * vd, ogg_packet * packet) -{ - ogg_int32_t **pcm; - guint sample_count; - GstBuffer *out; - GstFlowReturn result; - gint size; - - if (!vd->initialized) - goto not_initialized; - - /* FIXME, we should queue undecoded packets here until we get - * a timestamp, then we reverse timestamp the queued packets and - * clip them, then we decode only the ones we want and don't - * keep decoded data in memory. - * Ideally, of course, the demuxer gives us a valid timestamp on - * the first packet. - */ - - /* normal data packet */ - /* FIXME, we can skip decoding if the packet is outside of the - * segment, this is however not very trivial as we need a previous - * packet to decode the current one so we must be carefull not to - * throw away too much. For now we decode everything and clip right - * before pushing data. */ - if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet, 1))) - goto could_not_read; - - if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0)) - goto not_accepted; - - /* assume all goes well here */ - result = GST_FLOW_OK; - - /* count samples ready for reading */ - if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0) - goto done; - - size = sample_count * vd->vi.channels * vd->width; - - /* alloc buffer for it */ - result = - gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE, - size, GST_PAD_CAPS (vd->srcpad), &out); - if (G_UNLIKELY (result != GST_FLOW_OK)) - goto done; - - /* get samples ready for reading now, should be sample_count */ - if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count)) - goto wrong_samples; - - /* copy samples in buffer */ - if (vd->width == 4) { - copy_samples ((gint32 *) GST_BUFFER_DATA (out), pcm, sample_count, - vd->vi.channels); - } else if (vd->width == 2) { - copy_samples_16 ((gint16 *) GST_BUFFER_DATA (out), pcm, sample_count, - vd->vi.channels); - } else { - g_assert_not_reached (); - } - - GST_BUFFER_SIZE (out) = size; - GST_BUFFER_OFFSET (out) = vd->granulepos; - if (vd->granulepos != -1) { - GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count; - GST_BUFFER_TIMESTAMP (out) = - gst_util_uint64_scale_int (vd->granulepos, GST_SECOND, vd->vi.rate); - } else { - GST_BUFFER_TIMESTAMP (out) = -1; - } - /* this should not overflow */ - GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate; - - if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (out) = vd->cur_timestamp; - GST_DEBUG_OBJECT (vd, - "cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = % " - GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp), - GST_TIME_ARGS (GST_BUFFER_DURATION (out)), - GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out))); - vd->cur_timestamp += GST_BUFFER_DURATION (out); - GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp, - vd->vi.rate); - GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count; - } - - if (vd->granulepos != -1) - vd->granulepos += sample_count; - - result = vorbis_dec_push (vd, out); - -done: - vorbis_synthesis_read (&vd->vd, sample_count); - - /* granulepos is the last sample in the packet */ - if (packet->granulepos != -1) - vd->granulepos = packet->granulepos; - - return result; - - /* ERRORS */ -not_initialized: - { - GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, - (NULL), ("no header sent yet")); - return GST_FLOW_ERROR; - } -could_not_read: - { - GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, - (NULL), ("couldn't read data packet")); - return GST_FLOW_ERROR; - } -not_accepted: - { - GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, - (NULL), ("vorbis decoder did not accept data packet")); - return GST_FLOW_ERROR; - } -wrong_samples: - { - gst_buffer_unref (out); - GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, - (NULL), ("vorbis decoder reported wrong number of samples")); - return GST_FLOW_ERROR; - } -} - -static GstFlowReturn -vorbis_dec_chain (GstPad * pad, GstBuffer * buffer) -{ - GstIVorbisDec *vd; - ogg_packet packet; - ogg_reference ref; - ogg_buffer buf; - GstFlowReturn result = GST_FLOW_OK; - GstClockTime timestamp; - guint64 offset_end; - - vd = GST_IVORBIS_DEC (gst_pad_get_parent (pad)); - - /* resync on DISCONT */ - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { - GST_DEBUG_OBJECT (vd, "received DISCONT buffer"); - vd->granulepos = -1; - vd->cur_timestamp = GST_CLOCK_TIME_NONE; - vd->prev_timestamp = GST_CLOCK_TIME_NONE; -#ifdef HAVE_VORBIS_SYNTHESIS_RESTART - vorbis_synthesis_restart (&vd->vd); -#endif - vd->discont = TRUE; - } - - timestamp = GST_BUFFER_TIMESTAMP (buffer); - offset_end = GST_BUFFER_OFFSET_END (buffer); - - /* only ogg has granulepos, demuxers of other container formats - * might provide us with timestamps instead (e.g. matroskademux) */ - if (offset_end == GST_BUFFER_OFFSET_NONE && timestamp != GST_CLOCK_TIME_NONE) { - /* we might get multiple consecutive buffers with the same timestamp */ - if (timestamp != vd->prev_timestamp) { - vd->cur_timestamp = timestamp; - vd->prev_timestamp = timestamp; - } - } else { - vd->cur_timestamp = GST_CLOCK_TIME_NONE; - vd->prev_timestamp = GST_CLOCK_TIME_NONE; - } - - /* make ogg_packet out of the buffer */ - buf.data = GST_BUFFER_DATA (buffer); - buf.size = GST_BUFFER_SIZE (buffer); - buf.refcount = 1; - buf.ptr.owner = NULL; - buf.ptr.next = NULL; - - ref.buffer = &buf; - ref.begin = 0; - ref.length = buf.size; - ref.next = NULL; - - packet.packet = &ref; - packet.bytes = ref.length; - packet.granulepos = offset_end; - packet.packetno = 0; /* we don't care */ - /* - * FIXME. Is there anyway to know that this is the last packet and - * set e_o_s?? - * Yes there is, keep one packet at all times and only push out when - * you receive a new one. Implement this. - */ - packet.e_o_s = 0; - - if (G_UNLIKELY (packet.bytes < 1)) - goto wrong_size; - - GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GINT64_FORMAT, - (gint64) packet.granulepos); - - /* switch depending on packet type */ - if (buf.data[0] & 1) { - if (vd->initialized) { - GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet"); - goto done; - } - result = vorbis_handle_header_packet (vd, &packet); - } else { - result = vorbis_handle_data_packet (vd, &packet); - } - - GST_DEBUG_OBJECT (vd, "offset end: %" G_GUINT64_FORMAT, offset_end); - -done: - gst_buffer_unref (buffer); - gst_object_unref (vd); - - return result; - - /* ERRORS */ -wrong_size: - { - GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty buffer received")); - result = GST_FLOW_ERROR; - vd->discont = TRUE; - goto done; - } -} - -static GstStateChangeReturn -vorbis_dec_change_state (GstElement * element, GstStateChange transition) -{ - GstIVorbisDec *vd = GST_IVORBIS_DEC (element); - GstStateChangeReturn res; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - vorbis_info_init (&vd->vi); - vorbis_comment_init (&vd->vc); - vd->initialized = FALSE; - vd->width = 2; - gst_ivorbis_dec_reset (vd); - 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 (vd, "PAUSED -> READY, clearing vorbis structures"); - vorbis_block_clear (&vd->vb); - vorbis_dsp_clear (&vd->vd); - vorbis_comment_clear (&vd->vc); - vorbis_info_clear (&vd->vi); - gst_ivorbis_dec_reset (vd); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return res; -} diff --git a/ext/ivorbis/vorbisdec.h b/ext/ivorbis/vorbisdec.h deleted file mode 100644 index b5ac46243..000000000 --- a/ext/ivorbis/vorbisdec.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- c-basic-offset: 2 -*- - * GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * Tremor modifications <2006>: - * Chris Lord, OpenedHand Ltd. <chris@openedhand.com>, http://www.o-hand.com/ - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __GST_IVORBIS_DEC_H__ -#define __GST_IVORBIS_DEC_H__ - - -#include <gst/gst.h> -#include <tremor/ivorbiscodec.h> - -G_BEGIN_DECLS - -#define GST_TYPE_IVORBIS_DEC \ - (gst_ivorbis_dec_get_type()) -#define GST_IVORBIS_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IVORBIS_DEC,GstIVorbisDec)) -#define GST_IVORBIS_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IVORBIS_DEC,GstIVorbisDecClass)) -#define GST_IS_IVORBIS_DEC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IVORBIS_DEC)) -#define GST_IS_IVORBIS_DEC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IVORBIS_DEC)) - -typedef struct _GstIVorbisDec GstIVorbisDec; -typedef struct _GstIVorbisDecClass GstIVorbisDecClass; - -/** - * GstIVorbisDec: - * - * Opaque data structure. - */ -struct _GstIVorbisDec { - GstElement element; - - /* < private > */ - GstPad * sinkpad; - GstPad * srcpad; - - vorbis_dsp_state vd; - vorbis_info vi; - vorbis_comment vc; - vorbis_block vb; - guint64 granulepos; - - gboolean initialized; - guint width; - - GList *queued; - - GstSegment segment; - gboolean discont; - - GstClockTime cur_timestamp; /* only used with non-ogg container formats */ - GstClockTime prev_timestamp; /* only used with non-ogg container formats */ - - GList *pendingevents; - GstTagList *taglist; -}; - -struct _GstIVorbisDecClass { - GstElementClass parent_class; -}; - -GType gst_ivorbis_dec_get_type(void); - -G_END_DECLS - -#endif /* __GST_IVORBIS_DEC_H__ */ diff --git a/ext/ivorbis/vorbisenc.h b/ext/ivorbis/vorbisenc.h deleted file mode 100644 index 219082751..000000000 --- a/ext/ivorbis/vorbisenc.h +++ /dev/null @@ -1,100 +0,0 @@ -/* GStreamer - * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> - * - * 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., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - - -#ifndef __VORBISENC_H__ -#define __VORBISENC_H__ - - -#include <gst/gst.h> - -#include <tremor/ivorbiscodec.h> - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#define GST_TYPE_VORBISENC \ - (vorbisenc_get_type()) -#define GST_VORBISENC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBISENC,VorbisEnc)) -#define GST_VORBISENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBISENC,VorbisEncClass)) -#define GST_IS_VORBISENC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBISENC)) -#define GST_IS_VORBISENC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBISENC)) - -typedef struct _VorbisEnc VorbisEnc; -typedef struct _VorbisEncClass VorbisEncClass; - -struct _VorbisEnc { - GstElement element; - - GstPad *sinkpad, - *srcpad; - - ogg_stream_state os; /* take physical pages, weld into a logical - stream of packets */ - ogg_page og; /* one Ogg bitstream page. Vorbis packets are inside */ - ogg_packet op; /* one raw packet of data for decode */ - - vorbis_info vi; /* struct that stores all the static vorbis bitstream - settings */ - vorbis_comment vc; /* struct that stores all the user comments */ - - vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ - vorbis_block vb; /* local working space for packet->PCM decode */ - - gboolean eos; - - gboolean managed; - gint bitrate; - gint min_bitrate; - gint max_bitrate; - gfloat quality; - gboolean quality_set; - gint serial; - - gint channels; - gint frequency; - - guint64 samples_in; - guint64 bytes_out; - - GstCaps *metadata; - - gboolean setup; - gboolean flush_header; - gchar *last_message; -}; - -struct _VorbisEncClass { - GstElementClass parent_class; -}; - -GType vorbisenc_get_type(void); - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - - -#endif /* __VORBISENC_H__ */ diff --git a/ext/ivorbis/vorbisfile.c b/ext/ivorbis/vorbisfile.c deleted file mode 100644 index 6ee71ef0d..000000000 --- a/ext/ivorbis/vorbisfile.c +++ /dev/null @@ -1,1412 +0,0 @@ -/* GStreamer -* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> -* -* 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., 59 Temple Place - Suite 330, -* Boston, MA 02111-1307, USA. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include <string.h> -#include <gst/gst.h> -#include <tremor/ivorbiscodec.h> -#include <tremor/ivorbisfile.h> -#include <gst/base/gstadapter.h> - -GST_DEBUG_CATEGORY_STATIC (ivorbisfile_debug); -#define GST_CAT_DEFAULT ivorbisfile_debug - -#define GST_TYPE_IVORBISFILE \ - (ivorbisfile_get_type()) -#define GST_IVORBISFILE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IVORBISFILE,Ivorbisfile)) -#define GST_IVORBISFILE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IVORBISFILE,IvorbisfileClass)) -#define GST_IS_IVORBISFILE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IVORBISFILE)) -#define GST_IS_IVORBISFILE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IVORBISFILE)) - -typedef struct _Ivorbisfile Ivorbisfile; -typedef struct _IvorbisfileClass IvorbisfileClass; - -struct _Ivorbisfile -{ - GstElement element; - - GstPad *sinkpad, *srcpad; - GstAdapter *adapter; - guint64 adapterOffset; - - OggVorbis_File vf; - gint current_link; - - gboolean restart; - gboolean need_discont; - gboolean eos; - gboolean seek_pending; - gint64 seek_value; - GstFormat seek_format; - gboolean seek_accurate; - - gboolean may_eos; - guint64 total_bytes; - guint64 offset; - - gint rate; - gint channels; - gint width; - - GstCaps *metadata; - GstCaps *streaminfo; -}; - -struct _IvorbisfileClass -{ - GstElementClass parent_class; - -}; - -GType ivorbisfile_get_type (void); - -static GstPadTemplate *gst_vorbisdec_src_template, *gst_vorbisdec_sink_template; - -/* elementfactory information */ -static const GstElementDetails ivorbisfile_details = -GST_ELEMENT_DETAILS ("Ogg Vorbis audio decoder", - "Codec/Decoder/Audio", - "Decodes OGG Vorbis audio using the Tremor vorbisfile API", - "Monty <monty@xiph.org>\n" - "Wim Taymans <wim.taymans@chello.be>\n" - "Amaury Jacquot <sxpert@esitcom.org>"); - -/* Ivorbisfile signals and args */ -enum -{ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_METADATA, - ARG_STREAMINFO -}; - -static void gst_ivorbisfile_base_init (gpointer g_class); -static void gst_ivorbisfile_class_init (IvorbisfileClass * klass); -static void gst_ivorbisfile_init (Ivorbisfile * ivorbisfile); -static void gst_ivorbisfile_finalize (GObject * object); - -static GstStateChangeReturn -gst_ivorbisfile_change_state (GstElement * element, GstStateChange transition); - -static gboolean gst_ivorbisfile_src_convert (GstPad * pad, - GstFormat src_format, - gint64 src_value, GstFormat * dest_format, gint64 * dest_value); -static gboolean gst_ivorbisfile_sink_convert (GstPad * pad, - GstFormat src_format, - gint64 src_value, GstFormat * dest_format, gint64 * dest_value); -static const GstQueryType *gst_ivorbisfile_get_src_query_types (GstPad * pad); - -static gboolean gst_ivorbisfile_src_query (GstPad * pad, GstQuery * query); - -static gboolean gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event); - -static gboolean gst_ivorbisfile_sink_event (GstPad * pad, GstEvent * event); - -static const GstQueryType *gst_ivorbisfile_get_sink_query_types (GstPad * pad); - -static gboolean gst_ivorbisfile_sink_query (GstPad * pad, GstQuery * query); - -static void gst_ivorbisfile_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_ivorbisfile_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); - -static GstFlowReturn gst_ivorbisfile_chain (GstPad * pad, GstBuffer * buffer); -static gboolean gst_ivorbisfile_sink_activate (GstPad * sinkpad); - -static gboolean -gst_ivorbisfile_sink_activate_pull (GstPad * sinkpad, gboolean active); - -static void gst_ivorbisfile_loop (GstPad * pad); -static GstFlowReturn gst_ivorbisfile_play (GstPad * pad); - -static GstElementClass *parent_class = NULL; - -static GstFormat logical_stream_format; - -GType -ivorbisfile_get_type (void) -{ - static GType ivorbisfile_type = 0; - - if (!ivorbisfile_type) { - static const GTypeInfo ivorbisfile_info = { - sizeof (IvorbisfileClass), - gst_ivorbisfile_base_init, - NULL, - (GClassInitFunc) gst_ivorbisfile_class_init, NULL, NULL, - sizeof (Ivorbisfile), 0, - (GInstanceInitFunc) gst_ivorbisfile_init, - }; - - ivorbisfile_type = g_type_register_static (GST_TYPE_ELEMENT, "Ivorbisfile", - &ivorbisfile_info, 0); - - logical_stream_format = - gst_format_register ("logical_stream", "The logical stream"); - - GST_DEBUG_CATEGORY_INIT (ivorbisfile_debug, "ivorbisfile", 0, - "vorbis in ogg decoding element (integer arithmetic)"); - } - return ivorbisfile_type; -} - -static GstCaps * -vorbis_caps_factory (void) -{ - return gst_caps_new_simple ("application/ogg", NULL); - -} - -static GstCaps * -raw_caps_factory (void) -{ - return - gst_caps_new_simple ("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", GST_TYPE_INT_RANGE, 11025, 48000, - "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); -} - -static GstCaps * -raw_caps2_factory (void) -{ - return - gst_caps_new_simple ("audio/x-raw-float", - "depth", G_TYPE_INT, 32, - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "rate", GST_TYPE_INT_RANGE, 11025, 48000, - "channels", G_TYPE_INT, 2, NULL); -} - - -static void -gst_ivorbisfile_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - GstCaps *raw_caps, *vorbis_caps, *raw_caps2; - - raw_caps = raw_caps_factory (); - raw_caps2 = raw_caps2_factory (); - vorbis_caps = vorbis_caps_factory (); - - /* register sink pads */ - gst_vorbisdec_sink_template = gst_pad_template_new ("sink", GST_PAD_SINK, - GST_PAD_ALWAYS, vorbis_caps); - gst_caps_append (raw_caps2, raw_caps); - /* register src pads */ - gst_vorbisdec_src_template = gst_pad_template_new ("src", GST_PAD_SRC, - GST_PAD_ALWAYS, raw_caps2); - gst_element_class_add_pad_template (element_class, - gst_vorbisdec_sink_template); - gst_element_class_add_pad_template (element_class, - gst_vorbisdec_src_template); - gst_element_class_set_details (element_class, &ivorbisfile_details); -} - -static void -gst_ivorbisfile_class_init (IvorbisfileClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->get_property = gst_ivorbisfile_get_property; - gobject_class->set_property = gst_ivorbisfile_set_property; - - g_object_class_install_property (gobject_class, ARG_METADATA, - g_param_spec_boxed ("metadata", "Metadata", "(logical) Stream metadata", - GST_TYPE_CAPS, G_PARAM_READABLE)); - g_object_class_install_property (gobject_class, ARG_STREAMINFO, - g_param_spec_boxed ("streaminfo", "stream", - "(logical) Stream information", GST_TYPE_CAPS, G_PARAM_READABLE)); - - gobject_class->finalize = gst_ivorbisfile_finalize; - gstelement_class->change_state = gst_ivorbisfile_change_state; -} - -static void -gst_ivorbisfile_init (Ivorbisfile * ivorbisfile) -{ - ivorbisfile->sinkpad = gst_pad_new_from_template (gst_vorbisdec_sink_template, - "sink"); - gst_element_add_pad (GST_ELEMENT (ivorbisfile), ivorbisfile->sinkpad); - - gst_pad_set_query_type_function (ivorbisfile->sinkpad, - gst_ivorbisfile_get_sink_query_types); - gst_pad_set_query_function (ivorbisfile->sinkpad, gst_ivorbisfile_sink_query); - - gst_pad_set_activate_function (ivorbisfile->sinkpad, - gst_ivorbisfile_sink_activate); - gst_pad_set_activatepull_function (ivorbisfile->sinkpad, - gst_ivorbisfile_sink_activate_pull); - gst_pad_set_chain_function (ivorbisfile->sinkpad, gst_ivorbisfile_chain); - gst_pad_set_event_function (ivorbisfile->sinkpad, gst_ivorbisfile_sink_event); - - ivorbisfile->srcpad = - gst_pad_new_from_template (gst_vorbisdec_src_template, "src"); - gst_element_add_pad (GST_ELEMENT (ivorbisfile), ivorbisfile->srcpad); - - gst_pad_set_query_type_function (ivorbisfile->srcpad, - gst_ivorbisfile_get_src_query_types); - gst_pad_set_query_function (ivorbisfile->srcpad, gst_ivorbisfile_src_query); - - gst_pad_set_event_function (ivorbisfile->srcpad, gst_ivorbisfile_src_event); - - ivorbisfile->adapter = NULL; - - if (ivorbisfile->metadata) { - ivorbisfile->metadata = NULL; - } - if (ivorbisfile->streaminfo) { - ivorbisfile->streaminfo = NULL; - } - -} - - -static void -gst_ivorbisfile_finalize (GObject * object) -{ - Ivorbisfile *ivorbisfile; - - ivorbisfile = GST_IVORBISFILE (object); - - if (ivorbisfile->adapter) { - g_object_unref (ivorbisfile->adapter); - ivorbisfile->adapter = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - - - -/* the next four functions are the ov callbacks we provide to ivorbisfile - * which interface between GStreamer's handling of the data flow and - * vorbis's needs */ -static size_t -gst_ivorbisfile_read (void *ptr, size_t size, size_t nmemb, void *datasource) -{ - size_t read_size = size * nmemb; - guint buf_size = 0; - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource); - size_t ret; - - GST_LOG ("read %d", read_size); - - /* make sure we don't go to EOS */ - - if (!ivorbisfile->may_eos && ivorbisfile->total_bytes && - ivorbisfile->offset + read_size > ivorbisfile->total_bytes) { - read_size = ivorbisfile->total_bytes - ivorbisfile->offset; - } - - if (read_size == 0 || ivorbisfile->eos) { - return 0; - } - - if (ivorbisfile->adapter) { - const guint8 *buf = NULL; - - buf_size = gst_adapter_available (ivorbisfile->adapter); - - if (buf_size < read_size) { - return 0; - } - - if (buf_size > read_size) { - buf_size = read_size; - } else if (buf_size == 0) { - return 0; - } - - - buf = gst_adapter_peek (ivorbisfile->adapter, buf_size); - - memcpy (ptr, buf, buf_size); - - gst_adapter_flush (ivorbisfile->adapter, buf_size); - - } else { - - GstBuffer *buf = NULL; - - if (GST_FLOW_OK != gst_pad_pull_range (ivorbisfile->sinkpad, - ivorbisfile->offset, read_size, &buf)) { - return 0; - } - - buf_size = GST_BUFFER_SIZE (buf); - - memcpy (ptr, GST_BUFFER_DATA (buf), buf_size); - - gst_buffer_unref (buf); - - } - - ivorbisfile->offset += buf_size; - - ret = buf_size / size; - - return ret; -} - -static int -gst_ivorbisfile_seek (void *datasource, ogg_int64_t offset, int whence) -{ - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource); - guint64 pending_offset = ivorbisfile->offset; - gboolean need_total = FALSE; - - - if (!ivorbisfile->vf.seekable) { - return -1; - } - - GST_DEBUG ("seek %" G_GINT64_FORMAT " %d", offset, whence); - - if (whence == SEEK_SET) { - pending_offset = offset; - ivorbisfile->adapterOffset = offset; - } else if (whence == SEEK_CUR) { - pending_offset += offset; - ivorbisfile->adapterOffset += offset; - } else if (whence == SEEK_END) { - need_total = TRUE; - pending_offset = ivorbisfile->total_bytes - offset; - ivorbisfile->adapterOffset = ivorbisfile->total_bytes - offset; - } else - return -1; - - - ivorbisfile->offset = pending_offset; - if (need_total) - ivorbisfile->total_bytes = ivorbisfile->adapterOffset + offset; - - return 0; -} - -static int -gst_ivorbisfile_close (void *datasource) -{ - GST_DEBUG ("close"); - return 0; -} - -static long -gst_ivorbisfile_tell (void *datasource) -{ - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (datasource); - long result; - - result = ivorbisfile->adapterOffset; - - GST_DEBUG ("tell %ld", result); - - return result; -} - -ov_callbacks ivorbisfile_ov_callbacks = { - gst_ivorbisfile_read, - gst_ivorbisfile_seek, - gst_ivorbisfile_close, - gst_ivorbisfile_tell, -}; - -#if 0 -/* retrieve the comment field (or tags) and put in metadata GstCaps - * returns TRUE if caps could be set, - * FALSE if they couldn't be read somehow */ -static gboolean -gst_ivorbisfile_update_metadata (Ivorbisfile * ivorbisfile, gint link) -{ - OggVorbis_File *vf = &ivorbisfile->vf; - gchar **ptr; - vorbis_comment *vc; - GstProps *props = NULL; - GstPropsEntry *entry; - gchar *name, *value; - - /* clear old one */ - if (ivorbisfile->metadata) { - gst_caps_unref (ivorbisfile->metadata); - ivorbisfile->metadata = NULL; - } - - /* create props to hold the key/value pairs */ - props = gst_props_empty_new (); - - vc = ov_comment (vf, link); - ptr = vc->user_comments; - while (*ptr) { - value = strstr (*ptr, "="); - if (value) { - name = g_strndup (*ptr, value - *ptr); - entry = gst_props_entry_new (name, GST_PROPS_STRING_TYPE, value + 1); - gst_props_add_entry (props, (GstPropsEntry *) entry); - } - ptr++; - } - ivorbisfile->metadata = gst_caps_new ("ivorbisfile_metadata", - "application/x-gst-metadata", props); - - g_object_notify (G_OBJECT (ivorbisfile), "metadata"); - - return TRUE; -} - -/* retrieve logical stream properties and put them in streaminfo GstCaps - * returns TRUE if caps could be set, - * FALSE if they couldn't be read somehow */ -static gboolean -gst_ivorbisfile_update_streaminfo (Ivorbisfile * ivorbisfile, gint link) -{ - OggVorbis_File *vf = &ivorbisfile->vf; - vorbis_info *vi; - GstProps *props = NULL; - GstPropsEntry *entry; - - /* clear old one */ - if (ivorbisfile->streaminfo) { - gst_caps_unref (ivorbisfile->streaminfo); - ivorbisfile->streaminfo = NULL; - } - - /* create props to hold the key/value pairs */ - props = gst_props_empty_new (); - - vi = ov_info (vf, link); - entry = gst_props_entry_new ("version", GST_PROPS_INT_TYPE, vi->version); - gst_props_add_entry (props, (GstPropsEntry *) entry); - entry = gst_props_entry_new ("bitrate_upper", GST_PROPS_INT_TYPE, - vi->bitrate_upper); - gst_props_add_entry (props, (GstPropsEntry *) entry); - entry = gst_props_entry_new ("bitrate_nominal", GST_PROPS_INT_TYPE, - vi->bitrate_nominal); - gst_props_add_entry (props, (GstPropsEntry *) entry); - entry = gst_props_entry_new ("bitrate_lower", GST_PROPS_INT_TYPE, - vi->bitrate_lower); - gst_props_add_entry (props, (GstPropsEntry *) entry); - entry = gst_props_entry_new ("serial", GST_PROPS_INT_TYPE, - ov_serialnumber (vf, link)); - gst_props_add_entry (props, (GstPropsEntry *) entry); - entry = gst_props_entry_new ("bitrate", GST_PROPS_INT_TYPE, - ov_bitrate (vf, link)); - gst_props_add_entry (props, (GstPropsEntry *) entry); - - ivorbisfile->streaminfo = gst_caps_new ("ivorbisfile_streaminfo", - "application/x-gst-streaminfo", props); - - g_object_notify (G_OBJECT (ivorbisfile), "streaminfo"); - - return TRUE; -} -#endif - -static gboolean -gst_ivorbisfile_new_link (Ivorbisfile * ivorbisfile, gint link) -{ - vorbis_info *vi = ov_info (&ivorbisfile->vf, link); - GstCaps *caps; - gboolean res = TRUE; - - /* new logical bitstream */ - ivorbisfile->current_link = link; - - caps = gst_caps_new_simple ("audio/x-raw-int", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "signed", G_TYPE_BOOLEAN, TRUE, - "width", G_TYPE_INT, 16, - "depth", G_TYPE_INT, 16, - "rate", G_TYPE_INT, vi->rate, "channels", G_TYPE_INT, vi->channels, NULL); - - ivorbisfile->rate = vi->rate; - ivorbisfile->channels = vi->channels; - ivorbisfile->width = 16; - - if (gst_pad_set_caps (ivorbisfile->srcpad, caps) <= 0) { - res = FALSE; - } - - gst_caps_unref (caps); - - return TRUE; -} - - -static gboolean -gst_ivorbisfile_sink_activate (GstPad * sinkpad) -{ - - Ivorbisfile *ivorbisfile; - - ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (sinkpad)); - - if (gst_pad_check_pull_range (sinkpad)) { - /* FIX ME */ - /* ivorbisfile->vf.seekable = TRUE; */ - ivorbisfile->vf.seekable = FALSE; - if (ivorbisfile->adapter) { - gst_adapter_clear (ivorbisfile->adapter); - g_object_unref (ivorbisfile->adapter); - ivorbisfile->adapter = NULL; - } - return gst_pad_activate_pull (sinkpad, TRUE); - } else { - - if (ivorbisfile->adapter) { - gst_adapter_clear (ivorbisfile->adapter); - } else { - ivorbisfile->adapter = gst_adapter_new (); - } - ivorbisfile->vf.seekable = FALSE; - return gst_pad_activate_push (sinkpad, TRUE); - } - - -} - - -static gboolean -gst_ivorbisfile_sink_activate_pull (GstPad * sinkpad, gboolean active) -{ - - gboolean result; - - if (active) { - /* if we have a scheduler we can start the task */ - result = gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_ivorbisfile_loop, sinkpad); - } else { - result = gst_pad_stop_task (sinkpad); - } - - return result; -} - - - -static GstFlowReturn -gst_ivorbisfile_chain (GstPad * pad, GstBuffer * buffer) -{ - - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad)); - - if (NULL == ivorbisfile->adapter) { - GST_ERROR ("pull expected! Chain func should not be called"); - return GST_FLOW_UNEXPECTED; - } - - gst_adapter_push (ivorbisfile->adapter, buffer); - - return gst_ivorbisfile_play (pad); - -} - - -static void -gst_ivorbisfile_loop (GstPad * pad) -{ - gst_ivorbisfile_play (pad); -} - -static GstFlowReturn -gst_ivorbisfile_play (GstPad * pad) -{ - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad)); - GstBuffer *outbuf; - long ret; - GstClockTime time; - gint64 samples; - gint link; - GstFlowReturn res = GST_FLOW_OK; - - if (ivorbisfile->eos) { - goto done; - } - - /* this function needs to go first since you don't want to be messing - * with an unset vf ;) */ - if (ivorbisfile->restart) { - gint err; - - if (ivorbisfile->adapter) { - if (gst_adapter_available (ivorbisfile->adapter) < 40960) { - goto done; - } - } - - ivorbisfile->offset = 0; - ivorbisfile->total_bytes = 0; - ivorbisfile->may_eos = FALSE; - ivorbisfile->adapterOffset = 0; - GST_DEBUG ("ivorbisfile: seekable: %s\n", - ivorbisfile->vf.seekable ? "yes" : "no"); - - /* open our custom ivorbisfile data object with the callbacks we provide */ - - if ((err = ov_open_callbacks (ivorbisfile, &ivorbisfile->vf, NULL, 0, - ivorbisfile_ov_callbacks)) < 0) { - GST_ELEMENT_ERROR (ivorbisfile, STREAM, DECODE, (NULL), (NULL)); - goto done; - } - - ivorbisfile->need_discont = TRUE; - ivorbisfile->restart = FALSE; - ivorbisfile->current_link = -1; - } - - if (ivorbisfile->seek_pending) { - /* get time to seek to in seconds */ - - switch (ivorbisfile->seek_format) { - case GST_FORMAT_TIME: - { - gdouble seek_to = (gdouble) ivorbisfile->seek_value / GST_SECOND; - - if (ivorbisfile->seek_accurate) { - if (ov_time_seek (&ivorbisfile->vf, seek_to) == 0) { - ivorbisfile->need_discont = TRUE; - } - } else { - if (ov_time_seek_page (&ivorbisfile->vf, seek_to) == 0) { - ivorbisfile->need_discont = TRUE; - } - } - break; - } - case GST_FORMAT_DEFAULT: - if (ivorbisfile->seek_accurate) { - if (ov_pcm_seek (&ivorbisfile->vf, ivorbisfile->seek_value) == 0) { - ivorbisfile->need_discont = TRUE; - } - } else { - if (ov_pcm_seek_page (&ivorbisfile->vf, ivorbisfile->seek_value) == 0) { - ivorbisfile->need_discont = TRUE; - } - } - break; - default: - if (ivorbisfile->seek_format == logical_stream_format) { - gint64 seek_to; - - seek_to = ivorbisfile->vf.offsets[ivorbisfile->seek_value]; - - if (ov_raw_seek (&ivorbisfile->vf, seek_to) == 0) { - ivorbisfile->need_discont = TRUE; - ivorbisfile->current_link = -1; - } else { - GST_WARNING ("raw seek failed"); - } - } else - GST_WARNING ("unknown seek method, implement me !"); - break; - } - ivorbisfile->seek_pending = FALSE; - } - - /* we update the caps for each logical stream */ - if (ivorbisfile->vf.current_link != ivorbisfile->current_link) { - if (!gst_ivorbisfile_new_link (ivorbisfile, ivorbisfile->vf.current_link)) { - GST_ELEMENT_ERROR (ivorbisfile, CORE, NEGOTIATION, (NULL), (NULL)); - } - goto done; - } - - do { - - outbuf = gst_buffer_new_and_alloc (4096); - - ret = ov_read (&ivorbisfile->vf, - (char *) GST_BUFFER_DATA (outbuf), GST_BUFFER_SIZE (outbuf), &link); - - /* get current time for discont and buffer timestamp */ - time = (GstClockTime) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND); - - if (ret == 0) { - gst_buffer_unref (outbuf); - if (ivorbisfile->adapter == NULL) { - ivorbisfile->eos = TRUE; - ivorbisfile->restart = TRUE; - gst_pad_push_event (ivorbisfile->srcpad, gst_event_new_eos ()); - } - goto done; - } else if (ret < 0) { - switch (ret) { - case OV_HOLE: - GST_WARNING - ("Vorbisfile encoutered missing or corrupt data in the bitstream." - " Recovery is normally automatic and" - " this return code is for informational purposes only."); - break; - case OV_EBADLINK: - GST_WARNING ("The given link exists in the Vorbis data stream," - " but is not decipherable due to garbacge or corruption."); - break; - default: - GST_ERROR ("ivorbisfile: decoding error, unexpected ret = %ld", ret); - break; - } - gst_buffer_unref (outbuf); - goto done; - } else { - if (ivorbisfile->need_discont) { - GstEvent *event; - - ivorbisfile->need_discont = FALSE; - - /* get stream stats */ - samples = (gint64) (ov_pcm_tell (&ivorbisfile->vf)); - - event = - gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, time, - GST_CLOCK_TIME_NONE, 0); - - gst_pad_push_event (ivorbisfile->srcpad, event); - - } - - if (NULL == GST_PAD_CAPS (ivorbisfile->srcpad)) { - gst_buffer_unref (outbuf); - goto done; - } - - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (ivorbisfile->srcpad)); - - GST_BUFFER_SIZE (outbuf) = ret; - /* FIX ME TO SET RIGHT TIMESTAMP - gint bufsize = ret / (ivorbisfile->width / 8); - GST_BUFFER_TIMESTAMP (outbuf) = time; - GST_BUFFER_DURATION (outbuf) = GST_SECOND * bufsize / (ivorbisfile->rate * ivorbisfile->channels); - */ - - ivorbisfile->may_eos = TRUE; - - if (!ivorbisfile->vf.seekable) { - ivorbisfile->total_bytes += GST_BUFFER_SIZE (outbuf); - } - - if (GST_FLOW_OK != (res = gst_pad_push (ivorbisfile->srcpad, outbuf))) { - goto done; - } - - } - - } while (TRUE); - -done: - - gst_object_unref (ivorbisfile); - return res; - -} - -static gboolean -gst_ivorbisfile_src_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - guint scale = 1; - gint bytes_per_sample; - Ivorbisfile *ivorbisfile; - vorbis_info *vi; - - ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad)); - - vi = ov_info (&ivorbisfile->vf, -1); - bytes_per_sample = vi->channels * 2; - - switch (src_format) { - case GST_FORMAT_BYTES: - switch (*dest_format) { - case GST_FORMAT_DEFAULT: - *dest_value = src_value / (vi->channels * 2); - break; - case GST_FORMAT_TIME: - { - gint byterate = bytes_per_sample * vi->rate; - - if (byterate == 0) - return FALSE; - *dest_value = src_value * GST_SECOND / byterate; - break; - } - default: - res = FALSE; - } - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_BYTES: - *dest_value = src_value * bytes_per_sample; - break; - case GST_FORMAT_TIME: - if (vi->rate == 0) - return FALSE; - *dest_value = src_value * GST_SECOND / vi->rate; - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_BYTES: - scale = bytes_per_sample; - case GST_FORMAT_DEFAULT: - *dest_value = src_value * scale * vi->rate / GST_SECOND; - break; - default: - res = FALSE; - } - break; - default: - if (src_format == logical_stream_format) { - /* because we need to convert relative from 0, we have to add - * all pcm totals */ - gint i; - gint64 count = 0; - - switch (*dest_format) { - case GST_FORMAT_BYTES: - res = FALSE; - break; - case GST_FORMAT_DEFAULT: - if (src_value > ivorbisfile->vf.links) { - src_value = ivorbisfile->vf.links; - } - for (i = 0; i < src_value; i++) { - vi = ov_info (&ivorbisfile->vf, i); - - count += ov_pcm_total (&ivorbisfile->vf, i); - } - *dest_value = count; - break; - case GST_FORMAT_TIME: - { - if (src_value > ivorbisfile->vf.links) { - src_value = ivorbisfile->vf.links; - } - for (i = 0; i < src_value; i++) { - vi = ov_info (&ivorbisfile->vf, i); - if (vi->rate) - count += - ov_pcm_total (&ivorbisfile->vf, i) * GST_SECOND / vi->rate; - else - count += ov_time_total (&ivorbisfile->vf, i) * GST_SECOND; - } - /* we use the pcm totals to get the total time, it's more accurate */ - *dest_value = count; - break; - } - default: - res = FALSE; - } - } else - res = FALSE; - break; - } - return res; -} - -static gboolean -gst_ivorbisfile_sink_query (GstPad * pad, GstQuery * query) -{ - gboolean res; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - /* peel off input */ - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - if ((res = gst_ivorbisfile_sink_convert (pad, src_fmt, src_val, - &dest_fmt, &dest_val))) { - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - } - break; - } - default: - res = FALSE; - break; - } - return res; -} - -static gboolean -gst_ivorbisfile_sink_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - Ivorbisfile *ivorbisfile; - - ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad)); - - switch (src_format) { - case GST_FORMAT_BYTES: - switch (*dest_format) { - case GST_FORMAT_TIME: - break; - default: - if (*dest_format == logical_stream_format) { - } else - res = FALSE; - } - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_BYTES: - break; - default: - if (*dest_format == logical_stream_format) { - } else - res = FALSE; - } - default: - if (src_format == logical_stream_format) { - switch (*dest_format) { - case GST_FORMAT_TIME: - break; - case GST_FORMAT_BYTES: - break; - default: - res = FALSE; - } - } else - res = FALSE; - break; - } - - return res; -} - -static const GstQueryType * -gst_ivorbisfile_get_sink_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_CONVERT, - 0 - }; - - return types; -} - -static const GstQueryType * -gst_ivorbisfile_get_src_query_types (GstPad * pad) -{ - static const GstQueryType types[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_CONVERT, - 0 - }; - - return types; -} - -/* handles queries for location in the stream in the requested format */ -static gboolean -gst_ivorbisfile_src_query (GstPad * pad, GstQuery * query) -{ - gboolean res = TRUE; - Ivorbisfile *ivorbisfile; - vorbis_info *vi; - - ivorbisfile = GST_IVORBISFILE (GST_PAD_PARENT (pad)); - - vi = ov_info (&ivorbisfile->vf, -1); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - - GstFormat format; - GstFormat rformat = GST_FORMAT_TIME; - gint64 cur; - GstPad *peer; - - /* save requested format */ - gst_query_parse_position (query, &format, NULL); - - /* query peer for current position in time */ - gst_query_set_position (query, GST_FORMAT_TIME, -1); - - if ((peer = gst_pad_get_peer (ivorbisfile->sinkpad)) == NULL) - goto error; - - if (!gst_pad_query_position (peer, &rformat, &cur)) { - GST_LOG_OBJECT (ivorbisfile, "query on peer pad failed"); - gst_object_unref (peer); - goto error; - } - gst_object_unref (peer); - - if (format != rformat) { - gst_ivorbisfile_src_convert (pad, rformat, cur, &format, &cur); - } - - switch (format) { - case GST_FORMAT_DEFAULT: - if (ivorbisfile->vf.seekable) - cur = ov_pcm_tell (&ivorbisfile->vf); - else - cur = ivorbisfile->total_bytes / (vi->channels * 2); - break; - case GST_FORMAT_TIME: - if (ivorbisfile->vf.seekable) - cur = (gint64) (ov_time_tell (&ivorbisfile->vf) * GST_SECOND); - else - cur = ivorbisfile->total_bytes * GST_SECOND - / (vi->rate * vi->channels * 2); - break; - case GST_FORMAT_BYTES: - if (ivorbisfile->vf.seekable) - cur = ov_pcm_tell (&ivorbisfile->vf) * vi->channels * 2; - else - cur = ivorbisfile->total_bytes; - break; - default: - if (format == logical_stream_format) { - if (ivorbisfile->vf.seekable) - cur = ivorbisfile->current_link; - else - return FALSE; - } else - res = FALSE; - break; - } - - gst_query_set_position (query, format, cur); - - break; - } - case GST_QUERY_DURATION: - { - - GstFormat format; - GstFormat rformat = GST_FORMAT_TIME; - gint64 cur; - GstPad *peer; - - /* save requested format */ - gst_query_parse_position (query, &format, NULL); - - /* query peer for current position in time */ - gst_query_set_position (query, GST_FORMAT_TIME, -1); - - if ((peer = gst_pad_get_peer (ivorbisfile->sinkpad)) == NULL) - goto error; - - if (!gst_pad_query_position (peer, &rformat, &cur)) { - GST_LOG_OBJECT (ivorbisfile, "query on peer pad failed"); - gst_object_unref (peer); - goto error; - } - gst_object_unref (peer); - - if (format != rformat) { - gst_ivorbisfile_src_convert (pad, rformat, cur, &format, &cur); - } - - switch (format) { - case GST_FORMAT_DEFAULT: - if (ivorbisfile->vf.seekable) - cur = ov_pcm_total (&ivorbisfile->vf, -1); - else - return FALSE; - break; - case GST_FORMAT_BYTES: - if (ivorbisfile->vf.seekable) - cur = ov_pcm_total (&ivorbisfile->vf, -1) * vi->channels * 2; - else - return FALSE; - break; - case GST_FORMAT_TIME: - if (ivorbisfile->vf.seekable) - cur = (gint64) (ov_time_total (&ivorbisfile->vf, -1) * GST_SECOND); - else - return FALSE; - break; - default: - if (format == logical_stream_format) { - if (ivorbisfile->vf.seekable) - cur = ivorbisfile->vf.links; - else - return FALSE; - } else - res = FALSE; - break; - } - - gst_query_set_position (query, format, cur); - - break; - } - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - /* peel off input */ - gst_query_parse_convert (query, &src_fmt, &src_val, NULL, NULL); - if ((res = gst_ivorbisfile_src_convert (pad, src_fmt, src_val, - &dest_fmt, &dest_val))) { - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - } - break; - } - default: - res = FALSE; - break; - } - - return res; - -error: - - return FALSE; - -} - - -static gboolean -gst_ivorbisfile_sink_event (GstPad * pad, GstEvent * event) -{ - - Ivorbisfile *ivorbisfile; - gboolean ret = TRUE; - - ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - GST_DEBUG ("eos"); - ivorbisfile->eos = TRUE; - ivorbisfile->restart = TRUE; - break; - case GST_EVENT_NEWSEGMENT: - GST_DEBUG ("discont"); - ivorbisfile->need_discont = TRUE; - gst_event_unref (event); - goto done; - default: - break; - } - - ret = gst_pad_event_default (pad, event); - -done: - gst_object_unref (ivorbisfile); - - return ret; - -} - - -/* handle events on src pad */ -static gboolean -gst_ivorbisfile_src_event (GstPad * pad, GstEvent * event) -{ - gboolean res = TRUE; - Ivorbisfile *ivorbisfile; - - ivorbisfile = GST_IVORBISFILE (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - gint64 offset; - vorbis_info *vi; - GstFormat format; - GstSeekFlags flags; - - GST_DEBUG ("ivorbisfile: handling seek event on pad %s:%s", - GST_DEBUG_PAD_NAME (pad)); - if (!ivorbisfile->vf.seekable) { - gst_event_unref (event); - GST_DEBUG ("vorbis stream is not seekable"); - gst_object_unref (ivorbisfile); - return FALSE; - } - - gst_event_parse_seek (event, NULL, &format, &flags, NULL, &offset, NULL, - NULL); - - switch (format) { - case GST_FORMAT_TIME: - ivorbisfile->seek_pending = TRUE; - ivorbisfile->seek_value = offset; - ivorbisfile->seek_format = format; - ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE; - break; - case GST_FORMAT_BYTES: - vi = ov_info (&ivorbisfile->vf, -1); - if (vi->channels == 0) { - GST_DEBUG ("vorbis stream has 0 channels ?"); - res = FALSE; - goto done; - } - offset /= vi->channels * 2; - /* fallthrough */ - case GST_FORMAT_DEFAULT: - ivorbisfile->seek_pending = TRUE; - ivorbisfile->seek_value = offset; - ivorbisfile->seek_format = format; - ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE; - break; - default: - if (format == logical_stream_format) { - ivorbisfile->seek_pending = TRUE; - ivorbisfile->seek_value = offset; - ivorbisfile->seek_format = format; - ivorbisfile->seek_accurate = flags & GST_SEEK_FLAG_ACCURATE; - } else { - GST_DEBUG ("unhandled seek format"); - res = FALSE; - } - break; - } - break; - } - default: - res = FALSE; - break; - } - -done: - gst_event_unref (event); - gst_object_unref (ivorbisfile); - return res; -} - -static GstStateChangeReturn -gst_ivorbisfile_change_state (GstElement * element, GstStateChange transition) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - Ivorbisfile *ivorbisfile = GST_IVORBISFILE (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - ivorbisfile->total_bytes = 0; - ivorbisfile->offset = 0; - ivorbisfile->seek_pending = 0; - ivorbisfile->need_discont = FALSE; - if (ivorbisfile->metadata) { - gst_caps_unref (ivorbisfile->metadata); - ivorbisfile->metadata = NULL; - } - if (ivorbisfile->streaminfo) { - gst_caps_unref (ivorbisfile->streaminfo); - ivorbisfile->streaminfo = NULL; - } - ivorbisfile->current_link = -1; - - ivorbisfile->rate = -1; - ivorbisfile->channels = -1; - ivorbisfile->width = -1; - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - if (ivorbisfile->adapter) { - gst_adapter_clear (ivorbisfile->adapter); - } - ivorbisfile->restart = TRUE; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - ivorbisfile->eos = FALSE; - break; - default: - break; - } - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - ov_clear (&ivorbisfile->vf); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - default: - break; - } - - - - return ret; -} - -static void -gst_ivorbisfile_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - Ivorbisfile *ivorbisfile; - - g_return_if_fail (GST_IS_IVORBISFILE (object)); - - ivorbisfile = GST_IVORBISFILE (object); - - switch (prop_id) { - default: - GST_WARNING ("Unknown property id\n"); - } -} - -static void -gst_ivorbisfile_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - Ivorbisfile *ivorbisfile; - - g_return_if_fail (GST_IS_IVORBISFILE (object)); - - ivorbisfile = GST_IVORBISFILE (object); - - switch (prop_id) { - case ARG_METADATA: - g_value_set_boxed (value, ivorbisfile->metadata); - break; - case ARG_STREAMINFO: - g_value_set_boxed (value, ivorbisfile->streaminfo); - break; - default: - GST_WARNING ("Unknown property id\n"); - } -} |