omxvideodec: support interlace-mode=interleaved input
[platform/upstream/gstreamer.git] / omx / gstomxmp3enc.c
1 /*
2  * Copyright (C) 2017
3  *   Author: Julien Isorce <julien.isorce@gmail.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 "gstomxmp3enc.h"
28
29 GST_DEBUG_CATEGORY_STATIC (gst_omx_mp3_enc_debug_category);
30 #define GST_CAT_DEFAULT gst_omx_mp3_enc_debug_category
31
32 /* prototypes */
33 static void gst_omx_mp3_enc_set_property (GObject * object, guint prop_id,
34     const GValue * value, GParamSpec * pspec);
35 static void gst_omx_mp3_enc_get_property (GObject * object, guint prop_id,
36     GValue * value, GParamSpec * pspec);
37 static gboolean gst_omx_mp3_enc_set_format (GstOMXAudioEnc * enc,
38     GstOMXPort * port, GstAudioInfo * info);
39 static GstCaps *gst_omx_mp3_enc_get_caps (GstOMXAudioEnc * enc,
40     GstOMXPort * port, GstAudioInfo * info);
41 static guint gst_omx_mp3_enc_get_num_samples (GstOMXAudioEnc * enc,
42     GstOMXPort * port, GstAudioInfo * info, GstOMXBuffer * buf);
43
44 enum
45 {
46   PROP_0,
47   PROP_BITRATE
48 };
49
50 #define DEFAULT_BITRATE (128)
51
52 /* class initialization */
53
54 #define DEBUG_INIT \
55   GST_DEBUG_CATEGORY_INIT (gst_omx_mp3_enc_debug_category, "omxmp3enc", 0, \
56       "debug category for gst-omx audio encoder base class");
57
58 G_DEFINE_TYPE_WITH_CODE (GstOMXMP3Enc, gst_omx_mp3_enc,
59     GST_TYPE_OMX_AUDIO_ENC, DEBUG_INIT);
60
61
62 static void
63 gst_omx_mp3_enc_class_init (GstOMXMP3EncClass * klass)
64 {
65   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
66   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
67   GstOMXAudioEncClass *audioenc_class = GST_OMX_AUDIO_ENC_CLASS (klass);
68
69   gobject_class->set_property = gst_omx_mp3_enc_set_property;
70   gobject_class->get_property = gst_omx_mp3_enc_get_property;
71
72   g_object_class_install_property (gobject_class, PROP_BITRATE,
73       g_param_spec_uint ("bitrate", "Bitrate (kb/s)",
74           "Bitrate in kbit/sec",
75           0, G_MAXUINT, DEFAULT_BITRATE,
76           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
77           GST_PARAM_MUTABLE_READY));
78
79   audioenc_class->set_format = GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_set_format);
80   audioenc_class->get_caps = GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_get_caps);
81   audioenc_class->get_num_samples =
82       GST_DEBUG_FUNCPTR (gst_omx_mp3_enc_get_num_samples);
83
84   audioenc_class->cdata.default_src_template_caps = "audio/mpeg, "
85       "mpegversion=(int)1, "
86       "layer=(int)3, "
87       "mpegaudioversion=(int)[1,3], "
88       "rate=(int)[8000,48000], " "channels=(int)[1,2]";
89
90   gst_element_class_set_static_metadata (element_class,
91       "OpenMAX MP3 Audio Encoder",
92       "Codec/Encoder/Audio/Hardware",
93       "Encode AAC audio streams", "Julien Isorce <julien.isorce@gmail.com>");
94
95   gst_omx_set_default_role (&audioenc_class->cdata, "audio_encoder.mp3");
96 }
97
98 static void
99 gst_omx_mp3_enc_init (GstOMXMP3Enc * self)
100 {
101   self->mpegaudioversion = 1;
102   self->bitrate = DEFAULT_BITRATE;
103 }
104
105 static void
106 gst_omx_mp3_enc_set_property (GObject * object, guint prop_id,
107     const GValue * value, GParamSpec * pspec)
108 {
109   GstOMXMP3Enc *self = GST_OMX_MP3_ENC (object);
110
111   switch (prop_id) {
112     case PROP_BITRATE:
113       self->bitrate = g_value_get_uint (value);
114       break;
115     default:
116       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
117       break;
118   }
119 }
120
121 static void
122 gst_omx_mp3_enc_get_property (GObject * object, guint prop_id, GValue * value,
123     GParamSpec * pspec)
124 {
125   GstOMXMP3Enc *self = GST_OMX_MP3_ENC (object);
126
127   switch (prop_id) {
128     case PROP_BITRATE:
129       g_value_set_uint (value, self->bitrate);
130       break;
131     default:
132       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
133       break;
134   }
135 }
136
137 static gboolean
138 gst_omx_mp3_enc_set_format (GstOMXAudioEnc * enc, GstOMXPort * port,
139     GstAudioInfo * info)
140 {
141   GstOMXMP3Enc *self = GST_OMX_MP3_ENC (enc);
142   OMX_AUDIO_PARAM_MP3TYPE mp3_param;
143   GstCaps *peercaps;
144   OMX_ERRORTYPE err;
145
146   GST_OMX_INIT_STRUCT (&mp3_param);
147   mp3_param.nPortIndex = enc->enc_out_port->index;
148
149   err =
150       gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioMp3,
151       &mp3_param);
152   if (err != OMX_ErrorNone) {
153     GST_ERROR_OBJECT (self,
154         "Failed to get MP# parameters from component: %s (0x%08x)",
155         gst_omx_error_to_string (err), err);
156     return FALSE;
157   }
158
159   peercaps = gst_pad_peer_query_caps (GST_AUDIO_ENCODER_SRC_PAD (self),
160       gst_pad_get_pad_template_caps (GST_AUDIO_ENCODER_SRC_PAD (self)));
161   if (peercaps) {
162     GstStructure *s;
163     gint mpegaudioversion = 0;
164
165     if (gst_caps_is_empty (peercaps)) {
166       gst_caps_unref (peercaps);
167       GST_ERROR_OBJECT (self, "Empty caps");
168       return FALSE;
169     }
170
171     s = gst_caps_get_structure (peercaps, 0);
172
173     if (gst_structure_get_int (s, "mpegaudioversion", &mpegaudioversion)) {
174       switch (mpegaudioversion) {
175         case 1:
176           mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP1Layer3;
177           break;
178         case 2:
179           mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2Layer3;
180           break;
181         case 3:
182           mp3_param.eFormat = OMX_AUDIO_MP3StreamFormatMP2_5Layer3;
183           break;
184         default:
185           GST_ERROR_OBJECT (self, "Unsupported mpegaudioversion '%d'",
186               mpegaudioversion);
187           gst_caps_unref (peercaps);
188           return FALSE;
189       }
190       self->mpegaudioversion = mpegaudioversion;
191     }
192
193     gst_caps_unref (peercaps);
194
195     mp3_param.nSampleRate = info->rate;
196     mp3_param.nChannels = info->channels;
197
198     mp3_param.eChannelMode =
199         info->channels ==
200         1 ? OMX_AUDIO_ChannelModeMono : OMX_AUDIO_ChannelModeStereo;
201   }
202
203   mp3_param.nBitRate = self->bitrate;
204
205   err =
206       gst_omx_component_set_parameter (enc->enc, OMX_IndexParamAudioMp3,
207       &mp3_param);
208   if (err != OMX_ErrorNone) {
209     GST_ERROR_OBJECT (self, "Error setting MP3 parameters: %s (0x%08x)",
210         gst_omx_error_to_string (err), err);
211     return FALSE;
212   }
213
214   return TRUE;
215 }
216
217 static GstCaps *
218 gst_omx_mp3_enc_get_caps (GstOMXAudioEnc * enc, GstOMXPort * port,
219     GstAudioInfo * info)
220 {
221   GstCaps *caps;
222   OMX_ERRORTYPE err;
223   OMX_AUDIO_PARAM_MP3TYPE mp3_param;
224   gint mpegaudioversion = 0;
225
226   GST_OMX_INIT_STRUCT (&mp3_param);
227   mp3_param.nPortIndex = enc->enc_out_port->index;
228
229   err =
230       gst_omx_component_get_parameter (enc->enc, OMX_IndexParamAudioMp3,
231       &mp3_param);
232   if (err != OMX_ErrorNone) {
233     GST_ERROR_OBJECT (enc,
234         "Failed to get MP3 parameters from component: %s (0x%08x)",
235         gst_omx_error_to_string (err), err);
236     return NULL;
237   }
238
239   switch (mp3_param.eFormat) {
240     case OMX_AUDIO_MP3StreamFormatMP1Layer3:
241       mpegaudioversion = 1;
242       break;
243     case OMX_AUDIO_MP3StreamFormatMP2Layer3:
244       mpegaudioversion = 2;
245       break;
246     case OMX_AUDIO_MP3StreamFormatMP2_5Layer3:
247       mpegaudioversion = 3;
248       break;
249     default:
250       GST_ERROR_OBJECT (enc, "Unsupported mpegaudioversion %d",
251           mp3_param.eFormat);
252       break;
253   }
254
255   caps =
256       gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, "layer",
257       G_TYPE_INT, 3, NULL);
258
259   if (mpegaudioversion != 0)
260     gst_caps_set_simple (caps, "mpegaudioversion", G_TYPE_INT, mpegaudioversion,
261         NULL);
262   if (mp3_param.nChannels != 0)
263     gst_caps_set_simple (caps, "channels", G_TYPE_INT, mp3_param.nChannels,
264         NULL);
265   if (mp3_param.nSampleRate != 0)
266     gst_caps_set_simple (caps, "rate", G_TYPE_INT, mp3_param.nSampleRate, NULL);
267
268   return caps;
269
270 }
271
272 static guint
273 gst_omx_mp3_enc_get_num_samples (GstOMXAudioEnc * enc, GstOMXPort * port,
274     GstAudioInfo * info, GstOMXBuffer * buf)
275 {
276   GstOMXMP3Enc *self = GST_OMX_MP3_ENC (enc);
277   return (self->mpegaudioversion == 1) ? 1152 : 576;
278 }