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