2 * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
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
7 * version 2.1 of the License.
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, Boston, MA 02110-1301 USA
26 #include "gstomxaacdec.h"
28 GST_DEBUG_CATEGORY_STATIC (gst_omx_aac_dec_debug_category);
29 #define GST_CAT_DEFAULT gst_omx_aac_dec_debug_category
32 static gboolean gst_omx_aac_dec_set_format (GstOMXAudioDec * dec,
33 GstOMXPort * port, GstCaps * caps);
34 static gboolean gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec,
35 GstOMXPort * port, GstCaps * caps);
36 static gint gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec,
38 static gboolean gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
39 GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
41 /* class initialization */
44 GST_DEBUG_CATEGORY_INIT (gst_omx_aac_dec_debug_category, "omxaacdec", 0, \
45 "debug category for gst-omx aac audio decoder");
47 G_DEFINE_TYPE_WITH_CODE (GstOMXAACDec, gst_omx_aac_dec,
48 GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
51 gst_omx_aac_dec_class_init (GstOMXAACDecClass * klass)
53 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
54 GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
56 audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_aac_dec_set_format);
57 audiodec_class->is_format_change =
58 GST_DEBUG_FUNCPTR (gst_omx_aac_dec_is_format_change);
59 audiodec_class->get_samples_per_frame =
60 GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_samples_per_frame);
61 audiodec_class->get_channel_positions =
62 GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_channel_positions);
64 audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, "
65 "mpegversion=(int){2, 4}, "
66 "stream-format=(string) { raw, adts, adif, loas }, "
67 "rate=(int)[8000,48000], "
68 "channels=(int)[1,9], " "framed=(boolean) true";
70 gst_element_class_set_static_metadata (element_class,
71 "OpenMAX AAC Audio Decoder",
72 "Codec/Decoder/Audio/Hardware",
73 "Decode AAC audio streams",
74 "Sebastian Dröge <sebastian@centricular.com>");
76 gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.aac");
80 gst_omx_aac_dec_init (GstOMXAACDec * self)
82 /* FIXME: Other values exist too! */
87 gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
90 GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
91 OMX_PARAM_PORTDEFINITIONTYPE port_def;
92 OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
95 gint rate, channels, mpegversion;
96 const gchar *stream_format;
98 gst_omx_port_get_port_definition (port, &port_def);
99 port_def.format.audio.eEncoding = OMX_AUDIO_CodingAAC;
100 err = gst_omx_port_update_port_definition (port, &port_def);
101 if (err != OMX_ErrorNone) {
102 GST_ERROR_OBJECT (self,
103 "Failed to set AAC format on component: %s (0x%08x)",
104 gst_omx_error_to_string (err), err);
108 GST_OMX_INIT_STRUCT (&aac_param);
109 aac_param.nPortIndex = port->index;
112 gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
114 if (err != OMX_ErrorNone) {
115 GST_ERROR_OBJECT (self,
116 "Failed to get AAC parameters from component: %s (0x%08x)",
117 gst_omx_error_to_string (err), err);
121 s = gst_caps_get_structure (caps, 0);
123 if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
124 !gst_structure_get_int (s, "rate", &rate) ||
125 !gst_structure_get_int (s, "channels", &channels)) {
126 GST_ERROR_OBJECT (self, "Incomplete caps");
130 stream_format = gst_structure_get_string (s, "stream-format");
131 if (!stream_format) {
132 GST_ERROR_OBJECT (self, "Incomplete caps");
136 aac_param.nChannels = channels;
137 aac_param.nSampleRate = rate;
138 aac_param.nBitRate = 0; /* unknown */
139 aac_param.nAudioBandWidth = 0; /* decoder decision */
140 aac_param.eChannelMode = 0; /* FIXME */
141 if (mpegversion == 2)
142 aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS;
143 else if (strcmp (stream_format, "adts") == 0)
144 aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
145 else if (strcmp (stream_format, "loas") == 0)
146 aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS;
147 else if (strcmp (stream_format, "adif") == 0)
148 aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
149 else if (strcmp (stream_format, "raw") == 0)
150 aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW;
152 GST_ERROR_OBJECT (self, "Unexpected format: %s", stream_format);
157 gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAac,
159 if (err != OMX_ErrorNone) {
160 GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)",
161 gst_omx_error_to_string (err), err);
169 gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
172 GstOMXAACDec *self = GST_OMX_AAC_DEC (dec);
173 OMX_AUDIO_PARAM_AACPROFILETYPE aac_param;
176 gint rate, channels, mpegversion;
177 const gchar *stream_format;
179 GST_OMX_INIT_STRUCT (&aac_param);
180 aac_param.nPortIndex = port->index;
183 gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac,
185 if (err != OMX_ErrorNone) {
186 GST_ERROR_OBJECT (self,
187 "Failed to get AAC parameters from component: %s (0x%08x)",
188 gst_omx_error_to_string (err), err);
192 s = gst_caps_get_structure (caps, 0);
194 if (!gst_structure_get_int (s, "mpegversion", &mpegversion) ||
195 !gst_structure_get_int (s, "rate", &rate) ||
196 !gst_structure_get_int (s, "channels", &channels)) {
197 GST_ERROR_OBJECT (self, "Incomplete caps");
201 stream_format = gst_structure_get_string (s, "stream-format");
202 if (!stream_format) {
203 GST_ERROR_OBJECT (self, "Incomplete caps");
207 if (aac_param.nChannels != channels)
210 if (aac_param.nSampleRate != rate)
214 && aac_param.eAACStreamFormat != OMX_AUDIO_AACStreamFormatMP2ADTS)
216 if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS &&
217 strcmp (stream_format, "adts") != 0)
219 if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4LOAS &&
220 strcmp (stream_format, "loas") != 0)
222 if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF &&
223 strcmp (stream_format, "adif") != 0)
225 if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW &&
226 strcmp (stream_format, "raw") != 0)
233 gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
235 return GST_OMX_AAC_DEC (dec)->spf;
239 gst_omx_aac_dec_get_channel_positions (GstOMXAudioDec * dec,
240 GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
242 OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
245 GST_OMX_INIT_STRUCT (&pcm_param);
246 pcm_param.nPortIndex = port->index;
248 gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
250 if (err != OMX_ErrorNone) {
251 GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
252 gst_omx_error_to_string (err), err);
256 /* FIXME: Rather arbitrary values here, based on what we do in gstfaac.c */
257 switch (pcm_param.nChannels) {
259 position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
262 position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
263 position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
266 position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
267 position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
268 position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
271 position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
272 position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
273 position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
274 position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_CENTER;
277 position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
278 position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
279 position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
280 position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
281 position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
284 position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER;
285 position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT;
286 position[2] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT;
287 position[3] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT;
288 position[4] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT;
289 position[5] = GST_AUDIO_CHANNEL_POSITION_LFE1;