2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * @file mediademuxer_port_gst.c
19 * @brief Handling for GStreamer Port, defined function and there implementation
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>
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);
50 /* Media Demuxer API common */
51 static media_port_demuxer_ops def_demux_ops = {
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,
69 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
71 MEDIADEMUXER_FENTER();
72 int ret = MD_ERROR_NONE;
73 MEDIADEMUXER_CHECK_NULL(pOps);
74 def_demux_ops.n_size = sizeof(def_demux_ops);
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));
80 MEDIADEMUXER_FLEAVE();
84 static int gst_demuxer_init(MMHandleType *pHandle)
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");
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();
108 MEDIADEMUXER_FLEAVE();
112 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
114 MEDIADEMUXER_FENTER();
115 int ret = MD_ERROR_NONE;
116 switch (GST_MESSAGE_TYPE(msg)) {
117 case GST_MESSAGE_EOS: {
121 case GST_MESSAGE_ERROR: {
122 GError *error = NULL;
123 gst_message_parse_error(msg, &error, NULL);
125 MD_I("GST error message parsing failed");
128 MD_E("Error: %s\n", error->message);
135 MEDIADEMUXER_FLEAVE();
139 static void __gst_no_more_pad(GstElement *element, gpointer data)
141 MEDIADEMUXER_FENTER();
142 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
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__);
153 for (loop_track = 0; loop_track < gst_handle->total_tracks;
155 gst_handle->selected_tracks[loop_track] = false;
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);
163 MD_I("track caps[%s]\n", head->name);
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();
172 void __gst_free_stuct(track **head)
174 MEDIADEMUXER_FENTER();
180 MD_I("deallocate GST_PAD %p\n", temp->pad);
181 gst_object_unref(temp->pad);
184 MD_I("deallocate GST_PAD caps_ %p\n", temp->caps);
185 gst_caps_unref(temp->caps);
188 MD_I("deallocate GST_PAD name %p\n", temp->name);
191 if (temp->caps_string) {
192 MD_I("deallocate GST_PAD caps_string %p\n",
194 g_free(temp->caps_string);
197 MD_I("unref media_format %p\n", temp->format);
198 media_format_unref(temp->format);
201 track *next = temp->next;
202 MD_I("deallocate memory %p\n", temp);
206 MD_I("deallocate memory %p\n", temp);
212 MEDIADEMUXER_FLEAVE();
215 int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
216 GstElement *pipeline)
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;
227 temp = (track *)(g_malloc(sizeof(track)));
229 MD_E("Not able to allocate memory");
232 MD_I("allocate memory %p", temp);
235 temp->caps = gst_pad_get_current_caps(pad);
237 temp->caps_string = gst_caps_to_string(temp->caps);
240 temp->need_codec_data = TRUE;
242 /* Link demuxer - queue */
243 temp->queue = gst_element_factory_make("queue", NULL);
245 MD_E("factory not able to make queue");
249 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
250 MD_E("fail add queue in pipeline");
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");
260 MEDIADEMUXER_SET_STATE(temp->queue, GST_STATE_PAUSED, ERROR);
261 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
263 temp->appsink = gst_element_factory_make("appsink", NULL);
264 if (!temp->appsink) {
265 MD_E("factory not able to make appsink");
269 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
270 MD_E("fail add queue in pipeline");
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);
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");
283 apppad = gst_element_get_static_pad(temp->appsink, "sink");
285 MD_E("sink pad of appsink not avaible");
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");
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");
302 g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
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");
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);
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);
324 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
327 } else if (strstr(name, "audio")) {
329 if (strstr(temp->caps_string, "audio/mpeg")) {
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);
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");
356 MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
358 /* Link demuxer pad with sink pad of parse element */
359 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
361 /* Link src pad with appSink element */
362 gst_element_link(parse_element, temp->appsink);
364 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
366 /* gst_pad_link(pad, fpad) */
376 gst_object_unref(queue_sink_pad);
378 gst_object_unref(queue_src_pad);
380 gst_object_unref(apppad);
382 gst_object_unref(parse_sink_pad);
383 MEDIADEMUXER_FLEAVE();
384 return MD_ERROR_NONE;
388 gst_object_unref(parse_element);
390 gst_object_unref(temp->caps);
391 if (temp->caps_string)
392 g_free(temp->caps_string);
394 gst_object_unref(temp->queue);
396 gst_object_unref(temp->appsink);
398 gst_object_unref(queue_sink_pad);
400 gst_object_unref(queue_src_pad);
402 gst_object_unref(apppad);
404 gst_object_unref(parse_sink_pad);
405 __gst_free_stuct(head);
406 MEDIADEMUXER_FLEAVE();
410 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
412 MEDIADEMUXER_FENTER();
413 MD_I("Dynamic pad created, linking demuxer/decoder\n");
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)
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));
429 tmp = head_track->head;
432 if (!tmp || !tmp->caps_string) {
433 MD_I("trak or trak caps_string is NULL\n");
434 MEDIADEMUXER_FLEAVE();
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)++;
447 MD_W("found Pad %s\n", name);
448 (head_track->num_other_track)++;
450 MEDIADEMUXER_FLEAVE();
453 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
455 MEDIADEMUXER_FENTER();
456 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
458 GstPad *aud_pad = NULL;
459 GstPad *aud_srcpad = NULL;
460 GstPad *fake_pad = NULL;
461 GstElement *id3tag = NULL;
464 track_info *head_track = &(gst_handle->info);
465 track *tmp_track = NULL;
467 gst_handle->is_valid_container = true;
469 type = gst_caps_to_string(caps);
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);
487 if (!gst_handle->demux) {
488 gst_handle->is_valid_container = false;
489 MD_E("factory not able to create audio parse element\n");
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");
496 MD_E("fail to get typefind src pad.\n");
500 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
502 MD_E("fail to get fakesink sink pad.\n");
505 gst_pad_unlink(pad, fake_pad);
508 gst_object_unref(fake_pad);
511 aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
513 aud_pad = gst_element_get_static_pad(id3tag, "sink");
515 MD_E("fail to get audio parse sink pad.\n");
519 MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
521 gst_object_unref(pad);
523 gst_object_unref(aud_pad);
526 MEDIADEMUXER_SET_STATE(gst_handle->demux, GST_STATE_PAUSED, ERROR);
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);
534 gst_handle->total_tracks++;
536 aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
538 MD_E("fail to get audioparse source pad.\n");
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));
553 tmp_track = head_track->head;
554 while (tmp_track != NULL && aud_srcpad != tmp_track->pad)
555 tmp_track = tmp_track->next;
557 if (tmp_track != NULL) {
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);
566 g_free(tmp_track->name);
567 g_strlcpy(name, "audio", strlen(name));
568 tmp_track->name = name;
571 (head_track->num_audio_track)++;
575 gst_object_unref(aud_srcpad);
577 __gst_no_more_pad(gst_handle->demux, data);
579 MEDIADEMUXER_FLEAVE();
580 return MD_ERROR_NONE;
583 gst_handle->is_valid_container = false;
584 if (gst_handle->demux)
585 gst_object_unref(gst_handle->demux);
587 gst_object_unref(pad);
589 gst_object_unref(aud_pad);
591 gst_object_unref(fake_pad);
593 gst_object_unref(aud_srcpad);
596 MEDIADEMUXER_FLEAVE();
600 static void __gst_cb_typefind(GstElement *tf, guint probability,
601 GstCaps *caps, gpointer data)
603 MEDIADEMUXER_FENTER();
604 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
606 GstPad *demuxer_pad = NULL;
607 GstPad *fake_pad = NULL;
609 type = gst_caps_to_string(caps);
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);
622 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
624 if (!gst_handle->demux) {
625 gst_handle->is_valid_container = false;
626 MD_E("factory not able to create qtdemux\n");
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");
637 MD_E("fail to get typefind src pad.\n");
640 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
642 MD_E("fail to get qtdemuc sink pad.\n");
645 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
647 MD_E("fail to get fakesink sink pad.\n");
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);
655 gst_object_unref(pad);
657 gst_object_unref(demuxer_pad);
659 gst_object_unref(fake_pad);
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);
671 gst_handle->is_valid_container = false;
672 MD_E("Not supported container %s\n", type);
676 MEDIADEMUXER_FLEAVE();
679 gst_handle->is_valid_container = false;
680 if (gst_handle->demux)
681 gst_object_unref(gst_handle->demux);
685 gst_object_unref(pad);
687 gst_object_unref(demuxer_pad);
689 gst_object_unref(fake_pad);
690 MEDIADEMUXER_FLEAVE();
694 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
696 MEDIADEMUXER_FENTER();
697 int ret = MD_ERROR_NONE;
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);
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");
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");
719 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
720 MD_I("Source is file stream \n");
722 if (!gst_handle->filesrc) {
723 MD_E("filesrc creation failed");
728 /* Modify the source's properties */
729 if (remote_streaming == 1)
730 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
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");
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");
748 /* Build the pipeline */
749 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
751 gst_handle->typefind,
752 gst_handle->fakesink,
754 gst_element_link_many(gst_handle->filesrc,
755 gst_handle->typefind,
756 gst_handle->fakesink,
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));
765 /* set pipeline state to PAUSED */
766 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
769 while (gst_handle->is_prepared != true) {
771 usleep(POLLING_INTERVAL);
772 MD_I("Inside while loop\n");
773 if (count > POLLING_INTERVAL) {
774 MD_E("Error occure\n");
780 MEDIADEMUXER_FLEAVE();
783 MEDIADEMUXER_FLEAVE();
787 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
789 MEDIADEMUXER_FENTER();
790 int ret = MD_ERROR_NONE;
791 MEDIADEMUXER_CHECK_NULL(pHandle);
792 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
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);
800 MEDIADEMUXER_FLEAVE();
803 MEDIADEMUXER_FLEAVE();
807 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
809 MEDIADEMUXER_FENTER();
810 int ret = MD_ERROR_NONE;
811 MEDIADEMUXER_CHECK_NULL(pHandle);
812 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
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();
822 int _gst_set_appsink(track *temp, int index, int loop)
824 MEDIADEMUXER_FENTER();
825 int ret = MD_ERROR_NONE;
828 while (count != index) {
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();
838 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
840 MEDIADEMUXER_FENTER();
841 int ret = MD_ERROR_NONE;
842 MEDIADEMUXER_CHECK_NULL(pHandle);
843 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
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;
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;
857 MEDIADEMUXER_FLEAVE();
861 static int _gst_unlink_unselected_track(track *temp, int index)
863 MEDIADEMUXER_FENTER();
864 int ret = MD_ERROR_NONE;
866 GstPad *queue_sink_pad = NULL;
867 while (count != index) {
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");
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);
879 gst_object_unref(queue_sink_pad);
880 MEDIADEMUXER_FLEAVE();
884 static int gst_demuxer_start(MMHandleType pHandle)
886 MEDIADEMUXER_FENTER();
887 int ret = MD_ERROR_NONE;
888 MEDIADEMUXER_CHECK_NULL(pHandle);
889 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
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]);
896 if (gst_handle->selected_tracks[indx] == false)
897 _gst_demuxer_unset(pHandle, indx);
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;
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);
914 track *temp = head_track->head;
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;
924 MD_I("set the state to playing\n");
927 track *next = temp->next;
934 MD_I("gst_demuxer_start pipeine %p", gst_handle);
935 MEDIADEMUXER_FLEAVE();
938 MEDIADEMUXER_FLEAVE();
942 int _set_mime_text(media_format_h format, track *head)
944 MEDIADEMUXER_FENTER();
945 int ret = MD_ERROR_NONE;
946 GstStructure *struc = NULL;
947 struc = gst_caps_get_structure(head->caps, 0);
949 MD_E("cannot get structure from caps.\n");
952 if (gst_structure_has_name(struc, "text/x-raw")) {
953 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
956 MD_I("Text mime not supported so far\n");
960 MEDIADEMUXER_FLEAVE();
963 MEDIADEMUXER_FLEAVE();
967 int _set_mime_video(media_format_h format, track *head)
969 MEDIADEMUXER_FENTER();
970 int ret = MD_ERROR_NONE;
971 GstStructure *struc = NULL;
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);
979 MD_E("cannot get structure from caps.\n");
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;
989 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
992 if (media_format_set_video_mime(format, mime_type)) {
993 MD_E("Unable to set video mime type (%x)\n", mime_type);
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");
1002 if (media_format_set_video_height(format, src_height)) {
1003 MD_E("Unable to set video height\n");
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");
1011 MEDIADEMUXER_FLEAVE();
1014 MEDIADEMUXER_FLEAVE();
1018 int _set_mime_audio(media_format_h format, track *head)
1020 MEDIADEMUXER_FENTER();
1021 int ret = MD_ERROR_NONE;
1022 GstStructure *struc = NULL;
1027 const gchar *stream_format;
1028 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1030 struc = gst_caps_get_structure(head->caps, 0);
1032 MD_E("cannot get structure from caps.\n");
1036 if (gst_structure_has_name(struc, "application/x-id3"))
1038 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
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);
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;
1054 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
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;
1064 mime_type = MEDIA_FORMAT_AMR_WB;
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;
1078 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1081 if (media_format_set_audio_mime(format, mime_type))
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)
1090 if (media_format_set_audio_channel(format, channels))
1093 gst_structure_get_int(struc, "rate", &rate);
1095 rate = 44100; /* default */
1096 if (media_format_set_audio_samplerate(format, rate))
1098 gst_structure_get_int(struc, "bit", &bit);
1100 bit = 16; /* default */
1101 if (media_format_set_audio_bit(format, bit))
1103 MEDIADEMUXER_FLEAVE();
1106 MEDIADEMUXER_FLEAVE();
1110 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1111 media_format_h *format, int index)
1113 MEDIADEMUXER_FENTER();
1114 int ret = MD_ERROR_NONE;
1115 MEDIADEMUXER_CHECK_NULL(pHandle);
1116 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
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");
1132 while (count != index) {
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;
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;
1150 MEDIADEMUXER_FLEAVE();
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;
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);
1172 MD_W("Not supported so far (except audio, video and subtitle)\n");
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;
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;
1188 MEDIADEMUXER_FLEAVE();
1191 MEDIADEMUXER_FLEAVE();
1195 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1196 GstBuffer *buffer, GstBuffer *codec_data)
1198 MEDIADEMUXER_FENTER();
1199 int ret = MD_ERROR_NONE;
1200 MEDIADEMUXER_CHECK_NULL(out_pkt);
1205 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1206 MD_E("gst_buffer_map failed\n");
1207 ret = MD_ERROR_UNKNOWN;
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);
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;
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;
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;
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;
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;
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;
1251 /* set codec data into media packet */
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;
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);
1266 gst_buffer_unmap(codec_data, &codec_data_map);
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);
1273 gst_buffer_unmap(buffer, &map);
1274 MEDIADEMUXER_FLEAVE();
1278 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1280 media_packet_h mediabuf = NULL;
1281 int ret = MD_ERROR_NONE;
1283 MEDIADEMUXER_FENTER();
1284 if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1285 MD_E("media_packet_create_alloc failed\n");
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;
1297 MEDIADEMUXER_FLEAVE();
1302 media_packet_destroy(mediabuf);
1304 MEDIADEMUXER_FLEAVE();
1308 static int gst_demuxer_read_sample(MMHandleType pHandle,
1309 media_packet_h *outbuf, int track_indx)
1311 MEDIADEMUXER_FENTER();
1312 int ret = MD_ERROR_NONE;
1313 MEDIADEMUXER_CHECK_NULL(pHandle);
1314 mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1316 media_packet_h mediabuf = NULL;
1319 track *atrack = demuxer->info.head;
1320 if ((demuxer->selected_tracks)[track_indx] == false) {
1321 MD_E("Track Not selected\n");
1326 if (indx == track_indx) /* Got the requird track details */
1329 track *next = atrack->next;
1332 MD_E("Invalid track Index\n");
1333 ret = MD_ERROR_INVALID_ARGUMENT;
1340 MD_E("atrack is NULL\n");
1344 if (indx != track_indx) {
1345 MD_E("Invalid track Index\n");
1346 ret = MD_ERROR_INVALID_ARGUMENT;
1349 GstElement *sink = atrack->appsink;
1350 GstSample *sample = NULL;
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;
1358 __gst_eos_callback(track_indx, demuxer);
1361 _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1364 MD_E("gst_demuxer_read_sample failed\n");
1366 ret = MD_ERROR_UNKNOWN;
1371 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1372 MD_E("media_packet_create_alloc failed\n");
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;
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;
1392 structure = gst_caps_get_structure(atrack->caps, 0);
1393 /* get codec data from caps*/
1394 value = gst_structure_get_value(structure, "codec_data");
1396 codec_data_buffer = gst_value_get_buffer(value);
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);
1404 MEDIADEMUXER_FLEAVE();
1408 media_packet_destroy(mediabuf);
1410 MEDIADEMUXER_FLEAVE();
1414 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1416 MEDIADEMUXER_FENTER();
1417 MEDIADEMUXER_CHECK_NULL(pHandle);
1418 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1422 track_info *head_track = &(gst_handle->info);
1423 track *temp = head_track->head;
1424 track *temp_track = head_track->head;
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");
1434 MD_I("set the state to paused\n");
1437 if (temp_track->next) {
1438 track *next = temp_track->next;
1445 pos = pos1 * GST_MSECOND;
1447 MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
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");
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");
1469 track *next = temp->next;
1475 MEDIADEMUXER_FLEAVE();
1476 return MD_ERROR_NONE;
1478 MEDIADEMUXER_FLEAVE();
1482 int _gst_unset_appsink(track *temp, int index, int loop)
1484 MEDIADEMUXER_FENTER();
1485 int ret = MD_ERROR_NONE;
1488 while (count != index) {
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();
1498 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1500 MEDIADEMUXER_FENTER();
1501 int ret = MD_ERROR_NONE;
1502 MEDIADEMUXER_CHECK_NULL(pHandle);
1503 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
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;
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();
1516 MEDIADEMUXER_FLEAVE();
1520 static int gst_demuxer_stop(MMHandleType pHandle)
1522 MEDIADEMUXER_FENTER();
1523 int ret = MD_ERROR_NONE;
1524 MEDIADEMUXER_CHECK_NULL(pHandle);
1525 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
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;
1534 MEDIADEMUXER_FLEAVE();
1537 MEDIADEMUXER_FLEAVE();
1541 void _gst_clear_struct(mdgst_handle_t *gst_handle)
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;
1550 if ((gst_handle->info).head)
1551 __gst_free_stuct(&(gst_handle->info).head);
1552 MEDIADEMUXER_FLEAVE();
1555 int _md_gst_destroy_pipeline(GstElement *pipeline)
1557 MEDIADEMUXER_FENTER();
1558 int ret = MD_ERROR_NONE;
1560 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1562 gst_object_unref(GST_OBJECT(pipeline));
1563 MEDIADEMUXER_FLEAVE();
1567 gst_object_unref(GST_OBJECT(pipeline));
1568 MEDIADEMUXER_FLEAVE();
1572 static int gst_demuxer_unprepare(MMHandleType pHandle)
1574 MEDIADEMUXER_FENTER();
1575 int ret = MD_ERROR_NONE;
1576 MEDIADEMUXER_CHECK_NULL(pHandle);
1577 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
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);
1584 g_source_destroy(source);
1585 LOGD("Deallocation bus watch id");
1589 MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1590 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1594 MEDIADEMUXER_FLEAVE();
1597 MEDIADEMUXER_FLEAVE();
1601 static int gst_demuxer_destroy(MMHandleType pHandle)
1603 MEDIADEMUXER_FENTER();
1604 int ret = MD_ERROR_NONE;
1605 MEDIADEMUXER_CHECK_NULL(pHandle);
1606 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1608 MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1610 g_free(new_mediademuxer);
1611 MEDIADEMUXER_FLEAVE();
1615 int gst_set_error_cb(MMHandleType pHandle,
1616 gst_error_cb callback, void *user_data)
1618 MEDIADEMUXER_FENTER();
1619 int ret = MD_ERROR_NONE;
1620 MEDIADEMUXER_CHECK_NULL(pHandle);
1621 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
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;
1629 MD_E("fail invaild argument (callback)\n");
1630 ret = MD_ERROR_INVALID_ARGUMENT;
1635 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
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;
1642 MEDIADEMUXER_FLEAVE();
1646 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1648 MEDIADEMUXER_FENTER();
1649 int ret = MD_ERROR_NONE;
1650 MEDIADEMUXER_CHECK_NULL(pHandle);
1651 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
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;
1659 MD_E("fail invaild argument (callback)\n");
1660 ret = MD_ERROR_INVALID_ARGUMENT;
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;
1671 MEDIADEMUXER_FLEAVE();
1675 static int __gst_eos_callback(int track_num, void* user_data)
1677 if (user_data == NULL) {
1678 MD_E("Invalid argument");
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]);
1686 MD_E("EOS received, but callback is not set!!!");
1687 return MD_ERROR_NONE;