1 /*
2 * Copyright (C) 2016 Sebastian Dröge <sebastian@centricular.com>
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., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "gstfdkaacdec.h"
25
26 #include <gst/pbutils/pbutils.h>
27
28 #include <string.h>
29
30 /* TODO:
31 * - LOAS / LATM support
32 * - Error concealment
33 */
34
35 #ifndef HAVE_FDK_AAC_0_1_4
36 #define AAC_PCM_MAX_OUTPUT_CHANNELS AAC_PCM_OUTPUT_CHANNELS
37 #define CHANNELS_CAPS_STR "channels = (int) [1, 6]"
38 #else
39 #define CHANNELS_CAPS_STR "channels = (int) [1, 8]"
40 #endif
41
42 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
43 GST_PAD_SINK,
44 GST_PAD_ALWAYS,
45 GST_STATIC_CAPS ("audio/mpeg, "
46 "mpegversion = (int) {2, 4}, "
47 "stream-format = (string) { adts, adif, raw }, " CHANNELS_CAPS_STR)
48 );
49
50 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
51 GST_PAD_SRC,
52 GST_PAD_ALWAYS,
53 GST_STATIC_CAPS ("audio/x-raw, "
54 "format = (string) " GST_AUDIO_NE (S16) ", "
55 "layout = (string) interleaved, "
56 "rate = (int) [8000, 96000], " CHANNELS_CAPS_STR)
57 );
58
59 GST_DEBUG_CATEGORY_STATIC (gst_fdkaacdec_debug);
60 #define GST_CAT_DEFAULT gst_fdkaacdec_debug
61
62 static gboolean gst_fdkaacdec_start (GstAudioDecoder * dec);
63 static gboolean gst_fdkaacdec_stop (GstAudioDecoder * dec);
64 static gboolean gst_fdkaacdec_set_format (GstAudioDecoder * dec,
65 GstCaps * caps);
66 static GstFlowReturn gst_fdkaacdec_handle_frame (GstAudioDecoder * dec,
67 GstBuffer * in_buf);
68 static void gst_fdkaacdec_flush (GstAudioDecoder * dec, gboolean hard);
69
70 G_DEFINE_TYPE (GstFdkAacDec, gst_fdkaacdec, GST_TYPE_AUDIO_DECODER);
71 GST_ELEMENT_REGISTER_DEFINE (fdkaacdec, "fdkaacdec", GST_RANK_MARGINAL,
72 GST_TYPE_FDKAACDEC);
73
74 static gboolean
gst_fdkaacdec_start(GstAudioDecoder * dec)75 gst_fdkaacdec_start (GstAudioDecoder * dec)
76 {
77 GstFdkAacDec *self = GST_FDKAACDEC (dec);
78
79 GST_DEBUG_OBJECT (self, "start");
80
81 return TRUE;
82 }
83
84 static gboolean
gst_fdkaacdec_stop(GstAudioDecoder * dec)85 gst_fdkaacdec_stop (GstAudioDecoder * dec)
86 {
87 GstFdkAacDec *self = GST_FDKAACDEC (dec);
88
89 GST_DEBUG_OBJECT (self, "stop");
90
91 g_free (self->decode_buffer);
92 self->decode_buffer = NULL;
93
94 if (self->dec)
95 aacDecoder_Close (self->dec);
96 self->dec = NULL;
97
98 return TRUE;
99 }
100
101 static gboolean
gst_fdkaacdec_set_format(GstAudioDecoder * dec,GstCaps * caps)102 gst_fdkaacdec_set_format (GstAudioDecoder * dec, GstCaps * caps)
103 {
104 GstFdkAacDec *self = GST_FDKAACDEC (dec);
105 TRANSPORT_TYPE transport_format;
106 GstStructure *s;
107 const gchar *stream_format;
108 AAC_DECODER_ERROR err;
109
110 if (self->dec) {
111 /* drain */
112 gst_fdkaacdec_handle_frame (dec, NULL);
113 aacDecoder_Close (self->dec);
114 self->dec = NULL;
115 }
116
117 s = gst_caps_get_structure (caps, 0);
118 stream_format = gst_structure_get_string (s, "stream-format");
119 if (strcmp (stream_format, "raw") == 0) {
120 transport_format = TT_MP4_RAW;
121 } else if (strcmp (stream_format, "adif") == 0) {
122 transport_format = TT_MP4_ADIF;
123 } else if (strcmp (stream_format, "adts") == 0) {
124 transport_format = TT_MP4_ADTS;
125 } else {
126 g_assert_not_reached ();
127 }
128
129 self->dec = aacDecoder_Open (transport_format, 1);
130 if (!self->dec) {
131 GST_ERROR_OBJECT (self, "Failed to open decoder");
132 return FALSE;
133 }
134
135 if (transport_format == TT_MP4_RAW) {
136 GstBuffer *codec_data = NULL;
137 GstMapInfo map;
138 guint8 *data;
139 guint size;
140
141 gst_structure_get (s, "codec_data", GST_TYPE_BUFFER, &codec_data, NULL);
142
143 if (!codec_data) {
144 GST_ERROR_OBJECT (self, "Raw AAC without codec_data not supported");
145 return FALSE;
146 }
147
148 gst_buffer_map (codec_data, &map, GST_MAP_READ);
149 data = map.data;
150 size = map.size;
151
152 if ((err = aacDecoder_ConfigRaw (self->dec, &data, &size)) != AAC_DEC_OK) {
153 gst_buffer_unmap (codec_data, &map);
154 gst_buffer_unref (codec_data);
155 GST_ERROR_OBJECT (self, "Invalid codec_data: %d", err);
156 return FALSE;
157 }
158
159 gst_buffer_unmap (codec_data, &map);
160 gst_buffer_unref (codec_data);
161 }
162
163 err = aacDecoder_SetParam (self->dec, AAC_PCM_MAX_OUTPUT_CHANNELS, 0);
164 if (err != AAC_DEC_OK) {
165 GST_ERROR_OBJECT (self, "Failed to disable downmixing: %d", err);
166 return FALSE;
167 }
168
169 /* Choose WAV channel mapping to get interleaving even with libfdk-aac 2.0.0
170 * The pChannelIndices retain the indices from the standard MPEG mapping so
171 * we're agnostic to the actual order. */
172 err = aacDecoder_SetParam (self->dec, AAC_PCM_OUTPUT_CHANNEL_MAPPING, 1);
173 if (err != AAC_DEC_OK) {
174 GST_ERROR_OBJECT (self, "Failed to set output channel mapping: %d", err);
175 return FALSE;
176 }
177
178 /* 8 channels * 2 bytes per sample * 2048 samples */
179 if (!self->decode_buffer) {
180 self->decode_buffer_size = 8 * 2048;
181 self->decode_buffer = g_new (gint16, self->decode_buffer_size);
182 }
183
184 return TRUE;
185 }
186
187 static GstFlowReturn
gst_fdkaacdec_handle_frame(GstAudioDecoder * dec,GstBuffer * inbuf)188 gst_fdkaacdec_handle_frame (GstAudioDecoder * dec, GstBuffer * inbuf)
189 {
190 GstFdkAacDec *self = GST_FDKAACDEC (dec);
191 GstFlowReturn ret = GST_FLOW_OK;
192 GstBuffer *outbuf;
193 GstMapInfo imap;
194 AAC_DECODER_ERROR err;
195 guint size, valid;
196 CStreamInfo *stream_info;
197 GstAudioInfo info;
198 guint flags = 0, i;
199 GstAudioChannelPosition pos[64], gst_pos[64];
200 gboolean need_reorder;
201
202 if (inbuf) {
203 gst_buffer_ref (inbuf);
204 gst_buffer_map (inbuf, &imap, GST_MAP_READ);
205 valid = size = imap.size;
206
207 err = aacDecoder_Fill (self->dec, (guint8 **) & imap.data, &size, &valid);
208 if (err != AAC_DEC_OK) {
209 GST_AUDIO_DECODER_ERROR (self, 1, STREAM, DECODE, (NULL),
210 ("filling error: %d", err), ret);
211 goto out;
212 }
213
214 if (GST_BUFFER_IS_DISCONT (inbuf)) {
215 flags |= AACDEC_INTR;
216 }
217 } else {
218 flags |= AACDEC_FLUSH;
219 }
220
221 err = aacDecoder_DecodeFrame (self->dec, self->decode_buffer,
222 self->decode_buffer_size, flags);
223 if (err == AAC_DEC_TRANSPORT_SYNC_ERROR) {
224 ret = GST_FLOW_OK;
225 outbuf = NULL;
226 goto finish;
227 } else if (err != AAC_DEC_OK) {
228 GST_AUDIO_DECODER_ERROR (self, 1, STREAM, DECODE, (NULL),
229 ("decoding error: %d", err), ret);
230 goto out;
231 }
232
233 stream_info = aacDecoder_GetStreamInfo (self->dec);
234 if (!stream_info) {
235 GST_AUDIO_DECODER_ERROR (self, 1, STREAM, DECODE, (NULL),
236 ("failed to get stream info"), ret);
237 goto out;
238 }
239
240 /* FIXME: Don't recalculate this on every buffer */
241 if (stream_info->numChannels == 1) {
242 pos[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
243 } else {
244 gint n_front = 0, n_back = 0, n_lfe = 0;
245
246 /* FIXME: Can this be simplified somehow? */
247 for (i = 0; i < stream_info->numChannels; i++) {
248 if (stream_info->pChannelType[i] == ACT_FRONT) {
249 n_front++;
250 } else if (stream_info->pChannelType[i] == ACT_BACK) {
251 n_back++;
252 } else if (stream_info->pChannelType[i] == ACT_LFE) {
253 n_lfe++;
254 } else {
255 GST_ERROR_OBJECT (self, "Channel type %d not supported",
256 stream_info->pChannelType[i]);
257 ret = GST_FLOW_NOT_NEGOTIATED;
258 goto out;
259 }
260 }
261
262 for (i = 0; i < stream_info->numChannels; i++) {
263 if (stream_info->pChannelType[i] == ACT_FRONT) {
264 if (stream_info->pChannelIndices[i] == 0) {
265 if (n_front & 1)
266 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
267 else if (n_front > 2)
268 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
269 else
270 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
271 } else if (stream_info->pChannelIndices[i] == 1) {
272 if ((n_front & 1) && n_front > 3)
273 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
274 else if (n_front & 1)
275 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
276 else if (n_front > 2)
277 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
278 else
279 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
280 } else if (stream_info->pChannelIndices[i] == 2) {
281 if ((n_front & 1) && n_front > 3)
282 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
283 else if (n_front & 1)
284 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
285 else if (n_front > 2)
286 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
287 else
288 g_assert_not_reached ();
289 } else if (stream_info->pChannelIndices[i] == 3) {
290 if ((n_front & 1) && n_front > 3)
291 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
292 else if (n_front & 1)
293 g_assert_not_reached ();
294 else if (n_front > 2)
295 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
296 else
297 g_assert_not_reached ();
298 } else if (stream_info->pChannelIndices[i] == 4) {
299 if ((n_front & 1) && n_front > 2)
300 pos[i] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
301 else if (n_front & 1)
302 g_assert_not_reached ();
303 else if (n_front > 2)
304 g_assert_not_reached ();
305 else
306 g_assert_not_reached ();
307 } else {
308 GST_ERROR_OBJECT (self, "Front channel index %d not supported",
309 stream_info->pChannelIndices[i]);
310 ret = GST_FLOW_NOT_NEGOTIATED;
311 goto out;
312 }
313 } else if (stream_info->pChannelType[i] == ACT_BACK) {
314 if (stream_info->pChannelIndices[i] == 0) {
315 if (n_back & 1)
316 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
317 else if (n_back > 2)
318 pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
319 else
320 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
321 } else if (stream_info->pChannelIndices[i] == 1) {
322 if ((n_back & 1) && n_back > 3)
323 pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT;
324 else if (n_back & 1)
325 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
326 else if (n_back > 2)
327 pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
328 else
329 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
330 } else if (stream_info->pChannelIndices[i] == 2) {
331 if ((n_back & 1) && n_back > 3)
332 pos[i] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT;
333 else if (n_back & 1)
334 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
335 else if (n_back > 2)
336 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
337 else
338 g_assert_not_reached ();
339 } else if (stream_info->pChannelIndices[i] == 3) {
340 if ((n_back & 1) && n_back > 3)
341 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
342 else if (n_back & 1)
343 g_assert_not_reached ();
344 else if (n_back > 2)
345 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
346 else
347 g_assert_not_reached ();
348 } else if (stream_info->pChannelIndices[i] == 4) {
349 if ((n_back & 1) && n_back > 3)
350 pos[i] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
351 else if (n_back & 1)
352 g_assert_not_reached ();
353 else if (n_back > 2)
354 g_assert_not_reached ();
355 else
356 g_assert_not_reached ();
357 } else {
358 GST_ERROR_OBJECT (self, "Side channel index %d not supported",
359 stream_info->pChannelIndices[i]);
360 ret = GST_FLOW_NOT_NEGOTIATED;
361 goto out;
362 }
363 } else if (stream_info->pChannelType[i] == ACT_LFE) {
364 if (stream_info->pChannelIndices[i] == 0) {
365 pos[i] = GST_AUDIO_CHANNEL_POSITION_LFE1;
366 } else {
367 GST_ERROR_OBJECT (self, "LFE channel index %d not supported",
368 stream_info->pChannelIndices[i]);
369 ret = GST_FLOW_NOT_NEGOTIATED;
370 goto out;
371 }
372 } else {
373 GST_ERROR_OBJECT (self, "Channel type %d not supported",
374 stream_info->pChannelType[i]);
375 ret = GST_FLOW_NOT_NEGOTIATED;
376 goto out;
377 }
378 }
379 }
380
381 memcpy (gst_pos, pos,
382 sizeof (GstAudioChannelPosition) * stream_info->numChannels);
383 if (!gst_audio_channel_positions_to_valid_order (gst_pos,
384 stream_info->numChannels)) {
385 ret = GST_FLOW_NOT_NEGOTIATED;
386 goto out;
387 }
388
389 need_reorder =
390 memcmp (pos, gst_pos,
391 sizeof (GstAudioChannelPosition) * stream_info->numChannels) != 0;
392
393 gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16,
394 stream_info->sampleRate, stream_info->numChannels, gst_pos);
395 if (!gst_audio_decoder_set_output_format (dec, &info)) {
396 GST_ERROR_OBJECT (self, "Failed to set output format");
397 ret = GST_FLOW_NOT_NEGOTIATED;
398 goto out;
399 }
400
401 outbuf =
402 gst_audio_decoder_allocate_output_buffer (dec,
403 stream_info->frameSize * GST_AUDIO_INFO_BPF (&info));
404 gst_buffer_fill (outbuf, 0, self->decode_buffer,
405 gst_buffer_get_size (outbuf));
406
407 if (need_reorder) {
408 gst_audio_buffer_reorder_channels (outbuf, GST_AUDIO_INFO_FORMAT (&info),
409 GST_AUDIO_INFO_CHANNELS (&info), pos, gst_pos);
410 }
411
412 finish:
413 ret = gst_audio_decoder_finish_frame (dec, outbuf, 1);
414
415 out:
416
417 if (inbuf) {
418 gst_buffer_unmap (inbuf, &imap);
419 gst_buffer_unref (inbuf);
420 }
421
422 return ret;
423 }
424
425 static void
gst_fdkaacdec_flush(GstAudioDecoder * dec,gboolean hard)426 gst_fdkaacdec_flush (GstAudioDecoder * dec, gboolean hard)
427 {
428 GstFdkAacDec *self = GST_FDKAACDEC (dec);
429
430 if (self->dec) {
431 AAC_DECODER_ERROR err;
432 err = aacDecoder_DecodeFrame (self->dec, self->decode_buffer,
433 self->decode_buffer_size, AACDEC_FLUSH);
434 if (err != AAC_DEC_OK) {
435 GST_ERROR_OBJECT (self, "flushing error: %d", err);
436 }
437 }
438 }
439
440 static void
gst_fdkaacdec_init(GstFdkAacDec * self)441 gst_fdkaacdec_init (GstFdkAacDec * self)
442 {
443 self->dec = NULL;
444
445 gst_audio_decoder_set_drainable (GST_AUDIO_DECODER (self), TRUE);
446 gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (self), TRUE);
447 }
448
449 static void
gst_fdkaacdec_class_init(GstFdkAacDecClass * klass)450 gst_fdkaacdec_class_init (GstFdkAacDecClass * klass)
451 {
452 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
453 GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
454
455 base_class->start = GST_DEBUG_FUNCPTR (gst_fdkaacdec_start);
456 base_class->stop = GST_DEBUG_FUNCPTR (gst_fdkaacdec_stop);
457 base_class->set_format = GST_DEBUG_FUNCPTR (gst_fdkaacdec_set_format);
458 base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_fdkaacdec_handle_frame);
459 base_class->flush = GST_DEBUG_FUNCPTR (gst_fdkaacdec_flush);
460
461 gst_element_class_add_static_pad_template (element_class, &sink_template);
462 gst_element_class_add_static_pad_template (element_class, &src_template);
463
464 gst_element_class_set_static_metadata (element_class, "FDK AAC audio decoder",
465 "Codec/Decoder/Audio", "FDK AAC audio decoder",
466 "Sebastian Dröge <sebastian@centricular.com>");
467
468 GST_DEBUG_CATEGORY_INIT (gst_fdkaacdec_debug, "fdkaacdec", 0,
469 "fdkaac decoder");
470 }
471