Tizen 2.1 base
[profile/ivi/gst-plugins-ugly0.10.git] / gst / mpegaudioparse / gstxingmux.c
1 /*
2  * Copyright (c) 2006 Christophe Fergeau  <teuf@gnome.org>
3  * Copyright (c) 2008 Sebastian Dröge  <slomo@circular-chaos.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /* Xing SDK: http://www.mp3-tech.org/programmer/sources/vbrheadersdk.zip */
22
23
24 /**
25  * SECTION:element-xingmux
26  *
27  * xingmux adds a Xing header to MP3 files. This contains information about the duration and size
28  * of the file and a seek table and is very useful for getting an almost correct duration and better
29  * seeking on VBR MP3 files.
30  * 
31  * This element will remove any existing Xing, LAME or VBRI headers from the beginning of the file.
32  *
33  * <refsect2>
34  * <title>Example launch line</title>
35  * |[
36  * gst-launch audiotestsrc num-buffers=1000 ! audioconvert ! lame ! xingmux ! filesink location=test.mp3
37  * gst-launch filesrc location=test.mp3 ! xingmux ! filesink location=test2.mp3
38  * gst-launch filesrc location=test.mp3 ! mp3parse ! xingmux ! filesink location=test2.mp3
39  * ]|
40  * </refsect2>
41  */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #include <string.h>
48 #include "gstxingmux.h"
49
50 GST_DEBUG_CATEGORY_STATIC (xing_mux_debug);
51 #define GST_CAT_DEFAULT xing_mux_debug
52
53 GST_BOILERPLATE (GstXingMux, gst_xing_mux, GstElement, GST_TYPE_ELEMENT);
54
55 /* Xing Header stuff */
56 #define GST_XING_FRAME_FIELD   (1 << 0)
57 #define GST_XING_BYTES_FIELD   (1 << 1)
58 #define GST_XING_TOC_FIELD     (1 << 2)
59 #define GST_XING_QUALITY_FIELD (1 << 3)
60
61 typedef struct _GstXingSeekEntry
62 {
63   gint64 timestamp;
64   gint byte;
65 } GstXingSeekEntry;
66
67 static inline GstXingSeekEntry *
68 gst_xing_seek_entry_new (void)
69 {
70   return g_slice_new (GstXingSeekEntry);
71 }
72
73 static inline void
74 gst_xing_seek_entry_free (GstXingSeekEntry * entry)
75 {
76   g_slice_free (GstXingSeekEntry, entry);
77 }
78
79 static void gst_xing_mux_finalize (GObject * obj);
80 static GstStateChangeReturn
81 gst_xing_mux_change_state (GstElement * element, GstStateChange transition);
82 static GstFlowReturn gst_xing_mux_chain (GstPad * pad, GstBuffer * buffer);
83 static gboolean gst_xing_mux_sink_event (GstPad * pad, GstEvent * event);
84
85 static GstStaticPadTemplate gst_xing_mux_sink_template =
86 GST_STATIC_PAD_TEMPLATE ("sink",
87     GST_PAD_SINK,
88     GST_PAD_ALWAYS,
89     GST_STATIC_CAPS ("audio/mpeg, "
90         "mpegversion = (int) 1, " "layer = (int) [ 1, 3 ]"));
91
92
93 static GstStaticPadTemplate gst_xing_mux_src_template =
94 GST_STATIC_PAD_TEMPLATE ("src",
95     GST_PAD_SRC,
96     GST_PAD_ALWAYS,
97     GST_STATIC_CAPS ("audio/mpeg, "
98         "mpegversion = (int) 1, " "layer = (int) [ 1, 3 ]"));
99 static const guint mp3types_bitrates[2][3][16] = {
100   {
101         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
102         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
103         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
104       },
105   {
106         {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
107         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
108         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
109       },
110 };
111
112 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
113 {22050, 24000, 16000},
114 {11025, 12000, 8000}
115 };
116
117 static gboolean
118 parse_header (guint32 header, guint * ret_size, guint * ret_spf,
119     gulong * ret_rate)
120 {
121   guint length, spf;
122   gulong samplerate, bitrate, layer, padding;
123   gint lsf, mpg25;
124
125   if ((header & 0xffe00000) != 0xffe00000) {
126     g_warning ("invalid sync");
127     return FALSE;
128   }
129
130   if (((header >> 19) & 3) == 0x01) {
131     g_warning ("invalid MPEG version");
132     return FALSE;
133   }
134
135   if (((header >> 17) & 3) == 0x00) {
136     g_warning ("invalid MPEG layer");
137     return FALSE;
138   }
139
140   if (((header >> 12) & 0xf) == 0xf || ((header >> 12) & 0xf) == 0x0) {
141     g_warning ("invalid bitrate");
142     return FALSE;
143   }
144
145   if (((header >> 10) & 0x3) == 0x3) {
146     g_warning ("invalid sampling rate");
147     return FALSE;
148   }
149
150   if (header & 0x00000002) {
151     g_warning ("invalid emphasis");
152     return FALSE;
153   }
154
155   if (header & (1 << 20)) {
156     lsf = (header & (1 << 19)) ? 0 : 1;
157     mpg25 = 0;
158   } else {
159     lsf = 1;
160     mpg25 = 1;
161   }
162
163   layer = 4 - ((header >> 17) & 0x3);
164
165   bitrate = (header >> 12) & 0xF;
166   bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
167   if (bitrate == 0)
168     return FALSE;
169
170   samplerate = (header >> 10) & 0x3;
171   samplerate = mp3types_freqs[lsf + mpg25][samplerate];
172
173   padding = (header >> 9) & 0x1;
174
175   switch (layer) {
176     case 1:
177       length = 4 * ((bitrate * 12) / samplerate + padding);
178       break;
179     case 2:
180       length = (bitrate * 144) / samplerate + padding;
181       break;
182     default:
183     case 3:
184       length = (bitrate * 144) / (samplerate << lsf) + padding;
185       break;
186   }
187
188   if (layer == 1)
189     spf = 384;
190   else if (layer == 2 || lsf == 0)
191     spf = 1152;
192   else
193     spf = 576;
194
195   if (ret_size)
196     *ret_size = length;
197   if (ret_spf)
198     *ret_spf = spf;
199   if (ret_rate)
200     *ret_rate = samplerate;
201
202   return TRUE;
203 }
204
205 static guint
206 get_xing_offset (guint32 header)
207 {
208   guint mpeg_version = (header >> 19) & 0x3;
209   guint channel_mode = (header >> 6) & 0x3;
210
211   if (mpeg_version == 0x3) {
212     if (channel_mode == 0x3) {
213       return 0x11;
214     } else {
215       return 0x20;
216     }
217   } else {
218     if (channel_mode == 0x3) {
219       return 0x09;
220     } else {
221       return 0x11;
222     }
223   }
224 }
225
226 static gboolean
227 has_xing_header (guint32 header, guchar * data, gsize size)
228 {
229   data += 4;
230   data += get_xing_offset (header);
231
232   if (memcmp (data, "Xing", 4) == 0 ||
233       memcmp (data, "Info", 4) == 0 || memcmp (data, "VBRI", 4) == 0)
234     return TRUE;
235   else
236     return FALSE;
237 }
238
239 static GstBuffer *
240 generate_xing_header (GstXingMux * xing)
241 {
242   guint8 *xing_flags;
243   guint32 xing_flags_tmp = 0;
244   GstBuffer *xing_header;
245   guchar *data;
246
247   guint32 header;
248   guint32 header_be;
249   guint size, spf, xing_offset;
250   gulong rate;
251   guint bitrate = 0x00;
252
253   gint64 duration;
254   gint64 byte_count;
255
256   header = xing->first_header;
257
258   /* Set bitrate and choose lowest possible size */
259   do {
260     bitrate++;
261
262     header &= 0xffff0fff;
263     header |= bitrate << 12;
264
265     parse_header (header, &size, &spf, &rate);
266     xing_offset = get_xing_offset (header);
267   } while (size < (4 + xing_offset + 4 + 4 + 4 + 4 + 100) && bitrate < 0xe);
268
269   if (bitrate == 0xe) {
270     GST_ERROR ("No usable bitrate found!");
271     return NULL;
272   }
273
274   if (gst_pad_alloc_buffer_and_set_caps (xing->srcpad, 0, size,
275           GST_PAD_CAPS (xing->srcpad), &xing_header) != GST_FLOW_OK) {
276     xing_header = gst_buffer_new_and_alloc (size);
277     gst_buffer_set_caps (xing_header, GST_PAD_CAPS (xing->srcpad));
278   }
279
280   data = GST_BUFFER_DATA (xing_header);
281   memset (data, 0, size);
282   header_be = GUINT32_TO_BE (header);
283   memcpy (data, &header_be, 4);
284
285   data += 4;
286   data += xing_offset;
287
288   memcpy (data, "Xing", 4);
289   data += 4;
290
291   xing_flags = data;
292   data += 4;
293
294   if (xing->duration != GST_CLOCK_TIME_NONE) {
295     duration = xing->duration;
296   } else {
297     GstFormat fmt = GST_FORMAT_TIME;
298
299     if (!gst_pad_query_peer_duration (xing->sinkpad, &fmt, &duration))
300       duration = GST_CLOCK_TIME_NONE;
301   }
302
303   if (duration != GST_CLOCK_TIME_NONE) {
304     guint32 number_of_frames;
305
306     /* The Xing Header contains a NumberOfFrames field, which verifies to:
307      * Duration = NumberOfFrames *SamplesPerFrame/SamplingRate
308      * SamplesPerFrame and SamplingRate are values for the current frame. 
309      */
310     number_of_frames = gst_util_uint64_scale (duration, rate, GST_SECOND) / spf;
311     GST_DEBUG ("Setting number of frames to %u", number_of_frames);
312     number_of_frames = GUINT32_TO_BE (number_of_frames);
313     memcpy (data, &number_of_frames, 4);
314     xing_flags_tmp |= GST_XING_FRAME_FIELD;
315     data += 4;
316   }
317
318   if (xing->byte_count != 0) {
319     byte_count = xing->byte_count;
320   } else {
321     GstFormat fmt = GST_FORMAT_BYTES;
322
323     if (!gst_pad_query_peer_duration (xing->sinkpad, &fmt, &byte_count))
324       byte_count = 0;
325     if (byte_count == -1)
326       byte_count = 0;
327   }
328
329   if (byte_count != 0) {
330     guint32 nbytes;
331
332     if (byte_count > G_MAXUINT32) {
333       GST_DEBUG ("Too large stream: %" G_GINT64_FORMAT " > %u bytes",
334           byte_count, G_MAXUINT32);
335     } else {
336       nbytes = byte_count;
337       GST_DEBUG ("Setting number of bytes to %u", nbytes);
338       nbytes = GUINT32_TO_BE (nbytes);
339       memcpy (data, &nbytes, 4);
340       xing_flags_tmp |= GST_XING_BYTES_FIELD;
341       data += 4;
342     }
343   }
344
345   if (xing->seek_table != NULL && byte_count != 0
346       && duration != GST_CLOCK_TIME_NONE) {
347     GList *it;
348     gint percent = 0;
349
350     xing_flags_tmp |= GST_XING_TOC_FIELD;
351
352     GST_DEBUG ("Writing seek table");
353     for (it = xing->seek_table; it != NULL && percent < 100; it = it->next) {
354       GstXingSeekEntry *entry = (GstXingSeekEntry *) it->data;
355       gint64 pos;
356       guchar byte;
357
358       while ((entry->timestamp * 100) / duration >= percent) {
359         pos = (entry->byte * 256) / byte_count;
360         GST_DEBUG ("  %d %% -- %" G_GINT64_FORMAT " 1/256", percent, pos);
361         byte = (guchar) pos;
362         memcpy (data, &byte, 1);
363         data++;
364         percent++;
365       }
366     }
367
368     if (percent < 100) {
369       guchar b;
370       gint i;
371
372       memcpy (&b, data - 1, 1);
373
374       for (i = percent; i < 100; i++) {
375         GST_DEBUG ("  %d %% -- %d 1/256", i, b);
376         memcpy (data, &b, 1);
377         data++;
378       }
379     }
380   }
381
382   GST_DEBUG ("Setting Xing flags to 0x%x\n", xing_flags_tmp);
383   xing_flags_tmp = GUINT32_TO_BE (xing_flags_tmp);
384   memcpy (xing_flags, &xing_flags_tmp, 4);
385   return xing_header;
386 }
387
388 static void
389 gst_xing_mux_base_init (gpointer g_class)
390 {
391   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
392
393   gst_element_class_add_static_pad_template (element_class,
394       &gst_xing_mux_src_template);
395   gst_element_class_add_static_pad_template (element_class,
396       &gst_xing_mux_sink_template);
397
398   GST_DEBUG_CATEGORY_INIT (xing_mux_debug, "xingmux", 0, "Xing Header Muxer");
399
400   gst_element_class_set_details_simple (element_class, "MP3 Xing muxer",
401       "Formatter/Metadata",
402       "Adds a Xing header to the beginning of a VBR MP3 file",
403       "Christophe Fergeau <teuf@gnome.org>");
404 }
405
406 static void
407 gst_xing_mux_class_init (GstXingMuxClass * klass)
408 {
409   GObjectClass *gobject_class;
410   GstElementClass *gstelement_class;
411
412   gobject_class = (GObjectClass *) klass;
413   gstelement_class = (GstElementClass *) klass;
414
415   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_xing_mux_finalize);
416   gstelement_class->change_state =
417       GST_DEBUG_FUNCPTR (gst_xing_mux_change_state);
418 }
419
420 static void
421 gst_xing_mux_finalize (GObject * obj)
422 {
423   GstXingMux *xing = GST_XING_MUX (obj);
424
425   if (xing->adapter) {
426     g_object_unref (xing->adapter);
427     xing->adapter = NULL;
428   }
429
430   if (xing->seek_table) {
431     g_list_foreach (xing->seek_table, (GFunc) gst_xing_seek_entry_free, NULL);
432     g_list_free (xing->seek_table);
433     xing->seek_table = NULL;
434   }
435
436   G_OBJECT_CLASS (parent_class)->finalize (obj);
437 }
438
439 static void
440 xing_reset (GstXingMux * xing)
441 {
442   xing->duration = GST_CLOCK_TIME_NONE;
443   xing->byte_count = 0;
444
445   gst_adapter_clear (xing->adapter);
446
447   if (xing->seek_table) {
448     g_list_foreach (xing->seek_table, (GFunc) gst_xing_seek_entry_free, NULL);
449     g_list_free (xing->seek_table);
450     xing->seek_table = NULL;
451   }
452
453   xing->sent_xing = FALSE;
454 }
455
456
457 static void
458 gst_xing_mux_init (GstXingMux * xing, GstXingMuxClass * xingmux_class)
459 {
460   GstElementClass *klass = GST_ELEMENT_CLASS (xingmux_class);
461
462   /* pad through which data comes in to the element */
463   xing->sinkpad =
464       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
465           "sink"), "sink");
466   gst_pad_set_setcaps_function (xing->sinkpad,
467       GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps));
468   gst_pad_set_chain_function (xing->sinkpad,
469       GST_DEBUG_FUNCPTR (gst_xing_mux_chain));
470   gst_pad_set_event_function (xing->sinkpad,
471       GST_DEBUG_FUNCPTR (gst_xing_mux_sink_event));
472   gst_element_add_pad (GST_ELEMENT (xing), xing->sinkpad);
473
474   /* pad through which data goes out of the element */
475   xing->srcpad =
476       gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
477           "src"), "src");
478   gst_element_add_pad (GST_ELEMENT (xing), xing->srcpad);
479
480   xing->adapter = gst_adapter_new ();
481
482   xing_reset (xing);
483 }
484
485 static GstFlowReturn
486 gst_xing_mux_chain (GstPad * pad, GstBuffer * buffer)
487 {
488   GstXingMux *xing = GST_XING_MUX (GST_PAD_PARENT (pad));
489   GstFlowReturn ret = GST_FLOW_OK;
490
491   gst_adapter_push (xing->adapter, buffer);
492
493   while (gst_adapter_available (xing->adapter) >= 4) {
494     const guchar *data = gst_adapter_peek (xing->adapter, 4);
495     guint32 header;
496     GstBuffer *outbuf;
497     GstClockTime duration;
498     guint size, spf;
499     gulong rate;
500     GstXingSeekEntry *seek_entry;
501
502     header = GST_READ_UINT32_BE (data);
503
504     if (!parse_header (header, &size, &spf, &rate)) {
505       GST_DEBUG ("Lost sync, resyncing");
506       gst_adapter_flush (xing->adapter, 1);
507       continue;
508     }
509
510     if (gst_adapter_available (xing->adapter) < size)
511       break;
512
513     outbuf = gst_adapter_take_buffer (xing->adapter, size);
514     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (xing->srcpad));
515
516     if (!xing->sent_xing) {
517       if (has_xing_header (header, GST_BUFFER_DATA (outbuf), size)) {
518         GST_LOG_OBJECT (xing, "Dropping old Xing header");
519         gst_buffer_unref (outbuf);
520         continue;
521       } else {
522         GstBuffer *xing_header;
523         guint64 xing_header_size;
524
525         xing->first_header = header;
526
527         xing_header = generate_xing_header (xing);
528
529         if (xing_header == NULL) {
530           GST_ERROR ("Can't generate Xing header");
531           gst_buffer_unref (outbuf);
532           return GST_FLOW_ERROR;
533         }
534
535         xing_header_size = GST_BUFFER_SIZE (xing_header);
536
537         if ((ret = gst_pad_push (xing->srcpad, xing_header)) != GST_FLOW_OK) {
538           GST_ERROR_OBJECT (xing, "Failed to push Xing header: %s",
539               gst_flow_get_name (ret));
540           gst_buffer_unref (xing_header);
541           gst_buffer_unref (outbuf);
542           return ret;
543         }
544
545         xing->byte_count += xing_header_size;
546         xing->sent_xing = TRUE;
547       }
548     }
549
550     seek_entry = gst_xing_seek_entry_new ();
551     seek_entry->timestamp =
552         (xing->duration == GST_CLOCK_TIME_NONE) ? 0 : xing->duration;
553     /* Workaround for parsers checking that the first seek table entry is 0 */
554     seek_entry->byte = (seek_entry->timestamp == 0) ? 0 : xing->byte_count;
555     xing->seek_table = g_list_append (xing->seek_table, seek_entry);
556
557     duration = gst_util_uint64_scale (spf, GST_SECOND, rate);
558
559     GST_BUFFER_TIMESTAMP (outbuf) =
560         (xing->duration == GST_CLOCK_TIME_NONE) ? 0 : xing->duration;
561     GST_BUFFER_DURATION (outbuf) = duration;
562     GST_BUFFER_OFFSET (outbuf) = xing->byte_count;
563     GST_BUFFER_OFFSET_END (outbuf) =
564         xing->byte_count + GST_BUFFER_SIZE (outbuf);
565
566     xing->byte_count += GST_BUFFER_SIZE (outbuf);
567
568     if (xing->duration == GST_CLOCK_TIME_NONE)
569       xing->duration = duration;
570     else
571       xing->duration += duration;
572
573     if ((ret = gst_pad_push (xing->srcpad, outbuf)) != GST_FLOW_OK) {
574       GST_ERROR_OBJECT (xing, "Failed to push MP3 frame: %s",
575           gst_flow_get_name (ret));
576       return ret;
577     }
578   }
579
580   return ret;
581 }
582
583 static gboolean
584 gst_xing_mux_sink_event (GstPad * pad, GstEvent * event)
585 {
586   GstXingMux *xing;
587   gboolean result;
588
589   xing = GST_XING_MUX (gst_pad_get_parent (pad));
590
591   switch (GST_EVENT_TYPE (event)) {
592     case GST_EVENT_NEWSEGMENT:
593       if (xing->sent_xing) {
594         GST_ERROR ("Already sent Xing header, dropping NEWSEGMENT event!");
595         gst_event_unref (event);
596         result = FALSE;
597       } else {
598         GstFormat fmt;
599
600         gst_event_parse_new_segment (event, NULL, NULL, &fmt, NULL, NULL, NULL);
601
602         if (fmt == GST_FORMAT_BYTES) {
603           result = gst_pad_push_event (xing->srcpad, event);
604         } else {
605           gst_event_unref (event);
606
607           event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
608               0, GST_CLOCK_TIME_NONE, 0);
609
610           result = gst_pad_push_event (xing->srcpad, event);
611         }
612       }
613       break;
614
615     case GST_EVENT_EOS:{
616       GstEvent *n_event;
617
618       GST_DEBUG_OBJECT (xing, "handling EOS event");
619
620       if (xing->sent_xing) {
621
622         n_event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
623             0, GST_CLOCK_TIME_NONE, 0);
624
625         if (G_UNLIKELY (!gst_pad_push_event (xing->srcpad, n_event))) {
626           GST_WARNING
627               ("Failed to seek to position 0 for pushing the Xing header");
628         } else {
629           GstBuffer *header;
630           GstFlowReturn ret;
631
632           header = generate_xing_header (xing);
633
634           if (header == NULL) {
635             GST_ERROR ("Can't generate Xing header");
636           } else {
637
638             GST_INFO ("Writing real Xing header to beginning of stream");
639
640             if ((ret = gst_pad_push (xing->srcpad, header)) != GST_FLOW_OK)
641               GST_WARNING ("Failed to push updated Xing header: %s\n",
642                   gst_flow_get_name (ret));
643           }
644         }
645       }
646       result = gst_pad_push_event (xing->srcpad, event);
647       break;
648     }
649     default:
650       result = gst_pad_event_default (pad, event);
651       break;
652   }
653   gst_object_unref (GST_OBJECT (xing));
654
655   return result;
656 }
657
658
659 static GstStateChangeReturn
660 gst_xing_mux_change_state (GstElement * element, GstStateChange transition)
661 {
662   GstXingMux *xing;
663   GstStateChangeReturn result;
664
665   xing = GST_XING_MUX (element);
666
667   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
668
669   switch (transition) {
670     case GST_STATE_CHANGE_PAUSED_TO_READY:
671       xing_reset (xing);
672       break;
673     default:
674       break;
675   }
676
677   return result;
678 }