ugly: use new gst_element_class_add_static_pad_template()
[platform/upstream/gst-plugins-good.git] / ext / twolame / gsttwolamemp2enc.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) <2008> 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  * Based on the lame element.
25  */
26
27 /**
28  * SECTION:element-twolame
29  * @see_also: mad, lame
30  *
31  * This element encodes raw integer audio into an MPEG-1 layer 2 (MP2) stream.
32  *
33  * <refsect2>
34  * <title>Example pipelines</title>
35  * |[
36  * gst-launch-1.0 -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! twolame ! filesink location=sine.mp2
37  * ]| Encode a test sine signal to MP2.
38  * |[
39  * gst-launch-1.0 -v alsasrc ! audioconvert ! twolame bitrate=192 ! filesink location=alsasrc.mp2
40  * ]| Record from a sound card using ALSA and encode to MP2
41  * |[
42  * gst-launch-1.0 -v filesrc location=music.wav ! decodebin ! audioconvert ! audioresample ! twolame bitrate=192 ! id3v2mux ! filesink location=music.mp2
43  * ]| Transcode from a .wav file to MP2 (the id3v2mux element is optional)
44  * |[
45  * gst-launch-1.0 -v cdda://5 ! audioconvert ! twolame bitrate=192 ! filesink location=track5.mp2
46  * ]| Encode Audio CD track 5 to MP2
47  * </refsect2>
48  *
49  */
50
51 #ifdef HAVE_CONFIG_H
52 #include "config.h"
53 #endif
54
55 #include "string.h"
56 #include "gsttwolamemp2enc.h"
57 #include "gst/gst-i18n-plugin.h"
58
59 GST_DEBUG_CATEGORY_STATIC (debug);
60 #define GST_CAT_DEFAULT debug
61
62 /* TwoLAME can do MPEG-1, MPEG-2 so it has 6 possible
63  * sample rates it supports */
64 static GstStaticPadTemplate gst_two_lame_sink_template =
65     GST_STATIC_PAD_TEMPLATE ("sink",
66     GST_PAD_SINK,
67     GST_PAD_ALWAYS,
68     GST_STATIC_CAPS ("audio/x-raw, "
69         "format = (string) { " GST_AUDIO_NE (F32) ", " GST_AUDIO_NE (S16) " }, "
70         "layout = (string) interleaved, "
71         "rate = (int) { 16000, 22050, 24000, 32000, 44100, 48000 }, "
72         "channels = (int) 1; "
73         "audio/x-raw, "
74         "format = (string) { " GST_AUDIO_NE (F32) ", " GST_AUDIO_NE (S16) " }, "
75         "layout = (string) interleaved, "
76         "rate = (int) { 16000, 22050, 24000, 32000, 44100, 48000 }, "
77         "channels = (int) 2," "channel-mask = (bitmask) 0x3")
78     );
79
80 static GstStaticPadTemplate gst_two_lame_src_template =
81 GST_STATIC_PAD_TEMPLATE ("src",
82     GST_PAD_SRC,
83     GST_PAD_ALWAYS,
84     GST_STATIC_CAPS ("audio/mpeg, "
85         "mpegversion = (int) 1, "
86         "layer = (int) 2, "
87         "rate = (int) { 16000, 22050, 24000, 32000, 44100, 48000 }, "
88         "channels = (int) [ 1, 2 ]")
89     );
90
91 static struct
92 {
93   gint mode;
94   gint psymodel;
95   gint bitrate;
96   gint padding;
97   gboolean energy_level_extension;
98   gint emphasis;
99   gboolean error_protection;
100   gboolean copyright;
101   gboolean original;
102   gboolean vbr;
103   gfloat vbr_level;
104   gfloat ath_level;
105   gint vbr_max_bitrate;
106   gboolean quick_mode;
107   gint quick_mode_count;
108 } gst_two_lame_default_settings;
109
110 /********** Define useful types for non-programmatic interfaces **********/
111 #define GST_TYPE_TWO_LAME_MODE (gst_two_lame_mode_get_type())
112 static GType
113 gst_two_lame_mode_get_type (void)
114 {
115   static GType two_lame_mode_type = 0;
116   static const GEnumValue two_lame_modes[] = {
117     {TWOLAME_AUTO_MODE, "Auto", "auto"},
118     {TWOLAME_STEREO, "Stereo", "stereo"},
119     {TWOLAME_JOINT_STEREO, "Joint Stereo", "joint"},
120     {TWOLAME_DUAL_CHANNEL, "Dual Channel", "dual"},
121     {TWOLAME_MONO, "Mono", "mono"},
122     {0, NULL, NULL}
123   };
124
125   if (!two_lame_mode_type) {
126     two_lame_mode_type =
127         g_enum_register_static ("GstTwoLameMode", two_lame_modes);
128   }
129   return two_lame_mode_type;
130 }
131
132 #define GST_TYPE_TWO_LAME_PADDING (gst_two_lame_padding_get_type())
133 static GType
134 gst_two_lame_padding_get_type (void)
135 {
136   static GType two_lame_padding_type = 0;
137   static const GEnumValue two_lame_padding[] = {
138     {TWOLAME_PAD_NO, "No Padding", "never"},
139     {TWOLAME_PAD_ALL, "Always Pad", "always"},
140     {0, NULL, NULL}
141   };
142
143   if (!two_lame_padding_type) {
144     two_lame_padding_type =
145         g_enum_register_static ("GstTwoLamePadding", two_lame_padding);
146   }
147   return two_lame_padding_type;
148 }
149
150 #define GST_TYPE_TWO_LAME_EMPHASIS (gst_two_lame_emphasis_get_type())
151 static GType
152 gst_two_lame_emphasis_get_type (void)
153 {
154   static GType two_lame_emphasis_type = 0;
155   static const GEnumValue two_lame_emphasis[] = {
156     {TWOLAME_EMPHASIS_N, "No emphasis", "none"},
157     {TWOLAME_EMPHASIS_5, "50/15 ms", "5"},
158     {TWOLAME_EMPHASIS_C, "CCIT J.17", "ccit"},
159     {0, NULL, NULL}
160   };
161
162   if (!two_lame_emphasis_type) {
163     two_lame_emphasis_type =
164         g_enum_register_static ("GstTwoLameEmphasis", two_lame_emphasis);
165   }
166
167   return two_lame_emphasis_type;
168 }
169
170 /********** Standard stuff for signals and arguments **********/
171
172 enum
173 {
174   ARG_0,
175   ARG_MODE,
176   ARG_PSYMODEL,
177   ARG_BITRATE,
178   ARG_PADDING,
179   ARG_ENERGY_LEVEL_EXTENSION,
180   ARG_EMPHASIS,
181   ARG_ERROR_PROTECTION,
182   ARG_COPYRIGHT,
183   ARG_ORIGINAL,
184   ARG_VBR,
185   ARG_VBR_LEVEL,
186   ARG_ATH_LEVEL,
187   ARG_VBR_MAX_BITRATE,
188   ARG_QUICK_MODE,
189   ARG_QUICK_MODE_COUNT
190 };
191
192 static gboolean gst_two_lame_start (GstAudioEncoder * enc);
193 static gboolean gst_two_lame_stop (GstAudioEncoder * enc);
194 static gboolean gst_two_lame_set_format (GstAudioEncoder * enc,
195     GstAudioInfo * info);
196 static GstFlowReturn gst_two_lame_handle_frame (GstAudioEncoder * enc,
197     GstBuffer * in_buf);
198 static void gst_two_lame_flush (GstAudioEncoder * enc);
199
200 static void gst_two_lame_set_property (GObject * object, guint prop_id,
201     const GValue * value, GParamSpec * pspec);
202 static void gst_two_lame_get_property (GObject * object, guint prop_id,
203     GValue * value, GParamSpec * pspec);
204 static gboolean gst_two_lame_setup (GstTwoLame * twolame);
205
206 G_DEFINE_TYPE (GstTwoLame, gst_two_lame, GST_TYPE_AUDIO_ENCODER);
207
208 static void
209 gst_two_lame_release_memory (GstTwoLame * twolame)
210 {
211   if (twolame->glopts) {
212     twolame_close (&twolame->glopts);
213     twolame->glopts = NULL;
214   }
215 }
216
217 static void
218 gst_two_lame_finalize (GObject * obj)
219 {
220   gst_two_lame_release_memory (GST_TWO_LAME (obj));
221
222   G_OBJECT_CLASS (gst_two_lame_parent_class)->finalize (obj);
223 }
224
225 static void
226 gst_two_lame_class_init (GstTwoLameClass * klass)
227 {
228   GObjectClass *gobject_class;
229   GstAudioEncoderClass *gstbase_class;
230
231   gobject_class = (GObjectClass *) klass;
232   gstbase_class = (GstAudioEncoderClass *) klass;
233
234   gobject_class->set_property = gst_two_lame_set_property;
235   gobject_class->get_property = gst_two_lame_get_property;
236   gobject_class->finalize = gst_two_lame_finalize;
237
238   gstbase_class->start = GST_DEBUG_FUNCPTR (gst_two_lame_start);
239   gstbase_class->stop = GST_DEBUG_FUNCPTR (gst_two_lame_stop);
240   gstbase_class->set_format = GST_DEBUG_FUNCPTR (gst_two_lame_set_format);
241   gstbase_class->handle_frame = GST_DEBUG_FUNCPTR (gst_two_lame_handle_frame);
242   gstbase_class->flush = GST_DEBUG_FUNCPTR (gst_two_lame_flush);
243
244   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
245       g_param_spec_enum ("mode", "Mode", "Encoding mode",
246           GST_TYPE_TWO_LAME_MODE, gst_two_lame_default_settings.mode,
247           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
248
249   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PSYMODEL,
250       g_param_spec_int ("psymodel", "Psychoacoustic Model",
251           "Psychoacoustic model used to encode the audio",
252           -1, 4, gst_two_lame_default_settings.psymodel,
253           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
254
255   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
256       g_param_spec_int ("bitrate", "Bitrate (kb/s)",
257           "Bitrate in kbit/sec (8, 16, 24, 32, 40, 48, 56, 64, 80, 96, "
258           "112, 128, 144, 160, 192, 224, 256, 320, 384)",
259           8, 384, gst_two_lame_default_settings.bitrate,
260           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
261
262   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PADDING,
263       g_param_spec_enum ("padding", "Padding", "Padding type",
264           GST_TYPE_TWO_LAME_PADDING, gst_two_lame_default_settings.padding,
265           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
266
267   g_object_class_install_property (G_OBJECT_CLASS (klass),
268       ARG_ENERGY_LEVEL_EXTENSION,
269       g_param_spec_boolean ("energy-level-extension", "Energy Level Extension",
270           "Write peak PCM level to each frame",
271           gst_two_lame_default_settings.energy_level_extension,
272           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
273
274   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EMPHASIS,
275       g_param_spec_enum ("emphasis", "Emphasis",
276           "Pre-emphasis to apply to the decoded audio",
277           GST_TYPE_TWO_LAME_EMPHASIS, gst_two_lame_default_settings.emphasis,
278           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
279
280   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_PROTECTION,
281       g_param_spec_boolean ("error-protection", "Error protection",
282           "Adds checksum to every frame",
283           gst_two_lame_default_settings.error_protection,
284           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285
286   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPYRIGHT,
287       g_param_spec_boolean ("copyright", "Copyright", "Mark as copyright",
288           gst_two_lame_default_settings.copyright,
289           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
290
291   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ORIGINAL,
292       g_param_spec_boolean ("original", "Original", "Mark as original",
293           gst_two_lame_default_settings.original,
294           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
295
296   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
297       g_param_spec_boolean ("vbr", "VBR", "Enable variable bitrate mode",
298           gst_two_lame_default_settings.vbr,
299           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
300
301   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_LEVEL,
302       g_param_spec_float ("vbr-level", "VBR Level", "VBR Level",
303           -10.0, 10.0, gst_two_lame_default_settings.vbr_level,
304           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
305
306   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_LEVEL,
307       g_param_spec_float ("ath-level", "ATH Level", "ATH Level in dB",
308           -G_MAXFLOAT, G_MAXFLOAT, gst_two_lame_default_settings.ath_level,
309           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
310
311   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MAX_BITRATE,
312       g_param_spec_int ("vbr-max-bitrate", "VBR max bitrate",
313           "Specify maximum VBR bitrate (0=off, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, "
314           "112, 128, 144, 160, 192, 224, 256, 320, 384)",
315           0, 384, gst_two_lame_default_settings.vbr_max_bitrate,
316           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
317
318   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUICK_MODE,
319       g_param_spec_boolean ("quick-mode", "Quick mode",
320           "Calculate Psymodel every frames",
321           gst_two_lame_default_settings.quick_mode,
322           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
323
324   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUICK_MODE_COUNT,
325       g_param_spec_int ("quick-mode-count", "Quick mode count",
326           "Calculate Psymodel every n frames",
327           0, G_MAXINT, gst_two_lame_default_settings.quick_mode_count,
328           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
329
330   gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
331       &gst_two_lame_src_template);
332   gst_element_class_add_static_pad_template (GST_ELEMENT_CLASS (klass),
333       &gst_two_lame_sink_template);
334
335   gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
336       "TwoLAME mp2 encoder", "Codec/Encoder/Audio",
337       "High-quality free MP2 encoder",
338       "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
339 }
340
341 static gboolean
342 gst_two_lame_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
343 {
344   GstTwoLame *twolame;
345   gint out_samplerate;
346   gint version;
347   GstCaps *othercaps;
348
349   twolame = GST_TWO_LAME (enc);
350
351   /* parameters already parsed for us */
352   twolame->samplerate = GST_AUDIO_INFO_RATE (info);
353   twolame->num_channels = GST_AUDIO_INFO_CHANNELS (info);
354   twolame->float_input = !GST_AUDIO_INFO_IS_INTEGER (info);
355
356   /* but we might be asked to reconfigure, so reset */
357   gst_two_lame_release_memory (twolame);
358
359   GST_DEBUG_OBJECT (twolame, "setting up twolame");
360   if (!gst_two_lame_setup (twolame))
361     goto setup_failed;
362
363   out_samplerate = twolame_get_out_samplerate (twolame->glopts);
364   if (out_samplerate == 0)
365     goto zero_output_rate;
366
367   if (out_samplerate != twolame->samplerate) {
368     GST_WARNING_OBJECT (twolame,
369         "output samplerate %d is different from incoming samplerate %d",
370         out_samplerate, twolame->samplerate);
371   }
372
373   version = twolame_get_version (twolame->glopts);
374   if (version == TWOLAME_MPEG2)
375     version = 2;
376   else
377     version = 1;
378
379   othercaps =
380       gst_caps_new_simple ("audio/mpeg",
381       "mpegversion", G_TYPE_INT, 1,
382       "mpegaudioversion", G_TYPE_INT, version,
383       "layer", G_TYPE_INT, 2,
384       "channels", G_TYPE_INT,
385       twolame->mode == TWOLAME_MONO ? 1 : twolame->num_channels, "rate",
386       G_TYPE_INT, out_samplerate, NULL);
387
388   /* and use these caps */
389   gst_audio_encoder_set_output_format (GST_AUDIO_ENCODER (twolame), othercaps);
390   gst_caps_unref (othercaps);
391
392   /* report needs to base class:
393    * hand one frame at a time, if we are pretty sure what a frame is */
394   if (out_samplerate == twolame->samplerate) {
395     gst_audio_encoder_set_frame_samples_min (enc, 1152);
396     gst_audio_encoder_set_frame_samples_max (enc, 1152);
397     gst_audio_encoder_set_frame_max (enc, 1);
398   }
399
400   return TRUE;
401
402 zero_output_rate:
403   {
404     GST_ELEMENT_ERROR (twolame, LIBRARY, SETTINGS, (NULL),
405         ("TwoLAME decided on a zero sample rate"));
406     return FALSE;
407   }
408 setup_failed:
409   {
410     GST_ELEMENT_ERROR (twolame, LIBRARY, SETTINGS,
411         (_("Failed to configure TwoLAME encoder. Check your encoding parameters.")), (NULL));
412     return FALSE;
413   }
414 }
415
416 static void
417 gst_two_lame_init (GstTwoLame * twolame)
418 {
419   GST_DEBUG_OBJECT (twolame, "starting initialization");
420
421   GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_ENCODER_SINK_PAD (twolame));
422
423   twolame->mode = gst_two_lame_default_settings.mode;
424   twolame->psymodel = gst_two_lame_default_settings.psymodel;
425   twolame->bitrate = gst_two_lame_default_settings.bitrate;
426   twolame->padding = gst_two_lame_default_settings.padding;
427   twolame->energy_level_extension =
428       gst_two_lame_default_settings.energy_level_extension;
429   twolame->emphasis = gst_two_lame_default_settings.emphasis;
430   twolame->error_protection = gst_two_lame_default_settings.error_protection;
431   twolame->copyright = gst_two_lame_default_settings.copyright;
432   twolame->original = gst_two_lame_default_settings.original;
433   twolame->vbr = gst_two_lame_default_settings.vbr;
434   twolame->vbr_level = gst_two_lame_default_settings.vbr_level;
435   twolame->ath_level = gst_two_lame_default_settings.ath_level;
436   twolame->vbr_max_bitrate = gst_two_lame_default_settings.vbr_max_bitrate;
437   twolame->quick_mode = gst_two_lame_default_settings.quick_mode;
438   twolame->quick_mode_count = gst_two_lame_default_settings.quick_mode_count;
439
440   GST_DEBUG_OBJECT (twolame, "done initializing");
441 }
442
443 static gboolean
444 gst_two_lame_start (GstAudioEncoder * enc)
445 {
446   GstTwoLame *twolame = GST_TWO_LAME (enc);
447
448   GST_DEBUG_OBJECT (twolame, "start");
449   return TRUE;
450 }
451
452 static gboolean
453 gst_two_lame_stop (GstAudioEncoder * enc)
454 {
455   GstTwoLame *twolame = GST_TWO_LAME (enc);
456
457   GST_DEBUG_OBJECT (twolame, "stop");
458
459   gst_two_lame_release_memory (twolame);
460   return TRUE;
461 }
462
463 /* <php-emulation-mode>three underscores for ___rate is really really really
464  * private as opposed to one underscore<php-emulation-mode> */
465 /* call this MACRO outside of the NULL state so that we have a higher chance
466  * of actually having a pipeline and bus to get the message through */
467
468 #define CHECK_AND_FIXUP_BITRATE(obj,param,rate)                           \
469 G_STMT_START {                                                            \
470   gint ___rate = rate;                                                    \
471   gint maxrate = 320;                                                     \
472   gint multiplier = 64;                                                   \
473   if (rate <= 64) {                                                       \
474     maxrate = 64; multiplier = 8;                                         \
475     if ((rate % 8) != 0) ___rate = GST_ROUND_UP_8 (rate);                 \
476   } else if (rate <= 144) {                                               \
477     maxrate = 144; multiplier = 16;                                       \
478     if ((rate % 16) != 0) ___rate = GST_ROUND_UP_16 (rate);               \
479   } else if (rate <= 256) {                                               \
480     maxrate = 256; multiplier = 32;                                       \
481     if ((rate % 32) != 0) ___rate = GST_ROUND_UP_32 (rate);               \
482   } else if (rate <= 384) {                                               \
483     maxrate = 384; multiplier = 64;                                       \
484     if ((rate % 64) != 0) ___rate = GST_ROUND_UP_64 (rate);               \
485   }                                                                       \
486   if (___rate != rate) {                                                  \
487     GST_ELEMENT_WARNING (obj, LIBRARY, SETTINGS,                          \
488         (_("The requested bitrate %d kbit/s for property '%s' "           \
489            "is not allowed. "                                             \
490            "The bitrate was changed to %d kbit/s."), rate,                \
491          param,  ___rate),                                                \
492         ("A bitrate below %d should be a multiple of %d.",                \
493             maxrate, multiplier));                                        \
494     rate = ___rate;                                                       \
495   }                                                                       \
496 } G_STMT_END
497
498 static void
499 gst_two_lame_set_property (GObject * object, guint prop_id,
500     const GValue * value, GParamSpec * pspec)
501 {
502   GstTwoLame *twolame = GST_TWO_LAME (object);
503
504   switch (prop_id) {
505     case ARG_MODE:
506       twolame->mode = g_value_get_enum (value);
507       break;
508     case ARG_PSYMODEL:
509       twolame->psymodel = g_value_get_int (value);
510       break;
511     case ARG_BITRATE:
512       twolame->bitrate = g_value_get_int (value);
513       break;
514     case ARG_PADDING:
515       twolame->padding = g_value_get_enum (value);
516       break;
517     case ARG_ENERGY_LEVEL_EXTENSION:
518       twolame->energy_level_extension = g_value_get_boolean (value);
519       break;
520     case ARG_EMPHASIS:
521       twolame->emphasis = g_value_get_enum (value);
522       break;
523     case ARG_ERROR_PROTECTION:
524       twolame->error_protection = g_value_get_boolean (value);
525       break;
526     case ARG_COPYRIGHT:
527       twolame->copyright = g_value_get_boolean (value);
528       break;
529     case ARG_ORIGINAL:
530       twolame->original = g_value_get_boolean (value);
531       break;
532     case ARG_VBR:
533       twolame->vbr = g_value_get_boolean (value);
534       break;
535     case ARG_VBR_LEVEL:
536       twolame->vbr_level = g_value_get_float (value);
537       break;
538     case ARG_ATH_LEVEL:
539       twolame->ath_level = g_value_get_float (value);
540       break;
541     case ARG_VBR_MAX_BITRATE:
542       twolame->vbr_max_bitrate = g_value_get_int (value);
543       break;
544     case ARG_QUICK_MODE:
545       twolame->quick_mode = g_value_get_boolean (value);
546       break;
547     case ARG_QUICK_MODE_COUNT:
548       twolame->quick_mode_count = g_value_get_int (value);
549       break;
550     default:
551       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
552       break;
553   }
554 }
555
556 static void
557 gst_two_lame_get_property (GObject * object, guint prop_id, GValue * value,
558     GParamSpec * pspec)
559 {
560   GstTwoLame *twolame = GST_TWO_LAME (object);
561
562   switch (prop_id) {
563     case ARG_MODE:
564       g_value_set_enum (value, twolame->mode);
565       break;
566     case ARG_PSYMODEL:
567       g_value_set_int (value, twolame->psymodel);
568       break;
569     case ARG_BITRATE:
570       g_value_set_int (value, twolame->bitrate);
571       break;
572     case ARG_PADDING:
573       g_value_set_enum (value, twolame->padding);
574       break;
575     case ARG_ENERGY_LEVEL_EXTENSION:
576       g_value_set_boolean (value, twolame->energy_level_extension);
577       break;
578     case ARG_EMPHASIS:
579       g_value_set_enum (value, twolame->emphasis);
580       break;
581     case ARG_ERROR_PROTECTION:
582       g_value_set_boolean (value, twolame->error_protection);
583       break;
584     case ARG_COPYRIGHT:
585       g_value_set_boolean (value, twolame->copyright);
586       break;
587     case ARG_ORIGINAL:
588       g_value_set_boolean (value, twolame->original);
589       break;
590     case ARG_VBR:
591       g_value_set_boolean (value, twolame->vbr);
592       break;
593     case ARG_VBR_LEVEL:
594       g_value_set_float (value, twolame->vbr_level);
595       break;
596     case ARG_ATH_LEVEL:
597       g_value_set_float (value, twolame->ath_level);
598       break;
599     case ARG_VBR_MAX_BITRATE:
600       g_value_set_int (value, twolame->vbr_max_bitrate);
601       break;
602     case ARG_QUICK_MODE:
603       g_value_set_boolean (value, twolame->quick_mode);
604       break;
605     case ARG_QUICK_MODE_COUNT:
606       g_value_set_int (value, twolame->quick_mode_count);
607       break;
608     default:
609       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
610       break;
611   }
612 }
613
614 static GstFlowReturn
615 gst_two_lame_flush_full (GstTwoLame * lame, gboolean push)
616 {
617   GstBuffer *buf;
618   GstMapInfo map;
619   gint size;
620   GstFlowReturn result = GST_FLOW_OK;
621
622   if (!lame->glopts)
623     return GST_FLOW_OK;
624
625   buf = gst_buffer_new_and_alloc (16384);
626   gst_buffer_map (buf, &map, GST_MAP_WRITE);
627   size = twolame_encode_flush (lame->glopts, map.data, 16384);
628   gst_buffer_unmap (buf, &map);
629
630   if (size > 0 && push) {
631     gst_buffer_set_size (buf, size);
632     GST_DEBUG_OBJECT (lame, "pushing final packet of %u bytes", size);
633     result = gst_audio_encoder_finish_frame (GST_AUDIO_ENCODER (lame), buf, -1);
634   } else {
635     GST_DEBUG_OBJECT (lame, "no final packet (size=%d, push=%d)", size, push);
636     gst_buffer_unref (buf);
637     result = GST_FLOW_OK;
638   }
639   return result;
640 }
641
642 static void
643 gst_two_lame_flush (GstAudioEncoder * enc)
644 {
645   gst_two_lame_flush_full (GST_TWO_LAME (enc), FALSE);
646 }
647
648 static GstFlowReturn
649 gst_two_lame_handle_frame (GstAudioEncoder * enc, GstBuffer * buf)
650 {
651   GstTwoLame *twolame;
652   gint mp3_buffer_size, mp3_size;
653   GstBuffer *mp3_buf;
654   GstFlowReturn result;
655   gint num_samples;
656   GstMapInfo map, mp3_map;
657
658   twolame = GST_TWO_LAME (enc);
659
660   /* squeeze remaining and push */
661   if (G_UNLIKELY (buf == NULL))
662     return gst_two_lame_flush_full (twolame, TRUE);
663
664   gst_buffer_map (buf, &map, GST_MAP_READ);
665
666   if (twolame->float_input)
667     num_samples = map.size / 4;
668   else
669     num_samples = map.size / 2;
670
671   /* allocate space for output */
672   mp3_buffer_size = 1.25 * num_samples + 16384;
673   mp3_buf = gst_buffer_new_and_alloc (mp3_buffer_size);
674   gst_buffer_map (mp3_buf, &mp3_map, GST_MAP_WRITE);
675
676   if (twolame->num_channels == 1) {
677     if (twolame->float_input)
678       mp3_size = twolame_encode_buffer_float32 (twolame->glopts,
679           (float *) map.data,
680           (float *) map.data, num_samples, mp3_map.data, mp3_buffer_size);
681     else
682       mp3_size = twolame_encode_buffer (twolame->glopts,
683           (short int *) map.data,
684           (short int *) map.data, num_samples, mp3_map.data, mp3_buffer_size);
685   } else {
686     if (twolame->float_input)
687       mp3_size = twolame_encode_buffer_float32_interleaved (twolame->glopts,
688           (float *) map.data,
689           num_samples / twolame->num_channels, mp3_map.data, mp3_buffer_size);
690     else
691       mp3_size = twolame_encode_buffer_interleaved (twolame->glopts,
692           (short int *) map.data,
693           num_samples / twolame->num_channels, mp3_map.data, mp3_buffer_size);
694   }
695
696   GST_LOG_OBJECT (twolame, "encoded %" G_GSIZE_FORMAT " bytes of audio "
697       "to %d bytes of mp3", map.size, mp3_size);
698
699   gst_buffer_unmap (buf, &map);
700   gst_buffer_unmap (mp3_buf, &mp3_map);
701
702   if (mp3_size > 0) {
703     gst_buffer_set_size (mp3_buf, mp3_size);
704     result = gst_audio_encoder_finish_frame (enc, mp3_buf, -1);
705   } else {
706     if (mp3_size < 0) {
707       /* eat error ? */
708       g_warning ("error %d", mp3_size);
709     }
710     gst_buffer_unref (mp3_buf);
711     result = GST_FLOW_OK;
712   }
713
714   return result;
715 }
716
717 /* set up the encoder state */
718 static gboolean
719 gst_two_lame_setup (GstTwoLame * twolame)
720 {
721
722 #define CHECK_ERROR(command) G_STMT_START {\
723   if ((command) < 0) { \
724     GST_ERROR_OBJECT (twolame, "setup failed: " G_STRINGIFY (command)); \
725     return FALSE; \
726   } \
727 }G_STMT_END
728
729   int retval;
730   GstCaps *allowed_caps;
731
732   GST_DEBUG_OBJECT (twolame, "starting setup");
733
734   /* check if we're already setup; if we are, we might want to check
735    * if this initialization is compatible with the previous one */
736   /* FIXME: do this */
737   if (twolame->setup) {
738     GST_WARNING_OBJECT (twolame, "already setup");
739     twolame->setup = FALSE;
740   }
741
742   twolame->glopts = twolame_init ();
743
744   if (twolame->glopts == NULL)
745     return FALSE;
746
747   /* copy the parameters over */
748   twolame_set_in_samplerate (twolame->glopts, twolame->samplerate);
749
750   /* let twolame choose default samplerate unless outgoing sample rate is fixed */
751   allowed_caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (twolame));
752
753   if (allowed_caps != NULL) {
754     GstStructure *structure;
755     gint samplerate;
756
757     structure = gst_caps_get_structure (allowed_caps, 0);
758
759     if (gst_structure_get_int (structure, "rate", &samplerate)) {
760       GST_DEBUG_OBJECT (twolame,
761           "Setting sample rate to %d as fixed in src caps", samplerate);
762       twolame_set_out_samplerate (twolame->glopts, samplerate);
763     } else {
764       GST_DEBUG_OBJECT (twolame, "Letting twolame choose sample rate");
765       twolame_set_out_samplerate (twolame->glopts, 0);
766     }
767     gst_caps_unref (allowed_caps);
768     allowed_caps = NULL;
769   } else {
770     GST_DEBUG_OBJECT (twolame,
771         "No peer yet, letting twolame choose sample rate");
772     twolame_set_out_samplerate (twolame->glopts, 0);
773   }
774
775   /* force mono encoding if we only have one channel */
776   if (twolame->num_channels == 1)
777     twolame->mode = 3;
778
779   /* Fix bitrates and MPEG version */
780
781   CHECK_ERROR (twolame_set_num_channels (twolame->glopts,
782           twolame->num_channels));
783
784   CHECK_ERROR (twolame_set_mode (twolame->glopts, twolame->mode));
785   CHECK_ERROR (twolame_set_psymodel (twolame->glopts, twolame->psymodel));
786   CHECK_AND_FIXUP_BITRATE (twolame, "bitrate", twolame->bitrate);
787   CHECK_ERROR (twolame_set_bitrate (twolame->glopts, twolame->bitrate));
788   CHECK_ERROR (twolame_set_padding (twolame->glopts, twolame->padding));
789   CHECK_ERROR (twolame_set_energy_levels (twolame->glopts,
790           twolame->energy_level_extension));
791   CHECK_ERROR (twolame_set_emphasis (twolame->glopts, twolame->emphasis));
792   CHECK_ERROR (twolame_set_error_protection (twolame->glopts,
793           twolame->error_protection));
794   CHECK_ERROR (twolame_set_copyright (twolame->glopts, twolame->copyright));
795   CHECK_ERROR (twolame_set_original (twolame->glopts, twolame->original));
796   CHECK_ERROR (twolame_set_VBR (twolame->glopts, twolame->vbr));
797   CHECK_ERROR (twolame_set_VBR_level (twolame->glopts, twolame->vbr_level));
798   CHECK_ERROR (twolame_set_ATH_level (twolame->glopts, twolame->ath_level));
799   CHECK_AND_FIXUP_BITRATE (twolame, "vbr-max-bitrate",
800       twolame->vbr_max_bitrate);
801   CHECK_ERROR (twolame_set_VBR_max_bitrate_kbps (twolame->glopts,
802           twolame->vbr_max_bitrate));
803   CHECK_ERROR (twolame_set_quick_mode (twolame->glopts, twolame->quick_mode));
804   CHECK_ERROR (twolame_set_quick_count (twolame->glopts,
805           twolame->quick_mode_count));
806
807   /* initialize the twolame encoder */
808   if ((retval = twolame_init_params (twolame->glopts)) >= 0) {
809     twolame->setup = TRUE;
810     /* FIXME: it would be nice to print out the mode here */
811     GST_INFO ("twolame encoder setup (%d kbit/s, %d Hz, %d channels)",
812         twolame->bitrate, twolame->samplerate, twolame->num_channels);
813   } else {
814     GST_ERROR_OBJECT (twolame, "twolame_init_params returned %d", retval);
815   }
816
817   GST_DEBUG_OBJECT (twolame, "done with setup");
818
819   return twolame->setup;
820 #undef CHECK_ERROR
821 }
822
823 static gboolean
824 gst_two_lame_get_default_settings (void)
825 {
826   twolame_options *glopts = NULL;
827
828   glopts = twolame_init ();
829   if (glopts == NULL) {
830     GST_ERROR ("Couldn't initialize TwoLAME");
831     return FALSE;
832   }
833
834   twolame_set_num_channels (glopts, 2);
835   twolame_set_in_samplerate (glopts, 44100);
836
837   if (twolame_init_params (glopts) != 0) {
838     GST_ERROR ("Couldn't set default parameters");
839     return FALSE;
840   }
841
842   gst_two_lame_default_settings.mode = TWOLAME_JOINT_STEREO;    /* twolame_get_mode (glopts); */
843   gst_two_lame_default_settings.psymodel = twolame_get_psymodel (glopts);
844   gst_two_lame_default_settings.bitrate = twolame_get_bitrate (glopts);
845   gst_two_lame_default_settings.padding = twolame_get_padding (glopts);
846   gst_two_lame_default_settings.energy_level_extension =
847       twolame_get_energy_levels (glopts);
848   gst_two_lame_default_settings.emphasis = twolame_get_emphasis (glopts);
849   gst_two_lame_default_settings.error_protection =
850       twolame_get_error_protection (glopts);
851   gst_two_lame_default_settings.copyright = twolame_get_copyright (glopts);
852   gst_two_lame_default_settings.original = twolame_get_original (glopts);
853   gst_two_lame_default_settings.vbr = twolame_get_VBR (glopts);
854   gst_two_lame_default_settings.vbr_level = twolame_get_VBR_level (glopts);
855   gst_two_lame_default_settings.ath_level = twolame_get_ATH_level (glopts);
856   gst_two_lame_default_settings.vbr_max_bitrate =
857       twolame_get_VBR_max_bitrate_kbps (glopts);
858   gst_two_lame_default_settings.quick_mode = twolame_get_quick_mode (glopts);
859   gst_two_lame_default_settings.quick_mode_count =
860       twolame_get_quick_count (glopts);
861
862   twolame_close (&glopts);
863
864   return TRUE;
865 }
866
867 static gboolean
868 plugin_init (GstPlugin * plugin)
869 {
870   GST_DEBUG_CATEGORY_INIT (debug, "twolame", 0, "twolame mp2 encoder");
871
872   if (!gst_two_lame_get_default_settings ())
873     return FALSE;
874
875 #ifdef ENABLE_NLS
876   GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE,
877       LOCALEDIR);
878   bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
879   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
880 #endif /* ENABLE_NLS */
881
882   if (!gst_element_register (plugin, "twolamemp2enc", GST_RANK_PRIMARY,
883           GST_TYPE_TWO_LAME))
884     return FALSE;
885
886   return TRUE;
887 }
888
889 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
890     GST_VERSION_MINOR,
891     twolame,
892     "Encode MP2s with TwoLAME",
893     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);