]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/mad/gstmad.c
gst_element_class_set_details => gst_element_class_set_details_simple
[glsdk/gst-plugins-ugly0-10.git] / ext / mad / gstmad.c
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 enum
44 {
45   ARG_0,
46   ARG_HALF,
47   ARG_IGNORE_CRC
48 };
50 GST_DEBUG_CATEGORY_STATIC (mad_debug);
51 #define GST_CAT_DEFAULT mad_debug
53 static GstStaticPadTemplate mad_src_template_factory =
54 GST_STATIC_PAD_TEMPLATE ("src",
55     GST_PAD_SRC,
56     GST_PAD_ALWAYS,
57     GST_STATIC_CAPS ("audio/x-raw-int, "
58         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
59         "signed = (boolean) true, "
60         "width = (int) 32, "
61         "depth = (int) 32, "
62         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
63         "channels = (int) [ 1, 2 ]")
64     );
66 /* FIXME: make three caps, for mpegversion 1, 2 and 2.5 */
67 static GstStaticPadTemplate mad_sink_template_factory =
68 GST_STATIC_PAD_TEMPLATE ("sink",
69     GST_PAD_SINK,
70     GST_PAD_ALWAYS,
71     GST_STATIC_CAPS ("audio/mpeg, "
72         "mpegversion = (int) 1, "
73         "layer = (int) [ 1, 3 ], "
74         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
75         "channels = (int) [ 1, 2 ]")
76     );
78 static void gst_mad_base_init (gpointer g_class);
79 static void gst_mad_class_init (GstMadClass * klass);
80 static void gst_mad_init (GstMad * mad, GstMadClass * klass);
81 static void gst_mad_dispose (GObject * object);
83 static void gst_mad_set_property (GObject * object, guint prop_id,
84     const GValue * value, GParamSpec * pspec);
85 static void gst_mad_get_property (GObject * object, guint prop_id,
86     GValue * value, GParamSpec * pspec);
88 static gboolean gst_mad_src_event (GstPad * pad, GstEvent * event);
90 static const GstQueryType *gst_mad_get_query_types (GstPad * pad);
92 static gboolean gst_mad_src_query (GstPad * pad, GstQuery * query);
93 static gboolean gst_mad_convert_sink (GstPad * pad, GstFormat src_format,
94     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
95 static gboolean gst_mad_convert_src (GstPad * pad, GstFormat src_format,
96     gint64 src_value, GstFormat * dest_format, gint64 * dest_value);
98 static gboolean gst_mad_sink_event (GstPad * pad, GstEvent * event);
99 static GstFlowReturn gst_mad_chain (GstPad * pad, GstBuffer * buffer);
101 static GstStateChangeReturn gst_mad_change_state (GstElement * element,
102     GstStateChange transition);
104 #ifndef GST_DISABLE_INDEX
105 static void gst_mad_set_index (GstElement * element, GstIndex * index);
106 static GstIndex *gst_mad_get_index (GstElement * element);
107 #endif
109 static GstTagList *gst_mad_id3_to_tag_list (const struct id3_tag *tag);
111 GST_BOILERPLATE (GstMad, gst_mad, GstElement, GST_TYPE_ELEMENT);
113 /*
114 #define GST_TYPE_MAD_LAYER (gst_mad_layer_get_type())
115 static GType
116 gst_mad_layer_get_type (void)
118   static GType mad_layer_type = 0;
119   static GEnumValue mad_layer[] = {
120     {0, "Unknown", "unknown"},
121     {MAD_LAYER_I, "Layer I", "1"},
122     {MAD_LAYER_II, "Layer II", "2"},
123     {MAD_LAYER_III, "Layer III", "3"},
124     {0, NULL, NULL},
125   };
127   if (!mad_layer_type) {
128     mad_layer_type = g_enum_register_static ("GstMadLayer", mad_layer);
129   }
130   return mad_layer_type;
132 */
134 #define GST_TYPE_MAD_MODE (gst_mad_mode_get_type())
135 static GType
136 gst_mad_mode_get_type (void)
138   static GType mad_mode_type = 0;
139   static GEnumValue mad_mode[] = {
140     {-1, "Unknown", "unknown"},
141     {MAD_MODE_SINGLE_CHANNEL, "Mono", "mono"},
142     {MAD_MODE_DUAL_CHANNEL, "Dual Channel", "dual"},
143     {MAD_MODE_JOINT_STEREO, "Joint Stereo", "joint"},
144     {MAD_MODE_STEREO, "Stereo", "stereo"},
145     {0, NULL, NULL},
146   };
148   if (!mad_mode_type) {
149     mad_mode_type = g_enum_register_static ("GstMadMode", mad_mode);
150   }
151   return mad_mode_type;
154 #define GST_TYPE_MAD_EMPHASIS (gst_mad_emphasis_get_type())
155 static GType
156 gst_mad_emphasis_get_type (void)
158   static GType mad_emphasis_type = 0;
159   static GEnumValue mad_emphasis[] = {
160     {-1, "Unknown", "unknown"},
161     {MAD_EMPHASIS_NONE, "None", "none"},
162     {MAD_EMPHASIS_50_15_US, "50/15 Microseconds", "50-15"},
163     {MAD_EMPHASIS_CCITT_J_17, "CCITT J.17", "j-17"},
164     {MAD_EMPHASIS_RESERVED, "Reserved", "reserved"},
165     {0, NULL, NULL},
166   };
168   if (!mad_emphasis_type) {
169     mad_emphasis_type = g_enum_register_static ("GstMadEmphasis", mad_emphasis);
170   }
171   return mad_emphasis_type;
174 static void
175 gst_mad_base_init (gpointer g_class)
177   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
179   gst_element_class_add_pad_template (element_class,
180       gst_static_pad_template_get (&mad_sink_template_factory));
181   gst_element_class_add_pad_template (element_class,
182       gst_static_pad_template_get (&mad_src_template_factory));
183   gst_element_class_set_details_simple (element_class, "mad mp3 decoder",
184       "Codec/Decoder/Audio",
185       "Uses mad code to decode mp3 streams", "Wim Taymans <wim@fluendo.com>");
188 static void
189 gst_mad_class_init (GstMadClass * klass)
191   GObjectClass *gobject_class;
192   GstElementClass *gstelement_class;
194   gobject_class = (GObjectClass *) klass;
195   gstelement_class = (GstElementClass *) klass;
197   parent_class = g_type_class_peek_parent (klass);
199   gobject_class->set_property = gst_mad_set_property;
200   gobject_class->get_property = gst_mad_get_property;
201   gobject_class->dispose = gst_mad_dispose;
203   gstelement_class->change_state = gst_mad_change_state;
204 #ifndef GST_DISABLE_INDEX
205   gstelement_class->set_index = gst_mad_set_index;
206   gstelement_class->get_index = gst_mad_get_index;
207 #endif
209   /* init properties */
210   /* currently, string representations are used, we might want to change that */
211   /* FIXME: descriptions need to be more technical,
212    * default values and ranges need to be selected right */
213   g_object_class_install_property (gobject_class, ARG_HALF,
214       g_param_spec_boolean ("half", "Half", "Generate PCM at 1/2 sample rate",
215           FALSE, G_PARAM_READWRITE));
216   g_object_class_install_property (gobject_class, ARG_IGNORE_CRC,
217       g_param_spec_boolean ("ignore_crc", "Ignore CRC", "Ignore CRC errors",
218           TRUE, G_PARAM_READWRITE));
220   /* register tags */
221 #define GST_TAG_LAYER    "layer"
222 #define GST_TAG_MODE     "mode"
223 #define GST_TAG_EMPHASIS "emphasis"
225   /* FIXME 0.11: strings!? why? */
226   gst_tag_register (GST_TAG_LAYER, GST_TAG_FLAG_ENCODED, G_TYPE_UINT,
227       "layer", "MPEG audio layer", NULL);
228   gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
229       "mode", "MPEG audio channel mode", NULL);
230   gst_tag_register (GST_TAG_EMPHASIS, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
231       "emphasis", "MPEG audio emphasis", NULL);
233   /* ref these here from a thread-safe context (ie. not the streaming thread) */
234   g_type_class_ref (GST_TYPE_MAD_MODE);
235   g_type_class_ref (GST_TYPE_MAD_EMPHASIS);
238 static void
239 gst_mad_init (GstMad * mad, GstMadClass * klass)
241   GstPadTemplate *template;
243   /* create the sink and src pads */
244   template = gst_static_pad_template_get (&mad_sink_template_factory);
245   mad->sinkpad = gst_pad_new_from_template (template, "sink");
246   gst_object_unref (template);
247   gst_element_add_pad (GST_ELEMENT (mad), mad->sinkpad);
248   gst_pad_set_chain_function (mad->sinkpad, GST_DEBUG_FUNCPTR (gst_mad_chain));
249   gst_pad_set_event_function (mad->sinkpad,
250       GST_DEBUG_FUNCPTR (gst_mad_sink_event));
252   template = gst_static_pad_template_get (&mad_src_template_factory);
253   mad->srcpad = gst_pad_new_from_template (template, "src");
254   gst_object_unref (template);
255   gst_element_add_pad (GST_ELEMENT (mad), mad->srcpad);
256   gst_pad_set_event_function (mad->srcpad,
257       GST_DEBUG_FUNCPTR (gst_mad_src_event));
258   gst_pad_set_query_function (mad->srcpad,
259       GST_DEBUG_FUNCPTR (gst_mad_src_query));
260   gst_pad_set_query_type_function (mad->srcpad,
261       GST_DEBUG_FUNCPTR (gst_mad_get_query_types));
262   gst_pad_use_fixed_caps (mad->srcpad);
264   mad->tempbuffer = g_malloc (MAD_BUFFER_MDLEN * 3);
265   mad->tempsize = 0;
266   mad->base_byte_offset = 0;
267   mad->bytes_consumed = 0;
268   mad->total_samples = 0;
269   mad->new_header = TRUE;
270   mad->framecount = 0;
271   mad->vbr_average = 0;
272   mad->vbr_rate = 0;
273   mad->restart = TRUE;
274   mad->segment_start = 0;
275   gst_segment_init (&mad->segment, GST_FORMAT_TIME);
276   mad->header.mode = -1;
277   mad->header.emphasis = -1;
278   mad->tags = NULL;
280   mad->half = FALSE;
281   mad->ignore_crc = TRUE;
282   mad->check_for_xing = TRUE;
283   mad->xing_found = FALSE;
286 static void
287 gst_mad_dispose (GObject * object)
289   GstMad *mad = GST_MAD (object);
291 #ifndef GST_DISABLE_INDEX
292   gst_mad_set_index (GST_ELEMENT (object), NULL);
293 #endif
295   g_free (mad->tempbuffer);
296   mad->tempbuffer = NULL;
298   g_list_foreach (mad->pending_events, (GFunc) gst_mini_object_unref, NULL);
299   g_list_free (mad->pending_events);
300   mad->pending_events = NULL;
302   G_OBJECT_CLASS (parent_class)->dispose (object);
305 #ifndef GST_DISABLE_INDEX
306 static void
307 gst_mad_set_index (GstElement * element, GstIndex * index)
309   GstMad *mad = GST_MAD (element);
311   mad->index = index;
313   if (index)
314     gst_index_get_writer_id (index, GST_OBJECT (element), &mad->index_id);
317 static GstIndex *
318 gst_mad_get_index (GstElement * element)
320   GstMad *mad = GST_MAD (element);
322   return mad->index;
324 #endif
326 static gboolean
327 gst_mad_convert_sink (GstPad * pad, GstFormat src_format, gint64 src_value,
328     GstFormat * dest_format, gint64 * dest_value)
330   gboolean res = TRUE;
331   GstMad *mad;
333   if (src_format == *dest_format) {
334     *dest_value = src_value;
335     return TRUE;
336   }
338   /* -1 always maps to -1, and 0 to 0, we don't need any more info for that */
339   if (src_value == -1 || src_value == 0) {
340     *dest_value = src_value;
341     return TRUE;
342   }
344   mad = GST_MAD (GST_PAD_PARENT (pad));
346   if (mad->vbr_average == 0)
347     return FALSE;
349   switch (src_format) {
350     case GST_FORMAT_BYTES:
351       switch (*dest_format) {
352         case GST_FORMAT_TIME:
353           /* multiply by 8 because vbr is in bits/second */
354           *dest_value = gst_util_uint64_scale (src_value, 8 * GST_SECOND,
355               mad->vbr_average);
356           break;
357         default:
358           res = FALSE;
359       }
360       break;
361     case GST_FORMAT_TIME:
362       switch (*dest_format) {
363         case GST_FORMAT_BYTES:
364           /* multiply by 8 because vbr is in bits/second */
365           *dest_value = gst_util_uint64_scale (src_value, mad->vbr_average,
366               8 * GST_SECOND);
367           break;
368         default:
369           res = FALSE;
370       }
371       break;
372     default:
373       res = FALSE;
374   }
375   return res;
378 static gboolean
379 gst_mad_convert_src (GstPad * pad, GstFormat src_format, gint64 src_value,
380     GstFormat * dest_format, gint64 * dest_value)
382   gboolean res = TRUE;
383   guint scale = 1;
384   gint bytes_per_sample;
385   GstMad *mad;
387   if (src_format == *dest_format) {
388     *dest_value = src_value;
389     return TRUE;
390   }
392   /* -1 always maps to -1, and 0 to 0, we don't need any more info for that */
393   if (src_value == -1 || src_value == 0) {
394     *dest_value = src_value;
395     return TRUE;
396   }
398   mad = GST_MAD (GST_PAD_PARENT (pad));
400   bytes_per_sample = mad->channels * 4;
402   switch (src_format) {
403     case GST_FORMAT_BYTES:
404       switch (*dest_format) {
405         case GST_FORMAT_DEFAULT:
406           if (bytes_per_sample == 0)
407             return FALSE;
408           *dest_value = src_value / bytes_per_sample;
409           break;
410         case GST_FORMAT_TIME:
411         {
412           gint byterate = bytes_per_sample * mad->rate;
414           if (byterate == 0)
415             return FALSE;
416           *dest_value =
417               gst_util_uint64_scale_int (src_value, GST_SECOND, byterate);
418           break;
419         }
420         default:
421           res = FALSE;
422       }
423       break;
424     case GST_FORMAT_DEFAULT:
425       switch (*dest_format) {
426         case GST_FORMAT_BYTES:
427           *dest_value = src_value * bytes_per_sample;
428           break;
429         case GST_FORMAT_TIME:
430           if (mad->rate == 0)
431             return FALSE;
432           *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND,
433               mad->rate);
434           break;
435         default:
436           res = FALSE;
437       }
438       break;
439     case GST_FORMAT_TIME:
440       switch (*dest_format) {
441         case GST_FORMAT_BYTES:
442           scale = bytes_per_sample;
443           /* fallthrough */
444         case GST_FORMAT_DEFAULT:
445           *dest_value = gst_util_uint64_scale_int (src_value,
446               scale * mad->rate, GST_SECOND);
447           break;
448         default:
449           res = FALSE;
450       }
451       break;
452     default:
453       res = FALSE;
454   }
455   return res;
458 static const GstQueryType *
459 gst_mad_get_query_types (GstPad * pad)
461   static const GstQueryType gst_mad_src_query_types[] = {
462     GST_QUERY_POSITION,
463     GST_QUERY_DURATION,
464     GST_QUERY_CONVERT,
465     0
466   };
468   return gst_mad_src_query_types;
471 static gboolean
472 gst_mad_src_query (GstPad * pad, GstQuery * query)
474   gboolean res = TRUE;
475   GstPad *peer;
476   GstMad *mad;
478   mad = GST_MAD (GST_PAD_PARENT (pad));
480   peer = gst_pad_get_peer (mad->sinkpad);
482   switch (GST_QUERY_TYPE (query)) {
483     case GST_QUERY_FORMATS:
484       gst_query_set_formats (query, 3, GST_FORMAT_DEFAULT, GST_FORMAT_TIME,
485           GST_FORMAT_BYTES);
486       break;
487     case GST_QUERY_POSITION:
488     {
489       GstFormat format;
490       gint64 cur;
492       /* save requested format */
493       gst_query_parse_position (query, &format, NULL);
495       /* try any demuxer before us first */
496       if (format == GST_FORMAT_TIME && peer && gst_pad_query (peer, query)) {
497         gst_query_parse_position (query, NULL, &cur);
498         GST_LOG_OBJECT (mad, "peer returned position %" GST_TIME_FORMAT,
499             GST_TIME_ARGS (cur));
500         break;
501       }
503       /* and convert to the requested format */
504       if (format != GST_FORMAT_DEFAULT) {
505         if (!gst_mad_convert_src (pad, GST_FORMAT_DEFAULT, mad->total_samples,
506                 &format, &cur))
507           goto error;
508       } else {
509         cur = mad->total_samples;
510       }
512       gst_query_set_position (query, format, cur);
514       if (format == GST_FORMAT_TIME) {
515         GST_LOG ("position=%" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
516       } else {
517         GST_LOG ("position=%" G_GINT64_FORMAT ", format=%u", cur, format);
518       }
519       break;
520     }
521     case GST_QUERY_DURATION:
522     {
523       GstFormat bytes_format = GST_FORMAT_BYTES;
524       GstFormat time_format = GST_FORMAT_TIME;
525       GstFormat req_format;
526       gint64 total, total_bytes;
528       /* save requested format */
529       gst_query_parse_duration (query, &req_format, NULL);
531       if (peer == NULL)
532         goto error;
534       /* try any demuxer before us first */
535       if (req_format == GST_FORMAT_TIME && gst_pad_query (peer, query)) {
536         gst_query_parse_duration (query, NULL, &total);
537         GST_LOG_OBJECT (mad, "peer returned duration %" GST_TIME_FORMAT,
538             GST_TIME_ARGS (total));
539         break;
540       }
542       /* query peer for total length in bytes */
543       if (!gst_pad_query_peer_duration (mad->sinkpad, &bytes_format,
544               &total_bytes) || total_bytes <= 0) {
545         GST_LOG_OBJECT (mad, "duration query on peer pad failed");
546         goto error;
547       }
549       GST_LOG_OBJECT (mad, "peer pad returned total=%" G_GINT64_FORMAT
550           " bytes", total_bytes);
552       if (!gst_mad_convert_sink (pad, GST_FORMAT_BYTES, total_bytes,
553               &time_format, &total)) {
554         GST_DEBUG_OBJECT (mad, "conversion BYTE => TIME failed");
555         goto error;
556       }
557       if (!gst_mad_convert_src (pad, GST_FORMAT_TIME, total,
558               &req_format, &total)) {
559         GST_DEBUG_OBJECT (mad, "conversion TIME => %s failed",
560             gst_format_get_name (req_format));
561         goto error;
562       }
564       gst_query_set_duration (query, req_format, total);
566       if (req_format == GST_FORMAT_TIME) {
567         GST_LOG_OBJECT (mad, "duration=%" GST_TIME_FORMAT,
568             GST_TIME_ARGS (total));
569       } else {
570         GST_LOG_OBJECT (mad, "duration=%" G_GINT64_FORMAT " (%s)",
571             total, gst_format_get_name (req_format));
572       }
573       break;
574     }
575     case GST_QUERY_CONVERT:
576     {
577       GstFormat src_fmt, dest_fmt;
578       gint64 src_val, dest_val;
580       gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val);
581       if (!(res =
582               gst_mad_convert_src (pad, src_fmt, src_val, &dest_fmt,
583                   &dest_val)))
584         goto error;
585       gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val);
586       break;
587     }
588     default:
589       res = gst_pad_query_default (pad, query);
590       break;
591   }
593   if (peer)
594     gst_object_unref (peer);
596   return res;
598 error:
600   GST_DEBUG ("error handling query");
602   if (peer)
603     gst_object_unref (peer);
605   return FALSE;
608 #ifndef GST_DISABLE_INDEX
609 static gboolean
610 index_seek (GstMad * mad, GstPad * pad, GstEvent * event)
612   gdouble rate;
613   GstFormat format;
614   GstSeekFlags flags;
615   GstSeekType cur_type, stop_type;
616   gint64 cur, stop;
617   GstIndexEntry *entry = NULL;
619   /* since we know the exact byteoffset of the frame,
620      make sure to try bytes first */
622   const GstFormat try_all_formats[] = {
623     GST_FORMAT_BYTES,
624     GST_FORMAT_TIME,
625     0
626   };
627   const GstFormat *try_formats = try_all_formats;
628   const GstFormat *peer_formats;
630   gst_event_parse_seek (event, &rate, &format, &flags,
631       &cur_type, &cur, &stop_type, &stop);
633   if (format == GST_FORMAT_TIME) {
634     gst_segment_set_seek (&mad->segment, rate, format, flags, cur_type,
635         cur, stop_type, stop, NULL);
636   } else {
637     gst_segment_init (&mad->segment, GST_FORMAT_UNDEFINED);
638   }
640   entry = gst_index_get_assoc_entry (mad->index, mad->index_id,
641       GST_INDEX_LOOKUP_BEFORE, 0, format, cur);
643   GST_DEBUG ("index seek");
645   if (!entry)
646     return FALSE;
648 #if 0
649   peer_formats = gst_pad_get_formats (GST_PAD_PEER (mad->sinkpad));
650 #else
651   peer_formats = try_all_formats;       /* FIXME */
652 #endif
654   while (gst_formats_contains (peer_formats, *try_formats)) {
655     gint64 value;
656     GstEvent *seek_event;
658     if (gst_index_entry_assoc_map (entry, *try_formats, &value)) {
659       /* lookup succeeded, create the seek */
661       GST_DEBUG ("index %s %" G_GINT64_FORMAT
662           " -> %s %" G_GINT64_FORMAT,
663           gst_format_get_details (format)->nick,
664           cur, gst_format_get_details (*try_formats)->nick, value);
666       seek_event = gst_event_new_seek (rate, *try_formats, flags,
667           cur_type, value, stop_type, stop);
669       if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), seek_event)) {
670         /* seek worked, we're done, loop will exit */
671         mad->restart = TRUE;
672         g_assert (format == GST_FORMAT_TIME);
673         mad->segment_start = cur;
674         return TRUE;
675       }
676     }
677     try_formats++;
678   }
680   return FALSE;
682 #endif
684 static gboolean
685 normal_seek (GstMad * mad, GstPad * pad, GstEvent * event)
687   gdouble rate;
688   GstFormat format, conv;
689   GstSeekFlags flags;
690   GstSeekType cur_type, stop_type;
691   gint64 cur, stop;
692   gint64 time_cur, time_stop;
693   gint64 bytes_cur, bytes_stop;
694   gboolean flush;
696   /* const GstFormat *peer_formats; */
697   gboolean res;
699   GST_DEBUG ("normal seek");
701   gst_event_parse_seek (event, &rate, &format, &flags,
702       &cur_type, &cur, &stop_type, &stop);
704   if (format != GST_FORMAT_TIME) {
705     conv = GST_FORMAT_TIME;
706     if (!gst_mad_convert_src (pad, format, cur, &conv, &time_cur))
707       goto convert_error;
708     if (!gst_mad_convert_src (pad, format, stop, &conv, &time_stop))
709       goto convert_error;
710   } else {
711     time_cur = cur;
712     time_stop = stop;
713   }
715   gst_segment_set_seek (&mad->segment, rate, GST_FORMAT_TIME, flags, cur_type,
716       time_cur, stop_type, time_stop, NULL);
718   GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT,
719       GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop));
721   /* shave off the flush flag, we'll need it later */
722   flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0);
724   conv = GST_FORMAT_BYTES;
725   if (!gst_mad_convert_sink (pad, GST_FORMAT_TIME, time_cur, &conv, &bytes_cur))
726     goto convert_error;
727   if (!gst_mad_convert_sink (pad, GST_FORMAT_TIME, time_stop, &conv,
728           &bytes_stop))
729     goto convert_error;
731   {
732     GstEvent *seek_event;
734     /* conversion succeeded, create the seek */
735     seek_event =
736         gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
737         bytes_cur, stop_type, bytes_stop);
739     /* do the seek */
740     res = gst_pad_push_event (mad->sinkpad, seek_event);
742     if (res) {
743       /* we need to break out of the processing loop on flush */
744       mad->restart = flush;
745       mad->segment_start = time_cur;
746       mad->last_ts = time_cur;
747     }
748   }
749 #if 0
750   peer_formats = gst_pad_get_formats (GST_PAD_PEER (mad->sinkpad));
751   /* while we did not exhaust our seek formats without result */
752   while (peer_formats && *peer_formats && !res) {
753     gint64 desired_offset;
755     format = *peer_formats;
757     /* try to convert requested format to one we can seek with on the sinkpad */
758     if (gst_pad_convert (mad->sinkpad, GST_FORMAT_TIME, src_offset,
759             &format, &desired_offset)) {
760       GstEvent *seek_event;
762       /* conversion succeeded, create the seek */
763       seek_event =
764           gst_event_new_seek (format | GST_EVENT_SEEK_METHOD (event) | flush,
765           desired_offset);
766       /* do the seek */
767       if (gst_pad_send_event (GST_PAD_PEER (mad->sinkpad), seek_event)) {
768         /* seek worked, we're done, loop will exit */
769         res = TRUE;
770       }
771     }
772     /* at this point, either the seek worked or res == FALSE */
773     if (res)
774       /* we need to break out of the processing loop on flush */
775       mad->restart = flush;
777     peer_formats++;
778   }
779 #endif
781   return res;
783   /* ERRORS */
784 convert_error:
785   {
786     /* probably unsupported seek format */
787     GST_DEBUG ("failed to convert format %u into GST_FORMAT_TIME", format);
788     return FALSE;
789   }
792 static gboolean
793 gst_mad_src_event (GstPad * pad, GstEvent * event)
795   gboolean res = TRUE;
796   GstMad *mad;
798   mad = GST_MAD (GST_PAD_PARENT (pad));
800   switch (GST_EVENT_TYPE (event)) {
801     case GST_EVENT_SEEK:
802       /* the all-formats seek logic, ref the event, we need it later */
803       gst_event_ref (event);
804       if (!(res = gst_pad_push_event (mad->sinkpad, event))) {
805 #ifndef GST_DISABLE_INDEX
806         if (mad->index)
807           res = index_seek (mad, pad, event);
808         else
809 #endif
810           res = normal_seek (mad, pad, event);
811       }
812       gst_event_unref (event);
813       break;
814     default:
815       res = gst_pad_push_event (mad->sinkpad, event);
816       break;
817   }
819   return res;
822 static inline gint32
823 scale (mad_fixed_t sample)
825 #if MAD_F_FRACBITS < 28
826   /* round */
827   sample += (1L << (28 - MAD_F_FRACBITS - 1));
828 #endif
830   /* clip */
831   if (sample >= MAD_F_ONE)
832     sample = MAD_F_ONE - 1;
833   else if (sample < -MAD_F_ONE)
834     sample = -MAD_F_ONE;
836 #if MAD_F_FRACBITS < 28
837   /* quantize */
838   sample >>= (28 - MAD_F_FRACBITS);
839 #endif
841   /* convert from 29 bits to 32 bits */
842   return (gint32) (sample << 3);
845 /* do we need this function? */
846 static void
847 gst_mad_set_property (GObject * object, guint prop_id,
848     const GValue * value, GParamSpec * pspec)
850   GstMad *mad;
852   mad = GST_MAD (object);
854   switch (prop_id) {
855     case ARG_HALF:
856       mad->half = g_value_get_boolean (value);
857       break;
858     case ARG_IGNORE_CRC:
859       mad->ignore_crc = g_value_get_boolean (value);
860       break;
861     default:
862       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
863       break;
864   }
867 static void
868 gst_mad_get_property (GObject * object, guint prop_id,
869     GValue * value, GParamSpec * pspec)
871   GstMad *mad;
873   mad = GST_MAD (object);
875   switch (prop_id) {
876     case ARG_HALF:
877       g_value_set_boolean (value, mad->half);
878       break;
879     case ARG_IGNORE_CRC:
880       g_value_set_boolean (value, mad->ignore_crc);
881       break;
882     default:
883       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
884       break;
885   }
888 static void
889 gst_mad_update_info (GstMad * mad)
891   struct mad_header *header = &mad->frame.header;
892   gboolean changed = FALSE;
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->header.bitrate = header->bitrate;
916   mad->new_header = FALSE;
918   if (changed) {
919     GstTagList *list;
920     GEnumValue *mode;
921     GEnumValue *emphasis;
923     mode =
924         g_enum_get_value (g_type_class_peek (GST_TYPE_MAD_MODE),
925         mad->header.mode);
926     emphasis =
927         g_enum_get_value (g_type_class_peek (GST_TYPE_MAD_EMPHASIS),
928         mad->header.emphasis);
929     list = gst_tag_list_new ();
930     gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
931         GST_TAG_LAYER, mad->header.layer,
932         GST_TAG_MODE, mode->value_nick,
933         GST_TAG_EMPHASIS, emphasis->value_nick, NULL);
934     if (!mad->framed) {
935       gchar *str;
937       str = g_strdup_printf ("MPEG-1 layer %d", mad->header.layer);
938       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
939           GST_TAG_AUDIO_CODEC, str, NULL);
940       g_free (str);
941     }
942     if (!mad->xing_found) {
943       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
944           GST_TAG_BITRATE, mad->header.bitrate, NULL);
945     }
946     gst_element_post_message (GST_ELEMENT (mad),
947         gst_message_new_tag (GST_OBJECT (mad), list));
948   }
949 #undef CHECK_HEADER
953 static gboolean
954 gst_mad_sink_event (GstPad * pad, GstEvent * event)
956   GstMad *mad = GST_MAD (GST_PAD_PARENT (pad));
957   gboolean result;
959   GST_DEBUG ("handling %s event", GST_EVENT_TYPE_NAME (event));
961   switch (GST_EVENT_TYPE (event)) {
962     case GST_EVENT_NEWSEGMENT:{
963       GstFormat format;
964       gboolean update;
965       gdouble rate, applied_rate;
966       gint64 start, stop, pos;
968       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
969           &format, &start, &stop, &pos);
971       if (format == GST_FORMAT_TIME) {
972         /* FIXME: is this really correct? */
973         mad->tempsize = 0;
974         result = gst_pad_push_event (mad->srcpad, event);
975         /* we don't need to restart when we get here */
976         mad->restart = FALSE;
977         mad->framed = TRUE;
978         gst_segment_set_newsegment_full (&mad->segment, update, rate,
979             applied_rate, GST_FORMAT_TIME, start, stop, pos);
980       } else {
981         GST_DEBUG ("dropping newsegment event in format %s",
982             gst_format_get_name (format));
983         /* on restart the chain function will generate a new
984          * newsegment event, so we can just drop this one */
985         mad->restart = TRUE;
986         gst_event_unref (event);
987         mad->tempsize = 0;
988         mad->framed = FALSE;
989         result = TRUE;
990       }
991       break;
992     }
993     case GST_EVENT_EOS:
994       mad->caps_set = FALSE;    /* could be a new stream */
995       result = gst_pad_push_event (mad->srcpad, event);
996       break;
997     case GST_EVENT_FLUSH_STOP:
998       /* Clear any stored data, as it won't make sense once
999        * the new data arrives */
1000       mad->tempsize = 0;
1001       mad_frame_mute (&mad->frame);
1002       mad_synth_mute (&mad->synth);
1003     case GST_EVENT_FLUSH_START:
1004       result = gst_pad_event_default (pad, event);
1006       break;
1007     default:
1008       if (mad->restart) {
1009         /* Cache all other events if we still have to send a NEWSEGMENT */
1010         mad->pending_events = g_list_append (mad->pending_events, event);
1011         result = TRUE;
1012       } else {
1013         result = gst_pad_event_default (pad, event);
1014       }
1015       break;
1016   }
1017   return result;
1020 static gboolean
1021 gst_mad_check_restart (GstMad * mad)
1023   gboolean yes = mad->restart;
1025   if (mad->restart) {
1026     mad->restart = FALSE;
1027     mad->tempsize = 0;
1028   }
1029   return yes;
1033 /* The following code has been taken from 
1034  * rhythmbox/metadata/monkey-media/stream-info-impl/id3-vfs/mp3bitrate.c
1035  * which took it from xine-lib/src/demuxers/demux_mpgaudio.c
1036  * This code has been kindly relicensed to LGPL by Thibaut Mattern and 
1037  * Bastien Nocera
1038  */
1039 #define BE_32(x) GST_READ_UINT32_BE(x)
1041 #define FOURCC_TAG( ch0, ch1, ch2, ch3 )                \
1042         ( (long)(unsigned char)(ch3) |                  \
1043           ( (long)(unsigned char)(ch2) << 8 ) |         \
1044           ( (long)(unsigned char)(ch1) << 16 ) |        \
1045           ( (long)(unsigned char)(ch0) << 24 ) )
1047 /* Xing header stuff */
1048 #define XING_TAG FOURCC_TAG('X', 'i', 'n', 'g')
1049 #define XING_FRAMES_FLAG     0x0001
1050 #define XING_BYTES_FLAG      0x0002
1051 #define XING_TOC_FLAG        0x0004
1052 #define XING_VBR_SCALE_FLAG  0x0008
1053 #define XING_TOC_LENGTH      100
1055 /* check for valid "Xing" VBR header */
1056 static int
1057 is_xhead (unsigned char *buf)
1059   return (BE_32 (buf) == XING_TAG);
1063 #undef LOG
1064 /*#define LOG*/
1065 #ifdef LOG
1066 #ifndef WIN32
1067 #define lprintf(x...) g_print(x)
1068 #else
1069 #define lprintf GST_DEBUG
1070 #endif
1071 #else
1072 #ifndef WIN32
1073 #define lprintf(x...)
1074 #else
1075 #define lprintf GST_DEBUG
1076 #endif
1077 #endif
1079 static int
1080 mpg123_parse_xing_header (struct mad_header *header,
1081     const guint8 * buf, int bufsize, int *bitrate, int *time)
1083   int i;
1084   guint8 *ptr = (guint8 *) buf;
1085   double frame_duration;
1086   int xflags, xframes, xbytes;
1087   int abr;
1088   guint8 xtoc[XING_TOC_LENGTH];
1089   int lsf_bit = !(header->flags & MAD_FLAG_LSF_EXT);
1091   xframes = xbytes = 0;
1093   /* offset of the Xing header */
1094   if (lsf_bit) {
1095     if (header->mode != MAD_MODE_SINGLE_CHANNEL)
1096       ptr += (32 + 4);
1097     else
1098       ptr += (17 + 4);
1099   } else {
1100     if (header->mode != MAD_MODE_SINGLE_CHANNEL)
1101       ptr += (17 + 4);
1102     else
1103       ptr += (9 + 4);
1104   }
1106   if (ptr >= (buf + bufsize - 4))
1107     return 0;
1109   if (is_xhead (ptr)) {
1110     lprintf ("Xing header found\n");
1112     ptr += 4;
1113     if (ptr >= (buf + bufsize - 4))
1114       return 0;
1116     xflags = BE_32 (ptr);
1117     ptr += 4;
1119     if (xflags & XING_FRAMES_FLAG) {
1120       if (ptr >= (buf + bufsize - 4))
1121         return 0;
1122       xframes = BE_32 (ptr);
1123       lprintf ("xframes: %d\n", xframes);
1124       ptr += 4;
1125     }
1126     if (xflags & XING_BYTES_FLAG) {
1127       if (ptr >= (buf + bufsize - 4))
1128         return 0;
1129       xbytes = BE_32 (ptr);
1130       lprintf ("xbytes: %d\n", xbytes);
1131       ptr += 4;
1132     }
1133     if (xflags & XING_TOC_FLAG) {
1134       guchar old = 0;
1136       lprintf ("toc found\n");
1137       if (ptr >= (buf + bufsize - XING_TOC_LENGTH))
1138         return 0;
1139       if (*ptr != 0) {
1140         lprintf ("skipping broken Xing TOC\n");
1141         goto skip_toc;
1142       }
1143       for (i = 0; i < XING_TOC_LENGTH; i++) {
1144         xtoc[i] = *(ptr + i);
1145         if (old > xtoc[i]) {
1146           lprintf ("skipping broken Xing TOC\n");
1147           goto skip_toc;
1148         }
1149         lprintf ("%d ", xtoc[i]);
1150       }
1151       lprintf ("\n");
1152     skip_toc:
1153       ptr += XING_TOC_LENGTH;
1154     }
1156     if (xflags & XING_VBR_SCALE_FLAG) {
1157       if (ptr >= (buf + bufsize - 4))
1158         return 0;
1159       lprintf ("xvbr_scale: %d\n", BE_32 (ptr));
1160     }
1162     /* 1 kbit = 1000 bits ! (and not 1024 bits) */
1163     if (xflags & (XING_FRAMES_FLAG | XING_BYTES_FLAG)) {
1164       if (header->layer == MAD_LAYER_I) {
1165         frame_duration = 384.0 / (double) header->samplerate;
1166       } else {
1167         int slots_per_frame;
1169         slots_per_frame = ((header->layer == MAD_LAYER_III)
1170             && !lsf_bit) ? 72 : 144;
1171         frame_duration = slots_per_frame * 8.0 / (double) header->samplerate;
1172       }
1173       abr = ((double) xbytes * 8.0) / ((double) xframes * frame_duration);
1174       lprintf ("abr: %d bps\n", abr);
1175       if (bitrate != NULL) {
1176         *bitrate = abr;
1177       }
1178       if (time != NULL) {
1179         *time = (double) xframes *frame_duration;
1181         lprintf ("stream_length: %d s, %d min %d s\n", *time,
1182             *time / 60, *time % 60);
1183       }
1184     } else {
1185       /* it's a stupid Xing header */
1186       lprintf ("not a Xing VBR file\n");
1187     }
1188     return 1;
1189   } else {
1190     lprintf ("Xing header not found\n");
1191     return 0;
1192   }
1195 /* End of Xine code */
1197 /* internal function to check if the header has changed and thus the
1198  * caps need to be reset.  Only call during normal mode, not resyncing */
1199 static void
1200 gst_mad_check_caps_reset (GstMad * mad)
1202   guint nchannels;
1203   guint rate, old_rate = mad->rate;
1205   nchannels = MAD_NCHANNELS (&mad->frame.header);
1207 #if MAD_VERSION_MINOR <= 12
1208   rate = mad->header.sfreq;
1209 #else
1210   rate = mad->frame.header.samplerate;
1211 #endif
1213   /* rate and channels are not supposed to change in a continuous stream,
1214    * so check this first before doing anything */
1216   /* only set caps if they weren't already set for this continuous stream */
1217   if (mad->channels != nchannels || mad->rate != rate) {
1218     if (mad->caps_set) {
1219       GST_DEBUG
1220           ("Header changed from %d Hz/%d ch to %d Hz/%d ch, failed sync after seek ?",
1221           mad->rate, mad->channels, rate, nchannels);
1222       /* we're conservative on stream changes. However, our *initial* caps
1223        * might have been wrong as well - mad ain't perfect in syncing. So,
1224        * we count caps changes and change if we pass a limit treshold (3). */
1225       if (nchannels != mad->pending_channels || rate != mad->pending_rate) {
1226         mad->times_pending = 0;
1227         mad->pending_channels = nchannels;
1228         mad->pending_rate = rate;
1229       }
1230       if (++mad->times_pending < 3)
1231         return;
1232     }
1233   }
1234   gst_mad_update_info (mad);
1236   if (mad->channels != nchannels || mad->rate != rate) {
1237     GstCaps *caps;
1239     if (mad->stream.options & MAD_OPTION_HALFSAMPLERATE)
1240       rate >>= 1;
1242     /* FIXME see if peer can accept the caps */
1244     /* we set the caps even when the pad is not connected so they
1245      * can be gotten for streaminfo */
1246     caps = gst_caps_new_simple ("audio/x-raw-int",
1247         "endianness", G_TYPE_INT, G_BYTE_ORDER,
1248         "signed", G_TYPE_BOOLEAN, TRUE,
1249         "width", G_TYPE_INT, 32,
1250         "depth", G_TYPE_INT, 32,
1251         "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, nchannels, NULL);
1253     gst_pad_set_caps (mad->srcpad, caps);
1254     gst_caps_unref (caps);
1256     mad->caps_set = TRUE;       /* set back to FALSE on discont */
1257     mad->channels = nchannels;
1258     mad->rate = rate;
1260     /* update sample count so we don't come up with crazy timestamps */
1261     if (mad->total_samples && old_rate) {
1262       mad->total_samples = mad->total_samples * rate / old_rate;
1263     }
1264   }
1267 static GstFlowReturn
1268 gst_mad_chain (GstPad * pad, GstBuffer * buffer)
1270   GstMad *mad;
1271   guint8 *data;
1272   glong size, tempsize;
1273   gboolean new_pts = FALSE;
1274   gboolean discont;
1275   GstClockTime timestamp;
1276   GstFlowReturn result = GST_FLOW_OK;
1278   mad = GST_MAD (GST_PAD_PARENT (pad));
1280   /* restarts happen on discontinuities, ie. seek, flush, PAUSED to PLAYING */
1281   if (gst_mad_check_restart (mad)) {
1282     mad->need_newsegment = TRUE;
1283     GST_DEBUG ("mad restarted");
1284   }
1286   /* take discont flag */
1287   discont = GST_BUFFER_IS_DISCONT (buffer);
1289   timestamp = GST_BUFFER_TIMESTAMP (buffer);
1290   GST_DEBUG ("mad in timestamp %" GST_TIME_FORMAT " duration:%" GST_TIME_FORMAT,
1291       GST_TIME_ARGS (timestamp), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
1293   /* handle timestamps */
1294   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1295     /* if there is nothing left to process in our temporary buffer,
1296      * we can set this timestamp on the next outgoing buffer */
1297     if (mad->tempsize == 0) {
1298       /* we have to save the result here because we can't yet convert
1299        * the timestamp to a sample offset, as the samplerate might not
1300        * be known yet */
1301       mad->last_ts = timestamp;
1302       mad->base_byte_offset = GST_BUFFER_OFFSET (buffer);
1303       mad->bytes_consumed = 0;
1304     }
1305     /* else we need to finish the current partial frame with the old timestamp
1306      * and queue this timestamp for the next frame */
1307     else {
1308       new_pts = TRUE;
1309     }
1310   }
1311   GST_DEBUG ("last_ts %" GST_TIME_FORMAT, GST_TIME_ARGS (mad->last_ts));
1313   /* handle data */
1314   data = GST_BUFFER_DATA (buffer);
1315   size = GST_BUFFER_SIZE (buffer);
1317   tempsize = mad->tempsize;
1319   /* process the incoming buffer in chunks of maximum MAD_BUFFER_MDLEN bytes;
1320    * this is the upper limit on processable chunk sizes set by mad */
1321   while (size > 0) {
1322     gint tocopy;
1323     guchar *mad_input_buffer;   /* convenience pointer to tempbuffer */
1325     if (mad->tempsize == 0 && discont) {
1326       mad->discont = TRUE;
1327       discont = FALSE;
1328     }
1329     tocopy =
1330         MIN (MAD_BUFFER_MDLEN, MIN (size,
1331             MAD_BUFFER_MDLEN * 3 - mad->tempsize));
1332     if (tocopy == 0) {
1333       GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL),
1334           ("mad claims to need more data than %u bytes, we don't have that much",
1335               MAD_BUFFER_MDLEN * 3));
1336       result = GST_FLOW_ERROR;
1337       goto end;
1338     }
1340     /* append the chunk to process to our internal temporary buffer */
1341     GST_LOG ("tempbuffer size %ld, copying %d bytes from incoming buffer",
1342         mad->tempsize, tocopy);
1343     memcpy (mad->tempbuffer + mad->tempsize, data, tocopy);
1344     mad->tempsize += tocopy;
1346     /* update our incoming buffer's parameters to reflect this */
1347     size -= tocopy;
1348     data += tocopy;
1350     mad_input_buffer = mad->tempbuffer;
1352     /* while we have data we can consume it */
1353     while (mad->tempsize > 0) {
1354       gint consumed = 0;
1355       guint nsamples;
1356       guint64 time_offset = GST_CLOCK_TIME_NONE;
1357       guint64 time_duration = GST_CLOCK_TIME_NONE;
1358       unsigned char const *before_sync, *after_sync;
1359       gboolean goto_exit = FALSE;
1361       mad->in_error = FALSE;
1363       mad_stream_buffer (&mad->stream, mad_input_buffer, mad->tempsize);
1365       /* added separate header decoding to catch errors earlier, also fixes
1366        * some weird decoding errors... */
1367       GST_LOG ("decoding the header now");
1368       if (mad_header_decode (&mad->frame.header, &mad->stream) == -1) {
1369         if (mad->stream.error == MAD_ERROR_BUFLEN) {
1370           GST_LOG ("not enough data in tempbuffer (%ld), breaking to get more",
1371               mad->tempsize);
1372           break;
1373         } else {
1374           GST_WARNING ("mad_header_decode had an error: %s",
1375               mad_stream_errorstr (&mad->stream));
1376         }
1377       }
1379       GST_LOG ("decoding one frame now");
1381       if (mad_frame_decode (&mad->frame, &mad->stream) == -1) {
1382         GST_LOG ("got error %d", mad->stream.error);
1384         /* not enough data, need to wait for next buffer? */
1385         if (mad->stream.error == MAD_ERROR_BUFLEN) {
1386           if (mad->stream.next_frame == mad_input_buffer) {
1387             GST_LOG
1388                 ("not enough data in tempbuffer (%ld), breaking to get more",
1389                 mad->tempsize);
1390             break;
1391           } else {
1392             GST_LOG ("sync error, flushing unneeded data");
1393             goto next_no_samples;
1394           }
1395         } else if (mad->stream.error == MAD_ERROR_BADDATAPTR) {
1396           /* Flush data */
1397           goto next_no_samples;
1398         }
1399         /* we are in an error state */
1400         mad->in_error = TRUE;
1401         GST_WARNING ("mad_frame_decode had an error: %s",
1402             mad_stream_errorstr (&mad->stream));
1403         if (!MAD_RECOVERABLE (mad->stream.error)) {
1404           GST_ELEMENT_ERROR (mad, STREAM, DECODE, (NULL), (NULL));
1405           result = GST_FLOW_ERROR;
1406           goto end;
1407         } else if (mad->stream.error == MAD_ERROR_LOSTSYNC) {
1408           /* lost sync, force a resync */
1409           signed long tagsize;
1411           GST_INFO ("recoverable lost sync error");
1413           tagsize = id3_tag_query (mad->stream.this_frame,
1414               mad->stream.bufend - mad->stream.this_frame);
1416           if (tagsize > mad->tempsize) {
1417             GST_INFO ("mad: got partial id3 tag in buffer, skipping");
1418           } else if (tagsize > 0) {
1419             struct id3_tag *tag;
1420             id3_byte_t const *data;
1422             GST_INFO ("mad: got ID3 tag size %ld", tagsize);
1424             data = mad->stream.this_frame;
1426             /* mad has moved the pointer to the next frame over the start of the
1427              * id3 tags, so we need to flush one byte less than the tagsize */
1428             mad_stream_skip (&mad->stream, tagsize - 1);
1430             tag = id3_tag_parse (data, tagsize);
1431             if (tag) {
1432               GstTagList *list;
1434               list = gst_mad_id3_to_tag_list (tag);
1435               id3_tag_delete (tag);
1436               GST_DEBUG ("found tag");
1437               gst_element_post_message (GST_ELEMENT (mad),
1438                   gst_message_new_tag (GST_OBJECT (mad),
1439                       gst_tag_list_copy (list)));
1440               if (mad->tags) {
1441                 gst_tag_list_insert (mad->tags, list, GST_TAG_MERGE_PREPEND);
1442               } else {
1443                 mad->tags = gst_tag_list_copy (list);
1444               }
1445               if (mad->need_newsegment)
1446                 mad->pending_events =
1447                     g_list_append (mad->pending_events,
1448                     gst_event_new_tag (list));
1449               else
1450                 gst_pad_push_event (mad->srcpad, gst_event_new_tag (list));
1451             }
1452           }
1453         }
1455         mad_frame_mute (&mad->frame);
1456         mad_synth_mute (&mad->synth);
1457         before_sync = mad->stream.ptr.byte;
1458         if (mad_stream_sync (&mad->stream) != 0)
1459           GST_WARNING ("mad_stream_sync failed");
1460         after_sync = mad->stream.ptr.byte;
1461         /* a succesful resync should make us drop bytes as consumed, so
1462            calculate from the byte pointers before and after resync */
1463         consumed = after_sync - before_sync;
1464         GST_DEBUG ("resynchronization consumes %d bytes", consumed);
1465         GST_DEBUG ("synced to data: 0x%0x 0x%0x", *mad->stream.ptr.byte,
1466             *(mad->stream.ptr.byte + 1));
1468         mad_stream_sync (&mad->stream);
1469         /* recoverable errors pass */
1470         goto next_no_samples;
1471       }
1473       if (mad->check_for_xing) {
1474         int bitrate = 0, time = 0;
1475         GstTagList *list;
1476         int frame_len = mad->stream.next_frame - mad->stream.this_frame;
1478         mad->check_for_xing = FALSE;
1480         /* Assume Xing headers can only be the first frame in a mp3 file */
1481         if (mpg123_parse_xing_header (&mad->frame.header,
1482                 mad->stream.this_frame, frame_len, &bitrate, &time)) {
1483           mad->xing_found = TRUE;
1484           list = gst_tag_list_new ();
1485           gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
1486               GST_TAG_DURATION, (gint64) time * 1000 * 1000 * 1000,
1487               GST_TAG_BITRATE, bitrate, NULL);
1488           gst_element_post_message (GST_ELEMENT (mad),
1489               gst_message_new_tag (GST_OBJECT (mad), gst_tag_list_copy (list)));
1491           if (mad->need_newsegment)
1492             mad->pending_events =
1493                 g_list_append (mad->pending_events, gst_event_new_tag (list));
1494           else
1495             gst_pad_push_event (mad->srcpad, gst_event_new_tag (list));
1497           goto next_no_samples;
1498         }
1499       }
1501       /* if we're not resyncing/in error, check if caps need to be set again */
1502       if (!mad->in_error)
1503         gst_mad_check_caps_reset (mad);
1504       nsamples = MAD_NSBSAMPLES (&mad->frame.header) *
1505           (mad->stream.options & MAD_OPTION_HALFSAMPLERATE ? 16 : 32);
1507       if (mad->rate == 0) {
1508         g_warning ("mad->rate is 0; timestamps cannot be calculated");
1509       } else {
1510         /* if we have a pending timestamp, we can use it now to calculate the sample offset */
1511         if (GST_CLOCK_TIME_IS_VALID (mad->last_ts)) {
1512           GstFormat format = GST_FORMAT_DEFAULT;
1513           gint64 total;
1515           /* Convert incoming timestamp to a number of encoded samples */
1516           gst_pad_query_convert (mad->srcpad, GST_FORMAT_TIME, mad->last_ts,
1517               &format, &total);
1519           GST_DEBUG_OBJECT (mad, "calculated samples offset from ts is %"
1520               G_GUINT64_FORMAT " accumulated samples offset is %"
1521               G_GUINT64_FORMAT, total, mad->total_samples);
1523           /* We are using the incoming timestamps to generate the outgoing ones
1524            * if available. However some muxing formats are not precise enough
1525            * to allow us to generate a perfect stream. When converting the 
1526            * timestamp to a number of encoded samples so far we are introducing
1527            * a lot of potential error compared to our accumulated number of 
1528            * samples encoded. If the difference between those 2 numbers is 
1529            * bigger than half a frame we then use the incoming timestamp 
1530            * as a reference, otherwise we continue using our accumulated samples
1531            * counter */
1532           if (ABS (mad->total_samples - total) > nsamples / 2) {
1533             GST_DEBUG_OBJECT (mad, "difference is bigger than half a frame, "
1534                 "using calculated samples offset %" G_GUINT64_FORMAT, total);
1535             /* Override our accumulated samples counter */
1536             mad->total_samples = total;
1537             /* We use that timestamp directly */
1538             time_offset = mad->last_ts;
1539           }
1541           mad->last_ts = GST_CLOCK_TIME_NONE;
1542         }
1544         if (!GST_CLOCK_TIME_IS_VALID (time_offset)) {
1545           time_offset = gst_util_uint64_scale_int (mad->total_samples,
1546               GST_SECOND, mad->rate);
1547         }
1548         /* Duration is next timestamp - this one to generate a continuous
1549          * stream */
1550         time_duration =
1551             gst_util_uint64_scale_int (mad->total_samples + nsamples,
1552             GST_SECOND, mad->rate) - time_offset;
1553       }
1555 #ifndef GST_DISABLE_INDEX
1556       if (mad->index) {
1557         guint64 x_bytes = mad->base_byte_offset + mad->bytes_consumed;
1559         gst_index_add_association (mad->index, mad->index_id, 0,
1560             GST_FORMAT_BYTES, x_bytes, GST_FORMAT_TIME, time_offset, NULL);
1561       }
1562 #endif
1564       if (mad->segment_start <= (time_offset ==
1565               GST_CLOCK_TIME_NONE ? 0 : time_offset)) {
1567         /* for sample accurate seeking, calculate how many samples
1568            to skip and send the remaining pcm samples */
1570         GstBuffer *outbuffer = NULL;
1571         gint32 *outdata;
1572         mad_fixed_t const *left_ch, *right_ch;
1574         if (mad->need_newsegment) {
1575           gint64 start = time_offset;
1577           GST_DEBUG ("Sending NEWSEGMENT event, start=%" GST_TIME_FORMAT,
1578               GST_TIME_ARGS (start));
1580           gst_segment_set_newsegment (&mad->segment, FALSE, 1.0,
1581               GST_FORMAT_TIME, start, GST_CLOCK_TIME_NONE, start);
1583           gst_pad_push_event (mad->srcpad,
1584               gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
1585                   start, GST_CLOCK_TIME_NONE, start));
1586           mad->need_newsegment = FALSE;
1587         }
1589         if (mad->pending_events) {
1590           GList *l;
1592           for (l = mad->pending_events; l != NULL; l = l->next) {
1593             gst_pad_push_event (mad->srcpad, GST_EVENT (l->data));
1594           }
1595           g_list_free (mad->pending_events);
1596           mad->pending_events = NULL;
1597         }
1599         /* will attach the caps to the buffer */
1600         result =
1601             gst_pad_alloc_buffer_and_set_caps (mad->srcpad, 0,
1602             nsamples * mad->channels * 4, GST_PAD_CAPS (mad->srcpad),
1603             &outbuffer);
1604         if (result != GST_FLOW_OK) {
1605           /* Head for the exit, dropping samples as we go */
1606           GST_LOG ("Skipping frame synthesis due to pad_alloc return value");
1607           goto_exit = TRUE;
1608           goto skip_frame;
1609         }
1611         mad_synth_frame (&mad->synth, &mad->frame);
1612         left_ch = mad->synth.pcm.samples[0];
1613         right_ch = mad->synth.pcm.samples[1];
1615         outdata = (gint32 *) GST_BUFFER_DATA (outbuffer);
1617         GST_DEBUG ("mad out timestamp %" GST_TIME_FORMAT " dur: %"
1618             GST_TIME_FORMAT, GST_TIME_ARGS (time_offset),
1619             GST_TIME_ARGS (time_duration));
1621         GST_BUFFER_TIMESTAMP (outbuffer) = time_offset;
1622         GST_BUFFER_DURATION (outbuffer) = time_duration;
1623         GST_BUFFER_OFFSET (outbuffer) = mad->total_samples;
1624         GST_BUFFER_OFFSET_END (outbuffer) = mad->total_samples + nsamples;
1626         /* output sample(s) in 16-bit signed native-endian PCM */
1627         if (mad->channels == 1) {
1628           gint count = nsamples;
1630           while (count--) {
1631             *outdata++ = scale (*left_ch++) & 0xffffffff;
1632           }
1633         } else {
1634           gint count = nsamples;
1636           while (count--) {
1637             *outdata++ = scale (*left_ch++) & 0xffffffff;
1638             *outdata++ = scale (*right_ch++) & 0xffffffff;
1639           }
1640         }
1642         if ((outbuffer = gst_audio_buffer_clip (outbuffer, &mad->segment,
1643                     mad->rate, 4 * mad->channels))) {
1644           GST_LOG_OBJECT (mad,
1645               "pushing buffer, off=%" G_GUINT64_FORMAT ", ts=%" GST_TIME_FORMAT,
1646               GST_BUFFER_OFFSET (outbuffer),
1647               GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuffer)));
1649           /* apply discont */
1650           if (mad->discont) {
1651             GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_DISCONT);
1652             mad->discont = FALSE;
1653           }
1655           mad->segment.last_stop = GST_BUFFER_TIMESTAMP (outbuffer);
1656           result = gst_pad_push (mad->srcpad, outbuffer);
1657           if (result != GST_FLOW_OK) {
1658             /* Head for the exit, dropping samples as we go */
1659             goto_exit = TRUE;
1660           }
1661         } else {
1662           GST_LOG_OBJECT (mad, "Dropping buffer");
1663         }
1664       }
1666     skip_frame:
1667       mad->total_samples += nsamples;
1669       /* we have a queued timestamp on the incoming buffer that we should
1670        * use for the next frame */
1671       if (new_pts && (mad->stream.next_frame - mad_input_buffer >= tempsize)) {
1672         new_pts = FALSE;
1673         mad->last_ts = timestamp;
1674         mad->base_byte_offset = GST_BUFFER_OFFSET (buffer);
1675         mad->bytes_consumed = 0;
1676       }
1677       tempsize = 0;
1678       if (discont) {
1679         mad->discont = TRUE;
1680         discont = FALSE;
1681       }
1683       if (gst_mad_check_restart (mad)) {
1684         goto end;
1685       }
1687     next_no_samples:
1688       /* figure out how many bytes mad consumed */
1689       /* if consumed is already set, it's from the resync higher up, so
1690          we need to use that value instead.  Otherwise, recalculate from
1691          mad's consumption */
1692       if (consumed == 0)
1693         consumed = mad->stream.next_frame - mad_input_buffer;
1695       GST_LOG ("mad consumed %d bytes", consumed);
1696       /* move out pointer to where mad want the next data */
1697       mad_input_buffer += consumed;
1698       mad->tempsize -= consumed;
1699       mad->bytes_consumed += consumed;
1700       if (goto_exit == TRUE)
1701         goto end;
1702     }
1703     /* we only get here from breaks, tempsize never actually drops below 0 */
1704     memmove (mad->tempbuffer, mad_input_buffer, mad->tempsize);
1705   }
1706   result = GST_FLOW_OK;
1708 end:
1709   gst_buffer_unref (buffer);
1711   return result;
1714 static GstStateChangeReturn
1715 gst_mad_change_state (GstElement * element, GstStateChange transition)
1717   GstMad *mad;
1718   GstStateChangeReturn ret;
1720   mad = GST_MAD (element);
1722   switch (transition) {
1723     case GST_STATE_CHANGE_NULL_TO_READY:
1724       break;
1725     case GST_STATE_CHANGE_READY_TO_PAUSED:
1726     {
1727       guint options = 0;
1729       mad_stream_init (&mad->stream);
1730       mad_frame_init (&mad->frame);
1731       mad_synth_init (&mad->synth);
1732       mad->tempsize = 0;
1733       mad->discont = TRUE;
1734       mad->total_samples = 0;
1735       mad->rate = 0;
1736       mad->channels = 0;
1737       mad->caps_set = FALSE;
1738       mad->times_pending = mad->pending_rate = mad->pending_channels = 0;
1739       mad->vbr_average = 0;
1740       gst_segment_init (&mad->segment, GST_FORMAT_TIME);
1741       mad->new_header = TRUE;
1742       mad->framed = FALSE;
1743       mad->framecount = 0;
1744       mad->vbr_rate = 0;
1745       mad->frame.header.samplerate = 0;
1746       mad->last_ts = GST_CLOCK_TIME_NONE;
1747       if (mad->ignore_crc)
1748         options |= MAD_OPTION_IGNORECRC;
1749       if (mad->half)
1750         options |= MAD_OPTION_HALFSAMPLERATE;
1751       mad_stream_options (&mad->stream, options);
1752       break;
1753     }
1754     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1755       break;
1756     default:
1757       break;
1758   }
1760   ret = parent_class->change_state (element, transition);
1762   switch (transition) {
1763     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1764       break;
1765     case GST_STATE_CHANGE_PAUSED_TO_READY:
1766       mad_synth_finish (&mad->synth);
1767       mad_frame_finish (&mad->frame);
1768       mad_stream_finish (&mad->stream);
1769       mad->restart = TRUE;
1770       mad->check_for_xing = TRUE;
1771       if (mad->tags) {
1772         gst_tag_list_free (mad->tags);
1773         mad->tags = NULL;
1774       }
1775       break;
1776     case GST_STATE_CHANGE_READY_TO_NULL:
1777       break;
1778     default:
1779       break;
1780   }
1781   return ret;
1784 /* id3 tag helper (FIXME: why does mad parse id3 tags at all? It shouldn't) */
1785 static GstTagList *
1786 gst_mad_id3_to_tag_list (const struct id3_tag *tag)
1788   const struct id3_frame *frame;
1789   const id3_ucs4_t *ucs4;
1790   id3_utf8_t *utf8;
1791   GstTagList *tag_list;
1792   GType tag_type;
1793   guint i = 0;
1795   tag_list = gst_tag_list_new ();
1797   while ((frame = id3_tag_findframe (tag, NULL, i++)) != NULL) {
1798     const union id3_field *field;
1799     unsigned int nstrings, j;
1800     const gchar *tag_name;
1802     /* find me the function to query the frame id */
1803     gchar *id = g_strndup (frame->id, 5);
1805     tag_name = gst_tag_from_id3_tag (id);
1806     if (tag_name == NULL) {
1807       g_free (id);
1808       continue;
1809     }
1811     if (strcmp (id, "COMM") == 0) {
1812       if (frame->nfields < 4)
1813         continue;
1815       ucs4 = id3_field_getfullstring (&frame->fields[3]);
1816       g_assert (ucs4);
1818       utf8 = id3_ucs4_utf8duplicate (ucs4);
1819       if (utf8 == 0)
1820         continue;
1822       if (!g_utf8_validate ((char *) utf8, -1, NULL)) {
1823         GST_ERROR ("converted string is not valid utf-8");
1824         g_free (utf8);
1825         continue;
1826       }
1828       gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1829           GST_TAG_COMMENT, utf8, NULL);
1831       g_free (utf8);
1832       continue;
1833     }
1835     if (frame->nfields < 2)
1836       continue;
1838     field = &frame->fields[1];
1839     nstrings = id3_field_getnstrings (field);
1841     for (j = 0; j < nstrings; ++j) {
1842       ucs4 = id3_field_getstrings (field, j);
1843       g_assert (ucs4);
1845       if (strcmp (id, ID3_FRAME_GENRE) == 0)
1846         ucs4 = id3_genre_name (ucs4);
1848       utf8 = id3_ucs4_utf8duplicate (ucs4);
1849       if (utf8 == 0)
1850         continue;
1852       if (!g_utf8_validate ((char *) utf8, -1, NULL)) {
1853         GST_ERROR ("converted string is not valid utf-8");
1854         free (utf8);
1855         continue;
1856       }
1858       tag_type = gst_tag_get_type (tag_name);
1860       /* be sure to add non-string tags here */
1861       switch (tag_type) {
1862         case G_TYPE_UINT:
1863         {
1864           guint tmp;
1865           gchar *check;
1867           tmp = strtoul ((char *) utf8, &check, 10);
1869           if (strcmp (tag_name, GST_TAG_DATE) == 0) {
1870             GDate *d;
1872             if (*check != '\0')
1873               break;
1874             if (tmp == 0)
1875               break;
1876             d = g_date_new_dmy (1, 1, tmp);
1877             tmp = g_date_get_julian (d);
1878             g_date_free (d);
1879           } else if (strcmp (tag_name, GST_TAG_TRACK_NUMBER) == 0) {
1880             if (*check == '/') {
1881               guint total;
1883               check++;
1884               total = strtoul (check, &check, 10);
1885               if (*check != '\0')
1886                 break;
1888               gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1889                   GST_TAG_TRACK_COUNT, total, NULL);
1890             }
1891           } else if (strcmp (tag_name, GST_TAG_ALBUM_VOLUME_NUMBER) == 0) {
1892             if (*check == '/') {
1893               guint total;
1895               check++;
1896               total = strtoul (check, &check, 10);
1897               if (*check != '\0')
1898                 break;
1900               gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1901                   GST_TAG_ALBUM_VOLUME_COUNT, total, NULL);
1902             }
1903           }
1905           if (*check != '\0')
1906             break;
1907           gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, tmp,
1908               NULL);
1909           break;
1910         }
1911         case G_TYPE_UINT64:
1912         {
1913           guint64 tmp;
1915           g_assert (strcmp (tag_name, GST_TAG_DURATION) == 0);
1916           tmp = strtoul ((char *) utf8, NULL, 10);
1917           if (tmp == 0) {
1918             break;
1919           }
1920           gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1921               GST_TAG_DURATION, tmp * 1000 * 1000, NULL);
1922           break;
1923         }
1924         case G_TYPE_STRING:{
1925           gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
1926               tag_name, (const gchar *) utf8, NULL);
1927           break;
1928         }
1929           /* handles GST_TYPE_DATE and anything else */
1930         default:{
1931           GValue src = { 0, };
1932           GValue dest = { 0, };
1934           g_value_init (&src, G_TYPE_STRING);
1935           g_value_set_string (&src, (const gchar *) utf8);
1937           g_value_init (&dest, tag_type);
1938           if (g_value_transform (&src, &dest)) {
1939             gst_tag_list_add_values (tag_list, GST_TAG_MERGE_APPEND,
1940                 tag_name, &dest, NULL);
1941           } else {
1942             GST_WARNING ("Failed to transform tag from string to type '%s'",
1943                 g_type_name (tag_type));
1944           }
1945           g_value_unset (&src);
1946           g_value_unset (&dest);
1947           break;
1948         }
1949       }
1950       free (utf8);
1951     }
1952     g_free (id);
1953   }
1955   return tag_list;
1958 /* plugin initialisation */
1960 static gboolean
1961 plugin_init (GstPlugin * plugin)
1963   GST_DEBUG_CATEGORY_INIT (mad_debug, "mad", 0, "mad mp3 decoding");
1965   return gst_element_register (plugin, "mad", GST_RANK_SECONDARY,
1966       gst_mad_get_type ());
1969 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1970     GST_VERSION_MINOR,
1971     "mad",
1972     "mp3 decoding based on the mad library",
1973     plugin_init, VERSION, "GPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);