Fix to unify add track info function for audio only case
[platform/core/api/mediademuxer.git] / src / port_gst / mediademuxer_port_gst.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file mediademuxer_port_gst.c
19  * @brief Handling for GStreamer Port, defined function and there implementation
20  */
21
22 #include <mm_debug.h>
23 #include <unistd.h>
24 #include <mediademuxer_error.h>
25 #include <mediademuxer_private.h>
26 #include <mediademuxer_port.h>
27 #include <mediademuxer_port_gst.h>
28 #include <media_packet_internal.h>
29
30 static int gst_demuxer_init(MMHandleType *pHandle);
31 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri);
32 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count);
33 static int gst_demuxer_set_track(MMHandleType pHandle, int track);
34 static int gst_demuxer_start(MMHandleType pHandle);
35 static int gst_demuxer_read_sample(MMHandleType pHandle,
36                         media_packet_h *outbuf, int track_indx);
37 static int gst_demuxer_get_track_info(MMHandleType pHandle,
38                         media_format_h *format, int index);
39 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1);
40 static int gst_demuxer_unset_track(MMHandleType pHandle, int track);
41 static int gst_demuxer_stop(MMHandleType pHandle);
42 static int gst_demuxer_unprepare(MMHandleType pHandle);
43 static int gst_demuxer_destroy(MMHandleType pHandle);
44 static int gst_set_error_cb(MMHandleType pHandle,
45                         gst_error_cb callback, void *user_data);
46 static int gst_set_eos_cb(MMHandleType pHandle,
47                         gst_eos_cb callback, void *user_data);
48 static int __gst_eos_callback(int track_num, void *user_data);
49
50 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code);
51 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code);
52 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code);
53 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message);
54 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error);
55
56 /* Media Demuxer API common */
57 static media_port_demuxer_ops def_demux_ops = {
58         .n_size = 0,
59         .init = gst_demuxer_init,
60         .prepare = gst_demuxer_prepare,
61         .get_track_count = gst_demuxer_get_data_count,
62         .set_track = gst_demuxer_set_track,
63         .start = gst_demuxer_start,
64         .get_track_info = gst_demuxer_get_track_info,
65         .read_sample = gst_demuxer_read_sample,
66         .seek = gst_demuxer_seek,
67         .unset_track = gst_demuxer_unset_track,
68         .stop = gst_demuxer_stop,
69         .unprepare = gst_demuxer_unprepare,
70         .destroy = gst_demuxer_destroy,
71         .set_error_cb = gst_set_error_cb,
72         .set_eos_cb = gst_set_eos_cb,
73 };
74
75 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code)
76 {
77         gint trans_err = MEDIADEMUXER_ERROR_NONE;
78
79         MEDIADEMUXER_CHECK_NULL(gst_handle);
80
81         switch (code) {
82         case GST_CORE_ERROR_MISSING_PLUGIN:
83                 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
84         case GST_CORE_ERROR_STATE_CHANGE:
85         case GST_CORE_ERROR_SEEK:
86         case GST_CORE_ERROR_NOT_IMPLEMENTED:
87         case GST_CORE_ERROR_FAILED:
88         case GST_CORE_ERROR_TOO_LAZY:
89         case GST_CORE_ERROR_PAD:
90         case GST_CORE_ERROR_THREAD:
91         case GST_CORE_ERROR_NEGOTIATION:
92         case GST_CORE_ERROR_EVENT:
93         case GST_CORE_ERROR_CAPS:
94         case GST_CORE_ERROR_TAG:
95         case GST_CORE_ERROR_CLOCK:
96         case GST_CORE_ERROR_DISABLED:
97         default:
98                 trans_err =  MEDIADEMUXER_ERROR_INVALID_OPERATION;
99                 break;
100         }
101
102         return trans_err;
103 }
104
105 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code)
106 {
107         gint trans_err = MEDIADEMUXER_ERROR_NONE;
108
109         MEDIADEMUXER_CHECK_NULL(gst_handle);
110
111         switch (code) {
112         case GST_LIBRARY_ERROR_FAILED:
113         case GST_LIBRARY_ERROR_TOO_LAZY:
114         case GST_LIBRARY_ERROR_INIT:
115         case GST_LIBRARY_ERROR_SHUTDOWN:
116         case GST_LIBRARY_ERROR_SETTINGS:
117         case GST_LIBRARY_ERROR_ENCODE:
118         default:
119                 trans_err =  MEDIADEMUXER_ERROR_INVALID_OPERATION;
120                 break;
121         }
122
123         return trans_err;
124 }
125
126
127 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code)
128 {
129         gint trans_err = MEDIADEMUXER_ERROR_NONE;
130
131         MEDIADEMUXER_CHECK_NULL(gst_handle);
132
133         switch (code) {
134         case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
135                 trans_err = MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
136                 break;
137         case GST_RESOURCE_ERROR_WRITE:
138         case GST_RESOURCE_ERROR_FAILED:
139         case GST_RESOURCE_ERROR_SEEK:
140         case GST_RESOURCE_ERROR_TOO_LAZY:
141         case GST_RESOURCE_ERROR_BUSY:
142         case GST_RESOURCE_ERROR_OPEN_WRITE:
143         case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
144         case GST_RESOURCE_ERROR_CLOSE:
145         case GST_RESOURCE_ERROR_SYNC:
146         case GST_RESOURCE_ERROR_SETTINGS:
147         default:
148                 trans_err = MEDIADEMUXER_ERROR_RESOURCE_LIMIT;
149                 break;
150         }
151
152         return trans_err;
153 }
154
155 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message)
156 {
157         gint trans_err = MEDIADEMUXER_ERROR_NONE;
158
159         MEDIADEMUXER_CHECK_NULL(gst_handle);
160         MEDIADEMUXER_CHECK_NULL(error);
161         MEDIADEMUXER_CHECK_NULL(message);
162
163         switch (error->code) {
164         case GST_STREAM_ERROR_FAILED:
165         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
166         case GST_STREAM_ERROR_DECODE:
167         case GST_STREAM_ERROR_WRONG_TYPE:
168         case GST_STREAM_ERROR_DECRYPT:
169         case GST_STREAM_ERROR_DECRYPT_NOKEY:
170         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
171                 trans_err = __gst_transform_gsterror(gst_handle, message, error);
172                 break;
173
174         case GST_STREAM_ERROR_NOT_IMPLEMENTED:
175         case GST_STREAM_ERROR_TOO_LAZY:
176         case GST_STREAM_ERROR_ENCODE:
177         case GST_STREAM_ERROR_DEMUX:
178         case GST_STREAM_ERROR_MUX:
179         case GST_STREAM_ERROR_FORMAT:
180         default:
181                 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
182                 break;
183         }
184
185         return trans_err;
186 }
187
188 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error)
189 {
190         gchar *src_element_name = NULL;
191         GstElement *src_element = NULL;
192         GstElementFactory *factory = NULL;
193         const gchar *klass = NULL;
194
195         MEDIADEMUXER_CHECK_NULL(gst_handle);
196
197         src_element = GST_ELEMENT_CAST(message->src);
198         if (!src_element)
199                 goto INTERNAL_ERROR;
200
201         src_element_name = GST_ELEMENT_NAME(src_element);
202         if (!src_element_name)
203                 goto INTERNAL_ERROR;
204
205         factory = gst_element_get_factory(src_element);
206         if (!factory)
207                 goto INTERNAL_ERROR;
208
209         klass = gst_element_factory_get_klass(factory);
210         if (!klass)
211                 goto INTERNAL_ERROR;
212
213         MD_I("error code=%d, msg=%s, src element=%s, class=%s\n",
214                         error->code, error->message, src_element_name, klass);
215
216         switch (error->code) {
217         case GST_STREAM_ERROR_DECODE:
218         case GST_STREAM_ERROR_FAILED:
219                 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
220                 break;
221
222         case GST_STREAM_ERROR_CODEC_NOT_FOUND:
223         case GST_STREAM_ERROR_TYPE_NOT_FOUND:
224         case GST_STREAM_ERROR_WRONG_TYPE:
225                 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
226                 break;
227
228         default:
229                 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
230                 break;
231         }
232
233         return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
234
235 INTERNAL_ERROR:
236         return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
237 }
238
239
240 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
241 {
242         MEDIADEMUXER_FENTER();
243         int ret = MD_ERROR_NONE;
244         MEDIADEMUXER_CHECK_NULL(pOps);
245         def_demux_ops.n_size = sizeof(def_demux_ops);
246
247         memcpy((char *)pOps + sizeof(pOps->n_size),
248                (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
249                pOps->n_size - sizeof(pOps->n_size));
250
251         MEDIADEMUXER_FLEAVE();
252         return ret;
253 }
254
255 static int gst_demuxer_init(MMHandleType *pHandle)
256 {
257         MEDIADEMUXER_FENTER();
258         int ret = MD_ERROR_NONE;
259         mdgst_handle_t *new_mediademuxer = NULL;
260         new_mediademuxer = (mdgst_handle_t *)g_malloc(sizeof(mdgst_handle_t));
261         MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
262         if (!new_mediademuxer) {
263                 MD_E("Cannot allocate memory for demuxer\n");
264                 ret = MD_ERROR;
265                 goto ERROR;
266         }
267         memset(new_mediademuxer, 0, sizeof(mdgst_handle_t));
268         new_mediademuxer->is_prepared = false;
269         (new_mediademuxer->info).num_audio_track = 0;
270         (new_mediademuxer->info).num_video_track = 0;
271         (new_mediademuxer->info).num_subtitle_track = 0;
272         (new_mediademuxer->info).num_other_track = 0;
273         (new_mediademuxer->info).head = NULL;
274         *pHandle = (MMHandleType)new_mediademuxer;
275         new_mediademuxer->total_tracks = 0;
276         MEDIADEMUXER_FLEAVE();
277         return ret;
278 ERROR:
279         MEDIADEMUXER_FLEAVE();
280         return ret;
281 }
282
283 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
284 {
285         mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
286         MEDIADEMUXER_FENTER();
287         int ret = MD_ERROR_NONE;
288         switch (GST_MESSAGE_TYPE(msg)) {
289         case GST_MESSAGE_EOS: {
290                         MD_I("EOS Reached");
291                 }
292                 break;
293         case GST_MESSAGE_ERROR: {
294                         GError *error = NULL;
295                         gst_message_parse_error(msg, &error, NULL);
296                         if (!error) {
297                                 MD_I("GST error message parsing failed");
298                                 break;
299                         }
300
301                         if (error->domain == GST_STREAM_ERROR)
302                                 ret = __gst_handle_stream_error(gst_handle, error, msg);
303                         else if (error->domain == GST_RESOURCE_ERROR)
304                                 ret = __gst_handle_resource_error(gst_handle, error->code);
305                         else if (error->domain == GST_LIBRARY_ERROR)
306                                 ret = __gst_handle_library_error(gst_handle, error->code);
307                         else if (error->domain == GST_CORE_ERROR)
308                                 ret = __gst_handle_core_error(gst_handle, error->code);
309                         else
310                                 MD_W("Unexpected error has occured");
311
312                         if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
313                                 ((mediademuxer_error_cb)gst_handle->user_cb[_GST_EVENT_TYPE_ERROR])
314                                         (ret, gst_handle->user_data[_GST_EVENT_TYPE_ERROR]);
315                                         MD_W("Error : (ox%08x)", ret);
316                         }
317                         MD_E("Error: %s\n", error->message);
318                         g_error_free(error);
319                 }
320                 break;
321         default:
322                 break;
323         }
324         MEDIADEMUXER_FLEAVE();
325         return ret;
326 }
327
328 static void __gst_no_more_pad(GstElement *element, gpointer data)
329 {
330         MEDIADEMUXER_FENTER();
331         mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
332         int loop_track;
333         track_info *head_track = &(gst_handle->info);
334         track *head = head_track->head;
335         gst_handle->selected_tracks =
336             (bool *) g_malloc(sizeof(bool) * (gst_handle->total_tracks));
337         MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
338         if (!gst_handle->selected_tracks) {
339                 MD_E("[%s]Memory allocation failed\n", __FUNCTION__);
340                 return;
341         } else {
342                 for (loop_track = 0; loop_track < gst_handle->total_tracks;
343                      loop_track++)
344                         gst_handle->selected_tracks[loop_track] = false;
345         }
346         MD_I("Number of video tracks are %d\n", head_track->num_video_track);
347         MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
348         MD_I("Number of subtitle tracks are %d\n",
349              head_track->num_subtitle_track);
350         MD_I("Number of other tracks are %d\n", head_track->num_other_track);
351         while (head) {
352                 MD_I("track caps[%s]\n", head->caps_string);
353                 head = head->next;
354         }
355         gst_handle->is_prepared = true;
356         MD_I("core->is_prepared: ");
357         gst_handle->is_prepared ? MD_I("true\n") : MD_I("false\n");
358         MEDIADEMUXER_FLEAVE();
359 }
360
361 void __gst_free_stuct(track **head)
362 {
363         MEDIADEMUXER_FENTER();
364         track *temp = NULL;
365         temp = *head;
366         while (temp) {
367                 /*
368                 if (temp->pad) {
369                         MD_I("unref GST_PAD %p\n", temp->pad);
370                         gst_object_unref(temp->pad);
371                 } */
372                 if (temp->caps) {
373                         MD_I("unref GST_PAD caps %p\n", temp->caps);
374                         gst_caps_unref(temp->caps);
375                 }
376                 if (temp->caps_string) {
377                         MD_I("deallocate GST_PAD caps_string  %p\n",
378                              temp->caps_string);
379                         g_free(temp->caps_string);
380                 }
381                 if (temp->format) {
382                         MD_I("unref media_format  %p\n", temp->format);
383                         media_format_unref(temp->format);
384                 }
385                 if (temp->next) {
386                         track *next = temp->next;
387                         MD_I("deallocate memory %p\n", temp);
388                         free(temp);
389                         temp = next;
390                 } else {
391                         MD_I("deallocate memory %p\n", temp);
392                         free(temp);
393                         temp = NULL;
394                         *head = NULL;
395                 }
396         }
397         MEDIADEMUXER_FLEAVE();
398 }
399
400 int __gst_add_track_info(GstPad *pad, GstCaps *caps, track **head,
401                                                 GstElement *pipeline)
402 {
403         MEDIADEMUXER_FENTER();
404         GstPad *apppad = NULL;
405         GstPad *queue_sink_pad = NULL;
406         GstPad *queue_src_pad = NULL;
407         GstCaps *outcaps = NULL;
408         GstPad *parse_sink_pad = NULL;
409         GstElement *parse_element = NULL;
410         GstElement *id3tag = NULL;
411         GstPad *id3_sinkpad = NULL;
412         GstPad *id3_srcpad = NULL;
413         track *temp = NULL;
414
415         temp = (track *)(g_malloc(sizeof(track)));
416         if (!temp) {
417                 MD_E("Not able to allocate memory");
418                 return MD_ERROR;
419         } else {
420                 MD_I("allocate memory %p", temp);
421         }
422         temp->pad = pad;
423         temp->caps = gst_caps_ref(caps);
424         temp->caps_string = gst_caps_to_string(caps);
425         temp->next = NULL;
426         temp->format = NULL;
427         temp->need_codec_data = TRUE;
428
429         MD_I("track caps(%s)", temp->caps_string ? temp->caps_string : "NULL");
430
431         /* Link demuxer - queue */
432         temp->queue = gst_element_factory_make("queue", NULL);
433         if (!temp->queue) {
434                 MD_E("factory not able to make queue");
435                 goto ERROR;
436         }
437
438         if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
439                 gst_object_unref(temp->queue);
440                 MD_E("fail add queue in pipeline");
441                 goto ERROR;
442         }
443         MD_I("added queue element in pipeline.");
444
445         queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
446         if (!queue_sink_pad) {
447                 MD_E("sink pad of queue not avaible");
448                 goto ERROR;
449         }
450
451         MEDIADEMUXER_SET_STATE(temp->queue, GST_STATE_PAUSED, ERROR);
452         MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
453
454         temp->appsink = gst_element_factory_make("appsink", NULL);
455         if (!temp->appsink) {
456                 MD_E("factory not able to make appsink");
457                 goto ERROR;
458         }
459
460         if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
461                 gst_object_unref(temp->appsink);
462                 MD_E("fail add appsink in pipeline");
463                 goto ERROR;
464         }
465         MD_I("added appsink element in pipeline.");
466
467         gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
468         gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
469         MEDIADEMUXER_SET_STATE(temp->appsink, GST_STATE_PAUSED, ERROR);
470
471         queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
472         if (!queue_src_pad) {
473                 MD_E("src pad of queue not avaible");
474                 goto ERROR;
475         }
476         apppad = gst_element_get_static_pad(temp->appsink, "sink");
477         if (!apppad) {
478                 MD_E("sink pad of appsink not avaible");
479                 goto ERROR;
480         }
481         /* Check for type video and it should be h264 */
482         if (temp->caps_string && strstr(temp->caps_string, "video")) {
483                 if (strstr(temp->caps_string, "h264")) {
484                         parse_element = gst_element_factory_make("h264parse", NULL);
485                         if (!parse_element) {
486                                 MD_E("factory not able to make h264parse");
487                                 goto ERROR;
488                         }
489                 } else if (strstr(temp->caps_string, "mpeg")) {
490                         parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
491                         if (!parse_element) {
492                                 MD_E("factory not able to make h264parse");
493                                 goto ERROR;
494                         }
495                         g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
496                 }
497
498                 if (parse_element) {
499                         MD_I("add video parse element(%s).", GST_ELEMENT_NAME(parse_element));
500                         if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
501                                 gst_object_unref(parse_element);
502                                 MD_E("fail add video parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
503                                 goto ERROR;
504                         }
505                         parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
506                         if (!parse_sink_pad) {
507                                 MD_E("sink pad of video parse(%s) not available", GST_ELEMENT_NAME(parse_element));
508                                 goto ERROR;
509                         }
510                         MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
511                         /* Link demuxer pad with sink pad of parse element */
512                         MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
513
514                         if (strstr(temp->caps_string, "h264")) {
515                                 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
516                                 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
517                                 gst_caps_unref(outcaps);
518                         } else if (strstr(temp->caps_string, "mpeg")) {
519                                 gst_element_link(parse_element, temp->appsink);
520                         } else {
521                                 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
522                         }
523                 } else {
524                         MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
525                 }
526         } else if (temp->caps_string && (strstr(temp->caps_string, "audio") || strstr(temp->caps_string, "x-id3"))) {
527                 if (strstr(temp->caps_string, "audio/mpeg")) {
528                         int mpegversion = 0;
529                         GstStructure *structure = NULL;
530                         structure = gst_caps_get_structure(temp->caps, 0);
531                         gst_structure_get_int (structure, "mpegversion", &mpegversion);
532                         if (mpegversion == 2 || mpegversion == 4) {
533                                 parse_element = gst_element_factory_make("aacparse", NULL);
534                                 if (!parse_element) {
535                                         MD_E("factory not able to make aacparse");
536                                         goto ERROR;
537                                 }
538                         } else if (mpegversion == 1) {
539                                 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
540                                 if (!parse_element) {
541                                         MD_E("factory not able to make mpegaudioparse");
542                                         goto ERROR;
543                                 }
544                         }
545                 } else if (strstr(temp->caps_string, "application/x-id3")) {
546                         id3tag = gst_element_factory_make("id3demux", NULL);
547                         if (!id3tag) {
548                                 MD_E("factory not able to make id3demux");
549                                 goto ERROR;
550                         }
551                         if (!gst_bin_add(GST_BIN(pipeline), id3tag)) {
552                                 gst_object_unref(id3tag);
553                                 MD_E("fail add id3tag element in pipeline");
554                                 goto ERROR;
555                         }
556                         id3_sinkpad = gst_element_get_static_pad(id3tag, "sink");
557                         if (!id3_sinkpad) {
558                                 MD_E("fail to get id3demux sink pad.\n");
559                                 goto ERROR;
560                         }
561                         MEDIADEMUXER_LINK_PAD(queue_src_pad, id3_sinkpad, ERROR);
562                         MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
563                         id3_srcpad = gst_element_get_static_pad(id3tag, "src");
564                         if (!id3_srcpad) {
565                                 MD_E("fail to get id3demux src pad.\n");
566                                 goto ERROR;
567                         }
568                         parse_element = gst_element_factory_make("mpegaudioparse", NULL);
569                         if (!parse_element) {
570                                 MD_E("factory not able to make mpegaudioparse");
571                                 goto ERROR;
572                         }
573                 } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
574                                 || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
575                         parse_element = gst_element_factory_make("amrparse", NULL);
576                         if (!parse_element) {
577                                 MD_E("factory not able to make amrparse");
578                                 goto ERROR;
579                         }
580                 } else if (strstr(temp->caps_string, "audio/x-wav")) {
581                         parse_element = gst_element_factory_make("wavparse", NULL);
582                         if (!parse_element) {
583                                 MD_E("factory not able to make wavparse");
584                                 goto ERROR;
585                         }
586                 } else if (strstr(temp->caps_string, "audio/x-flac")) {
587                         parse_element = gst_element_factory_make("flacparse", NULL);
588                         if (!parse_element) {
589                                 MD_E("factory not able to make flacparse");
590                                 goto ERROR;
591                         }
592                 }
593
594                 if (parse_element) {
595                         MD_I("add audio parse element(%s).", GST_ELEMENT_NAME(parse_element));
596                         if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
597                                 gst_object_unref(parse_element);
598                                 MD_E("fail add audio parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
599                                 goto ERROR;
600                         }
601                         parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
602                         if (!parse_sink_pad) {
603                                 MD_E("sink pad of audio parse(%s) not available", GST_ELEMENT_NAME(parse_element));
604                                 goto ERROR;
605                         }
606                         MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
607
608                         /* Link demuxer pad with sink pad of parse element */
609                         if (id3tag)
610                                 MEDIADEMUXER_LINK_PAD(id3_srcpad, parse_sink_pad, ERROR);
611                         else
612                                 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
613
614                         /* Link src pad with appSink element */
615                         gst_element_link(parse_element, temp->appsink);
616                 } else {
617                         MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
618                 }
619         } else {
620                 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
621         }
622         /* gst_pad_link(pad, fpad) */
623         if (*head == NULL) {
624                 *head = temp;
625         } else {
626                 track *prev = *head;
627                 while (prev->next)
628                         prev = prev->next;
629                 prev->next = temp;
630         }
631         if (queue_sink_pad)
632                 gst_object_unref(queue_sink_pad);
633         if (queue_src_pad)
634                 gst_object_unref(queue_src_pad);
635         if (apppad)
636                 gst_object_unref(apppad);
637         if (parse_sink_pad)
638                 gst_object_unref(parse_sink_pad);
639         if (id3_sinkpad)
640                 gst_object_unref(id3_sinkpad);
641         if (id3_srcpad)
642                 gst_object_unref(id3_srcpad);
643         MEDIADEMUXER_FLEAVE();
644         return MD_ERROR_NONE;
645
646 ERROR:
647         __gst_free_stuct(&temp);
648         if (queue_sink_pad)
649                 gst_object_unref(queue_sink_pad);
650         if (queue_src_pad)
651                 gst_object_unref(queue_src_pad);
652         if (apppad)
653                 gst_object_unref(apppad);
654         if (parse_sink_pad)
655                 gst_object_unref(parse_sink_pad);
656         if (id3_sinkpad)
657                 gst_object_unref(id3_sinkpad);
658         if (id3_srcpad)
659                 gst_object_unref(id3_srcpad);
660         __gst_free_stuct(head);
661         MEDIADEMUXER_FLEAVE();
662         return MD_ERROR;
663 }
664
665 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
666 {
667         MEDIADEMUXER_FENTER();
668         MD_I("Dynamic pad created, linking demuxer/decoder\n");
669         track *tmp = NULL;
670         mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
671         track_info *head_track = &(gst_handle->info);
672         GstCaps *caps = gst_pad_get_current_caps(pad);
673         if (!caps) {
674                 MD_E("caps is NULL");
675                 return;
676         }
677         gst_handle->total_tracks++;
678         if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline)
679             != MD_ERROR_NONE) {
680                 MD_E("unable to added track info");
681                 head_track->num_audio_track = 0;
682                 head_track->num_video_track = 0;
683                 head_track->num_subtitle_track = 0;
684                 head_track->num_other_track = 0;
685                 gst_caps_unref(caps);
686                 __gst_free_stuct(&(head_track->head));
687                 return;
688         }
689         gst_caps_unref(caps);
690         tmp = head_track->head;
691         while (tmp->next)
692                 tmp = tmp->next;
693         if (!tmp || !tmp->caps_string) {
694                 MD_I("trak or trak caps_string is NULL\n");
695                 MEDIADEMUXER_FLEAVE();
696                 return;
697         }
698         if (tmp->caps_string[0] == 'v') {
699                 MD_I("found Video Pad\n");
700                 (head_track->num_video_track)++;
701         } else if (tmp->caps_string[0] == 'a') {
702                 MD_I("found Audio Pad\n");
703                 (head_track->num_audio_track)++;
704         } else if (tmp->caps_string[0] == 's') {
705                 MD_I("found subtitle(or Text) Pad\n");
706                 (head_track->num_subtitle_track)++;
707         } else {
708                 MD_W("found Pad, caps: %s\n", tmp->caps_string);
709                 (head_track->num_other_track)++;
710         }
711         MEDIADEMUXER_FLEAVE();
712 }
713
714 static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
715 {
716         MEDIADEMUXER_FENTER();
717         mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
718         GstPad *pad = NULL;
719         track_info *head_track = &(gst_handle->info);
720
721         gst_handle->is_valid_container = true;
722
723         pad = gst_element_get_static_pad(gst_handle->typefind, "src");
724         if (!pad) {
725                 MD_E("fail to get typefind src pad.\n");
726                 goto ERROR;
727         }
728
729         gst_handle->total_tracks++;
730         if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
731                 MD_E("unable to added track info");
732                 head_track->num_audio_track = 0;
733                 head_track->num_video_track = 0;
734                 head_track->num_subtitle_track = 0;
735                 head_track->num_other_track = 0;
736                 __gst_free_stuct(&(head_track->head));
737                 goto ERROR;
738         }
739
740         (head_track->num_audio_track)++;
741
742         /* unref pads */
743         if (pad)
744                 gst_object_unref(pad);
745
746         /* In the case of audio only, there is no gst_handle->demux. So we pass NULL */
747         __gst_no_more_pad(NULL, data);
748
749         MEDIADEMUXER_FLEAVE();
750         return MD_ERROR_NONE;
751
752 ERROR:
753         gst_handle->is_valid_container = false;
754
755         if (pad)
756                 gst_object_unref(pad);
757
758         MEDIADEMUXER_FLEAVE();
759         return MD_ERROR;
760 }
761
762 static void __gst_cb_typefind(GstElement *tf, guint probability,
763                                         GstCaps *caps, gpointer data)
764 {
765         MEDIADEMUXER_FENTER();
766         mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
767         GstPad *pad = NULL;
768         GstPad *demuxer_pad = NULL;
769         GstPad *fake_pad = NULL;
770         gchar *type;
771         type = gst_caps_to_string(caps);
772         if (type) {
773                 MD_I("Media type %s found, probability %d%%\n", type, probability);
774                 if (strstr(type, "quicktime") || (strstr(type, "audio/x-m4a")) || strstr(type, "x-3gp")
775                                 || strstr(type, "ogg") || strstr(type, "flv") || strstr(type, "x-msvideo")) {
776                         gst_handle->is_valid_container = true;
777                         if (strstr(type, "ogg"))
778                                 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
779                         else if (strstr(type, "flv"))
780                                 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
781                         else if (strstr(type, "x-msvideo"))
782                                 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
783                         else
784                                 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
785
786                         if (!gst_handle->demux) {
787                                 gst_handle->is_valid_container = false;
788                                 MD_E("factory not able to create qtdemux\n");
789                                 goto ERROR;
790                         } else {
791                                 g_signal_connect(gst_handle->demux, "pad-added",
792                                                                 G_CALLBACK(__gst_on_pad_added), gst_handle);
793                                 g_signal_connect(gst_handle->demux, "no-more-pads",
794                                                                 G_CALLBACK(__gst_no_more_pad), gst_handle);
795                                 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
796                                                                 gst_handle->demux, NULL);
797                                 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
798                                 if (!pad) {
799                                         MD_E("fail to get typefind src pad.\n");
800                                         goto ERROR;
801                                 }
802                                 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
803                                 if (!demuxer_pad) {
804                                         MD_E("fail to get qtdemuc sink pad.\n");
805                                         goto ERROR;
806                                 }
807                                 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
808                                 if (!fake_pad) {
809                                         MD_E("fail to get fakesink sink pad.\n");
810                                         goto ERROR;
811                                 }
812                                 gst_pad_unlink(pad, fake_pad);
813                                 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
814                                 MEDIADEMUXER_SET_STATE(gst_handle->demux,
815                                                                         GST_STATE_PAUSED, ERROR);
816                                 if (pad)
817                                         gst_object_unref(pad);
818                                 if (demuxer_pad)
819                                         gst_object_unref(demuxer_pad);
820                                 if (fake_pad)
821                                         gst_object_unref(fake_pad);
822                         }
823                 } else if ((strstr(type, "adts"))
824                            || (strstr(type, "audio/mpeg"))
825                            || (strstr(type, "audio/x-wav"))
826                            || (strstr(type, "audio/x-flac"))
827                            || (strstr(type, "application/x-id3"))
828                            || (strstr(type, "audio/x-amr-nb-sh"))
829                            || (strstr(type, "audio/x-amr-wb-sh"))) {
830                         MD_I("Audio only format is found\n");
831                         pad = gst_element_get_static_pad(gst_handle->typefind, "src");
832                         if (!pad) {
833                                 MD_E("fail to get typefind src pad.\n");
834                                 goto ERROR;
835                         }
836                         fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
837                         if (!fake_pad) {
838                                 MD_E("fail to get fakesink sink pad.\n");
839                                 goto ERROR;
840                         }
841                         gst_pad_unlink(pad, fake_pad);
842                         if (pad)
843                                 gst_object_unref(pad);
844                         if (fake_pad)
845                                 gst_object_unref(fake_pad);
846
847                         __gst_create_audio_only_pipeline(data, caps);
848                 } else {
849                         gst_handle->is_valid_container = false;
850                         MD_E("Not supported container %s\n", type);
851                 }
852                 g_free(type);
853         }
854         MEDIADEMUXER_FLEAVE();
855         return;
856 ERROR:
857         gst_handle->is_valid_container = false;
858         if (type)
859                 g_free(type);
860         if (pad)
861                 gst_object_unref(pad);
862         if (demuxer_pad)
863                 gst_object_unref(demuxer_pad);
864         if (fake_pad)
865                 gst_object_unref(fake_pad);
866         MEDIADEMUXER_FLEAVE();
867         return;
868 }
869
870 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
871 {
872         MEDIADEMUXER_FENTER();
873         int ret = MD_ERROR_NONE;
874         GstBus *bus = NULL;
875         char *path = NULL;
876         int remote_streaming = 0;
877         /* Initialize GStreamer */
878         /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
879         gst_init(NULL, NULL);
880
881         /* Create the empty pipeline */
882         gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
883         if (!gst_handle->pipeline) {
884                 MD_E("pipeline create fail");
885                 ret = MD_ERROR;
886                 goto ERROR;
887         }
888
889         /* Create the elements */
890         if ((path = strstr(uri, "http://"))) {
891                 gst_handle->filesrc  = gst_element_factory_make("souphttpsrc", NULL);
892                 remote_streaming = 1;
893                 MD_I("Source is http stream. \n");
894         } else {
895                 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
896                 MD_I("Source is file stream \n");
897         }
898         if (!gst_handle->filesrc) {
899                 MD_E("filesrc creation failed");
900                 ret = MD_ERROR;
901                 goto ERROR;
902         }
903
904         /* Modify the source's properties */
905         if (remote_streaming == 1)
906                 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
907         else
908                 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
909         gst_handle->typefind = gst_element_factory_make("typefind", NULL);
910         if (!gst_handle->typefind) {
911                 MD_E("typefind creation failed");
912                 ret = MD_ERROR;
913                 goto ERROR;
914         }
915         g_signal_connect(gst_handle->typefind, "have-type",
916                                         G_CALLBACK(__gst_cb_typefind), gst_handle);
917         gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
918         if (!gst_handle->fakesink) {
919                 MD_E("fakesink creation failed");
920                 ret = MD_ERROR;
921                 goto ERROR;
922         }
923
924         /* Build the pipeline */
925         gst_bin_add_many(GST_BIN(gst_handle->pipeline),
926                                                 gst_handle->filesrc,
927                                                 gst_handle->typefind,
928                                                 gst_handle->fakesink,
929                                                 NULL);
930         gst_element_link_many(gst_handle->filesrc,
931                                                         gst_handle->typefind,
932                                                         gst_handle->fakesink,
933                                                         NULL);
934
935         /* connect signals, bus watcher */
936         bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
937         gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
938         gst_handle->thread_default = g_main_context_get_thread_default();
939         gst_object_unref(GST_OBJECT(bus));
940
941         /* set pipeline state to PAUSED */
942         MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
943
944         int count = 0;
945         while (gst_handle->is_prepared != true) {
946                 count++;
947                 usleep(POLLING_INTERVAL);
948                 MD_I("Inside while loop\n");
949                 if (count > POLLING_INTERVAL) {
950                         MD_E("Error occure\n");
951                         ret = MD_ERROR;
952                         break;
953                 }
954         }
955
956         MEDIADEMUXER_FLEAVE();
957         return ret;
958 ERROR:
959         MEDIADEMUXER_FLEAVE();
960         return ret;
961 }
962
963 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
964 {
965         MEDIADEMUXER_FENTER();
966         int ret = MD_ERROR_NONE;
967         MEDIADEMUXER_CHECK_NULL(pHandle);
968         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
969
970         MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
971         ret = _gst_create_pipeline(new_mediademuxer, uri);
972         if (ret != MD_ERROR_NONE) {
973                 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
974                 goto ERROR;
975         }
976         MEDIADEMUXER_FLEAVE();
977         return ret;
978 ERROR:
979         MEDIADEMUXER_FLEAVE();
980         return ret;
981 }
982
983 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
984 {
985         MEDIADEMUXER_FENTER();
986         int ret = MD_ERROR_NONE;
987         MEDIADEMUXER_CHECK_NULL(pHandle);
988         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
989
990         *count = (new_mediademuxer->info).num_video_track +
991                         (new_mediademuxer->info).num_audio_track +
992                         (new_mediademuxer->info).num_subtitle_track +
993                         (new_mediademuxer->info).num_other_track;
994         MEDIADEMUXER_FLEAVE();
995         return ret;
996 }
997
998 int _gst_set_appsink(track *temp, int index, int loop)
999 {
1000         MEDIADEMUXER_FENTER();
1001         int ret = MD_ERROR_NONE;
1002         int count = 0;
1003
1004         while (count != index) {
1005                 temp = temp->next;
1006                 count++;
1007         }
1008         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
1009         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
1010         MEDIADEMUXER_FLEAVE();
1011         return ret;
1012 }
1013
1014 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
1015 {
1016         MEDIADEMUXER_FENTER();
1017         int ret = MD_ERROR_NONE;
1018         MEDIADEMUXER_CHECK_NULL(pHandle);
1019         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1020
1021         MD_I("total_tracks (%d) :: selected  track (%d)", new_mediademuxer->total_tracks, track);
1022         if (track >= new_mediademuxer->total_tracks || track < 0) {
1023                 MD_E("total_tracks is less then selected track, So not support this track");
1024                 ret = MD_ERROR_INVALID_ARGUMENT;
1025                 goto ERROR;
1026         }
1027         new_mediademuxer->selected_tracks[track] = true;
1028         _gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1029                                         new_mediademuxer->total_tracks);
1030         MEDIADEMUXER_FLEAVE();
1031         return MD_ERROR_NONE;
1032 ERROR:
1033         MEDIADEMUXER_FLEAVE();
1034         return ret;
1035 }
1036
1037 static int _gst_unlink_unselected_track(track *temp, int index)
1038 {
1039         MEDIADEMUXER_FENTER();
1040         int ret = MD_ERROR_NONE;
1041         int count = 0;
1042         GstPad *queue_sink_pad = NULL;
1043         while (count != index) {
1044                 temp = temp->next;
1045                 count++;
1046         }
1047         queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
1048         if (!queue_sink_pad) {
1049                 MD_E("queue_sink_pad of appsink not avaible\n");
1050                 return MD_ERROR;
1051         }
1052         if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
1053                 MD_W("demuxer is already unlinked from queue for track %d\n", index);
1054
1055         gst_object_unref(queue_sink_pad);
1056         MEDIADEMUXER_FLEAVE();
1057         return ret;
1058 }
1059
1060 static int gst_demuxer_start(MMHandleType pHandle)
1061 {
1062         MEDIADEMUXER_FENTER();
1063         int ret = MD_ERROR_NONE;
1064         MEDIADEMUXER_CHECK_NULL(pHandle);
1065         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1066
1067         int indx;
1068         for (indx = 0; indx < gst_handle->total_tracks; indx++) {
1069                 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
1070                         indx, gst_handle->selected_tracks[indx]);
1071                 /*
1072                 if (gst_handle->selected_tracks[indx] ==  false)
1073                         _gst_demuxer_unset(pHandle, indx);
1074                 */
1075                 if (gst_handle->selected_tracks[indx] != true) {
1076                         if (_gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
1077                                 MD_E("Failed to unlink unselected tracks\n");
1078                                 ret = MD_INTERNAL_ERROR;
1079                                 goto ERROR;
1080                         }
1081                 }
1082
1083         }
1084
1085         track_info *head_track = &(gst_handle->info);
1086         MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
1087                         head_track->num_audio_track, head_track->num_video_track,
1088                         head_track->num_subtitle_track);
1089
1090         track *temp = head_track->head;
1091         indx = 0;
1092         while (temp) {
1093                 MD_I("Got one element %p\n", temp->appsink);
1094                 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
1095                         GST_STATE_CHANGE_FAILURE) {
1096                         MD_E("Failed to set into PLAYING state");
1097                         ret = MD_INTERNAL_ERROR;
1098                         goto ERROR;
1099                 }
1100                 MD_I("set the state to playing\n");
1101                 indx++;
1102                 if (temp->next) {
1103                         track *next = temp->next;
1104                         temp = next;
1105                 } else {
1106                         temp = NULL;
1107                 }
1108         }
1109
1110         MD_I("gst_demuxer_start pipeine %p", gst_handle);
1111         MEDIADEMUXER_FLEAVE();
1112         return ret;
1113 ERROR:
1114         MEDIADEMUXER_FLEAVE();
1115         return ret;
1116 }
1117
1118 int _set_mime_text(media_format_h format, track *head)
1119 {
1120         MEDIADEMUXER_FENTER();
1121         int ret = MD_ERROR_NONE;
1122         GstStructure *struc = NULL;
1123         struc = gst_caps_get_structure(head->caps, 0);
1124         if (!struc) {
1125                 MD_E("cannot get structure from caps.\n");
1126                 goto ERROR;
1127         }
1128         if (gst_structure_has_name(struc, "text/x-raw")) {
1129                 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
1130                         goto ERROR;
1131         } else {
1132                 MD_I("Text mime not supported so far\n");
1133                 goto ERROR;
1134         }
1135
1136         MEDIADEMUXER_FLEAVE();
1137         return ret;
1138 ERROR:
1139         MEDIADEMUXER_FLEAVE();
1140         return MD_ERROR;
1141 }
1142
1143 int _set_mime_video(media_format_h format, track *head)
1144 {
1145         MEDIADEMUXER_FENTER();
1146         int ret = MD_ERROR_NONE;
1147         GstStructure *struc = NULL;
1148         int src_width;
1149         int src_height;
1150         int frame_rate_numerator = 0;
1151         int frame_rate_denominator = 0;
1152         media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1153         struc = gst_caps_get_structure(head->caps, 0);
1154         if (!struc) {
1155                 MD_E("cannot get structure from caps.\n");
1156                 goto ERROR;
1157         }
1158         if (gst_structure_has_name(struc, "video/x-h264")) {
1159                 mime_type = MEDIA_FORMAT_H264_SP;
1160         } else if (gst_structure_has_name(struc, "video/x-h263")) {
1161                 mime_type = MEDIA_FORMAT_H263;
1162         } else if (gst_structure_has_name(struc, "video/mpeg")) {
1163                 mime_type = MEDIA_FORMAT_MPEG4_SP;
1164         } else {
1165                 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
1166                 goto ERROR;
1167         }
1168         if (media_format_set_video_mime(format, mime_type)) {
1169                 MD_E("Unable to set video mime type (%x)\n", mime_type);
1170                 goto ERROR;
1171         }
1172         gst_structure_get_int(struc, "width", &src_width);
1173         gst_structure_get_int(struc, "height", &src_height);
1174         if (media_format_set_video_width(format, src_width)) {
1175                 MD_E("Unable to set video width\n");
1176                 goto ERROR;
1177         }
1178         if (media_format_set_video_height(format, src_height)) {
1179                 MD_E("Unable to set video height\n");
1180                 goto ERROR;
1181         }
1182         gst_structure_get_fraction(struc, "framerate",  &frame_rate_numerator, &frame_rate_denominator);
1183         if (media_format_set_video_frame_rate(format, frame_rate_numerator)) {
1184                 MD_E("Unable to set video frame rate\n");
1185                 goto ERROR;
1186         }
1187         MEDIADEMUXER_FLEAVE();
1188         return ret;
1189 ERROR:
1190         MEDIADEMUXER_FLEAVE();
1191         return MD_ERROR;
1192 }
1193
1194 int _set_mime_audio(media_format_h format, track *head)
1195 {
1196         MEDIADEMUXER_FENTER();
1197         int ret = MD_ERROR_NONE;
1198         GstStructure *struc = NULL;
1199         int rate = 0;
1200         int bit = 0;
1201         int channels = 0;
1202         int id3_flag = 0;
1203         const gchar *stream_format;
1204         media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1205
1206         struc = gst_caps_get_structure(head->caps, 0);
1207         if (!struc) {
1208                 MD_E("cannot get structure from caps.\n");
1209                 goto ERROR;
1210         }
1211
1212         if (gst_structure_has_name(struc, "application/x-id3"))
1213                 id3_flag = 1;
1214         if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1215                 gint mpegversion;
1216                 int layer;
1217                 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1218                 if (mpegversion == 4 || mpegversion == 2) {
1219                         mime_type = MEDIA_FORMAT_AAC_LC;
1220                         if (media_format_set_audio_mime(format, mime_type))
1221                                 goto ERROR;
1222                         stream_format = gst_structure_get_string(struc, "stream-format");
1223
1224                         if (strncmp(stream_format, "adts", 4) == 0)
1225                                 media_format_set_audio_aac_type(format, 1);
1226                         else
1227                                 media_format_set_audio_aac_type(format, 0);
1228
1229                 } else if (mpegversion == 1 || id3_flag) {
1230                         gst_structure_get_int(struc, "layer", &layer);
1231                         if ((layer == 3) || (id3_flag == 1)) {
1232                                 mime_type = MEDIA_FORMAT_MP3;
1233                         } else {
1234                                 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1235                                 goto ERROR;
1236                         }
1237                 }
1238         } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1239                 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1240                 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1241                         mime_type = MEDIA_FORMAT_AMR_NB;
1242                         rate = 8000;
1243                 } else {
1244                         mime_type = MEDIA_FORMAT_AMR_WB;
1245                         rate = 16000;
1246                 }
1247         } else if (gst_structure_has_name(struc, "audio/AMR")) {
1248                 mime_type = MEDIA_FORMAT_AMR_NB;
1249         } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1250                 mime_type = MEDIA_FORMAT_AMR_WB;
1251         } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1252                 mime_type = MEDIA_FORMAT_PCM;
1253         } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1254                 mime_type = MEDIA_FORMAT_FLAC;
1255         } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1256                 mime_type = MEDIA_FORMAT_VORBIS;
1257         } else {
1258                 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1259                 goto ERROR;
1260         }
1261         if (media_format_set_audio_mime(format, mime_type))
1262                 goto ERROR;
1263         gst_structure_get_int(struc, "channels", &channels);
1264         if (channels == 0) {    /* default */
1265                 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1266                         channels = 1;
1267                 else
1268                         channels = 2;
1269         }
1270         if (media_format_set_audio_channel(format, channels))
1271                 goto ERROR;
1272         if (rate == 0)
1273                 gst_structure_get_int(struc, "rate", &rate);
1274         if (rate == 0)
1275                 rate = 44100;   /* default */
1276         if (media_format_set_audio_samplerate(format, rate))
1277                 goto ERROR;
1278         gst_structure_get_int(struc, "bit", &bit);
1279         if (bit == 0)
1280                 bit = 16;       /* default */
1281         if (media_format_set_audio_bit(format, bit))
1282                 goto ERROR;
1283         MEDIADEMUXER_FLEAVE();
1284         return ret;
1285 ERROR:
1286         MEDIADEMUXER_FLEAVE();
1287         return MD_ERROR;
1288 }
1289
1290 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1291                                                         media_format_h *format, int index)
1292 {
1293         MEDIADEMUXER_FENTER();
1294         int ret = MD_ERROR_NONE;
1295         MEDIADEMUXER_CHECK_NULL(pHandle);
1296         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1297
1298         track *temp = NULL;
1299         int loop;
1300         int count = 0;
1301         temp = (new_mediademuxer->info).head;
1302         loop = (new_mediademuxer->info).num_video_track +
1303                         (new_mediademuxer->info).num_audio_track +
1304                         (new_mediademuxer->info).num_subtitle_track +
1305                         (new_mediademuxer->info).num_other_track;
1306         if (index >= loop || index < 0) {
1307                 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1308                 ret = MD_ERROR;
1309                 goto ERROR;
1310         }
1311
1312         while (count != index) {
1313                 temp = temp->next;
1314                 count++;
1315         }
1316         if (temp->format != NULL) {
1317                 ret = media_format_ref(temp->format);
1318                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1319                         MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1320                         ret = MD_INTERNAL_ERROR;
1321                         goto ERROR;
1322                 }
1323                 ret = media_format_make_writable(temp->format, format); /* copy the content */
1324                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1325                         MD_E("Mediaformat create copy failed. returned %d\n", ret);
1326                         media_format_unref(temp->format);
1327                         ret = MD_INTERNAL_ERROR;
1328                         goto ERROR;
1329                 }
1330                 MEDIADEMUXER_FLEAVE();
1331                 return ret;
1332         }
1333         ret = media_format_create(&(temp->format));
1334         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1335                 MD_E("Mediaformat creation failed. returned %d\n", ret);
1336                 ret = MD_INTERNAL_ERROR;
1337                 goto ERROR;
1338         }
1339
1340         MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1341         MD_I("format ptr[%p]\n", temp->format);
1342         if (temp->caps_string[0] == 'a') {
1343                 MD_I("Setting for Audio \n");
1344                 _set_mime_audio(temp->format, temp);
1345         } else if (temp->caps_string[0] == 'v') {
1346                 MD_I("Setting for Video \n");
1347                 _set_mime_video(temp->format, temp);
1348         } else if (temp->caps_string[0] == 't') {
1349                 MD_I("Setting for Subtitle\n");
1350                 _set_mime_text(temp->format, temp);
1351         } else {
1352                 MD_W("Not supported so far (except audio, video and subtitle)\n");
1353         }
1354
1355         ret = media_format_ref(temp->format);   /* increment the ref to retain the original content */
1356         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1357                 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1358                 ret = MD_INTERNAL_ERROR;
1359                 goto ERROR;
1360         }
1361         ret = media_format_make_writable(temp->format, format); /* copy the content */
1362         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1363                 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1364                 media_format_unref(temp->format);
1365                 ret = MD_INTERNAL_ERROR;
1366                 goto ERROR;
1367         }
1368         MEDIADEMUXER_FLEAVE();
1369         return ret;
1370 ERROR:
1371         MEDIADEMUXER_FLEAVE();
1372         return ret;
1373 }
1374
1375 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1376                                                         GstBuffer *buffer, GstBuffer *codec_data)
1377 {
1378         MEDIADEMUXER_FENTER();
1379         int ret = MD_ERROR_NONE;
1380         MEDIADEMUXER_CHECK_NULL(out_pkt);
1381         void *pkt_data;
1382         uint64_t size;
1383         GstMapInfo map;
1384
1385         if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1386                 MD_E("gst_buffer_map failed\n");
1387                 ret = MD_ERROR_UNKNOWN;
1388                 goto ERROR;
1389         }
1390         /* copy data */
1391         media_packet_get_buffer_size(out_pkt, &size);
1392         MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1393         if (size < (uint64_t)map.size) {
1394                 MD_W("Media packet Buffer capacity[%llu] is \
1395                         less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1396                 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1397                 media_packet_get_buffer_size(out_pkt, &size);
1398                 MD_I("Media packet Buffer NEW  capacity: %llu \n", size);
1399         }
1400         if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1401                 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1402                 ret = MD_ERROR_UNKNOWN;
1403                 goto ERROR;
1404         }
1405         memcpy((char *)pkt_data, map.data, map.size);
1406         if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1407                 MD_E("unable to set the pts\n");
1408                 ret = MD_ERROR_UNKNOWN;
1409                 goto ERROR;
1410         }
1411         if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1412                 MD_E("unable to set the dts\n");
1413                 ret = MD_ERROR_UNKNOWN;
1414                 goto ERROR;
1415         }
1416         if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1417                 MD_E("unable to set the duration\n");
1418                 ret = MD_ERROR_UNKNOWN;
1419                 goto ERROR;
1420         }
1421         if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1422                 MD_E("unable to set the buffer size\n");
1423                 ret = MD_ERROR_UNKNOWN;
1424                 goto ERROR;
1425         }
1426         if (media_packet_set_flags(out_pkt, GST_BUFFER_FLAGS(buffer))) {
1427                 MD_E("unable to set the buffer size\n");
1428                 ret = MD_ERROR_UNKNOWN;
1429                 goto ERROR;
1430         }
1431         /* set codec data into media packet */
1432         if (codec_data) {
1433                 GstMapInfo codec_data_map;
1434                 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1435                         MD_E("codec data buffer map failed\n");
1436                         ret = MD_ERROR_UNKNOWN;
1437                         goto ERROR;
1438                 }
1439                 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1440                         (unsigned int)codec_data_map.size)) {
1441                         MD_E("unable to set the codec data\n");
1442                         ret = MD_ERROR_UNKNOWN;
1443                         gst_buffer_unmap(codec_data, &codec_data_map);
1444                         goto ERROR;
1445                 }
1446                 gst_buffer_unmap(codec_data, &codec_data_map);
1447
1448                 media_buffer_flags_e flags;
1449                 media_packet_get_flags(out_pkt, &flags);
1450                 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1451         }
1452 ERROR:
1453         gst_buffer_unmap(buffer, &map);
1454         MEDIADEMUXER_FLEAVE();
1455         return ret;
1456 }
1457
1458 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1459 {
1460         media_packet_h mediabuf = NULL;
1461         int ret = MD_ERROR_NONE;
1462
1463         MEDIADEMUXER_FENTER();
1464         if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1465                 MD_E("media_packet_create_alloc failed\n");
1466                 ret = MD_ERROR;
1467                 goto ERROR;
1468         }
1469
1470         if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1471                 MD_E("unable to set EOS flag\n");
1472                 ret = MD_ERROR_UNKNOWN;
1473                 goto ERROR;
1474         }
1475
1476         *outbuf = mediabuf;
1477         MEDIADEMUXER_FLEAVE();
1478
1479         return ret;
1480 ERROR:
1481         if (mediabuf)
1482                 media_packet_destroy(mediabuf);
1483         *outbuf = NULL;
1484         MEDIADEMUXER_FLEAVE();
1485         return ret;
1486 }
1487
1488 static int gst_demuxer_read_sample(MMHandleType pHandle,
1489                                                 media_packet_h *outbuf, int track_indx)
1490 {
1491         MEDIADEMUXER_FENTER();
1492         int ret = MD_ERROR_NONE;
1493         MEDIADEMUXER_CHECK_NULL(pHandle);
1494         mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1495
1496         media_packet_h mediabuf = NULL;
1497         int indx = 0;
1498
1499         track *atrack = demuxer->info.head;
1500         if ((demuxer->selected_tracks)[track_indx] == false) {
1501                 MD_E("Track Not selected\n");
1502                 ret = MD_ERROR;
1503                 goto ERROR;
1504         }
1505         while (atrack) {
1506                 if (indx == track_indx)  /* Got the requird track details */
1507                         break;
1508                 if (atrack->next) {
1509                         track *next = atrack->next;
1510                         atrack = next;
1511                 } else {
1512                         MD_E("Invalid track Index\n");
1513                         ret = MD_ERROR_INVALID_ARGUMENT;
1514                         goto ERROR;
1515                 }
1516                 indx++;
1517         }
1518
1519         if (!atrack) {
1520                 MD_E("atrack is NULL\n");
1521                 goto ERROR;
1522         }
1523
1524         if (indx != track_indx) {
1525                 MD_E("Invalid track Index\n");
1526                 ret = MD_ERROR_INVALID_ARGUMENT;
1527                 goto ERROR;
1528         }
1529         GstElement *sink = atrack->appsink;
1530         GstSample *sample = NULL;
1531
1532         sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1533         if (sample == NULL) {
1534                 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1535                         MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1536                         ret = MD_ERROR_NONE;
1537                         *outbuf = NULL;
1538                         __gst_eos_callback(track_indx, demuxer);
1539
1540                         //Make EOS packet
1541                         _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1542                         return ret;
1543                 } else {
1544                         MD_E("gst_demuxer_read_sample failed\n");
1545                         *outbuf = NULL;
1546                         ret = MD_ERROR_UNKNOWN;
1547                         return ret;
1548                 }
1549         }
1550
1551         if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1552                 MD_E("media_packet_create_alloc failed\n");
1553                 ret = MD_ERROR;
1554                 goto ERROR;
1555         }
1556
1557         GstBuffer *buffer = gst_sample_get_buffer(sample);
1558         if (buffer == NULL) {
1559                 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1560                 ret = MD_ERROR_UNKNOWN;
1561                 goto ERROR;
1562         }
1563
1564         GstBuffer *codec_data_buffer = NULL;
1565         /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1566         if (atrack->need_codec_data) {
1567                 atrack->need_codec_data = FALSE;
1568                 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1569                 GstStructure *structure = NULL;
1570                 const GValue *value = NULL;
1571
1572                 structure = gst_caps_get_structure(atrack->caps, 0);
1573                 /* get codec data from caps*/
1574                 value = gst_structure_get_value(structure, "codec_data");
1575                 if (value)
1576                         codec_data_buffer = gst_value_get_buffer(value);
1577         }
1578
1579         /* Fill the media_packet with proper information */
1580         ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1581         gst_sample_unref(sample);
1582         *outbuf = mediabuf;
1583
1584         MEDIADEMUXER_FLEAVE();
1585         return ret;
1586 ERROR:
1587         if (mediabuf)
1588                 media_packet_destroy(mediabuf);
1589         *outbuf = NULL;
1590         MEDIADEMUXER_FLEAVE();
1591         return ret;
1592 }
1593
1594 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1595 {
1596         MEDIADEMUXER_FENTER();
1597         MEDIADEMUXER_CHECK_NULL(pHandle);
1598         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1599
1600         gint64 pos = 0;
1601         gdouble rate = 1;
1602         track_info *head_track = &(gst_handle->info);
1603         track *temp = head_track->head;
1604         track *temp_track = head_track->head;
1605         int indx = 0;
1606
1607         /* Setting each appsink to paused state before seek */
1608         while (temp_track) {
1609                 if (gst_handle->selected_tracks[indx] == true) {
1610                         if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1611                                 MD_E("Failed to set into PAUSED state");
1612                                 goto ERROR;
1613                         }
1614                         MD_I("set the state to paused\n");
1615                 }
1616                 indx++;
1617                 if (temp_track->next) {
1618                         track *next = temp_track->next;
1619                         temp_track = next;
1620                 } else {
1621                         temp_track = NULL;
1622                 }
1623         }
1624
1625         pos = pos1 * GST_MSECOND;
1626
1627         MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1628
1629         indx = 0;
1630         while (temp) {
1631                 MD_I("Got one element %p\n", temp->appsink);
1632                 if (gst_handle->selected_tracks[indx] == true) {
1633                         temp->need_codec_data = TRUE;
1634                         if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1635                              GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1636                              GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1637                                 MD_E("Seek failed!\n");
1638                                 goto ERROR;
1639                         } else {
1640                                 MD_I("Seek success...setting appsink to playing state\n");
1641                                 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1642                                         MD_E("Failed to set into PLAYING state");
1643                                         goto ERROR;
1644                                 }
1645                         }
1646                 }
1647                 indx++;
1648                 if (temp->next) {
1649                         track *next = temp->next;
1650                         temp = next;
1651                 } else {
1652                         temp = NULL;
1653                 }
1654         }
1655         MEDIADEMUXER_FLEAVE();
1656         return MD_ERROR_NONE;
1657 ERROR:
1658         MEDIADEMUXER_FLEAVE();
1659         return MD_ERROR;
1660 }
1661
1662 int _gst_unset_appsink(track *temp, int index, int loop)
1663 {
1664         MEDIADEMUXER_FENTER();
1665         int ret = MD_ERROR_NONE;
1666         int count = 0;
1667
1668         while (count != index) {
1669                 temp = temp->next;
1670                 count++;
1671         }
1672         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1673         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1674         MEDIADEMUXER_FLEAVE();
1675         return ret;
1676 }
1677
1678 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1679 {
1680         MEDIADEMUXER_FENTER();
1681         int ret = MD_ERROR_NONE;
1682         MEDIADEMUXER_CHECK_NULL(pHandle);
1683         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1684
1685         if (track >= new_mediademuxer->total_tracks || track < 0) {
1686                 MD_E("total tracks is less then unselected track, So not support this track");
1687                 ret = MD_ERROR_INVALID_ARGUMENT;
1688                 goto ERROR;
1689         }
1690         new_mediademuxer->selected_tracks[track] = false;
1691         _gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1692                                         new_mediademuxer->total_tracks);
1693         MEDIADEMUXER_FLEAVE();
1694         return ret;
1695 ERROR:
1696         MEDIADEMUXER_FLEAVE();
1697         return ret;
1698 }
1699
1700 static int gst_demuxer_stop(MMHandleType pHandle)
1701 {
1702         MEDIADEMUXER_FENTER();
1703         int ret = MD_ERROR_NONE;
1704         MEDIADEMUXER_CHECK_NULL(pHandle);
1705         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1706
1707         MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1708         if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1709             GST_STATE_CHANGE_FAILURE) {
1710                 MD_E("Failed to set into PAUSE state");
1711                 ret = MD_INTERNAL_ERROR;
1712                 goto ERROR;
1713         }
1714         MEDIADEMUXER_FLEAVE();
1715         return ret;
1716 ERROR:
1717         MEDIADEMUXER_FLEAVE();
1718         return ret;
1719 }
1720
1721 void  _gst_clear_struct(mdgst_handle_t *gst_handle)
1722 {
1723         MEDIADEMUXER_FENTER();
1724         if (gst_handle->selected_tracks) {
1725                 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1726                      gst_handle->selected_tracks);
1727                 g_free(gst_handle->selected_tracks);
1728                 gst_handle->selected_tracks = NULL;
1729         }
1730         if ((gst_handle->info).head)
1731                 __gst_free_stuct(&(gst_handle->info).head);
1732         MEDIADEMUXER_FLEAVE();
1733 }
1734
1735 int _md_gst_destroy_pipeline(GstElement *pipeline)
1736 {
1737         MEDIADEMUXER_FENTER();
1738         int ret = MD_ERROR_NONE;
1739         if (pipeline)
1740                 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1741         if (pipeline)
1742                 gst_object_unref(GST_OBJECT(pipeline));
1743         MEDIADEMUXER_FLEAVE();
1744         return ret;
1745 ERROR:
1746         if (pipeline)
1747                 gst_object_unref(GST_OBJECT(pipeline));
1748         MEDIADEMUXER_FLEAVE();
1749         return MD_ERROR;
1750 }
1751
1752 static int gst_demuxer_unprepare(MMHandleType pHandle)
1753 {
1754         MEDIADEMUXER_FENTER();
1755         int ret = MD_ERROR_NONE;
1756         MEDIADEMUXER_CHECK_NULL(pHandle);
1757         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1758
1759         _gst_clear_struct(gst_handle);
1760         if (gst_handle->bus_watch_id) {
1761                 GSource *source = NULL;
1762                 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1763                 if (source) {
1764                         g_source_destroy(source);
1765                         LOGD("Deallocation bus watch id");
1766                 }
1767         }
1768
1769         MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1770         if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1771                 ret = MD_ERROR;
1772                 goto ERROR;
1773         }
1774         MEDIADEMUXER_FLEAVE();
1775         return ret;
1776 ERROR:
1777         MEDIADEMUXER_FLEAVE();
1778         return ret;
1779 }
1780
1781 static int gst_demuxer_destroy(MMHandleType pHandle)
1782 {
1783         MEDIADEMUXER_FENTER();
1784         int ret = MD_ERROR_NONE;
1785         MEDIADEMUXER_CHECK_NULL(pHandle);
1786         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1787
1788         MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1789              new_mediademuxer);
1790         g_free(new_mediademuxer);
1791         MEDIADEMUXER_FLEAVE();
1792         return ret;
1793 }
1794
1795 int gst_set_error_cb(MMHandleType pHandle,
1796                         gst_error_cb callback, void *user_data)
1797 {
1798         MEDIADEMUXER_FENTER();
1799         int ret = MD_ERROR_NONE;
1800         MEDIADEMUXER_CHECK_NULL(pHandle);
1801         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1802
1803         if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1804                 MD_E("Already set mediademuxer_error_cb\n");
1805                 ret = MD_ERROR_INVALID_ARGUMENT;
1806                 goto ERROR;
1807         } else {
1808                 if (!callback) {
1809                         MD_E("fail invaild argument (callback)\n");
1810                         ret = MD_ERROR_INVALID_ARGUMENT;
1811                         goto ERROR;
1812                 }
1813         }
1814
1815         MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1816
1817         gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1818         gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1819         MEDIADEMUXER_FLEAVE();
1820         return MD_ERROR_NONE;
1821 ERROR:
1822         MEDIADEMUXER_FLEAVE();
1823         return ret;
1824 }
1825
1826 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1827 {
1828         MEDIADEMUXER_FENTER();
1829         int ret = MD_ERROR_NONE;
1830         MEDIADEMUXER_CHECK_NULL(pHandle);
1831         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1832
1833         if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1834                 MD_E("Already set mediademuxer_eos_cb\n");
1835                 ret = MD_ERROR_INVALID_ARGUMENT;
1836                 goto ERROR;
1837         } else {
1838                 if (!callback) {
1839                         MD_E("fail invaild argument (callback)\n");
1840                         ret = MD_ERROR_INVALID_ARGUMENT;
1841                         goto ERROR;
1842                 }
1843         }
1844
1845         MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1846         gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1847         gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1848         MEDIADEMUXER_FLEAVE();
1849         return MD_ERROR_NONE;
1850 ERROR:
1851         MEDIADEMUXER_FLEAVE();
1852         return ret;
1853 }
1854
1855 static int __gst_eos_callback(int track_num, void* user_data)
1856 {
1857         if (user_data == NULL) {
1858                 MD_E("Invalid argument");
1859                 return MD_ERROR;
1860         }
1861         mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1862         if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1863                 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1864                                         gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1865         else
1866                 MD_E("EOS received, but callback is not set!!!");
1867         return MD_ERROR_NONE;
1868 }