Support avi file format
[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") || strstr(type, "x-msvideo")) {
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 if (strstr(type, "x-msvideo"))
620                                 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
621                         else
622                                 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
623
624                         if (!gst_handle->demux) {
625                                 gst_handle->is_valid_container = false;
626                                 MD_E("factory not able to create qtdemux\n");
627                                 goto ERROR;
628                         } else {
629                                 g_signal_connect(gst_handle->demux, "pad-added",
630                                                                 G_CALLBACK(__gst_on_pad_added), gst_handle);
631                                 g_signal_connect(gst_handle->demux, "no-more-pads",
632                                                                 G_CALLBACK(__gst_no_more_pad), gst_handle);
633                                 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
634                                                                 gst_handle->demux, NULL);
635                                 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
636                                 if (!pad) {
637                                         MD_E("fail to get typefind src pad.\n");
638                                         goto ERROR;
639                                 }
640                                 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
641                                 if (!demuxer_pad) {
642                                         MD_E("fail to get qtdemuc sink pad.\n");
643                                         goto ERROR;
644                                 }
645                                 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
646                                 if (!fake_pad) {
647                                         MD_E("fail to get fakesink sink pad.\n");
648                                         goto ERROR;
649                                 }
650                                 gst_pad_unlink(pad, fake_pad);
651                                 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
652                                 MEDIADEMUXER_SET_STATE(gst_handle->demux,
653                                                                         GST_STATE_PAUSED, ERROR);
654                                 if (pad)
655                                         gst_object_unref(pad);
656                                 if (demuxer_pad)
657                                         gst_object_unref(demuxer_pad);
658                                 if (fake_pad)
659                                         gst_object_unref(fake_pad);
660                         }
661                 } else if ((strstr(type, "adts"))
662                            || (strstr(type, "audio/mpeg"))
663                            || (strstr(type, "audio/x-wav"))
664                            || (strstr(type, "audio/x-flac"))
665                            || (strstr(type, "application/x-id3"))
666                            || (strstr(type, "audio/x-amr-nb-sh"))
667                            || (strstr(type, "audio/x-amr-wb-sh"))) {
668                         MD_I("Audio only format is found\n");
669                         __gst_create_audio_only_pipeline(data, caps);
670                 } else {
671                         gst_handle->is_valid_container = false;
672                         MD_E("Not supported container %s\n", type);
673                 }
674                 g_free(type);
675         }
676         MEDIADEMUXER_FLEAVE();
677         return;
678 ERROR:
679         gst_handle->is_valid_container = false;
680         if (gst_handle->demux)
681                 gst_object_unref(gst_handle->demux);
682         if (type)
683                 g_free(type);
684         if (pad)
685                 gst_object_unref(pad);
686         if (demuxer_pad)
687                 gst_object_unref(demuxer_pad);
688         if (fake_pad)
689                 gst_object_unref(fake_pad);
690         MEDIADEMUXER_FLEAVE();
691         return;
692 }
693
694 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
695 {
696         MEDIADEMUXER_FENTER();
697         int ret = MD_ERROR_NONE;
698         GstBus *bus = NULL;
699         char *path = NULL;
700         int remote_streaming = 0;
701         /* Initialize GStreamer */
702         /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
703         gst_init(NULL, NULL);
704
705         /* Create the empty pipeline */
706         gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
707         if (!gst_handle->pipeline) {
708                 MD_E("pipeline create fail");
709                 ret = MD_ERROR;
710                 goto ERROR;
711         }
712
713         /* Create the elements */
714         if ((path = strstr(uri, "http://"))) {
715                 gst_handle->filesrc  = gst_element_factory_make("souphttpsrc", NULL);
716                 remote_streaming = 1;
717                 MD_I("Source is http stream. \n");
718         } else {
719                 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
720                 MD_I("Source is file stream \n");
721         }
722         if (!gst_handle->filesrc) {
723                 MD_E("filesrc creation failed");
724                 ret = MD_ERROR;
725                 goto ERROR;
726         }
727
728         /* Modify the source's properties */
729         if (remote_streaming == 1)
730                 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
731         else
732                 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
733         gst_handle->typefind = gst_element_factory_make("typefind", NULL);
734         if (!gst_handle->typefind) {
735                 MD_E("typefind creation failed");
736                 ret = MD_ERROR;
737                 goto ERROR;
738         }
739         g_signal_connect(gst_handle->typefind, "have-type",
740                                         G_CALLBACK(__gst_cb_typefind), gst_handle);
741         gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
742         if (!gst_handle->fakesink) {
743                 MD_E("fakesink creation failed");
744                 ret = MD_ERROR;
745                 goto ERROR;
746         }
747
748         /* Build the pipeline */
749         gst_bin_add_many(GST_BIN(gst_handle->pipeline),
750                                                 gst_handle->filesrc,
751                                                 gst_handle->typefind,
752                                                 gst_handle->fakesink,
753                                                 NULL);
754         gst_element_link_many(gst_handle->filesrc,
755                                                         gst_handle->typefind,
756                                                         gst_handle->fakesink,
757                                                         NULL);
758
759         /* connect signals, bus watcher */
760         bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
761         gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
762         gst_handle->thread_default = g_main_context_get_thread_default();
763         gst_object_unref(GST_OBJECT(bus));
764
765         /* set pipeline state to PAUSED */
766         MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
767
768         int count = 0;
769         while (gst_handle->is_prepared != true) {
770                 count++;
771                 usleep(POLLING_INTERVAL);
772                 MD_I("Inside while loop\n");
773                 if (count > POLLING_INTERVAL) {
774                         MD_E("Error occure\n");
775                         ret = MD_ERROR;
776                         break;
777                 }
778         }
779
780         MEDIADEMUXER_FLEAVE();
781         return ret;
782 ERROR:
783         MEDIADEMUXER_FLEAVE();
784         return ret;
785 }
786
787 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
788 {
789         MEDIADEMUXER_FENTER();
790         int ret = MD_ERROR_NONE;
791         MEDIADEMUXER_CHECK_NULL(pHandle);
792         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
793
794         MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
795         ret = _gst_create_pipeline(new_mediademuxer, uri);
796         if (ret != MD_ERROR_NONE) {
797                 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
798                 goto ERROR;
799         }
800         MEDIADEMUXER_FLEAVE();
801         return ret;
802 ERROR:
803         MEDIADEMUXER_FLEAVE();
804         return ret;
805 }
806
807 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
808 {
809         MEDIADEMUXER_FENTER();
810         int ret = MD_ERROR_NONE;
811         MEDIADEMUXER_CHECK_NULL(pHandle);
812         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
813
814         *count = (new_mediademuxer->info).num_video_track +
815                         (new_mediademuxer->info).num_audio_track +
816                         (new_mediademuxer->info).num_subtitle_track +
817                         (new_mediademuxer->info).num_other_track;
818         MEDIADEMUXER_FLEAVE();
819         return ret;
820 }
821
822 int _gst_set_appsink(track *temp, int index, int loop)
823 {
824         MEDIADEMUXER_FENTER();
825         int ret = MD_ERROR_NONE;
826         int count = 0;
827
828         while (count != index) {
829                 temp = temp->next;
830                 count++;
831         }
832         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
833         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
834         MEDIADEMUXER_FLEAVE();
835         return ret;
836 }
837
838 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
839 {
840         MEDIADEMUXER_FENTER();
841         int ret = MD_ERROR_NONE;
842         MEDIADEMUXER_CHECK_NULL(pHandle);
843         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
844
845         MD_I("total_tracks (%d) :: selected  track (%d)", new_mediademuxer->total_tracks, track);
846         if (track >= new_mediademuxer->total_tracks || track < 0) {
847                 MD_E("total_tracks is less then selected track, So not support this track");
848                 ret = MD_ERROR_INVALID_ARGUMENT;
849                 goto ERROR;
850         }
851         new_mediademuxer->selected_tracks[track] = true;
852         _gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
853                                         new_mediademuxer->total_tracks);
854         MEDIADEMUXER_FLEAVE();
855         return MD_ERROR_NONE;
856 ERROR:
857         MEDIADEMUXER_FLEAVE();
858         return ret;
859 }
860
861 static int _gst_unlink_unselected_track(track *temp, int index)
862 {
863         MEDIADEMUXER_FENTER();
864         int ret = MD_ERROR_NONE;
865         int count = 0;
866         GstPad *queue_sink_pad = NULL;
867         while (count != index) {
868                 temp = temp->next;
869                 count++;
870         }
871         queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
872         if (!queue_sink_pad) {
873                 MD_E("queue_sink_pad of appsink not avaible\n");
874                 return MD_ERROR;
875         }
876         if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
877                 MD_W("demuxer is already unlinked from queue for track %d\n", index);
878
879         gst_object_unref(queue_sink_pad);
880         MEDIADEMUXER_FLEAVE();
881         return ret;
882 }
883
884 static int gst_demuxer_start(MMHandleType pHandle)
885 {
886         MEDIADEMUXER_FENTER();
887         int ret = MD_ERROR_NONE;
888         MEDIADEMUXER_CHECK_NULL(pHandle);
889         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
890
891         int indx;
892         for (indx = 0; indx < gst_handle->total_tracks; indx++) {
893                 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
894                         indx, gst_handle->selected_tracks[indx]);
895                 /*
896                 if (gst_handle->selected_tracks[indx] ==  false)
897                         _gst_demuxer_unset(pHandle, indx);
898                 */
899                 if (gst_handle->selected_tracks[indx] != true) {
900                         if (_gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
901                                 MD_E("Failed to unlink unselected tracks\n");
902                                 ret = MD_INTERNAL_ERROR;
903                                 goto ERROR;
904                         }
905                 }
906
907         }
908
909         track_info *head_track = &(gst_handle->info);
910         MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
911                         head_track->num_audio_track, head_track->num_video_track,
912                         head_track->num_subtitle_track);
913
914         track *temp = head_track->head;
915         indx = 0;
916         while (temp) {
917                 MD_I("Got one element %p\n", temp->appsink);
918                 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
919                         GST_STATE_CHANGE_FAILURE) {
920                         MD_E("Failed to set into PLAYING state");
921                         ret = MD_INTERNAL_ERROR;
922                         goto ERROR;
923                 }
924                 MD_I("set the state to playing\n");
925                 indx++;
926                 if (temp->next) {
927                         track *next = temp->next;
928                         temp = next;
929                 } else {
930                         temp = NULL;
931                 }
932         }
933
934         MD_I("gst_demuxer_start pipeine %p", gst_handle);
935         MEDIADEMUXER_FLEAVE();
936         return ret;
937 ERROR:
938         MEDIADEMUXER_FLEAVE();
939         return ret;
940 }
941
942 int _set_mime_text(media_format_h format, track *head)
943 {
944         MEDIADEMUXER_FENTER();
945         int ret = MD_ERROR_NONE;
946         GstStructure *struc = NULL;
947         struc = gst_caps_get_structure(head->caps, 0);
948         if (!struc) {
949                 MD_E("cannot get structure from caps.\n");
950                 goto ERROR;
951         }
952         if (gst_structure_has_name(struc, "text/x-raw")) {
953                 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
954                         goto ERROR;
955         } else {
956                 MD_I("Text mime not supported so far\n");
957                 goto ERROR;
958         }
959
960         MEDIADEMUXER_FLEAVE();
961         return ret;
962 ERROR:
963         MEDIADEMUXER_FLEAVE();
964         return MD_ERROR;
965 }
966
967 int _set_mime_video(media_format_h format, track *head)
968 {
969         MEDIADEMUXER_FENTER();
970         int ret = MD_ERROR_NONE;
971         GstStructure *struc = NULL;
972         int src_width;
973         int src_height;
974         int frame_rate_numerator = 0;
975         int frame_rate_denominator = 0;
976         media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
977         struc = gst_caps_get_structure(head->caps, 0);
978         if (!struc) {
979                 MD_E("cannot get structure from caps.\n");
980                 goto ERROR;
981         }
982         if (gst_structure_has_name(struc, "video/x-h264")) {
983                 mime_type = MEDIA_FORMAT_H264_SP;
984         } else if (gst_structure_has_name(struc, "video/x-h263")) {
985                 mime_type = MEDIA_FORMAT_H263;
986         } else if (gst_structure_has_name(struc, "video/mpeg")) {
987                 mime_type = MEDIA_FORMAT_MPEG4_SP;
988         } else {
989                 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
990                 goto ERROR;
991         }
992         if (media_format_set_video_mime(format, mime_type)) {
993                 MD_E("Unable to set video mime type (%x)\n", mime_type);
994                 goto ERROR;
995         }
996         gst_structure_get_int(struc, "width", &src_width);
997         gst_structure_get_int(struc, "height", &src_height);
998         if (media_format_set_video_width(format, src_width)) {
999                 MD_E("Unable to set video width\n");
1000                 goto ERROR;
1001         }
1002         if (media_format_set_video_height(format, src_height)) {
1003                 MD_E("Unable to set video height\n");
1004                 goto ERROR;
1005         }
1006         gst_structure_get_fraction(struc, "framerate",  &frame_rate_numerator, &frame_rate_denominator);
1007         if (media_format_set_video_frame_rate(format, frame_rate_numerator)) {
1008                 MD_E("Unable to set video frame rate\n");
1009                 goto ERROR;
1010         }
1011         MEDIADEMUXER_FLEAVE();
1012         return ret;
1013 ERROR:
1014         MEDIADEMUXER_FLEAVE();
1015         return MD_ERROR;
1016 }
1017
1018 int _set_mime_audio(media_format_h format, track *head)
1019 {
1020         MEDIADEMUXER_FENTER();
1021         int ret = MD_ERROR_NONE;
1022         GstStructure *struc = NULL;
1023         int rate = 0;
1024         int bit = 0;
1025         int channels = 0;
1026         int id3_flag = 0;
1027         const gchar *stream_format;
1028         media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1029
1030         struc = gst_caps_get_structure(head->caps, 0);
1031         if (!struc) {
1032                 MD_E("cannot get structure from caps.\n");
1033                 goto ERROR;
1034         }
1035
1036         if (gst_structure_has_name(struc, "application/x-id3"))
1037                 id3_flag = 1;
1038         if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1039                 gint mpegversion;
1040                 int layer;
1041                 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1042                 if (mpegversion == 4 || mpegversion == 2) {
1043                         mime_type = MEDIA_FORMAT_AAC_LC;
1044                         stream_format = gst_structure_get_string(struc, "stream-format");
1045                         if (strncmp(stream_format, "adts", 4) == 0)
1046                                 media_format_set_audio_aac_type(format, 1);
1047                         else
1048                                 media_format_set_audio_aac_type(format, 0);
1049                 } else if (mpegversion == 1 || id3_flag) {
1050                         gst_structure_get_int(struc, "layer", &layer);
1051                         if ((layer == 3) || (id3_flag == 1)) {
1052                                 mime_type = MEDIA_FORMAT_MP3;
1053                         } else {
1054                                 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1055                                 goto ERROR;
1056                         }
1057                 }
1058         } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1059                 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1060                 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1061                         mime_type = MEDIA_FORMAT_AMR_NB;
1062                         rate = 8000;
1063                 } else {
1064                         mime_type = MEDIA_FORMAT_AMR_WB;
1065                         rate = 16000;
1066                 }
1067         } else if (gst_structure_has_name(struc, "audio/AMR")) {
1068                 mime_type = MEDIA_FORMAT_AMR_NB;
1069         } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1070                 mime_type = MEDIA_FORMAT_AMR_WB;
1071         } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1072                 mime_type = MEDIA_FORMAT_PCM;
1073         } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1074                 mime_type = MEDIA_FORMAT_FLAC;
1075         } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1076                 mime_type = MEDIA_FORMAT_VORBIS;
1077         } else {
1078                 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1079                 goto ERROR;
1080         }
1081         if (media_format_set_audio_mime(format, mime_type))
1082                 goto ERROR;
1083         gst_structure_get_int(struc, "channels", &channels);
1084         if (channels == 0) {    /* default */
1085                 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1086                         channels = 1;
1087                 else
1088                         channels = 2;
1089         }
1090         if (media_format_set_audio_channel(format, channels))
1091                 goto ERROR;
1092         if (rate == 0)
1093                 gst_structure_get_int(struc, "rate", &rate);
1094         if (rate == 0)
1095                 rate = 44100;   /* default */
1096         if (media_format_set_audio_samplerate(format, rate))
1097                 goto ERROR;
1098         gst_structure_get_int(struc, "bit", &bit);
1099         if (bit == 0)
1100                 bit = 16;       /* default */
1101         if (media_format_set_audio_bit(format, bit))
1102                 goto ERROR;
1103         MEDIADEMUXER_FLEAVE();
1104         return ret;
1105 ERROR:
1106         MEDIADEMUXER_FLEAVE();
1107         return MD_ERROR;
1108 }
1109
1110 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1111                                                         media_format_h *format, int index)
1112 {
1113         MEDIADEMUXER_FENTER();
1114         int ret = MD_ERROR_NONE;
1115         MEDIADEMUXER_CHECK_NULL(pHandle);
1116         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1117
1118         track *temp = NULL;
1119         int loop;
1120         int count = 0;
1121         temp = (new_mediademuxer->info).head;
1122         loop = (new_mediademuxer->info).num_video_track +
1123                         (new_mediademuxer->info).num_audio_track +
1124                         (new_mediademuxer->info).num_subtitle_track +
1125                         (new_mediademuxer->info).num_other_track;
1126         if (index >= loop || index < 0) {
1127                 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1128                 ret = MD_ERROR;
1129                 goto ERROR;
1130         }
1131
1132         while (count != index) {
1133                 temp = temp->next;
1134                 count++;
1135         }
1136         if (temp->format != NULL) {
1137                 ret = media_format_ref(temp->format);
1138                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1139                         MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1140                         ret = MD_INTERNAL_ERROR;
1141                         goto ERROR;
1142                 }
1143                 ret = media_format_make_writable(temp->format, format); /* copy the content */
1144                 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1145                         MD_E("Mediaformat create copy failed. returned %d\n", ret);
1146                         media_format_unref(temp->format);
1147                         ret = MD_INTERNAL_ERROR;
1148                         goto ERROR;
1149                 }
1150                 MEDIADEMUXER_FLEAVE();
1151                 return ret;
1152         }
1153         ret = media_format_create(&(temp->format));
1154         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1155                 MD_E("Mediaformat creation failed. returned %d\n", ret);
1156                 ret = MD_INTERNAL_ERROR;
1157                 goto ERROR;
1158         }
1159
1160         MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1161         MD_I("format ptr[%p]\n", temp->format);
1162         if (temp->caps_string[0] == 'a') {
1163                 MD_I("Setting for Audio \n");
1164                 _set_mime_audio(temp->format, temp);
1165         } else if (temp->caps_string[0] == 'v') {
1166                 MD_I("Setting for Video \n");
1167                 _set_mime_video(temp->format, temp);
1168         } else if (temp->caps_string[0] == 't') {
1169                 MD_I("Setting for Subtitle\n");
1170                 _set_mime_text(temp->format, temp);
1171         } else {
1172                 MD_W("Not supported so far (except audio, video and subtitle)\n");
1173         }
1174
1175         ret = media_format_ref(temp->format);   /* increment the ref to retain the original content */
1176         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1177                 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1178                 ret = MD_INTERNAL_ERROR;
1179                 goto ERROR;
1180         }
1181         ret = media_format_make_writable(temp->format, format); /* copy the content */
1182         if (ret != MEDIA_FORMAT_ERROR_NONE) {
1183                 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1184                 media_format_unref(temp->format);
1185                 ret = MD_INTERNAL_ERROR;
1186                 goto ERROR;
1187         }
1188         MEDIADEMUXER_FLEAVE();
1189         return ret;
1190 ERROR:
1191         MEDIADEMUXER_FLEAVE();
1192         return ret;
1193 }
1194
1195 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1196                                                         GstBuffer *buffer, GstBuffer *codec_data)
1197 {
1198         MEDIADEMUXER_FENTER();
1199         int ret = MD_ERROR_NONE;
1200         MEDIADEMUXER_CHECK_NULL(out_pkt);
1201         void *pkt_data;
1202         uint64_t size;
1203         GstMapInfo map;
1204
1205         if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1206                 MD_E("gst_buffer_map failed\n");
1207                 ret = MD_ERROR_UNKNOWN;
1208                 goto ERROR;
1209         }
1210         /* copy data */
1211         media_packet_get_buffer_size(out_pkt, &size);
1212         MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1213         if (size < (uint64_t)map.size) {
1214                 MD_W("Media packet Buffer capacity[%llu] is \
1215                         less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1216                 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1217                 media_packet_get_buffer_size(out_pkt, &size);
1218                 MD_I("Media packet Buffer NEW  capacity: %llu \n", size);
1219         }
1220         if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1221                 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1222                 ret = MD_ERROR_UNKNOWN;
1223                 goto ERROR;
1224         }
1225         memcpy((char *)pkt_data, map.data, map.size);
1226         if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1227                 MD_E("unable to set the pts\n");
1228                 ret = MD_ERROR_UNKNOWN;
1229                 goto ERROR;
1230         }
1231         if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1232                 MD_E("unable to set the dts\n");
1233                 ret = MD_ERROR_UNKNOWN;
1234                 goto ERROR;
1235         }
1236         if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1237                 MD_E("unable to set the duration\n");
1238                 ret = MD_ERROR_UNKNOWN;
1239                 goto ERROR;
1240         }
1241         if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1242                 MD_E("unable to set the buffer size\n");
1243                 ret = MD_ERROR_UNKNOWN;
1244                 goto ERROR;
1245         }
1246         if (media_packet_set_flags(out_pkt, GST_BUFFER_FLAGS(buffer))) {
1247                 MD_E("unable to set the buffer size\n");
1248                 ret = MD_ERROR_UNKNOWN;
1249                 goto ERROR;
1250         }
1251         /* set codec data into media packet */
1252         if (codec_data) {
1253                 GstMapInfo codec_data_map;
1254                 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1255                         MD_E("codec data buffer map failed\n");
1256                         ret = MD_ERROR_UNKNOWN;
1257                         goto ERROR;
1258                 }
1259                 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1260                         (unsigned int)codec_data_map.size)) {
1261                         MD_E("unable to set the codec data\n");
1262                         ret = MD_ERROR_UNKNOWN;
1263                         gst_buffer_unmap(codec_data, &codec_data_map);
1264                         goto ERROR;
1265                 }
1266                 gst_buffer_unmap(codec_data, &codec_data_map);
1267
1268                 media_buffer_flags_e flags;
1269                 media_packet_get_flags(out_pkt, &flags);
1270                 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1271         }
1272 ERROR:
1273         gst_buffer_unmap(buffer, &map);
1274         MEDIADEMUXER_FLEAVE();
1275         return ret;
1276 }
1277
1278 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1279 {
1280         media_packet_h mediabuf = NULL;
1281         int ret = MD_ERROR_NONE;
1282
1283         MEDIADEMUXER_FENTER();
1284         if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1285                 MD_E("media_packet_create_alloc failed\n");
1286                 ret = MD_ERROR;
1287                 goto ERROR;
1288         }
1289
1290         if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1291                 MD_E("unable to set EOS flag\n");
1292                 ret = MD_ERROR_UNKNOWN;
1293                 goto ERROR;
1294         }
1295
1296         *outbuf = mediabuf;
1297         MEDIADEMUXER_FLEAVE();
1298
1299         return ret;
1300 ERROR:
1301         if (mediabuf)
1302                 media_packet_destroy(mediabuf);
1303         *outbuf = NULL;
1304         MEDIADEMUXER_FLEAVE();
1305         return ret;
1306 }
1307
1308 static int gst_demuxer_read_sample(MMHandleType pHandle,
1309                                                 media_packet_h *outbuf, int track_indx)
1310 {
1311         MEDIADEMUXER_FENTER();
1312         int ret = MD_ERROR_NONE;
1313         MEDIADEMUXER_CHECK_NULL(pHandle);
1314         mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1315
1316         media_packet_h mediabuf = NULL;
1317         int indx = 0;
1318
1319         track *atrack = demuxer->info.head;
1320         if ((demuxer->selected_tracks)[track_indx] == false) {
1321                 MD_E("Track Not selected\n");
1322                 ret = MD_ERROR;
1323                 goto ERROR;
1324         }
1325         while (atrack) {
1326                 if (indx == track_indx)  /* Got the requird track details */
1327                         break;
1328                 if (atrack->next) {
1329                         track *next = atrack->next;
1330                         atrack = next;
1331                 } else {
1332                         MD_E("Invalid track Index\n");
1333                         ret = MD_ERROR_INVALID_ARGUMENT;
1334                         goto ERROR;
1335                 }
1336                 indx++;
1337         }
1338
1339         if (!atrack) {
1340                 MD_E("atrack is NULL\n");
1341                 goto ERROR;
1342         }
1343
1344         if (indx != track_indx) {
1345                 MD_E("Invalid track Index\n");
1346                 ret = MD_ERROR_INVALID_ARGUMENT;
1347                 goto ERROR;
1348         }
1349         GstElement *sink = atrack->appsink;
1350         GstSample *sample = NULL;
1351
1352         sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1353         if (sample == NULL) {
1354                 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1355                         MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1356                         ret = MD_ERROR_NONE;
1357                         *outbuf = NULL;
1358                         __gst_eos_callback(track_indx, demuxer);
1359
1360                         //Make EOS packet
1361                         _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1362                         return ret;
1363                 } else {
1364                         MD_E("gst_demuxer_read_sample failed\n");
1365                         *outbuf = NULL;
1366                         ret = MD_ERROR_UNKNOWN;
1367                         return ret;
1368                 }
1369         }
1370
1371         if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1372                 MD_E("media_packet_create_alloc failed\n");
1373                 ret = MD_ERROR;
1374                 goto ERROR;
1375         }
1376
1377         GstBuffer *buffer = gst_sample_get_buffer(sample);
1378         if (buffer == NULL) {
1379                 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1380                 ret = MD_ERROR_UNKNOWN;
1381                 goto ERROR;
1382         }
1383
1384         GstBuffer *codec_data_buffer = NULL;
1385         /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1386         if (atrack->need_codec_data) {
1387                 atrack->need_codec_data = FALSE;
1388                 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1389                 GstStructure *structure = NULL;
1390                 const GValue *value = NULL;
1391
1392                 structure = gst_caps_get_structure(atrack->caps, 0);
1393                 /* get codec data from caps*/
1394                 value = gst_structure_get_value(structure, "codec_data");
1395                 if (value)
1396                         codec_data_buffer = gst_value_get_buffer(value);
1397         }
1398
1399         /* Fill the media_packet with proper information */
1400         ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1401         gst_sample_unref(sample);
1402         *outbuf = mediabuf;
1403
1404         MEDIADEMUXER_FLEAVE();
1405         return ret;
1406 ERROR:
1407         if (mediabuf)
1408                 media_packet_destroy(mediabuf);
1409         *outbuf = NULL;
1410         MEDIADEMUXER_FLEAVE();
1411         return ret;
1412 }
1413
1414 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1415 {
1416         MEDIADEMUXER_FENTER();
1417         MEDIADEMUXER_CHECK_NULL(pHandle);
1418         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1419
1420         gint64 pos = 0;
1421         gdouble rate = 1;
1422         track_info *head_track = &(gst_handle->info);
1423         track *temp = head_track->head;
1424         track *temp_track = head_track->head;
1425         int indx = 0;
1426
1427         /* Setting each appsink to paused state before seek */
1428         while (temp_track) {
1429                 if (gst_handle->selected_tracks[indx] == true) {
1430                         if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1431                                 MD_E("Failed to set into PAUSED state");
1432                                 goto ERROR;
1433                         }
1434                         MD_I("set the state to paused\n");
1435                 }
1436                 indx++;
1437                 if (temp_track->next) {
1438                         track *next = temp_track->next;
1439                         temp_track = next;
1440                 } else {
1441                         temp_track = NULL;
1442                 }
1443         }
1444
1445         pos = pos1 * GST_MSECOND;
1446
1447         MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1448
1449         indx = 0;
1450         while (temp) {
1451                 MD_I("Got one element %p\n", temp->appsink);
1452                 if (gst_handle->selected_tracks[indx] == true) {
1453                         temp->need_codec_data = TRUE;
1454                         if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1455                              GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1456                              GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1457                                 MD_E("Seek failed!\n");
1458                                 goto ERROR;
1459                         } else {
1460                                 MD_I("Seek success...setting appsink to playing state\n");
1461                                 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1462                                         MD_E("Failed to set into PLAYING state");
1463                                         goto ERROR;
1464                                 }
1465                         }
1466                 }
1467                 indx++;
1468                 if (temp->next) {
1469                         track *next = temp->next;
1470                         temp = next;
1471                 } else {
1472                         temp = NULL;
1473                 }
1474         }
1475         MEDIADEMUXER_FLEAVE();
1476         return MD_ERROR_NONE;
1477 ERROR:
1478         MEDIADEMUXER_FLEAVE();
1479         return MD_ERROR;
1480 }
1481
1482 int _gst_unset_appsink(track *temp, int index, int loop)
1483 {
1484         MEDIADEMUXER_FENTER();
1485         int ret = MD_ERROR_NONE;
1486         int count = 0;
1487
1488         while (count != index) {
1489                 temp = temp->next;
1490                 count++;
1491         }
1492         gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1493         gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1494         MEDIADEMUXER_FLEAVE();
1495         return ret;
1496 }
1497
1498 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1499 {
1500         MEDIADEMUXER_FENTER();
1501         int ret = MD_ERROR_NONE;
1502         MEDIADEMUXER_CHECK_NULL(pHandle);
1503         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1504
1505         if (track >= new_mediademuxer->total_tracks || track < 0) {
1506                 MD_E("total tracks is less then unselected track, So not support this track");
1507                 ret = MD_ERROR_INVALID_ARGUMENT;
1508                 goto ERROR;
1509         }
1510         new_mediademuxer->selected_tracks[track] = false;
1511         _gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1512                                         new_mediademuxer->total_tracks);
1513         MEDIADEMUXER_FLEAVE();
1514         return ret;
1515 ERROR:
1516         MEDIADEMUXER_FLEAVE();
1517         return ret;
1518 }
1519
1520 static int gst_demuxer_stop(MMHandleType pHandle)
1521 {
1522         MEDIADEMUXER_FENTER();
1523         int ret = MD_ERROR_NONE;
1524         MEDIADEMUXER_CHECK_NULL(pHandle);
1525         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1526
1527         MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1528         if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1529             GST_STATE_CHANGE_FAILURE) {
1530                 MD_E("Failed to set into PAUSE state");
1531                 ret = MD_INTERNAL_ERROR;
1532                 goto ERROR;
1533         }
1534         MEDIADEMUXER_FLEAVE();
1535         return ret;
1536 ERROR:
1537         MEDIADEMUXER_FLEAVE();
1538         return ret;
1539 }
1540
1541 void  _gst_clear_struct(mdgst_handle_t *gst_handle)
1542 {
1543         MEDIADEMUXER_FENTER();
1544         if (gst_handle->selected_tracks) {
1545                 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1546                      gst_handle->selected_tracks);
1547                 g_free(gst_handle->selected_tracks);
1548                 gst_handle->selected_tracks = NULL;
1549         }
1550         if ((gst_handle->info).head)
1551                 __gst_free_stuct(&(gst_handle->info).head);
1552         MEDIADEMUXER_FLEAVE();
1553 }
1554
1555 int _md_gst_destroy_pipeline(GstElement *pipeline)
1556 {
1557         MEDIADEMUXER_FENTER();
1558         int ret = MD_ERROR_NONE;
1559         if (pipeline)
1560                 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1561         if (pipeline)
1562                 gst_object_unref(GST_OBJECT(pipeline));
1563         MEDIADEMUXER_FLEAVE();
1564         return ret;
1565 ERROR:
1566         if (pipeline)
1567                 gst_object_unref(GST_OBJECT(pipeline));
1568         MEDIADEMUXER_FLEAVE();
1569         return MD_ERROR;
1570 }
1571
1572 static int gst_demuxer_unprepare(MMHandleType pHandle)
1573 {
1574         MEDIADEMUXER_FENTER();
1575         int ret = MD_ERROR_NONE;
1576         MEDIADEMUXER_CHECK_NULL(pHandle);
1577         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1578
1579         _gst_clear_struct(gst_handle);
1580         if (gst_handle->bus_watch_id) {
1581                 GSource *source = NULL;
1582                 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1583                 if (source) {
1584                         g_source_destroy(source);
1585                         LOGD("Deallocation bus watch id");
1586                 }
1587         }
1588
1589         MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1590         if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1591                 ret = MD_ERROR;
1592                 goto ERROR;
1593         }
1594         MEDIADEMUXER_FLEAVE();
1595         return ret;
1596 ERROR:
1597         MEDIADEMUXER_FLEAVE();
1598         return ret;
1599 }
1600
1601 static int gst_demuxer_destroy(MMHandleType pHandle)
1602 {
1603         MEDIADEMUXER_FENTER();
1604         int ret = MD_ERROR_NONE;
1605         MEDIADEMUXER_CHECK_NULL(pHandle);
1606         mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1607
1608         MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1609              new_mediademuxer);
1610         g_free(new_mediademuxer);
1611         MEDIADEMUXER_FLEAVE();
1612         return ret;
1613 }
1614
1615 int gst_set_error_cb(MMHandleType pHandle,
1616                         gst_error_cb callback, void *user_data)
1617 {
1618         MEDIADEMUXER_FENTER();
1619         int ret = MD_ERROR_NONE;
1620         MEDIADEMUXER_CHECK_NULL(pHandle);
1621         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1622
1623         if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1624                 MD_E("Already set mediademuxer_error_cb\n");
1625                 ret = MD_ERROR_INVALID_ARGUMENT;
1626                 goto ERROR;
1627         } else {
1628                 if (!callback) {
1629                         MD_E("fail invaild argument (callback)\n");
1630                         ret = MD_ERROR_INVALID_ARGUMENT;
1631                         goto ERROR;
1632                 }
1633         }
1634
1635         MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1636
1637         gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1638         gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1639         MEDIADEMUXER_FLEAVE();
1640         return MD_ERROR_NONE;
1641 ERROR:
1642         MEDIADEMUXER_FLEAVE();
1643         return ret;
1644 }
1645
1646 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1647 {
1648         MEDIADEMUXER_FENTER();
1649         int ret = MD_ERROR_NONE;
1650         MEDIADEMUXER_CHECK_NULL(pHandle);
1651         mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1652
1653         if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1654                 MD_E("Already set mediademuxer_eos_cb\n");
1655                 ret = MD_ERROR_INVALID_ARGUMENT;
1656                 goto ERROR;
1657         } else {
1658                 if (!callback) {
1659                         MD_E("fail invaild argument (callback)\n");
1660                         ret = MD_ERROR_INVALID_ARGUMENT;
1661                         goto ERROR;
1662                 }
1663         }
1664
1665         MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1666         gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1667         gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1668         MEDIADEMUXER_FLEAVE();
1669         return MD_ERROR_NONE;
1670 ERROR:
1671         MEDIADEMUXER_FLEAVE();
1672         return ret;
1673 }
1674
1675 static int __gst_eos_callback(int track_num, void* user_data)
1676 {
1677         if (user_data == NULL) {
1678                 MD_E("Invalid argument");
1679                 return MD_ERROR;
1680         }
1681         mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1682         if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1683                 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1684                                         gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1685         else
1686                 MD_E("EOS received, but callback is not set!!!");
1687         return MD_ERROR_NONE;
1688 }