• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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