• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
4  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
5  * Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
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., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 /**
24  * SECTION:element-lamemp3enc
25  * @see_also: lame, mad, vorbisenc
26  *
27  * This element encodes raw integer audio into an MPEG-1 layer 3 (MP3) stream.
28  * Note that [MP3](http://en.wikipedia.org/wiki/MP3) is not
29  * a free format, there are licensing and patent issues to take into
30  * consideration. See [Ogg/Vorbis](http://www.vorbis.com/) for a royalty free
31  * (and often higher quality) alternative.
32  *
33  * ## Output sample rate
34  *
35  * If no fixed output sample rate is negotiated on the element's src pad,
36  * the element will choose an optimal sample rate to resample to internally.
37  * For example, a 16-bit 44.1 KHz mono audio stream encoded at 48 kbit will
38  * get resampled to 32 KHz.  Use filter caps on the src pad to force a
39  * particular sample rate.
40  *
41  * ## Example pipelines
42  *
43  * |[
44  * gst-launch-1.0 -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! lamemp3enc ! filesink location=sine.mp3
45  * ]| Encode a test sine signal to MP3.
46  * |[
47  * gst-launch-1.0 -v autoaudiosrc ! audioconvert ! lamemp3enc target=bitrate bitrate=192 ! filesink location=alsasrc.mp3
48  * ]| Record from a sound card using ALSA and encode to MP3 with an average bitrate of 192kbps
49  * |[
50  * gst-launch-1.0 -v filesrc location=music.wav ! decodebin ! audioconvert ! audioresample ! lamemp3enc target=quality quality=0 ! id3v2mux ! filesink location=music.mp3
51  * ]| Transcode from a .wav file to MP3 (the id3v2mux element is optional) with best VBR quality
52  * |[
53  * gst-launch-1.0 -v cdda://5 ! audioconvert ! lamemp3enc target=bitrate cbr=true bitrate=192 ! filesink location=track5.mp3
54  * ]| Encode Audio CD track 5 to MP3 with a constant bitrate of 192kbps
55  * |[
56  * gst-launch-1.0 -v audiotestsrc num-buffers=10 ! audio/x-raw,rate=44100,channels=1 ! lamemp3enc target=bitrate cbr=true bitrate=48 ! filesink location=test.mp3
57  * ]| Encode to a fixed sample rate
58  */
59 
60 #ifdef HAVE_CONFIG_H
61 #include "config.h"
62 #endif
63 
64 #include <string.h>
65 #include "gstlamemp3enc.h"
66 #include <gst/gst-i18n-plugin.h>
67 
68 /* lame < 3.98 */
69 #ifndef HAVE_LAME_SET_VBR_QUALITY
70 #define lame_set_VBR_quality(flags,q) lame_set_VBR_q((flags),(int)(q))
71 #endif
72 
73 GST_DEBUG_CATEGORY_STATIC (debug);
74 #define GST_CAT_DEFAULT debug
75 
76 /* elementfactory information */
77 
78 /* LAMEMP3ENC can do MPEG-1, MPEG-2, and MPEG-2.5, so it has 9 possible
79  * sample rates it supports */
80 static GstStaticPadTemplate gst_lamemp3enc_sink_template =
81     GST_STATIC_PAD_TEMPLATE ("sink",
82     GST_PAD_SINK,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS ("audio/x-raw, "
85         "format = (string) " GST_AUDIO_NE (S16) ", "
86         "layout = (string) interleaved, "
87         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
88         "channels = (int) 1; "
89         "audio/x-raw, "
90         "format = (string) " GST_AUDIO_NE (S16) ", "
91         "layout = (string) interleaved, "
92         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
93         "channels = (int) 2, " "channel-mask = (bitmask) 0x3")
94     );
95 
96 static GstStaticPadTemplate gst_lamemp3enc_src_template =
97 GST_STATIC_PAD_TEMPLATE ("src",
98     GST_PAD_SRC,
99     GST_PAD_ALWAYS,
100     GST_STATIC_CAPS ("audio/mpeg, "
101         "mpegversion = (int) 1, "
102         "layer = (int) 3, "
103         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
104         "channels = (int) [ 1, 2 ]")
105     );
106 
107 /********** Define useful types for non-programmatic interfaces **********/
108 enum
109 {
110   LAMEMP3ENC_TARGET_QUALITY = 0,
111   LAMEMP3ENC_TARGET_BITRATE
112 };
113 
114 #define GST_TYPE_LAMEMP3ENC_TARGET (gst_lamemp3enc_target_get_type())
115 static GType
gst_lamemp3enc_target_get_type(void)116 gst_lamemp3enc_target_get_type (void)
117 {
118   static GType lame_target_type = 0;
119   static const GEnumValue lame_targets[] = {
120     {LAMEMP3ENC_TARGET_QUALITY, "Quality", "quality"},
121     {LAMEMP3ENC_TARGET_BITRATE, "Bitrate", "bitrate"},
122     {0, NULL, NULL}
123   };
124 
125   if (!lame_target_type) {
126     lame_target_type =
127         g_enum_register_static ("GstLameMP3EncTarget", lame_targets);
128   }
129   return lame_target_type;
130 }
131 
132 enum
133 {
134   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST = 0,
135   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD,
136   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH
137 };
138 
139 #define GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY (gst_lamemp3enc_encoding_engine_quality_get_type())
140 static GType
gst_lamemp3enc_encoding_engine_quality_get_type(void)141 gst_lamemp3enc_encoding_engine_quality_get_type (void)
142 {
143   static GType lame_encoding_engine_quality_type = 0;
144   static const GEnumValue lame_encoding_engine_quality[] = {
145     {0, "Fast", "fast"},
146     {1, "Standard", "standard"},
147     {2, "High", "high"},
148     {0, NULL, NULL}
149   };
150 
151   if (!lame_encoding_engine_quality_type) {
152     lame_encoding_engine_quality_type =
153         g_enum_register_static ("GstLameMP3EncEncodingEngineQuality",
154         lame_encoding_engine_quality);
155   }
156   return lame_encoding_engine_quality_type;
157 }
158 
159 /********** Standard stuff for signals and arguments **********/
160 
161 enum
162 {
163   ARG_0,
164   ARG_TARGET,
165   ARG_BITRATE,
166   ARG_CBR,
167   ARG_QUALITY,
168   ARG_ENCODING_ENGINE_QUALITY,
169   ARG_MONO
170 };
171 
172 #define DEFAULT_TARGET LAMEMP3ENC_TARGET_QUALITY
173 #define DEFAULT_BITRATE 128
174 #define DEFAULT_CBR FALSE
175 #define DEFAULT_QUALITY 4
176 #define DEFAULT_ENCODING_ENGINE_QUALITY LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD
177 #define DEFAULT_MONO FALSE
178 
179 static gboolean gst_lamemp3enc_start (GstAudioEncoder * enc);
180 static gboolean gst_lamemp3enc_stop (GstAudioEncoder * enc);
181 static gboolean gst_lamemp3enc_set_format (GstAudioEncoder * enc,
182     GstAudioInfo * info);
183 static GstFlowReturn gst_lamemp3enc_handle_frame (GstAudioEncoder * enc,
184     GstBuffer * in_buf);
185 static void gst_lamemp3enc_flush (GstAudioEncoder * enc);
186 
187 static void gst_lamemp3enc_set_property (GObject * object, guint prop_id,
188     const GValue * value, GParamSpec * pspec);
189 static void gst_lamemp3enc_get_property (GObject * object, guint prop_id,
190     GValue * value, GParamSpec * pspec);
191 static gboolean gst_lamemp3enc_setup (GstLameMP3Enc * lame, GstTagList ** tags);
192 
193 #define gst_lamemp3enc_parent_class parent_class
194 #ifdef ENABLE_NLS
195 #define _do_init \
196   GST_DEBUG_CATEGORY_INIT (debug, "lamemp3enc", 0, "lame mp3 encoder");\
197   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);\
198   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
199 #else /* ENABLE_NLS */
200 #define _do_init \
201   GST_DEBUG_CATEGORY_INIT (debug, "lamemp3enc", 0, "lame mp3 encoder");
202 #endif
203 G_DEFINE_TYPE_WITH_CODE (GstLameMP3Enc, gst_lamemp3enc, GST_TYPE_AUDIO_ENCODER,
204     _do_init);
205 GST_ELEMENT_REGISTER_DEFINE (lamemp3enc, "lamemp3enc", GST_RANK_PRIMARY,
206     GST_TYPE_LAMEMP3ENC);
207 
208 static void
gst_lamemp3enc_release_memory(GstLameMP3Enc * lame)209 gst_lamemp3enc_release_memory (GstLameMP3Enc * lame)
210 {
211   if (lame->lgf) {
212     lame_close (lame->lgf);
213     lame->lgf = NULL;
214   }
215 }
216 
217 static void
gst_lamemp3enc_finalize(GObject * obj)218 gst_lamemp3enc_finalize (GObject * obj)
219 {
220   gst_lamemp3enc_release_memory (GST_LAMEMP3ENC (obj));
221 
222   G_OBJECT_CLASS (parent_class)->finalize (obj);
223 }
224 
225 static void
gst_lamemp3enc_class_init(GstLameMP3EncClass * klass)226 gst_lamemp3enc_class_init (GstLameMP3EncClass * klass)
227 {
228   GObjectClass *gobject_class;
229   GstElementClass *gstelement_class;
230   GstAudioEncoderClass *base_class;
231 
232   gobject_class = (GObjectClass *) klass;
233   gstelement_class = (GstElementClass *) klass;
234   base_class = (GstAudioEncoderClass *) klass;
235 
236   gobject_class->set_property = gst_lamemp3enc_set_property;
237   gobject_class->get_property = gst_lamemp3enc_get_property;
238   gobject_class->finalize = gst_lamemp3enc_finalize;
239 
240   gst_element_class_add_static_pad_template (gstelement_class,
241       &gst_lamemp3enc_src_template);
242   gst_element_class_add_static_pad_template (gstelement_class,
243       &gst_lamemp3enc_sink_template);
244 
245   gst_element_class_set_static_metadata (gstelement_class,
246       "L.A.M.E. mp3 encoder", "Codec/Encoder/Audio",
247       "High-quality free MP3 encoder",
248       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
249 
250   base_class->start = GST_DEBUG_FUNCPTR (gst_lamemp3enc_start);
251   base_class->stop = GST_DEBUG_FUNCPTR (gst_lamemp3enc_stop);
252   base_class->set_format = GST_DEBUG_FUNCPTR (gst_lamemp3enc_set_format);
253   base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_lamemp3enc_handle_frame);
254   base_class->flush = GST_DEBUG_FUNCPTR (gst_lamemp3enc_flush);
255 
256   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TARGET,
257       g_param_spec_enum ("target", "Target",
258           "Optimize for quality or bitrate", GST_TYPE_LAMEMP3ENC_TARGET,
259           DEFAULT_TARGET,
260           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
261   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
262       g_param_spec_int ("bitrate", "Bitrate (kb/s)",
263           "Bitrate in kbit/sec (Only valid if target is bitrate, for CBR one "
264           "of 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, "
265           "256 or 320)", 8, 320, DEFAULT_BITRATE,
266           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
267   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CBR,
268       g_param_spec_boolean ("cbr", "CBR", "Enforce constant bitrate encoding "
269           "(Only valid if target is bitrate)", DEFAULT_CBR,
270           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
271   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
272       g_param_spec_float ("quality", "Quality",
273           "VBR Quality from 0 to 10, 0 being the best "
274           "(Only valid if target is quality)", 0.0, 9.999,
275           DEFAULT_QUALITY,
276           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
277   g_object_class_install_property (G_OBJECT_CLASS (klass),
278       ARG_ENCODING_ENGINE_QUALITY, g_param_spec_enum ("encoding-engine-quality",
279           "Encoding Engine Quality", "Quality/speed of the encoding engine, "
280           "this does not affect the bitrate!",
281           GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY,
282           DEFAULT_ENCODING_ENGINE_QUALITY,
283           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
284   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MONO,
285       g_param_spec_boolean ("mono", "Mono", "Enforce mono encoding",
286           DEFAULT_MONO,
287           G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
288 
289   gst_type_mark_as_plugin_api (GST_TYPE_LAMEMP3ENC_TARGET, 0);
290   gst_type_mark_as_plugin_api (GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY, 0);
291 }
292 
293 static void
gst_lamemp3enc_init(GstLameMP3Enc * lame)294 gst_lamemp3enc_init (GstLameMP3Enc * lame)
295 {
296   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (lame));
297 }
298 
299 static gboolean
gst_lamemp3enc_start(GstAudioEncoder * enc)300 gst_lamemp3enc_start (GstAudioEncoder * enc)
301 {
302   GstLameMP3Enc *lame = GST_LAMEMP3ENC (enc);
303 
304   GST_DEBUG_OBJECT (lame, "start");
305 
306   if (!lame->adapter)
307     lame->adapter = gst_adapter_new ();
308   gst_adapter_clear (lame->adapter);
309 
310   return TRUE;
311 }
312 
313 static gboolean
gst_lamemp3enc_stop(GstAudioEncoder * enc)314 gst_lamemp3enc_stop (GstAudioEncoder * enc)
315 {
316   GstLameMP3Enc *lame = GST_LAMEMP3ENC (enc);
317 
318   GST_DEBUG_OBJECT (lame, "stop");
319 
320   if (lame->adapter) {
321     g_object_unref (lame->adapter);
322     lame->adapter = NULL;
323   }
324 
325   gst_lamemp3enc_release_memory (lame);
326   return TRUE;
327 }
328 
329 static gboolean
gst_lamemp3enc_set_format(GstAudioEncoder * enc,GstAudioInfo * info)330 gst_lamemp3enc_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
331 {
332   GstLameMP3Enc *lame;
333   gint out_samplerate;
334   gint version;
335   GstCaps *othercaps;
336   GstClockTime latency;
337   GstTagList *tags = NULL;
338 
339   lame = GST_LAMEMP3ENC (enc);
340 
341   /* parameters already parsed for us */
342   lame->samplerate = GST_AUDIO_INFO_RATE (info);
343   lame->num_channels = GST_AUDIO_INFO_CHANNELS (info);
344 
345   /* but we might be asked to reconfigure, so reset */
346   gst_lamemp3enc_release_memory (lame);
347 
348   GST_DEBUG_OBJECT (lame, "setting up lame");
349   if (!gst_lamemp3enc_setup (lame, &tags))
350     goto setup_failed;
351 
352   out_samplerate = lame_get_out_samplerate (lame->lgf);
353   if (out_samplerate == 0)
354     goto zero_output_rate;
355   if (out_samplerate != lame->samplerate) {
356     GST_WARNING_OBJECT (lame,
357         "output samplerate %d is different from incoming samplerate %d",
358         out_samplerate, lame->samplerate);
359   }
360   lame->out_samplerate = out_samplerate;
361 
362   version = lame_get_version (lame->lgf);
363   if (version == 0)
364     version = 2;
365   else if (version == 1)
366     version = 1;
367   else if (version == 2)
368     version = 3;
369 
370   othercaps =
371       gst_caps_new_simple ("audio/mpeg",
372       "mpegversion", G_TYPE_INT, 1,
373       "mpegaudioversion", G_TYPE_INT, version,
374       "layer", G_TYPE_INT, 3,
375       "channels", G_TYPE_INT, lame->mono ? 1 : lame->num_channels,
376       "rate", G_TYPE_INT, out_samplerate, NULL);
377 
378   /* and use these caps */
379   gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (enc), othercaps);
380   gst_caps_unref (othercaps);
381 
382   /* base class feedback:
383    * - we will handle buffers, just hand us all available
384    * - report latency */
385   latency = gst_util_uint64_scale_int (lame_get_framesize (lame->lgf),
386       GST_SECOND, lame->samplerate);
387   gst_audio_encoder_set_latency (enc, latency, latency);
388 
389   if (tags) {
390     gst_audio_encoder_merge_tags (enc, tags, GST_TAG_MERGE_REPLACE);
391     gst_tag_list_unref (tags);
392   }
393 
394   return TRUE;
395 
396 zero_output_rate:
397   {
398     if (tags)
399       gst_tag_list_unref (tags);
400     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS, (NULL),
401         ("LAME mp3 audio decided on a zero sample rate"));
402     return FALSE;
403   }
404 setup_failed:
405   {
406     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS,
407         (_("Failed to configure LAME mp3 audio encoder. Check your encoding parameters.")), (NULL));
408     return FALSE;
409   }
410 }
411 
412 /* <php-emulation-mode>three underscores for ___rate is really really really
413  * private as opposed to one underscore<php-emulation-mode> */
414 /* call this MACRO outside of the NULL state so that we have a higher chance
415  * of actually having a pipeline and bus to get the message through */
416 
417 #define CHECK_AND_FIXUP_BITRATE(obj,param,rate)		 		  \
418 G_STMT_START {                                                            \
419   gint ___rate = rate;                                                    \
420   gint maxrate = 320;							  \
421   gint multiplier = 64;							  \
422   if (rate == 0) {                                                        \
423     ___rate = rate;                                                       \
424   } else if (rate <= 64) {				                  \
425     maxrate = 64; multiplier = 8;                                         \
426     if ((rate % 8) != 0) ___rate = GST_ROUND_UP_8 (rate); 		  \
427   } else if (rate <= 128) {						  \
428     maxrate = 128; multiplier = 16;                                       \
429     if ((rate % 16) != 0) ___rate = GST_ROUND_UP_16 (rate);               \
430   } else if (rate <= 256) {						  \
431     maxrate = 256; multiplier = 32;                                       \
432     if ((rate % 32) != 0) ___rate = GST_ROUND_UP_32 (rate);               \
433   } else if (rate <= 320) { 						  \
434     maxrate = 320; multiplier = 64;                                       \
435     if ((rate % 64) != 0) ___rate = GST_ROUND_UP_64 (rate);               \
436   }                                                                       \
437   if (___rate != rate) {                                                  \
438     GST_ELEMENT_WARNING (obj, LIBRARY, SETTINGS,			  \
439       (_("The requested bitrate %d kbit/s for property '%s' "             \
440        "is not allowed. "  					          \
441        "The bitrate was changed to %d kbit/s."), rate,		          \
442          param,  ___rate), 					          \
443        ("A bitrate below %d should be a multiple of %d.", 		  \
444           maxrate, multiplier));		  			  \
445     rate = ___rate;                                                       \
446   }                                                                       \
447 } G_STMT_END
448 
449 static void
gst_lamemp3enc_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)450 gst_lamemp3enc_set_property (GObject * object, guint prop_id,
451     const GValue * value, GParamSpec * pspec)
452 {
453   GstLameMP3Enc *lame;
454 
455   lame = GST_LAMEMP3ENC (object);
456 
457   switch (prop_id) {
458     case ARG_TARGET:
459       lame->target = g_value_get_enum (value);
460       break;
461     case ARG_BITRATE:
462       lame->bitrate = g_value_get_int (value);
463       break;
464     case ARG_CBR:
465       lame->cbr = g_value_get_boolean (value);
466       break;
467     case ARG_QUALITY:
468       lame->quality = g_value_get_float (value);
469       break;
470     case ARG_ENCODING_ENGINE_QUALITY:
471       lame->encoding_engine_quality = g_value_get_enum (value);
472       break;
473     case ARG_MONO:
474       lame->mono = g_value_get_boolean (value);
475       break;
476     default:
477       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
478       break;
479   }
480 }
481 
482 static void
gst_lamemp3enc_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)483 gst_lamemp3enc_get_property (GObject * object, guint prop_id, GValue * value,
484     GParamSpec * pspec)
485 {
486   GstLameMP3Enc *lame;
487 
488   lame = GST_LAMEMP3ENC (object);
489 
490   switch (prop_id) {
491     case ARG_TARGET:
492       g_value_set_enum (value, lame->target);
493       break;
494     case ARG_BITRATE:
495       g_value_set_int (value, lame->bitrate);
496       break;
497     case ARG_CBR:
498       g_value_set_boolean (value, lame->cbr);
499       break;
500     case ARG_QUALITY:
501       g_value_set_float (value, lame->quality);
502       break;
503     case ARG_ENCODING_ENGINE_QUALITY:
504       g_value_set_enum (value, lame->encoding_engine_quality);
505       break;
506     case ARG_MONO:
507       g_value_set_boolean (value, lame->mono);
508       break;
509     default:
510       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
511       break;
512   }
513 }
514 
515 /* **** credits go to mpegaudioparse **** */
516 
517 static const guint mp3types_bitrates[2][3][16] = {
518   {
519         {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,},
520         {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,},
521         {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,}
522       },
523   {
524         {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,},
525         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,},
526         {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}
527       },
528 };
529 
530 static const guint mp3types_freqs[3][3] = { {44100, 48000, 32000},
531 {22050, 24000, 16000},
532 {11025, 12000, 8000}
533 };
534 
535 static inline guint
mp3_type_frame_length_from_header(GstLameMP3Enc * lame,guint32 header,guint * put_version,guint * put_layer,guint * put_channels,guint * put_bitrate,guint * put_samplerate,guint * put_mode,guint * put_crc)536 mp3_type_frame_length_from_header (GstLameMP3Enc * lame, guint32 header,
537     guint * put_version, guint * put_layer, guint * put_channels,
538     guint * put_bitrate, guint * put_samplerate, guint * put_mode,
539     guint * put_crc)
540 {
541   guint length;
542   gulong mode, samplerate, bitrate, layer, channels, padding, crc;
543   gulong version;
544   gint lsf, mpg25;
545 
546   if (header & (1 << 20)) {
547     lsf = (header & (1 << 19)) ? 0 : 1;
548     mpg25 = 0;
549   } else {
550     lsf = 1;
551     mpg25 = 1;
552   }
553 
554   version = 1 + lsf + mpg25;
555 
556   layer = 4 - ((header >> 17) & 0x3);
557 
558   crc = (header >> 16) & 0x1;
559 
560   bitrate = (header >> 12) & 0xF;
561   bitrate = mp3types_bitrates[lsf][layer - 1][bitrate] * 1000;
562   /* The caller has ensured we have a valid header, so bitrate can't be
563      zero here. */
564   g_assert (bitrate != 0);
565 
566   samplerate = (header >> 10) & 0x3;
567   samplerate = mp3types_freqs[lsf + mpg25][samplerate];
568 
569   padding = (header >> 9) & 0x1;
570 
571   mode = (header >> 6) & 0x3;
572   channels = (mode == 3) ? 1 : 2;
573 
574   switch (layer) {
575     case 1:
576       length = 4 * ((bitrate * 12) / samplerate + padding);
577       break;
578     case 2:
579       length = (bitrate * 144) / samplerate + padding;
580       break;
581     default:
582     case 3:
583       length = (bitrate * 144) / (samplerate << lsf) + padding;
584       break;
585   }
586 
587   GST_DEBUG_OBJECT (lame, "Calculated mp3 frame length of %u bytes", length);
588   GST_DEBUG_OBJECT (lame, "samplerate = %lu, bitrate = %lu, version = %lu, "
589       "layer = %lu, channels = %lu", samplerate, bitrate, version,
590       layer, channels);
591 
592   if (put_version)
593     *put_version = version;
594   if (put_layer)
595     *put_layer = layer;
596   if (put_channels)
597     *put_channels = channels;
598   if (put_bitrate)
599     *put_bitrate = bitrate;
600   if (put_samplerate)
601     *put_samplerate = samplerate;
602   if (put_mode)
603     *put_mode = mode;
604   if (put_crc)
605     *put_crc = crc;
606 
607   return length;
608 }
609 
610 static gboolean
mp3_sync_check(GstLameMP3Enc * lame,unsigned long head)611 mp3_sync_check (GstLameMP3Enc * lame, unsigned long head)
612 {
613   GST_DEBUG_OBJECT (lame, "checking mp3 header 0x%08lx", head);
614   /* if it's not a valid sync */
615   if ((head & 0xffe00000) != 0xffe00000) {
616     GST_WARNING_OBJECT (lame, "invalid sync");
617     return FALSE;
618   }
619   /* if it's an invalid MPEG version */
620   if (((head >> 19) & 3) == 0x1) {
621     GST_WARNING_OBJECT (lame, "invalid MPEG version: 0x%lx", (head >> 19) & 3);
622     return FALSE;
623   }
624   /* if it's an invalid layer */
625   if (!((head >> 17) & 3)) {
626     GST_WARNING_OBJECT (lame, "invalid layer: 0x%lx", (head >> 17) & 3);
627     return FALSE;
628   }
629   /* if it's an invalid bitrate */
630   if (((head >> 12) & 0xf) == 0x0) {
631     GST_WARNING_OBJECT (lame, "invalid bitrate: 0x%lx."
632         "Free format files are not supported yet", (head >> 12) & 0xf);
633     return FALSE;
634   }
635   if (((head >> 12) & 0xf) == 0xf) {
636     GST_WARNING_OBJECT (lame, "invalid bitrate: 0x%lx", (head >> 12) & 0xf);
637     return FALSE;
638   }
639   /* if it's an invalid samplerate */
640   if (((head >> 10) & 0x3) == 0x3) {
641     GST_WARNING_OBJECT (lame, "invalid samplerate: 0x%lx", (head >> 10) & 0x3);
642     return FALSE;
643   }
644 
645   if ((head & 0x3) == 0x2) {
646     /* Ignore this as there are some files with emphasis 0x2 that can
647      * be played fine. See BGO #537235 */
648     GST_WARNING_OBJECT (lame, "invalid emphasis: 0x%lx", head & 0x3);
649   }
650 
651   return TRUE;
652 }
653 
654 /* **** end mpegaudioparse **** */
655 
656 static GstFlowReturn
gst_lamemp3enc_finish_frames(GstLameMP3Enc * lame)657 gst_lamemp3enc_finish_frames (GstLameMP3Enc * lame)
658 {
659   gint av;
660   guint header;
661   GstFlowReturn result = GST_FLOW_OK;
662 
663   /* limited parsing, we don't expect to lose sync here */
664   while ((result == GST_FLOW_OK) &&
665       ((av = gst_adapter_available (lame->adapter)) > 4)) {
666     guint rate, version, layer, size;
667     GstBuffer *mp3_buf;
668     const guint8 *data;
669     guint samples_per_frame;
670 
671     data = gst_adapter_map (lame->adapter, 4);
672     header = GST_READ_UINT32_BE (data);
673     gst_adapter_unmap (lame->adapter);
674 
675     if (!mp3_sync_check (lame, header))
676       goto invalid_header;
677 
678     size = mp3_type_frame_length_from_header (lame, header, &version, &layer,
679         NULL, NULL, &rate, NULL, NULL);
680 
681     if (G_UNLIKELY (layer != 3 || rate != lame->out_samplerate)) {
682       GST_DEBUG_OBJECT (lame,
683           "unexpected mp3 header with rate %u, version %u, layer %u",
684           rate, version, layer);
685       goto invalid_header;
686     }
687 
688     if (size > av) {
689       /* pretty likely to occur when lame is holding back on us */
690       GST_LOG_OBJECT (lame, "frame size %u (> %d)", size, av);
691       break;
692     }
693 
694     /* Account for the internal resampling, finish frame really wants to
695      * know about the number of incoming samples
696      */
697     samples_per_frame = (version == 1) ? 1152 : 576;
698     samples_per_frame *= lame->samplerate;
699     samples_per_frame /= lame->out_samplerate;
700 
701     /* should be ok now */
702     mp3_buf = gst_adapter_take_buffer (lame->adapter, size);
703     /* number of samples for MPEG-1, layer 3 */
704     result = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (lame),
705         mp3_buf, samples_per_frame);
706   }
707 
708 exit:
709   return result;
710 
711   /* ERRORS */
712 invalid_header:
713   {
714     GST_ELEMENT_ERROR (lame, STREAM, ENCODE,
715         ("invalid lame mp3 sync header %08X", header), (NULL));
716     result = GST_FLOW_ERROR;
717     goto exit;
718   }
719 }
720 
721 static GstFlowReturn
gst_lamemp3enc_flush_full(GstLameMP3Enc * lame,gboolean push)722 gst_lamemp3enc_flush_full (GstLameMP3Enc * lame, gboolean push)
723 {
724   GstBuffer *buf;
725   GstMapInfo map;
726   gint size;
727   GstFlowReturn result = GST_FLOW_OK;
728   gint av;
729 
730   if (!lame->lgf)
731     return GST_FLOW_OK;
732 
733   buf = gst_buffer_new_and_alloc (7200);
734   gst_buffer_map (buf, &map, GST_MAP_WRITE);
735   size = lame_encode_flush (lame->lgf, map.data, 7200);
736 
737   if (size > 0) {
738     gst_buffer_unmap (buf, &map);
739     gst_buffer_resize (buf, 0, size);
740     GST_DEBUG_OBJECT (lame, "collecting final %d bytes", size);
741     gst_adapter_push (lame->adapter, buf);
742   } else {
743     gst_buffer_unmap (buf, &map);
744     GST_DEBUG_OBJECT (lame, "no final packet (size=%d, push=%d)", size, push);
745     gst_buffer_unref (buf);
746     result = GST_FLOW_OK;
747   }
748 
749   if (push) {
750     result = gst_lamemp3enc_finish_frames (lame);
751   } else {
752     /* never mind */
753     gst_adapter_clear (lame->adapter);
754   }
755 
756   /* either way, we expect nothing left */
757   if ((av = gst_adapter_available (lame->adapter))) {
758     /* should this be more fatal ?? */
759     GST_WARNING_OBJECT (lame, "unparsed %d bytes left after flushing", av);
760     /* clean up anyway */
761     gst_adapter_clear (lame->adapter);
762   }
763 
764   return result;
765 }
766 
767 static void
gst_lamemp3enc_flush(GstAudioEncoder * enc)768 gst_lamemp3enc_flush (GstAudioEncoder * enc)
769 {
770   gst_lamemp3enc_flush_full (GST_LAMEMP3ENC (enc), FALSE);
771 }
772 
773 static GstFlowReturn
gst_lamemp3enc_handle_frame(GstAudioEncoder * enc,GstBuffer * in_buf)774 gst_lamemp3enc_handle_frame (GstAudioEncoder * enc, GstBuffer * in_buf)
775 {
776   GstLameMP3Enc *lame;
777   gint mp3_buffer_size, mp3_size;
778   GstBuffer *mp3_buf;
779   GstFlowReturn result;
780   gint num_samples;
781   GstMapInfo in_map, mp3_map;
782 
783   lame = GST_LAMEMP3ENC (enc);
784 
785   /* squeeze remaining and push */
786   if (G_UNLIKELY (in_buf == NULL))
787     return gst_lamemp3enc_flush_full (lame, TRUE);
788 
789   gst_buffer_map (in_buf, &in_map, GST_MAP_READ);
790 
791   num_samples = in_map.size / 2;
792 
793   /* allocate space for output */
794   mp3_buffer_size = 1.25 * num_samples + 7200;
795   mp3_buf = gst_buffer_new_allocate (NULL, mp3_buffer_size, NULL);
796   gst_buffer_map (mp3_buf, &mp3_map, GST_MAP_WRITE);
797 
798   /* lame seems to be too stupid to get mono interleaved going */
799   if (lame->num_channels == 1) {
800     mp3_size = lame_encode_buffer (lame->lgf,
801         (short int *) in_map.data,
802         (short int *) in_map.data, num_samples, mp3_map.data, mp3_buffer_size);
803   } else {
804     mp3_size = lame_encode_buffer_interleaved (lame->lgf,
805         (short int *) in_map.data,
806         num_samples / lame->num_channels, mp3_map.data, mp3_buffer_size);
807   }
808   gst_buffer_unmap (in_buf, &in_map);
809 
810   GST_LOG_OBJECT (lame, "encoded %" G_GSIZE_FORMAT " bytes of audio "
811       "to %d bytes of mp3", in_map.size, mp3_size);
812 
813   if (G_LIKELY (mp3_size > 0)) {
814     /* unfortunately lame does not provide frame delineated output,
815      * so collect output and parse into frames ... */
816     gst_buffer_unmap (mp3_buf, &mp3_map);
817     gst_buffer_resize (mp3_buf, 0, mp3_size);
818     gst_adapter_push (lame->adapter, mp3_buf);
819     result = gst_lamemp3enc_finish_frames (lame);
820   } else {
821     gst_buffer_unmap (mp3_buf, &mp3_map);
822     if (mp3_size < 0) {
823       /* eat error ? */
824       g_warning ("error %d", mp3_size);
825     }
826     gst_buffer_unref (mp3_buf);
827     result = GST_FLOW_OK;
828   }
829 
830   return result;
831 }
832 
833 /* set up the encoder state */
834 static gboolean
gst_lamemp3enc_setup(GstLameMP3Enc * lame,GstTagList ** tags)835 gst_lamemp3enc_setup (GstLameMP3Enc * lame, GstTagList ** tags)
836 {
837   gboolean res;
838 
839 #define CHECK_ERROR(command) G_STMT_START {\
840   if ((command) < 0) { \
841     GST_ERROR_OBJECT (lame, "setup failed: " G_STRINGIFY (command)); \
842     if (*tags) { \
843       gst_tag_list_unref (*tags); \
844       *tags = NULL; \
845     } \
846     return FALSE; \
847   } \
848 }G_STMT_END
849 
850   int retval;
851   GstCaps *allowed_caps;
852 
853   GST_DEBUG_OBJECT (lame, "starting setup");
854 
855   lame->lgf = lame_init ();
856 
857   if (lame->lgf == NULL)
858     return FALSE;
859 
860   *tags = gst_tag_list_new_empty ();
861 
862   /* copy the parameters over */
863   lame_set_in_samplerate (lame->lgf, lame->samplerate);
864 
865   /* let lame choose default samplerate unless outgoing sample rate is fixed */
866   allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (lame));
867 
868   if (allowed_caps != NULL) {
869     GstStructure *structure;
870     gint samplerate;
871 
872     structure = gst_caps_get_structure (allowed_caps, 0);
873 
874     if (gst_structure_get_int (structure, "rate", &samplerate)) {
875       GST_DEBUG_OBJECT (lame, "Setting sample rate to %d as fixed in src caps",
876           samplerate);
877       lame_set_out_samplerate (lame->lgf, samplerate);
878     } else {
879       GST_DEBUG_OBJECT (lame, "Letting lame choose sample rate");
880       lame_set_out_samplerate (lame->lgf, 0);
881     }
882     gst_caps_unref (allowed_caps);
883     allowed_caps = NULL;
884   } else {
885     GST_DEBUG_OBJECT (lame, "No peer yet, letting lame choose sample rate");
886     lame_set_out_samplerate (lame->lgf, 0);
887   }
888 
889   CHECK_ERROR (lame_set_num_channels (lame->lgf, lame->num_channels));
890   CHECK_ERROR (lame_set_bWriteVbrTag (lame->lgf, 0));
891 
892   if (lame->target == LAMEMP3ENC_TARGET_QUALITY) {
893     CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_default));
894     CHECK_ERROR (lame_set_VBR_quality (lame->lgf, lame->quality));
895   } else {
896     if (lame->cbr) {
897       CHECK_AND_FIXUP_BITRATE (lame, "bitrate", lame->bitrate);
898       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_off));
899       CHECK_ERROR (lame_set_brate (lame->lgf, lame->bitrate));
900     } else {
901       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_abr));
902       CHECK_ERROR (lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->bitrate));
903     }
904     gst_tag_list_add (*tags, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE,
905         lame->bitrate * 1000, NULL);
906   }
907 
908   if (lame->encoding_engine_quality == LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST)
909     CHECK_ERROR (lame_set_quality (lame->lgf, 7));
910   else if (lame->encoding_engine_quality ==
911       LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH)
912     CHECK_ERROR (lame_set_quality (lame->lgf, 2));
913   /* else default */
914 
915   if (lame->mono)
916     CHECK_ERROR (lame_set_mode (lame->lgf, MONO));
917 
918   /* initialize the lame encoder */
919   if ((retval = lame_init_params (lame->lgf)) >= 0) {
920     /* FIXME: it would be nice to print out the mode here */
921     GST_INFO
922         ("lame encoder setup (target %s, quality %f, bitrate %d, %d Hz, %d channels)",
923         (lame->target == LAMEMP3ENC_TARGET_QUALITY) ? "quality" : "bitrate",
924         lame->quality, lame->bitrate, lame->samplerate, lame->num_channels);
925     res = TRUE;
926   } else {
927     GST_ERROR_OBJECT (lame, "lame_init_params returned %d", retval);
928     res = FALSE;
929   }
930 
931   GST_DEBUG_OBJECT (lame, "done with setup");
932   return res;
933 #undef CHECK_ERROR
934 }
935