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 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 #include "string.h"
26 #include "gstlame.h"
28 #ifdef lame_set_preset
29 #define GST_LAME_PRESET
30 #endif
32 GST_DEBUG_CATEGORY_STATIC (debug);
33 #define GST_CAT_DEFAULT debug
35 /* elementfactory information */
36 static GstElementDetails gst_lame_details = {
37 "L.A.M.E. mp3 encoder",
38 "Codec/Encoder/Audio",
39 "High-quality free MP3 encoder",
40 "Erik Walthinsen <omega@cse.ogi.edu>, " "Wim Taymans <wim@fluendo.com>",
41 };
43 /* LAME can do MPEG-1, MPEG-2, and MPEG-2.5, so it has 9 possible
44 * sample rates it supports */
45 static GstStaticPadTemplate gst_lame_sink_template =
46 GST_STATIC_PAD_TEMPLATE ("sink",
47 GST_PAD_SINK,
48 GST_PAD_ALWAYS,
49 GST_STATIC_CAPS ("audio/x-raw-int, "
50 "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
51 "signed = (boolean) true, "
52 "width = (int) 16, "
53 "depth = (int) 16, "
54 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
55 "channels = (int) [ 1, 2 ]")
56 );
58 static GstStaticPadTemplate gst_lame_src_template =
59 GST_STATIC_PAD_TEMPLATE ("src",
60 GST_PAD_SRC,
61 GST_PAD_ALWAYS,
62 GST_STATIC_CAPS ("audio/mpeg, "
63 "mpegversion = (int) 1, "
64 "layer = (int) 3, "
65 "rate = (int) { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 }, "
66 "channels = (int) [ 1, 2 ]")
67 );
69 /********** Define useful types for non-programmatic interfaces **********/
70 #define GST_TYPE_LAME_MODE (gst_lame_mode_get_type())
71 static GType
72 gst_lame_mode_get_type (void)
73 {
74 static GType lame_mode_type = 0;
75 static GEnumValue lame_modes[] = {
76 {0, "Stereo", "stereo"},
77 {1, "Joint Stereo", "joint"},
78 {2, "Dual Channel", "dual"},
79 {3, "Mono", "mono"},
80 {4, "Auto", "auto"},
81 {0, NULL, NULL}
82 };
84 if (!lame_mode_type) {
85 lame_mode_type = g_enum_register_static ("GstLameMode", lame_modes);
86 }
87 return lame_mode_type;
88 }
90 #define GST_TYPE_LAME_QUALITY (gst_lame_quality_get_type())
91 static GType
92 gst_lame_quality_get_type (void)
93 {
94 static GType lame_quality_type = 0;
95 static GEnumValue lame_quality[] = {
96 {0, "0 - Best", "0"},
97 {1, "1", "1"},
98 {2, "2", "2"},
99 {3, "3", "3"},
100 {4, "4", "4"},
101 {5, "5 - Default", "5"},
102 {6, "6", "6"},
103 {7, "7", "7"},
104 {8, "8", "8"},
105 {9, "9 - Worst", "9"},
106 {0, NULL, NULL}
107 };
109 if (!lame_quality_type) {
110 lame_quality_type = g_enum_register_static ("GstLameQuality", lame_quality);
111 }
112 return lame_quality_type;
113 }
115 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
116 static GType
117 gst_lame_padding_get_type (void)
118 {
119 static GType lame_padding_type = 0;
120 static GEnumValue lame_padding[] = {
121 {0, "No Padding", "never"},
122 {1, "Always Pad", "always"},
123 {2, "Adjust Padding", "adjust"},
124 {0, NULL, NULL}
125 };
127 if (!lame_padding_type) {
128 lame_padding_type = g_enum_register_static ("GstLamePadding", lame_padding);
129 }
130 return lame_padding_type;
131 }
133 #define GST_TYPE_LAME_VBRMODE (gst_lame_vbrmode_get_type())
134 static GType
135 gst_lame_vbrmode_get_type (void)
136 {
137 static GType lame_vbrmode_type = 0;
138 static GEnumValue lame_vbrmode[] = {
139 {vbr_off, "No VBR (Constant Bitrate)", "none"},
140 {vbr_rh, "Lame's old VBR algorithm", "old"},
141 {vbr_abr, "VBR Average Bitrate", "abr"},
142 {vbr_mtrh, "Lame's new VBR algorithm", "new"},
143 {0, NULL, NULL}
144 };
146 if (!lame_vbrmode_type) {
147 lame_vbrmode_type = g_enum_register_static ("GstLameVbrmode", lame_vbrmode);
148 }
150 return lame_vbrmode_type;
151 }
153 #ifdef GSTLAME_PRESET
154 #define GST_TYPE_LAME_PRESET (gst_lame_preset_get_type())
155 static GType
156 gst_lame_preset_get_type (void)
157 {
158 static GType gst_lame_preset = 0;
159 static GEnumValue gst_lame_presets[] = {
160 {0, "None", "none"},
161 {MEDIUM, "Medium", "medium"},
162 {STANDARD, "Standard", "standard"},
163 {EXTREME, "Extreme", "extreme"},
164 {INSANE, "Insane", "insane"},
165 {0, NULL, NULL}
166 };
168 if (!gst_lame_preset) {
169 gst_lame_preset =
170 g_enum_register_static ("GstLamePreset", gst_lame_presets);
171 }
173 return gst_lame_preset;
174 }
175 #endif
177 /********** Standard stuff for signals and arguments **********/
178 /* GstLame signals and args */
179 enum
180 {
181 /* FILL_ME */
182 LAST_SIGNAL
183 };
185 enum
186 {
187 ARG_0,
188 ARG_BITRATE,
189 ARG_COMPRESSION_RATIO,
190 ARG_QUALITY,
191 ARG_MODE,
192 ARG_FORCE_MS,
193 ARG_FREE_FORMAT,
194 ARG_COPYRIGHT,
195 ARG_ORIGINAL,
196 ARG_ERROR_PROTECTION,
197 ARG_PADDING_TYPE,
198 ARG_EXTENSION,
199 ARG_STRICT_ISO,
200 ARG_DISABLE_RESERVOIR,
201 ARG_VBR,
202 ARG_VBR_MEAN_BITRATE,
203 ARG_VBR_MIN_BITRATE,
204 ARG_VBR_MAX_BITRATE,
205 ARG_VBR_HARD_MIN,
206 ARG_LOWPASS_FREQ,
207 ARG_LOWPASS_WIDTH,
208 ARG_HIGHPASS_FREQ,
209 ARG_HIGHPASS_WIDTH,
210 ARG_ATH_ONLY,
211 ARG_ATH_SHORT,
212 ARG_NO_ATH,
213 ARG_ATH_LOWER,
214 ARG_CWLIMIT,
215 ARG_ALLOW_DIFF_SHORT,
216 ARG_NO_SHORT_BLOCKS,
217 ARG_EMPHASIS,
218 ARG_VBR_QUALITY,
219 #ifdef GSTLAME_PRESET
220 ARG_XINGHEADER, /* FIXME: remove in 0.11 */
221 ARG_PRESET
222 #else
223 ARG_XINGHEADER /* FIXME: remove in 0.11 */
224 #endif
225 };
227 static void gst_lame_base_init (gpointer g_class);
228 static void gst_lame_class_init (GstLameClass * klass);
229 static void gst_lame_init (GstLame * gst_lame);
231 static void gst_lame_set_property (GObject * object, guint prop_id,
232 const GValue * value, GParamSpec * pspec);
233 static void gst_lame_get_property (GObject * object, guint prop_id,
234 GValue * value, GParamSpec * pspec);
235 static gboolean gst_lame_sink_event (GstPad * pad, GstEvent * event);
236 static GstFlowReturn gst_lame_chain (GstPad * pad, GstBuffer * buf);
237 static gboolean gst_lame_setup (GstLame * lame);
238 static GstStateChangeReturn gst_lame_change_state (GstElement * element,
239 GstStateChange transition);
241 static GstElementClass *parent_class = NULL;
243 /* static guint gst_lame_signals[LAST_SIGNAL] = { 0 }; */
245 GType
246 gst_lame_get_type (void)
247 {
248 static GType gst_lame_type = 0;
250 if (!gst_lame_type) {
251 static const GTypeInfo gst_lame_info = {
252 sizeof (GstLameClass),
253 gst_lame_base_init,
254 NULL,
255 (GClassInitFunc) gst_lame_class_init,
256 NULL,
257 NULL,
258 sizeof (GstLame),
259 0,
260 (GInstanceInitFunc) gst_lame_init,
261 };
263 static const GInterfaceInfo tag_setter_info = {
264 NULL,
265 NULL,
266 NULL
267 };
269 gst_lame_type =
270 g_type_register_static (GST_TYPE_ELEMENT, "GstLame", &gst_lame_info, 0);
271 g_type_add_interface_static (gst_lame_type, GST_TYPE_TAG_SETTER,
272 &tag_setter_info);
274 }
275 return gst_lame_type;
276 }
278 static void
279 gst_lame_release_memory (GstLame * lame)
280 {
281 g_slist_foreach (lame->tag_strings, (GFunc) g_free, NULL);
282 g_slist_free (lame->tag_strings);
283 lame->tag_strings = NULL;
285 if (lame->tags) {
286 gst_tag_list_free (lame->tags);
287 lame->tags = NULL;
288 }
290 if (lame->lgf) {
291 lame_close (lame->lgf);
292 lame->lgf = NULL;
293 }
294 }
296 static void
297 gst_lame_finalize (GObject * obj)
298 {
299 gst_lame_release_memory (GST_LAME (obj));
301 G_OBJECT_CLASS (parent_class)->finalize (obj);
302 }
304 static void
305 gst_lame_base_init (gpointer g_class)
306 {
307 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
309 gst_element_class_add_pad_template (element_class,
310 gst_static_pad_template_get (&gst_lame_src_template));
311 gst_element_class_add_pad_template (element_class,
312 gst_static_pad_template_get (&gst_lame_sink_template));
313 gst_element_class_set_details (element_class, &gst_lame_details);
314 }
316 static void
317 gst_lame_class_init (GstLameClass * klass)
318 {
319 GObjectClass *gobject_class;
320 GstElementClass *gstelement_class;
322 gobject_class = (GObjectClass *) klass;
323 gstelement_class = (GstElementClass *) klass;
325 parent_class = g_type_class_peek_parent (klass);
327 gobject_class->set_property = gst_lame_set_property;
328 gobject_class->get_property = gst_lame_get_property;
329 gobject_class->finalize = gst_lame_finalize;
331 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE,
332 g_param_spec_int ("bitrate", "Bitrate (kb/s)", "Bitrate in kbit/sec",
333 8, 320, 128, G_PARAM_READWRITE));
334 /* compression ratio set to 0.0 by default otherwise it overrides the bitrate setting */
335 g_object_class_install_property (G_OBJECT_CLASS (klass),
336 ARG_COMPRESSION_RATIO, g_param_spec_float ("compression_ratio",
337 "Compression Ratio",
338 "let lame choose bitrate to achieve selected compression ratio", 0.0,
339 200.0, 0.0, G_PARAM_READWRITE));
340 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY,
341 g_param_spec_enum ("quality", "Quality",
342 "Quality of algorithm used for encoding", GST_TYPE_LAME_QUALITY, 5,
343 G_PARAM_READWRITE));
344 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE,
345 g_param_spec_enum ("mode", "Mode", "Encoding mode", GST_TYPE_LAME_MODE, 0,
346 G_PARAM_READWRITE));
347 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FORCE_MS,
348 g_param_spec_boolean ("force_ms", "Force ms",
349 "Force ms_stereo on all frames", TRUE, G_PARAM_READWRITE));
350 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FREE_FORMAT,
351 g_param_spec_boolean ("free_format", "Free format",
352 "Produce a free format bitstream", TRUE, G_PARAM_READWRITE));
353 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_COPYRIGHT,
354 g_param_spec_boolean ("copyright", "Copyright", "Mark as copyright", TRUE,
355 G_PARAM_READWRITE));
356 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ORIGINAL,
357 g_param_spec_boolean ("original", "Original", "Mark as non-original",
358 TRUE, G_PARAM_READWRITE));
359 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ERROR_PROTECTION,
360 g_param_spec_boolean ("error_protection", "Error protection",
361 "Adds 16 bit checksum to every frame", TRUE, G_PARAM_READWRITE));
362 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PADDING_TYPE,
363 g_param_spec_enum ("padding_type", "Padding type", "Padding type",
364 GST_TYPE_LAME_PADDING, 0, G_PARAM_READWRITE));
365 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EXTENSION,
366 g_param_spec_boolean ("extension", "Extension", "Extension", TRUE,
367 G_PARAM_READWRITE));
368 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_STRICT_ISO,
369 g_param_spec_boolean ("strict_iso", "Strict ISO",
370 "Comply as much as possible to ISO MPEG spec", TRUE,
371 G_PARAM_READWRITE));
372 g_object_class_install_property (G_OBJECT_CLASS (klass),
373 ARG_DISABLE_RESERVOIR, g_param_spec_boolean ("disable_reservoir",
374 "Disable reservoir", "Disable the bit reservoir", TRUE,
375 G_PARAM_READWRITE));
376 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR,
377 g_param_spec_enum ("vbr", "VBR", "Specify bitrate mode",
378 GST_TYPE_LAME_VBRMODE, vbr_off, G_PARAM_READWRITE));
379 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_QUALITY,
380 g_param_spec_enum ("vbr_quality", "VBR Quality", "VBR Quality",
381 GST_TYPE_LAME_QUALITY, 5, G_PARAM_READWRITE));
382 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MEAN_BITRATE,
383 g_param_spec_int ("vbr_mean_bitrate", "VBR mean bitrate",
384 "Specify mean bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
385 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MIN_BITRATE,
386 g_param_spec_int ("vbr_min_bitrate", "VBR min bitrate",
387 "Specify min bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
388 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_MAX_BITRATE,
389 g_param_spec_int ("vbr_max_bitrate", "VBR max bitrate",
390 "Specify max bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
391 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_VBR_HARD_MIN,
392 g_param_spec_int ("vbr_hard_min", "VBR hard min",
393 "Specify hard min bitrate", 0, G_MAXINT, 0, G_PARAM_READWRITE));
394 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_FREQ,
395 g_param_spec_int ("lowpass_freq", "Lowpass freq",
396 "frequency(kHz), lowpass filter cutoff above freq", 0, 50000, 0,
397 G_PARAM_READWRITE));
398 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LOWPASS_WIDTH,
399 g_param_spec_int ("lowpass_width", "Lowpass width",
400 "frequency(kHz) - default 15% of lowpass freq", 0, G_MAXINT, 0,
401 G_PARAM_READWRITE));
402 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_FREQ,
403 g_param_spec_int ("highpass_freq", "Highpass freq",
404 "frequency(kHz), highpass filter cutoff below freq", 0, 50000, 0,
405 G_PARAM_READWRITE));
406 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_HIGHPASS_WIDTH,
407 g_param_spec_int ("highpass_width", "Highpass width",
408 "frequency(kHz) - default 15% of highpass freq", 0, G_MAXINT, 0,
409 G_PARAM_READWRITE));
410 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_ONLY,
411 g_param_spec_boolean ("ath_only", "ATH only",
412 "Ignore GPSYCHO completely, use ATH only", TRUE, G_PARAM_READWRITE));
413 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_SHORT,
414 g_param_spec_boolean ("ath_short", "ATH short",
415 "Ignore GPSYCHO for short blocks, use ATH only", TRUE,
416 G_PARAM_READWRITE));
417 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_ATH,
418 g_param_spec_boolean ("no_ath", "No ath",
419 "turns ATH down to a flat noise floor", TRUE, G_PARAM_READWRITE));
420 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ATH_LOWER,
421 g_param_spec_int ("ath_lower", "ATH lower", "lowers ATH by x dB",
422 G_MININT, G_MAXINT, 0, G_PARAM_READWRITE));
423 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_CWLIMIT,
424 g_param_spec_int ("cwlimit", "Cwlimit",
425 "Compute tonality up to freq (in kHz) default 8.8717", 0, 50000, 0,
426 G_PARAM_READWRITE));
427 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_ALLOW_DIFF_SHORT,
428 g_param_spec_boolean ("allow_diff_short", "Allow diff short",
429 "Allow diff short", TRUE, G_PARAM_READWRITE));
430 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NO_SHORT_BLOCKS,
431 g_param_spec_boolean ("no_short_blocks", "No short blocks",
432 "Do not use short blocks", TRUE, G_PARAM_READWRITE));
433 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_EMPHASIS,
434 g_param_spec_boolean ("emphasis", "Emphasis", "Emphasis", TRUE,
435 G_PARAM_READWRITE));
436 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_XINGHEADER,
437 g_param_spec_boolean ("xingheader", "Output Xing Header",
438 "Output Xing Header (BROKEN, use xingmux instead)",
439 FALSE, G_PARAM_READWRITE));
440 #ifdef GSTLAME_PRESET
441 g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PRESET,
442 g_param_spec_enum ("preset", "Lame Preset", "Lame Preset",
443 GST_TYPE_LAME_PRESET, 0, G_PARAM_READWRITE));
444 #endif
446 gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_lame_change_state);
447 }
449 static gboolean
450 gst_lame_sink_setcaps (GstPad * pad, GstCaps * caps)
451 {
452 GstLame *lame;
453 gint out_samplerate;
454 GstStructure *structure;
455 GstCaps *othercaps;
457 lame = GST_LAME (gst_pad_get_parent (pad));
458 structure = gst_caps_get_structure (caps, 0);
460 if (!gst_structure_get_int (structure, "rate", &lame->samplerate))
461 goto no_rate;
462 if (!gst_structure_get_int (structure, "channels", &lame->num_channels))
463 goto no_channels;
465 GST_DEBUG_OBJECT (lame, "sink_setcaps, setting up lame");
466 if (!gst_lame_setup (lame))
467 goto setup_failed;
470 out_samplerate = lame_get_out_samplerate (lame->lgf);
471 if (out_samplerate == 0)
472 goto zero_output_rate;
474 othercaps =
475 gst_caps_new_simple ("audio/mpeg",
476 "mpegversion", G_TYPE_INT, 1,
477 "layer", G_TYPE_INT, 3,
478 "channels", G_TYPE_INT, lame->num_channels,
479 "rate", G_TYPE_INT, out_samplerate, NULL);
481 /* and use these caps */
482 gst_pad_set_caps (lame->srcpad, othercaps);
483 gst_caps_unref (othercaps);
484 gst_object_unref (lame);
486 return TRUE;
488 no_rate:
489 {
490 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
491 ("no rate specified in input"));
492 gst_object_unref (lame);
493 return FALSE;
494 }
495 no_channels:
496 {
497 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
498 ("no channels specified in input"));
499 gst_object_unref (lame);
500 return FALSE;
501 }
502 zero_output_rate:
503 {
504 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
505 ("lame decided on a zero sample rate"));
506 gst_object_unref (lame);
507 return FALSE;
508 }
509 setup_failed:
510 {
511 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
512 ("could not initialize encoder (wrong parameters?)"));
513 gst_object_unref (lame);
514 return FALSE;
515 }
516 }
518 static void
519 gst_lame_init (GstLame * lame)
520 {
521 GST_DEBUG_OBJECT (lame, "starting initialization");
523 lame->sinkpad =
524 gst_pad_new_from_static_template (&gst_lame_sink_template, "sink");
525 gst_pad_set_event_function (lame->sinkpad,
526 GST_DEBUG_FUNCPTR (gst_lame_sink_event));
527 gst_pad_set_chain_function (lame->sinkpad,
528 GST_DEBUG_FUNCPTR (gst_lame_chain));
529 gst_pad_set_setcaps_function (lame->sinkpad,
530 GST_DEBUG_FUNCPTR (gst_lame_sink_setcaps));
531 gst_element_add_pad (GST_ELEMENT (lame), lame->sinkpad);
533 lame->srcpad =
534 gst_pad_new_from_static_template (&gst_lame_src_template, "src");
535 gst_element_add_pad (GST_ELEMENT (lame), lame->srcpad);
537 /* create an encoder state so we can ask about defaults */
538 lame->lgf = lame_init ();
540 lame->samplerate = 44100;
541 lame->num_channels = 2;
542 lame->setup = FALSE;
544 lame->bitrate = 128; /* lame_get_brate (lame->lgf);
545 * => 0/out of range */
546 lame->compression_ratio = 0.0; /* lame_get_compression_ratio (lame->lgf);
547 * => 0/out of range ...
548 * NOTE: 0.0 makes bitrate take precedence */
549 lame->quality = 5; /* lame_get_quality (lame->lgf);
550 * => -1/out of range */
551 lame->mode = lame_get_mode (lame->lgf);
552 lame->force_ms = lame_get_force_ms (lame->lgf);
553 lame->free_format = lame_get_free_format (lame->lgf);
554 lame->copyright = lame_get_copyright (lame->lgf);
555 lame->original = lame_get_original (lame->lgf);
556 lame->error_protection = lame_get_error_protection (lame->lgf);
557 lame->padding_type = lame_get_padding_type (lame->lgf);
558 lame->extension = lame_get_extension (lame->lgf);
559 lame->strict_iso = lame_get_strict_ISO (lame->lgf);
560 lame->disable_reservoir = lame_get_disable_reservoir (lame->lgf);
561 lame->vbr = vbr_off; /* lame_get_VBR (lame->lgf); */
562 lame->vbr_quality = 5;
563 lame->vbr_mean_bitrate = lame_get_VBR_mean_bitrate_kbps (lame->lgf);
564 lame->vbr_min_bitrate = lame_get_VBR_min_bitrate_kbps (lame->lgf);
565 lame->vbr_max_bitrate = 0; /* lame_get_VBR_max_bitrate_kbps (lame->lgf);
566 * => 0/no vbr possible */
567 lame->vbr_hard_min = lame_get_VBR_hard_min (lame->lgf);
568 /* lame->lowpass_freq = 50000; lame_get_lowpassfreq (lame->lgf);
569 * => 0/lowpass on everything ? */
570 lame->lowpass_freq = 0;
571 lame->lowpass_width = 0; /* lame_get_lowpasswidth (lame->lgf);
572 * => -1/out of range */
573 lame->highpass_freq = lame_get_highpassfreq (lame->lgf);
574 lame->highpass_width = 0; /* lame_get_highpasswidth (lame->lgf);
575 * => -1/out of range */
576 lame->ath_only = lame_get_ATHonly (lame->lgf);
577 lame->ath_short = lame_get_ATHshort (lame->lgf);
578 lame->no_ath = lame_get_noATH (lame->lgf);
579 /* lame->ath_type = lame_get_ATHtype (lame->lgf); */
580 lame->ath_lower = lame_get_ATHlower (lame->lgf);
581 lame->cwlimit = 8.8717; /* lame_get_cwlimit (lame->lgf); => 0 */
582 lame->allow_diff_short = lame_get_allow_diff_short (lame->lgf);
583 lame->no_short_blocks = TRUE; /* lame_get_no_short_blocks (lame->lgf); */
584 lame->emphasis = lame_get_emphasis (lame->lgf);
585 lame->preset = 0;
586 lame_close (lame->lgf);
587 lame->lgf = NULL;
588 lame->tag_strings = NULL;
590 GST_DEBUG_OBJECT (lame, "done initializing");
591 }
593 typedef struct _GstLameTagMatch GstLameTagMatch;
594 typedef void (*GstLameTagFunc) (lame_global_flags * gfp, const char *value);
596 struct _GstLameTagMatch
597 {
598 gchar *gstreamer_tag;
599 GstLameTagFunc tag_func;
600 };
602 static GstLameTagMatch tag_matches[] = {
603 {GST_TAG_TITLE, id3tag_set_title},
604 {GST_TAG_DATE, id3tag_set_year},
605 {GST_TAG_TRACK_NUMBER, id3tag_set_track},
606 {GST_TAG_COMMENT, id3tag_set_comment},
607 {GST_TAG_ARTIST, id3tag_set_artist},
608 {GST_TAG_ALBUM, id3tag_set_album},
609 {GST_TAG_GENRE, (GstLameTagFunc) id3tag_set_genre},
610 {NULL, NULL}
611 };
613 static void
614 add_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data)
615 {
616 GstLame *lame;
617 gchar *value = NULL;
618 int i = 0;
620 lame = GST_LAME (user_data);
621 g_return_if_fail (lame != NULL);
623 while (tag_matches[i].gstreamer_tag != NULL) {
624 if (strcmp (tag, tag_matches[i].gstreamer_tag) == 0) {
625 break;
626 }
627 i++;
628 }
630 if (tag_matches[i].tag_func == NULL) {
631 GST_WARNING_OBJECT (lame,
632 "Couldn't find matching gstreamer tag for \"%s\"", tag);
633 return;
634 }
636 switch (gst_tag_get_type (tag)) {
637 case G_TYPE_UINT:{
638 guint ivalue;
640 if (!gst_tag_list_get_uint (list, tag, &ivalue)) {
641 GST_WARNING_OBJECT (lame, "Error reading \"%s\" tag value", tag);
642 return;
643 }
644 value = g_strdup_printf ("%u", ivalue);
645 break;
646 }
647 case G_TYPE_STRING:
648 if (!gst_tag_list_get_string (list, tag, &value)) {
649 GST_WARNING_OBJECT (lame, "Error reading \"%s\" tag value", tag);
650 return;
651 };
652 break;
653 default:{
654 if (strcmp (tag, GST_TAG_DATE) == 0) {
655 GDate *date = NULL;
657 if (!gst_tag_list_get_date (list, tag, &date) || date == NULL) {
658 GST_WARNING_OBJECT (lame, "Error reading \"%s\" tag value", tag);
659 } else {
660 value = g_strdup_printf ("%u", g_date_get_year (date));
661 g_date_free (date);
662 }
663 } else {
664 GST_WARNING_OBJECT (lame, "Couldn't write tag %s", tag);
665 }
666 break;
667 }
668 }
670 if (value != NULL && *value != '\0') {
671 GST_LOG_OBJECT (lame, "Adding tag %s:%s", tag, value);
672 tag_matches[i].tag_func (lame->lgf, value);
673 }
675 /* lame does not copy strings passed to it and expects them
676 * to be around later, but it does not free them for us either,
677 * so we just add them to a list and free it later when it's safe */
678 lame->tag_strings = g_slist_prepend (lame->tag_strings, value);
679 }
681 static void
682 gst_lame_set_metadata (GstLame * lame)
683 {
684 const GstTagList *user_tags;
685 GstTagList *copy;
687 g_return_if_fail (lame != NULL);
689 user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (lame));
691 GST_DEBUG_OBJECT (lame, "lame->tags = %" GST_PTR_FORMAT, lame->tags);
692 GST_DEBUG_OBJECT (lame, "user tags = %" GST_PTR_FORMAT, user_tags);
694 if ((lame->tags == NULL) && (user_tags == NULL)) {
695 return;
696 }
698 copy = gst_tag_list_merge (user_tags, lame->tags,
699 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (lame)));
701 GST_DEBUG_OBJECT (lame, "merged tags = %" GST_PTR_FORMAT, copy);
703 gst_tag_list_foreach ((GstTagList *) copy, add_one_tag, lame);
705 gst_tag_list_free (copy);
706 }
710 static void
711 gst_lame_set_property (GObject * object, guint prop_id, const GValue * value,
712 GParamSpec * pspec)
713 {
714 GstLame *lame;
716 g_return_if_fail (GST_IS_LAME (object));
718 lame = GST_LAME (object);
720 switch (prop_id) {
721 case ARG_BITRATE:
722 lame->bitrate = g_value_get_int (value);
723 break;
724 case ARG_COMPRESSION_RATIO:
725 lame->compression_ratio = g_value_get_float (value);
726 break;
727 case ARG_QUALITY:
728 lame->quality = g_value_get_enum (value);
729 break;
730 case ARG_MODE:
731 lame->mode = g_value_get_enum (value);
732 break;
733 case ARG_FORCE_MS:
734 lame->force_ms = g_value_get_boolean (value);
735 break;
736 case ARG_FREE_FORMAT:
737 lame->free_format = g_value_get_boolean (value);
738 break;
739 case ARG_COPYRIGHT:
740 lame->copyright = g_value_get_boolean (value);
741 break;
742 case ARG_ORIGINAL:
743 lame->original = g_value_get_boolean (value);
744 break;
745 case ARG_ERROR_PROTECTION:
746 lame->error_protection = g_value_get_boolean (value);
747 break;
748 case ARG_PADDING_TYPE:
749 lame->padding_type = g_value_get_int (value);
750 break;
751 case ARG_EXTENSION:
752 lame->extension = g_value_get_boolean (value);
753 break;
754 case ARG_STRICT_ISO:
755 lame->strict_iso = g_value_get_boolean (value);
756 break;
757 case ARG_DISABLE_RESERVOIR:
758 lame->disable_reservoir = g_value_get_boolean (value);
759 break;
760 case ARG_VBR:
761 lame->vbr = g_value_get_enum (value);
762 break;
763 case ARG_VBR_QUALITY:
764 lame->vbr_quality = g_value_get_enum (value);
765 break;
766 case ARG_VBR_MEAN_BITRATE:
767 lame->vbr_mean_bitrate = g_value_get_int (value);
768 break;
769 case ARG_VBR_MIN_BITRATE:
770 lame->vbr_min_bitrate = g_value_get_int (value);
771 break;
772 case ARG_VBR_MAX_BITRATE:
773 lame->vbr_max_bitrate = g_value_get_int (value);
774 break;
775 case ARG_VBR_HARD_MIN:
776 lame->vbr_hard_min = g_value_get_int (value);
777 break;
778 case ARG_LOWPASS_FREQ:
779 lame->lowpass_freq = g_value_get_int (value);
780 break;
781 case ARG_LOWPASS_WIDTH:
782 lame->lowpass_width = g_value_get_int (value);
783 break;
784 case ARG_HIGHPASS_FREQ:
785 lame->highpass_freq = g_value_get_int (value);
786 break;
787 case ARG_HIGHPASS_WIDTH:
788 lame->highpass_width = g_value_get_int (value);
789 break;
790 case ARG_ATH_ONLY:
791 lame->ath_only = g_value_get_boolean (value);
792 break;
793 case ARG_ATH_SHORT:
794 lame->ath_short = g_value_get_boolean (value);
795 break;
796 case ARG_NO_ATH:
797 lame->no_ath = g_value_get_boolean (value);
798 break;
799 case ARG_ATH_LOWER:
800 lame->ath_lower = g_value_get_int (value);
801 break;
802 case ARG_CWLIMIT:
803 lame->cwlimit = g_value_get_int (value);
804 break;
805 case ARG_ALLOW_DIFF_SHORT:
806 lame->allow_diff_short = g_value_get_boolean (value);
807 break;
808 case ARG_NO_SHORT_BLOCKS:
809 lame->no_short_blocks = g_value_get_boolean (value);
810 break;
811 case ARG_EMPHASIS:
812 lame->emphasis = g_value_get_boolean (value);
813 break;
814 case ARG_XINGHEADER:
815 break;
816 #ifdef GSTLAME_PRESET
817 case ARG_PRESET:
818 lame->preset = g_value_get_enum (value);
819 break;
820 #endif
821 default:
822 break;
823 }
825 }
827 static void
828 gst_lame_get_property (GObject * object, guint prop_id, GValue * value,
829 GParamSpec * pspec)
830 {
831 GstLame *lame;
833 g_return_if_fail (GST_IS_LAME (object));
835 lame = GST_LAME (object);
837 switch (prop_id) {
838 case ARG_BITRATE:
839 g_value_set_int (value, lame->bitrate);
840 break;
841 case ARG_COMPRESSION_RATIO:
842 g_value_set_float (value, lame->compression_ratio);
843 break;
844 case ARG_QUALITY:
845 g_value_set_enum (value, lame->quality);
846 break;
847 case ARG_MODE:
848 g_value_set_enum (value, lame->mode);
849 break;
850 case ARG_FORCE_MS:
851 g_value_set_boolean (value, lame->force_ms);
852 break;
853 case ARG_FREE_FORMAT:
854 g_value_set_boolean (value, lame->free_format);
855 break;
856 case ARG_COPYRIGHT:
857 g_value_set_boolean (value, lame->copyright);
858 break;
859 case ARG_ORIGINAL:
860 g_value_set_boolean (value, lame->original);
861 break;
862 case ARG_ERROR_PROTECTION:
863 g_value_set_boolean (value, lame->error_protection);
864 break;
865 case ARG_PADDING_TYPE:
866 g_value_set_enum (value, lame->padding_type);
867 break;
868 case ARG_EXTENSION:
869 g_value_set_boolean (value, lame->extension);
870 break;
871 case ARG_STRICT_ISO:
872 g_value_set_boolean (value, lame->strict_iso);
873 break;
874 case ARG_DISABLE_RESERVOIR:
875 g_value_set_boolean (value, lame->disable_reservoir);
876 break;
877 case ARG_VBR:
878 g_value_set_enum (value, lame->vbr);
879 break;
880 case ARG_VBR_QUALITY:
881 g_value_set_enum (value, lame->vbr_quality);
882 break;
883 case ARG_VBR_MEAN_BITRATE:
884 g_value_set_int (value, lame->vbr_mean_bitrate);
885 break;
886 case ARG_VBR_MIN_BITRATE:
887 g_value_set_int (value, lame->vbr_min_bitrate);
888 break;
889 case ARG_VBR_MAX_BITRATE:
890 g_value_set_int (value, lame->vbr_max_bitrate);
891 break;
892 case ARG_VBR_HARD_MIN:
893 g_value_set_int (value, lame->vbr_hard_min);
894 break;
895 case ARG_LOWPASS_FREQ:
896 g_value_set_int (value, lame->lowpass_freq);
897 break;
898 case ARG_LOWPASS_WIDTH:
899 g_value_set_int (value, lame->lowpass_width);
900 break;
901 case ARG_HIGHPASS_FREQ:
902 g_value_set_int (value, lame->highpass_freq);
903 break;
904 case ARG_HIGHPASS_WIDTH:
905 g_value_set_int (value, lame->highpass_width);
906 break;
907 case ARG_ATH_ONLY:
908 g_value_set_boolean (value, lame->ath_only);
909 break;
910 case ARG_ATH_SHORT:
911 g_value_set_boolean (value, lame->ath_short);
912 break;
913 case ARG_NO_ATH:
914 g_value_set_boolean (value, lame->no_ath);
915 break;
916 case ARG_ATH_LOWER:
917 g_value_set_int (value, lame->ath_lower);
918 break;
919 case ARG_CWLIMIT:
920 g_value_set_int (value, lame->cwlimit);
921 break;
922 case ARG_ALLOW_DIFF_SHORT:
923 g_value_set_boolean (value, lame->allow_diff_short);
924 break;
925 case ARG_NO_SHORT_BLOCKS:
926 g_value_set_boolean (value, lame->no_short_blocks);
927 break;
928 case ARG_EMPHASIS:
929 g_value_set_boolean (value, lame->emphasis);
930 break;
931 case ARG_XINGHEADER:
932 break;
933 #ifdef GSTLAME_PRESET
934 case ARG_PRESET:
935 g_value_set_enum (value, lame->preset);
936 break;
937 #endif
938 default:
939 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
940 break;
941 }
942 }
944 static gboolean
945 gst_lame_sink_event (GstPad * pad, GstEvent * event)
946 {
947 gboolean ret;
948 GstLame *lame;
950 lame = GST_LAME (gst_pad_get_parent (pad));
952 switch (GST_EVENT_TYPE (event)) {
953 case GST_EVENT_EOS:{
954 GstBuffer *buf;
955 gint size;
957 GST_DEBUG_OBJECT (lame, "handling EOS event");
958 buf = gst_buffer_new_and_alloc (7200);
959 size = lame_encode_flush (lame->lgf, GST_BUFFER_DATA (buf), 7200);
960 if (size > 0) {
961 GST_BUFFER_SIZE (buf) = size;
962 GST_DEBUG_OBJECT (lame, "pushing final packet of %u bytes", size);
963 gst_buffer_set_caps (buf, GST_PAD_CAPS (lame->srcpad));
964 gst_pad_push (lame->srcpad, buf);
965 } else {
966 GST_DEBUG_OBJECT (lame, "no final packet (size=%d)", size);
967 gst_buffer_unref (buf);
968 }
970 ret = gst_pad_event_default (pad, event);
971 break;
972 }
973 case GST_EVENT_FLUSH_START:
974 GST_DEBUG_OBJECT (lame, "handling FLUSH start event");
975 /* forward event */
976 ret = gst_pad_push_event (lame->srcpad, event);
977 break;
978 case GST_EVENT_FLUSH_STOP:
979 {
980 guchar *mp3_data = NULL;
981 gint mp3_buffer_size, mp3_size = 0;
983 GST_DEBUG_OBJECT (lame, "handling FLUSH stop event");
985 /* clear buffers */
986 mp3_buffer_size = 7200;
987 mp3_data = g_malloc (mp3_buffer_size);
988 mp3_size = lame_encode_flush (lame->lgf, mp3_data, mp3_buffer_size);
990 ret = gst_pad_push_event (lame->srcpad, event);
991 break;
992 }
993 case GST_EVENT_TAG:
994 GST_DEBUG_OBJECT (lame, "handling TAG event");
995 if (lame->tags) {
996 GstTagList *taglist;
998 gst_event_parse_tag (event, &taglist),
999 gst_tag_list_insert (lame->tags, taglist,
1000 gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (lame)));
1001 } else {
1002 g_assert_not_reached ();
1003 }
1004 ret = gst_pad_push_event (lame->srcpad, event);
1005 break;
1006 default:
1007 ret = gst_pad_event_default (pad, event);
1008 break;
1009 }
1010 gst_object_unref (lame);
1011 return ret;
1012 }
1014 static GstFlowReturn
1015 gst_lame_chain (GstPad * pad, GstBuffer * buf)
1016 {
1017 GstLame *lame;
1018 guchar *mp3_data;
1019 gint mp3_buffer_size, mp3_size;
1020 gint64 duration;
1021 GstFlowReturn result;
1022 gint num_samples;
1023 guint8 *data;
1024 guint size;
1026 lame = GST_LAME (gst_pad_get_parent (pad));
1028 GST_LOG_OBJECT (lame, "entered chain");
1030 if (!lame->setup)
1031 goto not_setup;
1033 data = GST_BUFFER_DATA (buf);
1034 size = GST_BUFFER_SIZE (buf);
1036 num_samples = size / 2;
1038 /* allocate space for output */
1039 mp3_buffer_size = 1.25 * num_samples + 7200;
1040 mp3_data = g_malloc (mp3_buffer_size);
1042 /* lame seems to be too stupid to get mono interleaved going */
1043 if (lame->num_channels == 1) {
1044 mp3_size = lame_encode_buffer (lame->lgf,
1045 (short int *) data,
1046 (short int *) data, num_samples, mp3_data, mp3_buffer_size);
1047 } else {
1048 mp3_size = lame_encode_buffer_interleaved (lame->lgf,
1049 (short int *) data,
1050 num_samples / lame->num_channels, mp3_data, mp3_buffer_size);
1051 }
1053 GST_LOG_OBJECT (lame, "encoded %d bytes of audio to %d bytes of mp3",
1054 GST_BUFFER_SIZE (buf), mp3_size);
1056 duration = gst_util_uint64_scale_int (size, GST_SECOND,
1057 2 * lame->samplerate * lame->num_channels);
1059 if (GST_BUFFER_DURATION (buf) != GST_CLOCK_TIME_NONE &&
1060 GST_BUFFER_DURATION (buf) != duration)
1061 GST_DEBUG_OBJECT (lame, "incoming buffer had incorrect duration %"
1062 GST_TIME_FORMAT "outgoing buffer will have correct duration %"
1063 GST_TIME_FORMAT,
1064 GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (duration));
1066 if (lame->last_ts == GST_CLOCK_TIME_NONE) {
1067 lame->last_ts = GST_BUFFER_TIMESTAMP (buf);
1068 lame->last_offs = GST_BUFFER_OFFSET (buf);
1069 lame->last_duration = duration;
1070 } else {
1071 lame->last_duration += duration;
1072 }
1074 gst_buffer_unref (buf);
1076 if (mp3_size < 0) {
1077 g_warning ("error %d", mp3_size);
1078 }
1080 if (mp3_size > 0) {
1081 GstBuffer *outbuf;
1083 outbuf = gst_buffer_new ();
1084 GST_BUFFER_DATA (outbuf) = mp3_data;
1085 GST_BUFFER_MALLOCDATA (outbuf) = mp3_data;
1086 GST_BUFFER_SIZE (outbuf) = mp3_size;
1087 GST_BUFFER_TIMESTAMP (outbuf) = lame->last_ts;
1088 GST_BUFFER_OFFSET (outbuf) = lame->last_offs;
1089 GST_BUFFER_DURATION (outbuf) = lame->last_duration;
1090 gst_buffer_set_caps (outbuf, GST_PAD_CAPS (lame->srcpad));
1092 result = gst_pad_push (lame->srcpad, outbuf);
1094 lame->last_ts = GST_CLOCK_TIME_NONE;
1095 } else {
1096 g_free (mp3_data);
1097 result = GST_FLOW_OK;
1098 }
1099 gst_object_unref (lame);
1101 return result;
1103 /* ERRORS */
1104 not_setup:
1105 {
1106 gst_buffer_unref (buf);
1107 GST_ELEMENT_ERROR (lame, CORE, NEGOTIATION, (NULL),
1108 ("encoder not initialized (input is not audio?)"));
1109 gst_object_unref (lame);
1110 return GST_FLOW_ERROR;
1111 }
1112 }
1114 /* set up the encoder state */
1115 static gboolean
1116 gst_lame_setup (GstLame * lame)
1117 {
1118 #define CHECK_ERROR(command) G_STMT_START {\
1119 if ((command) < 0) { \
1120 GST_ERROR_OBJECT (lame, "setup failed: " G_STRINGIFY (command)); \
1121 return FALSE; \
1122 } \
1123 }G_STMT_END
1124 int retval;
1126 GST_DEBUG_OBJECT (lame, "starting setup");
1128 /* check if we're already setup; if we are, we might want to check
1129 * if this initialization is compatible with the previous one */
1130 /* FIXME: do this */
1131 if (lame->setup) {
1132 GST_WARNING_OBJECT (lame, "already setup");
1133 lame->setup = FALSE;
1134 }
1136 lame->lgf = lame_init ();
1137 id3tag_init (lame->lgf);
1139 /* let lame choose a default samplerate */
1140 lame_set_out_samplerate (lame->lgf, 0);
1142 /* copy the parameters over */
1143 lame_set_in_samplerate (lame->lgf, lame->samplerate);
1145 /* force mono encoding if we only have one channel */
1146 if (lame->num_channels == 1)
1147 lame->mode = 3;
1149 CHECK_ERROR (lame_set_num_channels (lame->lgf, lame->num_channels));
1150 CHECK_ERROR (lame_set_brate (lame->lgf, lame->bitrate));
1151 CHECK_ERROR (lame_set_compression_ratio (lame->lgf, lame->compression_ratio));
1152 CHECK_ERROR (lame_set_quality (lame->lgf, lame->quality));
1153 CHECK_ERROR (lame_set_mode (lame->lgf, lame->mode));
1154 CHECK_ERROR (lame_set_force_ms (lame->lgf, lame->force_ms));
1155 CHECK_ERROR (lame_set_free_format (lame->lgf, lame->free_format));
1156 CHECK_ERROR (lame_set_copyright (lame->lgf, lame->copyright));
1157 CHECK_ERROR (lame_set_original (lame->lgf, lame->original));
1158 CHECK_ERROR (lame_set_error_protection (lame->lgf, lame->error_protection));
1159 CHECK_ERROR (lame_set_padding_type (lame->lgf, lame->padding_type));
1160 CHECK_ERROR (lame_set_extension (lame->lgf, lame->extension));
1161 CHECK_ERROR (lame_set_strict_ISO (lame->lgf, lame->strict_iso));
1162 CHECK_ERROR (lame_set_disable_reservoir (lame->lgf, lame->disable_reservoir));
1163 CHECK_ERROR (lame_set_VBR (lame->lgf, lame->vbr));
1164 CHECK_ERROR (lame_set_VBR_q (lame->lgf, lame->vbr_quality));
1165 CHECK_ERROR (lame_set_VBR_mean_bitrate_kbps (lame->lgf,
1166 lame->vbr_mean_bitrate));
1167 CHECK_ERROR (lame_set_VBR_min_bitrate_kbps (lame->lgf,
1168 lame->vbr_min_bitrate));
1169 CHECK_ERROR (lame_set_VBR_max_bitrate_kbps (lame->lgf,
1170 lame->vbr_max_bitrate));
1171 CHECK_ERROR (lame_set_VBR_hard_min (lame->lgf, lame->vbr_hard_min));
1172 CHECK_ERROR (lame_set_lowpassfreq (lame->lgf, lame->lowpass_freq));
1173 CHECK_ERROR (lame_set_lowpasswidth (lame->lgf, lame->lowpass_width));
1174 CHECK_ERROR (lame_set_highpassfreq (lame->lgf, lame->highpass_freq));
1175 CHECK_ERROR (lame_set_highpasswidth (lame->lgf, lame->highpass_width));
1176 CHECK_ERROR (lame_set_ATHonly (lame->lgf, lame->ath_only));
1177 CHECK_ERROR (lame_set_ATHshort (lame->lgf, lame->ath_short));
1178 CHECK_ERROR (lame_set_noATH (lame->lgf, lame->no_ath));
1179 CHECK_ERROR (lame_set_ATHlower (lame->lgf, lame->ath_lower));
1180 CHECK_ERROR (lame_set_cwlimit (lame->lgf, lame->cwlimit));
1181 CHECK_ERROR (lame_set_allow_diff_short (lame->lgf, lame->allow_diff_short));
1182 CHECK_ERROR (lame_set_no_short_blocks (lame->lgf, lame->no_short_blocks));
1183 CHECK_ERROR (lame_set_emphasis (lame->lgf, lame->emphasis));
1184 #ifdef GSTLAME_PRESET
1185 if (lame->preset > 0) {
1186 CHECK_ERROR (lame_set_preset (lame->lgf, lame->preset));
1187 }
1188 #endif
1189 gst_lame_set_metadata (lame);
1191 /* initialize the lame encoder */
1192 if ((retval = lame_init_params (lame->lgf)) >= 0) {
1193 lame->setup = TRUE;
1194 /* FIXME: it would be nice to print out the mode here */
1195 GST_INFO ("lame encoder setup (%d kbit/s, %d Hz, %d channels)",
1196 lame->bitrate, lame->samplerate, lame->num_channels);
1197 } else {
1198 GST_ERROR_OBJECT (lame, "lame_init_params returned %d", retval);
1199 }
1201 GST_DEBUG_OBJECT (lame, "done with setup");
1203 return lame->setup;
1204 #undef CHECK_ERROR
1205 }
1207 static GstStateChangeReturn
1208 gst_lame_change_state (GstElement * element, GstStateChange transition)
1209 {
1210 GstLame *lame;
1211 GstStateChangeReturn result;
1213 lame = GST_LAME (element);
1215 switch (transition) {
1216 case GST_STATE_CHANGE_NULL_TO_READY:
1217 lame->tags = gst_tag_list_new ();
1218 case GST_STATE_CHANGE_READY_TO_PAUSED:
1219 lame->last_ts = GST_CLOCK_TIME_NONE;
1220 break;
1221 default:
1222 break;
1223 }
1225 result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1227 switch (transition) {
1228 case GST_STATE_CHANGE_READY_TO_NULL:
1229 gst_lame_release_memory (lame);
1230 break;
1231 default:
1232 break;
1233 }
1235 return result;
1236 }
1238 static gboolean
1239 plugin_init (GstPlugin * plugin)
1240 {
1241 if (!gst_element_register (plugin, "lame", GST_RANK_NONE, GST_TYPE_LAME))
1242 return FALSE;
1244 GST_DEBUG_CATEGORY_INIT (debug, "lame", 0, "lame mp3 encoder");
1245 return TRUE;
1246 }
1248 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1249 GST_VERSION_MINOR,
1250 "lame",
1251 "Encode MP3's with LAME",
1252 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);