2 * Copyright (C) 2007-2009 Nokia Corporation.
4 * Author: Felipe Contreras <felipe.contreras@nokia.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation
9 * version 2.1 of the License.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 #include "gstomx_mp3dec_alp.h"
25 #define OMX_MP3DEC_OUTBUF_ALP
26 #define OMX_MP3DEC_INBUF_ALP
27 #ifdef OMX_MP3DEC_INBUF_ALP
28 #define SRP_INPUT_SIZE 0
30 #define SRP_INPUT_SIZE 32768
33 #define SRP_MP3_FRAME_SIZE 1152
34 #define SRP_MP3_SAMPLE_SIZE 2
36 GSTOMX_BOILERPLATE (GstOmxMp3DecAlp, gst_omx_mp3dec_alp, GstOmxBaseAudioDec,
37 GST_OMX_BASE_AUDIODEC_TYPE);
39 static void instance_init (GstElement * element);
40 static void instance_deinit (GstElement * element);
43 #ifdef SRP_ENABLE_DUMP
44 static void init_dump_config(GstOmxMp3DecAlp *self)
46 dictionary * dict = NULL;
48 dict = iniparser_load (SRP_DUMP_INI_DEFAULT_PATH);
50 GST_INFO ("%s load failed. Use temporary file", SRP_DUMP_INI_DEFAULT_PATH);
51 dict = iniparser_load (SRP_DUMP_INI_TEMP_PATH);
53 GST_WARNING ("%s load failed", SRP_DUMP_INI_TEMP_PATH);
58 if (iniparser_getboolean (dict, "pcm_dump:codec", 0) == TRUE) {
59 char *suffix, *dump_path;
60 GDateTime *time = g_date_time_new_now_local ();
62 suffix = g_date_time_format (time, "%Y%m%d_%H%M%S.pcm");
63 dump_path = g_strjoin (NULL, SRP_DUMP_INPUT_PATH_PREFIX, suffix, NULL);
64 self->pcmFd = fopen (dump_path, "w+");
67 g_date_time_unref (time);
69 GST_ERROR ("Can not create debug dump file");
73 iniparser_freedict (dict);
79 process_output_buf(GstOmxBaseFilter * omx_base, GstBuffer **buf, OMX_BUFFERHEADERTYPE *omx_buffer)
81 GstFlowReturn ret = GST_FLOW_OK;
82 GstOmxMp3DecAlp *self;
84 GstStructure *structure;
88 guint offset = 0, output_size;
89 GstClockTime timestamp = 0, duration = 0;
91 self = GST_OMX_MP3DEC_ALP (omx_base);
92 caps = gst_pad_get_negotiated_caps (omx_base->srcpad);
93 caps = gst_caps_make_writable (caps);
94 structure = gst_caps_get_structure (caps, 0);
95 gst_structure_get_int (structure, "rate", &samplerate);
96 gst_structure_get_int (structure, "channels", &channels);
97 output_size = SRP_MP3_FRAME_SIZE * SRP_MP3_SAMPLE_SIZE * channels;
98 timestamp = GST_BUFFER_TIMESTAMP (*buf);
99 duration = GST_SECOND * SRP_MP3_FRAME_SIZE / samplerate;
100 gst_caps_unref (caps);
102 /* merge remained data */
103 if (self->remain_buffer) {
104 if (GST_BUFFER_SIZE(self->remain_buffer) +GST_BUFFER_SIZE(*buf) < output_size) {
105 GST_DEBUG_OBJECT (self, "remain_buf (%d) + current_buf (%d) < output_size (%d). change output_size.",
106 GST_BUFFER_SIZE(self->remain_buffer), GST_BUFFER_SIZE(*buf), output_size);
107 output_size = GST_BUFFER_SIZE(self->remain_buffer) +GST_BUFFER_SIZE(*buf);
109 push_buf = gst_buffer_span (self->remain_buffer, 0, *buf, output_size);
110 gst_buffer_copy_metadata (push_buf, *buf,
111 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_CAPS);
112 GST_BUFFER_DURATION (push_buf) = duration;
114 GST_LOG_OBJECT (self, "OUT_BUFFER: remained = %lu size = %lu",
115 GST_BUFFER_SIZE (self->remain_buffer), GST_BUFFER_SIZE (push_buf));
117 offset += output_size - GST_BUFFER_SIZE (self->remain_buffer);
118 gst_buffer_unref (self->remain_buffer);
119 self->remain_buffer = NULL;
120 ret = gst_pad_push (omx_base->srcpad, push_buf);
121 GST_LOG_OBJECT (self, "gst_pad_push end. ret = %d", ret);
124 /* separate data by frame size */
125 if (GST_BUFFER_SIZE (*buf) - offset >= output_size) {
126 push_buf = gst_buffer_create_sub (*buf, offset, output_size);
127 gst_buffer_copy_metadata (push_buf, *buf,
128 GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_CAPS);
129 GST_BUFFER_TIMESTAMP (push_buf) = timestamp
130 + (GST_SECOND * offset / (SRP_MP3_SAMPLE_SIZE * channels * samplerate));
131 GST_BUFFER_DURATION (push_buf) = duration;
133 GST_LOG_OBJECT (self, "OUT_BUFFER: offset = %lu size = %lu",
134 offset, GST_BUFFER_SIZE (push_buf));
136 offset += output_size;
137 ret = gst_pad_push (omx_base->srcpad, push_buf);
138 GST_LOG_OBJECT (self, "gst_pad_push end. ret = %d", ret);
140 /* store remained data */
141 if (GST_BUFFER_SIZE (*buf) - offset > 0) {
142 self->remain_buffer = gst_buffer_create_sub (*buf, offset,
143 GST_BUFFER_SIZE (*buf) - offset);
144 GST_BUFFER_TIMESTAMP (self->remain_buffer) = timestamp
145 + (GST_SECOND * offset / (SRP_MP3_SAMPLE_SIZE * channels * samplerate));
151 #ifdef SRP_ENABLE_DUMP
153 fwrite (GST_BUFFER_DATA (*buf), 1, GST_BUFFER_SIZE (*buf), self->pcmFd);
157 return GSTOMX_RETURN_SKIP;
162 pad_event (GstPad * pad, GstEvent * event)
164 GstOmxBaseFilter *omx_base;
165 GstOmxMp3DecAlp *self;
168 omx_base = GST_OMX_BASE_FILTER (GST_OBJECT_PARENT (pad));
169 self = GST_OMX_MP3DEC_ALP (omx_base);
171 GST_LOG_OBJECT (self, "begin");
173 GST_INFO_OBJECT (self, "event: %s", GST_EVENT_TYPE_NAME (event));
175 switch (GST_EVENT_TYPE (event)) {
176 case GST_EVENT_FLUSH_STOP:
177 if (self->remain_buffer) {
178 gst_buffer_unref (self->remain_buffer);
179 self->remain_buffer = NULL;
190 instance_deinit (GstElement * element)
192 GstOmxMp3DecAlp *self;
193 self = GST_OMX_MP3DEC_ALP (element);
195 GST_WARNING_OBJECT (self, "mp3 alp deinit");
197 if (self->remain_buffer) {
198 gst_buffer_unref (self->remain_buffer);
199 self->remain_buffer = NULL;
202 #ifdef SRP_ENABLE_DUMP
204 fclose (self->pcmFd);
209 GST_OMX_BASE_FILTER_CLASS (parent_class)->instance_deinit(element);
213 finalize (GObject * obj)
215 G_OBJECT_CLASS (parent_class)->finalize (obj);
219 type_base_init (gpointer g_class)
221 GstElementClass *element_class;
223 element_class = GST_ELEMENT_CLASS (g_class);
225 gst_element_class_set_details_simple (element_class,
226 "OpenMAX IL ALP MP3 audio decoder",
227 "Codec/Decoder/Audio/ALP",
228 "Decodes audio in MP3 format with OpenMAX IL", "Felipe Contreras");
230 gst_element_class_add_pad_template (element_class,
231 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
232 gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "sink")));
234 gst_element_class_add_pad_template (element_class,
235 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
236 gstomx_template_caps (G_TYPE_FROM_CLASS (g_class), "src")));
240 type_class_init (gpointer g_class, gpointer class_data)
242 GObjectClass *gobject_class;
243 GstOmxBaseFilterClass *basefilter_class;
245 gobject_class = G_OBJECT_CLASS (g_class);
246 gobject_class->finalize = finalize;
248 basefilter_class = GST_OMX_BASE_FILTER_CLASS (g_class);
249 basefilter_class->instance_init = instance_init;
250 basefilter_class->instance_deinit = instance_deinit;
254 instance_private_value_init(GstElement * element)
256 GstOmxBaseFilter *base_filter;
257 #ifdef SRP_ENABLE_DUMP
258 GstOmxMp3DecAlp *self;
261 base_filter = GST_OMX_BASE_FILTER (element);
262 #ifdef SRP_ENABLE_DUMP
263 self = GST_OMX_MP3DEC_ALP (element);
266 /* ALP audio use adapter */
267 base_filter->adapter_size = SRP_INPUT_SIZE;
269 GST_INFO_OBJECT (base_filter, "mp3dec ALP. adapter_size=%d", base_filter ->adapter_size);
271 self->remain_buffer = NULL;
272 #ifdef SRP_ENABLE_DUMP
273 init_dump_config (self);
278 instance_init (GstElement * element)
280 GST_OMX_BASE_FILTER_CLASS (parent_class)->instance_init(element);
282 instance_private_value_init(element);
286 type_instance_init (GTypeInstance * instance, gpointer g_class)
288 GstOmxBaseFilter *base_filter;
290 base_filter = GST_OMX_BASE_FILTER (instance);
291 base_filter->pad_event = pad_event;
293 instance_private_value_init(GST_ELEMENT(instance));