]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - ext/lame/gstlame.c
configure.ac: rework similarly to other modules
[glsdk/gst-plugins-ugly0-10.git] / ext / lame / gstlame.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) <2004> Wim Taymans <wim@fluendo.com>
4  * Copyright (C) <2005> Thomas Vander Stichele <thomas at apestaart dot org>
5  *
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;
115 #define GST_TYPE_LAME_PADDING (gst_lame_padding_get_type())
116 static GType
117 gst_lame_padding_get_type (void)
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;
133 #define GST_TYPE_LAME_VBRMODE (gst_lame_vbrmode_get_type())
134 static GType
135 gst_lame_vbrmode_get_type (void)
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;
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)
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;
175 #endif
177 /********** Standard stuff for signals and arguments **********/
178 /* GstLame signals and args */
179 enum
181   /* FILL_ME */
182   LAST_SIGNAL
183 };
185 enum
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)
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;
278 static void
279 gst_lame_release_memory (GstLame * lame)
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   }
296 static void
297 gst_lame_finalize (GObject * obj)
299   gst_lame_release_memory (GST_LAME (obj));
301   G_OBJECT_CLASS (parent_class)->finalize (obj);
304 static void
305 gst_lame_base_init (gpointer g_class)
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);
316 static void
317 gst_lame_class_init (GstLameClass * klass)
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);
449 static gboolean
450 gst_lame_sink_setcaps (GstPad * pad, GstCaps * caps)
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   }
518 static void
519 gst_lame_init (GstLame * lame)
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");
593 typedef struct _GstLameTagMatch GstLameTagMatch;
594 typedef void (*GstLameTagFunc) (lame_global_flags * gfp, const char *value);
596 struct _GstLameTagMatch
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)
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);
681 static void
682 gst_lame_set_metadata (GstLame * lame)
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);
710 static void
711 gst_lame_set_property (GObject * object, guint prop_id, const GValue * value,
712     GParamSpec * pspec)
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   }
827 static void
828 gst_lame_get_property (GObject * object, guint prop_id, GValue * value,
829     GParamSpec * pspec)
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   }
944 static gboolean
945 gst_lame_sink_event (GstPad * pad, GstEvent * event)
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;
1014 static GstFlowReturn
1015 gst_lame_chain (GstPad * pad, GstBuffer * buf)
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   }
1114 /* set up the encoder state */
1115 static gboolean
1116 gst_lame_setup (GstLame * lame)
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
1207 static GstStateChangeReturn
1208 gst_lame_change_state (GstElement * element, GstStateChange transition)
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;
1238 static gboolean
1239 plugin_init (GstPlugin * plugin)
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;
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);