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