From: Sebastian Dröge Date: Sun, 13 Jul 2014 16:22:39 +0000 (+0200) Subject: omx: Add AAC audio decoder X-Git-Tag: 1.19.3~501^2~428 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=03cf0bc9a40c44e35add8c8a139cc0e954d29a6e;p=platform%2Fupstream%2Fgstreamer.git omx: Add AAC audio decoder --- diff --git a/omx/Makefile.am b/omx/Makefile.am index 203d28f..9182579 100644 --- a/omx/Makefile.am +++ b/omx/Makefile.am @@ -29,6 +29,7 @@ libgstomx_la_SOURCES = \ gstomxmpeg4videoenc.c \ gstomxh264enc.c \ gstomxh263enc.c \ + gstomxaacdec.c \ gstomxmp3dec.c \ gstomxaacenc.c \ gstomxaudiosink.c \ @@ -53,6 +54,7 @@ noinst_HEADERS = \ gstomxmpeg4videoenc.h \ gstomxh264enc.h \ gstomxh263enc.h \ + gstomxaacdec.h \ gstomxmp3dec.h \ gstomxaacenc.h \ gstomxaudiosink.h \ diff --git a/omx/gstomx.c b/omx/gstomx.c index d611de3..9a77e5b 100644 --- a/omx/gstomx.c +++ b/omx/gstomx.c @@ -39,6 +39,7 @@ #include "gstomxmpeg4videoenc.h" #include "gstomxh264enc.h" #include "gstomxh263enc.h" +#include "gstomxaacdec.h" #include "gstomxmp3dec.h" #include "gstomxaacenc.h" #include "gstomxanalogaudiosink.h" @@ -2246,7 +2247,7 @@ static const GGetTypeFunction types[] = { gst_omx_wmv_dec_get_type, gst_omx_mpeg4_video_enc_get_type, gst_omx_h264_enc_get_type, gst_omx_h263_enc_get_type, gst_omx_aac_enc_get_type, gst_omx_mjpeg_dec_get_type, - gst_omx_mp3_dec_get_type + gst_omx_aac_dec_get_type, gst_omx_mp3_dec_get_type #ifdef HAVE_VP8 , gst_omx_vp8_dec_get_type #endif diff --git a/omx/gstomxaacdec.c b/omx/gstomxaacdec.c new file mode 100644 index 0000000..2422275 --- /dev/null +++ b/omx/gstomxaacdec.c @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstomxaacdec.h" + +GST_DEBUG_CATEGORY_STATIC (gst_omx_aac_dec_debug_category); +#define GST_CAT_DEFAULT gst_omx_aac_dec_debug_category + +/* prototypes */ +static gboolean gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, + GstOMXPort * port, GstCaps * caps); +static gboolean gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, + GstOMXPort * port, GstCaps * caps); +static gint gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec, + GstOMXPort * port); + +/* class initialization */ + +#define DEBUG_INIT \ + GST_DEBUG_CATEGORY_INIT (gst_omx_aac_dec_debug_category, "omxaacdec", 0, \ + "debug category for gst-omx aac audio decoder"); + +G_DEFINE_TYPE_WITH_CODE (GstOMXAACDec, gst_omx_aac_dec, + GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT); + +static void +gst_omx_aac_dec_class_init (GstOMXAACDecClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass); + + audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_aac_dec_set_format); + audiodec_class->is_format_change = + GST_DEBUG_FUNCPTR (gst_omx_aac_dec_is_format_change); + audiodec_class->get_samples_per_frame = + GST_DEBUG_FUNCPTR (gst_omx_aac_dec_get_samples_per_frame); + + audiodec_class->cdata.default_sink_template_caps = "audio/mpeg, " + "mpegversion=(int){2, 4}, " + "stream-format=(string) { raw, adts, adif, loas }, " + "rate=(int)[8000,48000], " + "channels=(int)[1,9], " "framed=(boolean) true"; + + gst_element_class_set_static_metadata (element_class, + "OpenMAX AAC Audio Decoder", + "Codec/Decoder/Audio", + "Decode AAC audio streams", + "Sebastian Dröge "); + + gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.aac"); +} + +static void +gst_omx_aac_dec_init (GstOMXAACDec * self) +{ + /* FIXME: Other values exist too! */ + self->spf = 1024; +} + +static gboolean +gst_omx_aac_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port, + GstCaps * caps) +{ + GstOMXAACDec *self = GST_OMX_AAC_DEC (dec); + OMX_PARAM_PORTDEFINITIONTYPE port_def; + OMX_AUDIO_PARAM_AACPROFILETYPE aac_param; + OMX_ERRORTYPE err; + GstStructure *s; + gint rate, channels, mpegversion; + const gchar *stream_format; + + gst_omx_port_get_port_definition (port, &port_def); + port_def.format.audio.eEncoding = OMX_AUDIO_CodingAAC; + err = gst_omx_port_update_port_definition (port, &port_def); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (self, + "Failed to set AAC format on component: %s (0x%08x)", + gst_omx_error_to_string (err), err); + return FALSE; + } + + GST_OMX_INIT_STRUCT (&aac_param); + aac_param.nPortIndex = port->index; + + err = + gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac, + &aac_param); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (self, + "Failed to get AAC parameters from component: %s (0x%08x)", + gst_omx_error_to_string (err), err); + return FALSE; + } + + s = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (s, "mpegversion", &mpegversion) || + !gst_structure_get_int (s, "rate", &rate) || + !gst_structure_get_int (s, "channels", &channels)) { + GST_ERROR_OBJECT (self, "Incomplete caps"); + return FALSE; + } + + stream_format = gst_structure_get_string (s, "stream-format"); + if (!stream_format) { + GST_ERROR_OBJECT (self, "Incomplete caps"); + return FALSE; + } + + aac_param.nChannels = channels; + aac_param.nSampleRate = rate; + aac_param.nBitRate = 0; /* unknown */ + aac_param.nAudioBandWidth = 0; /* decoder decision */ + aac_param.eChannelMode = 0; /* FIXME */ + if (mpegversion == 2) + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP2ADTS; + else if (strcmp (stream_format, "adts") == 0) + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS; + else if (strcmp (stream_format, "loas") == 0) + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LOAS; + else if (strcmp (stream_format, "adif") == 0) + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF; + else if (strcmp (stream_format, "raw") == 0) + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW; + else + aac_param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatRAW; + + err = + gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAac, + &aac_param); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (self, "Error setting AAC parameters: %s (0x%08x)", + gst_omx_error_to_string (err), err); + return FALSE; + } + + return TRUE; +} + +static gboolean +gst_omx_aac_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port, + GstCaps * caps) +{ + GstOMXAACDec *self = GST_OMX_AAC_DEC (dec); + OMX_AUDIO_PARAM_AACPROFILETYPE aac_param; + OMX_ERRORTYPE err; + GstStructure *s; + gint rate, channels, mpegversion; + const gchar *stream_format; + + GST_OMX_INIT_STRUCT (&aac_param); + aac_param.nPortIndex = port->index; + + err = + gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAac, + &aac_param); + if (err != OMX_ErrorNone) { + GST_ERROR_OBJECT (self, + "Failed to get AAC parameters from component: %s (0x%08x)", + gst_omx_error_to_string (err), err); + return FALSE; + } + + s = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (s, "mpegversion", &mpegversion) || + !gst_structure_get_int (s, "rate", &rate) || + !gst_structure_get_int (s, "channels", &channels)) { + GST_ERROR_OBJECT (self, "Incomplete caps"); + return FALSE; + } + + stream_format = gst_structure_get_string (s, "stream-format"); + if (!stream_format) { + GST_ERROR_OBJECT (self, "Incomplete caps"); + return FALSE; + } + + if (aac_param.nChannels != channels) + return TRUE; + + if (aac_param.nSampleRate != rate) + return TRUE; + + if (mpegversion == 2 + && aac_param.eAACStreamFormat != OMX_AUDIO_AACStreamFormatMP2ADTS) + return TRUE; + if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4ADTS && + strcmp (stream_format, "adts") != 0) + return TRUE; + if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatMP4LOAS && + strcmp (stream_format, "loas") != 0) + return TRUE; + if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatADIF && + strcmp (stream_format, "adif") != 0) + return TRUE; + if (aac_param.eAACStreamFormat == OMX_AUDIO_AACStreamFormatRAW && + strcmp (stream_format, "raw") != 0) + return TRUE; + + return FALSE; +} + +static gint +gst_omx_aac_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port) +{ + return GST_OMX_AAC_DEC (dec)->spf; +} diff --git a/omx/gstomxaacdec.h b/omx/gstomxaacdec.h new file mode 100644 index 0000000..891589b --- /dev/null +++ b/omx/gstomxaacdec.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014, Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GST_OMX_AAC_DEC_H__ +#define __GST_OMX_AAC_DEC_H__ + +#include +#include "gstomxaudiodec.h" + +G_BEGIN_DECLS + +#define GST_TYPE_OMX_AAC_DEC \ + (gst_omx_aac_dec_get_type()) +#define GST_OMX_AAC_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDec)) +#define GST_OMX_AAC_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass)) +#define GST_OMX_AAC_DEC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_OMX_AAC_DEC,GstOMXAACDecClass)) +#define GST_IS_OMX_AAC_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OMX_AAC_DEC)) +#define GST_IS_OMX_AAC_DEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OMX_AAC_DEC)) + +typedef struct _GstOMXAACDec GstOMXAACDec; +typedef struct _GstOMXAACDecClass GstOMXAACDecClass; + +struct _GstOMXAACDec +{ + GstOMXAudioDec parent; + gint spf; +}; + +struct _GstOMXAACDecClass +{ + GstOMXAudioDecClass parent_class; +}; + +GType gst_omx_aac_dec_get_type (void); + +G_END_DECLS + +#endif /* __GST_OMX_AAC_DEC_H__ */ + diff --git a/omx/gstomxmp3dec.c b/omx/gstomxmp3dec.c index f52a8f5..3f84913 100644 --- a/omx/gstomxmp3dec.c +++ b/omx/gstomxmp3dec.c @@ -40,7 +40,7 @@ static gint gst_omx_mp3_dec_get_samples_per_frame (GstOMXAudioDec * dec, #define DEBUG_INIT \ GST_DEBUG_CATEGORY_INIT (gst_omx_mp3_dec_debug_category, "omxmp3dec", 0, \ - "debug category for gst-omx audio decoder base class"); + "debug category for gst-omx mp3 audio decoder"); G_DEFINE_TYPE_WITH_CODE (GstOMXMP3Dec, gst_omx_mp3_dec, GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);