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