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