tizen 2.0 init
[framework/multimedia/gst-plugins-good0.10.git] / gst / audioparsers / gstmpegaudioparse.c
1 /* GStreamer MPEG audio parser
2  * Copyright (C) 2006-2007 Jan Schmidt <thaytan@mad.scientist.com>
3  * Copyright (C) 2010 Mark Nauwelaerts <mnauw users sf net>
4  * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5  *   Contact: Stefan Kost <stefan.kost@nokia.com>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 /**
23  * SECTION:element-mpegaudioparse
24  * @short_description: MPEG audio parser
25  * @see_also: #GstAmrParse, #GstAACParse
26  *
27  * Parses and frames mpeg1 audio streams. Provides seeking.
28  *
29  * <refsect2>
30  * <title>Example launch line</title>
31  * |[
32  * gst-launch filesrc location=test.mp3 ! mpegaudioparse ! mad ! autoaudiosink
33  * ]|
34  * </refsect2>
35  */
36
37 /* FIXME: we should make the base class (GstBaseParse) aware of the
38  * XING seek table somehow, so it can use it properly for things like
39  * accurate seeks. Currently it can only do a lookup via the convert function,
40  * but then doesn't know what the result represents exactly. One could either
41  * add a vfunc for index lookup, or just make mpegaudioparse populate the
42  * base class's index via the API provided.
43  */
44 #ifdef HAVE_CONFIG_H
45 #include "config.h"
46 #endif
47
48 #include <string.h>
49
50 #include "gstmpegaudioparse.h"
51 #include <gst/base/gstbytereader.h>
52
53 GST_DEBUG_CATEGORY_STATIC (mpeg_audio_parse_debug);
54 #define GST_CAT_DEFAULT mpeg_audio_parse_debug
55
56 #define MPEG_AUDIO_CHANNEL_MODE_UNKNOWN -1
57 #define MPEG_AUDIO_CHANNEL_MODE_STEREO 0
58 #define MPEG_AUDIO_CHANNEL_MODE_JOINT_STEREO 1
59 #define MPEG_AUDIO_CHANNEL_MODE_DUAL_CHANNEL 2
60 #define MPEG_AUDIO_CHANNEL_MODE_MONO 3
61
62 #define CRC_UNKNOWN -1
63 #define CRC_PROTECTED 0
64 #define CRC_NOT_PROTECTED 1
65
66 #define XING_FRAMES_FLAG     0x0001
67 #define XING_BYTES_FLAG      0x0002
68 #define XING_TOC_FLAG        0x0004
69 #define XING_VBR_SCALE_FLAG  0x0008
70
71 #define MIN_FRAME_SIZE       6
72
73 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
74     GST_PAD_SRC,
75     GST_PAD_ALWAYS,
76     GST_STATIC_CAPS ("audio/mpeg, "
77         "mpegversion = (int) 1, "
78         "layer = (int) [ 1, 3 ], "
79         "mpegaudioversion = (int) [ 1, 3], "
80         "rate = (int) [ 8000, 48000 ], "
81         "channels = (int) [ 1, 2 ], " "parsed=(boolean) true")
82     );
83
84 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
85     GST_PAD_SINK,
86     GST_PAD_ALWAYS,
87     GST_STATIC_CAPS ("audio/mpeg, mpegversion = (int) 1")
88     );
89
90 static void gst_mpeg_audio_parse_finalize (GObject * object);
91
92 static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse);
93 static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
94 static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
95     GstBaseParseFrame * frame, guint * size, gint * skipsize);
96 static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
97     GstBaseParseFrame * frame);
98 static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
99     GstBaseParseFrame * frame);
100 static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
101     GstFormat src_format, gint64 src_value,
102     GstFormat dest_format, gint64 * dest_value);
103 static GstCaps *gst_mpeg_audio_parse_get_sink_caps (GstBaseParse * parse);
104
105 GST_BOILERPLATE (GstMpegAudioParse, gst_mpeg_audio_parse, GstBaseParse,
106     GST_TYPE_BASE_PARSE);
107
108 #define GST_TYPE_MPEG_AUDIO_CHANNEL_MODE  \
109     (gst_mpeg_audio_channel_mode_get_type())
110
111 static const GEnumValue mpeg_audio_channel_mode[] = {
112   {MPEG_AUDIO_CHANNEL_MODE_UNKNOWN, "Unknown", "unknown"},
113   {MPEG_AUDIO_CHANNEL_MODE_MONO, "Mono", "mono"},
114   {MPEG_AUDIO_CHANNEL_MODE_DUAL_CHANNEL, "Dual Channel", "dual-channel"},
115   {MPEG_AUDIO_CHANNEL_MODE_JOINT_STEREO, "Joint Stereo", "joint-stereo"},
116   {MPEG_AUDIO_CHANNEL_MODE_STEREO, "Stereo", "stereo"},
117   {0, NULL, NULL},
118 };
119
120 static GType
121 gst_mpeg_audio_channel_mode_get_type (void)
122 {
123   static GType mpeg_audio_channel_mode_type = 0;
124
125   if (!mpeg_audio_channel_mode_type) {
126     mpeg_audio_channel_mode_type =
127         g_enum_register_static ("GstMpegAudioChannelMode",
128         mpeg_audio_channel_mode);
129   }
130   return mpeg_audio_channel_mode_type;
131 }
132
133 static const gchar *
134 gst_mpeg_audio_channel_mode_get_nick (gint mode)
135 {
136   guint i;
137   for (i = 0; i < G_N_ELEMENTS (mpeg_audio_channel_mode); i++) {
138     if (mpeg_audio_channel_mode[i].value == mode)
139       return mpeg_audio_channel_mode[i].value_nick;
140   }
141   return NULL;
142 }
143
144 static void
145 gst_mpeg_audio_parse_base_init (gpointer klass)
146 {
147   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
148
149   gst_element_class_add_static_pad_template (element_class,
150       &sink_template);
151   gst_element_class_add_static_pad_template (element_class, &src_template);
152
153   gst_element_class_set_details_simple (element_class, "MPEG1 Audio Parser",
154       "Codec/Parser/Audio",
155       "Parses and frames mpeg1 audio streams (levels 1-3), provides seek",
156       "Jan Schmidt <thaytan@mad.scientist.com>,"
157       "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
158 }
159
160 static void
161 gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
162 {
163   GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
164   GObjectClass *object_class = G_OBJECT_CLASS (klass);
165
166   GST_DEBUG_CATEGORY_INIT (mpeg_audio_parse_debug, "mpegaudioparse", 0,
167       "MPEG1 audio stream parser");
168
169   object_class->finalize = gst_mpeg_audio_parse_finalize;
170
171   parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_start);
172   parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
173   parse_class->check_valid_frame =
174       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame);
175   parse_class->parse_frame =
176       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
177   parse_class->pre_push_frame =
178       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame);
179   parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert);
180   parse_class->get_sink_caps =
181       GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_get_sink_caps);
182
183   /* register tags */
184 #define GST_TAG_CRC      "has-crc"
185 #define GST_TAG_MODE     "channel-mode"
186
187   gst_tag_register (GST_TAG_CRC, GST_TAG_FLAG_META, G_TYPE_BOOLEAN,
188       "has crc", "Using CRC", NULL);
189   gst_tag_register (GST_TAG_MODE, GST_TAG_FLAG_ENCODED, G_TYPE_STRING,
190       "channel mode", "MPEG audio channel mode", NULL);
191
192   g_type_class_ref (GST_TYPE_MPEG_AUDIO_CHANNEL_MODE);
193 }
194
195 static void
196 gst_mpeg_audio_parse_reset (GstMpegAudioParse * mp3parse)
197 {
198   mp3parse->channels = -1;
199   mp3parse->rate = -1;
200   mp3parse->sent_codec_tag = FALSE;
201   mp3parse->last_posted_crc = CRC_UNKNOWN;
202   mp3parse->last_posted_channel_mode = MPEG_AUDIO_CHANNEL_MODE_UNKNOWN;
203
204   mp3parse->hdr_bitrate = 0;
205
206   mp3parse->xing_flags = 0;
207   mp3parse->xing_bitrate = 0;
208   mp3parse->xing_frames = 0;
209   mp3parse->xing_total_time = 0;
210   mp3parse->xing_bytes = 0;
211   mp3parse->xing_vbr_scale = 0;
212   memset (mp3parse->xing_seek_table, 0, 100);
213   memset (mp3parse->xing_seek_table_inverse, 0, 256);
214
215   mp3parse->vbri_bitrate = 0;
216   mp3parse->vbri_frames = 0;
217   mp3parse->vbri_total_time = 0;
218   mp3parse->vbri_bytes = 0;
219   mp3parse->vbri_seek_points = 0;
220   g_free (mp3parse->vbri_seek_table);
221   mp3parse->vbri_seek_table = NULL;
222
223   mp3parse->encoder_delay = 0;
224   mp3parse->encoder_padding = 0;
225 }
226
227 static void
228 gst_mpeg_audio_parse_init (GstMpegAudioParse * mp3parse,
229     GstMpegAudioParseClass * klass)
230 {
231   gst_mpeg_audio_parse_reset (mp3parse);
232 }
233
234 static void
235 gst_mpeg_audio_parse_finalize (GObject * object)
236 {
237   G_OBJECT_CLASS (parent_class)->finalize (object);
238 }
239
240 static gboolean
241 gst_mpeg_audio_parse_start (GstBaseParse * parse)
242 {
243   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
244
245   gst_base_parse_set_min_frame_size (GST_BASE_PARSE (mp3parse), MIN_FRAME_SIZE);
246   GST_DEBUG_OBJECT (parse, "starting");
247
248   gst_mpeg_audio_parse_reset (mp3parse);
249
250   return TRUE;
251 }
252
253 static gboolean
254 gst_mpeg_audio_parse_stop (GstBaseParse * parse)
255 {
256   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
257
258   GST_DEBUG_OBJECT (parse, "stopping");
259
260   gst_mpeg_audio_parse_reset (mp3parse);
261
262   return TRUE;
263 }
264
265 static const guint mp3types_bitrates[2][3][16] = {
266   {
267         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
268         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
269         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
270       },
271   {
272         {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
273         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
274         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
275       },
276 };
277
278 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
279 {22050, 24000, 16000},
280 {11025, 12000, 8000}
281 };
282
283 static inline guint
284 mp3_type_frame_length_from_header (GstMpegAudioParse * mp3parse, guint32 header,
285     guint * put_version, guint * put_layer, guint * put_channels,
286     guint * put_bitrate, guint * put_samplerate, guint * put_mode,
287     guint * put_crc)
288 {
289   guint length;
290   gulong mode, samplerate, bitrate, layer, channels, padding, crc;
291   gulong version;
292   gint lsf, mpg25;
293
294   if (header & (1 << 20)) {
295     lsf = (header & (1 << 19)) ? 0 : 1;
296     mpg25 = 0;
297   } else {
298     lsf = 1;
299     mpg25 = 1;
300   }
301
302   version = 1 + lsf + mpg25;
303
304   layer = 4 - ((header >> 17) & 0x3);
305
306   crc = (header >> 16) & 0x1;
307
308   bitrate = (header >> 12) & 0xF;
309   bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
310   /* The caller has ensured we have a valid header, so bitrate can't be
311      zero here. */
312   g_assert (bitrate != 0);
313
314   samplerate = (header >> 10) & 0x3;
315   samplerate = mp3types_freqs[lsf + mpg25][samplerate];
316
317   padding = (header >> 9) & 0x1;
318
319   mode = (header >> 6) & 0x3;
320   channels = (mode == 3) ? 1 : 2;
321
322   switch (layer) {
323     case 1:
324       length = 4 * ((bitrate * 12) / samplerate + padding);
325       break;
326     case 2:
327       length = (bitrate * 144) / samplerate + padding;
328       break;
329     default:
330     case 3:
331       length = (bitrate * 144) / (samplerate << lsf) + padding;
332       break;
333   }
334
335   GST_DEBUG_OBJECT (mp3parse, "Calculated mp3 frame length of %u bytes",
336       length);
337   GST_DEBUG_OBJECT (mp3parse, "samplerate = %lu, bitrate = %lu, version = %lu, "
338       "layer = %lu, channels = %lu, mode = %s", samplerate, bitrate, version,
339       layer, channels, gst_mpeg_audio_channel_mode_get_nick (mode));
340
341   if (put_version)
342     *put_version = version;
343   if (put_layer)
344     *put_layer = layer;
345   if (put_channels)
346     *put_channels = channels;
347   if (put_bitrate)
348     *put_bitrate = bitrate;
349   if (put_samplerate)
350     *put_samplerate = samplerate;
351   if (put_mode)
352     *put_mode = mode;
353   if (put_crc)
354     *put_crc = crc;
355
356   return length;
357 }
358
359 /* Minimum number of consecutive, valid-looking frames to consider
360  * for resyncing */
361 #define MIN_RESYNC_FRAMES 3
362
363 /* Perform extended validation to check that subsequent headers match
364  * the first header given here in important characteristics, to avoid
365  * false sync. We look for a minimum of MIN_RESYNC_FRAMES consecutive
366  * frames to match their major characteristics.
367  *
368  * If at_eos is set to TRUE, we just check that we don't find any invalid
369  * frames in whatever data is available, rather than requiring a full
370  * MIN_RESYNC_FRAMES of data.
371  *
372  * Returns TRUE if we've seen enough data to validate or reject the frame.
373  * If TRUE is returned, then *valid contains TRUE if it validated, or false
374  * if we decided it was false sync.
375  * If FALSE is returned, then *valid contains minimum needed data.
376  */
377 static gboolean
378 gst_mp3parse_validate_extended (GstMpegAudioParse * mp3parse, GstBuffer * buf,
379     guint32 header, int bpf, gboolean at_eos, gint * valid)
380 {
381   guint32 next_header;
382   const guint8 *data;
383   guint available;
384   int frames_found = 1;
385   int offset = bpf;
386
387   available = GST_BUFFER_SIZE (buf);
388   data = GST_BUFFER_DATA (buf);
389
390   while (frames_found < MIN_RESYNC_FRAMES) {
391     /* Check if we have enough data for all these frames, plus the next
392        frame header. */
393     if (available < offset + 4) {
394       if (at_eos) {
395         /* Running out of data at EOS is fine; just accept it */
396         *valid = TRUE;
397         return TRUE;
398       } else {
399         *valid = offset + 4;
400         return FALSE;
401       }
402     }
403
404     next_header = GST_READ_UINT32_BE (data + offset);
405     GST_DEBUG_OBJECT (mp3parse, "At %d: header=%08X, header2=%08X, bpf=%d",
406         offset, (unsigned int) header, (unsigned int) next_header, bpf);
407
408 /* mask the bits which are allowed to differ between frames */
409 #define HDRMASK ~((0xF << 12)  /* bitrate */ | \
410                   (0x1 <<  9)  /* padding */ | \
411                   (0xf <<  4)  /* mode|mode extension */ | \
412                   (0xf))        /* copyright|emphasis */
413
414     if ((next_header & HDRMASK) != (header & HDRMASK)) {
415       /* If any of the unmasked bits don't match, then it's not valid */
416       GST_DEBUG_OBJECT (mp3parse, "next header doesn't match "
417           "(header=%08X (%08X), header2=%08X (%08X), bpf=%d)",
418           (guint) header, (guint) header & HDRMASK, (guint) next_header,
419           (guint) next_header & HDRMASK, bpf);
420       *valid = FALSE;
421       return TRUE;
422     } else if ((((next_header >> 12) & 0xf) == 0) ||
423         (((next_header >> 12) & 0xf) == 0xf)) {
424       /* The essential parts were the same, but the bitrate held an
425          invalid value - also reject */
426       GST_DEBUG_OBJECT (mp3parse, "next header invalid (bitrate)");
427       *valid = FALSE;
428       return TRUE;
429     }
430
431     bpf = mp3_type_frame_length_from_header (mp3parse, next_header,
432         NULL, NULL, NULL, NULL, NULL, NULL, NULL);
433
434     offset += bpf;
435     frames_found++;
436   }
437
438   *valid = TRUE;
439   return TRUE;
440 }
441
442 static gboolean
443 gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
444     unsigned long head)
445 {
446   GST_DEBUG_OBJECT (mp3parse, "checking mp3 header 0x%08lx", head);
447   /* if it's not a valid sync */
448   if ((head & 0xffe00000) != 0xffe00000) {
449     GST_WARNING_OBJECT (mp3parse, "invalid sync");
450     return FALSE;
451   }
452   /* if it's an invalid MPEG version */
453   if (((head >> 19) & 3) == 0x1) {
454     GST_WARNING_OBJECT (mp3parse, "invalid MPEG version: 0x%lx",
455         (head >> 19) & 3);
456     return FALSE;
457   }
458   /* if it's an invalid layer */
459   if (!((head >> 17) & 3)) {
460     GST_WARNING_OBJECT (mp3parse, "invalid layer: 0x%lx", (head >> 17) & 3);
461     return FALSE;
462   }
463   /* if it's an invalid bitrate */
464   if (((head >> 12) & 0xf) == 0x0) {
465     GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx."
466         "Free format files are not supported yet", (head >> 12) & 0xf);
467     return FALSE;
468   }
469   if (((head >> 12) & 0xf) == 0xf) {
470     GST_WARNING_OBJECT (mp3parse, "invalid bitrate: 0x%lx", (head >> 12) & 0xf);
471     return FALSE;
472   }
473   /* if it's an invalid samplerate */
474   if (((head >> 10) & 0x3) == 0x3) {
475     GST_WARNING_OBJECT (mp3parse, "invalid samplerate: 0x%lx",
476         (head >> 10) & 0x3);
477     return FALSE;
478   }
479
480   if ((head & 0x3) == 0x2) {
481     /* Ignore this as there are some files with emphasis 0x2 that can
482      * be played fine. See BGO #537235 */
483     GST_WARNING_OBJECT (mp3parse, "invalid emphasis: 0x%lx", head & 0x3);
484   }
485
486   return TRUE;
487 }
488
489 static gboolean
490 gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
491     GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
492 {
493   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
494   GstBuffer *buf = frame->buffer;
495   GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
496   gint off, bpf;
497   gboolean lost_sync, draining, valid, caps_change;
498   guint32 header;
499   guint bitrate, layer, rate, channels, version, mode, crc;
500
501   if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 6))
502     return FALSE;
503
504   off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffe00000, 0xffe00000,
505       0, GST_BUFFER_SIZE (buf));
506
507   GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
508
509   /* didn't find anything that looks like a sync word, skip */
510   if (off < 0) {
511     *skipsize = GST_BUFFER_SIZE (buf) - 3;
512     return FALSE;
513   }
514
515   /* possible frame header, but not at offset 0? skip bytes before sync */
516   if (off > 0) {
517     *skipsize = off;
518     return FALSE;
519   }
520
521   /* make sure the values in the frame header look sane */
522   header = GST_READ_UINT32_BE (GST_BUFFER_DATA (buf));
523   if (!gst_mpeg_audio_parse_head_check (mp3parse, header)) {
524     *skipsize = 1;
525     return FALSE;
526   }
527
528   GST_LOG_OBJECT (parse, "got frame");
529
530   bpf = mp3_type_frame_length_from_header (mp3parse, header,
531       &version, &layer, &channels, &bitrate, &rate, &mode, &crc);
532   g_assert (bpf != 0);
533
534   if (channels != mp3parse->channels || rate != mp3parse->rate ||
535       layer != mp3parse->layer || version != mp3parse->version)
536     caps_change = TRUE;
537   else
538     caps_change = FALSE;
539
540   lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
541   draining = GST_BASE_PARSE_DRAINING (parse);
542
543   if (!draining && (lost_sync || caps_change)) {
544     if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, draining,
545             &valid)) {
546       /* not enough data */
547       gst_base_parse_set_min_frame_size (parse, valid);
548       *skipsize = 0;
549       return FALSE;
550     } else {
551       if (!valid) {
552         *skipsize = off + 2;
553         return FALSE;
554       }
555     }
556   } else if (draining && lost_sync && caps_change && mp3parse->rate > 0) {
557     /* avoid caps jitter that we can't be sure of */
558     *skipsize = off + 2;
559     return FALSE;
560   }
561
562   /* restore default minimum */
563   gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
564
565   *framesize = bpf;
566   return TRUE;
567 }
568
569 static void
570 gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse,
571     GstBuffer * buf)
572 {
573   const guint32 xing_id = 0x58696e67;   /* 'Xing' in hex */
574   const guint32 info_id = 0x496e666f;   /* 'Info' in hex - found in LAME CBR files */
575   const guint32 vbri_id = 0x56425249;   /* 'VBRI' in hex */
576   const guint32 lame_id = 0x4c414d45;   /* 'LAME' in hex */
577   gint offset_xing, offset_vbri;
578   guint64 avail;
579   gint64 upstream_total_bytes = 0;
580   GstFormat fmt = GST_FORMAT_BYTES;
581   guint32 read_id_xing = 0, read_id_vbri = 0;
582   const guint8 *data;
583   guint bitrate;
584
585   if (mp3parse->sent_codec_tag)
586     return;
587
588   /* Check first frame for Xing info */
589   if (mp3parse->version == 1) { /* MPEG-1 file */
590     if (mp3parse->channels == 1)
591       offset_xing = 0x11;
592     else
593       offset_xing = 0x20;
594   } else {                      /* MPEG-2 header */
595     if (mp3parse->channels == 1)
596       offset_xing = 0x09;
597     else
598       offset_xing = 0x11;
599   }
600
601   /* The VBRI tag is always at offset 0x20 */
602   offset_vbri = 0x20;
603
604   /* Skip the 4 bytes of the MP3 header too */
605   offset_xing += 4;
606   offset_vbri += 4;
607
608   /* Check if we have enough data to read the Xing header */
609   avail = GST_BUFFER_SIZE (buf);
610   data = GST_BUFFER_DATA (buf);
611
612   if (avail >= offset_xing + 4) {
613     read_id_xing = GST_READ_UINT32_BE (data + offset_xing);
614   }
615   if (avail >= offset_vbri + 4) {
616     read_id_vbri = GST_READ_UINT32_BE (data + offset_vbri);
617   }
618
619   /* obtain real upstream total bytes */
620   fmt = GST_FORMAT_BYTES;
621   if (!gst_pad_query_peer_duration (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE
622               (mp3parse)), &fmt, &upstream_total_bytes))
623     upstream_total_bytes = 0;
624
625   if (read_id_xing == xing_id || read_id_xing == info_id) {
626     guint32 xing_flags;
627     guint bytes_needed = offset_xing + 8;
628     gint64 total_bytes;
629     GstClockTime total_time;
630
631     GST_DEBUG_OBJECT (mp3parse, "Found Xing header marker 0x%x", xing_id);
632
633     /* Move data after Xing header */
634     data += offset_xing + 4;
635
636     /* Read 4 base bytes of flags, big-endian */
637     xing_flags = GST_READ_UINT32_BE (data);
638     data += 4;
639     if (xing_flags & XING_FRAMES_FLAG)
640       bytes_needed += 4;
641     if (xing_flags & XING_BYTES_FLAG)
642       bytes_needed += 4;
643     if (xing_flags & XING_TOC_FLAG)
644       bytes_needed += 100;
645     if (xing_flags & XING_VBR_SCALE_FLAG)
646       bytes_needed += 4;
647     if (avail < bytes_needed) {
648       GST_DEBUG_OBJECT (mp3parse,
649           "Not enough data to read Xing header (need %d)", bytes_needed);
650       return;
651     }
652
653     GST_DEBUG_OBJECT (mp3parse, "Reading Xing header");
654     mp3parse->xing_flags = xing_flags;
655
656     if (xing_flags & XING_FRAMES_FLAG) {
657       mp3parse->xing_frames = GST_READ_UINT32_BE (data);
658       if (mp3parse->xing_frames == 0) {
659         GST_WARNING_OBJECT (mp3parse,
660             "Invalid number of frames in Xing header");
661         mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
662       } else {
663         mp3parse->xing_total_time = gst_util_uint64_scale (GST_SECOND,
664             (guint64) (mp3parse->xing_frames) * (mp3parse->spf),
665             mp3parse->rate);
666       }
667
668       data += 4;
669     } else {
670       mp3parse->xing_frames = 0;
671       mp3parse->xing_total_time = 0;
672     }
673
674     if (xing_flags & XING_BYTES_FLAG) {
675       mp3parse->xing_bytes = GST_READ_UINT32_BE (data);
676       if (mp3parse->xing_bytes == 0) {
677         GST_WARNING_OBJECT (mp3parse, "Invalid number of bytes in Xing header");
678         mp3parse->xing_flags &= ~XING_BYTES_FLAG;
679       }
680       data += 4;
681     } else {
682       mp3parse->xing_bytes = 0;
683     }
684
685     /* If we know the upstream size and duration, compute the
686      * total bitrate, rounded up to the nearest kbit/sec */
687     if ((total_time = mp3parse->xing_total_time) &&
688         (total_bytes = mp3parse->xing_bytes)) {
689       mp3parse->xing_bitrate = gst_util_uint64_scale (total_bytes,
690           8 * GST_SECOND, total_time);
691       mp3parse->xing_bitrate += 500;
692       mp3parse->xing_bitrate -= mp3parse->xing_bitrate % 1000;
693     }
694
695     if (xing_flags & XING_TOC_FLAG) {
696       int i, percent = 0;
697       guchar *table = mp3parse->xing_seek_table;
698       guchar old = 0, new;
699       guint first;
700
701       first = data[0];
702       GST_DEBUG_OBJECT (mp3parse,
703           "Subtracting initial offset of %d bytes from Xing TOC", first);
704
705       /* xing seek table: percent time -> 1/256 bytepos */
706       for (i = 0; i < 100; i++) {
707         new = data[i] - first;
708         if (old > new) {
709           GST_WARNING_OBJECT (mp3parse, "Skipping broken Xing TOC");
710           mp3parse->xing_flags &= ~XING_TOC_FLAG;
711           goto skip_toc;
712         }
713         mp3parse->xing_seek_table[i] = old = new;
714       }
715
716       /* build inverse table: 1/256 bytepos -> 1/100 percent time */
717       for (i = 0; i < 256; i++) {
718         while (percent < 99 && table[percent + 1] <= i)
719           percent++;
720
721         if (table[percent] == i) {
722           mp3parse->xing_seek_table_inverse[i] = percent * 100;
723         } else if (table[percent] < i && percent < 99) {
724           gdouble fa, fb, fx;
725           gint a = percent, b = percent + 1;
726
727           fa = table[a];
728           fb = table[b];
729           fx = (b - a) / (fb - fa) * (i - fa) + a;
730           mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
731         } else if (percent == 99) {
732           gdouble fa, fb, fx;
733           gint a = percent, b = 100;
734
735           fa = table[a];
736           fb = 256.0;
737           fx = (b - a) / (fb - fa) * (i - fa) + a;
738           mp3parse->xing_seek_table_inverse[i] = (guint16) (fx * 100);
739         }
740       }
741     skip_toc:
742       data += 100;
743     } else {
744       memset (mp3parse->xing_seek_table, 0, 100);
745       memset (mp3parse->xing_seek_table_inverse, 0, 256);
746     }
747
748     if (xing_flags & XING_VBR_SCALE_FLAG) {
749       mp3parse->xing_vbr_scale = GST_READ_UINT32_BE (data);
750       data += 4;
751     } else
752       mp3parse->xing_vbr_scale = 0;
753
754     GST_DEBUG_OBJECT (mp3parse, "Xing header reported %u frames, time %"
755         GST_TIME_FORMAT ", %u bytes, vbr scale %u", mp3parse->xing_frames,
756         GST_TIME_ARGS (mp3parse->xing_total_time), mp3parse->xing_bytes,
757         mp3parse->xing_vbr_scale);
758
759     /* check for truncated file */
760     if (upstream_total_bytes && mp3parse->xing_bytes &&
761         mp3parse->xing_bytes * 0.8 > upstream_total_bytes) {
762       GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
763           "invalidating Xing header duration and size");
764       mp3parse->xing_flags &= ~XING_BYTES_FLAG;
765       mp3parse->xing_flags &= ~XING_FRAMES_FLAG;
766     }
767
768     /* Optional LAME tag? */
769     if (avail - bytes_needed >= 36 && GST_READ_UINT32_BE (data) == lame_id) {
770       gchar lame_version[10] = { 0, };
771       guint tag_rev;
772       guint32 encoder_delay, encoder_padding;
773
774       memcpy (lame_version, data, 9);
775       data += 9;
776       tag_rev = data[0] >> 4;
777       GST_DEBUG_OBJECT (mp3parse, "Found LAME tag revision %d created by '%s'",
778           tag_rev, lame_version);
779
780       /* Skip all the information we're not interested in */
781       data += 12;
782       /* Encoder delay and end padding */
783       encoder_delay = GST_READ_UINT24_BE (data);
784       encoder_delay >>= 12;
785       encoder_padding = GST_READ_UINT24_BE (data);
786       encoder_padding &= 0x000fff;
787
788       mp3parse->encoder_delay = encoder_delay;
789       mp3parse->encoder_padding = encoder_padding;
790
791       GST_DEBUG_OBJECT (mp3parse, "Encoder delay %u, encoder padding %u",
792           encoder_delay, encoder_padding);
793     }
794   }
795
796   if (read_id_vbri == vbri_id) {
797     gint64 total_bytes, total_frames;
798     GstClockTime total_time;
799     guint16 nseek_points;
800
801     GST_DEBUG_OBJECT (mp3parse, "Found VBRI header marker 0x%x", vbri_id);
802
803     if (avail < offset_vbri + 26) {
804       GST_DEBUG_OBJECT (mp3parse,
805           "Not enough data to read VBRI header (need %d)", offset_vbri + 26);
806       return;
807     }
808
809     GST_DEBUG_OBJECT (mp3parse, "Reading VBRI header");
810
811     /* Move data after VBRI header */
812     data += offset_vbri + 4;
813
814     if (GST_READ_UINT16_BE (data) != 0x0001) {
815       GST_WARNING_OBJECT (mp3parse,
816           "Unsupported VBRI version 0x%x", GST_READ_UINT16_BE (data));
817       return;
818     }
819     data += 2;
820
821     /* Skip encoder delay */
822     data += 2;
823
824     /* Skip quality */
825     data += 2;
826
827     total_bytes = GST_READ_UINT32_BE (data);
828     if (total_bytes != 0)
829       mp3parse->vbri_bytes = total_bytes;
830     data += 4;
831
832     total_frames = GST_READ_UINT32_BE (data);
833     if (total_frames != 0) {
834       mp3parse->vbri_frames = total_frames;
835       mp3parse->vbri_total_time = gst_util_uint64_scale (GST_SECOND,
836           (guint64) (mp3parse->vbri_frames) * (mp3parse->spf), mp3parse->rate);
837     }
838     data += 4;
839
840     /* If we know the upstream size and duration, compute the
841      * total bitrate, rounded up to the nearest kbit/sec */
842     if ((total_time = mp3parse->vbri_total_time) &&
843         (total_bytes = mp3parse->vbri_bytes)) {
844       mp3parse->vbri_bitrate = gst_util_uint64_scale (total_bytes,
845           8 * GST_SECOND, total_time);
846       mp3parse->vbri_bitrate += 500;
847       mp3parse->vbri_bitrate -= mp3parse->vbri_bitrate % 1000;
848     }
849
850     nseek_points = GST_READ_UINT16_BE (data);
851     data += 2;
852
853     if (nseek_points > 0) {
854       guint scale, seek_bytes, seek_frames;
855       gint i;
856
857       mp3parse->vbri_seek_points = nseek_points;
858
859       scale = GST_READ_UINT16_BE (data);
860       data += 2;
861
862       seek_bytes = GST_READ_UINT16_BE (data);
863       data += 2;
864
865       seek_frames = GST_READ_UINT16_BE (data);
866
867       if (scale == 0 || seek_bytes == 0 || seek_bytes > 4 || seek_frames == 0) {
868         GST_WARNING_OBJECT (mp3parse, "Unsupported VBRI seek table");
869         goto out_vbri;
870       }
871
872       if (avail < offset_vbri + 26 + nseek_points * seek_bytes) {
873         GST_WARNING_OBJECT (mp3parse,
874             "Not enough data to read VBRI seek table (need %d)",
875             offset_vbri + 26 + nseek_points * seek_bytes);
876         goto out_vbri;
877       }
878
879       if (seek_frames * nseek_points < total_frames - seek_frames ||
880           seek_frames * nseek_points > total_frames + seek_frames) {
881         GST_WARNING_OBJECT (mp3parse,
882             "VBRI seek table doesn't cover the complete file");
883         goto out_vbri;
884       }
885
886       if (avail < offset_vbri + 26) {
887         GST_DEBUG_OBJECT (mp3parse,
888             "Not enough data to read VBRI header (need %d)",
889             offset_vbri + 26 + nseek_points * seek_bytes);
890         return;
891       }
892
893       data = GST_BUFFER_DATA (buf);
894       data += offset_vbri + 26;
895
896       /* VBRI seek table: frame/seek_frames -> byte */
897       mp3parse->vbri_seek_table = g_new (guint32, nseek_points);
898       if (seek_bytes == 4)
899         for (i = 0; i < nseek_points; i++) {
900           mp3parse->vbri_seek_table[i] = GST_READ_UINT32_BE (data) * scale;
901           data += 4;
902       } else if (seek_bytes == 3)
903         for (i = 0; i < nseek_points; i++) {
904           mp3parse->vbri_seek_table[i] = GST_READ_UINT24_BE (data) * scale;
905           data += 3;
906       } else if (seek_bytes == 2)
907         for (i = 0; i < nseek_points; i++) {
908           mp3parse->vbri_seek_table[i] = GST_READ_UINT16_BE (data) * scale;
909           data += 2;
910       } else                    /* seek_bytes == 1 */
911         for (i = 0; i < nseek_points; i++) {
912           mp3parse->vbri_seek_table[i] = GST_READ_UINT8 (data) * scale;
913           data += 1;
914         }
915     }
916   out_vbri:
917
918     GST_DEBUG_OBJECT (mp3parse, "VBRI header reported %u frames, time %"
919         GST_TIME_FORMAT ", bytes %u", mp3parse->vbri_frames,
920         GST_TIME_ARGS (mp3parse->vbri_total_time), mp3parse->vbri_bytes);
921
922     /* check for truncated file */
923     if (upstream_total_bytes && mp3parse->vbri_bytes &&
924         mp3parse->vbri_bytes * 0.8 > upstream_total_bytes) {
925       GST_WARNING_OBJECT (mp3parse, "File appears to have been truncated; "
926           "invalidating VBRI header duration and size");
927       mp3parse->vbri_valid = FALSE;
928     } else {
929       mp3parse->vbri_valid = TRUE;
930     }
931   } else {
932     GST_DEBUG_OBJECT (mp3parse,
933         "Xing, LAME or VBRI header not found in first frame");
934   }
935
936   /* set duration if tables provided a valid one */
937   if (mp3parse->xing_flags & XING_FRAMES_FLAG) {
938     gst_base_parse_set_duration (GST_BASE_PARSE (mp3parse), GST_FORMAT_TIME,
939         mp3parse->xing_total_time, 0);
940   }
941   if (mp3parse->vbri_total_time != 0 && mp3parse->vbri_valid) {
942     gst_base_parse_set_duration (GST_BASE_PARSE (mp3parse), GST_FORMAT_TIME,
943         mp3parse->vbri_total_time, 0);
944   }
945
946   /* tell baseclass how nicely we can seek, and a bitrate if one found */
947   /* FIXME: fill index with seek table */
948 #if 0
949   seekable = GST_BASE_PARSE_SEEK_DEFAULT;
950   if ((mp3parse->xing_flags & XING_TOC_FLAG) && mp3parse->xing_bytes &&
951       mp3parse->xing_total_time)
952     seekable = GST_BASE_PARSE_SEEK_TABLE;
953
954   if (mp3parse->vbri_seek_table && mp3parse->vbri_bytes &&
955       mp3parse->vbri_total_time)
956     seekable = GST_BASE_PARSE_SEEK_TABLE;
957 #endif
958
959   if (mp3parse->xing_bitrate)
960     bitrate = mp3parse->xing_bitrate;
961   else if (mp3parse->vbri_bitrate)
962     bitrate = mp3parse->vbri_bitrate;
963   else
964     bitrate = 0;
965
966   gst_base_parse_set_average_bitrate (GST_BASE_PARSE (mp3parse), bitrate);
967 }
968
969 static GstFlowReturn
970 gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
971     GstBaseParseFrame * frame)
972 {
973   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
974   GstBuffer *buf = frame->buffer;
975   guint bitrate, layer, rate, channels, version, mode, crc;
976
977   g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
978
979   if (!mp3_type_frame_length_from_header (mp3parse,
980           GST_READ_UINT32_BE (GST_BUFFER_DATA (buf)),
981           &version, &layer, &channels, &bitrate, &rate, &mode, &crc))
982     goto broken_header;
983
984   if (G_UNLIKELY (channels != mp3parse->channels || rate != mp3parse->rate ||
985           layer != mp3parse->layer || version != mp3parse->version)) {
986     GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
987         "mpegversion", G_TYPE_INT, 1,
988         "mpegaudioversion", G_TYPE_INT, version,
989         "layer", G_TYPE_INT, layer,
990         "rate", G_TYPE_INT, rate,
991         "channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
992     gst_buffer_set_caps (buf, caps);
993     gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
994     gst_caps_unref (caps);
995
996     mp3parse->rate = rate;
997     mp3parse->channels = channels;
998     mp3parse->layer = layer;
999     mp3parse->version = version;
1000
1001     /* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
1002     if (mp3parse->layer == 1)
1003       mp3parse->spf = 384;
1004     else if (mp3parse->layer == 2)
1005       mp3parse->spf = 1152;
1006     else if (mp3parse->version == 1) {
1007       mp3parse->spf = 1152;
1008     } else {
1009       /* MPEG-2 or "2.5" */
1010       mp3parse->spf = 576;
1011     }
1012
1013     /* lead_in:
1014      * We start pushing 9 frames earlier (29 frames for MPEG2) than
1015      * segment start to be able to decode the first frame we want.
1016      * 9 (29) frames are the theoretical maximum of frames that contain
1017      * data for the current frame (bit reservoir).
1018      *
1019      * lead_out:
1020      * Some mp3 streams have an offset in the timestamps, for which we have to
1021      * push the frame *after* the end position in order for the decoder to be
1022      * able to decode everything up until the segment.stop position. */
1023     gst_base_parse_set_frame_rate (parse, mp3parse->rate, mp3parse->spf,
1024         (version == 1) ? 10 : 30, 2);
1025   }
1026
1027   mp3parse->hdr_bitrate = bitrate;
1028
1029   /* For first frame; check for seek tables and output a codec tag */
1030   gst_mpeg_audio_parse_handle_first_frame (mp3parse, buf);
1031
1032   /* store some frame info for later processing */
1033   mp3parse->last_crc = crc;
1034   mp3parse->last_mode = mode;
1035
1036   return GST_FLOW_OK;
1037
1038 /* ERRORS */
1039 broken_header:
1040   {
1041     /* this really shouldn't ever happen */
1042     GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
1043     return GST_FLOW_ERROR;
1044   }
1045 }
1046
1047 static gboolean
1048 gst_mpeg_audio_parse_time_to_bytepos (GstMpegAudioParse * mp3parse,
1049     GstClockTime ts, gint64 * bytepos)
1050 {
1051   gint64 total_bytes;
1052   GstClockTime total_time;
1053
1054   /* If XING seek table exists use this for time->byte conversion */
1055   if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
1056       (total_bytes = mp3parse->xing_bytes) &&
1057       (total_time = mp3parse->xing_total_time)) {
1058     gdouble fa, fb, fx;
1059     gdouble percent =
1060         CLAMP ((100.0 * gst_util_guint64_to_gdouble (ts)) /
1061         gst_util_guint64_to_gdouble (total_time), 0.0, 100.0);
1062     gint index = CLAMP (percent, 0, 99);
1063
1064     fa = mp3parse->xing_seek_table[index];
1065     if (index < 99)
1066       fb = mp3parse->xing_seek_table[index + 1];
1067     else
1068       fb = 256.0;
1069
1070     fx = fa + (fb - fa) * (percent - index);
1071
1072     *bytepos = (1.0 / 256.0) * fx * total_bytes;
1073
1074     return TRUE;
1075   }
1076
1077   if (mp3parse->vbri_seek_table && (total_bytes = mp3parse->vbri_bytes) &&
1078       (total_time = mp3parse->vbri_total_time)) {
1079     gint i, j;
1080     gdouble a, b, fa, fb;
1081
1082     i = gst_util_uint64_scale (ts, mp3parse->vbri_seek_points - 1, total_time);
1083     i = CLAMP (i, 0, mp3parse->vbri_seek_points - 1);
1084
1085     a = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
1086             mp3parse->vbri_seek_points));
1087     fa = 0.0;
1088     for (j = i; j >= 0; j--)
1089       fa += mp3parse->vbri_seek_table[j];
1090
1091     if (i + 1 < mp3parse->vbri_seek_points) {
1092       b = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
1093               mp3parse->vbri_seek_points));
1094       fb = fa + mp3parse->vbri_seek_table[i + 1];
1095     } else {
1096       b = gst_guint64_to_gdouble (total_time);
1097       fb = total_bytes;
1098     }
1099
1100     *bytepos = fa + ((fb - fa) / (b - a)) * (gst_guint64_to_gdouble (ts) - a);
1101
1102     return TRUE;
1103   }
1104
1105   return FALSE;
1106 }
1107
1108 static gboolean
1109 gst_mpeg_audio_parse_bytepos_to_time (GstMpegAudioParse * mp3parse,
1110     gint64 bytepos, GstClockTime * ts)
1111 {
1112   gint64 total_bytes;
1113   GstClockTime total_time;
1114
1115   /* If XING seek table exists use this for byte->time conversion */
1116   if ((mp3parse->xing_flags & XING_TOC_FLAG) &&
1117       (total_bytes = mp3parse->xing_bytes) &&
1118       (total_time = mp3parse->xing_total_time)) {
1119     gdouble fa, fb, fx;
1120     gdouble pos;
1121     gint index;
1122
1123     pos = CLAMP ((bytepos * 256.0) / total_bytes, 0.0, 256.0);
1124     index = CLAMP (pos, 0, 255);
1125     fa = mp3parse->xing_seek_table_inverse[index];
1126     if (index < 255)
1127       fb = mp3parse->xing_seek_table_inverse[index + 1];
1128     else
1129       fb = 10000.0;
1130
1131     fx = fa + (fb - fa) * (pos - index);
1132
1133     *ts = (1.0 / 10000.0) * fx * gst_util_guint64_to_gdouble (total_time);
1134
1135     return TRUE;
1136   }
1137
1138   if (mp3parse->vbri_seek_table &&
1139       (total_bytes = mp3parse->vbri_bytes) &&
1140       (total_time = mp3parse->vbri_total_time)) {
1141     gint i = 0;
1142     guint64 sum = 0;
1143     gdouble a, b, fa, fb;
1144
1145     do {
1146       sum += mp3parse->vbri_seek_table[i];
1147       i++;
1148     } while (i + 1 < mp3parse->vbri_seek_points
1149         && sum + mp3parse->vbri_seek_table[i] < bytepos);
1150     i--;
1151
1152     a = gst_guint64_to_gdouble (sum);
1153     fa = gst_guint64_to_gdouble (gst_util_uint64_scale (i, total_time,
1154             mp3parse->vbri_seek_points));
1155
1156     if (i + 1 < mp3parse->vbri_seek_points) {
1157       b = a + mp3parse->vbri_seek_table[i + 1];
1158       fb = gst_guint64_to_gdouble (gst_util_uint64_scale (i + 1, total_time,
1159               mp3parse->vbri_seek_points));
1160     } else {
1161       b = total_bytes;
1162       fb = gst_guint64_to_gdouble (total_time);
1163     }
1164
1165     *ts = gst_gdouble_to_guint64 (fa + ((fb - fa) / (b - a)) * (bytepos - a));
1166
1167     return TRUE;
1168   }
1169
1170   return FALSE;
1171 }
1172
1173 static gboolean
1174 gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format,
1175     gint64 src_value, GstFormat dest_format, gint64 * dest_value)
1176 {
1177   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
1178   gboolean res = FALSE;
1179
1180   if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES)
1181     res =
1182         gst_mpeg_audio_parse_time_to_bytepos (mp3parse, src_value, dest_value);
1183   else if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME)
1184     res = gst_mpeg_audio_parse_bytepos_to_time (mp3parse, src_value,
1185         (GstClockTime *) dest_value);
1186
1187   /* if no tables, fall back to default estimated rate based conversion */
1188   if (!res)
1189     return gst_base_parse_convert_default (parse, src_format, src_value,
1190         dest_format, dest_value);
1191
1192   return res;
1193 }
1194
1195 static GstFlowReturn
1196 gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
1197     GstBaseParseFrame * frame)
1198 {
1199   GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
1200   GstTagList *taglist;
1201
1202   /* tag sending done late enough in hook to ensure pending events
1203    * have already been sent */
1204
1205   if (!mp3parse->sent_codec_tag) {
1206     gchar *codec;
1207
1208     /* codec tag */
1209     if (mp3parse->layer == 3) {
1210       codec = g_strdup_printf ("MPEG %d Audio, Layer %d (MP3)",
1211           mp3parse->version, mp3parse->layer);
1212     } else {
1213       codec = g_strdup_printf ("MPEG %d Audio, Layer %d",
1214           mp3parse->version, mp3parse->layer);
1215     }
1216     taglist = gst_tag_list_new ();
1217     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1218         GST_TAG_AUDIO_CODEC, codec, NULL);
1219     if (mp3parse->hdr_bitrate > 0 && mp3parse->xing_bitrate == 0 &&
1220         mp3parse->vbri_bitrate == 0) {
1221       /* We don't have a VBR bitrate, so post the available bitrate as
1222        * nominal and let baseparse calculate the real bitrate */
1223       gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
1224           GST_TAG_NOMINAL_BITRATE, mp3parse->hdr_bitrate, NULL);
1225     }
1226     gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
1227         GST_BASE_PARSE_SRC_PAD (mp3parse), taglist);
1228     g_free (codec);
1229
1230     /* also signals the end of first-frame processing */
1231     mp3parse->sent_codec_tag = TRUE;
1232   }
1233
1234   /* we will create a taglist (if any of the parameters has changed)
1235    * to add the tags that changed */
1236   taglist = NULL;
1237   if (mp3parse->last_posted_crc != mp3parse->last_crc) {
1238     gboolean using_crc;
1239
1240     if (!taglist) {
1241       taglist = gst_tag_list_new ();
1242     }
1243     mp3parse->last_posted_crc = mp3parse->last_crc;
1244     if (mp3parse->last_posted_crc == CRC_PROTECTED) {
1245       using_crc = TRUE;
1246     } else {
1247       using_crc = FALSE;
1248     }
1249     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_CRC,
1250         using_crc, NULL);
1251   }
1252
1253   if (mp3parse->last_posted_channel_mode != mp3parse->last_mode) {
1254     if (!taglist) {
1255       taglist = gst_tag_list_new ();
1256     }
1257     mp3parse->last_posted_channel_mode = mp3parse->last_mode;
1258
1259     gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MODE,
1260         gst_mpeg_audio_channel_mode_get_nick (mp3parse->last_mode), NULL);
1261   }
1262
1263   /* if the taglist exists, we need to send it */
1264   if (taglist) {
1265     gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse),
1266         GST_BASE_PARSE_SRC_PAD (mp3parse), taglist);
1267   }
1268
1269   /* usual clipping applies */
1270   frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
1271
1272   return GST_FLOW_OK;
1273 }
1274
1275 static GstCaps *
1276 gst_mpeg_audio_parse_get_sink_caps (GstBaseParse * parse)
1277 {
1278   GstCaps *peercaps;
1279   GstCaps *res;
1280
1281   peercaps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (parse));
1282   if (peercaps) {
1283     guint i, n;
1284
1285     /* Remove the parsed field */
1286     peercaps = gst_caps_make_writable (peercaps);
1287     n = gst_caps_get_size (peercaps);
1288     for (i = 0; i < n; i++) {
1289       GstStructure *s = gst_caps_get_structure (peercaps, i);
1290
1291       gst_structure_remove_field (s, "parsed");
1292     }
1293
1294     res =
1295         gst_caps_intersect_full (peercaps,
1296         gst_pad_get_pad_template_caps (GST_BASE_PARSE_SRC_PAD (parse)),
1297         GST_CAPS_INTERSECT_FIRST);
1298     gst_caps_unref (peercaps);
1299   } else {
1300     res =
1301         gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD
1302             (parse)));
1303   }
1304
1305   return res;
1306 }