f898539dae4b3c6dbdd5494ac62c9f2eb92345e3
[platform/upstream/gst-plugins-good.git] / ext / lame / gstlamemp3enc.c
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., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, 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 <ulink url="http://en.wikipedia.org/wiki/MP3">MP3</ulink> is not
29  * a free format, there are licensing and patent issues to take into
30  * consideration. See <ulink url="http://www.vorbis.com/">Ogg/Vorbis</ulink>
31  * for a royalty free (and often higher quality) alternative.
32  *
33  * <refsect2>
34  * <title>Output sample rate</title>
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  * </refsect2>
41  * <refsect2>
42  * <title>Example pipelines</title>
43  * |[
44  * gst-launch -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 -v alsasrc ! 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 -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 -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 -v audiotestsrc num-buffers=10 ! audio/x-raw-int,rate=44100,channels=1 ! lamemp3enc target=bitrate cbr=true bitrate=48 ! filesink location=test.mp3
57  * ]| Encode to a fixed sample rate
58  * </refsect2>
59  *
60  */
61
62 #ifdef HAVE_CONFIG_H
63 #include "config.h"
64 #endif
65
66 #include <string.h>
67 #include "gstlamemp3enc.h"
68 #include <gst/gst-i18n-plugin.h>
69
70 /* lame < 3.98 */
71 #ifndef HAVE_LAME_SET_VBR_QUALITY
72 #define lame_set_VBR_quality(flags,q) lame_set_VBR_q((flags),(int)(q))
73 #endif
74
75 GST_DEBUG_CATEGORY_STATIC (debug);
76 #define GST_CAT_DEFAULT debug
77
78 /* elementfactory information */
79
80 /* LAMEMP3ENC can do MPEG-1, MPEG-2, and MPEG-2.5, so it has 9 possible
81  * sample rates it supports */
82 static GstStaticPadTemplate gst_lamemp3enc_sink_template =
83 GST_STATIC_PAD_TEMPLATE ("sink",
84     GST_PAD_SINK,
85     GST_PAD_ALWAYS,
86     GST_STATIC_CAPS ("audio/x-raw-int, "
87         "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
88         "signed = (boolean) true, "
89         "width = (int) 16, "
90         "depth = (int) 16, "
91         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
92         "channels = (int) [ 1, 2 ]")
93     );
94
95 static GstStaticPadTemplate gst_lamemp3enc_src_template =
96 GST_STATIC_PAD_TEMPLATE ("src",
97     GST_PAD_SRC,
98     GST_PAD_ALWAYS,
99     GST_STATIC_CAPS ("audio/mpeg, "
100         "mpegversion = (int) 1, "
101         "layer = (int) 3, "
102         "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
103         "channels = (int) [ 1, 2 ]")
104     );
105
106 /********** Define useful types for non-programmatic interfaces **********/
107 enum
108 {
109   LAMEMP3ENC_TARGET_QUALITY = 0,
110   LAMEMP3ENC_TARGET_BITRATE
111 };
112
113 #define GST_TYPE_LAMEMP3ENC_TARGET (gst_lamemp3enc_target_get_type())
114 static GType
115 gst_lamemp3enc_target_get_type (void)
116 {
117   static GType lame_target_type = 0;
118   static GEnumValue lame_targets[] = {
119     {LAMEMP3ENC_TARGET_QUALITY, "Quality", "quality"},
120     {LAMEMP3ENC_TARGET_BITRATE, "Bitrate", "bitrate"},
121     {0, NULL, NULL}
122   };
123
124   if (!lame_target_type) {
125     lame_target_type =
126         g_enum_register_static ("GstLameMP3EncTarget", lame_targets);
127   }
128   return lame_target_type;
129 }
130
131 enum
132 {
133   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST = 0,
134   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD,
135   LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH
136 };
137
138 #define GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY (gst_lamemp3enc_encoding_engine_quality_get_type())
139 static GType
140 gst_lamemp3enc_encoding_engine_quality_get_type (void)
141 {
142   static GType lame_encoding_engine_quality_type = 0;
143   static GEnumValue lame_encoding_engine_quality[] = {
144     {0, "Fast", "fast"},
145     {1, "Standard", "standard"},
146     {2, "High", "high"},
147     {0, NULL, NULL}
148   };
149
150   if (!lame_encoding_engine_quality_type) {
151     lame_encoding_engine_quality_type =
152         g_enum_register_static ("GstLameMP3EncEncodingEngineQuality",
153         lame_encoding_engine_quality);
154   }
155   return lame_encoding_engine_quality_type;
156 }
157
158 /********** Standard stuff for signals and arguments **********/
159
160 enum
161 {
162   ARG_0,
163   ARG_TARGET,
164   ARG_BITRATE,
165   ARG_CBR,
166   ARG_QUALITY,
167   ARG_ENCODING_ENGINE_QUALITY,
168   ARG_MONO
169 };
170
171 #define DEFAULT_TARGET LAMEMP3ENC_TARGET_QUALITY
172 #define DEFAULT_BITRATE 128
173 #define DEFAULT_CBR FALSE
174 #define DEFAULT_QUALITY 4
175 #define DEFAULT_ENCODING_ENGINE_QUALITY LAMEMP3ENC_ENCODING_ENGINE_QUALITY_STANDARD
176 #define DEFAULT_MONO FALSE
177
178 static void gst_lamemp3enc_base_init (gpointer g_class);
179 static void gst_lamemp3enc_class_init (GstLameMP3EncClass * klass);
180 static void gst_lamemp3enc_init (GstLameMP3Enc * gst_lame);
181
182 static void gst_lamemp3enc_set_property (GObject * object, guint prop_id,
183     const GValue * value, GParamSpec * pspec);
184 static void gst_lamemp3enc_get_property (GObject * object, guint prop_id,
185     GValue * value, GParamSpec * pspec);
186 static gboolean gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event);
187 static GstFlowReturn gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf);
188 static gboolean gst_lamemp3enc_setup (GstLameMP3Enc * lame);
189 static GstStateChangeReturn gst_lamemp3enc_change_state (GstElement * element,
190     GstStateChange transition);
191
192 static GstElementClass *parent_class = NULL;
193
194 GType
195 gst_lamemp3enc_get_type (void)
196 {
197   static GType gst_lamemp3enc_type = 0;
198
199   if (!gst_lamemp3enc_type) {
200     static const GTypeInfo gst_lamemp3enc_info = {
201       sizeof (GstLameMP3EncClass),
202       gst_lamemp3enc_base_init,
203       NULL,
204       (GClassInitFunc) gst_lamemp3enc_class_init,
205       NULL,
206       NULL,
207       sizeof (GstLameMP3Enc),
208       0,
209       (GInstanceInitFunc) gst_lamemp3enc_init,
210     };
211     static const GInterfaceInfo preset_info = {
212       NULL,
213       NULL,
214       NULL
215     };
216
217     gst_lamemp3enc_type =
218         g_type_register_static (GST_TYPE_ELEMENT, "GstLameMP3Enc",
219         &gst_lamemp3enc_info, 0);
220     g_type_add_interface_static (gst_lamemp3enc_type, GST_TYPE_PRESET,
221         &preset_info);
222   }
223   return gst_lamemp3enc_type;
224 }
225
226 static void
227 gst_lamemp3enc_release_memory (GstLameMP3Enc * lame)
228 {
229   if (lame->lgf) {
230     lame_close (lame->lgf);
231     lame->lgf = NULL;
232   }
233 }
234
235 static void
236 gst_lamemp3enc_finalize (GObject * obj)
237 {
238   gst_lamemp3enc_release_memory (GST_LAMEMP3ENC (obj));
239
240   G_OBJECT_CLASS (parent_class)->finalize (obj);
241 }
242
243 static void
244 gst_lamemp3enc_base_init (gpointer g_class)
245 {
246   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
247
248   gst_element_class_add_pad_template (element_class,
249       gst_static_pad_template_get (&gst_lamemp3enc_src_template));
250   gst_element_class_add_pad_template (element_class,
251       gst_static_pad_template_get (&gst_lamemp3enc_sink_template));
252   gst_element_class_set_details_simple (element_class, "L.A.M.E. mp3 encoder",
253       "Codec/Encoder/Audio",
254       "High-quality free MP3 encoder",
255       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
256 }
257
258 static void
259 gst_lamemp3enc_class_init (GstLameMP3EncClass * klass)
260 {
261   GObjectClass *gobject_class;
262   GstElementClass *gstelement_class;
263
264   gobject_class = (GObjectClass *) klass;
265   gstelement_class = (GstElementClass *) klass;
266
267   parent_class = g_type_class_peek_parent (klass);
268
269   gobject_class->set_property = gst_lamemp3enc_set_property;
270   gobject_class->get_property = gst_lamemp3enc_get_property;
271   gobject_class->finalize = gst_lamemp3enc_finalize;
272
273   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TARGET,
274       g_param_spec_enum ("target", "Target",
275           "Optimize for quality or bitrate", GST_TYPE_LAMEMP3ENC_TARGET,
276           DEFAULT_TARGET, G_PARAM_READWRITE));
277   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
278       g_param_spec_int ("bitrate", "Bitrate (kb/s)",
279           "Bitrate in kbit/sec (8, 16, 24, 32, 40, 48, 56, 64, 80, 96, "
280           "112, 128, 160, 192, 224, 256 or 320)",
281           8, 320, DEFAULT_BITRATE, G_PARAM_READWRITE));
282   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CBR,
283       g_param_spec_boolean ("cbr", "CBR", "Enforce constant bitrate encoding",
284           DEFAULT_CBR, G_PARAM_READWRITE));
285   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
286       g_param_spec_float ("quality", "Quality",
287           "VBR Quality from 0 to 10, 0 being the best", 0.0, 9.999,
288           DEFAULT_QUALITY, G_PARAM_READWRITE));
289   g_object_class_install_property (G_OBJECT_CLASS (klass),
290       ARG_ENCODING_ENGINE_QUALITY, g_param_spec_enum ("encoding-engine-quality",
291           "Encoding Engine Quality", "Quality/speed of the encoding engine, "
292           "this does not affect the bitrate!",
293           GST_TYPE_LAMEMP3ENC_ENCODING_ENGINE_QUALITY,
294           DEFAULT_ENCODING_ENGINE_QUALITY, G_PARAM_READWRITE));
295   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MONO,
296       g_param_spec_boolean ("mono", "Mono", "Enforce mono encoding",
297           DEFAULT_MONO, G_PARAM_READWRITE));
298
299   gstelement_class->change_state =
300       GST_DEBUG_FUNCPTR (gst_lamemp3enc_change_state);
301 }
302
303 static gboolean
304 gst_lamemp3enc_src_setcaps (GstPad * pad, GstCaps * caps)
305 {
306   GST_DEBUG_OBJECT (pad, "caps: %" GST_PTR_FORMAT, caps);
307   return TRUE;
308 }
309
310 static gboolean
311 gst_lamemp3enc_sink_setcaps (GstPad * pad, GstCaps * caps)
312 {
313   GstLameMP3Enc *lame;
314   gint out_samplerate;
315   gint version;
316   GstStructure *structure;
317   GstCaps *othercaps;
318
319   lame = GST_LAMEMP3ENC (GST_PAD_PARENT (pad));
320   structure = gst_caps_get_structure (caps, 0);
321
322   if (!gst_structure_get_int (structure, "rate", &lame->samplerate))
323     goto no_rate;
324   if (!gst_structure_get_int (structure, "channels", &lame->num_channels))
325     goto no_channels;
326
327   GST_DEBUG_OBJECT (lame, "setting up lame");
328   if (!gst_lamemp3enc_setup (lame))
329     goto setup_failed;
330
331
332   out_samplerate = lame_get_out_samplerate (lame->lgf);
333   if (out_samplerate == 0)
334     goto zero_output_rate;
335   if (out_samplerate != lame->samplerate) {
336     GST_WARNING_OBJECT (lame,
337         "output samplerate %d is different from incoming samplerate %d",
338         out_samplerate, lame->samplerate);
339   }
340
341   version = lame_get_version (lame->lgf);
342   if (version == 0)
343     version = 2;
344   else if (version == 1)
345     version = 1;
346   else if (version == 2)
347     version = 3;
348
349   othercaps =
350       gst_caps_new_simple ("audio/mpeg",
351       "mpegversion", G_TYPE_INT, 1,
352       "mpegaudioversion", G_TYPE_INT, version,
353       "layer", G_TYPE_INT, 3,
354       "channels", G_TYPE_INT, lame->mono ? 1 : lame->num_channels,
355       "rate", G_TYPE_INT, out_samplerate, NULL);
356
357   /* and use these caps */
358   gst_pad_set_caps (lame->srcpad, othercaps);
359   gst_caps_unref (othercaps);
360
361   return TRUE;
362
363 no_rate:
364   {
365     GST_ERROR_OBJECT (lame, "input caps have no sample rate field");
366     return FALSE;
367   }
368 no_channels:
369   {
370     GST_ERROR_OBJECT (lame, "input caps have no channels field");
371     return FALSE;
372   }
373 zero_output_rate:
374   {
375     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS, (NULL),
376         ("LAMEMP3ENC decided on a zero sample rate"));
377     return FALSE;
378   }
379 setup_failed:
380   {
381     GST_ELEMENT_ERROR (lame, LIBRARY, SETTINGS,
382         (_("Failed to configure LAMEMP3ENC encoder. Check your encoding parameters.")), (NULL));
383     return FALSE;
384   }
385 }
386
387 static void
388 gst_lamemp3enc_init (GstLameMP3Enc * lame)
389 {
390   GST_DEBUG_OBJECT (lame, "starting initialization");
391
392   lame->sinkpad =
393       gst_pad_new_from_static_template (&gst_lamemp3enc_sink_template, "sink");
394   gst_pad_set_event_function (lame->sinkpad,
395       GST_DEBUG_FUNCPTR (gst_lamemp3enc_sink_event));
396   gst_pad_set_chain_function (lame->sinkpad,
397       GST_DEBUG_FUNCPTR (gst_lamemp3enc_chain));
398   gst_pad_set_setcaps_function (lame->sinkpad,
399       GST_DEBUG_FUNCPTR (gst_lamemp3enc_sink_setcaps));
400   gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
401
402   lame->srcpad =
403       gst_pad_new_from_static_template (&gst_lamemp3enc_src_template, "src");
404   gst_pad_set_setcaps_function (lame->srcpad,
405       GST_DEBUG_FUNCPTR (gst_lamemp3enc_src_setcaps));
406   gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
407
408   lame->samplerate = 44100;
409   lame->num_channels = 2;
410   lame->setup = FALSE;
411
412   /* Set default settings */
413   lame->target = DEFAULT_TARGET;
414   lame->bitrate = DEFAULT_BITRATE;
415   lame->cbr = DEFAULT_CBR;
416   lame->quality = DEFAULT_QUALITY;
417   lame->encoding_engine_quality = DEFAULT_ENCODING_ENGINE_QUALITY;
418   lame->mono = DEFAULT_MONO;
419
420   GST_DEBUG_OBJECT (lame, "done initializing");
421 }
422
423 /* <php-emulation-mode>three underscores for ___rate is really really really
424  * private as opposed to one underscore<php-emulation-mode> */
425 /* call this MACRO outside of the NULL state so that we have a higher chance
426  * of actually having a pipeline and bus to get the message through */
427
428 #define CHECK_AND_FIXUP_BITRATE(obj,param,rate)                           \
429 G_STMT_START {                                                            \
430   gint ___rate = rate;                                                    \
431   gint maxrate = 320;                                                     \
432   gint multiplier = 64;                                                   \
433   if (rate == 0) {                                                        \
434     ___rate = rate;                                                       \
435   } else if (rate <= 64) {                                                \
436     maxrate = 64; multiplier = 8;                                         \
437     if ((rate % 8) != 0) ___rate = GST_ROUND_UP_8 (rate);                 \
438   } else if (rate <= 128) {                                               \
439     maxrate = 128; multiplier = 16;                                       \
440     if ((rate % 16) != 0) ___rate = GST_ROUND_UP_16 (rate);               \
441   } else if (rate <= 256) {                                               \
442     maxrate = 256; multiplier = 32;                                       \
443     if ((rate % 32) != 0) ___rate = GST_ROUND_UP_32 (rate);               \
444   } else if (rate <= 320) {                                               \
445     maxrate = 320; multiplier = 64;                                       \
446     if ((rate % 64) != 0) ___rate = GST_ROUND_UP_64 (rate);               \
447   }                                                                       \
448   if (___rate != rate) {                                                  \
449     GST_ELEMENT_WARNING (obj, LIBRARY, SETTINGS,                          \
450       (_("The requested bitrate %d kbit/s for property '%s' "             \
451        "is not allowed. "                                                 \
452        "The bitrate was changed to %d kbit/s."), rate,                    \
453          param,  ___rate),                                                \
454        ("A bitrate below %d should be a multiple of %d.",                 \
455           maxrate, multiplier));                                          \
456     rate = ___rate;                                                       \
457   }                                                                       \
458 } G_STMT_END
459
460 static void
461 gst_lamemp3enc_set_property (GObject * object, guint prop_id,
462     const GValue * value, GParamSpec * pspec)
463 {
464   GstLameMP3Enc *lame;
465
466   lame = GST_LAMEMP3ENC (object);
467
468   switch (prop_id) {
469     case ARG_TARGET:
470       lame->target = g_value_get_enum (value);
471       break;
472     case ARG_BITRATE:
473       lame->bitrate = g_value_get_int (value);
474       break;
475     case ARG_CBR:
476       lame->cbr = g_value_get_boolean (value);
477       break;
478     case ARG_QUALITY:
479       lame->quality = g_value_get_float (value);
480       break;
481     case ARG_ENCODING_ENGINE_QUALITY:
482       lame->encoding_engine_quality = g_value_get_enum (value);
483       break;
484     case ARG_MONO:
485       lame->mono = g_value_get_boolean (value);
486       break;
487     default:
488       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
489       break;
490   }
491 }
492
493 static void
494 gst_lamemp3enc_get_property (GObject * object, guint prop_id, GValue * value,
495     GParamSpec * pspec)
496 {
497   GstLameMP3Enc *lame;
498
499   lame = GST_LAMEMP3ENC (object);
500
501   switch (prop_id) {
502     case ARG_TARGET:
503       g_value_set_enum (value, lame->target);
504       break;
505     case ARG_BITRATE:
506       g_value_set_int (value, lame->bitrate);
507       break;
508     case ARG_CBR:
509       g_value_set_boolean (value, lame->cbr);
510       break;
511     case ARG_QUALITY:
512       g_value_set_float (value, lame->quality);
513       break;
514     case ARG_ENCODING_ENGINE_QUALITY:
515       g_value_set_enum (value, lame->encoding_engine_quality);
516       break;
517     case ARG_MONO:
518       g_value_set_boolean (value, lame->mono);
519       break;
520     default:
521       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
522       break;
523   }
524 }
525
526 static gboolean
527 gst_lamemp3enc_sink_event (GstPad * pad, GstEvent * event)
528 {
529   gboolean ret;
530   GstLameMP3Enc *lame;
531
532   lame = GST_LAMEMP3ENC (gst_pad_get_parent (pad));
533
534   switch (GST_EVENT_TYPE (event)) {
535     case GST_EVENT_EOS:{
536       GST_DEBUG_OBJECT (lame, "handling EOS event");
537
538       if (lame->lgf != NULL) {
539         GstBuffer *buf;
540         gint size;
541
542         buf = gst_buffer_new_and_alloc (7200);
543         size = lame_encode_flush (lame->lgf, GST_BUFFER_DATA (buf), 7200);
544
545         if (size > 0 && lame->last_flow == GST_FLOW_OK) {
546           gint64 duration;
547
548           duration = gst_util_uint64_scale (size, 8 * GST_SECOND,
549               1000 * lame->bitrate);
550
551           if (lame->last_ts == GST_CLOCK_TIME_NONE) {
552             lame->last_ts = lame->eos_ts;
553             lame->last_duration = duration;
554           } else {
555             lame->last_duration += duration;
556           }
557
558           GST_BUFFER_TIMESTAMP (buf) = lame->last_ts;
559           GST_BUFFER_DURATION (buf) = lame->last_duration;
560           lame->last_ts = GST_CLOCK_TIME_NONE;
561           GST_BUFFER_SIZE (buf) = size;
562           GST_DEBUG_OBJECT (lame, "pushing final packet of %u bytes", size);
563           gst_buffer_set_caps (buf, GST_PAD_CAPS (lame->srcpad));
564           gst_pad_push (lame->srcpad, buf);
565         } else {
566           GST_DEBUG_OBJECT (lame, "no final packet (size=%d, last_flow=%s)",
567               size, gst_flow_get_name (lame->last_flow));
568           gst_buffer_unref (buf);
569         }
570       }
571
572       ret = gst_pad_event_default (pad, event);
573       break;
574     }
575     case GST_EVENT_FLUSH_START:
576       GST_DEBUG_OBJECT (lame, "handling FLUSH start event");
577       /* forward event */
578       ret = gst_pad_push_event (lame->srcpad, event);
579       break;
580     case GST_EVENT_FLUSH_STOP:
581     {
582       guchar *mp3_data = NULL;
583       gint mp3_buffer_size;
584
585       GST_DEBUG_OBJECT (lame, "handling FLUSH stop event");
586
587       /* clear buffers */
588       mp3_buffer_size = 7200;
589       mp3_data = g_malloc (mp3_buffer_size);
590       lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
591       g_free (mp3_data);
592
593       ret = gst_pad_push_event (lame->srcpad, event);
594       break;
595     }
596     case GST_EVENT_TAG:
597       GST_DEBUG_OBJECT (lame, "ignoring TAG event, passing it on");
598       ret = gst_pad_push_event (lame->srcpad, event);
599       break;
600     default:
601       ret = gst_pad_event_default (pad, event);
602       break;
603   }
604   gst_object_unref (lame);
605   return ret;
606 }
607
608 static GstFlowReturn
609 gst_lamemp3enc_chain (GstPad * pad, GstBuffer * buf)
610 {
611   GstLameMP3Enc *lame;
612   guchar *mp3_data;
613   gint mp3_buffer_size, mp3_size;
614   gint64 duration;
615   GstFlowReturn result;
616   gint num_samples;
617   guint8 *data;
618   guint size;
619
620   lame = GST_LAMEMP3ENC (GST_PAD_PARENT (pad));
621
622   GST_LOG_OBJECT (lame, "entered chain");
623
624   if (!lame->setup)
625     goto not_setup;
626
627   data = GST_BUFFER_DATA (buf);
628   size = GST_BUFFER_SIZE (buf);
629
630   num_samples = size / 2;
631
632   /* allocate space for output */
633   mp3_buffer_size = 1.25 * num_samples + 7200;
634   mp3_data = g_malloc (mp3_buffer_size);
635
636   /* lame seems to be too stupid to get mono interleaved going */
637   if (lame->num_channels == 1) {
638     mp3_size = lame_encode_buffer (lame->lgf,
639         (short int *) data,
640         (short int *) data, num_samples, mp3_data, mp3_buffer_size);
641   } else {
642     mp3_size = lame_encode_buffer_interleaved (lame->lgf,
643         (short int *) data,
644         num_samples / lame->num_channels, mp3_data, mp3_buffer_size);
645   }
646
647   GST_LOG_OBJECT (lame, "encoded %d bytes of audio to %d bytes of mp3",
648       size, mp3_size);
649
650   duration = gst_util_uint64_scale_int (size, GST_SECOND,
651       2 * lame->samplerate * lame->num_channels);
652
653   if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
654       GST_BUFFER_DURATION (buf) != duration) {
655     GST_DEBUG_OBJECT (lame, "incoming buffer had incorrect duration %"
656         GST_TIME_FORMAT ", outgoing buffer will have correct duration %"
657         GST_TIME_FORMAT,
658         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (duration));
659   }
660
661   if (lame->last_ts == GST_CLOCK_TIME_NONE) {
662     lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
663     lame->last_offs = GST_BUFFER_OFFSET (buf);
664     lame->last_duration = duration;
665   } else {
666     lame->last_duration += duration;
667   }
668
669   gst_buffer_unref (buf);
670
671   if (mp3_size < 0) {
672     g_warning ("error %d", mp3_size);
673   }
674
675   if (mp3_size > 0) {
676     GstBuffer *outbuf;
677
678     outbuf = gst_buffer_new ();
679     GST_BUFFER_DATA (outbuf) = mp3_data;
680     GST_BUFFER_MALLOCDATA (outbuf) = mp3_data;
681     GST_BUFFER_SIZE (outbuf) = mp3_size;
682     GST_BUFFER_TIMESTAMP (outbuf) = lame->last_ts;
683     GST_BUFFER_OFFSET (outbuf) = lame->last_offs;
684     GST_BUFFER_DURATION (outbuf) = lame->last_duration;
685     gst_buffer_set_caps (outbuf, GST_PAD_CAPS (lame->srcpad));
686
687     result = gst_pad_push (lame->srcpad, outbuf);
688     lame->last_flow = result;
689     if (result != GST_FLOW_OK) {
690       GST_DEBUG_OBJECT (lame, "flow return: %s", gst_flow_get_name (result));
691     }
692
693     if (GST_CLOCK_TIME_IS_VALID (lame->last_ts))
694       lame->eos_ts = lame->last_ts + lame->last_duration;
695     else
696       lame->eos_ts = GST_CLOCK_TIME_NONE;
697     lame->last_ts = GST_CLOCK_TIME_NONE;
698   } else {
699     g_free (mp3_data);
700     result = GST_FLOW_OK;
701   }
702
703   return result;
704
705   /* ERRORS */
706 not_setup:
707   {
708     gst_buffer_unref (buf);
709     GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
710         ("encoder not initialized (input is not audio?)"));
711     return GST_FLOW_ERROR;
712   }
713 }
714
715 /* set up the encoder state */
716 static gboolean
717 gst_lamemp3enc_setup (GstLameMP3Enc * lame)
718 {
719
720 #define CHECK_ERROR(command) G_STMT_START {\
721   if ((command) < 0) { \
722     GST_ERROR_OBJECT (lame, "setup failed: " G_STRINGIFY (command)); \
723     return FALSE; \
724   } \
725 }G_STMT_END
726
727   int retval;
728   GstCaps *allowed_caps;
729
730   GST_DEBUG_OBJECT (lame, "starting setup");
731
732   /* check if we're already setup; if we are, we might want to check
733    * if this initialization is compatible with the previous one */
734   /* FIXME: do this */
735   if (lame->setup) {
736     GST_WARNING_OBJECT (lame, "already setup");
737     lame->setup = FALSE;
738   }
739
740   lame->lgf = lame_init ();
741
742   if (lame->lgf == NULL)
743     return FALSE;
744
745   /* copy the parameters over */
746   lame_set_in_samplerate (lame->lgf, lame->samplerate);
747
748   /* let lame choose default samplerate unless outgoing sample rate is fixed */
749   allowed_caps = gst_pad_get_allowed_caps (lame->srcpad);
750
751   if (allowed_caps != NULL) {
752     GstStructure *structure;
753     gint samplerate;
754
755     structure = gst_caps_get_structure (allowed_caps, 0);
756
757     if (gst_structure_get_int (structure, "rate", &samplerate)) {
758       GST_DEBUG_OBJECT (lame, "Setting sample rate to %d as fixed in src caps",
759           samplerate);
760       lame_set_out_samplerate (lame->lgf, samplerate);
761     } else {
762       GST_DEBUG_OBJECT (lame, "Letting lame choose sample rate");
763       lame_set_out_samplerate (lame->lgf, 0);
764     }
765     gst_caps_unref (allowed_caps);
766     allowed_caps = NULL;
767   } else {
768     GST_DEBUG_OBJECT (lame, "No peer yet, letting lame choose sample rate");
769     lame_set_out_samplerate (lame->lgf, 0);
770   }
771
772   CHECK_ERROR (lame_set_num_channels (lame->lgf, lame->num_channels));
773
774   if (lame->target == LAMEMP3ENC_TARGET_QUALITY) {
775     CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_default));
776     CHECK_ERROR (lame_set_VBR_quality (lame->lgf, lame->quality));
777   } else {
778     CHECK_AND_FIXUP_BITRATE (lame, "bitrate", lame->bitrate);
779     if (lame->cbr) {
780       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_off));
781       CHECK_ERROR (lame_set_brate (lame->lgf, lame->bitrate));
782     } else {
783       CHECK_ERROR (lame_set_VBR (lame->lgf, vbr_abr));
784       CHECK_ERROR (lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->bitrate));
785     }
786   }
787
788   if (lame->encoding_engine_quality == LAMEMP3ENC_ENCODING_ENGINE_QUALITY_FAST)
789     CHECK_ERROR (lame_set_quality (lame->lgf, 7));
790   else if (lame->encoding_engine_quality ==
791       LAMEMP3ENC_ENCODING_ENGINE_QUALITY_HIGH)
792     CHECK_ERROR (lame_set_quality (lame->lgf, 2));
793   /* else default */
794
795   if (lame->mono)
796     CHECK_ERROR (lame_set_mode (lame->lgf, MONO));
797
798   /* initialize the lame encoder */
799   if ((retval = lame_init_params (lame->lgf)) >= 0) {
800     lame->setup = TRUE;
801     /* FIXME: it would be nice to print out the mode here */
802     GST_INFO ("lame encoder setup (%d Hz, %d channels)",
803         lame->bitrate, lame->samplerate, lame->num_channels);
804   } else {
805     GST_ERROR_OBJECT (lame, "lame_init_params returned %d", retval);
806   }
807
808   GST_DEBUG_OBJECT (lame, "done with setup");
809
810   return lame->setup;
811 #undef CHECK_ERROR
812 }
813
814 static GstStateChangeReturn
815 gst_lamemp3enc_change_state (GstElement * element, GstStateChange transition)
816 {
817   GstLameMP3Enc *lame;
818   GstStateChangeReturn result;
819
820   lame = GST_LAMEMP3ENC (element);
821
822   switch (transition) {
823     case GST_STATE_CHANGE_READY_TO_PAUSED:
824       lame->last_flow = GST_FLOW_OK;
825       lame->last_ts = GST_CLOCK_TIME_NONE;
826       lame->eos_ts = GST_CLOCK_TIME_NONE;
827       break;
828     default:
829       break;
830   }
831
832   result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
833
834   switch (transition) {
835     case GST_STATE_CHANGE_READY_TO_NULL:
836       gst_lamemp3enc_release_memory (lame);
837       break;
838     default:
839       break;
840   }
841
842   return result;
843 }
844
845 gboolean
846 gst_lamemp3enc_register (GstPlugin * plugin)
847 {
848   GST_DEBUG_CATEGORY_INIT (debug, "lamemp3enc", 0, "lame mp3 encoder");
849
850   if (!gst_element_register (plugin, "lamemp3enc", GST_RANK_NONE,
851           GST_TYPE_LAMEMP3ENC))
852     return FALSE;
853
854   return TRUE;
855 }