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