omxvideodec: support interlace-mode=interleaved input
[platform/upstream/gstreamer.git] / omx / gstomxamrdec.c
1 /*
2  * Copyright (C) 2014, Sebastian Dröge <sebastian@centricular.com>
3  * Copyright (C) 2014, LG Electronics, Inc. <jun.ji@lge.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation
8  * version 2.1 of the License.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <gst/gst.h>
26
27 #include "gstomxamrdec.h"
28
29 GST_DEBUG_CATEGORY_STATIC (gst_omx_amr_dec_debug_category);
30 #define GST_CAT_DEFAULT gst_omx_amr_dec_debug_category
31
32 /* prototypes */
33 static gboolean gst_omx_amr_dec_set_format (GstOMXAudioDec * dec,
34     GstOMXPort * port, GstCaps * caps);
35 static gboolean gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec,
36     GstOMXPort * port, GstCaps * caps);
37 static gint gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec,
38     GstOMXPort * port);
39 static gboolean gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
40     GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS]);
41
42 /* class initialization */
43
44 #define DEBUG_INIT \
45   GST_DEBUG_CATEGORY_INIT (gst_omx_amr_dec_debug_category, "omxamrdec", 0, \
46       "debug category for gst-omx amr audio decoder");
47
48 G_DEFINE_TYPE_WITH_CODE (GstOMXAMRDec, gst_omx_amr_dec,
49     GST_TYPE_OMX_AUDIO_DEC, DEBUG_INIT);
50
51 static void
52 gst_omx_amr_dec_class_init (GstOMXAMRDecClass * klass)
53 {
54   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
55   GstOMXAudioDecClass *audiodec_class = GST_OMX_AUDIO_DEC_CLASS (klass);
56
57   audiodec_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_amr_dec_set_format);
58   audiodec_class->is_format_change =
59       GST_DEBUG_FUNCPTR (gst_omx_amr_dec_is_format_change);
60   audiodec_class->get_samples_per_frame =
61       GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_samples_per_frame);
62   audiodec_class->get_channel_positions =
63       GST_DEBUG_FUNCPTR (gst_omx_amr_dec_get_channel_positions);
64
65   audiodec_class->cdata.default_sink_template_caps =
66       "audio/AMR, rate=(int)8000, channels=(int)1; "
67       "audio/AMR-WB, rate=(int)16000, channels=(int)1";
68
69   gst_element_class_set_static_metadata (element_class,
70       "OpenMAX AMR Audio Decoder",
71       "Codec/Decoder/Audio/Hardware",
72       "Decode AMR audio streams",
73       "Sebastian Dröge <sebastian@centricular.com>");
74
75   gst_omx_set_default_role (&audiodec_class->cdata, "audio_decoder.amrnb");
76 }
77
78 static void
79 gst_omx_amr_dec_init (GstOMXAMRDec * self)
80 {
81   self->spf = -1;
82 }
83
84 static gboolean
85 gst_omx_amr_dec_set_format (GstOMXAudioDec * dec, GstOMXPort * port,
86     GstCaps * caps)
87 {
88   GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
89   OMX_PARAM_PORTDEFINITIONTYPE port_def;
90   OMX_AUDIO_PARAM_AMRTYPE amr_param;
91   OMX_ERRORTYPE err;
92   GstStructure *s;
93   gint rate, channels;
94
95   gst_omx_port_get_port_definition (port, &port_def);
96   port_def.format.audio.eEncoding = OMX_AUDIO_CodingAMR;        /* not tested for AMRWB */
97   err = gst_omx_port_update_port_definition (port, &port_def);
98   if (err != OMX_ErrorNone) {
99     GST_ERROR_OBJECT (self,
100         "Failed to set AMR format on component: %s (0x%08x)",
101         gst_omx_error_to_string (err), err);
102     return FALSE;
103   }
104
105   GST_OMX_INIT_STRUCT (&amr_param);
106   amr_param.nPortIndex = port->index;
107
108   err =
109       gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
110       &amr_param);
111   if (err != OMX_ErrorNone) {
112     GST_ERROR_OBJECT (self,
113         "Failed to get AMR parameters from component: %s (0x%08x)",
114         gst_omx_error_to_string (err), err);
115     return FALSE;
116   }
117
118   s = gst_caps_get_structure (caps, 0);
119
120   if (!gst_structure_get_int (s, "rate", &rate) ||
121       !gst_structure_get_int (s, "channels", &channels)) {
122     GST_ERROR_OBJECT (self, "Incomplete caps");
123     return FALSE;
124   }
125
126   self->rate = rate;
127
128   if (rate == 8000)
129     self->spf = 160;            /* (8000/50) */
130   else if (rate == 16000)
131     self->spf = 320;            /* (16000/50) */
132
133   amr_param.nChannels = channels;
134   amr_param.eAMRBandMode = 0;   /*FIXME: It may require a specific value */
135   amr_param.eAMRDTXMode = 0;
136   amr_param.eAMRFrameFormat = 0;
137
138   err =
139       gst_omx_component_set_parameter (dec->dec, OMX_IndexParamAudioAmr,
140       &amr_param);
141   if (err != OMX_ErrorNone) {
142     GST_ERROR_OBJECT (self, "Error setting AMR parameters: %s (0x%08x)",
143         gst_omx_error_to_string (err), err);
144     return FALSE;
145   }
146
147   return TRUE;
148 }
149
150 static gboolean
151 gst_omx_amr_dec_is_format_change (GstOMXAudioDec * dec, GstOMXPort * port,
152     GstCaps * caps)
153 {
154   GstOMXAMRDec *self = GST_OMX_AMR_DEC (dec);
155   OMX_AUDIO_PARAM_AMRTYPE amr_param;
156   OMX_ERRORTYPE err;
157   GstStructure *s;
158   gint rate, channels;
159
160   GST_OMX_INIT_STRUCT (&amr_param);
161   amr_param.nPortIndex = port->index;
162
163   err =
164       gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioAmr,
165       &amr_param);
166   if (err != OMX_ErrorNone) {
167     GST_ERROR_OBJECT (self,
168         "Failed to get AMR parameters from component: %s (0x%08x)",
169         gst_omx_error_to_string (err), err);
170     return FALSE;
171   }
172
173   s = gst_caps_get_structure (caps, 0);
174
175   if (!gst_structure_get_int (s, "rate", &rate) ||
176       !gst_structure_get_int (s, "channels", &channels)) {
177     GST_ERROR_OBJECT (self, "Incomplete caps");
178     return FALSE;
179   }
180
181   if (self->rate != rate)
182     return TRUE;
183
184   if (amr_param.nChannels != channels)
185     return TRUE;
186
187   return FALSE;
188 }
189
190 static gint
191 gst_omx_amr_dec_get_samples_per_frame (GstOMXAudioDec * dec, GstOMXPort * port)
192 {
193   return GST_OMX_AMR_DEC (dec)->spf;
194 }
195
196 static gboolean
197 gst_omx_amr_dec_get_channel_positions (GstOMXAudioDec * dec,
198     GstOMXPort * port, GstAudioChannelPosition position[OMX_AUDIO_MAXCHANNELS])
199 {
200   OMX_AUDIO_PARAM_PCMMODETYPE pcm_param;
201   OMX_ERRORTYPE err;
202
203   GST_OMX_INIT_STRUCT (&pcm_param);
204   pcm_param.nPortIndex = port->index;
205   err =
206       gst_omx_component_get_parameter (dec->dec, OMX_IndexParamAudioPcm,
207       &pcm_param);
208   if (err != OMX_ErrorNone) {
209     GST_ERROR_OBJECT (dec, "Failed to get PCM parameters: %s (0x%08x)",
210         gst_omx_error_to_string (err), err);
211     return FALSE;
212   }
213
214
215   g_return_val_if_fail (pcm_param.nChannels == 1, FALSE);       /* AMR supports only mono */
216
217   position[0] = GST_AUDIO_CHANNEL_POSITION_MONO;
218
219   return TRUE;
220 }