summaryrefslogtreecommitdiffstats
path: root/meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch')
-rw-r--r--meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch1365
1 files changed, 1365 insertions, 0 deletions
diff --git a/meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch b/meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch
new file mode 100644
index 0000000000..7e7afc3f6c
--- /dev/null
+++ b/meta/packages/gstreamer/gst-plugins-bad-0.10.3/ivorbisdec.patch
@@ -0,0 +1,1365 @@
1--- ../gst-plugins-bad0.10-0.10.3+cvs20060918/configure.ac 2006-09-18 18:35:13.000000000 +0100
2+++ ./configure.ac 2006-09-21 14:55:05.000000000 +0100
3@@ -526,7 +526,12 @@
4 IVORBIS_CFLAGS=
5 AC_CHECK_LIB(vorbisidec, vorbis_block_init,
6 [IVORBIS_LIBS=-lvorbisidec
7- HAVE_IVORBIS=yes],
8+ HAVE_IVORBIS=yes
9+ case $host in
10+ arm-*-*)
11+ IVORBIS_CFLAGS="-D_ARM_ASSEM_ $IVORBIS_CFLAGS"
12+ esac
13+ ],
14 HAVE_IVORBIS=no)
15 AC_SUBST(IVORBIS_LIBS)
16 AC_SUBST(IVORBIS_CFLAGS)
17diff -urNd ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/Makefile.am ext/ivorbis/Makefile.am
18--- ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/Makefile.am 2005-11-21 03:21:04.000000000 +0000
19+++ ext/ivorbis/Makefile.am 2006-09-20 15:41:30.000000000 +0100
20@@ -1,7 +1,7 @@
21
22 plugin_LTLIBRARIES = libgstivorbis.la
23
24-libgstivorbis_la_SOURCES = vorbis.c vorbisfile.c
25+libgstivorbis_la_SOURCES = vorbis.c vorbisfile.c vorbisdec.c
26 libgstivorbis_la_CFLAGS = $(GST_CFLAGS) $(IVORBIS_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
27 libgstivorbis_la_LIBADD = $(IVORBIS_LIBS) \
28 $(IVORBISFILE_LIBS) \
29diff -urNd ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbis.c ext/ivorbis/vorbis.c
30--- ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbis.c 2006-04-01 11:09:05.000000000 +0100
31+++ ext/ivorbis/vorbis.c 2006-09-20 18:47:11.000000000 +0100
32@@ -23,9 +23,11 @@
33
34 #include <gst/gst.h>
35 #include <tremor/ivorbiscodec.h>
36+#include "vorbisdec.h"
37
38-extern GType ivorbisfile_get_type (void);
39+GST_DEBUG_CATEGORY (vorbisdec_debug);
40
41+extern GType ivorbisfile_get_type (void);
42
43 static gboolean
44 plugin_init (GstPlugin * plugin)
45@@ -34,6 +36,13 @@
46 ivorbisfile_get_type ()))
47 return FALSE;
48
49+ if (!gst_element_register (plugin, "ivorbisdec", GST_RANK_SECONDARY,
50+ gst_ivorbis_dec_get_type ()))
51+ return FALSE;
52+
53+ GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "ivorbisdec", 0,
54+ "vorbis decoding element (integer decoder)");
55+
56 return TRUE;
57 }
58
59diff -urNd ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbisdec.c ext/ivorbis/vorbisdec.c
60--- ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbisdec.c 1970-01-01 01:00:00.000000000 +0100
61+++ ext/ivorbis/vorbisdec.c 2006-09-21 14:51:25.000000000 +0100
62@@ -0,0 +1,1212 @@
63+/* GStreamer
64+ * Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
65+ *
66+ * Tremor modifications <2006>:
67+ * Chris Lord, OpenedHand Ltd. <chris@openedhand.com>, http://www.o-hand.com/
68+ *
69+ * This library is free software; you can redistribute it and/or
70+ * modify it under the terms of the GNU Library General Public
71+ * License as published by the Free Software Foundation; either
72+ * version 2 of the License, or (at your option) any later version.
73+ *
74+ * This library is distributed in the hope that it will be useful,
75+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
76+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
77+ * Library General Public License for more details.
78+ *
79+ * You should have received a copy of the GNU Library General Public
80+ * License along with this library; if not, write to the
81+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
82+ * Boston, MA 02111-1307, USA.
83+ */
84+
85+/**
86+ * SECTION:element-vorbisdec
87+ * @short_description: a decoder that decodes Vorbis to raw audio
88+ * @see_also: vorbisenc, oggdemux
89+ *
90+ * <refsect2>
91+ * <para>
92+ * This element decodes a Vorbis stream to raw int audio.
93+ * <ulink url="http://www.vorbis.com/">Vorbis</ulink> is a royalty-free
94+ * audio codec maintained by the <ulink url="http://www.xiph.org/">Xiph.org
95+ * Foundation</ulink>.
96+ * </para>
97+ * <title>Example pipelines</title>
98+ * <para>
99+ * <programlisting>
100+ * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink
101+ * </programlisting>
102+ * Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc.
103+ * </para>
104+ * </refsect2>
105+ *
106+ * Last reviewed on 2006-03-01 (0.10.4)
107+ */
108+
109+#ifdef HAVE_CONFIG_H
110+# include "config.h"
111+#endif
112+
113+#include "vorbisdec.h"
114+#include <string.h>
115+#include <gst/audio/audio.h>
116+#include <gst/tag/tag.h>
117+#include <gst/audio/multichannel.h>
118+
119+GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug);
120+#define GST_CAT_DEFAULT vorbisdec_debug
121+
122+static const GstElementDetails vorbis_dec_details =
123+GST_ELEMENT_DETAILS ("Vorbis audio decoder",
124+ "Codec/Decoder/Audio",
125+ "decode raw vorbis streams to integer audio",
126+ "Benjamin Otte <in7y118@public.uni-hamburg.de>\n"
127+ "Chris Lord <chris@openedhand.com>");
128+
129+static GstStaticPadTemplate vorbis_dec_src_factory =
130+GST_STATIC_PAD_TEMPLATE ("src",
131+ GST_PAD_SRC,
132+ GST_PAD_ALWAYS,
133+ GST_STATIC_CAPS ("audio/x-raw-int, "
134+ "rate = (int) [ 1, MAX ], "
135+ "channels = (int) [ 1, 6 ], "
136+ "endianness = (int) BYTE_ORDER, "
137+ "width = (int) 32, "
138+ "depth = (int) 16, "
139+ "signed = (boolean) true")
140+ );
141+
142+static GstStaticPadTemplate vorbis_dec_sink_factory =
143+GST_STATIC_PAD_TEMPLATE ("sink",
144+ GST_PAD_SINK,
145+ GST_PAD_ALWAYS,
146+ GST_STATIC_CAPS ("audio/x-vorbis")
147+ );
148+
149+GST_BOILERPLATE (GstIVorbisDec, gst_ivorbis_dec, GstElement, GST_TYPE_ELEMENT);
150+
151+static void vorbis_dec_finalize (GObject * object);
152+static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event);
153+static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer);
154+static GstStateChangeReturn vorbis_dec_change_state (GstElement * element,
155+ GstStateChange transition);
156+
157+static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event);
158+static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query);
159+static gboolean vorbis_dec_convert (GstPad * pad,
160+ GstFormat src_format, gint64 src_value,
161+ GstFormat * dest_format, gint64 * dest_value);
162+
163+static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query);
164+
165+static void
166+gst_ivorbis_dec_base_init (gpointer g_class)
167+{
168+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
169+ GstPadTemplate *src_template, *sink_template;
170+
171+ src_template = gst_static_pad_template_get (&vorbis_dec_src_factory);
172+ gst_element_class_add_pad_template (element_class, src_template);
173+
174+ sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory);
175+ gst_element_class_add_pad_template (element_class, sink_template);
176+
177+ gst_element_class_set_details (element_class, &vorbis_dec_details);
178+}
179+
180+static void
181+gst_ivorbis_dec_class_init (GstIVorbisDecClass * klass)
182+{
183+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
184+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
185+
186+ gobject_class->finalize = vorbis_dec_finalize;
187+
188+ gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state);
189+}
190+
191+static const GstQueryType *
192+vorbis_get_query_types (GstPad * pad)
193+{
194+ static const GstQueryType vorbis_dec_src_query_types[] = {
195+ GST_QUERY_POSITION,
196+ GST_QUERY_DURATION,
197+ GST_QUERY_CONVERT,
198+ 0
199+ };
200+
201+ return vorbis_dec_src_query_types;
202+}
203+
204+static void
205+gst_ivorbis_dec_init (GstIVorbisDec * dec, GstIVorbisDecClass * g_class)
206+{
207+ dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory,
208+ "sink");
209+
210+ gst_pad_set_event_function (dec->sinkpad,
211+ GST_DEBUG_FUNCPTR (vorbis_dec_sink_event));
212+ gst_pad_set_chain_function (dec->sinkpad,
213+ GST_DEBUG_FUNCPTR (vorbis_dec_chain));
214+ gst_pad_set_query_function (dec->sinkpad,
215+ GST_DEBUG_FUNCPTR (vorbis_dec_sink_query));
216+ gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
217+
218+ dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory,
219+ "src");
220+
221+ gst_pad_set_event_function (dec->srcpad,
222+ GST_DEBUG_FUNCPTR (vorbis_dec_src_event));
223+ gst_pad_set_query_type_function (dec->srcpad,
224+ GST_DEBUG_FUNCPTR (vorbis_get_query_types));
225+ gst_pad_set_query_function (dec->srcpad,
226+ GST_DEBUG_FUNCPTR (vorbis_dec_src_query));
227+ gst_pad_use_fixed_caps (dec->srcpad);
228+ gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
229+
230+ dec->queued = NULL;
231+ dec->pendingevents = NULL;
232+ dec->taglist = NULL;
233+}
234+
235+static void
236+vorbis_dec_finalize (GObject * object)
237+{
238+ /* Release any possibly allocated libvorbis data.
239+ * _clear functions can safely be called multiple times
240+ */
241+ GstIVorbisDec *vd = GST_IVORBIS_DEC (object);
242+
243+ vorbis_block_clear (&vd->vb);
244+ vorbis_dsp_clear (&vd->vd);
245+ vorbis_comment_clear (&vd->vc);
246+ vorbis_info_clear (&vd->vi);
247+
248+ G_OBJECT_CLASS (parent_class)->finalize (object);
249+}
250+
251+static void
252+gst_ivorbis_dec_reset (GstIVorbisDec * dec)
253+{
254+ GList *walk;
255+
256+ dec->cur_timestamp = GST_CLOCK_TIME_NONE;
257+ dec->prev_timestamp = GST_CLOCK_TIME_NONE;
258+ dec->granulepos = -1;
259+ dec->discont = TRUE;
260+ gst_segment_init (&dec->segment, GST_FORMAT_TIME);
261+
262+ for (walk = dec->queued; walk; walk = g_list_next (walk)) {
263+ gst_buffer_unref (GST_BUFFER_CAST (walk->data));
264+ }
265+ g_list_free (dec->queued);
266+ dec->queued = NULL;
267+
268+ for (walk = dec->pendingevents; walk; walk = g_list_next (walk)) {
269+ gst_event_unref (GST_EVENT_CAST (walk->data));
270+ }
271+ g_list_free (dec->pendingevents);
272+ dec->pendingevents = NULL;
273+
274+ if (dec->taglist)
275+ gst_tag_list_free (dec->taglist);
276+ dec->taglist = NULL;
277+}
278+
279+
280+static gboolean
281+vorbis_dec_convert (GstPad * pad,
282+ GstFormat src_format, gint64 src_value,
283+ GstFormat * dest_format, gint64 * dest_value)
284+{
285+ gboolean res = TRUE;
286+ GstIVorbisDec *dec;
287+ guint64 scale = 1;
288+
289+ if (src_format == *dest_format) {
290+ *dest_value = src_value;
291+ return TRUE;
292+ }
293+
294+ dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
295+
296+ if (!dec->initialized)
297+ goto no_header;
298+
299+ if (dec->sinkpad == pad &&
300+ (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES))
301+ goto no_format;
302+
303+ switch (src_format) {
304+ case GST_FORMAT_TIME:
305+ switch (*dest_format) {
306+ case GST_FORMAT_BYTES:
307+ scale = sizeof (gint32) * dec->vi.channels;
308+ case GST_FORMAT_DEFAULT:
309+ *dest_value =
310+ scale * gst_util_uint64_scale_int (src_value, dec->vi.rate,
311+ GST_SECOND);
312+ break;
313+ default:
314+ res = FALSE;
315+ }
316+ break;
317+ case GST_FORMAT_DEFAULT:
318+ switch (*dest_format) {
319+ case GST_FORMAT_BYTES:
320+ *dest_value = src_value * sizeof (gint32) * dec->vi.channels;
321+ break;
322+ case GST_FORMAT_TIME:
323+ *dest_value =
324+ gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate);
325+ break;
326+ default:
327+ res = FALSE;
328+ }
329+ break;
330+ case GST_FORMAT_BYTES:
331+ switch (*dest_format) {
332+ case GST_FORMAT_DEFAULT:
333+ *dest_value = src_value / (sizeof (gint32) * dec->vi.channels);
334+ break;
335+ case GST_FORMAT_TIME:
336+ *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
337+ dec->vi.rate * sizeof (gint32) * dec->vi.channels);
338+ break;
339+ default:
340+ res = FALSE;
341+ }
342+ break;
343+ default:
344+ res = FALSE;
345+ }
346+done:
347+ gst_object_unref (dec);
348+
349+ return res;
350+
351+ /* ERRORS */
352+no_header:
353+ {
354+ GST_DEBUG_OBJECT (dec, "no header packets received");
355+ res = FALSE;
356+ goto done;
357+ }
358+no_format:
359+ {
360+ GST_DEBUG_OBJECT (dec, "formats unsupported");
361+ res = FALSE;
362+ goto done;
363+ }
364+}
365+
366+static gboolean
367+vorbis_dec_src_query (GstPad * pad, GstQuery * query)
368+{
369+ GstIVorbisDec *dec;
370+ gboolean res = FALSE;
371+
372+ dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
373+
374+ switch (GST_QUERY_TYPE (query)) {
375+ case GST_QUERY_POSITION:
376+ {
377+ gint64 granulepos, value;
378+ GstFormat my_format, format;
379+ gint64 time;
380+
381+ /* we start from the last seen granulepos */
382+ granulepos = dec->granulepos;
383+
384+ gst_query_parse_position (query, &format, NULL);
385+
386+ /* and convert to the final format in two steps with time as the
387+ * intermediate step */
388+ my_format = GST_FORMAT_TIME;
389+ if (!(res =
390+ vorbis_dec_convert (pad, GST_FORMAT_DEFAULT, granulepos,
391+ &my_format, &time)))
392+ goto error;
393+
394+ /* correct for the segment values */
395+ time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
396+
397+ GST_LOG_OBJECT (dec,
398+ "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time));
399+
400+ /* and convert to the final format */
401+ if (!(res = vorbis_dec_convert (pad, my_format, time, &format, &value)))
402+ goto error;
403+
404+ gst_query_set_position (query, format, value);
405+
406+ GST_LOG_OBJECT (dec,
407+ "query %p: we return %lld (format %u)", query, value, format);
408+
409+ break;
410+ }
411+ case GST_QUERY_DURATION:
412+ {
413+ GstPad *peer;
414+
415+ if (!(peer = gst_pad_get_peer (dec->sinkpad))) {
416+ GST_WARNING_OBJECT (dec, "sink pad %" GST_PTR_FORMAT " is not linked",
417+ dec->sinkpad);
418+ goto error;
419+ }
420+
421+ res = gst_pad_query (peer, query);
422+ gst_object_unref (peer);
423+ if (!res)
424+ goto error;
425+
426+ break;
427+ }
428+ case GST_QUERY_CONVERT:
429+ {
430+ GstFormat src_fmt, dest_fmt;
431+ gint64 src_val, dest_val;
432+
433+ gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
434+ if (!(res =
435+ vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
436+ goto error;
437+ gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
438+ break;
439+ }
440+ default:
441+ res = gst_pad_query_default (pad, query);
442+ break;
443+ }
444+done:
445+ gst_object_unref (dec);
446+
447+ return res;
448+
449+ /* ERRORS */
450+error:
451+ {
452+ GST_WARNING_OBJECT (dec, "error handling query");
453+ goto done;
454+ }
455+}
456+
457+static gboolean
458+vorbis_dec_sink_query (GstPad * pad, GstQuery * query)
459+{
460+ GstIVorbisDec *dec;
461+ gboolean res;
462+
463+ dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
464+
465+ switch (GST_QUERY_TYPE (query)) {
466+ case GST_QUERY_CONVERT:
467+ {
468+ GstFormat src_fmt, dest_fmt;
469+ gint64 src_val, dest_val;
470+
471+ gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
472+ if (!(res =
473+ vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val)))
474+ goto error;
475+ gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
476+ break;
477+ }
478+ default:
479+ res = gst_pad_query_default (pad, query);
480+ break;
481+ }
482+
483+done:
484+ gst_object_unref (dec);
485+
486+ return res;
487+
488+ /* ERRORS */
489+error:
490+ {
491+ GST_DEBUG_OBJECT (dec, "error converting value");
492+ goto done;
493+ }
494+}
495+
496+static gboolean
497+vorbis_dec_src_event (GstPad * pad, GstEvent * event)
498+{
499+ gboolean res = TRUE;
500+ GstIVorbisDec *dec;
501+
502+ dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
503+
504+ switch (GST_EVENT_TYPE (event)) {
505+ case GST_EVENT_SEEK:
506+ {
507+ GstFormat format, tformat;
508+ gdouble rate;
509+ GstEvent *real_seek;
510+ GstSeekFlags flags;
511+ GstSeekType cur_type, stop_type;
512+ gint64 cur, stop;
513+ gint64 tcur, tstop;
514+
515+ gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
516+ &stop_type, &stop);
517+ gst_event_unref (event);
518+
519+ /* we have to ask our peer to seek to time here as we know
520+ * nothing about how to generate a granulepos from the src
521+ * formats or anything.
522+ *
523+ * First bring the requested format to time
524+ */
525+ tformat = GST_FORMAT_TIME;
526+ if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur)))
527+ goto convert_error;
528+ if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop)))
529+ goto convert_error;
530+
531+ /* then seek with time on the peer */
532+ real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME,
533+ flags, cur_type, tcur, stop_type, tstop);
534+
535+ res = gst_pad_push_event (dec->sinkpad, real_seek);
536+
537+ break;
538+ }
539+ default:
540+ res = gst_pad_push_event (dec->sinkpad, event);
541+ break;
542+ }
543+done:
544+ gst_object_unref (dec);
545+
546+ return res;
547+
548+ /* ERRORS */
549+convert_error:
550+ {
551+ GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek");
552+ goto done;
553+ }
554+}
555+
556+static gboolean
557+vorbis_dec_sink_event (GstPad * pad, GstEvent * event)
558+{
559+ gboolean ret = FALSE;
560+ GstIVorbisDec *dec;
561+
562+ dec = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
563+
564+ GST_LOG_OBJECT (dec, "handling event");
565+ switch (GST_EVENT_TYPE (event)) {
566+ case GST_EVENT_EOS:
567+ ret = gst_pad_push_event (dec->srcpad, event);
568+ break;
569+ case GST_EVENT_FLUSH_START:
570+ ret = gst_pad_push_event (dec->srcpad, event);
571+ break;
572+ case GST_EVENT_FLUSH_STOP:
573+ /* here we must clean any state in the decoder */
574+#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
575+ vorbis_synthesis_restart (&dec->vd);
576+#endif
577+ gst_ivorbis_dec_reset (dec);
578+ ret = gst_pad_push_event (dec->srcpad, event);
579+ break;
580+ case GST_EVENT_NEWSEGMENT:
581+ {
582+ GstFormat format;
583+ gdouble rate, arate;
584+ gint64 start, stop, time;
585+ gboolean update;
586+
587+ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
588+ &start, &stop, &time);
589+
590+ /* we need time and a positive rate for now */
591+ if (format != GST_FORMAT_TIME)
592+ goto newseg_wrong_format;
593+
594+ if (rate <= 0.0)
595+ goto newseg_wrong_rate;
596+
597+ GST_DEBUG_OBJECT (dec,
598+ "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT
599+ ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT,
600+ update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
601+ GST_TIME_ARGS (time));
602+
603+ /* now configure the values */
604+ gst_segment_set_newsegment_full (&dec->segment, update,
605+ rate, arate, format, start, stop, time);
606+
607+ if (dec->initialized)
608+ /* and forward */
609+ ret = gst_pad_push_event (dec->srcpad, event);
610+ else {
611+ /* store it to send once we're initialized */
612+ dec->pendingevents = g_list_append (dec->pendingevents, event);
613+ ret = TRUE;
614+ }
615+ break;
616+ }
617+ default:
618+ ret = gst_pad_push_event (dec->srcpad, event);
619+ break;
620+ }
621+done:
622+ gst_object_unref (dec);
623+
624+ return ret;
625+
626+ /* ERRORS */
627+newseg_wrong_format:
628+ {
629+ GST_DEBUG_OBJECT (dec, "received non TIME newsegment");
630+ goto done;
631+ }
632+newseg_wrong_rate:
633+ {
634+ GST_DEBUG_OBJECT (dec, "negative rates not supported yet");
635+ goto done;
636+ }
637+}
638+
639+static GstFlowReturn
640+vorbis_handle_identification_packet (GstIVorbisDec * vd)
641+{
642+ GstCaps *caps;
643+ const GstAudioChannelPosition *pos = NULL;
644+
645+ switch (vd->vi.channels) {
646+ case 1:
647+ case 2:
648+ /* nothing */
649+ break;
650+ case 3:{
651+ static const GstAudioChannelPosition pos3[] = {
652+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
653+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
654+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT
655+ };
656+ pos = pos3;
657+ break;
658+ }
659+ case 4:{
660+ static const GstAudioChannelPosition pos4[] = {
661+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
662+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
663+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
664+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
665+ };
666+ pos = pos4;
667+ break;
668+ }
669+ case 5:{
670+ static const GstAudioChannelPosition pos5[] = {
671+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
672+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
673+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
674+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
675+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT
676+ };
677+ pos = pos5;
678+ break;
679+ }
680+ case 6:{
681+ static const GstAudioChannelPosition pos6[] = {
682+ GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
683+ GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
684+ GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
685+ GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
686+ GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
687+ GST_AUDIO_CHANNEL_POSITION_LFE
688+ };
689+ pos = pos6;
690+ break;
691+ }
692+ default:
693+ goto channel_count_error;
694+ }
695+
696+ caps = gst_caps_new_simple ("audio/x-raw-int",
697+ "rate", G_TYPE_INT, vd->vi.rate,
698+ "channels", G_TYPE_INT, vd->vi.channels,
699+ "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32,
700+ "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
701+
702+ if (pos) {
703+ gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos);
704+ }
705+ gst_pad_set_caps (vd->srcpad, caps);
706+ gst_caps_unref (caps);
707+
708+ return GST_FLOW_OK;
709+
710+ /* ERROR */
711+channel_count_error:
712+ {
713+ GST_ELEMENT_ERROR (vd, STREAM, NOT_IMPLEMENTED, (NULL),
714+ ("Unsupported channel count %d", vd->vi.channels));
715+ return GST_FLOW_ERROR;
716+ }
717+}
718+
719+static GstFlowReturn
720+vorbis_handle_comment_packet (GstIVorbisDec * vd, ogg_packet * packet)
721+{
722+#if 0
723+ guint bitrate = 0;
724+ gchar *encoder = NULL;
725+ GstTagList *list;
726+ GstBuffer *buf;
727+
728+ GST_DEBUG_OBJECT (vd, "parsing comment packet");
729+
730+ buf = gst_buffer_new_and_alloc (packet->bytes);
731+ GST_BUFFER_DATA (buf) = packet->packet;
732+
733+ list =
734+ gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7,
735+ &encoder);
736+
737+ vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE);
738+
739+ gst_tag_list_free (list);
740+ gst_buffer_unref (buf);
741+
742+ if (!vd->taglist) {
743+ GST_ERROR_OBJECT (vd, "couldn't decode comments");
744+ vd->taglist = gst_tag_list_new ();
745+ }
746+ if (encoder) {
747+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
748+ GST_TAG_ENCODER, encoder, NULL);
749+ g_free (encoder);
750+ }
751+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
752+ GST_TAG_ENCODER_VERSION, vd->vi.version,
753+ GST_TAG_AUDIO_CODEC, "Vorbis", NULL);
754+ if (vd->vi.bitrate_nominal > 0) {
755+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
756+ GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL);
757+ bitrate = vd->vi.bitrate_nominal;
758+ }
759+ if (vd->vi.bitrate_upper > 0) {
760+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
761+ GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL);
762+ if (!bitrate)
763+ bitrate = vd->vi.bitrate_upper;
764+ }
765+ if (vd->vi.bitrate_lower > 0) {
766+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
767+ GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL);
768+ if (!bitrate)
769+ bitrate = vd->vi.bitrate_lower;
770+ }
771+ if (bitrate) {
772+ gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE,
773+ GST_TAG_BITRATE, (guint) bitrate, NULL);
774+ }
775+
776+ if (vd->initialized) {
777+ gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad,
778+ vd->taglist);
779+ vd->taglist = NULL;
780+ } else {
781+ /* Only post them as messages for the time being. *
782+ * They will be pushed on the pad once the decoder is initialized */
783+ gst_element_post_message (GST_ELEMENT_CAST (vd),
784+ gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist)));
785+ }
786+#endif
787+ return GST_FLOW_OK;
788+}
789+
790+static GstFlowReturn
791+vorbis_handle_type_packet (GstIVorbisDec * vd)
792+{
793+ GList *walk;
794+
795+ g_assert (vd->initialized == FALSE);
796+
797+ vorbis_synthesis_init (&vd->vd, &vd->vi);
798+ vorbis_block_init (&vd->vd, &vd->vb);
799+ vd->initialized = TRUE;
800+
801+ if (vd->pendingevents) {
802+ for (walk = vd->pendingevents; walk; walk = g_list_next (walk))
803+ gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data));
804+ g_list_free (vd->pendingevents);
805+ vd->pendingevents = NULL;
806+ }
807+
808+ if (vd->taglist) {
809+ /* The tags have already been sent on the bus as messages. */
810+ gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist));
811+ vd->taglist = NULL;
812+ }
813+
814+ return GST_FLOW_OK;
815+}
816+
817+static GstFlowReturn
818+vorbis_handle_header_packet (GstIVorbisDec * vd, ogg_packet * packet)
819+{
820+ GstFlowReturn res;
821+
822+ GST_DEBUG_OBJECT (vd, "parsing header packet");
823+
824+ /* Packetno = 0 if the first byte is exactly 0x01 */
825+ packet->b_o_s = packet->packet->length ?
826+ ((packet->packet->buffer->data[0] == 0x1) ? 1 : 0) : 0;
827+
828+ if (vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet))
829+ goto header_read_error;
830+
831+ switch (packet->packet->length ? packet->packet->buffer->data[0] : 0x0) {
832+ case 0x01:
833+ res = vorbis_handle_identification_packet (vd);
834+ break;
835+ case 0x03:
836+ res = vorbis_handle_comment_packet (vd, packet);
837+ break;
838+ case 0x05:
839+ res = vorbis_handle_type_packet (vd);
840+ break;
841+ default:
842+ /* ignore */
843+ g_warning ("unknown vorbis header packet found");
844+ res = GST_FLOW_OK;
845+ break;
846+ }
847+ return res;
848+
849+ /* ERRORS */
850+header_read_error:
851+ {
852+ GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
853+ (NULL), ("couldn't read header packet"));
854+ return GST_FLOW_ERROR;
855+ }
856+}
857+
858+/* Taken from Tremor, misc.h */
859+#ifdef _ARM_ASSEM_
860+static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
861+ int tmp;
862+ asm volatile("subs %1, %0, #32768\n\t"
863+ "movpl %0, #0x7f00\n\t"
864+ "orrpl %0, %0, #0xff\n"
865+ "adds %1, %0, #32768\n\t"
866+ "movmi %0, #0x8000"
867+ : "+r"(x),"=r"(tmp)
868+ :
869+ : "cc");
870+ return(x);
871+}
872+#else
873+static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
874+ int ret=x;
875+ ret-= ((x<=32767)-1)&(x-32767);
876+ ret-= ((x>=-32768)-1)&(x+32768);
877+ return(ret);
878+}
879+#endif
880+
881+static void
882+copy_samples (gint32 *out, ogg_int32_t **in, guint samples, gint channels)
883+{
884+ gint i, j;
885+
886+ for (j = 0; j < samples; j++) {
887+ for (i = 0; i < channels; i++) {
888+ *out++ = CLIP_TO_15 (in[i][j]>>9);
889+ }
890+ }
891+}
892+
893+/* clip output samples to the segment boundaries
894+ */
895+static gboolean
896+vorbis_do_clip (GstIVorbisDec * dec, GstBuffer * buf)
897+{
898+ gint64 start, stop, cstart, cstop, diff;
899+
900+ start = GST_BUFFER_TIMESTAMP (buf);
901+ stop = start + GST_BUFFER_DURATION (buf);
902+
903+ if (!gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
904+ start, stop, &cstart, &cstop))
905+ goto clipped;
906+
907+ /* see if some clipping happened */
908+ diff = cstart - start;
909+ if (diff > 0) {
910+ GST_BUFFER_TIMESTAMP (buf) = cstart;
911+ GST_BUFFER_DURATION (buf) -= diff;
912+
913+ /* bring clipped time to samples */
914+ diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND);
915+ /* samples to bytes */
916+ diff *= (sizeof (gint32) * dec->vi.channels);
917+ GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %"
918+ G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
919+ GST_BUFFER_DATA (buf) += diff;
920+ GST_BUFFER_SIZE (buf) -= diff;
921+ }
922+ diff = stop - cstop;
923+ if (diff > 0) {
924+ GST_BUFFER_DURATION (buf) -= diff;
925+
926+ /* bring clipped time to samples and then to bytes */
927+ diff = gst_util_uint64_scale_int (diff, dec->vi.rate, GST_SECOND);
928+ diff *= (sizeof (gint32) * dec->vi.channels);
929+ GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %"
930+ G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
931+ GST_BUFFER_SIZE (buf) -= diff;
932+ }
933+
934+ return FALSE;
935+
936+ /* dropped buffer */
937+clipped:
938+ {
939+ GST_DEBUG_OBJECT (dec, "clipped buffer");
940+ gst_buffer_unref (buf);
941+ return TRUE;
942+ }
943+}
944+
945+static GstFlowReturn
946+vorbis_dec_push (GstIVorbisDec * dec, GstBuffer * buf)
947+{
948+ GstFlowReturn result;
949+ gint64 outoffset = GST_BUFFER_OFFSET (buf);
950+
951+ if (outoffset == -1) {
952+ dec->queued = g_list_append (dec->queued, buf);
953+ GST_DEBUG_OBJECT (dec, "queued buffer");
954+ result = GST_FLOW_OK;
955+ } else {
956+ if (G_UNLIKELY (dec->queued)) {
957+ gint64 size;
958+ GList *walk;
959+
960+ GST_DEBUG_OBJECT (dec, "first buffer with offset %lld", outoffset);
961+
962+ size = g_list_length (dec->queued);
963+ for (walk = g_list_last (dec->queued); walk;
964+ walk = g_list_previous (walk)) {
965+ GstBuffer *buffer = GST_BUFFER (walk->data);
966+
967+ outoffset -=
968+ GST_BUFFER_SIZE (buffer) / (sizeof (gint32) * dec->vi.channels);
969+
970+ GST_BUFFER_OFFSET (buffer) = outoffset;
971+ GST_BUFFER_TIMESTAMP (buffer) =
972+ gst_util_uint64_scale_int (outoffset, GST_SECOND, dec->vi.rate);
973+ GST_DEBUG_OBJECT (dec, "patch buffer %" G_GUINT64_FORMAT
974+ " offset %" G_GUINT64_FORMAT, size, outoffset);
975+ size--;
976+ }
977+ for (walk = dec->queued; walk; walk = g_list_next (walk)) {
978+ GstBuffer *buffer = GST_BUFFER (walk->data);
979+
980+ /* clips or returns FALSE with buffer unreffed when completely
981+ * clipped */
982+ if (vorbis_do_clip (dec, buffer))
983+ continue;
984+
985+ if (dec->discont) {
986+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
987+ dec->discont = FALSE;
988+ }
989+ /* ignore the result */
990+ gst_pad_push (dec->srcpad, buffer);
991+ }
992+ g_list_free (dec->queued);
993+ dec->queued = NULL;
994+ }
995+
996+ /* clip */
997+ if (vorbis_do_clip (dec, buf))
998+ return GST_FLOW_OK;
999+
1000+ if (dec->discont) {
1001+ GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
1002+ dec->discont = FALSE;
1003+ }
1004+ result = gst_pad_push (dec->srcpad, buf);
1005+ }
1006+
1007+ return result;
1008+}
1009+
1010+static GstFlowReturn
1011+vorbis_handle_data_packet (GstIVorbisDec * vd, ogg_packet * packet)
1012+{
1013+ ogg_int32_t **pcm;
1014+ guint sample_count;
1015+ GstBuffer *out;
1016+ GstFlowReturn result;
1017+ gint size;
1018+
1019+ if (!vd->initialized)
1020+ goto not_initialized;
1021+
1022+ /* FIXME, we should queue undecoded packets here until we get
1023+ * a timestamp, then we reverse timestamp the queued packets and
1024+ * clip them, then we decode only the ones we want and don't
1025+ * keep decoded data in memory.
1026+ * Ideally, of course, the demuxer gives us a valid timestamp on
1027+ * the first packet.
1028+ */
1029+
1030+ /* normal data packet */
1031+ /* FIXME, we can skip decoding if the packet is outside of the
1032+ * segment, this is however not very trivial as we need a previous
1033+ * packet to decode the current one so we must be carefull not to
1034+ * throw away too much. For now we decode everything and clip right
1035+ * before pushing data. */
1036+ if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet,1)))
1037+ goto could_not_read;
1038+
1039+ if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0))
1040+ goto not_accepted;
1041+
1042+ /* assume all goes well here */
1043+ result = GST_FLOW_OK;
1044+
1045+ /* count samples ready for reading */
1046+ if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0)
1047+ goto done;
1048+
1049+ size = sample_count * vd->vi.channels * sizeof (gint32);
1050+
1051+ /* alloc buffer for it */
1052+ result =
1053+ gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE,
1054+ size, GST_PAD_CAPS (vd->srcpad), &out);
1055+ if (G_UNLIKELY (result != GST_FLOW_OK))
1056+ goto done;
1057+
1058+ /* get samples ready for reading now, should be sample_count */
1059+ if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count))
1060+ goto wrong_samples;
1061+
1062+ /* copy samples in buffer */
1063+ copy_samples ((gint32 *) GST_BUFFER_DATA (out), pcm, sample_count,
1064+ vd->vi.channels);
1065+
1066+ GST_BUFFER_SIZE (out) = size;
1067+ GST_BUFFER_OFFSET (out) = vd->granulepos;
1068+ if (vd->granulepos != -1) {
1069+ GST_BUFFER_OFFSET_END (out) = vd->granulepos + sample_count;
1070+ GST_BUFFER_TIMESTAMP (out) =
1071+ gst_util_uint64_scale_int (vd->granulepos, GST_SECOND, vd->vi.rate);
1072+ } else {
1073+ GST_BUFFER_TIMESTAMP (out) = -1;
1074+ }
1075+ /* this should not overflow */
1076+ GST_BUFFER_DURATION (out) = sample_count * GST_SECOND / vd->vi.rate;
1077+
1078+ if (vd->cur_timestamp != GST_CLOCK_TIME_NONE) {
1079+ GST_BUFFER_TIMESTAMP (out) = vd->cur_timestamp;
1080+ GST_DEBUG_OBJECT (vd,
1081+ "cur_timestamp: %" GST_TIME_FORMAT " + %" GST_TIME_FORMAT " = % "
1082+ GST_TIME_FORMAT, GST_TIME_ARGS (vd->cur_timestamp),
1083+ GST_TIME_ARGS (GST_BUFFER_DURATION (out)),
1084+ GST_TIME_ARGS (vd->cur_timestamp + GST_BUFFER_DURATION (out)));
1085+ vd->cur_timestamp += GST_BUFFER_DURATION (out);
1086+ GST_BUFFER_OFFSET (out) = GST_CLOCK_TIME_TO_FRAMES (vd->cur_timestamp,
1087+ vd->vi.rate);
1088+ GST_BUFFER_OFFSET_END (out) = GST_BUFFER_OFFSET (out) + sample_count;
1089+ }
1090+
1091+ if (vd->granulepos != -1)
1092+ vd->granulepos += sample_count;
1093+
1094+ result = vorbis_dec_push (vd, out);
1095+
1096+done:
1097+ vorbis_synthesis_read (&vd->vd, sample_count);
1098+
1099+ /* granulepos is the last sample in the packet */
1100+ if (packet->granulepos != -1)
1101+ vd->granulepos = packet->granulepos;
1102+
1103+ return result;
1104+
1105+ /* ERRORS */
1106+not_initialized:
1107+ {
1108+ GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
1109+ (NULL), ("no header sent yet"));
1110+ return GST_FLOW_ERROR;
1111+ }
1112+could_not_read:
1113+ {
1114+ GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
1115+ (NULL), ("couldn't read data packet"));
1116+ return GST_FLOW_ERROR;
1117+ }
1118+not_accepted:
1119+ {
1120+ GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
1121+ (NULL), ("vorbis decoder did not accept data packet"));
1122+ return GST_FLOW_ERROR;
1123+ }
1124+wrong_samples:
1125+ {
1126+ gst_buffer_unref (out);
1127+ GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE,
1128+ (NULL), ("vorbis decoder reported wrong number of samples"));
1129+ return GST_FLOW_ERROR;
1130+ }
1131+}
1132+
1133+static GstFlowReturn
1134+vorbis_dec_chain (GstPad * pad, GstBuffer * buffer)
1135+{
1136+ GstIVorbisDec *vd;
1137+ ogg_packet packet;
1138+ ogg_reference ref;
1139+ ogg_buffer buf;
1140+ GstFlowReturn result = GST_FLOW_OK;
1141+ GstClockTime timestamp;
1142+ guint64 offset_end;
1143+
1144+ vd = GST_IVORBIS_DEC (gst_pad_get_parent (pad));
1145+
1146+ /* resync on DISCONT */
1147+ if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
1148+ GST_DEBUG_OBJECT (vd, "received DISCONT buffer");
1149+ vd->granulepos = -1;
1150+ vd->cur_timestamp = GST_CLOCK_TIME_NONE;
1151+ vd->prev_timestamp = GST_CLOCK_TIME_NONE;
1152+#ifdef HAVE_VORBIS_SYNTHESIS_RESTART
1153+ vorbis_synthesis_restart (&vd->vd);
1154+#endif
1155+ vd->discont = TRUE;
1156+ }
1157+
1158+ timestamp = GST_BUFFER_TIMESTAMP (buffer);
1159+ offset_end = GST_BUFFER_OFFSET_END (buffer);
1160+
1161+ /* only ogg has granulepos, demuxers of other container formats
1162+ * might provide us with timestamps instead (e.g. matroskademux) */
1163+ if (offset_end == GST_BUFFER_OFFSET_NONE && timestamp != GST_CLOCK_TIME_NONE) {
1164+ /* we might get multiple consecutive buffers with the same timestamp */
1165+ if (timestamp != vd->prev_timestamp) {
1166+ vd->cur_timestamp = timestamp;
1167+ vd->prev_timestamp = timestamp;
1168+ }
1169+ } else {
1170+ vd->cur_timestamp = GST_CLOCK_TIME_NONE;
1171+ vd->prev_timestamp = GST_CLOCK_TIME_NONE;
1172+ }
1173+
1174+ /* make ogg_packet out of the buffer */
1175+ buf.data = GST_BUFFER_DATA (buffer);
1176+ buf.size = GST_BUFFER_SIZE (buffer);
1177+ buf.refcount = 1;
1178+ buf.ptr.owner = NULL;
1179+ buf.ptr.next = NULL;
1180+
1181+ ref.buffer = &buf;
1182+ ref.begin = 0;
1183+ ref.length = buf.size;
1184+ ref.next = NULL;
1185+
1186+ packet.packet = &ref;
1187+ packet.bytes = ref.length;
1188+ packet.granulepos = offset_end;
1189+ packet.packetno = 0; /* we don't care */
1190+ /*
1191+ * FIXME. Is there anyway to know that this is the last packet and
1192+ * set e_o_s??
1193+ * Yes there is, keep one packet at all times and only push out when
1194+ * you receive a new one. Implement this.
1195+ */
1196+ packet.e_o_s = 0;
1197+
1198+ if (G_UNLIKELY (packet.bytes < 1))
1199+ goto wrong_size;
1200+
1201+ GST_DEBUG_OBJECT (vd, "vorbis granule: %" G_GINT64_FORMAT,
1202+ (gint64) packet.granulepos);
1203+
1204+ /* switch depending on packet type */
1205+ if (buf.data[0] & 1) {
1206+ if (vd->initialized) {
1207+ GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet");
1208+ goto done;
1209+ }
1210+ result = vorbis_handle_header_packet (vd, &packet);
1211+ } else {
1212+ result = vorbis_handle_data_packet (vd, &packet);
1213+ }
1214+
1215+ GST_DEBUG_OBJECT (vd, "offset end: %" G_GUINT64_FORMAT, offset_end);
1216+
1217+done:
1218+ gst_buffer_unref (buffer);
1219+ gst_object_unref (vd);
1220+
1221+ return result;
1222+
1223+ /* ERRORS */
1224+wrong_size:
1225+ {
1226+ GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty buffer received"));
1227+ result = GST_FLOW_ERROR;
1228+ vd->discont = TRUE;
1229+ goto done;
1230+ }
1231+}
1232+
1233+static GstStateChangeReturn
1234+vorbis_dec_change_state (GstElement * element, GstStateChange transition)
1235+{
1236+ GstIVorbisDec *vd = GST_IVORBIS_DEC (element);
1237+ GstStateChangeReturn res;
1238+
1239+ switch (transition) {
1240+ case GST_STATE_CHANGE_NULL_TO_READY:
1241+ break;
1242+ case GST_STATE_CHANGE_READY_TO_PAUSED:
1243+ vorbis_info_init (&vd->vi);
1244+ vorbis_comment_init (&vd->vc);
1245+ vd->initialized = FALSE;
1246+ gst_ivorbis_dec_reset (vd);
1247+ break;
1248+ case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1249+ break;
1250+ default:
1251+ break;
1252+ }
1253+
1254+ res = parent_class->change_state (element, transition);
1255+
1256+ switch (transition) {
1257+ case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1258+ break;
1259+ case GST_STATE_CHANGE_PAUSED_TO_READY:
1260+ GST_DEBUG_OBJECT (vd, "PAUSED -> READY, clearing vorbis structures");
1261+ vorbis_block_clear (&vd->vb);
1262+ vorbis_dsp_clear (&vd->vd);
1263+ vorbis_comment_clear (&vd->vc);
1264+ vorbis_info_clear (&vd->vi);
1265+ gst_ivorbis_dec_reset (vd);
1266+ break;
1267+ case GST_STATE_CHANGE_READY_TO_NULL:
1268+ break;
1269+ default:
1270+ break;
1271+ }
1272+
1273+ return res;
1274+}
1275diff -urNd ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbisdec.h ext/ivorbis/vorbisdec.h
1276--- ../gst-plugins-bad0.10-0.10.3+cvs20060918/ext/ivorbis/vorbisdec.h 1970-01-01 01:00:00.000000000 +0100
1277+++ ext/ivorbis/vorbisdec.h 2006-09-20 17:26:46.000000000 +0100
1278@@ -0,0 +1,87 @@
1279+/* -*- c-basic-offset: 2 -*-
1280+ * GStreamer
1281+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
1282+ *
1283+ * Tremor modifications <2006>:
1284+ * Chris Lord, OpenedHand Ltd. <chris@openedhand.com>, http://www.o-hand.com/
1285+ *
1286+ * This library is free software; you can redistribute it and/or
1287+ * modify it under the terms of the GNU Library General Public
1288+ * License as published by the Free Software Foundation; either
1289+ * version 2 of the License, or (at your option) any later version.
1290+ *
1291+ * This library is distributed in the hope that it will be useful,
1292+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1293+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1294+ * Library General Public License for more details.
1295+ *
1296+ * You should have received a copy of the GNU Library General Public
1297+ * License along with this library; if not, write to the
1298+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1299+ * Boston, MA 02111-1307, USA.
1300+ */
1301+
1302+
1303+#ifndef __GST_IVORBIS_DEC_H__
1304+#define __GST_IVORBIS_DEC_H__
1305+
1306+
1307+#include <gst/gst.h>
1308+#include <tremor/ivorbiscodec.h>
1309+
1310+G_BEGIN_DECLS
1311+
1312+#define GST_TYPE_IVORBIS_DEC \
1313+ (gst_ivorbis_dec_get_type())
1314+#define GST_IVORBIS_DEC(obj) \
1315+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IVORBIS_DEC,GstIVorbisDec))
1316+#define GST_IVORBIS_DEC_CLASS(klass) \
1317+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IVORBIS_DEC,GstIVorbisDecClass))
1318+#define GST_IS_IVORBIS_DEC(obj) \
1319+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IVORBIS_DEC))
1320+#define GST_IS_IVORBIS_DEC_CLASS(klass) \
1321+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IVORBIS_DEC))
1322+
1323+typedef struct _GstIVorbisDec GstIVorbisDec;
1324+typedef struct _GstIVorbisDecClass GstIVorbisDecClass;
1325+
1326+/**
1327+ * GstIVorbisDec:
1328+ *
1329+ * Opaque data structure.
1330+ */
1331+struct _GstIVorbisDec {
1332+ GstElement element;
1333+
1334+ GstPad * sinkpad;
1335+ GstPad * srcpad;
1336+
1337+ vorbis_dsp_state vd;
1338+ vorbis_info vi;
1339+ vorbis_comment vc;
1340+ vorbis_block vb;
1341+ guint64 granulepos;
1342+
1343+ gboolean initialized;
1344+
1345+ GList *queued;
1346+
1347+ GstSegment segment;
1348+ gboolean discont;
1349+
1350+ GstClockTime cur_timestamp; /* only used with non-ogg container formats */
1351+ GstClockTime prev_timestamp; /* only used with non-ogg container formats */
1352+
1353+ GList *pendingevents;
1354+ GstTagList *taglist;
1355+};
1356+
1357+struct _GstIVorbisDecClass {
1358+ GstElementClass parent_class;
1359+};
1360+
1361+GType gst_ivorbis_dec_get_type(void);
1362+
1363+G_END_DECLS
1364+
1365+#endif /* __GST_IVORBIS_DEC_H__ */