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