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