Revert "make creating audio decoders take codec data, too"
[swfdec.git] / swfdec / swfdec_audio_decoder_gst.c
blob9b29957fb3ecf722f2b58863e76353dc1e1e8d3e
1 /* Swfdec
2 * Copyright (C) 2006-2008 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 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 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <gst/pbutils/pbutils.h>
26 #include "swfdec_audio_decoder_gst.h"
27 #include "swfdec_debug.h"
28 #include "swfdec_internal.h"
30 /*** CAPS MATCHING ***/
32 static GstCaps *
33 swfdec_audio_decoder_get_caps (guint codec, SwfdecAudioFormat format)
35 GstCaps *caps;
36 char *s;
38 switch (codec) {
39 case SWFDEC_AUDIO_CODEC_MP3:
40 s = g_strdup ("audio/mpeg, mpegversion=(int)1, layer=(int)3");
41 break;
42 case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
43 s = g_strdup ("audio/x-nellymoser, rate=8000, channels=1");
44 break;
45 case SWFDEC_AUDIO_CODEC_NELLYMOSER:
46 s = g_strdup_printf ("audio/x-nellymoser, rate=%d, channels=%d",
47 swfdec_audio_format_get_rate (format),
48 swfdec_audio_format_get_channels (format));
49 break;
50 default:
51 return NULL;
54 caps = gst_caps_from_string (s);
55 g_assert (caps);
56 g_free (s);
57 return caps;
60 G_DEFINE_TYPE (SwfdecAudioDecoderGst, swfdec_audio_decoder_gst, SWFDEC_TYPE_AUDIO_DECODER)
62 static gboolean
63 swfdec_audio_decoder_gst_prepare (guint codec, SwfdecAudioFormat format, char **detail)
65 GstElementFactory *factory;
66 GstCaps *caps;
68 /* Check if we can handle the format at all. If not, no plugin will help us. */
69 caps = swfdec_audio_decoder_get_caps (codec, format);
70 if (caps == NULL)
71 return FALSE;
73 /* If we can already handle it, woohoo! */
74 factory = swfdec_gst_get_element_factory (caps);
75 if (factory != NULL) {
76 gst_object_unref (factory);
77 gst_caps_unref (caps);
78 return TRUE;
81 /* need to install plugins... */
82 *detail = gst_missing_decoder_installer_detail_new (caps);
83 gst_caps_unref (caps);
84 return FALSE;
87 static const char *
88 swfdec_audio_decoder_get_resampler (void)
90 /* FIXME: This is hardcoded as there's no autopluggable way to get the
91 * best resampler by rank.
92 * Even if there were, audioresample (which has the highest rank) is so slow
93 * it takes roughly a second to resample stuff that ffaudioresample does in
94 * 0.05 seconds.
96 static const char *options[] = { "ffaudioresample", "speexresample", "audioresample" };
97 guint i;
99 for (i = 0; i < G_N_ELEMENTS (options); i++) {
100 GstElementFactory *factory = gst_element_factory_find (options[i]);
101 if (factory) {
102 gst_object_unref (factory);
103 return options[i];
106 SWFDEC_ERROR ("no resampling element found. Check that GStreamer's base plugins are installed.");
107 return NULL;
110 static SwfdecAudioDecoder *
111 swfdec_audio_decoder_gst_create (guint type, SwfdecAudioFormat format)
113 SwfdecAudioDecoderGst *player;
114 GstCaps *srccaps, *sinkcaps;
115 const char *resample;
117 srccaps = swfdec_audio_decoder_get_caps (type, format);
118 if (srccaps == NULL)
119 return NULL;
121 player = g_object_new (SWFDEC_TYPE_AUDIO_DECODER_GST, NULL);
123 /* create decoder */
124 sinkcaps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2");
125 g_assert (sinkcaps);
126 resample = swfdec_audio_decoder_get_resampler ();
127 if (resample == NULL)
128 goto error;
129 if (!swfdec_gst_decoder_init (&player->dec, srccaps, sinkcaps,
130 "audioconvert", resample, NULL))
131 goto error;
133 gst_caps_unref (srccaps);
134 gst_caps_unref (sinkcaps);
135 return SWFDEC_AUDIO_DECODER (player);
137 error:
138 g_object_unref (player);
139 gst_caps_unref (srccaps);
140 gst_caps_unref (sinkcaps);
141 return NULL;
144 static void
145 swfdec_audio_decoder_gst_push (SwfdecAudioDecoder *dec, SwfdecBuffer *buffer)
147 SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
148 GstBuffer *buf;
150 if (buffer == NULL) {
151 swfdec_gst_decoder_push_eos (&player->dec);
152 } else {
153 swfdec_buffer_ref (buffer);
154 buf = swfdec_gst_buffer_new (buffer);
155 if (!swfdec_gst_decoder_push (&player->dec, buf))
156 swfdec_audio_decoder_error (dec, "error pushing");
160 static SwfdecBuffer *
161 swfdec_audio_decoder_gst_pull (SwfdecAudioDecoder *dec)
163 SwfdecAudioDecoderGst *player = SWFDEC_AUDIO_DECODER_GST (dec);
164 GstBuffer *buf;
166 buf = swfdec_gst_decoder_pull (&player->dec);
167 if (buf == NULL)
168 return NULL;
169 return swfdec_buffer_new_from_gst (buf);
172 static void
173 swfdec_audio_decoder_gst_dispose (GObject *object)
175 SwfdecAudioDecoderGst *player = (SwfdecAudioDecoderGst *) object;
177 swfdec_gst_decoder_finish (&player->dec);
179 G_OBJECT_CLASS (swfdec_audio_decoder_gst_parent_class)->dispose (object);
182 static void
183 swfdec_audio_decoder_gst_class_init (SwfdecAudioDecoderGstClass *klass)
185 GObjectClass *object_class = G_OBJECT_CLASS (klass);
186 SwfdecAudioDecoderClass *decoder_class = SWFDEC_AUDIO_DECODER_CLASS (klass);
188 object_class->dispose = swfdec_audio_decoder_gst_dispose;
190 decoder_class->prepare = swfdec_audio_decoder_gst_prepare;
191 decoder_class->create = swfdec_audio_decoder_gst_create;
192 decoder_class->pull = swfdec_audio_decoder_gst_pull;
193 decoder_class->push = swfdec_audio_decoder_gst_push;
196 static void
197 swfdec_audio_decoder_gst_init (SwfdecAudioDecoderGst *audio_decoder_gst)