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
gst_two_lame_mode_get_type(void)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
gst_two_lame_padding_get_type(void)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
gst_two_lame_emphasis_get_type(void)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
gst_two_lame_release_memory(GstTwoLame * twolame)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
gst_two_lame_finalize(GObject * obj)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
gst_two_lame_class_init(GstTwoLameClass * klass)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
gst_two_lame_set_format(GstAudioEncoder * enc,GstAudioInfo * info)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
gst_two_lame_init(GstTwoLame * twolame)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
gst_two_lame_start(GstAudioEncoder * enc)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
gst_two_lame_stop(GstAudioEncoder * enc)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
gst_two_lame_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)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
gst_two_lame_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)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
gst_two_lame_flush_full(GstTwoLame * lame,gboolean push)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
gst_two_lame_flush(GstAudioEncoder * enc)649 gst_two_lame_flush (GstAudioEncoder * enc)
650 {
651 gst_two_lame_flush_full (GST_TWO_LAME (enc), FALSE);
652 }
653
654 static GstFlowReturn
gst_two_lame_handle_frame(GstAudioEncoder * enc,GstBuffer * buf)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
gst_two_lame_setup(GstTwoLame * twolame)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
gst_two_lame_get_default_settings(void)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
two_lame_element_init(void)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
plugin_init(GstPlugin * plugin)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);
901