Sync with 2.4 [Fixed prevent issues].
[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
47 /* Media Demuxer API common */
48 static media_port_demuxer_ops def_demux_ops = {
49         .n_size = 0,
50         .init = gst_demuxer_init,
51         .prepare = gst_demuxer_prepare,
52         .get_track_count = gst_demuxer_get_data_count,
53         .set_track = gst_demuxer_set_track,
54         .start = gst_demuxer_start,
55         .get_track_info = gst_demuxer_get_track_info,
56         .read_sample = gst_demuxer_read_sample,
57         .seek = gst_demuxer_seek,
58         .unset_track = gst_demuxer_unset_track,
59         .stop = gst_demuxer_stop,
60         .unprepare = gst_demuxer_unprepare,
61         .destroy = gst_demuxer_destroy,
62         .set_error_cb = gst_set_error_cb,
63 };
64
65 int gst_port_register(media_port_demuxer_ops *pOps)
66 {
67         MEDIADEMUXER_FENTER();
68         int ret = MD_ERROR_NONE;
69         MEDIADEMUXER_CHECK_NULL(pOps);
70         def_demux_ops.n_size = sizeof(def_demux_ops);
71
72         memcpy((char *)pOps + sizeof(pOps->n_size),
73                (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
74                pOps->n_size - sizeof(pOps->n_size));
75
76         MEDIADEMUXER_FLEAVE();
77         return ret;
78 }
79
80 static int gst_demuxer_init(MMHandleType *pHandle)
81 {
82         MEDIADEMUXER_FENTER();
83         int ret = MD_ERROR_NONE;
84         mdgst_handle_t *new_mediademuxer = NULL;
85         new_mediademuxer = (mdgst_handle_t *) g_malloc(sizeof(mdgst_handle_t));
86         MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
87         if (!new_mediademuxer) {
88                 MD_E("Cannot allocate memory for demuxer\n");
89                 ret = MD_ERROR;
90                 goto ERROR;
91         }
92         memset(new_mediademuxer, 0, sizeof(mdgst_handle_t));
93         new_mediademuxer->is_prepared = false;
94         (new_mediademuxer->info).num_audio_track = 0;
95         (new_mediademuxer->info).num_video_track = 0;
96         (new_mediademuxer->info).num_subtitle_track = 0;
97         (new_mediademuxer->info).num_other_track = 0;
98         (new_mediademuxer->info).head = NULL;
99         *pHandle = (MMHandleType) new_mediademuxer;
100         new_mediademuxer->total_tracks = 0;
101         MEDIADEMUXER_FLEAVE();
102         return ret;
103 ERROR:
104         MEDIADEMUXER_FLEAVE();
105         return ret;
106 }
107
108 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
109 {
110         MEDIADEMUXER_FENTER();
111         int ret = MD_ERROR_NONE;
112         switch (GST_MESSAGE_TYPE(msg)) {
113         case GST_MESSAGE_EOS: {
114                         MD_I("EOS Reached");
115                 }
116                 break;
117         case GST_MESSAGE_ERROR: {
118                         GError *error = NULL;
119                         gst_message_parse_error(msg, &error, NULL);
120                         if (!error) {
121                                 MD_I("GST error message parsing failed");
122                                 break;
123                         }
124                         MD_E("Error: %s\n", error->message);
125                         g_error_free(error);
126                 }
127                 break;
128         default:
129                 break;
130         }
131         MEDIADEMUXER_FLEAVE();
132         return ret;
133 }
134
135 static void __gst_no_more_pad(GstElement *element, gpointer data)
136 {
137         MEDIADEMUXER_FENTER();
138         mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
139         int loop_track;
140         track_info *head_track = &(gst_handle->info);
141         track *head = head_track->head;
142         gst_handle->selected_tracks =
143             (bool *) g_malloc(sizeof(bool) * (gst_handle->total_tracks));
144         MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
145         if (!gst_handle->selected_tracks) {
146                 MD_E("[%s]Memory allocation failed\n", __FUNCTION__);
147                 return;
148         } else {
149                 for (loop_track = 0; loop_track < gst_handle->total_tracks;
150                      loop_track++)
151                         gst_handle->selected_tracks[loop_track] = false;
152         }
153         MD_I("Number of video tracks are %d\n", head_track->num_video_track);
154         MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
155         MD_I("Number of subtitle tracks are %d\n",
156              head_track->num_subtitle_track);
157         MD_I("Number of other tracks are %d\n", head_track->num_other_track);
158         while (head) {
159                 MD_I("track caps[%s]\n", head->name);
160                 head = head->next;
161         }
162         gst_handle->is_prepared = true;
163         MD_I("core->is_prepared: ");
164         gst_handle->is_prepared ? MD_I("true\n") : MD_I("false\n");
165         MEDIADEMUXER_FLEAVE();
166 }
167
168 void __gst_free_stuct(track **head)
169 {
170         MEDIADEMUXER_FENTER();
171         track *temp = NULL;
172         temp = *head;
173         while (temp) {
174                 /*
175                 if (temp->pad) {
176                         MD_I("deallocate GST_PAD %p\n", temp->pad);
177                         gst_object_unref(temp->pad);
178                 } */
179                 if (temp->name) {
180                         MD_I("deallocate GST_PAD name  %p\n", temp->name);
181                         g_free(temp->name);
182                 }
183                 if (temp->caps_string) {
184                         MD_I("deallocate GST_PAD caps_string  %p\n",
185                              temp->caps_string);
186                         g_free(temp->caps_string);
187                 }
188                 if (temp->caps) {
189                         MD_I("deallocate GST_PAD caps_  %p\n", temp->caps);
190                         gst_caps_unref(temp->caps);
191                 }
192
193                 if (temp->next) {
194                         track *next = temp->next;
195                         MD_I("deallocate memory %p\n", temp);
196                         free(temp);
197                         temp = next;
198                 } else {
199                         MD_I("deallocate memory %p\n", temp);
200                         free(temp);
201                         temp = NULL;
202                         *head = NULL;
203                 }
204         }
205         MEDIADEMUXER_FLEAVE();
206 }
207
208 int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
209                                                 GstElement *pipeline)
210 {
211         MEDIADEMUXER_FENTER();
212         GstPad *apppad = NULL;
213         GstCaps *outcaps = NULL;
214         GstPad *parse_sink_pad = NULL;
215         GstElement *parse_element = NULL;
216         track *temp = NULL;
217
218         temp = (track *)(g_malloc(sizeof(track)));
219         if (!temp) {
220                 MD_E("Not able to allocate memory");
221                 return MD_ERROR;
222         } else {
223                 MD_I("allocate memory %p", temp);
224         }
225         temp->pad = pad;
226         temp->caps = gst_pad_get_current_caps(pad);
227         temp->name = name;
228         temp->caps_string = gst_caps_to_string(temp->caps);
229         temp->next = NULL;
230         temp->appsink = gst_element_factory_make("appsink", NULL);
231         if (!temp->appsink) {
232                 MD_E("factory not able to make appsink");
233                 __gst_free_stuct(head);
234                 return MD_ERROR;
235         }
236         gst_bin_add_many(GST_BIN(pipeline), temp->appsink, NULL);
237         gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, MAX_APP_BUFFER);
238         MEDIADEMUXER_SET_STATE(temp->appsink, GST_STATE_PAUSED, ERROR);
239         apppad = gst_element_get_static_pad(temp->appsink, "sink");
240         if (!apppad) {
241                 MD_E("sink pad of appsink not avaible");
242                 __gst_free_stuct(head);
243                 return MD_ERROR;
244         }
245         /* Check for type video and it should be h264 */
246         if (strstr(name, "video") && strstr(temp->caps_string, "h264")) {
247                 parse_element = gst_element_factory_make("h264parse", NULL);
248                 if (!parse_element) {
249                         MD_E("factory not able to make h264parse");
250                         __gst_free_stuct(head);
251                         gst_object_unref(apppad);
252                         return MD_ERROR;
253                 }
254                 gst_bin_add_many(GST_BIN(pipeline), parse_element, NULL);
255                 MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
256
257                 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
258                 if (!parse_sink_pad) {
259                         MD_E("sink pad of h264parse not available");
260                         __gst_free_stuct(head);
261                         gst_object_unref(apppad);
262                         return MD_ERROR;
263                 }
264
265                 /* Link demuxer pad with sink pad of parse element */
266                 MEDIADEMUXER_LINK_PAD(pad, parse_sink_pad, ERROR);
267
268                 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
269                 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
270         } else {
271                 MEDIADEMUXER_LINK_PAD(pad, apppad, ERROR);
272         }
273         /* gst_pad_link(pad, fpad) */
274         if (*head == NULL) {
275                 *head = temp;
276         } else {
277                 track *prev = *head;
278                 while (prev->next)
279                         prev = prev->next;
280                 prev->next = temp;
281         }
282         gst_object_unref(apppad);
283         MEDIADEMUXER_FLEAVE();
284         return MD_ERROR_NONE;
285 ERROR:
286         if (apppad)
287                 gst_object_unref(apppad);
288         __gst_free_stuct(head);
289         MEDIADEMUXER_FLEAVE();
290         return MD_ERROR;
291 }
292
293 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
294 {
295         MEDIADEMUXER_FENTER();
296         MD_I("Dynamic pad created, linking demuxer/decoder\n");
297         track *tmp = NULL;
298         mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
299         track_info *head_track = &(gst_handle->info);
300         gchar *name = gst_pad_get_name(pad);
301         gst_handle->total_tracks++;
302         if (__gst_add_track_info(pad, name, &(head_track->head), gst_handle->pipeline)
303             != MD_ERROR_NONE) {
304                 MD_E("unable to added track info");
305                 head_track->num_audio_track = 0;
306                 head_track->num_video_track = 0;
307                 head_track->num_subtitle_track = 0;
308                 head_track->num_other_track = 0;
309                 __gst_free_stuct(&(head_track->head));
310                 return;
311         }
312         tmp = head_track->head;
313         while (tmp->next)
314                 tmp = tmp->next;
315         if (tmp->caps_string[0] == 'v') {
316                 MD_I("found Video Pad\n");
317                 (head_track->num_video_track)++;
318         } else if (tmp->caps_string[0] == 'a') {
319                 MD_I("found Audio Pad\n");
320                 (head_track->num_audio_track)++;
321         } else if (tmp->caps_string[0] == 's') {
322                 MD_I("found subtitle(or Text) Pad\n");
323                 (head_track->num_subtitle_track)++;
324         } else {
325                 MD_W("found Pad %s\n", name);
326                 (head_track->num_other_track)++;
327         }
328         MEDIADEMUXER_FLEAVE();
329 }
330
331 static int __gst_create_audio_only_pipeline(gpointer data,  GstCaps *caps)
332 {
333         MEDIADEMUXER_FENTER();
334         mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
335         GstPad *pad = NULL;
336         GstPad *aud_pad = NULL;
337         GstPad *queue_srcpad = NULL;
338         GstPad *queue_sinkpad = NULL;
339         GstPad *aud_srcpad = NULL;
340         GstPad *fake_pad = NULL;
341         GstElement *id3tag = NULL;
342         GstElement *adif_queue = NULL;
343         gchar *name;
344         gchar *type;
345         track_info *head_track = &(gst_handle->info);
346         track *trck;
347         gst_handle->is_valid_container = true;
348         type = gst_caps_to_string(caps);
349         if (strstr(type, "adts") || strstr(type, "adif")) {
350                 gst_handle->demux = gst_element_factory_make("aacparse", NULL);
351         } else if (strstr(type, "audio/mpeg")) {
352                 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
353         } else if (strstr(type, "application/x-id3")) {
354                 id3tag = gst_element_factory_make("id3demux", NULL);
355                 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
356         } else if (strstr(type, "audio/x-amr-nb-sh")
357                    || strstr(type, "audio/x-amr-wb-sh")) {
358                 gst_handle->demux = gst_element_factory_make("amrparse", NULL);
359         } else if (strstr(type, "audio/x-wav")) {
360                 gst_handle->demux = gst_element_factory_make("wavparse", NULL);
361         } else if (strstr(type, "audio/x-flac")) {
362                 gst_handle->demux = gst_element_factory_make("flacparse", NULL);
363         }
364
365         if (!gst_handle->demux) {
366                 gst_handle->is_valid_container = false;
367                 MD_E("factory not able to create audio parse element\n");
368                 goto ERROR;
369         } else {
370                 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
371                                  gst_handle->demux, id3tag, NULL);
372                 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
373                 if (!pad) {
374                         MD_E("fail to get typefind src pad.\n");
375                         goto ERROR;
376                 }
377                 if (!id3tag)
378                         aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
379                 else
380                         aud_pad = gst_element_get_static_pad(id3tag, "sink");
381                 if (!aud_pad) {
382                         MD_E("fail to get audio parse sink pad.\n");
383                         goto ERROR;
384                 }
385                 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
386                 if (!fake_pad) {
387                         MD_E("fail to get fakesink sink pad.\n");
388                         goto ERROR;
389                 }
390                 gst_pad_unlink(pad, fake_pad);
391                 if (strstr(type, "adif")) {
392                         adif_queue = gst_element_factory_make("queue", NULL);
393                         if (!adif_queue) {
394                                 MD_E("factory not able to make queue in case of adif aac\n");
395                                 goto ERROR;
396                         }
397                         /* Add this queue to the pipeline */
398                         gst_bin_add_many(GST_BIN(gst_handle->pipeline), adif_queue, NULL);
399                         queue_srcpad = gst_element_get_static_pad(adif_queue, "src");
400                         if (!queue_srcpad) {
401                                 MD_E("fail to get queue src pad for adif aac.\n");
402                                 goto ERROR;
403                         }
404                         queue_sinkpad = gst_element_get_static_pad(adif_queue, "sink");
405                         if (!queue_sinkpad) {
406                                 MD_E("fail to get queue sink pad for adif aac.\n");
407                                 goto ERROR;
408                         }
409                         /* link typefind with queue */
410                         MEDIADEMUXER_LINK_PAD(pad, queue_sinkpad, ERROR);
411                         /* link queue with aacparse */
412                         MEDIADEMUXER_LINK_PAD(queue_srcpad, aud_pad, ERROR);
413                 } else {
414                         MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
415                 }
416
417                 if (!id3tag) {
418                         MEDIADEMUXER_SET_STATE(gst_handle->demux,
419                                                GST_STATE_PAUSED, ERROR);
420                 } else {
421                         MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
422                         MEDIADEMUXER_SET_STATE(gst_handle->demux,
423                                                GST_STATE_PAUSED, ERROR);
424                         gst_element_link(id3tag, gst_handle->demux);
425                 }
426
427                 if (adif_queue)
428                         MEDIADEMUXER_SET_STATE(adif_queue, GST_STATE_PAUSED, ERROR);
429
430                 if (pad)
431                         gst_object_unref(pad);
432                 if (aud_pad)
433                         gst_object_unref(aud_pad);
434                 if (fake_pad)
435                         gst_object_unref(fake_pad);
436                 if (queue_sinkpad)
437                         gst_object_unref(queue_sinkpad);
438                 if (queue_srcpad)
439                         gst_object_unref(queue_srcpad);
440         }
441
442         g_free(type);
443         /* calling "on_pad_added" function to set the caps */
444         aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
445         if (!aud_srcpad) {
446                 MD_E("fail to get audioparse source pad.\n");
447                 goto ERROR;
448         }
449         gst_handle->total_tracks++;
450         name = gst_pad_get_name(aud_srcpad);
451         if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline)
452             != MD_ERROR_NONE) {
453                 MD_E("unable to added track info");
454                 head_track->num_audio_track = 0;
455                 head_track->num_video_track = 0;
456                 head_track->num_subtitle_track = 0;
457                 head_track->num_other_track = 0;
458                 __gst_free_stuct(&(head_track->head));
459                 goto ERROR;
460         }
461         if (aud_srcpad)
462                 gst_object_unref(aud_srcpad);
463
464         trck = head_track->head;
465         while (trck != NULL && aud_srcpad != trck->pad)
466                 trck = trck->next;
467         if (trck != NULL) {
468                 trck->caps = caps;
469                 trck->caps_string = gst_caps_to_string(trck->caps);
470                 MD_I("caps set to %s\n", trck->caps_string);
471                 g_strlcpy(name, "audio", strlen(name));
472                 trck->name = name;
473         }
474         (head_track->num_audio_track)++;
475         __gst_no_more_pad(gst_handle->demux, data);
476         MEDIADEMUXER_FLEAVE();
477         return MD_ERROR_NONE;
478 ERROR:
479         gst_handle->is_valid_container = false;
480         if (gst_handle->demux)
481                 gst_object_unref(gst_handle->demux);
482         if (pad)
483                 gst_object_unref(pad);
484         if (aud_pad)
485                 gst_object_unref(aud_pad);
486         if (fake_pad)
487                 gst_object_unref(fake_pad);
488         if (aud_srcpad)
489                 gst_object_unref(aud_srcpad);
490         if (queue_sinkpad)
491                 gst_object_unref(queue_sinkpad);
492         if (queue_srcpad)
493                 gst_object_unref(queue_srcpad);
494         g_free(type);
495         MEDIADEMUXER_FLEAVE();
496         return MD_ERROR;
497 }
498
499 static void __gst_cb_typefind(GstElement *tf, guint probability,
500                                         GstCaps *caps, gpointer data)
501 {
502         MEDIADEMUXER_FENTER();
503         mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
504         GstPad *pad = NULL;
505         GstPad *demuxer_pad = NULL;
506         GstPad *fake_pad = NULL;
507         gchar *type;
508         type = gst_caps_to_string(caps);
509         if (type) {
510                 MD_I("Media type %s found, probability %d%%\n", type, probability);
511                 if (strstr(type, "quicktime") || (strstr(type, "audio/x-m4a")) || strstr(type, "x-3gp")
512                                 || strstr(type, "ogg")) {
513                         gst_handle->is_valid_container = true;
514                         if (strstr(type, "ogg"))
515                                 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
516                         else
517                                 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
518
519                         if (!gst_handle->demux) {
520                                 gst_handle->is_valid_container = false;
521                                 MD_E("factory not able to create qtdemux\n");
522                                 goto ERROR;
523                         } else {
524                                 g_signal_connect(gst_handle->demux, "pad-added",
525                                                                 G_CALLBACK(__gst_on_pad_added), gst_handle);
526                                 g_signal_connect(gst_handle->demux, "no-more-pads",
527                                                                 G_CALLBACK(__gst_no_more_pad), gst_handle);
528                                 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
529                                                                 gst_handle->demux, NULL);
530                                 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
531                                 if (!pad) {
532                                         MD_E("fail to get typefind src pad.\n");
533                                         goto ERROR;
534                                 }
535                                 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
536                                 if (!demuxer_pad) {
537                                         MD_E("fail to get qtdemuc sink pad.\n");
538                                         goto ERROR;
539                                 }
540                                 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
541                                 if (!fake_pad) {
542                                         MD_E("fail to get fakesink sink pad.\n");
543                                         goto ERROR;
544                                 }
545                                 gst_pad_unlink(pad, fake_pad);
546                                 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
547                                 MEDIADEMUXER_SET_STATE(gst_handle->demux,
548                                                                         GST_STATE_PAUSED, ERROR);
549                                 if (pad)
550                                         gst_object_unref(pad);
551                                 if (demuxer_pad)
552                                         gst_object_unref(demuxer_pad);
553                                 if (fake_pad)
554                                         gst_object_unref(fake_pad);
555                         }
556                 } else if ((strstr(type, "adts"))
557                            || (strstr(type, "audio/mpeg"))
558                            || (strstr(type, "audio/x-wav"))
559                            || (strstr(type, "audio/x-flac"))
560                            || (strstr(type, "application/x-id3"))
561                            || (strstr(type, "audio/x-amr-nb-sh"))
562                            || (strstr(type, "audio/x-amr-wb-sh"))) {
563                         MD_I("Audio only format is found\n");
564                         __gst_create_audio_only_pipeline(data, caps);
565                 } else {
566                         gst_handle->is_valid_container = false;
567                         MD_E("Not supported container %s\n", type);
568                 }
569                 g_free(type);
570         }
571         MEDIADEMUXER_FLEAVE();
572         return;
573 ERROR:
574         gst_handle->is_valid_container = false;
575         if (gst_handle->demux)
576                 gst_object_unref(gst_handle->demux);
577         if (type)
578                 g_free(type);
579         if (pad)
580                 gst_object_unref(pad);
581         if (demuxer_pad)
582                 gst_object_unref(demuxer_pad);
583         if (fake_pad)
584                 gst_object_unref(fake_pad);
585         MEDIADEMUXER_FLEAVE();
586         return;
587 }
588
589 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
590 {
591         MEDIADEMUXER_FENTER();
592         int ret = MD_ERROR_NONE;
593         GstBus *bus = NULL;
594
595         /* Initialize GStreamer */
596         /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
597         gst_init(NULL, NULL);
598
599         /* Create the empty pipeline */
600         gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
601         if (!gst_handle->pipeline) {
602                 MD_E("pipeline create fail");
603                 ret = MD_ERROR;
604                 goto ERROR;
605         }
606
607         /* Create the elements */
608         gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
609         if (!gst_handle->filesrc) {
610                 MD_E("filesrc creation failed");
611                 ret = MD_ERROR;
612                 goto ERROR;
613         }
614
615         /* Modify the source's properties */
616         g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
617         gst_handle->typefind = gst_element_factory_make("typefind", NULL);
618         if (!gst_handle->typefind) {
619                 MD_E("typefind creation failed");
620                 ret = MD_ERROR;
621                 goto ERROR;
622         }
623         g_signal_connect(gst_handle->typefind, "have-type",
624                                         G_CALLBACK(__gst_cb_typefind), gst_handle);
625         gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
626         if (!gst_handle->fakesink) {
627                 MD_E("fakesink creation failed");
628                 ret = MD_ERROR;
629                 goto ERROR;
630         }
631
632         /* Build the pipeline */
633         gst_bin_add_many(GST_BIN(gst_handle->pipeline),
634                                                 gst_handle->filesrc,
635                                                 gst_handle->typefind,
636                                                 gst_handle->fakesink,
637                                                 NULL);
638         gst_element_link_many(gst_handle->filesrc,
639                                                         gst_handle->typefind,
640                                                         gst_handle->fakesink,
641                                                         NULL);
642
643         /* connect signals, bus watcher */
644         bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
645         gst_handle->bus_whatch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
646         gst_object_unref(bus);
647
648         /* set pipeline state to PAUSED */
649         MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
650
651         int count = 0;
652         while (gst_handle->is_prepared != true) {
653                 count++;
654                 usleep(POLLING_INTERVAL);
655                 MD_I("Inside while loop\n");
656                 if (count > POLLING_INTERVAL) {
657                         MD_E("Error occure\n");
658                         ret = MD_ERROR;
659                 }
660         }
661
662         MEDIADEMUXER_FLEAVE();
663         return ret;
664 ERROR:
665         MEDIADEMUXER_FLEAVE();
666         return ret;
667 }
668
669 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
670 {
671         MEDIADEMUXER_FENTER();
672         int ret = MD_ERROR_NONE;
673         MEDIADEMUXER_CHECK_NULL(pHandle);
674         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
675
676         MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
677         ret = _gst_create_pipeline(new_mediademuxer, uri);
678         if (ret != MD_ERROR_NONE) {
679                 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
680                 goto ERROR;
681         }
682         MEDIADEMUXER_FLEAVE();
683         return ret;
684 ERROR:
685         MEDIADEMUXER_FLEAVE();
686         return ret;
687 }
688
689 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
690 {
691         MEDIADEMUXER_FENTER();
692         int ret = MD_ERROR_NONE;
693         MEDIADEMUXER_CHECK_NULL(pHandle);
694         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
695
696         *count = (new_mediademuxer->info).num_video_track +
697                         (new_mediademuxer->info).num_audio_track +
698                         (new_mediademuxer->info).num_subtitle_track +
699                         (new_mediademuxer->info).num_other_track;
700         MEDIADEMUXER_FLEAVE();
701         return ret;
702 }
703
704 int _gst_set_appsink(track *temp, int index, int loop)
705 {
706         MEDIADEMUXER_FENTER();
707         int ret = MD_ERROR_NONE;
708         int count = 0;
709
710         while (count != index) {
711                 temp = temp->next;
712                 count++;
713         }
714         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
715         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
716         MEDIADEMUXER_FLEAVE();
717         return ret;
718 }
719
720 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
721 {
722         MEDIADEMUXER_FENTER();
723         int ret = MD_ERROR_NONE;
724         MEDIADEMUXER_CHECK_NULL(pHandle);
725         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
726
727         MD_I("total_tracks (%d) :: selected  track (%d)", new_mediademuxer->total_tracks, track);
728         if (track >= new_mediademuxer->total_tracks || track < 0) {
729                 MD_E("total_tracks is less then selected track, So not support this track");
730                 ret = MD_ERROR_INVALID_ARGUMENT;
731                 goto ERROR;
732         }
733         new_mediademuxer->selected_tracks[track] = true;
734         _gst_set_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
735                                         new_mediademuxer->total_tracks);
736         MEDIADEMUXER_FLEAVE();
737         return MD_ERROR_NONE;
738 ERROR:
739         MEDIADEMUXER_FLEAVE();
740         return ret;
741 }
742
743 static int gst_demuxer_start(MMHandleType pHandle)
744 {
745         MEDIADEMUXER_FENTER();
746         int ret = MD_ERROR_NONE;
747         MEDIADEMUXER_CHECK_NULL(pHandle);
748         mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
749
750         int indx;
751         for (indx = 0; indx < gst_handle->total_tracks; indx++) {
752                 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
753                         indx, gst_handle->selected_tracks[indx]);
754                 /*
755                 if (gst_handle->selected_tracks[indx] ==  false)
756                         _gst_demuxer_unset(pHandle, indx);
757                 */
758         }
759
760         track_info *head_track = &(gst_handle->info);
761         MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
762                         head_track->num_audio_track, head_track->num_video_track,
763                         head_track->num_subtitle_track);
764
765         track *temp = head_track->head;
766         indx = 0;
767         while (temp) {
768                 MD_I("Got one element %p\n", temp->appsink);
769                 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
770                         GST_STATE_CHANGE_FAILURE) {
771                         MD_E("Failed to set into PLAYING state");
772                         ret = MD_INTERNAL_ERROR;
773                         goto ERROR;
774                 }
775                 MD_I("set the state to playing\n");
776                 indx++;
777                 if (temp->next) {
778                         track *next = temp->next;
779                         temp = next;
780                 } else {
781                         temp = NULL;
782                 }
783         }
784
785         MD_I("gst_demuxer_start pipeine %p", gst_handle);
786         MEDIADEMUXER_FLEAVE();
787         return ret;
788 ERROR:
789         MEDIADEMUXER_FLEAVE();
790         return ret;
791 }
792
793 int _set_mime_video(media_format_h format, track *head)
794 {
795         MEDIADEMUXER_FENTER();
796         int ret = MD_ERROR_NONE;
797         GstStructure *struc = NULL;
798         int src_width;
799         int src_height;
800         struc = gst_caps_get_structure(head->caps, 0);
801         if (!struc) {
802                 MD_E("cannot get structure from caps.\n");
803                 goto ERROR;
804         }
805         if (gst_structure_has_name(struc, "video/x-h264")) {
806                 const gchar *version = gst_structure_get_string(struc, "stream-format");
807                 if (strncmp(version, "avc", 3) == 0) {
808                         gst_structure_get_int(struc, "width", &src_width);
809                         gst_structure_get_int(struc, "height", &src_height);
810                         if (media_format_set_video_mime(format, MEDIA_FORMAT_H264_SP))
811                                 goto ERROR;
812                         if (media_format_set_video_width(format, src_width))
813                                 goto ERROR;
814                         if (media_format_set_video_height(format, src_height))
815                                 goto ERROR;
816                 }
817         } else if (gst_structure_has_name(struc, "video/x-h263")) {
818                 gst_structure_get_int(struc, "width", &src_width);
819                 gst_structure_get_int(struc, "height", &src_height);
820                 if (media_format_set_video_mime(format, MEDIA_FORMAT_H263))
821                         goto ERROR;
822                 if (media_format_set_video_width(format, src_width))
823                         goto ERROR;
824                 if (media_format_set_video_height(format, src_height))
825                         goto ERROR;
826         } else {
827                 MD_I("Video mime not supported so far\n");
828                 goto ERROR;
829         }
830         MEDIADEMUXER_FLEAVE();
831         return ret;
832 ERROR:
833         MEDIADEMUXER_FLEAVE();
834         return MD_ERROR;
835 }
836
837 int _set_mime_audio(media_format_h format, track *head)
838 {
839         MEDIADEMUXER_FENTER();
840         int ret = MD_ERROR_NONE;
841         GstStructure *struc = NULL;
842         int rate = 0;
843         int bit = 0;
844         int channels = 0;
845         int id3_flag = 0;
846         const gchar *stream_format;
847
848         struc = gst_caps_get_structure(head->caps, 0);
849         if (!struc) {
850                 MD_E("cannot get structure from caps.\n");
851                 goto ERROR;
852         }
853
854         if (gst_structure_has_name(struc, "application/x-id3"))
855                 id3_flag = 1;
856         if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
857                 gint mpegversion;
858                 int layer;
859                 gst_structure_get_int(struc, "mpegversion", &mpegversion);
860                 if (mpegversion == 4 || mpegversion == 2) {
861                         gst_structure_get_int(struc, "channels", &channels);
862                         gst_structure_get_int(struc, "rate", &rate);
863                         gst_structure_get_int(struc, "bit", &bit);
864                         stream_format = gst_structure_get_string(struc, "stream-format");
865                         if (media_format_set_audio_mime(format, MEDIA_FORMAT_AAC_LC))
866                                 goto ERROR;
867                         if (channels == 0)
868                                 channels = 2;   /* default */
869                         if (media_format_set_audio_channel(format, channels))
870                                 goto ERROR;
871                         if (rate == 0)
872                                 rate = 44100;   /* default */
873                         if (media_format_set_audio_samplerate(format, rate))
874                                 goto ERROR;
875                         if (bit == 0)
876                                 bit = 16;       /* default */
877                         if (media_format_set_audio_bit(format, bit))
878                                 goto ERROR;
879                         if (strncmp(stream_format, "adts", 4) == 0)
880                                 media_format_set_audio_aac_type(format, 1);
881                         else
882                                 media_format_set_audio_aac_type(format, 0);
883                 }
884                 if (mpegversion == 1 || id3_flag) {
885                         gst_structure_get_int(struc, "layer", &layer);
886                         if ((layer == 3) || (id3_flag == 1)) {
887                                 gst_structure_get_int(struc, "channels", &channels);
888                                 gst_structure_get_int(struc, "rate", &rate);
889                                 gst_structure_get_int(struc, "bit", &bit);
890                                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_MP3))
891                                         goto ERROR;
892                                 if (channels == 0)
893                                         channels = 2;   /* default */
894                                 if (media_format_set_audio_channel(format, channels))
895                                         goto ERROR;
896                                 if (rate == 0)
897                                         rate = 44100;   /* default */
898                                 if (bit == 0)
899                                         bit = 16;       /* default */
900                                 if (media_format_set_audio_samplerate(format, rate))
901                                         goto ERROR;
902                                 if (media_format_set_audio_bit(format, bit))
903                                         goto ERROR;
904                         } else {
905                                 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
906                                 goto ERROR;
907                         }
908                 }
909         } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
910                 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
911                 media_format_mimetype_e mime_type;
912                 gst_structure_get_int(struc, "channels", &channels);
913                 gst_structure_get_int(struc, "rate", &rate);
914                 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
915                         mime_type = MEDIA_FORMAT_AMR_NB;
916                         rate = 8000;
917                 } else {
918                         mime_type = MEDIA_FORMAT_AMR_WB;
919                         rate = 16000;
920                 }
921                 if (media_format_set_audio_mime(format, mime_type))
922                         goto ERROR;
923                 if (channels == 0)
924                         channels = 1;   /* default */
925                 if (bit == 0)
926                         bit = 16;       /* default */
927                 if (media_format_set_audio_channel(format, channels))
928                         goto ERROR;
929                 if (media_format_set_audio_samplerate(format, rate))
930                         goto ERROR;
931                 if (media_format_set_audio_bit(format, bit))
932                         goto ERROR;
933         } else if (gst_structure_has_name(struc, "audio/AMR")) {
934                 gst_structure_get_int(struc, "channels", &channels);
935                 gst_structure_get_int(struc, "rate", &rate);
936                 gst_structure_get_int(struc, "bit", &bit);
937                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_AMR_NB))
938                         goto ERROR;
939                 if (channels == 0)
940                         channels = 1;   /* default */
941                 if (media_format_set_audio_channel(format, channels))
942                         goto ERROR;
943                 if (media_format_set_audio_samplerate(format, rate))
944                         goto ERROR;
945                 if (bit == 0)
946                         bit = 16;       /* default */
947                 if (media_format_set_audio_bit(format, bit))
948                         goto ERROR;
949         } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
950                 gst_structure_get_int(struc, "channels", &channels);
951                 gst_structure_get_int(struc, "rate", &rate);
952                 gst_structure_get_int(struc, "bit", &bit);
953                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_AMR_WB))
954                         goto ERROR;
955                 if (channels == 0)
956                         channels = 1;   /* default */
957                 if (media_format_set_audio_channel(format, channels))
958                         goto ERROR;
959                 if (media_format_set_audio_samplerate(format, rate))
960                         goto ERROR;
961                 if (bit == 0)
962                         bit = 16;       /* default */
963                 if (media_format_set_audio_bit(format, bit))
964                         goto ERROR;
965         } else if (gst_structure_has_name(struc, "audio/x-wav")) {
966                 gst_structure_get_int(struc, "channels", &channels);
967                 gst_structure_get_int(struc, "rate", &rate);
968                 gst_structure_get_int(struc, "bit", &bit);
969                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_PCM))
970                         goto ERROR;
971                 if (channels == 0)
972                         channels = 2;   /* default */
973                 if (media_format_set_audio_channel(format, channels))
974                         goto ERROR;
975                 if (rate == 0)
976                         rate = 44100;   /* default */
977                 if (media_format_set_audio_samplerate(format, rate))
978                         goto ERROR;
979                 if (bit == 0)
980                         bit = 16;       /* default */
981                 if (media_format_set_audio_bit(format, bit))
982                         goto ERROR;
983         } else if (gst_structure_has_name(struc, "audio/x-flac")) {
984                 gst_structure_get_int(struc, "channels", &channels);
985                 gst_structure_get_int(struc, "rate", &rate);
986                 gst_structure_get_int(struc, "bit", &bit);
987                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_FLAC))
988                         goto ERROR;
989                 if (channels == 0)
990                         channels = 2;   /* default */
991                 if (media_format_set_audio_channel(format, channels))
992                         goto ERROR;
993                 if (rate == 0)
994                         rate = 44100;   /* default */
995                 if (media_format_set_audio_samplerate(format, rate))
996                         goto ERROR;
997                 if (bit == 0)
998                         bit = 16;       /* default */
999                 if (media_format_set_audio_bit(format, bit))
1000                         goto ERROR;
1001         } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1002                 gst_structure_get_int(struc, "channels", &channels);
1003                 gst_structure_get_int(struc, "rate", &rate);
1004                 gst_structure_get_int(struc, "bit", &bit);
1005                 if (media_format_set_audio_mime(format, MEDIA_FORMAT_VORBIS))
1006                         goto ERROR;
1007                 if (channels == 0)
1008                         channels = 2;   /* default */
1009                 if (media_format_set_audio_channel(format, channels))
1010                         goto ERROR;
1011                 if (rate == 0)
1012                         rate = 44100;   /* default */
1013                 if (media_format_set_audio_samplerate(format, rate))
1014                         goto ERROR;
1015                 if (bit == 0)
1016                         bit = 16;       /* default */
1017                 if (media_format_set_audio_bit(format, bit))
1018                         goto ERROR;
1019         } else {
1020                 MD_I("Audio mime not supported so far\n");
1021                 goto ERROR;
1022         }
1023         MEDIADEMUXER_FLEAVE();
1024         return ret;
1025 ERROR:
1026         MEDIADEMUXER_FLEAVE();
1027         return MD_ERROR;
1028 }
1029
1030 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1031                                                         media_format_h *format, int index)
1032 {
1033         MEDIADEMUXER_FENTER();
1034         int ret = MD_ERROR_NONE;
1035         MEDIADEMUXER_CHECK_NULL(pHandle);
1036         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1037
1038         track *temp = NULL;
1039         int loop;
1040         int count = 0;
1041         temp = (new_mediademuxer->info).head;
1042         loop = (new_mediademuxer->info).num_video_track +
1043                         (new_mediademuxer->info).num_audio_track +
1044                         (new_mediademuxer->info).num_subtitle_track +
1045                         (new_mediademuxer->info).num_other_track;
1046         if (index >= loop || index < 0) {
1047                 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1048                 ret = MD_ERROR;
1049                 goto ERROR;
1050         }
1051
1052         while (count != index) {
1053                 temp = temp->next;
1054                 count++;
1055         }
1056
1057         ret = media_format_create(&(temp->format));
1058         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1059                 MD_E("Mediaformat creation failed. returned %d\n", ret);
1060                 ret = MD_INTERNAL_ERROR;
1061                 goto ERROR;
1062         }
1063
1064         MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1065         MD_I("format ptr[%p]\n", temp->format);
1066         if (temp->caps_string[0] == 'a') {
1067                 MD_I("Setting for Audio \n");
1068                 _set_mime_audio(temp->format, temp);
1069         } else if (temp->caps_string[0] == 'v') {
1070                 MD_I("Setting for Video \n");
1071                 _set_mime_video(temp->format, temp);
1072         } else
1073                 MD_W("Not supported so far (except audio and video)\n");
1074
1075         ret = media_format_ref(temp->format);   /* increment the ref to retain the original content */
1076         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1077                 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1078                 ret = MD_INTERNAL_ERROR;
1079                 goto ERROR;
1080         }
1081         ret = media_format_make_writable(temp->format, format); /* copy the content */
1082         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1083                 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1084                 media_format_unref(temp->format);
1085                 ret = MD_INTERNAL_ERROR;
1086                 goto ERROR;
1087         }
1088
1089         MEDIADEMUXER_FLEAVE();
1090         return ret;
1091 ERROR:
1092         MEDIADEMUXER_FLEAVE();
1093         return ret;
1094 }
1095
1096 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1097                                                         GstBuffer *buffer, char *codec_data)
1098 {
1099         MEDIADEMUXER_FENTER();
1100         int ret = MD_ERROR_NONE;
1101         MEDIADEMUXER_CHECK_NULL(out_pkt);
1102         void *pkt_data;
1103         uint64_t size;
1104         GstMapInfo map;
1105
1106         if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1107                 MD_E("gst_buffer_map failed\n");
1108                 ret = MD_ERROR_UNKNOWN;
1109                 goto ERROR;
1110         }
1111         /* copy data */
1112         media_packet_get_buffer_size(out_pkt, &size);
1113         MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1114         if (size < (uint64_t)map.size) {
1115                 MD_W("Media packet Buffer capacity[%llu] is \
1116                         less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1117                 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1118                 media_packet_get_buffer_size(out_pkt, &size);
1119                 MD_I("Media packet Buffer NEW  capacity: %llu \n", size);
1120         }
1121         if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1122                 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1123                 ret = MD_ERROR_UNKNOWN;
1124                 goto ERROR;
1125         }
1126         memcpy((char *)pkt_data, map.data, map.size);
1127         if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1128                 MD_E("unable to set the pts\n");
1129                 ret = MD_ERROR_UNKNOWN;
1130                 goto ERROR;
1131         }
1132         if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1133                 MD_E("unable to set the dts\n");
1134                 ret = MD_ERROR_UNKNOWN;
1135                 goto ERROR;
1136         }
1137         if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1138                 MD_E("unable to set the duration\n");
1139                 ret = MD_ERROR_UNKNOWN;
1140                 goto ERROR;
1141         }
1142         if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1143                 MD_E("unable to set the buffer size\n");
1144                 ret = MD_ERROR_UNKNOWN;
1145                 goto ERROR;
1146         }
1147         if (media_packet_set_flags(out_pkt, GST_BUFFER_FLAGS(buffer))) {
1148                 MD_E("unable to set the buffer size\n");
1149                 ret = MD_ERROR_UNKNOWN;
1150                 goto ERROR;
1151         }
1152         if (codec_data) {
1153                 if (media_packet_set_codec_data(out_pkt, (void*) codec_data, strlen(codec_data))) {
1154                         MD_E("unable to set the codec data\n");
1155                         ret = MD_ERROR_UNKNOWN;
1156                         goto ERROR;
1157                 }
1158         }
1159 ERROR:
1160         gst_buffer_unmap(buffer, &map);
1161         MEDIADEMUXER_FLEAVE();
1162         return ret;
1163 }
1164
1165 static int gst_demuxer_read_sample(MMHandleType pHandle,
1166                                                 media_packet_h *outbuf, int track_indx)
1167 {
1168         MEDIADEMUXER_FENTER();
1169         int ret = MD_ERROR_NONE;
1170         MEDIADEMUXER_CHECK_NULL(pHandle);
1171         mdgst_handle_t *demuxer = (mdgst_handle_t *) pHandle;
1172
1173         media_packet_h mediabuf = NULL;
1174         int indx = 0;
1175         char *codec_data = NULL;
1176         char *temp_codec_data = NULL;
1177         int index = 0;
1178
1179         track *atrack = demuxer->info.head;
1180         if ((demuxer->selected_tracks)[track_indx] == false) {
1181                 MD_E("Track Not selected\n");
1182                 ret = MD_ERROR;
1183                 goto ERROR;
1184         }
1185         while (atrack) {
1186                 if (indx == track_indx)  /* Got the requird track details */
1187                         break;
1188                 if (atrack->next) {
1189                         track *next = atrack->next;
1190                         atrack = next;
1191                 } else {
1192                         MD_E("Invalid track Index\n");
1193                         ret = MD_ERROR_INVALID_ARGUMENT;
1194                         goto ERROR;
1195                 }
1196                 indx++;
1197         }
1198
1199         if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1200                         MD_E("media_packet_create_alloc failed\n");
1201                         ret = MD_ERROR;
1202                         goto ERROR;
1203                 }
1204
1205         if (indx != track_indx) {
1206                 MD_E("Invalid track Index\n");
1207                 ret = MD_ERROR_INVALID_ARGUMENT;
1208                 goto ERROR;
1209         }
1210         GstElement *sink = atrack->appsink;
1211         GstSample *sample = NULL;
1212         if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1213                 MD_W("End of stream (EOS) reached\n");
1214                 ret = MD_EOS;
1215                 goto ERROR;
1216         }
1217
1218         sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1219         if (sample == NULL) {
1220                 MD_E("gst_demuxer_read_sample failed\n");
1221                 ret = MD_ERROR_UNKNOWN;
1222         }
1223
1224         GstBuffer *buffer = gst_sample_get_buffer(sample);
1225         if (buffer == NULL) {
1226                 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1227                 ret = MD_ERROR_UNKNOWN;
1228                 goto ERROR;
1229         }
1230
1231         /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1232         temp_codec_data = strstr(atrack->caps_string, "codec_data");
1233         if (temp_codec_data != NULL) {
1234                 while (*temp_codec_data != ')')
1235                         temp_codec_data++;
1236                 temp_codec_data++; /* to esacpe ')' */
1237                 codec_data = (char*) malloc(sizeof(char)*strlen(temp_codec_data));
1238                 if (codec_data != NULL) {
1239                         while (*temp_codec_data != ',') {
1240                                 codec_data[index++] = *temp_codec_data;
1241                                 temp_codec_data++;
1242                         }
1243                         codec_data[index] = '\0';
1244                 }
1245         }
1246
1247         /* Fill the media_packet with proper information */
1248         ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data);
1249         gst_sample_unref(sample);
1250         *outbuf = mediabuf;
1251         if (codec_data)
1252                 free(codec_data);
1253
1254         MEDIADEMUXER_FLEAVE();
1255         return ret;
1256 ERROR:
1257         MEDIADEMUXER_FLEAVE();
1258         return ret;
1259 }
1260
1261 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1262 {
1263         MEDIADEMUXER_FENTER();
1264         MEDIADEMUXER_CHECK_NULL(pHandle);
1265         mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1266
1267         gint64 pos = 0, len = 0;
1268         gdouble rate = 1;
1269         if (gst_element_query_position(gst_handle->pipeline, GST_FORMAT_TIME, &pos) &&
1270              gst_element_query_duration(gst_handle->pipeline, GST_FORMAT_TIME, &len)) {
1271                 MD_I("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
1272                      GST_TIME_ARGS(pos),
1273                      GST_TIME_ARGS(len));
1274         }
1275         pos1 = pos + (pos1 * GST_SECOND);
1276
1277         MD_I("\n\n");
1278         MD_I("NEW Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
1279              GST_TIME_ARGS(pos1), GST_TIME_ARGS(len));
1280
1281         track_info *head_track = &(gst_handle->info);
1282         track *temp = head_track->head;
1283         int indx = 0;
1284         while (temp) {
1285                 MD_I("Got one element %p\n", temp->appsink);
1286                 if (gst_handle->selected_tracks[indx] == true) {
1287                         if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1288                              GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, pos1,
1289                              GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1290                                 MD_E("Seek failed!\n");
1291                                 goto ERROR;
1292                         } else {
1293                                 MD_I("Seek success\n");
1294                         }
1295                 }
1296                 indx++;
1297                 if (temp->next) {
1298                         track *next = temp->next;
1299                         temp = next;
1300                 } else {
1301                         temp = NULL;
1302                 }
1303         }
1304         MEDIADEMUXER_FLEAVE();
1305         return MD_ERROR_NONE;
1306 ERROR:
1307         MEDIADEMUXER_FLEAVE();
1308         return MD_ERROR;
1309 }
1310
1311 int _gst_unset_appsink(track *temp, int index, int loop)
1312 {
1313         MEDIADEMUXER_FENTER();
1314         int ret = MD_ERROR_NONE;
1315         int count = 0;
1316
1317         while (count != index) {
1318                 temp = temp->next;
1319                 count++;
1320         }
1321         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) 0);
1322         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1323         MEDIADEMUXER_FLEAVE();
1324         return ret;
1325 }
1326
1327 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1328 {
1329         MEDIADEMUXER_FENTER();
1330         int ret = MD_ERROR_NONE;
1331         MEDIADEMUXER_CHECK_NULL(pHandle);
1332         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1333
1334         if (track >= new_mediademuxer->total_tracks || track < 0) {
1335                 MD_E("total tracks is less then unselected track, So not support this track");
1336                 ret = MD_ERROR_INVALID_ARGUMENT;
1337                 goto ERROR;
1338         }
1339         new_mediademuxer->selected_tracks[track] = false;
1340         _gst_unset_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
1341                                         new_mediademuxer->total_tracks);
1342         MEDIADEMUXER_FLEAVE();
1343         return ret;
1344 ERROR:
1345         MEDIADEMUXER_FLEAVE();
1346         return ret;
1347 }
1348
1349 static int gst_demuxer_stop(MMHandleType pHandle)
1350 {
1351         MEDIADEMUXER_FENTER();
1352         int ret = MD_ERROR_NONE;
1353         MEDIADEMUXER_CHECK_NULL(pHandle);
1354         mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1355
1356         MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1357         if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1358             GST_STATE_CHANGE_FAILURE) {
1359                 MD_E("Failed to set into PAUSE state");
1360                 ret = MD_INTERNAL_ERROR;
1361                 goto ERROR;
1362         }
1363         MEDIADEMUXER_FLEAVE();
1364         return ret;
1365 ERROR:
1366         MEDIADEMUXER_FLEAVE();
1367         return ret;
1368 }
1369
1370 void  _gst_clear_struct(mdgst_handle_t *gst_handle)
1371 {
1372         MEDIADEMUXER_FENTER();
1373         if (gst_handle->selected_tracks) {
1374                 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1375                      gst_handle->selected_tracks);
1376                 g_free(gst_handle->selected_tracks);
1377                 gst_handle->selected_tracks = NULL;
1378         }
1379         if ((gst_handle->info).head)
1380                 __gst_free_stuct(&(gst_handle->info).head);
1381         MEDIADEMUXER_FLEAVE();
1382 }
1383
1384 int _md_gst_destroy_pipeline(GstElement *pipeline)
1385 {
1386         MEDIADEMUXER_FENTER();
1387         int ret = MD_ERROR_NONE;
1388         if (pipeline)
1389                 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1390         MEDIADEMUXER_FLEAVE();
1391         return ret;
1392 ERROR:
1393         if (pipeline)
1394                 gst_object_unref(GST_OBJECT(pipeline));
1395         MEDIADEMUXER_FLEAVE();
1396         return MD_ERROR;
1397 }
1398
1399 static int gst_demuxer_unprepare(MMHandleType pHandle)
1400 {
1401         MEDIADEMUXER_FENTER();
1402         int ret = MD_ERROR_NONE;
1403         MEDIADEMUXER_CHECK_NULL(pHandle);
1404         mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1405
1406         _gst_clear_struct(gst_handle);
1407         MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1408         if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1409                 ret = MD_ERROR;
1410                 goto ERROR;
1411         }
1412         MEDIADEMUXER_FLEAVE();
1413         return ret;
1414 ERROR:
1415         MEDIADEMUXER_FLEAVE();
1416         return ret;
1417 }
1418
1419 static int gst_demuxer_destroy(MMHandleType pHandle)
1420 {
1421         MEDIADEMUXER_FENTER();
1422         int ret = MD_ERROR_NONE;
1423         MEDIADEMUXER_CHECK_NULL(pHandle);
1424         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1425
1426         MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1427              new_mediademuxer);
1428         g_free(new_mediademuxer);
1429         MEDIADEMUXER_FLEAVE();
1430         return ret;
1431 }
1432
1433 int gst_set_error_cb(MMHandleType pHandle,
1434                         gst_error_cb callback, void *user_data)
1435 {
1436         MEDIADEMUXER_FENTER();
1437         int ret = MD_ERROR_NONE;
1438         MEDIADEMUXER_CHECK_NULL(pHandle);
1439         mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1440
1441         if (!gst_handle) {
1442                 MD_E("fail invaild param (gst_handle)\n");
1443                 ret = MD_INVALID_ARG;
1444                 goto ERROR;
1445         }
1446
1447         if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1448                 MD_E("Already set mediademuxer_error_cb\n");
1449                 ret = MD_ERROR_INVALID_ARGUMENT;
1450                 goto ERROR;
1451         } else {
1452                 if (!callback) {
1453                         MD_E("fail invaild argument (callback)\n");
1454                         ret = MD_ERROR_INVALID_ARGUMENT;
1455                         goto ERROR;
1456                 }
1457         }
1458
1459         MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1460
1461         gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb) callback;
1462         gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1463         MEDIADEMUXER_FLEAVE();
1464         return MD_ERROR_NONE;
1465 ERROR:
1466         MEDIADEMUXER_FLEAVE();
1467         return ret;
1468 }