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 {
29 "L.A.M.E. mp3 encoder",
30 "Codec/Audio/Encoder",
31 "LGPL",
32 "High-quality free MP3 encoder",
33 VERSION,
34 "Erik Walthinsen <omega@cse.ogi.edu>",
35 "(C) 2000",
36 };
38 GST_PAD_TEMPLATE_FACTORY (gst_lame_sink_factory,
39 "sink",
40 GST_PAD_SINK,
41 GST_PAD_ALWAYS,
42 GST_CAPS_NEW (
43 "gstlame_sink",
44 "audio/x-raw-int",
45 "endianness", GST_PROPS_INT (G_BYTE_ORDER),
46 "signed", GST_PROPS_BOOLEAN (TRUE),
47 "width", GST_PROPS_INT (16),
48 "depth", GST_PROPS_INT (16),
49 "rate", GST_PROPS_LIST (
50 GST_PROPS_INT (8000),
51 GST_PROPS_INT (11025),
52 GST_PROPS_INT (12000),
53 GST_PROPS_INT (16000),
54 GST_PROPS_INT (22050),
55 GST_PROPS_INT (24000),
56 GST_PROPS_INT (32000),
57 GST_PROPS_INT (44100),
58 GST_PROPS_INT (48000)
59 ),
60 "channels", GST_PROPS_INT_RANGE (1, 2)
61 )
62 )
64 GST_PAD_TEMPLATE_FACTORY (gst_lame_src_factory,
65 "src",
66 GST_PAD_SRC,
67 GST_PAD_ALWAYS,
68 GST_CAPS_NEW (
69 "gstlame_src",
70 "audio/mpeg",
71 "mpegversion", GST_PROPS_INT (1),
72 "layer", GST_PROPS_INT (3),
73 "rate", GST_PROPS_LIST (
74 GST_PROPS_INT (8000),
75 GST_PROPS_INT (11025),
76 GST_PROPS_INT (12000),
77 GST_PROPS_INT (16000),
78 GST_PROPS_INT (22050),
79 GST_PROPS_INT (24000),
80 GST_PROPS_INT (32000),
81 GST_PROPS_INT (44100),
82 GST_PROPS_INT (48000)
83 ),
84 "channels", GST_PROPS_INT_RANGE (1, 2)
85 )
86 )
88 /********** Define useful types for non-programmatic interfaces **********/
89 #define GST_TYPE_LAME_MODE (gst_lame_mode_get_type())
90 static GType
91 gst_lame_mode_get_type (void)
92 {
93 static GType lame_mode_type = 0;
94 static GEnumValue lame_modes[] = {
95 { 0, "0", "Stereo" },
96 { 1, "1", "Joint-Stereo" },
97 { 2, "2", "Dual channel" },
98 { 3, "3", "Mono" },
99 { 4, "4", "Auto" },
100 { 0, NULL, NULL },
101 };
102 if (!lame_mode_type) {
103 lame_mode_type = g_enum_register_static ("GstLameMode", lame_modes);
104 }
105 return lame_mode_type;
106 }
108 #define GST_TYPE_LAME_QUALITY (gst_lame_quality_get_type())
109 static GType
110 gst_lame_quality_get_type (void)
111 {
112 static GType lame_quality_type = 0;
113 static GEnumValue lame_quality[] = {
114 { 0, "0", "0 - Best" },
115 { 1, "1", "1" },
116 { 2, "2", "2" },
117 { 3, "3", "3" },
118 { 4, "4", "4" },
119 { 5, "5", "5 - Default" },
120 { 6, "6", "6" },
121 { 7, "7", "7" },
122 { 8, "8", "8" },
123 { 9, "9", "9 - Worst" },
124 { 0, NULL, NULL },
125 };
126 if (!lame_quality_type) {
127 lame_quality_type = g_enum_register_static ("GstLameQuality", lame_quality);
128 }
129 return lame_quality_type;
130 }
132 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
133 static GType
134 gst_lame_padding_get_type (void)
135 {
136 static GType lame_padding_type = 0;
137 static GEnumValue lame_padding[] = {
138 { 0, "0", "No Padding" },
139 { 1, "1", "Always Pad" },
140 { 2, "2", "Adjust Padding" },
141 { 0, NULL, NULL },
142 };
143 if (!lame_padding_type) {
144 lame_padding_type = g_enum_register_static ("GstLamePadding", lame_padding);
145 }
146 return lame_padding_type;
147 }
149 /********** Standard stuff for signals and arguments **********/
150 /* GstLame signals and args */
151 enum {
152 /* FILL_ME */
153 LAST_SIGNAL
154 };
156 enum {
157 ARG_0,
158 ARG_BITRATE,
159 ARG_COMPRESSION_RATIO,
160 ARG_QUALITY,
161 ARG_MODE,
162 ARG_FORCE_MS,
163 ARG_FREE_FORMAT,
164 ARG_COPYRIGHT,
165 ARG_ORIGINAL,
166 ARG_ERROR_PROTECTION,
167 ARG_PADDING_TYPE,
168 ARG_EXTENSION,
169 ARG_STRICT_ISO,
170 ARG_DISABLE_RESERVOIR,
171 ARG_VBR,
172 ARG_VBR_MEAN_BITRATE,
173 ARG_VBR_MIN_BITRATE,
174 ARG_VBR_MAX_BITRATE,
175 ARG_VBR_HARD_MIN,
176 ARG_LOWPASS_FREQ,
177 ARG_LOWPASS_WIDTH,
178 ARG_HIGHPASS_FREQ,
179 ARG_HIGHPASS_WIDTH,
180 ARG_ATH_ONLY,
181 ARG_ATH_SHORT,
182 ARG_NO_ATH,
183 ARG_ATH_LOWER,
184 ARG_CWLIMIT,
185 ARG_ALLOW_DIFF_SHORT,
186 ARG_NO_SHORT_BLOCKS,
187 ARG_EMPHASIS,
188 ARG_METADATA,
189 };
192 static void gst_lame_class_init (GstLameClass *klass);
193 static void gst_lame_init (GstLame *gst_lame);
195 static void gst_lame_set_property (GObject *object, guint prop_id,
196 const GValue *value, GParamSpec *pspec);
197 static void gst_lame_get_property (GObject *object, guint prop_id,
198 GValue *value, GParamSpec *pspec);
199 static void gst_lame_chain (GstPad *pad, GstData *_data);
200 static gboolean gst_lame_setup (GstLame *lame);
201 static GstElementStateReturn gst_lame_change_state (GstElement *element);
203 static GstElementClass *parent_class = NULL;
204 /* static guint gst_lame_signals[LAST_SIGNAL] = { 0 }; */
206 GType
207 gst_lame_get_type (void)
208 {
209 static GType gst_lame_type = 0;
211 if (!gst_lame_type) {
212 static const GTypeInfo gst_lame_info = {
213 sizeof (GstLameClass),
214 NULL,
215 NULL,
216 (GClassInitFunc) gst_lame_class_init,
217 NULL,
218 NULL,
219 sizeof(GstLame),
220 0,
221 (GInstanceInitFunc) gst_lame_init,
222 };
223 gst_lame_type = g_type_register_static (GST_TYPE_ELEMENT, "GstLame", &gst_lame_info, 0);
224 }
225 return gst_lame_type;
226 }
228 static void
229 gst_lame_class_init (GstLameClass *klass)
230 {
231 GObjectClass *gobject_class;
232 GstElementClass *gstelement_class;
234 gobject_class = (GObjectClass*)klass;
235 gstelement_class = (GstElementClass*)klass;
237 parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
239 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
240 g_param_spec_int("bitrate", "Bitrate (kb/s)", "Bitrate in kbit/sec",
241 8, 320, 128, G_PARAM_READWRITE));
242 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COMPRESSION_RATIO,
243 g_param_spec_float ("compression_ratio", "Compression Ratio",
244 "choose bitrate to achive selected compression ratio",
245 1.0, 200.0, 11.0, G_PARAM_READWRITE));
246 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
247 g_param_spec_enum ("quality", "Quality", "Encoding Quality",
248 GST_TYPE_LAME_QUALITY, 5, G_PARAM_READWRITE));
249 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
250 g_param_spec_enum ("mode", "Mode", "Encoding mode",
251 GST_TYPE_LAME_MODE, 0, G_PARAM_READWRITE));
252 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FORCE_MS,
253 g_param_spec_boolean ("force_ms","Force ms","Force ms_stereo on all frames",
254 TRUE, G_PARAM_READWRITE));
255 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREE_FORMAT,
256 g_param_spec_boolean ("free_format","Free format","Produce a free format bitstream",
257 TRUE, G_PARAM_READWRITE));
258 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPYRIGHT,
259 g_param_spec_boolean ("copyright","Copyright","Mark as copyright",
260 TRUE, G_PARAM_READWRITE));
261 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_ORIGINAL,
262 g_param_spec_boolean("original", "Original", "Mark as non-original",
263 TRUE, G_PARAM_READWRITE));
264 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_PROTECTION,
265 g_param_spec_boolean ("error_protection","Error protection",
266 "Adds 16 bit checksum to every frame",
267 TRUE, G_PARAM_READWRITE));
268 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PADDING_TYPE,
269 g_param_spec_enum ("padding_type", "Padding type", "Padding type",
270 GST_TYPE_LAME_PADDING, 0, G_PARAM_READWRITE));
271 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EXTENSION,
272 g_param_spec_boolean ("extension", "Extension", "Extension",
273 TRUE, G_PARAM_READWRITE));
274 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STRICT_ISO,
275 g_param_spec_boolean ("strict_iso", "Strict ISO",
276 "Comply as much as possible to ISO MPEG spec",
277 TRUE, G_PARAM_READWRITE));
278 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DISABLE_RESERVOIR,
279 g_param_spec_boolean ("disable_reservoir", "Disable reservoir", "Disable the bit reservoir",
280 TRUE, G_PARAM_READWRITE));
281 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
282 g_param_spec_boolean ("vbr", "VBR", "Use variable bitrate",
283 TRUE, G_PARAM_READWRITE));
284 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MEAN_BITRATE,
285 g_param_spec_int ("vbr_mean_bitrate", "VBR mean bitrate", "Specify mean bitrate",
286 0, G_MAXINT, 0, G_PARAM_READWRITE));
287 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MIN_BITRATE,
288 g_param_spec_int ("vbr_min_bitrate", "VBR min bitrate", "Specify min bitrate",
289 0, G_MAXINT, 0, G_PARAM_READWRITE));
290 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_MAX_BITRATE,
291 g_param_spec_int ("vbr_max_bitrate", "VBR max bitrate", "Specify max bitrate",
292 0, G_MAXINT, 0, G_PARAM_READWRITE));
293 g_object_class_install_property(G_OBJECT_CLASS(klass), ARG_VBR_HARD_MIN,
294 g_param_spec_int ("vbr_hard_min", "VBR hard min", "Specify hard min bitrate",
295 0, G_MAXINT, 0, G_PARAM_READWRITE));
296 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_FREQ,
297 g_param_spec_int ("lowpass_freq", "Lowpass freq",
298 "frequency(kHz), lowpass filter cutoff above freq",
299 0, 50000, 0, G_PARAM_READWRITE));
300 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_WIDTH,
301 g_param_spec_int ("lowpass_width", "Lowpass width",
302 "frequency(kHz) - default 15% of lowpass freq",
303 0, G_MAXINT, 0, G_PARAM_READWRITE));
304 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_FREQ,
305 g_param_spec_int ("highpass_freq", "Highpass freq",
306 "frequency(kHz), highpass filter cutoff below freq",
307 0, 50000, 0, G_PARAM_READWRITE));
308 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_WIDTH,
309 g_param_spec_int ("highpass_width", "Highpass width",
310 "frequency(kHz) - default 15% of highpass freq",
311 0, G_MAXINT, 0, G_PARAM_READWRITE));
312 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_ONLY,
313 g_param_spec_boolean ("ath_only", "ATH only",
314 "Ignore GPSYCHO completely, use ATH only",
315 TRUE, G_PARAM_READWRITE));
316 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_SHORT,
317 g_param_spec_boolean ("ath_short", "ATH short",
318 "Ignore GPSYCHO for short blocks, use ATH only",
319 TRUE, G_PARAM_READWRITE));
320 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_ATH,
321 g_param_spec_boolean ("no_ath", "No ath", "turns ATH down to a flat noise floor",
322 TRUE, G_PARAM_READWRITE));
323 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_LOWER,
324 g_param_spec_int ("ath_lower", "ATH lower", "lowers ATH by x dB",
325 G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
326 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CWLIMIT,
327 g_param_spec_int ("cwlimit", "Cwlimit", "Compute tonality up to freq (in kHz) default 8.8717",
328 0, 50000, 0, G_PARAM_READWRITE));
329 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ALLOW_DIFF_SHORT,
330 g_param_spec_boolean ("allow_diff_short", "Allow diff short", "Allow diff short",
331 TRUE, G_PARAM_READWRITE));
332 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_SHORT_BLOCKS,
333 g_param_spec_boolean ("no_short_blocks", "No short blocks", "Do not use short blocks",
334 TRUE, G_PARAM_READWRITE));
335 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EMPHASIS,
336 g_param_spec_boolean ("emphasis", "Emphasis", "Emphasis",
337 TRUE, G_PARAM_READWRITE));
339 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_METADATA,
340 g_param_spec_boxed ("metadata", "Metadata", "Metadata to add to the stream,",
341 GST_TYPE_CAPS, G_PARAM_READWRITE));
344 gobject_class->set_property = gst_lame_set_property;
345 gobject_class->get_property = gst_lame_get_property;
347 gstelement_class->change_state = gst_lame_change_state;
348 }
350 static GstPadLinkReturn
351 gst_lame_sinkconnect (GstPad *pad, GstCaps *caps)
352 {
353 GstLame *lame;
354 gint out_samplerate;
356 lame = GST_LAME (gst_pad_get_parent (pad));
358 if (!GST_CAPS_IS_FIXED (caps)) {
359 GST_DEBUG ("caps on lame pad %s:%s not fixed, delayed",
360 GST_DEBUG_PAD_NAME (pad));
361 return GST_PAD_LINK_DELAYED;
362 }
364 gst_caps_get_int (caps, "rate", &lame->samplerate);
365 gst_caps_get_int (caps, "channels", &lame->num_channels);
367 if (!gst_lame_setup (lame)) {
368 gst_element_error (GST_ELEMENT (lame),
369 "could not initialize encoder (wrong parameters?)");
370 return GST_PAD_LINK_REFUSED;
371 }
373 out_samplerate = lame_get_out_samplerate (lame->lgf);
374 caps = GST_CAPS_NEW ("lame_src_caps",
375 "audio/mpeg",
376 "mpegversion", GST_PROPS_INT (1),
377 "layer", GST_PROPS_INT (3),
378 "channels", GST_PROPS_INT (lame->num_channels),
379 "rate", GST_PROPS_INT (out_samplerate));
381 return gst_pad_try_set_caps (lame->srcpad, caps);
382 }
384 static void
385 gst_lame_init (GstLame *lame)
386 {
387 GST_DEBUG_OBJECT (lame, "starting initialization");
389 lame->sinkpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (gst_lame_sink_factory), "sink");
390 gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
391 gst_pad_set_chain_function (lame->sinkpad, gst_lame_chain);
392 gst_pad_set_link_function (lame->sinkpad, gst_lame_sinkconnect);
394 lame->srcpad = gst_pad_new_from_template (GST_PAD_TEMPLATE_GET (gst_lame_src_factory), "src");
395 gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
397 GST_FLAG_SET (lame, GST_ELEMENT_EVENT_AWARE);
399 GST_DEBUG ("setting up lame encoder");
400 lame->lgf = lame_init ();
402 lame->samplerate = 44100;
403 lame->num_channels = 2;
404 lame->initialized = FALSE;
406 lame->bitrate = lame_get_brate (lame->lgf);
407 lame->compression_ratio = lame_get_compression_ratio (lame->lgf);
408 lame->quality = lame_get_quality (lame->lgf);
409 lame->mode = lame_get_mode (lame->lgf);
410 lame->force_ms = lame_get_force_ms (lame->lgf);
411 lame->free_format = lame_get_free_format (lame->lgf);
412 lame->copyright = lame_get_copyright (lame->lgf);
413 lame->original = lame_get_original (lame->lgf);
414 lame->error_protection = lame_get_error_protection (lame->lgf);
415 lame->padding_type = lame_get_padding_type (lame->lgf);
416 lame->extension = lame_get_extension (lame->lgf);
417 lame->strict_iso = lame_get_strict_ISO (lame->lgf);
418 lame->disable_reservoir = lame_get_disable_reservoir (lame->lgf);
419 lame->vbr = lame_get_VBR_q (lame->lgf);
420 lame->vbr_mean_bitrate = lame_get_VBR_mean_bitrate_kbps (lame->lgf);
421 lame->vbr_min_bitrate = lame_get_VBR_min_bitrate_kbps (lame->lgf);
422 lame->vbr_max_bitrate = lame_get_VBR_max_bitrate_kbps (lame->lgf);
423 lame->vbr_hard_min = lame_get_VBR_hard_min (lame->lgf);
424 lame->lowpass_freq = lame_get_lowpassfreq (lame->lgf);
425 lame->lowpass_width = lame_get_lowpasswidth (lame->lgf);
426 lame->highpass_freq = lame_get_highpassfreq (lame->lgf);
427 lame->highpass_width = lame_get_highpasswidth (lame->lgf);
428 lame->ath_only = lame_get_ATHonly (lame->lgf);
429 lame->ath_short = lame_get_ATHshort (lame->lgf);
430 lame->no_ath = lame_get_noATH (lame->lgf);
431 /* lame->ath_type = lame_get_ATHtype (lame->lgf); */
432 lame->ath_lower = lame_get_ATHlower (lame->lgf);
433 lame->cwlimit = lame_get_cwlimit (lame->lgf);
434 lame->allow_diff_short = lame_get_allow_diff_short (lame->lgf);
435 lame->no_short_blocks = lame_get_no_short_blocks (lame->lgf);
436 lame->emphasis = lame_get_emphasis (lame->lgf);
438 lame->metadata = GST_CAPS_NEW (
439 "lame_metadata",
440 "application/x-gst-metadata",
441 "comment", GST_PROPS_STRING ("Track encoded with GStreamer"),
442 "year", GST_PROPS_STRING (""),
443 "tracknumber", GST_PROPS_STRING (""),
444 "title", GST_PROPS_STRING (""),
445 "artist", GST_PROPS_STRING (""),
446 "album", GST_PROPS_STRING (""),
447 "genre", GST_PROPS_STRING ("")
448 );
450 id3tag_init (lame->lgf);
452 GST_DEBUG_OBJECT (lame, "done initializing");
453 }
455 static void
456 gst_lame_add_metadata (GstLame *lame, GstCaps *caps)
457 {
458 GList *props;
459 GstPropsEntry *prop;
461 if (caps == NULL)
462 return;
464 props = gst_caps_get_props (caps)->properties;
465 while (props) {
466 prop = (GstPropsEntry*)(props->data);
467 props = g_list_next(props);
469 if (gst_props_entry_get_props_type (prop) == GST_PROPS_STRING_TYPE) {
470 const gchar *name = gst_props_entry_get_name (prop);
471 const gchar *value;
473 gst_props_entry_get_string (prop, &value);
475 if (!value || strlen (value) == 0)
476 continue;
478 if (strcmp (name, "comment") == 0) {
479 id3tag_set_comment (lame->lgf, value);
480 } else if (strcmp (name, "date") == 0) {
481 id3tag_set_year (lame->lgf, value);
482 } else if (strcmp (name, "tracknumber") == 0) {
483 id3tag_set_track (lame->lgf, value);
484 } else if (strcmp (name, "title") == 0) {
485 id3tag_set_title (lame->lgf, value);
486 } else if (strcmp (name, "artist") == 0) {
487 id3tag_set_artist (lame->lgf, value);
488 } else if (strcmp (name, "album") == 0) {
489 id3tag_set_album (lame->lgf, value);
490 } else if (strcmp (name, "genre") == 0) {
491 id3tag_set_genre (lame->lgf, value);
492 }
493 }
494 }
495 }
497 static void
498 gst_lame_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
499 {
500 GstLame *lame;
502 /* it's not null if we got it, but it might not be ours */
503 g_return_if_fail (GST_IS_LAME (object));
505 lame = GST_LAME (object);
507 switch (prop_id) {
508 case ARG_BITRATE:
509 lame->bitrate = g_value_get_int (value);
510 break;
511 case ARG_COMPRESSION_RATIO:
512 lame->compression_ratio = g_value_get_float (value);
513 break;
514 case ARG_QUALITY:
515 lame->quality = g_value_get_enum (value);
516 break;
517 case ARG_MODE:
518 lame->mode = g_value_get_enum (value);
519 break;
520 case ARG_FORCE_MS:
521 lame->force_ms = g_value_get_boolean (value);
522 break;
523 case ARG_FREE_FORMAT:
524 lame->free_format = g_value_get_boolean (value);
525 break;
526 case ARG_COPYRIGHT:
527 lame->copyright = g_value_get_boolean (value);
528 break;
529 case ARG_ORIGINAL:
530 lame->original = g_value_get_boolean (value);
531 break;
532 case ARG_ERROR_PROTECTION:
533 lame->error_protection = g_value_get_boolean (value);
534 break;
535 case ARG_PADDING_TYPE:
536 lame->padding_type = g_value_get_int (value);
537 break;
538 case ARG_EXTENSION:
539 lame->extension = g_value_get_boolean (value);
540 break;
541 case ARG_STRICT_ISO:
542 lame->strict_iso = g_value_get_boolean (value);
543 break;
544 case ARG_DISABLE_RESERVOIR:
545 lame->disable_reservoir = g_value_get_boolean (value);
546 break;
547 case ARG_VBR:
548 lame->vbr = g_value_get_boolean (value);
549 break;
550 case ARG_VBR_MEAN_BITRATE:
551 lame->vbr_mean_bitrate = g_value_get_int (value);
552 break;
553 case ARG_VBR_MIN_BITRATE:
554 lame->vbr_min_bitrate = g_value_get_int (value);
555 break;
556 case ARG_VBR_MAX_BITRATE:
557 lame->vbr_max_bitrate = g_value_get_int (value);
558 break;
559 case ARG_VBR_HARD_MIN:
560 lame->vbr_hard_min = g_value_get_int (value);
561 break;
562 case ARG_LOWPASS_FREQ:
563 lame->lowpass_freq = g_value_get_int (value);
564 break;
565 case ARG_LOWPASS_WIDTH:
566 lame->lowpass_width = g_value_get_int (value);
567 break;
568 case ARG_HIGHPASS_FREQ:
569 lame->highpass_freq = g_value_get_int (value);
570 break;
571 case ARG_HIGHPASS_WIDTH:
572 lame->highpass_width = g_value_get_int (value);
573 break;
574 case ARG_ATH_ONLY:
575 lame->ath_only = g_value_get_boolean (value);
576 break;
577 case ARG_ATH_SHORT:
578 lame->ath_short = g_value_get_boolean (value);
579 break;
580 case ARG_NO_ATH:
581 lame->no_ath = g_value_get_boolean (value);
582 break;
583 case ARG_ATH_LOWER:
584 lame->ath_lower = g_value_get_int (value);
585 break;
586 case ARG_CWLIMIT:
587 lame->cwlimit = g_value_get_int (value);
588 break;
589 case ARG_ALLOW_DIFF_SHORT:
590 lame->allow_diff_short = g_value_get_boolean (value);
591 break;
592 case ARG_NO_SHORT_BLOCKS:
593 lame->no_short_blocks = g_value_get_boolean (value);
594 break;
595 case ARG_EMPHASIS:
596 lame->emphasis = g_value_get_boolean (value);
597 break;
598 case ARG_METADATA:
599 lame->metadata = g_value_get_boxed (value);
600 break;
601 default:
602 break;
603 }
605 }
607 static void
608 gst_lame_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
609 {
610 GstLame *lame;
612 /* it's not null if we got it, but it might not be ours */
613 g_return_if_fail (GST_IS_LAME (object));
615 lame = GST_LAME (object);
617 switch (prop_id) {
618 case ARG_BITRATE:
619 g_value_set_int (value, lame->bitrate);
620 break;
621 case ARG_COMPRESSION_RATIO:
622 g_value_set_float (value, lame->compression_ratio);
623 break;
624 case ARG_QUALITY:
625 g_value_set_enum (value, lame->quality);
626 break;
627 case ARG_MODE:
628 g_value_set_enum (value, lame->mode);
629 break;
630 case ARG_FORCE_MS:
631 g_value_set_boolean (value, lame->force_ms);
632 break;
633 case ARG_FREE_FORMAT:
634 g_value_set_boolean (value, lame->free_format);
635 break;
636 case ARG_COPYRIGHT:
637 g_value_set_boolean (value, lame->copyright);
638 break;
639 case ARG_ORIGINAL:
640 g_value_set_boolean (value, lame->original);
641 break;
642 case ARG_ERROR_PROTECTION:
643 g_value_set_boolean (value, lame->error_protection);
644 break;
645 case ARG_PADDING_TYPE:
646 g_value_set_enum (value, lame->padding_type);
647 break;
648 case ARG_EXTENSION:
649 g_value_set_boolean (value, lame->extension);
650 break;
651 case ARG_STRICT_ISO:
652 g_value_set_boolean (value, lame->strict_iso);
653 break;
654 case ARG_DISABLE_RESERVOIR:
655 g_value_set_boolean (value, lame->disable_reservoir);
656 break;
657 case ARG_VBR:
658 g_value_set_boolean (value, lame->vbr);
659 break;
660 case ARG_VBR_MEAN_BITRATE:
661 g_value_set_int (value, lame->vbr_mean_bitrate);
662 break;
663 case ARG_VBR_MIN_BITRATE:
664 g_value_set_int (value, lame->vbr_min_bitrate);
665 break;
666 case ARG_VBR_MAX_BITRATE:
667 g_value_set_int (value, lame->vbr_max_bitrate);
668 break;
669 case ARG_VBR_HARD_MIN:
670 g_value_set_int (value, lame->vbr_hard_min);
671 break;
672 case ARG_LOWPASS_FREQ:
673 g_value_set_int (value, lame->lowpass_freq);
674 break;
675 case ARG_LOWPASS_WIDTH:
676 g_value_set_int (value, lame->lowpass_width);
677 break;
678 case ARG_HIGHPASS_FREQ:
679 g_value_set_int (value, lame->highpass_freq);
680 break;
681 case ARG_HIGHPASS_WIDTH:
682 g_value_set_int (value, lame->highpass_width);
683 break;
684 case ARG_ATH_ONLY:
685 g_value_set_boolean (value, lame->ath_only);
686 break;
687 case ARG_ATH_SHORT:
688 g_value_set_boolean (value, lame->ath_short);
689 break;
690 case ARG_NO_ATH:
691 g_value_set_boolean (value, lame->no_ath);
692 break;
693 case ARG_ATH_LOWER:
694 g_value_set_int (value, lame->ath_lower);
695 break;
696 case ARG_CWLIMIT:
697 g_value_set_int (value, lame->cwlimit);
698 break;
699 case ARG_ALLOW_DIFF_SHORT:
700 g_value_set_boolean (value, lame->allow_diff_short);
701 break;
702 case ARG_NO_SHORT_BLOCKS:
703 g_value_set_boolean (value, lame->no_short_blocks);
704 break;
705 case ARG_EMPHASIS:
706 g_value_set_boolean (value, lame->emphasis);
707 break;
708 case ARG_METADATA:
709 g_value_set_static_boxed (value, lame->metadata);
710 break;
711 default:
712 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
713 break;
714 }
715 }
717 static void
718 gst_lame_chain (GstPad *pad, GstData *_data)
719 {
720 GstBuffer *buf = GST_BUFFER (_data);
721 GstLame *lame;
722 GstBuffer *outbuf;
723 gchar *mp3_data = NULL;
724 gint mp3_buffer_size, mp3_size = 0;
725 gboolean eos = FALSE;
727 lame = GST_LAME (gst_pad_get_parent (pad));
729 GST_DEBUG ("entered chain");
731 if (GST_IS_EVENT (buf)) {
732 switch (GST_EVENT_TYPE (buf)) {
733 case GST_EVENT_EOS:
734 eos = TRUE;
735 case GST_EVENT_FLUSH:
736 mp3_buffer_size = 7200;
737 mp3_data = g_malloc (mp3_buffer_size);
739 mp3_size = lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
740 gst_event_unref (GST_EVENT (buf));
741 break;
742 default:
743 gst_pad_event_default (pad, GST_EVENT (buf));
744 break;
745 }
746 }
747 else {
748 gint64 duration;
750 if (!lame->initialized) {
751 gst_buffer_unref (buf);
752 gst_element_error (GST_ELEMENT (lame), "encoder not initialized (input is not audio?)");
753 return;
754 }
756 /* allocate space for output */
757 mp3_buffer_size = ((GST_BUFFER_SIZE(buf) / (2+lame->num_channels)) * 1.25) + 7200;
758 mp3_data = g_malloc (mp3_buffer_size);
760 if (lame->num_channels == 2) {
761 mp3_size = lame_encode_buffer_interleaved (lame->lgf,
762 (short int *) (GST_BUFFER_DATA (buf)),
763 GST_BUFFER_SIZE (buf) / 4,
764 mp3_data, mp3_buffer_size);
765 }
766 else {
767 mp3_size = lame_encode_buffer (lame->lgf,
768 (short int *) (GST_BUFFER_DATA (buf)),
769 (short int *) (GST_BUFFER_DATA (buf)),
770 GST_BUFFER_SIZE (buf) / 2,
771 mp3_data, mp3_buffer_size);
772 }
774 GST_DEBUG (
775 "encoded %d bytes of audio to %d bytes of mp3",
776 GST_BUFFER_SIZE (buf), mp3_size);
778 duration = (GST_SECOND * GST_BUFFER_SIZE (buf) /
779 (2 * lame->samplerate * lame->num_channels));
781 if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
782 GST_BUFFER_DURATION (buf) != duration)
783 GST_DEBUG (
784 "mad: incoming buffer had incorrect duration %lld, "
785 "outgoing buffer will have correct duration %lld",
786 GST_BUFFER_DURATION (buf), duration);
788 if (lame->last_ts == GST_CLOCK_TIME_NONE) {
789 lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
790 lame->last_offs = GST_BUFFER_OFFSET (buf);
791 lame->last_duration = duration;
792 } else {
793 lame->last_duration += duration;
794 }
796 gst_buffer_unref (buf);
797 }
799 if (mp3_size > 0) {
800 outbuf = gst_buffer_new ();
801 GST_BUFFER_DATA (outbuf) = mp3_data;
802 GST_BUFFER_SIZE (outbuf) = mp3_size;
803 GST_BUFFER_TIMESTAMP (outbuf) = lame->last_ts;
804 GST_BUFFER_OFFSET (outbuf) = lame->last_offs;
805 GST_BUFFER_DURATION (outbuf) = lame->last_duration;
807 gst_pad_push (lame->srcpad,GST_DATA (outbuf));
809 lame->last_ts = GST_CLOCK_TIME_NONE;
810 }
811 else {
812 g_free (mp3_data);
813 }
815 if (eos) {
816 gst_pad_push (lame->srcpad, GST_DATA (gst_event_new (GST_EVENT_EOS))));
817 gst_element_set_eos (GST_ELEMENT (lame));
818 }
819 }
821 /* transition to the READY state by configuring the gst_lame encoder */
822 static gboolean
823 gst_lame_setup (GstLame *lame)
824 {
825 GST_DEBUG_OBJECT (lame, "starting setup");
827 /* check if we're already initialized; if we are, we might want to check
828 * if this initialization is compatible with the previous one */
829 /* FIXME: do this */
830 if (lame->initialized)
831 g_warning ("already initialized");
833 /* copy the parameters over */
834 lame_set_in_samplerate (lame->lgf, lame->samplerate);
836 /* force mono encoding if we only have one channel */
837 if (lame->num_channels == 1)
838 lame->mode = 3;
840 lame_set_brate (lame->lgf, lame->bitrate);
841 lame_set_compression_ratio (lame->lgf, lame->compression_ratio);
842 lame_set_quality (lame->lgf, lame->quality);
843 lame_set_mode (lame->lgf, lame->mode);
844 lame_set_force_ms (lame->lgf, lame->force_ms);
845 lame_set_free_format (lame->lgf, lame->free_format);
846 lame_set_copyright (lame->lgf, lame->copyright);
847 lame_set_original (lame->lgf, lame->original);
848 lame_set_error_protection (lame->lgf, lame->error_protection);
849 lame_set_padding_type (lame->lgf, lame->padding_type);
850 lame_set_extension (lame->lgf, lame->extension);
851 lame_set_strict_ISO (lame->lgf, lame->strict_iso);
852 lame_set_disable_reservoir (lame->lgf, lame->disable_reservoir);
853 lame_set_VBR_q (lame->lgf, lame->vbr);
854 lame_set_VBR_mean_bitrate_kbps (lame->lgf, lame->vbr_mean_bitrate);
855 lame_set_VBR_min_bitrate_kbps (lame->lgf, lame->vbr_min_bitrate);
856 lame_set_VBR_max_bitrate_kbps (lame->lgf, lame->vbr_max_bitrate);
857 lame_set_VBR_hard_min (lame->lgf, lame->vbr_hard_min);
858 lame_set_lowpassfreq (lame->lgf, lame->lowpass_freq);
859 lame_set_lowpasswidth (lame->lgf, lame->lowpass_width);
860 lame_set_highpassfreq (lame->lgf, lame->highpass_freq);
861 lame_set_highpasswidth (lame->lgf, lame->highpass_width);
862 lame_set_ATHonly (lame->lgf, lame->ath_only);
863 lame_set_ATHshort (lame->lgf, lame->ath_short);
864 lame_set_noATH (lame->lgf, lame->no_ath);
865 lame_set_ATHlower (lame->lgf, lame->ath_lower);
866 lame_set_cwlimit (lame->lgf, lame->cwlimit);
867 lame_set_allow_diff_short (lame->lgf, lame->allow_diff_short);
868 lame_set_no_short_blocks (lame->lgf, lame->no_short_blocks);
869 lame_set_emphasis (lame->lgf, lame->emphasis);
871 gst_lame_add_metadata (lame, lame->metadata);
873 /* initialize the lame encoder */
874 if (lame_init_params (lame->lgf) < 0) {
875 lame->initialized = FALSE;
876 }
877 else {
878 lame->initialized = TRUE;
879 /* FIXME: it would be nice to print out the mode here */
880 GST_INFO (
881 "lame encoder initialized (%d kbit/s, %d Hz, %d channels)",
882 lame->bitrate, lame->samplerate, lame->num_channels);
883 }
885 GST_DEBUG_OBJECT (lame, "done with setup");
887 return lame->initialized;
888 }
890 static GstElementStateReturn
891 gst_lame_change_state (GstElement *element)
892 {
893 GstLame *lame;
895 g_return_val_if_fail (GST_IS_LAME (element), GST_STATE_FAILURE);
897 lame = GST_LAME (element);
899 GST_DEBUG ("state pending %d", GST_STATE_PENDING (element));
901 switch (GST_STATE_TRANSITION (element)) {
902 case GST_STATE_READY_TO_PAUSED:
903 lame->last_ts = GST_CLOCK_TIME_NONE;
904 break;
905 case GST_STATE_READY_TO_NULL:
906 if (lame->initialized) {
907 lame_close (lame->lgf);
908 lame->initialized = FALSE;
909 }
910 break;
911 default:
912 break;
913 }
915 /* if we haven't failed already, give the parent class a chance to ;-) */
916 if (GST_ELEMENT_CLASS (parent_class)->change_state)
917 return GST_ELEMENT_CLASS (parent_class)->change_state (element);
919 return GST_STATE_SUCCESS;
920 }
922 static gboolean
923 plugin_init (GModule *module, GstPlugin *plugin)
924 {
925 GstElementFactory *factory;
927 /* create an elementfactory for the gst_lame element */
928 factory = gst_element_factory_new ("lame", GST_TYPE_LAME,
929 &gst_lame_details);
930 g_return_val_if_fail (factory != NULL, FALSE);
932 /* register the source's padtemplate */
933 gst_element_factory_add_pad_template (factory,
934 GST_PAD_TEMPLATE_GET (gst_lame_src_factory));
936 /* register the sink's padtemplate */
937 gst_element_factory_add_pad_template (factory,
938 GST_PAD_TEMPLATE_GET (gst_lame_sink_factory));
940 /* and add the gst_lame element factory to the plugin */
941 gst_plugin_add_feature (plugin, GST_PLUGIN_FEATURE (factory));
943 return TRUE;
944 }
946 GstPluginDesc plugin_desc = {
947 GST_VERSION_MAJOR,
948 GST_VERSION_MINOR,
949 "lame",
950 plugin_init
951 };