1 /* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
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 */
20 /**
21 * SECTION:element-mad
22 * @see_also: lame
23 *
24 * MP3 audio decoder.
25 *
26 * <refsect2>
27 * <title>Example pipelines</title>
28 * |[
29 * gst-launch filesrc location=music.mp3 ! mad ! audioconvert ! audioresample ! autoaudiosink
30 * ]| Decode the mp3 file and play
31 * </refsect2>
32 */
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <stdlib.h>
39 #include <string.h>
40 #include "gstmad.h"
41 #include <gst/audio/audio.h>
43 #ifdef HAVE_ID3TAG
44 #include <id3tag.h>
45 #endif
47 enum
48 {
49 ARG_0,
50 ARG_HALF,
51 ARG_IGNORE_CRC
52 };
54 GST_DEBUG_CATEGORY_STATIC (mad_debug);
55 #define GST_CAT_DEFAULT mad_debug
57 static GstStaticPadTemplate mad_src_template_factory =
58 GST_STATIC_PAD_TEMPLATE ("src",
59 GST_PAD_SRC,
60 GST_PAD_ALWAYS,
61 GST_STATIC_CAPS ("audio/x-raw-int, "
62 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
63 "signed = (boolean) true, "
64 "width = (int) 32, "
65 "depth = (int) 32, "
66 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
67 "channels = (int) [ 1, 2 ]")
68 );
70 /* FIXME: make three caps, for mpegversion 1, 2 and 2.5 */
71 static GstStaticPadTemplate mad_sink_template_factory =
72 GST_STATIC_PAD_TEMPLATE ("sink",
73 GST_PAD_SINK,
74 GST_PAD_ALWAYS,
75 GST_STATIC_CAPS ("audio/mpeg, "
76 "mpegversion = (int) 1, "
77 "layer = (int) [ 1, 3 ], "
78 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
79 "channels = (int) [ 1, 2 ]")
80 );
82 static void gst_mad_dispose (GObject * object);
83 static void gst_mad_clear_queues (GstMad * mad);
85 static void gst_mad_set_property (GObject * object, guint prop_id,
86 const GValue * value, GParamSpec * pspec);
87 static void gst_mad_get_property (GObject * object, guint prop_id,
88 GValue * value, GParamSpec * pspec);
90 static gboolean gst_mad_src_event (GstPad * pad, GstEvent * event);
92 static const GstQueryType *gst_mad_get_query_types (GstPad * pad);
94 static gboolean gst_mad_src_query (GstPad * pad, GstQuery * query);
95 static gboolean gst_mad_convert_sink (GstPad * pad, GstFormat src_format,
96 gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
97 static gboolean gst_mad_convert_src (GstPad * pad, GstFormat src_format,
98 gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
100 static gboolean gst_mad_sink_event (GstPad * pad, GstEvent * event);
101 static GstFlowReturn gst_mad_chain (GstPad * pad, GstBuffer * buffer);
102 static GstFlowReturn gst_mad_chain_reverse (GstMad * mad, GstBuffer * buf);
104 static GstStateChangeReturn gst_mad_change_state (GstElement * element,
105 GstStateChange transition);
107 static void gst_mad_set_index (GstElement * element, GstIndex * index);
108 static GstIndex *gst_mad_get_index (GstElement * element);
110 #ifdef HAVE_ID3TAG
111 static GstTagList *gst_mad_id3_to_tag_list (const struct id3_tag *tag);
112 #endif
114 GST_BOILERPLATE (GstMad, gst_mad, GstElement, GST_TYPE_ELEMENT);
116 /*
117 #define GST_TYPE_MAD_LAYER (gst_mad_layer_get_type())
118 static GType
119 gst_mad_layer_get_type (void)
120 {
121 static GType mad_layer_type = 0;
122 static GEnumValue mad_layer[] = {
123 {0, "Unknown", "unknown"},
124 {MAD_LAYER_I, "Layer I", "1"},
125 {MAD_LAYER_II, "Layer II", "2"},
126 {MAD_LAYER_III, "Layer III", "3"},
127 {0, NULL, NULL},
128 };
130 if (!mad_layer_type) {
131 mad_layer_type = g_enum_register_static ("GstMadLayer", mad_layer);
132 }
133 return mad_layer_type;
134 }
135 */
137 #define GST_TYPE_MAD_MODE (gst_mad_mode_get_type())
138 static GType
139 gst_mad_mode_get_type (void)
140 {
141 static GType mad_mode_type = 0;
142 static GEnumValue mad_mode[] = {
143 {-1, "Unknown", "unknown"},
144 {MAD_MODE_SINGLE_CHANNEL, "Mono", "mono"},
145 {MAD_MODE_DUAL_CHANNEL, "Dual Channel", "dual"},
146 {MAD_MODE_JOINT_STEREO, "Joint Stereo", "joint"},
147 {MAD_MODE_STEREO, "Stereo", "stereo"},
148 {0, NULL, NULL},
149 };
151 if (!mad_mode_type) {
152 mad_mode_type = g_enum_register_static ("GstMadMode", mad_mode);
153 }
154 return mad_mode_type;
155 }
157 #define GST_TYPE_MAD_EMPHASIS (gst_mad_emphasis_get_type())
158 static GType
159 gst_mad_emphasis_get_type (void)
160 {
161 static GType mad_emphasis_type = 0;
162 static GEnumValue mad_emphasis[] = {
163 {-1, "Unknown", "unknown"},
164 {MAD_EMPHASIS_NONE, "None", "none"},
165 {MAD_EMPHASIS_50_15_US, "50/15 Microseconds", "50-15"},
166 {MAD_EMPHASIS_CCITT_J_17, "CCITT J.17", "j-17"},
167 {MAD_EMPHASIS_RESERVED, "Reserved", "reserved"},
168 {0, NULL, NULL},
169 };
171 if (!mad_emphasis_type) {
172 mad_emphasis_type = g_enum_register_static ("GstMadEmphasis", mad_emphasis);
173 }
174 return mad_emphasis_type;
175 }
177 static void
178 gst_mad_base_init (gpointer g_class)
179 {
180 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
182 gst_element_class_add_pad_template (element_class,
183 gst_static_pad_template_get (&mad_sink_template_factory));
184 gst_element_class_add_pad_template (element_class,
185 gst_static_pad_template_get (&mad_src_template_factory));
186 gst_element_class_set_details_simple (element_class, "mad mp3 decoder",
187 "Codec/Decoder/Audio",
188 "Uses mad code to decode mp3 streams", "Wim Taymans <wim@fluendo.com>");
189 }
191 static void
192 gst_mad_class_init (GstMadClass * klass)
193 {
194 GObjectClass *gobject_class;
195 GstElementClass *gstelement_class;
197 gobject_class = (GObjectClass *) klass;
198 gstelement_class = (GstElementClass *) klass;
200 parent_class = g_type_class_peek_parent (klass);
202 gobject_class->set_property = gst_mad_set_property;
203 gobject_class->get_property = gst_mad_get_property;
204 gobject_class->dispose = gst_mad_dispose;
206 gstelement_class->change_state = gst_mad_change_state;
207 gstelement_class->set_index = gst_mad_set_index;
208 gstelement_class->get_index = gst_mad_get_index;
210 /* init properties */
211 /* currently, string representations are used, we might want to change that */
212 /* FIXME: descriptions need to be more technical,
213 * default values and ranges need to be selected right */
214 g_object_class_install_property (gobject_class, ARG_HALF,
215 g_param_spec_boolean ("half", "Half", "Generate PCM at 1/2 sample rate",
216 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
217 g_object_class_install_property (gobject_class, ARG_IGNORE_CRC,
218 g_param_spec_boolean ("ignore-crc", "Ignore CRC", "Ignore CRC errors",
219 TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
221 /* register tags */
222 #define GST_TAG_LAYER "layer"
223 #define GST_TAG_MODE "mode"
224 #define GST_TAG_EMPHASIS "emphasis"
226 /* FIXME 0.11: strings!? why? */
227 gst_tag_register (GST_TAG_LAYER, GST_TAG_FLAG_ENCODED, G_TYPE_UINT,
228 "layer", "MPEG audio layer", NULL);
229 gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
230 "mode", "MPEG audio channel mode", NULL);
231 gst_tag_register (GST_TAG_EMPHASIS, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
232 "emphasis", "MPEG audio emphasis", NULL);
234 /* ref these here from a thread-safe context (ie. not the streaming thread) */
235 g_type_class_ref (GST_TYPE_MAD_MODE);
236 g_type_class_ref (GST_TYPE_MAD_EMPHASIS);
237 }
239 static void
240 gst_mad_init (GstMad * mad, GstMadClass * klass)
241 {
242 GstPadTemplate *template;
244 /* create the sink and src pads */
245 template = gst_static_pad_template_get (&mad_sink_template_factory);
246 mad->sinkpad = gst_pad_new_from_template (template, "sink");
247 gst_object_unref (template);
248 gst_element_add_pad (GST_ELEMENT (mad), mad->sinkpad);
249 gst_pad_set_chain_function (mad->sinkpad, GST_DEBUG_FUNCPTR (gst_mad_chain));
250 gst_pad_set_event_function (mad->sinkpad,
251 GST_DEBUG_FUNCPTR (gst_mad_sink_event));
253 template = gst_static_pad_template_get (&mad_src_template_factory);
254 mad->srcpad = gst_pad_new_from_template (template, "src");
255 gst_object_unref (template);
256 gst_element_add_pad (GST_ELEMENT (mad), mad->srcpad);
257 gst_pad_set_event_function (mad->srcpad,
258 GST_DEBUG_FUNCPTR (gst_mad_src_event));
259 gst_pad_set_query_function (mad->srcpad,
260 GST_DEBUG_FUNCPTR (gst_mad_src_query));
261 gst_pad_set_query_type_function (mad->srcpad,
262 GST_DEBUG_FUNCPTR (gst_mad_get_query_types));
263 gst_pad_use_fixed_caps (mad->srcpad);
265 mad->tempbuffer = g_malloc (MAD_BUFFER_MDLEN * 3);
266 mad->tempsize = 0;
267 mad->base_byte_offset = 0;
268 mad->bytes_consumed = 0;
269 mad->total_samples = 0;
270 mad->new_header = TRUE;
271 mad->framecount = 0;
272 mad->vbr_average = 0;
273 mad->vbr_rate = 0;
274 mad->restart = TRUE;
275 mad->segment_start = 0;
276 gst_segment_init (&mad->segment, GST_FORMAT_TIME);
277 mad->header.mode = -1;
278 mad->header.emphasis = -1;
279 mad->tags = NULL;
281 mad->half = FALSE;
282 mad->ignore_crc = TRUE;
283 mad->check_for_xing = TRUE;
284 mad->xing_found = FALSE;
285 }
287 static void
288 gst_mad_dispose (GObject * object)
289 {
290 GstMad *mad = GST_MAD (object);
292 gst_mad_set_index (GST_ELEMENT (object), NULL);
294 g_free (mad->tempbuffer);
295 mad->tempbuffer = NULL;
297 g_list_foreach (mad->pending_events, (GFunc) gst_mini_object_unref, NULL);
298 g_list_free (mad->pending_events);
299 mad->pending_events = NULL;
301 G_OBJECT_CLASS (parent_class)->dispose (object);
302 }
304 static void
305 gst_mad_set_index (GstElement * element, GstIndex * index)
306 {
307 GstMad *mad = GST_MAD (element);
309 mad->index = index;
311 if (index)
312 gst_index_get_writer_id (index, GST_OBJECT (element), &mad->index_id);
313 }
315 static GstIndex *
316 gst_mad_get_index (GstElement * element)
317 {
318 GstMad *mad = GST_MAD (element);
320 return mad->index;
321 }
323 static gboolean
324 gst_mad_convert_sink (GstPad * pad, GstFormat src_format, gint64 src_value,
325 GstFormat * dest_format, gint64 * dest_value)
326 {
327 gboolean res = TRUE;
328 GstMad *mad;
330 if (src_format == *dest_format) {
331 *dest_value = src_value;
332 return TRUE;
333 }
335 /* -1 always maps to -1, and 0 to 0, we don't need any more info for that */
336 if (src_value == -1 || src_value == 0) {
337 *dest_value = src_value;
338 return TRUE;
339 }
341 mad = GST_MAD (GST_PAD_PARENT (pad));
343 if (mad->vbr_average == 0)
344 return FALSE;
346 switch (src_format) {
347 case GST_FORMAT_BYTES:
348 switch (*dest_format) {
349 case GST_FORMAT_TIME:
350 /* multiply by 8 because vbr is in bits/second */
351 *dest_value = gst_util_uint64_scale (src_value, 8 * GST_SECOND,
352 mad->vbr_average);
353 break;
354 default:
355 res = FALSE;
356 }
357 break;
358 case GST_FORMAT_TIME:
359 switch (*dest_format) {
360 case GST_FORMAT_BYTES:
361 /* multiply by 8 because vbr is in bits/second */
362 *dest_value = gst_util_uint64_scale (src_value, mad->vbr_average,
363 8 * GST_SECOND);
364 break;
365 default:
366 res = FALSE;
367 }
368 break;
369 default:
370 res = FALSE;
371 }
372 return res;
373 }
375 static gboolean
376 gst_mad_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
377 GstFormat * dest_format, gint64 * dest_value)
378 {
379 gboolean res = TRUE;
380 guint scale = 1;
381 gint bytes_per_sample;
382 GstMad *mad;
384 if (src_format == *dest_format) {
385 *dest_value = src_value;
386 return TRUE;
387 }
389 /* -1 always maps to -1, and 0 to 0, we don't need any more info for that */
390 if (src_value == -1 || src_value == 0) {
391 *dest_value = src_value;
392 return TRUE;
393 }
395 mad = GST_MAD (GST_PAD_PARENT (pad));
397 bytes_per_sample = mad->channels * 4;
399 switch (src_format) {
400 case GST_FORMAT_BYTES:
401 switch (*dest_format) {
402 case GST_FORMAT_DEFAULT:
403 if (bytes_per_sample == 0)
404 return FALSE;
405 *dest_value = src_value / bytes_per_sample;
406 break;
407 case GST_FORMAT_TIME:
408 {
409 gint byterate = bytes_per_sample * mad->rate;
411 if (byterate == 0)
412 return FALSE;
413 *dest_value =
414 gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
415 break;
416 }
417 default:
418 res = FALSE;
419 }
420 break;
421 case GST_FORMAT_DEFAULT:
422 switch (*dest_format) {
423 case GST_FORMAT_BYTES:
424 *dest_value = src_value * bytes_per_sample;
425 break;
426 case GST_FORMAT_TIME:
427 if (mad->rate == 0)
428 return FALSE;
429 *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
430 mad->rate);
431 break;
432 default:
433 res = FALSE;
434 }
435 break;
436 case GST_FORMAT_TIME:
437 switch (*dest_format) {
438 case GST_FORMAT_BYTES:
439 scale = bytes_per_sample;
440 /* fallthrough */
441 case GST_FORMAT_DEFAULT:
442 *dest_value = gst_util_uint64_scale_int (src_value,
443 scale * mad->rate, GST_SECOND);
444 break;
445 default:
446 res = FALSE;
447 }
448 break;
449 default:
450 res = FALSE;
451 }
452 return res;
453 }
455 static const GstQueryType *
456 gst_mad_get_query_types (GstPad * pad)
457 {
458 static const GstQueryType gst_mad_src_query_types[] = {
459 GST_QUERY_POSITION,
460 GST_QUERY_DURATION,
461 GST_QUERY_CONVERT,
462 0
463 };
465 return gst_mad_src_query_types;
466 }
468 static gboolean
469 gst_mad_src_query (GstPad * pad, GstQuery * query)
470 {
471 gboolean res = TRUE;
472 GstPad *peer;
473 GstMad *mad;
475 mad = GST_MAD (GST_PAD_PARENT (pad));
477 peer = gst_pad_get_peer (mad->sinkpad);
479 switch (GST_QUERY_TYPE (query)) {
480 case GST_QUERY_FORMATS:
481 gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, GST_FORMAT_TIME,
482 GST_FORMAT_BYTES);
483 break;
484 case GST_QUERY_POSITION:
485 {
486 GstFormat format;
487 gint64 cur;
489 /* save requested format */
490 gst_query_parse_position (query, &format, NULL);
492 /* try any demuxer before us first */
493 if (format == GST_FORMAT_TIME && peer && gst_pad_query (peer, query)) {
494 gst_query_parse_position (query, NULL, &cur);
495 GST_LOG_OBJECT (mad, "peer returned position %" GST_TIME_FORMAT,
496 GST_TIME_ARGS (cur));
497 break;
498 }
500 /* and convert to the requested format */
501 if (format != GST_FORMAT_DEFAULT) {
502 if (!gst_mad_convert_src (pad, GST_FORMAT_DEFAULT, mad->total_samples,
503 &format, &cur))
504 goto error;
505 } else {
506 cur = mad->total_samples;
507 }
509 gst_query_set_position (query, format, cur);
511 if (format == GST_FORMAT_TIME) {
512 GST_LOG ("position=%" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
513 } else {
514 GST_LOG ("position=%" G_GINT64_FORMAT ", format=%u", cur, format);
515 }
516 break;
517 }
518 case GST_QUERY_DURATION:
519 {
520 GstFormat bytes_format = GST_FORMAT_BYTES;
521 GstFormat time_format = GST_FORMAT_TIME;
522 GstFormat req_format;
523 gint64 total, total_bytes;
525 /* save requested format */
526 gst_query_parse_duration (query, &req_format, NULL);
528 if (peer == NULL)
529 goto error;
531 /* try any demuxer before us first */
532 if (req_format == GST_FORMAT_TIME && gst_pad_query (peer, query)) {
533 gst_query_parse_duration (query, NULL, &total);
534 GST_LOG_OBJECT (mad, "peer returned duration %" GST_TIME_FORMAT,
535 GST_TIME_ARGS (total));
536 break;
537 }
539 /* query peer for total length in bytes */
540 if (!gst_pad_query_peer_duration (mad->sinkpad, &bytes_format,
541 &total_bytes) || total_bytes <= 0) {
542 GST_LOG_OBJECT (mad, "duration query on peer pad failed");
543 goto error;
544 }
546 GST_LOG_OBJECT (mad, "peer pad returned total=%" G_GINT64_FORMAT
547 " bytes", total_bytes);
549 if (!gst_mad_convert_sink (pad, GST_FORMAT_BYTES, total_bytes,
550 &time_format, &total)) {
551 GST_DEBUG_OBJECT (mad, "conversion BYTE => TIME failed");
552 goto error;
553 }
554 if (!gst_mad_convert_src (pad, GST_FORMAT_TIME, total,
555 &req_format, &total)) {
556 GST_DEBUG_OBJECT (mad, "conversion TIME => %s failed",
557 gst_format_get_name (req_format));
558 goto error;
559 }
561 gst_query_set_duration (query, req_format, total);
563 if (req_format == GST_FORMAT_TIME) {
564 GST_LOG_OBJECT (mad, "duration=%" GST_TIME_FORMAT,
565 GST_TIME_ARGS (total));
566 } else {
567 GST_LOG_OBJECT (mad, "duration=%" G_GINT64_FORMAT " (%s)",
568 total, gst_format_get_name (req_format));
569 }
570 break;
571 }
572 case GST_QUERY_CONVERT:
573 {
574 GstFormat src_fmt, dest_fmt;
575 gint64 src_val, dest_val;
577 gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
578 if (!(res =
579 gst_mad_convert_src (pad, src_fmt, src_val, &dest_fmt,
580 &dest_val)))
581 goto error;
582 gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
583 break;
584 }
585 default:
586 res = gst_pad_query_default (pad, query);
587 break;
588 }
590 if (peer)
591 gst_object_unref (peer);
593 return res;
595 error:
597 GST_DEBUG ("error handling query");
599 if (peer)
600 gst_object_unref (peer);
602 return FALSE;
603 }
605 static gboolean
606 index_seek (GstMad * mad, GstPad * pad, GstEvent * event)
607 {
608 gdouble rate;
609 GstFormat format;
610 GstSeekFlags flags;
611 GstSeekType cur_type, stop_type;
612 gint64 cur, stop;
613 GstIndexEntry *entry = NULL;
615 /* since we know the exact byteoffset of the frame,
616 make sure to try bytes first */
618 const GstFormat try_all_formats[] = {
619 GST_FORMAT_BYTES,
620 GST_FORMAT_TIME,
621 0
622 };
623 const GstFormat *try_formats = try_all_formats;
624 const GstFormat *peer_formats;
626 gst_event_parse_seek (event, &rate, &format, &flags,
627 &cur_type, &cur, &stop_type, &stop);
629 if (rate < 0.0)
630 return FALSE;
632 if (format == GST_FORMAT_TIME) {
633 gst_segment_set_seek (&mad->segment, rate, format, flags, cur_type,
634 cur, stop_type, stop, NULL);
635 } else {
636 gst_segment_init (&mad->segment, GST_FORMAT_UNDEFINED);
637 }
639 entry = gst_index_get_assoc_entry (mad->index, mad->index_id,
640 GST_INDEX_LOOKUP_BEFORE, 0, format, cur);
642 GST_DEBUG ("index seek");
644 if (!entry)
645 return FALSE;
647 #if 0
648 peer_formats = gst_pad_get_formats (GST_PAD_PEER (mad->sinkpad));
649 #else
650 peer_formats = try_all_formats; /* FIXME */
651 #endif
653 while (gst_formats_contains (peer_formats, *try_formats)) {
654 gint64 value;
655 GstEvent *seek_event;
657 if (gst_index_entry_assoc_map (entry, *try_formats, &value)) {
658 /* lookup succeeded, create the seek */
660 GST_DEBUG ("index %s %" G_GINT64_FORMAT
661 " -> %s %" G_GINT64_FORMAT,
662 gst_format_get_details (format)->nick,
663 cur, gst_format_get_details (*try_formats)->nick, value);
665 seek_event = gst_event_new_seek (rate, *try_formats, flags,
666 cur_type, value, stop_type, stop);
668 if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), seek_event)) {
669 /* seek worked, we're done, loop will exit */
670 mad->restart = TRUE;
671 g_assert (format == GST_FORMAT_TIME);
672 mad->segment_start = cur;
673 return TRUE;
674 }
675 }
676 try_formats++;
677 }
679 return FALSE;
680 }
682 static gboolean
683 normal_seek (GstMad * mad, GstPad * pad, GstEvent * event)
684 {
685 gdouble rate;
686 GstFormat format, conv;
687 GstSeekFlags flags;
688 GstSeekType cur_type, stop_type;
689 gint64 cur, stop;
690 gint64 time_cur, time_stop;
691 gint64 bytes_cur, bytes_stop;
692 gboolean flush;
694 /* const GstFormat *peer_formats; */
695 gboolean res;
697 GST_DEBUG ("normal seek");
699 gst_event_parse_seek (event, &rate, &format, &flags,
700 &cur_type, &cur, &stop_type, &stop);
702 if (rate < 0.0)
703 return FALSE;
705 if (format != GST_FORMAT_TIME) {
706 conv = GST_FORMAT_TIME;
707 if (!gst_mad_convert_src (pad, format, cur, &conv, &time_cur))
708 goto convert_error;
709 if (!gst_mad_convert_src (pad, format, stop, &conv, &time_stop))
710 goto convert_error;
711 } else {
712 time_cur = cur;
713 time_stop = stop;
714 }
716 gst_segment_set_seek (&mad->segment, rate, GST_FORMAT_TIME, flags, cur_type,
717 time_cur, stop_type, time_stop, NULL);
719 GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
720 GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop));
722 /* shave off the flush flag, we'll need it later */
723 flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);
725 conv = GST_FORMAT_BYTES;
726 if (!gst_mad_convert_sink (pad, GST_FORMAT_TIME, time_cur, &conv, &bytes_cur))
727 goto convert_error;
728 if (!gst_mad_convert_sink (pad, GST_FORMAT_TIME, time_stop, &conv,
729 &bytes_stop))
730 goto convert_error;
732 {
733 GstEvent *seek_event;
735 /* conversion succeeded, create the seek */
736 seek_event =
737 gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
738 bytes_cur, stop_type, bytes_stop);
740 /* do the seek */
741 res = gst_pad_push_event (mad->sinkpad, seek_event);
743 if (res) {
744 /* we need to break out of the processing loop on flush */
745 mad->restart = flush;
746 mad->segment_start = time_cur;
747 mad->last_ts = time_cur;
748 }
749 }
750 #if 0
751 peer_formats = gst_pad_get_formats (GST_PAD_PEER (mad->sinkpad));
752 /* while we did not exhaust our seek formats without result */
753 while (peer_formats && *peer_formats && !res) {
754 gint64 desired_offset;
756 format = *peer_formats;
758 /* try to convert requested format to one we can seek with on the sinkpad */
759 if (gst_pad_convert (mad->sinkpad, GST_FORMAT_TIME, src_offset,
760 &format, &desired_offset)) {
761 GstEvent *seek_event;
763 /* conversion succeeded, create the seek */
764 seek_event =
765 gst_event_new_seek (format | GST_EVENT_SEEK_METHOD (event) | flush,
766 desired_offset);
767 /* do the seek */
768 if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), seek_event)) {
769 /* seek worked, we're done, loop will exit */
770 res = TRUE;
771 }
772 }
773 /* at this point, either the seek worked or res == FALSE */
774 if (res)
775 /* we need to break out of the processing loop on flush */
776 mad->restart = flush;
778 peer_formats++;
779 }
780 #endif
782 return res;
784 /* ERRORS */
785 convert_error:
786 {
787 /* probably unsupported seek format */
788 GST_DEBUG ("failed to convert format %u into GST_FORMAT_TIME", format);
789 return FALSE;
790 }
791 }
793 static gboolean
794 gst_mad_src_event (GstPad * pad, GstEvent * event)
795 {
796 gboolean res = TRUE;
797 GstMad *mad;
799 mad = GST_MAD (GST_PAD_PARENT (pad));
801 switch (GST_EVENT_TYPE (event)) {
802 case GST_EVENT_SEEK:
803 /* the all-formats seek logic, ref the event, we need it later */
804 gst_event_ref (event);
805 if (!(res = gst_pad_push_event (mad->sinkpad, event))) {
806 if (mad->index)
807 res = index_seek (mad, pad, event);
808 else
809 res = normal_seek (mad, pad, event);
810 }
811 gst_event_unref (event);
812 break;
813 default:
814 res = gst_pad_push_event (mad->sinkpad, event);
815 break;
816 }
818 return res;
819 }
821 static inline gint32
822 scale (mad_fixed_t sample)
823 {
824 #if MAD_F_FRACBITS < 28
825 /* round */
826 sample += (1L << (28 - MAD_F_FRACBITS - 1));
827 #endif
829 /* clip */
830 if (sample >= MAD_F_ONE)
831 sample = MAD_F_ONE - 1;
832 else if (sample < -MAD_F_ONE)
833 sample = -MAD_F_ONE;
835 #if MAD_F_FRACBITS < 28
836 /* quantize */
837 sample >>= (28 - MAD_F_FRACBITS);
838 #endif
840 /* convert from 29 bits to 32 bits */
841 return (gint32) (sample << 3);
842 }
844 /* do we need this function? */
845 static void
846 gst_mad_set_property (GObject * object, guint prop_id,
847 const GValue * value, GParamSpec * pspec)
848 {
849 GstMad *mad;
851 mad = GST_MAD (object);
853 switch (prop_id) {
854 case ARG_HALF:
855 mad->half = g_value_get_boolean (value);
856 break;
857 case ARG_IGNORE_CRC:
858 mad->ignore_crc = g_value_get_boolean (value);
859 break;
860 default:
861 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
862 break;
863 }
864 }
866 static void
867 gst_mad_get_property (GObject * object, guint prop_id,
868 GValue * value, GParamSpec * pspec)
869 {
870 GstMad *mad;
872 mad = GST_MAD (object);
874 switch (prop_id) {
875 case ARG_HALF:
876 g_value_set_boolean (value, mad->half);
877 break;
878 case ARG_IGNORE_CRC:
879 g_value_set_boolean (value, mad->ignore_crc);
880 break;
881 default:
882 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
883 break;
884 }
885 }
887 static void
888 gst_mad_update_info (GstMad * mad)
889 {
890 struct mad_header *header = &mad->frame.header;
891 gboolean changed = FALSE;
892 GstTagList *list = NULL;
894 #define CHECK_HEADER(h1,str) \
895 G_STMT_START{ \
896 if (mad->header.h1 != header->h1 || mad->new_header) { \
897 mad->header.h1 = header->h1; \
898 changed = TRUE; \
899 }; \
900 } G_STMT_END
902 /* update average bitrate */
903 if (mad->new_header) {
904 mad->framecount = 1;
905 mad->vbr_rate = header->bitrate;
906 } else {
907 mad->framecount++;
908 mad->vbr_rate += header->bitrate;
909 }
910 mad->vbr_average = (gint) (mad->vbr_rate / mad->framecount);
912 CHECK_HEADER (layer, "layer");
913 CHECK_HEADER (mode, "mode");
914 CHECK_HEADER (emphasis, "emphasis");
915 mad->new_header = FALSE;
917 if (changed) {
918 GEnumValue *mode;
919 GEnumValue *emphasis;
921 mode =
922 g_enum_get_value (g_type_class_peek (GST_TYPE_MAD_MODE),
923 mad->header.mode);
924 emphasis =
925 g_enum_get_value (g_type_class_peek (GST_TYPE_MAD_EMPHASIS),
926 mad->header.emphasis);
927 list = gst_tag_list_new ();
928 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
929 GST_TAG_LAYER, mad->header.layer,
930 GST_TAG_MODE, mode->value_nick,
931 GST_TAG_EMPHASIS, emphasis->value_nick, NULL);
932 if (!mad->framed) {
933 gchar *str;
935 str = g_strdup_printf ("MPEG-1 layer %d", mad->header.layer);
936 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
937 GST_TAG_AUDIO_CODEC, str, NULL);
938 g_free (str);
939 }
940 }
942 changed = FALSE;
943 CHECK_HEADER (bitrate, "bitrate");
944 if (!mad->xing_found && changed) {
945 if (!list)
946 list = gst_tag_list_new ();
947 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
948 GST_TAG_BITRATE, mad->header.bitrate, NULL);
949 }
950 mad->header.bitrate = header->bitrate;
951 #undef CHECK_HEADER
953 if (list) {
954 gst_element_post_message (GST_ELEMENT (mad),
955 gst_message_new_tag (GST_OBJECT (mad), gst_tag_list_copy (list)));
957 if (mad->need_newsegment)
958 mad->pending_events =
959 g_list_append (mad->pending_events, gst_event_new_tag (list));
960 else
961 gst_pad_push_event (mad->srcpad, gst_event_new_tag (list));
962 }
963 }
965 static gboolean
966 gst_mad_sink_event (GstPad * pad, GstEvent * event)
967 {
968 GstMad *mad = GST_MAD (GST_PAD_PARENT (pad));
969 gboolean result;
971 GST_DEBUG ("handling %s event", GST_EVENT_TYPE_NAME (event));
973 switch (GST_EVENT_TYPE (event)) {
974 case GST_EVENT_NEWSEGMENT:{
975 GstFormat format;
976 gboolean update;
977 gdouble rate, applied_rate;
978 gint64 start, stop, pos;
980 gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
981 &format, &start, &stop, &pos);
983 if (format == GST_FORMAT_TIME) {
984 /* FIXME: is this really correct? */
985 mad->tempsize = 0;
986 result = gst_pad_push_event (mad->srcpad, event);
987 /* we don't need to restart when we get here */
988 mad->restart = FALSE;
989 mad->framed = TRUE;
990 gst_segment_set_newsegment_full (&mad->segment, update, rate,
991 applied_rate, GST_FORMAT_TIME, start, stop, pos);
992 } else {
993 GST_DEBUG ("dropping newsegment event in format %s",
994 gst_format_get_name (format));
995 /* on restart the chain function will generate a new
996 * newsegment event, so we can just drop this one */
997 mad->restart = TRUE;
998 gst_event_unref (event);
999 mad->tempsize = 0;
1000 mad->framed = FALSE;
1001 result = TRUE;
1002 }
1003 break;
1004 }
1005 case GST_EVENT_EOS:
1006 if (mad->segment.rate < 0.0)
1007 gst_mad_chain_reverse (mad, NULL);
1008 mad->caps_set = FALSE; /* could be a new stream */
1009 result = gst_pad_push_event (mad->srcpad, event);
1010 break;
1011 case GST_EVENT_FLUSH_STOP:
1012 /* Clear any stored data, as it won't make sense once
1013 * the new data arrives */
1014 mad->tempsize = 0;
1015 mad_frame_mute (&mad->frame);
1016 mad_synth_mute (&mad->synth);
1017 gst_mad_clear_queues (mad);
1018 /* fall-through */
1019 case GST_EVENT_FLUSH_START:
1020 result = gst_pad_event_default (pad, event);
1021 break;
1022 default:
1023 if (mad->restart) {
1024 /* Cache all other events if we still have to send a NEWSEGMENT */
1025 mad->pending_events = g_list_append (mad->pending_events, event);
1026 result = TRUE;
1027 } else {
1028 result = gst_pad_event_default (pad, event);
1029 }
1030 break;
1031 }
1032 return result;
1033 }
1035 static gboolean
1036 gst_mad_check_restart (GstMad * mad)
1037 {
1038 gboolean yes = mad->restart;
1040 if (mad->restart) {
1041 mad->restart = FALSE;
1042 mad->tempsize = 0;
1043 }
1044 return yes;
1045 }
1048 /* The following code has been taken from
1049 * rhythmbox/metadata/monkey-media/stream-info-impl/id3-vfs/mp3bitrate.c
1050 * which took it from xine-lib/src/demuxers/demux_mpgaudio.c
1051 * This code has been kindly relicensed to LGPL by Thibaut Mattern and
1052 * Bastien Nocera
1053 */
1054 #define BE_32(x) GST_READ_UINT32_BE(x)
1056 #define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
1057 ( (long)(unsigned char)(ch3) | \
1058 ( (long)(unsigned char)(ch2) << 8 ) | \
1059 ( (long)(unsigned char)(ch1) << 16 ) | \
1060 ( (long)(unsigned char)(ch0) << 24 ) )
1062 /* Xing header stuff */
1063 #define XING_TAG FOURCC_TAG('X', 'i', 'n', 'g')
1064 #define XING_FRAMES_FLAG 0x0001
1065 #define XING_BYTES_FLAG 0x0002
1066 #define XING_TOC_FLAG 0x0004
1067 #define XING_VBR_SCALE_FLAG 0x0008
1068 #define XING_TOC_LENGTH 100
1070 /* check for valid "Xing" VBR header */
1071 static int
1072 is_xhead (unsigned char *buf)
1073 {
1074 return (BE_32 (buf) == XING_TAG);
1075 }
1078 #undef LOG
1079 /*#define LOG*/
1080 #ifdef LOG
1081 #ifndef WIN32
1082 #define lprintf(x...) g_print(x)
1083 #else
1084 #define lprintf GST_DEBUG
1085 #endif
1086 #else
1087 #ifndef WIN32
1088 #define lprintf(x...)
1089 #else
1090 #define lprintf GST_DEBUG
1091 #endif
1092 #endif
1094 static int
1095 mpg123_parse_xing_header (struct mad_header *header,
1096 const guint8 * buf, int bufsize, int *bitrate, int *time)
1097 {
1098 int i;
1099 guint8 *ptr = (guint8 *) buf;
1100 double frame_duration;
1101 int xflags, xframes, xbytes;
1102 int abr;
1103 guint8 xtoc[XING_TOC_LENGTH];
1104 int lsf_bit = !(header->flags & MAD_FLAG_LSF_EXT);
1106 xframes = xbytes = 0;
1108 /* offset of the Xing header */
1109 if (lsf_bit) {
1110 if (header->mode != MAD_MODE_SINGLE_CHANNEL)
1111 ptr += (32 + 4);
1112 else
1113 ptr += (17 + 4);
1114 } else {
1115 if (header->mode != MAD_MODE_SINGLE_CHANNEL)
1116 ptr += (17 + 4);
1117 else
1118 ptr += (9 + 4);
1119 }
1121 if (ptr >= (buf + bufsize - 4))
1122 return 0;
1124 if (is_xhead (ptr)) {
1125 lprintf ("Xing header found\n");
1127 ptr += 4;
1128 if (ptr >= (buf + bufsize - 4))
1129 return 0;
1131 xflags = BE_32 (ptr);
1132 ptr += 4;
1134 if (xflags & XING_FRAMES_FLAG) {
1135 if (ptr >= (buf + bufsize - 4))
1136 return 0;
1137 xframes = BE_32 (ptr);
1138 lprintf ("xframes: %d\n", xframes);
1139 ptr += 4;
1140 }
1141 if (xflags & XING_BYTES_FLAG) {
1142 if (ptr >= (buf + bufsize - 4))
1143 return 0;
1144 xbytes = BE_32 (ptr);
1145 lprintf ("xbytes: %d\n", xbytes);
1146 ptr += 4;
1147 }
1148 if (xflags & XING_TOC_FLAG) {
1149 guchar old = 0;
1151 lprintf ("toc found\n");
1152 if (ptr >= (buf + bufsize - XING_TOC_LENGTH))
1153 return 0;
1154 if (*ptr != 0) {
1155 lprintf ("skipping broken Xing TOC\n");
1156 goto skip_toc;
1157 }
1158 for (i = 0; i < XING_TOC_LENGTH; i++) {
1159 xtoc[i] = *(ptr + i);
1160 if (old > xtoc[i]) {
1161 lprintf ("skipping broken Xing TOC\n");
1162 goto skip_toc;
1163 }
1164 lprintf ("%d ", xtoc[i]);
1165 }
1166 lprintf ("\n");
1167 skip_toc:
1168 ptr += XING_TOC_LENGTH;
1169 }
1171 if (xflags & XING_VBR_SCALE_FLAG) {
1172 if (ptr >= (buf + bufsize - 4))
1173 return 0;
1174 lprintf ("xvbr_scale: %d\n", BE_32 (ptr));
1175 }
1177 /* 1 kbit = 1000 bits ! (and not 1024 bits) */
1178 if (xflags & (XING_FRAMES_FLAG | XING_BYTES_FLAG)) {
1179 if (header->layer == MAD_LAYER_I) {
1180 frame_duration = 384.0 / (double) header->samplerate;
1181 } else {
1182 int slots_per_frame;
1184 slots_per_frame = ((header->layer == MAD_LAYER_III)
1185 && !lsf_bit) ? 72 : 144;
1186 frame_duration = slots_per_frame * 8.0 / (double) header->samplerate;
1187 }
1188 abr = ((double) xbytes * 8.0) / ((double) xframes * frame_duration);
1189 lprintf ("abr: %d bps\n", abr);
1190 if (bitrate != NULL) {
1191 *bitrate = abr;
1192 }
1193 if (time != NULL) {
1194 *time = (double) xframes *frame_duration;
1196 lprintf ("stream_length: %d s, %d min %d s\n", *time,
1197 *time / 60, *time % 60);
1198 }
1199 } else {
1200 /* it's a stupid Xing header */
1201 lprintf ("not a Xing VBR file\n");
1202 }
1203 return 1;
1204 } else {
1205 lprintf ("Xing header not found\n");
1206 return 0;
1207 }
1208 }
1210 /* End of Xine code */
1212 /* internal function to check if the header has changed and thus the
1213 * caps need to be reset. Only call during normal mode, not resyncing */
1214 static void
1215 gst_mad_check_caps_reset (GstMad * mad)
1216 {
1217 guint nchannels;
1218 guint rate, old_rate = mad->rate;
1220 nchannels = MAD_NCHANNELS (&mad->frame.header);
1222 #if MAD_VERSION_MINOR <= 12
1223 rate = mad->header.sfreq;
1224 #else
1225 rate = mad->frame.header.samplerate;
1226 #endif
1228 /* rate and channels are not supposed to change in a continuous stream,
1229 * so check this first before doing anything */
1231 /* only set caps if they weren't already set for this continuous stream */
1232 if (mad->channels != nchannels || mad->rate != rate) {
1233 if (mad->caps_set) {
1234 GST_DEBUG
1235 ("Header changed from %d Hz/%d ch to %d Hz/%d ch, failed sync after seek ?",
1236 mad->rate, mad->channels, rate, nchannels);
1237 /* we're conservative on stream changes. However, our *initial* caps
1238 * might have been wrong as well - mad ain't perfect in syncing. So,
1239 * we count caps changes and change if we pass a limit treshold (3). */
1240 if (nchannels != mad->pending_channels || rate != mad->pending_rate) {
1241 mad->times_pending = 0;
1242 mad->pending_channels = nchannels;
1243 mad->pending_rate = rate;
1244 }
1245 if (++mad->times_pending < 3)
1246 return;
1247 }
1248 }
1249 gst_mad_update_info (mad);
1251 if (mad->channels != nchannels || mad->rate != rate) {
1252 GstCaps *caps;
1254 if (mad->stream.options & MAD_OPTION_HALFSAMPLERATE)
1255 rate >>= 1;
1257 /* FIXME see if peer can accept the caps */
1259 /* we set the caps even when the pad is not connected so they
1260 * can be gotten for streaminfo */
1261 caps = gst_caps_new_simple ("audio/x-raw-int",
1262 "endianness", G_TYPE_INT, G_BYTE_ORDER,
1263 "signed", G_TYPE_BOOLEAN, TRUE,
1264 "width", G_TYPE_INT, 32,
1265 "depth", G_TYPE_INT, 32,
1266 "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, nchannels, NULL);
1268 gst_pad_set_caps (mad->srcpad, caps);
1269 gst_caps_unref (caps);
1271 mad->caps_set = TRUE; /* set back to FALSE on discont */
1272 mad->channels = nchannels;
1273 mad->rate = rate;
1275 /* update sample count so we don't come up with crazy timestamps */
1276 if (mad->total_samples && old_rate) {
1277 mad->total_samples = mad->total_samples * rate / old_rate;
1278 }
1279 }
1280 }
1282 static void
1283 gst_mad_clear_queues (GstMad * mad)
1284 {
1285 g_list_foreach (mad->queued, (GFunc) gst_mini_object_unref, NULL);
1286 g_list_free (mad->queued);
1287 mad->queued = NULL;
1288 g_list_foreach (mad->gather, (GFunc) gst_mini_object_unref, NULL);
1289 g_list_free (mad->gather);
1290 mad->gather = NULL;
1291 g_list_foreach (mad->decode, (GFunc) gst_mini_object_unref, NULL);
1292 g_list_free (mad->decode);
1293 mad->decode = NULL;
1294 }
1296 static GstFlowReturn
1297 gst_mad_flush_decode (GstMad * mad)
1298 {
1299 GstFlowReturn res = GST_FLOW_OK;
1300 GList *walk;
1302 walk = mad->decode;
1304 GST_DEBUG_OBJECT (mad, "flushing buffers to decoder");
1306 /* clear buffer and decoder state */
1307 mad->tempsize = 0;
1308 mad_frame_mute (&mad->frame);
1309 mad_synth_mute (&mad->synth);
1311 mad->process = TRUE;
1312 while (walk) {
1313 GList *next;
1314 GstBuffer *buf = GST_BUFFER_CAST (walk->data);
1316 GST_DEBUG_OBJECT (mad, "decoding buffer %p, ts %" GST_TIME_FORMAT,
1317 buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1319 next = g_list_next (walk);
1320 /* decode buffer, resulting data prepended to output queue */
1321 gst_buffer_ref (buf);
1322 res = gst_mad_chain (mad->sinkpad, buf);
1324 /* if we generated output, we can discard the buffer, else we
1325 * keep it in the queue */
1326 if (mad->queued) {
1327 GST_DEBUG_OBJECT (mad, "decoded buffer to %p", mad->queued->data);
1328 mad->decode = g_list_delete_link (mad->decode, walk);
1329 gst_buffer_unref (buf);
1330 } else {
1331 GST_DEBUG_OBJECT (mad, "buffer did not decode, keeping");
1332 }
1333 walk = next;
1334 }
1335 mad->process = FALSE;
1337 /* now send queued data downstream */
1338 while (mad->queued) {
1339 GstBuffer *buf = GST_BUFFER_CAST (mad->queued->data);
1341 GST_DEBUG_OBJECT (mad, "pushing buffer %p of size %u, "
1342 "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
1343 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1344 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1345 res = gst_pad_push (mad->srcpad, buf);
1347 mad->queued = g_list_delete_link (mad->queued, mad->queued);
1348 }
1350 return res;
1351 }
1353 static GstFlowReturn
1354 gst_mad_chain_reverse (GstMad * mad, GstBuffer * buf)
1355 {
1356 GstFlowReturn result = GST_FLOW_OK;
1358 /* if we have a discont, move buffers to the decode list */
1359 if (!buf || GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) {
1360 GST_DEBUG_OBJECT (mad, "received discont");
1361 while (mad->gather) {
1362 GstBuffer *gbuf;
1364 gbuf = GST_BUFFER_CAST (mad->gather->data);
1365 /* remove from the gather list */
1366 mad->gather = g_list_delete_link (mad->gather, mad->gather);
1367 /* copy to decode queue */
1368 mad->decode = g_list_prepend (mad->decode, gbuf);
1369 }
1370 /* decode stuff in the decode queue */
1371 gst_mad_flush_decode (mad);
1372 }
1374 if (G_LIKELY (buf)) {
1375 GST_DEBUG_OBJECT (mad, "gathering buffer %p of size %u, "
1376 "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
1377 GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1378 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1380 /* add buffer to gather queue */
1381 mad->gather = g_list_prepend (mad->gather, buf);
1382 }
1384 return result;
1385 }
1387 static GstFlowReturn
1388 gst_mad_chain (GstPad * pad, GstBuffer * buffer)
1389 {
1390 GstMad *mad;
1391 guint8 *data;
1392 glong size, tempsize;
1393 gboolean new_pts = FALSE;
1394 gboolean discont;
1395 GstClockTime timestamp;
1396 GstFlowReturn result = GST_FLOW_OK;
1398 mad = GST_MAD (GST_PAD_PARENT (pad));
1400 /* restarts happen on discontinuities, ie. seek, flush, PAUSED to PLAYING */
1401 if (gst_mad_check_restart (mad)) {
1402 mad->need_newsegment = TRUE;
1403 GST_DEBUG ("mad restarted");
1404 }
1406 if (mad->segment.rate < 0.0) {
1407 if (!mad->process)
1408 return gst_mad_chain_reverse (mad, buffer);
1409 /* no output discont */
1410 discont = FALSE;
1411 } else {
1412 /* take discont flag */
1413 discont = GST_BUFFER_IS_DISCONT (buffer);
1414 }
1416 timestamp = GST_BUFFER_TIMESTAMP (buffer);
1417 GST_DEBUG ("mad in timestamp %" GST_TIME_FORMAT " duration:%" GST_TIME_FORMAT,
1418 GST_TIME_ARGS (timestamp), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1420 /* handle timestamps */
1421 if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1422 /* if there is nothing left to process in our temporary buffer,
1423 * we can set this timestamp on the next outgoing buffer */
1424 if (mad->tempsize == 0) {
1425 /* we have to save the result here because we can't yet convert
1426 * the timestamp to a sample offset, as the samplerate might not
1427 * be known yet */
1428 mad->last_ts = timestamp;
1429 mad->base_byte_offset = GST_BUFFER_OFFSET (buffer);
1430 mad->bytes_consumed = 0;
1431 }
1432 /* else we need to finish the current partial frame with the old timestamp
1433 * and queue this timestamp for the next frame */
1434 else {
1435 new_pts = TRUE;
1436 }
1437 }
1438 GST_DEBUG ("last_ts %" GST_TIME_FORMAT, GST_TIME_ARGS (mad->last_ts));
1440 /* handle data */
1441 data = GST_BUFFER_DATA (buffer);
1442 size = GST_BUFFER_SIZE (buffer);
1444 tempsize = mad->tempsize;
1446 /* process the incoming buffer in chunks of maximum MAD_BUFFER_MDLEN bytes;
1447 * this is the upper limit on processable chunk sizes set by mad */
1448 while (size > 0) {
1449 gint tocopy;
1450 guchar *mad_input_buffer; /* convenience pointer to tempbuffer */
1452 if (mad->tempsize == 0 && discont) {
1453 mad->discont = TRUE;
1454 discont = FALSE;
1455 }
1456 tocopy =
1457 MIN (MAD_BUFFER_MDLEN, MIN (size,
1458 MAD_BUFFER_MDLEN * 3 - mad->tempsize));
1459 if (tocopy == 0) {
1460 GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL),
1461 ("mad claims to need more data than %u bytes, we don't have that much",
1462 MAD_BUFFER_MDLEN * 3));
1463 result = GST_FLOW_ERROR;
1464 goto end;
1465 }
1467 /* append the chunk to process to our internal temporary buffer */
1468 GST_LOG ("tempbuffer size %ld, copying %d bytes from incoming buffer",
1469 mad->tempsize, tocopy);
1470 memcpy (mad->tempbuffer + mad->tempsize, data, tocopy);
1471 mad->tempsize += tocopy;
1473 /* update our incoming buffer's parameters to reflect this */
1474 size -= tocopy;
1475 data += tocopy;
1477 mad_input_buffer = mad->tempbuffer;
1479 /* while we have data we can consume it */
1480 while (mad->tempsize > 0) {
1481 gint consumed = 0;
1482 guint nsamples;
1483 guint64 time_offset = GST_CLOCK_TIME_NONE;
1484 guint64 time_duration = GST_CLOCK_TIME_NONE;
1485 unsigned char const *before_sync, *after_sync;
1486 gboolean goto_exit = FALSE;
1488 mad->in_error = FALSE;
1490 mad_stream_buffer (&mad->stream, mad_input_buffer, mad->tempsize);
1492 /* added separate header decoding to catch errors earlier, also fixes
1493 * some weird decoding errors... */
1494 GST_LOG ("decoding the header now");
1495 if (mad_header_decode (&mad->frame.header, &mad->stream) == -1) {
1496 if (mad->stream.error == MAD_ERROR_BUFLEN) {
1497 GST_LOG ("not enough data in tempbuffer (%ld), breaking to get more",
1498 mad->tempsize);
1499 break;
1500 } else {
1501 GST_WARNING ("mad_header_decode had an error: %s",
1502 mad_stream_errorstr (&mad->stream));
1503 }
1504 }
1506 GST_LOG ("decoding one frame now");
1508 if (mad_frame_decode (&mad->frame, &mad->stream) == -1) {
1509 GST_LOG ("got error %d", mad->stream.error);
1511 /* not enough data, need to wait for next buffer? */
1512 if (mad->stream.error == MAD_ERROR_BUFLEN) {
1513 if (mad->stream.next_frame == mad_input_buffer) {
1514 GST_LOG
1515 ("not enough data in tempbuffer (%ld), breaking to get more",
1516 mad->tempsize);
1517 break;
1518 } else {
1519 GST_LOG ("sync error, flushing unneeded data");
1520 goto next_no_samples;
1521 }
1522 } else if (mad->stream.error == MAD_ERROR_BADDATAPTR) {
1523 /* Flush data */
1524 goto next_no_samples;
1525 }
1526 /* we are in an error state */
1527 mad->in_error = TRUE;
1528 GST_WARNING ("mad_frame_decode had an error: %s",
1529 mad_stream_errorstr (&mad->stream));
1530 if (!MAD_RECOVERABLE (mad->stream.error)) {
1531 GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL), (NULL));
1532 result = GST_FLOW_ERROR;
1533 goto end;
1534 } else if (mad->stream.error == MAD_ERROR_LOSTSYNC) {
1535 /* lost sync, force a resync */
1536 GST_INFO ("recoverable lost sync error");
1538 #ifdef HAVE_ID3TAG
1539 {
1540 signed long tagsize;
1542 tagsize = id3_tag_query (mad->stream.this_frame,
1543 mad->stream.bufend - mad->stream.this_frame);
1545 if (tagsize > mad->tempsize) {
1546 GST_INFO ("mad: got partial id3 tag in buffer, skipping");
1547 } else if (tagsize > 0) {
1548 struct id3_tag *tag;
1549 id3_byte_t const *data;
1551 GST_INFO ("mad: got ID3 tag size %ld", tagsize);
1553 data = mad->stream.this_frame;
1555 /* mad has moved the pointer to the next frame over the start of the
1556 * id3 tags, so we need to flush one byte less than the tagsize */
1557 mad_stream_skip (&mad->stream, tagsize - 1);
1559 tag = id3_tag_parse (data, tagsize);
1560 if (tag) {
1561 GstTagList *list;
1563 list = gst_mad_id3_to_tag_list (tag);
1564 id3_tag_delete (tag);
1565 GST_DEBUG ("found tag");
1566 gst_element_post_message (GST_ELEMENT (mad),
1567 gst_message_new_tag (GST_OBJECT (mad),
1568 gst_tag_list_copy (list)));
1569 if (mad->tags) {
1570 gst_tag_list_insert (mad->tags, list, GST_TAG_MERGE_PREPEND);
1571 } else {
1572 mad->tags = gst_tag_list_copy (list);
1573 }
1574 if (mad->need_newsegment)
1575 mad->pending_events =
1576 g_list_append (mad->pending_events,
1577 gst_event_new_tag (list));
1578 else
1579 gst_pad_push_event (mad->srcpad, gst_event_new_tag (list));
1580 }
1581 }
1582 }
1583 #endif /* HAVE_ID3TAG */
1584 }
1586 mad_frame_mute (&mad->frame);
1587 mad_synth_mute (&mad->synth);
1588 before_sync = mad->stream.ptr.byte;
1589 if (mad_stream_sync (&mad->stream) != 0)
1590 GST_WARNING ("mad_stream_sync failed");
1591 after_sync = mad->stream.ptr.byte;
1592 /* a succesful resync should make us drop bytes as consumed, so
1593 calculate from the byte pointers before and after resync */
1594 consumed = after_sync - before_sync;
1595 GST_DEBUG ("resynchronization consumes %d bytes", consumed);
1596 GST_DEBUG ("synced to data: 0x%0x 0x%0x", *mad->stream.ptr.byte,
1597 *(mad->stream.ptr.byte + 1));
1599 mad_stream_sync (&mad->stream);
1600 /* recoverable errors pass */
1601 goto next_no_samples;
1602 }
1604 if (mad->check_for_xing) {
1605 int bitrate = 0, time = 0;
1606 GstTagList *list;
1607 int frame_len = mad->stream.next_frame - mad->stream.this_frame;
1609 mad->check_for_xing = FALSE;
1611 /* Assume Xing headers can only be the first frame in a mp3 file */
1612 if (mpg123_parse_xing_header (&mad->frame.header,
1613 mad->stream.this_frame, frame_len, &bitrate, &time)) {
1614 mad->xing_found = TRUE;
1615 list = gst_tag_list_new ();
1616 gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
1617 GST_TAG_DURATION, (gint64) time * 1000 * 1000 * 1000,
1618 GST_TAG_BITRATE, bitrate, NULL);
1619 gst_element_post_message (GST_ELEMENT (mad),
1620 gst_message_new_tag (GST_OBJECT (mad), gst_tag_list_copy (list)));
1622 if (mad->need_newsegment)
1623 mad->pending_events =
1624 g_list_append (mad->pending_events, gst_event_new_tag (list));
1625 else
1626 gst_pad_push_event (mad->srcpad, gst_event_new_tag (list));
1628 goto next_no_samples;
1629 }
1630 }
1632 /* if we're not resyncing/in error, check if caps need to be set again */
1633 if (!mad->in_error)
1634 gst_mad_check_caps_reset (mad);
1635 nsamples = MAD_NSBSAMPLES (&mad->frame.header) *
1636 (mad->stream.options & MAD_OPTION_HALFSAMPLERATE ? 16 : 32);
1638 if (mad->rate == 0) {
1639 g_warning ("mad->rate is 0; timestamps cannot be calculated");
1640 } else {
1641 /* if we have a pending timestamp, we can use it now to calculate the sample offset */
1642 if (GST_CLOCK_TIME_IS_VALID (mad->last_ts)) {
1643 GstFormat format = GST_FORMAT_DEFAULT;
1644 gint64 total;
1646 /* Convert incoming timestamp to a number of encoded samples */
1647 gst_pad_query_convert (mad->srcpad, GST_FORMAT_TIME, mad->last_ts,
1648 &format, &total);
1650 GST_DEBUG_OBJECT (mad, "calculated samples offset from ts is %"
1651 G_GUINT64_FORMAT " accumulated samples offset is %"
1652 G_GUINT64_FORMAT, total, mad->total_samples);
1654 /* We are using the incoming timestamps to generate the outgoing ones
1655 * if available. However some muxing formats are not precise enough
1656 * to allow us to generate a perfect stream. When converting the
1657 * timestamp to a number of encoded samples so far we are introducing
1658 * a lot of potential error compared to our accumulated number of
1659 * samples encoded. If the difference between those 2 numbers is
1660 * bigger than half a frame we then use the incoming timestamp
1661 * as a reference, otherwise we continue using our accumulated samples
1662 * counter */
1663 if (ABS (((gint64) (mad->total_samples)) - total) > nsamples / 2) {
1664 GST_DEBUG_OBJECT (mad, "difference is bigger than half a frame, "
1665 "using calculated samples offset %" G_GUINT64_FORMAT, total);
1666 /* Override our accumulated samples counter */
1667 mad->total_samples = total;
1668 /* We use that timestamp directly */
1669 time_offset = mad->last_ts;
1670 }
1672 mad->last_ts = GST_CLOCK_TIME_NONE;
1673 }
1675 if (!GST_CLOCK_TIME_IS_VALID (time_offset)) {
1676 time_offset = gst_util_uint64_scale_int (mad->total_samples,
1677 GST_SECOND, mad->rate);
1678 }
1679 /* Duration is next timestamp - this one to generate a continuous
1680 * stream */
1681 time_duration =
1682 gst_util_uint64_scale_int (mad->total_samples + nsamples,
1683 GST_SECOND, mad->rate) - time_offset;
1684 }
1686 if (mad->index) {
1687 guint64 x_bytes = mad->base_byte_offset + mad->bytes_consumed;
1689 gst_index_add_association (mad->index, mad->index_id,
1690 GST_ASSOCIATION_FLAG_DELTA_UNIT,
1691 GST_FORMAT_BYTES, x_bytes, GST_FORMAT_TIME, time_offset, NULL);
1692 }
1694 if (mad->segment_start <= (time_offset ==
1695 GST_CLOCK_TIME_NONE ? 0 : time_offset)) {
1697 /* for sample accurate seeking, calculate how many samples
1698 to skip and send the remaining pcm samples */
1700 GstBuffer *outbuffer = NULL;
1701 gint32 *outdata;
1702 mad_fixed_t const *left_ch, *right_ch;
1704 if (mad->need_newsegment) {
1705 gint64 start = time_offset;
1707 GST_DEBUG ("Sending NEWSEGMENT event, start=%" GST_TIME_FORMAT,
1708 GST_TIME_ARGS (start));
1710 gst_segment_set_newsegment (&mad->segment, FALSE, 1.0,
1711 GST_FORMAT_TIME, start, GST_CLOCK_TIME_NONE, start);
1713 gst_pad_push_event (mad->srcpad,
1714 gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
1715 start, GST_CLOCK_TIME_NONE, start));
1716 mad->need_newsegment = FALSE;
1717 }
1719 if (mad->pending_events) {
1720 GList *l;
1722 for (l = mad->pending_events; l != NULL; l = l->next) {
1723 gst_pad_push_event (mad->srcpad, GST_EVENT (l->data));
1724 }
1725 g_list_free (mad->pending_events);
1726 mad->pending_events = NULL;
1727 }
1729 /* will attach the caps to the buffer */
1730 result =
1731 gst_pad_alloc_buffer_and_set_caps (mad->srcpad, 0,
1732 nsamples * mad->channels * 4, GST_PAD_CAPS (mad->srcpad),
1733 &outbuffer);
1734 if (result != GST_FLOW_OK) {
1735 /* Head for the exit, dropping samples as we go */
1736 GST_LOG ("Skipping frame synthesis due to pad_alloc return value");
1737 goto_exit = TRUE;
1738 goto skip_frame;
1739 }
1741 if (GST_BUFFER_SIZE (outbuffer) != nsamples * mad->channels * 4) {
1742 gst_buffer_unref (outbuffer);
1744 outbuffer = gst_buffer_new_and_alloc (nsamples * mad->channels * 4);
1745 gst_buffer_set_caps (outbuffer, GST_PAD_CAPS (mad->srcpad));
1746 }
1748 mad_synth_frame (&mad->synth, &mad->frame);
1749 left_ch = mad->synth.pcm.samples[0];
1750 right_ch = mad->synth.pcm.samples[1];
1752 outdata = (gint32 *) GST_BUFFER_DATA (outbuffer);
1754 GST_DEBUG ("mad out timestamp %" GST_TIME_FORMAT " dur: %"
1755 GST_TIME_FORMAT, GST_TIME_ARGS (time_offset),
1756 GST_TIME_ARGS (time_duration));
1758 GST_BUFFER_TIMESTAMP (outbuffer) = time_offset;
1759 GST_BUFFER_DURATION (outbuffer) = time_duration;
1760 GST_BUFFER_OFFSET (outbuffer) = mad->total_samples;
1761 GST_BUFFER_OFFSET_END (outbuffer) = mad->total_samples + nsamples;
1763 /* output sample(s) in 16-bit signed native-endian PCM */
1764 if (mad->channels == 1) {
1765 gint count = nsamples;
1767 while (count--) {
1768 *outdata++ = scale (*left_ch++) & 0xffffffff;
1769 }
1770 } else {
1771 gint count = nsamples;
1773 while (count--) {
1774 *outdata++ = scale (*left_ch++) & 0xffffffff;
1775 *outdata++ = scale (*right_ch++) & 0xffffffff;
1776 }
1777 }
1779 if ((outbuffer = gst_audio_buffer_clip (outbuffer, &mad->segment,
1780 mad->rate, 4 * mad->channels))) {
1781 GST_LOG_OBJECT (mad,
1782 "pushing buffer, off=%" G_GUINT64_FORMAT ", ts=%" GST_TIME_FORMAT,
1783 GST_BUFFER_OFFSET (outbuffer),
1784 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuffer)));
1786 /* apply discont */
1787 if (mad->discont) {
1788 GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_DISCONT);
1789 mad->discont = FALSE;
1790 }
1792 mad->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuffer);
1793 if (mad->segment.rate > 0.0) {
1794 result = gst_pad_push (mad->srcpad, outbuffer);
1795 } else {
1796 GST_LOG_OBJECT (mad, "queued buffer");
1797 mad->queued = g_list_prepend (mad->queued, outbuffer);
1798 result = GST_FLOW_OK;
1799 }
1800 if (result != GST_FLOW_OK) {
1801 /* Head for the exit, dropping samples as we go */
1802 goto_exit = TRUE;
1803 }
1804 } else {
1805 GST_LOG_OBJECT (mad, "Dropping buffer");
1806 }
1807 }
1809 skip_frame:
1810 mad->total_samples += nsamples;
1812 /* we have a queued timestamp on the incoming buffer that we should
1813 * use for the next frame */
1814 if (new_pts && (mad->stream.next_frame - mad_input_buffer >= tempsize)) {
1815 new_pts = FALSE;
1816 mad->last_ts = timestamp;
1817 mad->base_byte_offset = GST_BUFFER_OFFSET (buffer);
1818 mad->bytes_consumed = 0;
1819 }
1820 tempsize = 0;
1821 if (discont) {
1822 mad->discont = TRUE;
1823 discont = FALSE;
1824 }
1826 if (gst_mad_check_restart (mad)) {
1827 goto end;
1828 }
1830 next_no_samples:
1831 /* figure out how many bytes mad consumed */
1832 /* if consumed is already set, it's from the resync higher up, so
1833 we need to use that value instead. Otherwise, recalculate from
1834 mad's consumption */
1835 if (consumed == 0)
1836 consumed = mad->stream.next_frame - mad_input_buffer;
1838 GST_LOG ("mad consumed %d bytes", consumed);
1839 /* move out pointer to where mad want the next data */
1840 mad_input_buffer += consumed;
1841 mad->tempsize -= consumed;
1842 mad->bytes_consumed += consumed;
1843 if (goto_exit == TRUE)
1844 goto end;
1845 }
1846 /* we only get here from breaks, tempsize never actually drops below 0 */
1847 memmove (mad->tempbuffer, mad_input_buffer, mad->tempsize);
1848 }
1849 result = GST_FLOW_OK;
1851 end:
1852 gst_buffer_unref (buffer);
1854 return result;
1855 }
1857 static GstStateChangeReturn
1858 gst_mad_change_state (GstElement * element, GstStateChange transition)
1859 {
1860 GstMad *mad;
1861 GstStateChangeReturn ret;
1863 mad = GST_MAD (element);
1865 switch (transition) {
1866 case GST_STATE_CHANGE_NULL_TO_READY:
1867 break;
1868 case GST_STATE_CHANGE_READY_TO_PAUSED:
1869 {
1870 guint options = 0;
1872 mad_stream_init (&mad->stream);
1873 mad_frame_init (&mad->frame);
1874 mad_synth_init (&mad->synth);
1875 mad->tempsize = 0;
1876 mad->discont = TRUE;
1877 mad->total_samples = 0;
1878 mad->rate = 0;
1879 mad->channels = 0;
1880 mad->caps_set = FALSE;
1881 mad->times_pending = mad->pending_rate = mad->pending_channels = 0;
1882 mad->vbr_average = 0;
1883 gst_segment_init (&mad->segment, GST_FORMAT_TIME);
1884 mad->new_header = TRUE;
1885 mad->framed = FALSE;
1886 mad->framecount = 0;
1887 mad->vbr_rate = 0;
1888 mad->frame.header.samplerate = 0;
1889 mad->last_ts = GST_CLOCK_TIME_NONE;
1890 if (mad->ignore_crc)
1891 options |= MAD_OPTION_IGNORECRC;
1892 if (mad->half)
1893 options |= MAD_OPTION_HALFSAMPLERATE;
1894 mad_stream_options (&mad->stream, options);
1895 break;
1896 }
1897 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1898 break;
1899 default:
1900 break;
1901 }
1903 ret = parent_class->change_state (element, transition);
1905 switch (transition) {
1906 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1907 break;
1908 case GST_STATE_CHANGE_PAUSED_TO_READY:
1909 mad_synth_finish (&mad->synth);
1910 mad_frame_finish (&mad->frame);
1911 mad_stream_finish (&mad->stream);
1912 mad->restart = TRUE;
1913 mad->check_for_xing = TRUE;
1914 if (mad->tags) {
1915 gst_tag_list_free (mad->tags);
1916 mad->tags = NULL;
1917 }
1918 gst_mad_clear_queues (mad);
1919 break;
1920 case GST_STATE_CHANGE_READY_TO_NULL:
1921 break;
1922 default:
1923 break;
1924 }
1925 return ret;
1926 }
1928 #ifdef HAVE_ID3TAG
1929 /* id3 tag helper (FIXME: why does mad parse id3 tags at all? It shouldn't) */
1930 static GstTagList *
1931 gst_mad_id3_to_tag_list (const struct id3_tag *tag)
1932 {
1933 const struct id3_frame *frame;
1934 const id3_ucs4_t *ucs4;
1935 id3_utf8_t *utf8;
1936 GstTagList *tag_list;
1937 GType tag_type;
1938 guint i = 0;
1940 tag_list = gst_tag_list_new ();
1942 while ((frame = id3_tag_findframe (tag, NULL, i++)) != NULL) {
1943 const union id3_field *field;
1944 unsigned int nstrings, j;
1945 const gchar *tag_name;
1947 /* find me the function to query the frame id */
1948 gchar *id = g_strndup (frame->id, 5);
1950 tag_name = gst_tag_from_id3_tag (id);
1951 if (tag_name == NULL) {
1952 g_free (id);
1953 continue;
1954 }
1956 if (strcmp (id, "COMM") == 0) {
1957 if (frame->nfields < 4)
1958 continue;
1960 ucs4 = id3_field_getfullstring (&frame->fields[3]);
1961 g_assert (ucs4);
1963 utf8 = id3_ucs4_utf8duplicate (ucs4);
1964 if (utf8 == 0)
1965 continue;
1967 if (!g_utf8_validate ((char *) utf8, -1, NULL)) {
1968 GST_ERROR ("converted string is not valid utf-8");
1969 g_free (utf8);
1970 continue;
1971 }
1973 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1974 GST_TAG_COMMENT, utf8, NULL);
1976 g_free (utf8);
1977 continue;
1978 }
1980 if (frame->nfields < 2)
1981 continue;
1983 field = &frame->fields[1];
1984 nstrings = id3_field_getnstrings (field);
1986 for (j = 0; j < nstrings; ++j) {
1987 ucs4 = id3_field_getstrings (field, j);
1988 g_assert (ucs4);
1990 if (strcmp (id, ID3_FRAME_GENRE) == 0)
1991 ucs4 = id3_genre_name (ucs4);
1993 utf8 = id3_ucs4_utf8duplicate (ucs4);
1994 if (utf8 == 0)
1995 continue;
1997 if (!g_utf8_validate ((char *) utf8, -1, NULL)) {
1998 GST_ERROR ("converted string is not valid utf-8");
1999 free (utf8);
2000 continue;
2001 }
2003 tag_type = gst_tag_get_type (tag_name);
2005 /* be sure to add non-string tags here */
2006 switch (tag_type) {
2007 case G_TYPE_UINT:
2008 {
2009 guint tmp;
2010 gchar *check;
2012 tmp = strtoul ((char *) utf8, &check, 10);
2014 if (strcmp (tag_name, GST_TAG_DATE) == 0) {
2015 GDate *d;
2017 if (*check != '\0')
2018 break;
2019 if (tmp == 0)
2020 break;
2021 d = g_date_new_dmy (1, 1, tmp);
2022 tmp = g_date_get_julian (d);
2023 g_date_free (d);
2024 } else if (strcmp (tag_name, GST_TAG_TRACK_NUMBER) == 0) {
2025 if (*check == '/') {
2026 guint total;
2028 check++;
2029 total = strtoul (check, &check, 10);
2030 if (*check != '\0')
2031 break;
2033 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
2034 GST_TAG_TRACK_COUNT, total, NULL);
2035 }
2036 } else if (strcmp (tag_name, GST_TAG_ALBUM_VOLUME_NUMBER) == 0) {
2037 if (*check == '/') {
2038 guint total;
2040 check++;
2041 total = strtoul (check, &check, 10);
2042 if (*check != '\0')
2043 break;
2045 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
2046 GST_TAG_ALBUM_VOLUME_COUNT, total, NULL);
2047 }
2048 }
2050 if (*check != '\0')
2051 break;
2052 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, tmp,
2053 NULL);
2054 break;
2055 }
2056 case G_TYPE_UINT64:
2057 {
2058 guint64 tmp;
2060 g_assert (strcmp (tag_name, GST_TAG_DURATION) == 0);
2061 tmp = strtoul ((char *) utf8, NULL, 10);
2062 if (tmp == 0) {
2063 break;
2064 }
2065 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
2066 GST_TAG_DURATION, tmp * 1000 * 1000, NULL);
2067 break;
2068 }
2069 case G_TYPE_STRING:{
2070 gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
2071 tag_name, (const gchar *) utf8, NULL);
2072 break;
2073 }
2074 /* handles GST_TYPE_DATE and anything else */
2075 default:{
2076 GValue src = { 0, };
2077 GValue dest = { 0, };
2079 g_value_init (&src, G_TYPE_STRING);
2080 g_value_set_string (&src, (const gchar *) utf8);
2082 g_value_init (&dest, tag_type);
2083 if (g_value_transform (&src, &dest)) {
2084 gst_tag_list_add_values (tag_list, GST_TAG_MERGE_APPEND,
2085 tag_name, &dest, NULL);
2086 } else {
2087 GST_WARNING ("Failed to transform tag from string to type '%s'",
2088 g_type_name (tag_type));
2089 }
2090 g_value_unset (&src);
2091 g_value_unset (&dest);
2092 break;
2093 }
2094 }
2095 free (utf8);
2096 }
2097 g_free (id);
2098 }
2100 return tag_list;
2101 }
2102 #endif /* HAVE_ID3TAG */
2104 /* plugin initialisation */
2106 static gboolean
2107 plugin_init (GstPlugin * plugin)
2108 {
2109 GST_DEBUG_CATEGORY_INIT (mad_debug, "mad", 0, "mad mp3 decoding");
2111 return gst_element_register (plugin, "mad", GST_RANK_SECONDARY,
2112 gst_mad_get_type ());
2113 }
2115 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
2116 GST_VERSION_MINOR,
2117 "mad",
2118 "mp3 decoding based on the mad library",
2119 plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);