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