1 // AudioDecoderGst.cpp: Audio decoding using Gstreamer.
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program 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
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
20 #include "AudioDecoderGst.h"
21 #include "MediaParser.h" // for AudioInfo
22 #include "MediaParserGst.h"
23 #include "GstUtil.h"
24 #include "FLVParser.h" // for ExtraAudioInfoFlv
25 #include "SoundInfo.h"
26
27 namespace gnash {
28 namespace media {
29 namespace gst {
30
31
AudioDecoderGst(SoundInfo & info,std::shared_ptr<HostInterface> eventHandler)32 AudioDecoderGst::AudioDecoderGst(SoundInfo& info, std::shared_ptr<HostInterface> eventHandler)
33 :
34 _eventHandler(eventHandler)
35 {
36 // init GStreamer. TODO: what about doing this in MediaHandlerGst ctor?
37 gst_init (nullptr, nullptr);
38
39 GstCaps* srccaps = gst_caps_new_simple ("audio/mpeg",
40 "mpegversion", G_TYPE_INT, 1,
41 "layer", G_TYPE_INT, 3,
42 "rate", G_TYPE_INT, info.getSampleRate(),
43 "channels", G_TYPE_INT, info.isStereo() ? 2 : 1, NULL);
44
45 setup(srccaps);
46
47 // FIXME: should we handle other types?
48 }
49
AudioDecoderGst(const AudioInfo & info,std::shared_ptr<HostInterface> eventHandler)50 AudioDecoderGst::AudioDecoderGst(const AudioInfo& info, std::shared_ptr<HostInterface> eventHandler)
51 :
52 _eventHandler(eventHandler)
53 {
54 // init GStreamer. TODO: what about doing this in MediaHandlerGst ctor?
55 gst_init (nullptr, nullptr);
56
57 GstCaps* srccaps=nullptr;
58
59 if (info.type == CODEC_TYPE_FLASH && info.codec == AUDIO_CODEC_MP3)
60 {
61 srccaps = gst_caps_new_simple ("audio/mpeg",
62 "mpegversion", G_TYPE_INT, 1,
63 "layer", G_TYPE_INT, 3,
64 "rate", G_TYPE_INT, info.sampleRate,
65 "channels", G_TYPE_INT, info.stereo ? 2 : 1, NULL);
66 setup(srccaps);
67 return;
68 }
69
70 if (info.type == CODEC_TYPE_FLASH && info.codec == AUDIO_CODEC_NELLYMOSER)
71 {
72 srccaps = gst_caps_new_simple ("audio/x-nellymoser",
73 "rate", G_TYPE_INT, info.sampleRate,
74 "channels", G_TYPE_INT, info.stereo ? 2 : 1, NULL);
75 setup(srccaps);
76 return;
77 }
78
79 if (info.type == CODEC_TYPE_FLASH && info.codec == AUDIO_CODEC_ADPCM)
80 {
81 srccaps = gst_caps_new_simple ("audio/x-adpcm",
82 "rate", G_TYPE_INT, info.sampleRate,
83 "channels", G_TYPE_INT, info.stereo ? 2 : 1,
84 "layout", G_TYPE_STRING, "swf", NULL);
85 setup(srccaps);
86 return;
87 }
88
89 if (info.type == CODEC_TYPE_FLASH && info.codec == AUDIO_CODEC_AAC)
90 {
91 srccaps = gst_caps_new_simple ("audio/mpeg",
92 "mpegversion", G_TYPE_INT, 4,
93 "rate", G_TYPE_INT, 44100,
94 "channels", G_TYPE_INT, 2,
95 NULL);
96
97 ExtraAudioInfoFlv* extra = dynamic_cast<ExtraAudioInfoFlv*>(info.extra.get());
98 if (extra) {
99 GstBuffer* buf = gst_buffer_new_and_alloc(extra->size);
100 memcpy(GST_BUFFER_DATA(buf), extra->data.get(), extra->size);
101 gst_caps_set_simple (srccaps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
102
103 } else {
104 log_error(_("Creating AAC decoder without extra data. This will probably fail!"));
105 }
106
107 setup(srccaps);
108 return;
109 }
110
111
112 if (info.type == CODEC_TYPE_FLASH) {
113 boost::format err = boost::format(
114 _("AudioDecoderGst: cannot handle codec %d (%s)")) %
115 info.codec %
116 (audioCodecType)info.codec;
117 throw MediaException(err.str());
118 }
119
120 ExtraInfoGst* extraaudioinfo = dynamic_cast<ExtraInfoGst*>(info.extra.get());
121
122 if (!extraaudioinfo) {
123 boost::format err = boost::format(
124 _("AudioDecoderGst: cannot handle codec %d "
125 "(no ExtraInfoGst attached)")) %
126 info.codec;
127 throw MediaException(err.str());
128 }
129
130 gst_caps_ref(extraaudioinfo->caps);
131 setup(extraaudioinfo->caps);
132 }
133
~AudioDecoderGst()134 AudioDecoderGst::~AudioDecoderGst()
135 {
136 assert(g_queue_is_empty (_decoder.queue));
137 swfdec_gst_decoder_push_eos(&_decoder);
138 swfdec_gst_decoder_finish(&_decoder);
139 }
140
141 /// Find the best available audio resampler on the system
142 static std::string
findResampler()143 findResampler()
144 {
145 std::string resampler = "ffaudioresample";
146
147 GstElementFactory* factory = gst_element_factory_find(resampler.c_str());
148
149 if (!factory) {
150 resampler = "speexresample";
151 factory = gst_element_factory_find(resampler.c_str());
152 if (!factory) {
153 log_error(_("The best available resampler is 'audioresample'."
154 " Please install gstreamer-ffmpeg 0.10.4 or newer, or you"
155 " may experience long delays in audio playback!"));
156 resampler = "audioresample";
157 }
158 }
159
160 if (factory) {
161 gst_object_unref(factory);
162 }
163
164 return resampler;
165 }
166
167
168
setup(GstCaps * srccaps)169 void AudioDecoderGst::setup(GstCaps* srccaps)
170 {
171 if (!srccaps) {
172 throw MediaException(_("AudioDecoderGst: internal error (caps creation failed)"));
173 }
174
175 bool success = GstUtil::check_missing_plugins(srccaps, _eventHandler.get());
176 if (!success) {
177 GstStructure* sct = gst_caps_get_structure(srccaps, 0);
178 std::string type(gst_structure_get_name(sct));
179 std::string msg = (boost::format(_("Couldn't find a plugin for "
180 "audio type %s!")) % type).str();
181
182 gst_caps_unref(srccaps);
183
184 throw MediaException(msg);
185 }
186
187
188 GstCaps* sinkcaps = gst_caps_from_string ("audio/x-raw-int, "
189 "endianness=byte_order, signed=(boolean)true, width=16, "
190 "depth=16, rate=44100, channels=2");
191 if (!sinkcaps) {
192 throw MediaException(_("AudioDecoderGst: internal error "
193 "(caps creation failed)"));
194 }
195
196 std::string resampler = findResampler();
197
198 success = swfdec_gst_decoder_init (&_decoder, srccaps, sinkcaps, "audioconvert", resampler.c_str(), NULL);
199 if (!success) {
200 GstStructure* sct = gst_caps_get_structure(srccaps, 0);
201 std::string type(gst_structure_get_name(sct));
202 std::string msg = (boost::format(
203 _("AudioDecoderGst: initialisation failed for audio type %s!"))
204 % type).str();
205 throw MediaException(msg);
206 }
207
208 gst_caps_unref (srccaps);
209 gst_caps_unref (sinkcaps);
210 }
211
212 static void
buf_add(gpointer buf,gpointer data)213 buf_add(gpointer buf, gpointer data)
214 {
215 std::uint32_t* total = (std::uint32_t*) data;
216
217 GstBuffer* buffer = (GstBuffer*) buf;
218 *total += GST_BUFFER_SIZE(buffer);
219 }
220
221
222 /* private */
223 std::uint8_t*
pullBuffers(std::uint32_t & outputSize)224 AudioDecoderGst::pullBuffers(std::uint32_t& outputSize)
225 {
226 outputSize = 0;
227
228 g_queue_foreach(_decoder.queue, buf_add, &outputSize);
229
230 if (!outputSize) {
231 log_debug(_("Pushed data, but there's nothing to pull (yet)"));
232 return nullptr;
233 }
234
235 std::uint8_t* rbuf = new std::uint8_t[outputSize];
236
237 std::uint8_t* ptr = rbuf;
238
239 while (true) {
240
241 GstBuffer* buffer = swfdec_gst_decoder_pull (&_decoder);
242 if (!buffer) {
243 break;
244 }
245
246 memcpy(ptr, GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer));
247 ptr += GST_BUFFER_SIZE(buffer);
248
249 gst_buffer_unref (buffer);
250 }
251
252 return rbuf;
253 }
254
255 std::uint8_t*
decode(const std::uint8_t * input,std::uint32_t inputSize,std::uint32_t & outputSize,std::uint32_t & decodedData)256 AudioDecoderGst::decode(const std::uint8_t* input, std::uint32_t inputSize,
257 std::uint32_t& outputSize,
258 std::uint32_t& decodedData)
259 {
260 outputSize = decodedData = 0;
261
262 GstBuffer* gstbuf = gst_buffer_new_and_alloc(inputSize);
263 memcpy (GST_BUFFER_DATA (gstbuf), input, inputSize);
264
265 bool success = swfdec_gst_decoder_push(&_decoder, gstbuf);
266 if (!success) {
267 log_error(_("AudioDecoderGst: buffer push failed."));
268 return nullptr;
269 }
270
271 decodedData = inputSize;
272
273 return pullBuffers(outputSize);
274 }
275
276 std::uint8_t*
decode(const EncodedAudioFrame & ef,std::uint32_t & outputSize)277 AudioDecoderGst::decode(const EncodedAudioFrame& ef, std::uint32_t& outputSize)
278 {
279 outputSize = 0;
280
281 GstBuffer* gstbuf;
282
283 EncodedExtraGstData* extradata = dynamic_cast<EncodedExtraGstData*>(ef.extradata.get());
284
285 if (extradata) {
286 gstbuf = extradata->buffer;
287 } else {
288
289 gstbuf = gst_buffer_new_and_alloc(ef.dataSize);
290 memcpy (GST_BUFFER_DATA (gstbuf), ef.data.get(), ef.dataSize);
291 }
292
293 bool success = swfdec_gst_decoder_push(&_decoder, gstbuf);
294 if (!success) {
295 log_error(_("AudioDecoderGst: buffer push failed."));
296 return nullptr;
297 }
298
299 return pullBuffers(outputSize);
300 }
301
302
303 } // gnash.media.gst namespace
304 } // end of media namespace
305 } // end of gnash namespace
306
307
308