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