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