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