1 /* GStreamer
2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
18 */
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include "string.h"
24 #include "gstlame.h"
26 /* elementfactory information */
27 static GstElementDetails gst_lame_details = {
28 "L.A.M.E. mp3 encoder",
29 "Codec/Audio/Encoder",
30 "High-quality free MP3 encoder",
31 "Erik Walthinsen <omega@cse.ogi.edu>",
32 };
34 static GstStaticPadTemplate gst_lame_sink_template =
35 GST_STATIC_PAD_TEMPLATE ("sink",
36 GST_PAD_SINK,
37 GST_PAD_ALWAYS,
38 GST_STATIC_CAPS ("audio/x-raw-int, "
39 "endianness = (int) BYTE_ORDER, "
40 "signed = (boolean) true, "
41 "width = (int) 16, "
42 "depth = (int) 16, "
43 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
44 "channels = (int) [ 1, 2 ]")
45 );
47 static GstStaticPadTemplate gst_lame_src_template =
48 GST_STATIC_PAD_TEMPLATE ("src",
49 GST_PAD_SRC,
50 GST_PAD_ALWAYS,
51 GST_STATIC_CAPS ("audio/mpeg, "
52 "mpegversion = (int) 1, "
53 "layer = (int) 3, "
54 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
55 "channels = (int) [ 1, 2 ]")
56 );
58 /********** Define useful types for non-programmatic interfaces **********/
59 #define GST_TYPE_LAME_MODE (gst_lame_mode_get_type())
60 static GType
61 gst_lame_mode_get_type (void)
62 {
63 static GType lame_mode_type = 0;
64 static GEnumValue lame_modes[] = {
65 {0, "0", "Stereo"},
66 {1, "1", "Joint-Stereo"},
67 {2, "2", "Dual channel"},
68 {3, "3", "Mono"},
69 {4, "4", "Auto"},
70 {0, NULL, NULL},
71 };
73 if (!lame_mode_type) {
74 lame_mode_type = g_enum_register_static ("GstLameMode", lame_modes);
75 }
76 return lame_mode_type;
77 }
79 #define GST_TYPE_LAME_QUALITY (gst_lame_quality_get_type())
80 static GType
81 gst_lame_quality_get_type (void)
82 {
83 static GType lame_quality_type = 0;
84 static GEnumValue lame_quality[] = {
85 {0, "0", "0 - Best"},
86 {1, "1", "1"},
87 {2, "2", "2"},
88 {3, "3", "3"},
89 {4, "4", "4"},
90 {5, "5", "5 - Default"},
91 {6, "6", "6"},
92 {7, "7", "7"},
93 {8, "8", "8"},
94 {9, "9", "9 - Worst"},
95 {0, NULL, NULL},
96 };
98 if (!lame_quality_type) {
99 lame_quality_type = g_enum_register_static ("GstLameQuality", lame_quality);
100 }
101 return lame_quality_type;
102 }
104 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
105 static GType
106 gst_lame_padding_get_type (void)
107 {
108 static GType lame_padding_type = 0;
109 static GEnumValue lame_padding[] = {
110 {0, "0", "No Padding"},
111 {1, "1", "Always Pad"},
112 {2, "2", "Adjust Padding"},
113 {0, NULL, NULL},
114 };
116 if (!lame_padding_type) {
117 lame_padding_type = g_enum_register_static ("GstLamePadding", lame_padding);
118 }
119 return lame_padding_type;
120 }
122 /********** Standard stuff for signals and arguments **********/
123 /* GstLame signals and args */
124 enum
125 {
126 /* FILL_ME */
127 LAST_SIGNAL
128 };
130 enum
131 {
132 ARG_0,
133 ARG_BITRATE,
134 ARG_COMPRESSION_RATIO,
135 ARG_QUALITY,
136 ARG_MODE,
137 ARG_FORCE_MS,
138 ARG_FREE_FORMAT,
139 ARG_COPYRIGHT,
140 ARG_ORIGINAL,
141 ARG_ERROR_PROTECTION,
142 ARG_PADDING_TYPE,
143 ARG_EXTENSION,
144 ARG_STRICT_ISO,
145 ARG_DISABLE_RESERVOIR,
146 ARG_VBR,
147 ARG_VBR_MEAN_BITRATE,
148 ARG_VBR_MIN_BITRATE,
149 ARG_VBR_MAX_BITRATE,
150 ARG_VBR_HARD_MIN,
151 ARG_LOWPASS_FREQ,
152 ARG_LOWPASS_WIDTH,
153 ARG_HIGHPASS_FREQ,
154 ARG_HIGHPASS_WIDTH,
155 ARG_ATH_ONLY,
156 ARG_ATH_SHORT,
157 ARG_NO_ATH,
158 ARG_ATH_LOWER,
159 ARG_CWLIMIT,
160 ARG_ALLOW_DIFF_SHORT,
161 ARG_NO_SHORT_BLOCKS,
162 ARG_EMPHASIS,
163 };
165 static void gst_lame_base_init (gpointer g_class);
166 static void gst_lame_class_init (GstLameClass * klass);
167 static void gst_lame_init (GstLame * gst_lame);
169 static void gst_lame_set_property (GObject * object, guint prop_id,
170 const GValue * value, GParamSpec * pspec);
171 static void gst_lame_get_property (GObject * object, guint prop_id,
172 GValue * value, GParamSpec * pspec);
173 static void gst_lame_chain (GstPad * pad, GstData * _data);
174 static gboolean gst_lame_setup (GstLame * lame);
175 static GstElementStateReturn gst_lame_change_state (GstElement * element);
177 static GstElementClass *parent_class = NULL;
179 /* static guint gst_lame_signals[LAST_SIGNAL] = { 0 }; */
181 GType
182 gst_lame_get_type (void)
183 {
184 static GType gst_lame_type = 0;
186 if (!gst_lame_type) {
187 static const GTypeInfo gst_lame_info = {
188 sizeof (GstLameClass),
189 gst_lame_base_init,
190 NULL,
191 (GClassInitFunc) gst_lame_class_init,
192 NULL,
193 NULL,
194 sizeof (GstLame),
195 0,
196 (GInstanceInitFunc) gst_lame_init,
197 };
199 static const GInterfaceInfo tag_setter_info = {
200 NULL,
201 NULL,
202 NULL
203 };
205 gst_lame_type =
206 g_type_register_static (GST_TYPE_ELEMENT, "GstLame", &gst_lame_info, 0);
207 g_type_add_interface_static (gst_lame_type, GST_TYPE_TAG_SETTER,
208 &tag_setter_info);
210 }
211 return gst_lame_type;
212 }
214 static void
215 gst_lame_base_init (gpointer g_class)
216 {
217 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
219 gst_element_class_add_pad_template (element_class,
220 gst_static_pad_template_get (&gst_lame_src_template));
221 gst_element_class_add_pad_template (element_class,
222 gst_static_pad_template_get (&gst_lame_sink_template));
223 gst_element_class_set_details (element_class, &gst_lame_details);
224 }
226 static void
227 gst_lame_class_init (GstLameClass * klass)
228 {
229 GObjectClass *gobject_class;
230 GstElementClass *gstelement_class;
232 gobject_class = (GObjectClass *) klass;
233 gstelement_class = (GstElementClass *) klass;
235 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
237 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
238 g_param_spec_int ("bitrate", "Bitrate (kb/s)", "Bitrate in kbit/sec",
239 8, 320, 128, G_PARAM_READWRITE));
240 g_object_class_install_property (G_OBJECT_CLASS (klass),
241 ARG_COMPRESSION_RATIO, g_param_spec_float ("compression_ratio",
242 "Compression Ratio",
243 "choose bitrate to achive selected compression ratio", 1.0, 200.0,
244 11.0, G_PARAM_READWRITE));
245 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
246 g_param_spec_enum ("quality", "Quality", "Encoding Quality",
247 GST_TYPE_LAME_QUALITY, 5, G_PARAM_READWRITE));
248 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
249 g_param_spec_enum ("mode", "Mode", "Encoding mode", GST_TYPE_LAME_MODE, 0,
250 G_PARAM_READWRITE));
251 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FORCE_MS,
252 g_param_spec_boolean ("force_ms", "Force ms",
253 "Force ms_stereo on all frames", TRUE, G_PARAM_READWRITE));
254 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREE_FORMAT,
255 g_param_spec_boolean ("free_format", "Free format",
256 "Produce a free format bitstream", TRUE, G_PARAM_READWRITE));
257 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPYRIGHT,
258 g_param_spec_boolean ("copyright", "Copyright", "Mark as copyright", TRUE,
259 G_PARAM_READWRITE));
260 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ORIGINAL,
261 g_param_spec_boolean ("original", "Original", "Mark as non-original",
262 TRUE, G_PARAM_READWRITE));
263 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_PROTECTION,
264 g_param_spec_boolean ("error_protection", "Error protection",
265 "Adds 16 bit checksum to every frame", TRUE, G_PARAM_READWRITE));
266 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PADDING_TYPE,
267 g_param_spec_enum ("padding_type", "Padding type", "Padding type",
268 GST_TYPE_LAME_PADDING, 0, G_PARAM_READWRITE));
269 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EXTENSION,
270 g_param_spec_boolean ("extension", "Extension", "Extension", TRUE,
271 G_PARAM_READWRITE));
272 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STRICT_ISO,
273 g_param_spec_boolean ("strict_iso", "Strict ISO",
274 "Comply as much as possible to ISO MPEG spec", TRUE,
275 G_PARAM_READWRITE));
276 g_object_class_install_property (G_OBJECT_CLASS (klass),
277 ARG_DISABLE_RESERVOIR, g_param_spec_boolean ("disable_reservoir",
278 "Disable reservoir", "Disable the bit reservoir", TRUE,
279 G_PARAM_READWRITE));
280 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
281 g_param_spec_boolean ("vbr", "VBR", "Use variable bitrate", TRUE,
282 G_PARAM_READWRITE));
283 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MEAN_BITRATE,
284 g_param_spec_int ("vbr_mean_bitrate", "VBR mean bitrate",
285 "Specify mean bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
286 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MIN_BITRATE,
287 g_param_spec_int ("vbr_min_bitrate", "VBR min bitrate",
288 "Specify min bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
289 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MAX_BITRATE,
290 g_param_spec_int ("vbr_max_bitrate", "VBR max bitrate",
291 "Specify max bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
292 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_HARD_MIN,
293 g_param_spec_int ("vbr_hard_min", "VBR hard min",
294 "Specify hard min bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
295 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_FREQ,
296 g_param_spec_int ("lowpass_freq", "Lowpass freq",
297 "frequency(kHz), lowpass filter cutoff above freq", 0, 50000, 0,
298 G_PARAM_READWRITE));
299 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_WIDTH,
300 g_param_spec_int ("lowpass_width", "Lowpass width",
301 "frequency(kHz) - default 15% of lowpass freq", 0, G_MAXINT, 0,
302 G_PARAM_READWRITE));
303 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_FREQ,
304 g_param_spec_int ("highpass_freq", "Highpass freq",
305 "frequency(kHz), highpass filter cutoff below freq", 0, 50000, 0,
306 G_PARAM_READWRITE));
307 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_WIDTH,
308 g_param_spec_int ("highpass_width", "Highpass width",
309 "frequency(kHz) - default 15% of highpass freq", 0, G_MAXINT, 0,
310 G_PARAM_READWRITE));
311 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_ONLY,
312 g_param_spec_boolean ("ath_only", "ATH only",
313 "Ignore GPSYCHO completely, use ATH only", TRUE, G_PARAM_READWRITE));
314 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_SHORT,
315 g_param_spec_boolean ("ath_short", "ATH short",
316 "Ignore GPSYCHO for short blocks, use ATH only", TRUE,
317 G_PARAM_READWRITE));
318 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_ATH,
319 g_param_spec_boolean ("no_ath", "No ath",
320 "turns ATH down to a flat noise floor", TRUE, G_PARAM_READWRITE));
321 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_LOWER,
322 g_param_spec_int ("ath_lower", "ATH lower", "lowers ATH by x dB",
323 G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
324 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CWLIMIT,
325 g_param_spec_int ("cwlimit", "Cwlimit",
326 "Compute tonality up to freq (in kHz) default 8.8717", 0, 50000, 0,
327 G_PARAM_READWRITE));
328 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ALLOW_DIFF_SHORT,
329 g_param_spec_boolean ("allow_diff_short", "Allow diff short",
330 "Allow diff short", TRUE, G_PARAM_READWRITE));
331 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_SHORT_BLOCKS,
332 g_param_spec_boolean ("no_short_blocks", "No short blocks",
333 "Do not use short blocks", TRUE, G_PARAM_READWRITE));
334 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EMPHASIS,
335 g_param_spec_boolean ("emphasis", "Emphasis", "Emphasis", TRUE,
336 G_PARAM_READWRITE));
338 gobject_class->set_property = gst_lame_set_property;
339 gobject_class->get_property = gst_lame_get_property;
341 gstelement_class->change_state = gst_lame_change_state;
342 }
344 static GstPadLinkReturn
345 gst_lame_sink_link (GstPad * pad, const GstCaps * caps)
346 {
347 GstLame *lame;
348 gint out_samplerate;
349 GstStructure *structure;
350 GstCaps *othercaps;
352 lame = GST_LAME (gst_pad_get_parent (pad));
353 structure = gst_caps_get_structure (caps, 0);
355 gst_structure_get_int (structure, "rate", &lame->samplerate);
356 gst_structure_get_int (structure, "channels", &lame->num_channels);
358 if (!gst_lame_setup (lame)) {
359 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
360 ("could not initialize encoder (wrong parameters?)"));
361 return GST_PAD_LINK_REFUSED;
362 }
364 out_samplerate = lame_get_out_samplerate (lame->lgf);
365 othercaps =
366 gst_caps_new_simple ("audio/mpeg",
367 "mpegversion", G_TYPE_INT, 1,
368 "layer", G_TYPE_INT, 3,
369 "channels", G_TYPE_INT, lame->num_channels,
370 "rate", G_TYPE_INT, out_samplerate, NULL);
372 return gst_pad_try_set_caps (lame->srcpad, othercaps);
373 }
375 static void
376 gst_lame_init (GstLame * lame)
377 {
378 GST_DEBUG_OBJECT (lame, "starting initialization");
380 lame->sinkpad =
381 gst_pad_new_from_template (gst_static_pad_template_get
382 (&gst_lame_sink_template), "sink");
383 gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
384 gst_pad_set_chain_function (lame->sinkpad, gst_lame_chain);
385 gst_pad_set_link_function (lame->sinkpad, gst_lame_sink_link);
387 lame->srcpad =
388 gst_pad_new_from_template (gst_static_pad_template_get
389 (&gst_lame_src_template), "src");
390 gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
392 GST_FLAG_SET (lame, GST_ELEMENT_EVENT_AWARE);
394 GST_DEBUG ("setting up lame encoder");
395 lame->lgf = lame_init ();
397 lame->samplerate = 44100;
398 lame->num_channels = 2;
399 lame->initialized = FALSE;
401 lame->bitrate = 128; /* lame_get_brate (lame->lgf); => 0/out of range */
402 lame->compression_ratio = 5; /* lame_get_compression_ratio (lame->lgf); => 0/out of range */
403 lame->quality = 5; /* lame_get_quality (lame->lgf); => -1/out of range */
404 lame->mode = lame_get_mode (lame->lgf);
405 lame->force_ms = lame_get_force_ms (lame->lgf);
406 lame->free_format = lame_get_free_format (lame->lgf);
407 lame->copyright = lame_get_copyright (lame->lgf);
408 lame->original = lame_get_original (lame->lgf);
409 lame->error_protection = lame_get_error_protection (lame->lgf);
410 lame->padding_type = lame_get_padding_type (lame->lgf);
411 lame->extension = lame_get_extension (lame->lgf);
412 lame->strict_iso = lame_get_strict_ISO (lame->lgf);
413 lame->disable_reservoir = lame_get_disable_reservoir (lame->lgf);
414 lame->vbr = lame_get_VBR_q (lame->lgf);
415 lame->vbr_mean_bitrate = lame_get_VBR_mean_bitrate_kbps (lame->lgf);
416 lame->vbr_min_bitrate = lame_get_VBR_min_bitrate_kbps (lame->lgf);
417 lame->vbr_max_bitrate = 320; /* lame_get_VBR_max_bitrate_kbps (lame->lgf); => 0/no vbr possible */
418 lame->vbr_hard_min = lame_get_VBR_hard_min (lame->lgf);
419 lame->lowpass_freq = 50000; /* lame_get_lowpassfreq (lame->lgf); => 0/lowpass on everything ? */
420 lame->lowpass_width = 0; /* lame_get_lowpasswidth (lame->lgf); => -1/out of range */
421 lame->highpass_freq = lame_get_highpassfreq (lame->lgf);
422 lame->highpass_width = 0; /* lame_get_highpasswidth (lame->lgf); => -1/out of range */
423 lame->ath_only = lame_get_ATHonly (lame->lgf);
424 lame->ath_short = lame_get_ATHshort (lame->lgf);
425 lame->no_ath = lame_get_noATH (lame->lgf);
426 /* lame->ath_type = lame_get_ATHtype (lame->lgf); */
427 lame->ath_lower = lame_get_ATHlower (lame->lgf);
428 lame->cwlimit = 8.8717; /* lame_get_cwlimit (lame->lgf); => 0 */
429 lame->allow_diff_short = lame_get_allow_diff_short (lame->lgf);
430 lame->no_short_blocks = lame_get_no_short_blocks (lame->lgf);
431 lame->emphasis = lame_get_emphasis (lame->lgf);
432 lame->tags = gst_tag_list_new ();
434 id3tag_init (lame->lgf);
436 GST_DEBUG_OBJECT (lame, "done initializing");
437 }
439 typedef struct _GstLameTagMatch GstLameTagMatch;
440 typedef void (*GstLameTagFunc) (lame_global_flags * gfp, const char *value);
442 struct _GstLameTagMatch
443 {
444 gchar *gstreamer_tag;
445 GstLameTagFunc tag_func;
446 };
448 static GstLameTagMatch tag_matches[] = {
449 {GST_TAG_TITLE, id3tag_set_title},
450 {GST_TAG_DATE, id3tag_set_year},
451 {GST_TAG_TRACK_NUMBER, id3tag_set_track},
452 {GST_TAG_COMMENT, id3tag_set_comment},
453 {GST_TAG_ARTIST, id3tag_set_artist},
454 {GST_TAG_ALBUM, id3tag_set_album},
455 {GST_TAG_GENRE, (GstLameTagFunc) id3tag_set_genre},
456 {NULL, NULL}
457 };
459 static void
460 add_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data)
461 {
462 GstLame *lame;
463 gchar *value;
464 int i = 0;
466 lame = GST_LAME (user_data);
467 g_return_if_fail (lame != NULL);
469 while (tag_matches[i].gstreamer_tag != NULL) {
470 if (strcmp (tag, tag_matches[i].gstreamer_tag) == 0) {
471 break;
472 }
473 i++;
474 }
476 if (tag_matches[i].tag_func == NULL) {
477 g_print ("Couldn't find matching gstreamer tag for %s\n", tag);
478 return;
479 }
481 switch (gst_tag_get_type (tag)) {
482 case G_TYPE_UINT:{
483 guint ivalue;
485 if (!gst_tag_list_get_uint (list, tag, &ivalue)) {
486 GST_DEBUG ("Error reading \"%s\" tag value\n", tag);
487 return;
488 }
489 value = g_strdup_printf ("%u", ivalue);
490 break;
491 }
492 case G_TYPE_STRING:
493 if (!gst_tag_list_get_string (list, tag, &value)) {
494 GST_DEBUG ("Error reading \"%s\" tag value\n", tag);
495 return;
496 };
497 break;
498 default:
499 GST_DEBUG ("Couldn't write tag %s", tag);
500 break;
501 }
503 tag_matches[i].tag_func (lame->lgf, value);
505 if (gst_tag_get_type (tag) == G_TYPE_UINT) {
506 g_free (value);
507 }
508 }
510 static void
511 gst_lame_set_metadata (GstLame * lame)
512 {
513 const GstTagList *user_tags;
514 GstTagList *copy;
516 g_return_if_fail (lame != NULL);
517 user_tags = gst_tag_setter_get_list (GST_TAG_SETTER (lame));
518 if ((lame->tags == NULL) && (user_tags == NULL)) {
519 return;
520 }
521 copy = gst_tag_list_merge (user_tags, lame->tags,
522 gst_tag_setter_get_merge_mode (GST_TAG_SETTER (lame)));
523 gst_tag_list_foreach ((GstTagList *) copy, add_one_tag, lame);
525 gst_tag_list_free (copy);
526 }
530 static void
531 gst_lame_set_property (GObject * object, guint prop_id, const GValue * value,
532 GParamSpec * pspec)
533 {
534 GstLame *lame;
536 /* it's not null if we got it, but it might not be ours */
537 g_return_if_fail (GST_IS_LAME (object));
539 lame = GST_LAME (object);
541 switch (prop_id) {
542 case ARG_BITRATE:
543 lame->bitrate = g_value_get_int (value);
544 break;
545 case ARG_COMPRESSION_RATIO:
546 lame->compression_ratio = g_value_get_float (value);
547 break;
548 case ARG_QUALITY:
549 lame->quality = g_value_get_enum (value);
550 break;
551 case ARG_MODE:
552 lame->mode = g_value_get_enum (value);
553 break;
554 case ARG_FORCE_MS:
555 lame->force_ms = g_value_get_boolean (value);
556 break;
557 case ARG_FREE_FORMAT:
558 lame->free_format = g_value_get_boolean (value);
559 break;
560 case ARG_COPYRIGHT:
561 lame->copyright = g_value_get_boolean (value);
562 break;
563 case ARG_ORIGINAL:
564 lame->original = g_value_get_boolean (value);
565 break;
566 case ARG_ERROR_PROTECTION:
567 lame->error_protection = g_value_get_boolean (value);
568 break;
569 case ARG_PADDING_TYPE:
570 lame->padding_type = g_value_get_int (value);
571 break;
572 case ARG_EXTENSION:
573 lame->extension = g_value_get_boolean (value);
574 break;
575 case ARG_STRICT_ISO:
576 lame->strict_iso = g_value_get_boolean (value);
577 break;
578 case ARG_DISABLE_RESERVOIR:
579 lame->disable_reservoir = g_value_get_boolean (value);
580 break;
581 case ARG_VBR:
582 lame->vbr = g_value_get_boolean (value);
583 break;
584 case ARG_VBR_MEAN_BITRATE:
585 lame->vbr_mean_bitrate = g_value_get_int (value);
586 break;
587 case ARG_VBR_MIN_BITRATE:
588 lame->vbr_min_bitrate = g_value_get_int (value);
589 break;
590 case ARG_VBR_MAX_BITRATE:
591 lame->vbr_max_bitrate = g_value_get_int (value);
592 break;
593 case ARG_VBR_HARD_MIN:
594 lame->vbr_hard_min = g_value_get_int (value);
595 break;
596 case ARG_LOWPASS_FREQ:
597 lame->lowpass_freq = g_value_get_int (value);
598 break;
599 case ARG_LOWPASS_WIDTH:
600 lame->lowpass_width = g_value_get_int (value);
601 break;
602 case ARG_HIGHPASS_FREQ:
603 lame->highpass_freq = g_value_get_int (value);
604 break;
605 case ARG_HIGHPASS_WIDTH:
606 lame->highpass_width = g_value_get_int (value);
607 break;
608 case ARG_ATH_ONLY:
609 lame->ath_only = g_value_get_boolean (value);
610 break;
611 case ARG_ATH_SHORT:
612 lame->ath_short = g_value_get_boolean (value);
613 break;
614 case ARG_NO_ATH:
615 lame->no_ath = g_value_get_boolean (value);
616 break;
617 case ARG_ATH_LOWER:
618 lame->ath_lower = g_value_get_int (value);
619 break;
620 case ARG_CWLIMIT:
621 lame->cwlimit = g_value_get_int (value);
622 break;
623 case ARG_ALLOW_DIFF_SHORT:
624 lame->allow_diff_short = g_value_get_boolean (value);
625 break;
626 case ARG_NO_SHORT_BLOCKS:
627 lame->no_short_blocks = g_value_get_boolean (value);
628 break;
629 case ARG_EMPHASIS:
630 lame->emphasis = g_value_get_boolean (value);
631 break;
632 default:
633 break;
634 }
636 }
638 static void
639 gst_lame_get_property (GObject * object, guint prop_id, GValue * value,
640 GParamSpec * pspec)
641 {
642 GstLame *lame;
644 /* it's not null if we got it, but it might not be ours */
645 g_return_if_fail (GST_IS_LAME (object));
647 lame = GST_LAME (object);
649 switch (prop_id) {
650 case ARG_BITRATE:
651 g_value_set_int (value, lame->bitrate);
652 break;
653 case ARG_COMPRESSION_RATIO:
654 g_value_set_float (value, lame->compression_ratio);
655 break;
656 case ARG_QUALITY:
657 g_value_set_enum (value, lame->quality);
658 break;
659 case ARG_MODE:
660 g_value_set_enum (value, lame->mode);
661 break;
662 case ARG_FORCE_MS:
663 g_value_set_boolean (value, lame->force_ms);
664 break;
665 case ARG_FREE_FORMAT:
666 g_value_set_boolean (value, lame->free_format);
667 break;
668 case ARG_COPYRIGHT:
669 g_value_set_boolean (value, lame->copyright);
670 break;
671 case ARG_ORIGINAL:
672 g_value_set_boolean (value, lame->original);
673 break;
674 case ARG_ERROR_PROTECTION:
675 g_value_set_boolean (value, lame->error_protection);
676 break;
677 case ARG_PADDING_TYPE:
678 g_value_set_enum (value, lame->padding_type);
679 break;
680 case ARG_EXTENSION:
681 g_value_set_boolean (value, lame->extension);
682 break;
683 case ARG_STRICT_ISO:
684 g_value_set_boolean (value, lame->strict_iso);
685 break;
686 case ARG_DISABLE_RESERVOIR:
687 g_value_set_boolean (value, lame->disable_reservoir);
688 break;
689 case ARG_VBR:
690 g_value_set_boolean (value, lame->vbr);
691 break;
692 case ARG_VBR_MEAN_BITRATE:
693 g_value_set_int (value, lame->vbr_mean_bitrate);
694 break;
695 case ARG_VBR_MIN_BITRATE:
696 g_value_set_int (value, lame->vbr_min_bitrate);
697 break;
698 case ARG_VBR_MAX_BITRATE:
699 g_value_set_int (value, lame->vbr_max_bitrate);
700 break;
701 case ARG_VBR_HARD_MIN:
702 g_value_set_int (value, lame->vbr_hard_min);
703 break;
704 case ARG_LOWPASS_FREQ:
705 g_value_set_int (value, lame->lowpass_freq);
706 break;
707 case ARG_LOWPASS_WIDTH:
708 g_value_set_int (value, lame->lowpass_width);
709 break;
710 case ARG_HIGHPASS_FREQ:
711 g_value_set_int (value, lame->highpass_freq);
712 break;
713 case ARG_HIGHPASS_WIDTH:
714 g_value_set_int (value, lame->highpass_width);
715 break;
716 case ARG_ATH_ONLY:
717 g_value_set_boolean (value, lame->ath_only);
718 break;
719 case ARG_ATH_SHORT:
720 g_value_set_boolean (value, lame->ath_short);
721 break;
722 case ARG_NO_ATH:
723 g_value_set_boolean (value, lame->no_ath);
724 break;
725 case ARG_ATH_LOWER:
726 g_value_set_int (value, lame->ath_lower);
727 break;
728 case ARG_CWLIMIT:
729 g_value_set_int (value, lame->cwlimit);
730 break;
731 case ARG_ALLOW_DIFF_SHORT:
732 g_value_set_boolean (value, lame->allow_diff_short);
733 break;
734 case ARG_NO_SHORT_BLOCKS:
735 g_value_set_boolean (value, lame->no_short_blocks);
736 break;
737 case ARG_EMPHASIS:
738 g_value_set_boolean (value, lame->emphasis);
739 break;
740 default:
741 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
742 break;
743 }
744 }
746 static void
747 gst_lame_chain (GstPad * pad, GstData * _data)
748 {
749 GstBuffer *buf = GST_BUFFER (_data);
750 GstLame *lame;
751 GstBuffer *outbuf;
752 gchar *mp3_data = NULL;
753 gint mp3_buffer_size, mp3_size = 0;
754 gboolean eos = FALSE;
756 lame = GST_LAME (gst_pad_get_parent (pad));
758 GST_DEBUG ("entered chain");
760 if (GST_IS_EVENT (buf)) {
761 switch (GST_EVENT_TYPE (buf)) {
762 case GST_EVENT_EOS:
763 eos = TRUE;
764 case GST_EVENT_FLUSH:
765 mp3_buffer_size = 7200;
766 mp3_data = g_malloc (mp3_buffer_size);
768 mp3_size = lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
769 gst_event_unref (GST_EVENT (buf));
770 break;
771 case GST_EVENT_TAG:
772 if (lame->tags) {
773 gst_tag_list_insert (lame->tags,
774 gst_event_tag_get_list (GST_EVENT (buf)),
775 gst_tag_setter_get_merge_mode (GST_TAG_SETTER (lame)));
776 } else {
777 g_assert_not_reached ();
778 }
779 // gst_pad_event_default (pad, GST_EVENT (buf));
780 break;
781 default:
782 gst_pad_event_default (pad, GST_EVENT (buf));
783 break;
784 }
785 } else {
786 gint64 duration;
788 if (!lame->initialized) {
789 gst_buffer_unref (buf);
790 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
791 ("encoder not initialized (input is not audio?)"));
792 return;
793 }
795 /* allocate space for output */
796 mp3_buffer_size =
797 ((GST_BUFFER_SIZE (buf) / (2 + lame->num_channels)) * 1.25) + 7200;
798 mp3_data = g_malloc (mp3_buffer_size);
800 mp3_size = lame_encode_buffer_interleaved (lame->lgf,
801 (short int *) (GST_BUFFER_DATA (buf)),
802 GST_BUFFER_SIZE (buf) / 2 / lame->num_channels,
803 mp3_data, mp3_buffer_size);
805 GST_DEBUG ("encoded %d bytes of audio to %d bytes of mp3",
806 GST_BUFFER_SIZE (buf), mp3_size);
808 duration = (GST_SECOND * GST_BUFFER_SIZE (buf) /
809 (2 * lame->samplerate * lame->num_channels));
811 if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
812 GST_BUFFER_DURATION (buf) != duration)
813 GST_DEBUG ("mad: incoming buffer had incorrect duration %lld, "
814 "outgoing buffer will have correct duration %lld",
815 GST_BUFFER_DURATION (buf), duration);
817 if (lame->last_ts == GST_CLOCK_TIME_NONE) {
818 lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
819 lame->last_offs = GST_BUFFER_OFFSET (buf);
820 lame->last_duration = duration;
821 } else {
822 lame->last_duration += duration;
823 }
825 gst_buffer_unref (buf);
826 }
828 if (mp3_size > 0) {
829 outbuf = gst_buffer_new ();
830 GST_BUFFER_DATA (outbuf) = mp3_data;
831 GST_BUFFER_SIZE (outbuf) = mp3_size;
832 GST_BUFFER_TIMESTAMP (outbuf) = lame->last_ts;
833 GST_BUFFER_OFFSET (outbuf) = lame->last_offs;
834 GST_BUFFER_DURATION (outbuf) = lame->last_duration;
836 gst_pad_push (lame->srcpad, GST_DATA (outbuf));
838 lame->last_ts = GST_CLOCK_TIME_NONE;
839 } else {
840 g_free (mp3_data);
841 }
843 if (eos) {
844 gst_pad_push (lame->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS)));
845 gst_element_set_eos (GST_ELEMENT (lame));
846 }
847 }
849 /* transition to the READY state by configuring the gst_lame encoder */
850 static gboolean
851 gst_lame_setup (GstLame * lame)
852 {
853 GST_DEBUG_OBJECT (lame, "starting setup");
855 /* check if we're already initialized; if we are, we might want to check
856 * if this initialization is compatible with the previous one */
857 /* FIXME: do this */
858 if (lame->initialized)
859 g_warning ("already initialized");
861 /* copy the parameters over */
862 lame_set_in_samplerate (lame->lgf, lame->samplerate);
864 /* force mono encoding if we only have one channel */
865 if (lame->num_channels == 1)
866 lame->mode = 3;
868 lame_set_brate (lame->lgf, lame->bitrate);
869 lame_set_compression_ratio (lame->lgf, lame->compression_ratio);
870 lame_set_quality (lame->lgf, lame->quality);
871 lame_set_mode (lame->lgf, lame->mode);
872 lame_set_force_ms (lame->lgf, lame->force_ms);
873 lame_set_free_format (lame->lgf, lame->free_format);
874 lame_set_copyright (lame->lgf, lame->copyright);
875 lame_set_original (lame->lgf, lame->original);
876 lame_set_error_protection (lame->lgf, lame->error_protection);
877 lame_set_padding_type (lame->lgf, lame->padding_type);
878 lame_set_extension (lame->lgf, lame->extension);
879 lame_set_strict_ISO (lame->lgf, lame->strict_iso);
880 lame_set_disable_reservoir (lame->lgf, lame->disable_reservoir);
881 lame_set_VBR_q (lame->lgf, lame->vbr);
882 lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->vbr_mean_bitrate);
883 lame_set_VBR_min_bitrate_kbps (lame->lgf, lame->vbr_min_bitrate);
884 lame_set_VBR_max_bitrate_kbps (lame->lgf, lame->vbr_max_bitrate);
885 lame_set_VBR_hard_min (lame->lgf, lame->vbr_hard_min);
886 lame_set_lowpassfreq (lame->lgf, lame->lowpass_freq);
887 lame_set_lowpasswidth (lame->lgf, lame->lowpass_width);
888 lame_set_highpassfreq (lame->lgf, lame->highpass_freq);
889 lame_set_highpasswidth (lame->lgf, lame->highpass_width);
890 lame_set_ATHonly (lame->lgf, lame->ath_only);
891 lame_set_ATHshort (lame->lgf, lame->ath_short);
892 lame_set_noATH (lame->lgf, lame->no_ath);
893 lame_set_ATHlower (lame->lgf, lame->ath_lower);
894 lame_set_cwlimit (lame->lgf, lame->cwlimit);
895 lame_set_allow_diff_short (lame->lgf, lame->allow_diff_short);
896 lame_set_no_short_blocks (lame->lgf, lame->no_short_blocks);
897 lame_set_emphasis (lame->lgf, lame->emphasis);
899 gst_lame_set_metadata (lame);
901 /* initialize the lame encoder */
902 if (lame_init_params (lame->lgf) < 0) {
903 lame->initialized = FALSE;
904 } else {
905 lame->initialized = TRUE;
906 /* FIXME: it would be nice to print out the mode here */
907 GST_INFO ("lame encoder initialized (%d kbit/s, %d Hz, %d channels)",
908 lame->bitrate, lame->samplerate, lame->num_channels);
909 }
911 GST_DEBUG_OBJECT (lame, "done with setup");
913 return lame->initialized;
914 }
916 static GstElementStateReturn
917 gst_lame_change_state (GstElement * element)
918 {
919 GstLame *lame;
921 g_return_val_if_fail (GST_IS_LAME (element), GST_STATE_FAILURE);
923 lame = GST_LAME (element);
925 GST_DEBUG ("state pending %d", GST_STATE_PENDING (element));
927 switch (GST_STATE_TRANSITION (element)) {
928 case GST_STATE_READY_TO_PAUSED:
929 lame->last_ts = GST_CLOCK_TIME_NONE;
930 break;
931 case GST_STATE_READY_TO_NULL:
932 if (lame->initialized) {
933 lame_close (lame->lgf);
934 lame->initialized = FALSE;
935 }
936 break;
937 default:
938 break;
939 }
941 /* if we haven't failed already, give the parent class a chance to ;-) */
942 if (GST_ELEMENT_CLASS (parent_class)->change_state)
943 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
945 return GST_STATE_SUCCESS;
946 }
948 static gboolean
949 plugin_init (GstPlugin * plugin)
950 {
951 if (!gst_element_register (plugin, "lame", GST_RANK_NONE, GST_TYPE_LAME))
952 return FALSE;
954 return TRUE;
955 }
957 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
958 GST_VERSION_MINOR,
959 "lame",
960 "Encode MP3's with LAME",
961 plugin_init, VERSION, "LGPL", GST_PACKAGE, GST_ORIGIN)