diff options
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.patch | 1365 |
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) | ||
17 | diff -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) \ | ||
29 | diff -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 | |||
59 | diff -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 | +} | ||
1275 | diff -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__ */ | ||