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_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);
241 /* Link demuxer - queue */
242 temp->queue = gst_element_factory_make("queue", NULL);
244 MD_E("factory not able to make queue");
248 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
249 MD_E("fail add queue in pipeline");
253 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
254 if (!queue_sink_pad) {
255 MD_E("queue_sink_pad of appsink not avaible");
259 MEDIADEMUXER_SET_STATE(temp->queue, GST_STATE_PAUSED, ERROR);
260 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
262 temp->appsink = gst_element_factory_make("appsink", NULL);
263 if (!temp->appsink) {
264 MD_E("factory not able to make appsink");
268 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
269 MD_E("fail add queue in pipeline");
273 gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
274 gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
275 MEDIADEMUXER_SET_STATE(temp->appsink, GST_STATE_PAUSED, ERROR);
277 queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
278 if (!queue_src_pad) {
279 MD_E("queue_src_pad of appsink not avaible");
282 apppad = gst_element_get_static_pad(temp->appsink, "sink");
284 MD_E("sink pad of appsink not avaible");
287 /* Check for type video and it should be h264 */
288 if (strstr(name, "video") && strstr(temp->caps_string, "h264")) {
289 parse_element = gst_element_factory_make("h264parse", NULL);
290 if (!parse_element) {
291 MD_E("factory not able to make h264parse");
294 gst_bin_add_many(GST_BIN(pipeline), parse_element, NULL);
295 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
296 if (!parse_sink_pad) {
297 gst_object_unref(parse_element);
298 MD_E("sink pad of h264parse not available");
302 MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
304 /* Link demuxer pad with sink pad of parse element */
305 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
307 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
308 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
309 gst_caps_unref(outcaps);
311 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
313 /* gst_pad_link(pad, fpad) */
323 gst_object_unref(queue_sink_pad);
325 gst_object_unref(queue_src_pad);
327 gst_object_unref(apppad);
329 gst_object_unref(parse_sink_pad);
330 MEDIADEMUXER_FLEAVE();
331 return MD_ERROR_NONE;
335 gst_object_unref(temp->caps);
336 if (temp->caps_string)
337 g_free(temp->caps_string);
339 gst_object_unref(temp->queue);
341 gst_object_unref(temp->appsink);
343 gst_object_unref(queue_sink_pad);
345 gst_object_unref(queue_src_pad);
347 gst_object_unref(apppad);
349 gst_object_unref(parse_sink_pad);
350 __gst_free_stuct(head);
351 MEDIADEMUXER_FLEAVE();
355 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
357 MEDIADEMUXER_FENTER();
358 MD_I("Dynamic pad created, linking demuxer/decoder\n");
360 mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
361 track_info *head_track = &(gst_handle->info);
362 gchar *name = gst_pad_get_name(pad);
363 gst_handle->total_tracks++;
364 if (__gst_add_track_info(pad, name, &(head_track->head), gst_handle->pipeline)
366 MD_E("unable to added track info");
367 head_track->num_audio_track = 0;
368 head_track->num_video_track = 0;
369 head_track->num_subtitle_track = 0;
370 head_track->num_other_track = 0;
371 __gst_free_stuct(&(head_track->head));
374 tmp = head_track->head;
377 if (!tmp || !tmp->caps_string) {
378 MD_I("trak or trak caps_string is NULL\n");
379 MEDIADEMUXER_FLEAVE();
382 if (tmp->caps_string[0] == 'v') {
383 MD_I("found Video Pad\n");
384 (head_track->num_video_track)++;
385 } else if (tmp->caps_string[0] == 'a') {
386 MD_I("found Audio Pad\n");
387 (head_track->num_audio_track)++;
388 } else if (tmp->caps_string[0] == 's') {
389 MD_I("found subtitle(or Text) Pad\n");
390 (head_track->num_subtitle_track)++;
392 MD_W("found Pad %s\n", name);
393 (head_track->num_other_track)++;
395 MEDIADEMUXER_FLEAVE();
398 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
400 MEDIADEMUXER_FENTER();
401 mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
403 GstPad *aud_pad = NULL;
404 GstPad *queue_srcpad = NULL;
405 GstPad *queue_sinkpad = NULL;
406 GstPad *aud_srcpad = NULL;
407 GstPad *fake_pad = NULL;
408 GstElement *id3tag = NULL;
409 GstElement *adif_queue = NULL;
412 track_info *head_track = &(gst_handle->info);
414 gst_handle->is_valid_container = true;
415 type = gst_caps_to_string(caps);
416 if (strstr(type, "adts") || strstr(type, "adif")) {
417 gst_handle->demux = gst_element_factory_make("aacparse", NULL);
418 } else if (strstr(type, "audio/mpeg")) {
419 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
420 } else if (strstr(type, "application/x-id3")) {
421 id3tag = gst_element_factory_make("id3demux", NULL);
422 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
423 } else if (strstr(type, "audio/x-amr-nb-sh")
424 || strstr(type, "audio/x-amr-wb-sh")) {
425 gst_handle->demux = gst_element_factory_make("amrparse", NULL);
426 } else if (strstr(type, "audio/x-wav")) {
427 gst_handle->demux = gst_element_factory_make("wavparse", NULL);
428 } else if (strstr(type, "audio/x-flac")) {
429 gst_handle->demux = gst_element_factory_make("flacparse", NULL);
432 if (!gst_handle->demux) {
433 gst_handle->is_valid_container = false;
434 MD_E("factory not able to create audio parse element\n");
437 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
438 gst_handle->demux, id3tag, NULL);
439 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
441 MD_E("fail to get typefind src pad.\n");
445 aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
447 aud_pad = gst_element_get_static_pad(id3tag, "sink");
449 MD_E("fail to get audio parse sink pad.\n");
452 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
454 MD_E("fail to get fakesink sink pad.\n");
457 gst_pad_unlink(pad, fake_pad);
459 MEDIADEMUXER_SET_STATE(gst_handle->demux,
460 GST_STATE_PAUSED, ERROR);
462 MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
463 MEDIADEMUXER_SET_STATE(gst_handle->demux,
464 GST_STATE_PAUSED, ERROR);
465 gst_element_link(id3tag, gst_handle->demux);
469 /* calling "on_pad_added" function to set the caps */
470 aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
472 MD_E("fail to get audioparse source pad.\n");
475 gst_handle->total_tracks++;
476 name = gst_pad_get_name(aud_srcpad);
477 if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline)
479 MD_E("unable to added track info");
480 head_track->num_audio_track = 0;
481 head_track->num_video_track = 0;
482 head_track->num_subtitle_track = 0;
483 head_track->num_other_track = 0;
484 __gst_free_stuct(&(head_track->head));
487 if (strstr(type, "adif")) {
488 adif_queue = gst_element_factory_make("queue", NULL);
490 MD_E("factory not able to make queue in case of adif aac\n");
493 /* Add this queue to the pipeline */
494 gst_bin_add_many(GST_BIN(gst_handle->pipeline), adif_queue, NULL);
495 queue_srcpad = gst_element_get_static_pad(adif_queue, "src");
497 MD_E("fail to get queue src pad for adif aac.\n");
500 queue_sinkpad = gst_element_get_static_pad(adif_queue, "sink");
501 if (!queue_sinkpad) {
502 MD_E("fail to get queue sink pad for adif aac.\n");
505 /* link typefind with queue */
506 MEDIADEMUXER_LINK_PAD(pad, queue_sinkpad, ERROR);
507 /* link queue with aacparse */
508 MEDIADEMUXER_LINK_PAD(queue_srcpad, aud_pad, ERROR);
510 MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
513 MEDIADEMUXER_SET_STATE(adif_queue, GST_STATE_PAUSED, ERROR);
515 trck = head_track->head;
516 while (trck != NULL && aud_srcpad != trck->pad)
521 gst_caps_unref(trck->caps);
523 if (trck->caps_string)
524 g_free(trck->caps_string);
525 trck->caps_string = gst_caps_to_string(trck->caps);
526 MD_I("caps set to %s\n", trck->caps_string);
529 g_strlcpy(name, "audio", strlen(name));
532 (head_track->num_audio_track)++;
536 gst_object_unref(pad);
538 gst_object_unref(aud_pad);
540 gst_object_unref(fake_pad);
542 gst_object_unref(queue_sinkpad);
544 gst_object_unref(queue_srcpad);
546 gst_object_unref(aud_srcpad);
548 __gst_no_more_pad(gst_handle->demux, data);
550 MEDIADEMUXER_FLEAVE();
551 return MD_ERROR_NONE;
553 gst_handle->is_valid_container = false;
554 if (gst_handle->demux)
555 gst_object_unref(gst_handle->demux);
557 gst_object_unref(pad);
559 gst_object_unref(aud_pad);
561 gst_object_unref(fake_pad);
563 gst_object_unref(aud_srcpad);
565 gst_object_unref(queue_sinkpad);
567 gst_object_unref(queue_srcpad);
569 MEDIADEMUXER_FLEAVE();
573 static void __gst_cb_typefind(GstElement *tf, guint probability,
574 GstCaps *caps, gpointer data)
576 MEDIADEMUXER_FENTER();
577 mdgst_handle_t *gst_handle = (mdgst_handle_t *) data;
579 GstPad *demuxer_pad = NULL;
580 GstPad *fake_pad = NULL;
582 type = gst_caps_to_string(caps);
584 MD_I("Media type %s found, probability %d%%\n", type, probability);
585 if (strstr(type, "quicktime") || (strstr(type, "audio/x-m4a")) || strstr(type, "x-3gp")
586 || strstr(type, "ogg") || strstr(type, "flv")) {
587 gst_handle->is_valid_container = true;
588 if (strstr(type, "ogg"))
589 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
590 else if (strstr(type, "flv"))
591 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
593 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
595 if (!gst_handle->demux) {
596 gst_handle->is_valid_container = false;
597 MD_E("factory not able to create qtdemux\n");
600 g_signal_connect(gst_handle->demux, "pad-added",
601 G_CALLBACK(__gst_on_pad_added), gst_handle);
602 g_signal_connect(gst_handle->demux, "no-more-pads",
603 G_CALLBACK(__gst_no_more_pad), gst_handle);
604 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
605 gst_handle->demux, NULL);
606 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
608 MD_E("fail to get typefind src pad.\n");
611 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
613 MD_E("fail to get qtdemuc sink pad.\n");
616 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
618 MD_E("fail to get fakesink sink pad.\n");
621 gst_pad_unlink(pad, fake_pad);
622 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
623 MEDIADEMUXER_SET_STATE(gst_handle->demux,
624 GST_STATE_PAUSED, ERROR);
626 gst_object_unref(pad);
628 gst_object_unref(demuxer_pad);
630 gst_object_unref(fake_pad);
632 } else if ((strstr(type, "adts"))
633 || (strstr(type, "audio/mpeg"))
634 || (strstr(type, "audio/x-wav"))
635 || (strstr(type, "audio/x-flac"))
636 || (strstr(type, "application/x-id3"))
637 || (strstr(type, "audio/x-amr-nb-sh"))
638 || (strstr(type, "audio/x-amr-wb-sh"))) {
639 MD_I("Audio only format is found\n");
640 __gst_create_audio_only_pipeline(data, caps);
642 gst_handle->is_valid_container = false;
643 MD_E("Not supported container %s\n", type);
647 MEDIADEMUXER_FLEAVE();
650 gst_handle->is_valid_container = false;
651 if (gst_handle->demux)
652 gst_object_unref(gst_handle->demux);
656 gst_object_unref(pad);
658 gst_object_unref(demuxer_pad);
660 gst_object_unref(fake_pad);
661 MEDIADEMUXER_FLEAVE();
665 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
667 MEDIADEMUXER_FENTER();
668 int ret = MD_ERROR_NONE;
671 int remote_streaming = 0;
672 /* Initialize GStreamer */
673 /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
674 gst_init(NULL, NULL);
676 /* Create the empty pipeline */
677 gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
678 if (!gst_handle->pipeline) {
679 MD_E("pipeline create fail");
684 /* Create the elements */
685 if ((path = strstr(uri, "http://"))) {
686 gst_handle->filesrc = gst_element_factory_make("souphttpsrc", NULL);
687 remote_streaming = 1;
688 MD_I("Source is http stream. \n");
690 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
691 MD_I("Source is file stream \n");
693 if (!gst_handle->filesrc) {
694 MD_E("filesrc creation failed");
699 /* Modify the source's properties */
700 if (remote_streaming == 1)
701 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
703 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
704 gst_handle->typefind = gst_element_factory_make("typefind", NULL);
705 if (!gst_handle->typefind) {
706 MD_E("typefind creation failed");
710 g_signal_connect(gst_handle->typefind, "have-type",
711 G_CALLBACK(__gst_cb_typefind), gst_handle);
712 gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
713 if (!gst_handle->fakesink) {
714 MD_E("fakesink creation failed");
719 /* Build the pipeline */
720 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
722 gst_handle->typefind,
723 gst_handle->fakesink,
725 gst_element_link_many(gst_handle->filesrc,
726 gst_handle->typefind,
727 gst_handle->fakesink,
730 /* connect signals, bus watcher */
731 bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
732 gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
733 gst_handle->thread_default = g_main_context_get_thread_default();
734 gst_object_unref(GST_OBJECT(bus));
736 /* set pipeline state to PAUSED */
737 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
740 while (gst_handle->is_prepared != true) {
742 usleep(POLLING_INTERVAL);
743 MD_I("Inside while loop\n");
744 if (count > POLLING_INTERVAL) {
745 MD_E("Error occure\n");
751 MEDIADEMUXER_FLEAVE();
754 MEDIADEMUXER_FLEAVE();
758 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
760 MEDIADEMUXER_FENTER();
761 int ret = MD_ERROR_NONE;
762 MEDIADEMUXER_CHECK_NULL(pHandle);
763 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
765 MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
766 ret = _gst_create_pipeline(new_mediademuxer, uri);
767 if (ret != MD_ERROR_NONE) {
768 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
771 MEDIADEMUXER_FLEAVE();
774 MEDIADEMUXER_FLEAVE();
778 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
780 MEDIADEMUXER_FENTER();
781 int ret = MD_ERROR_NONE;
782 MEDIADEMUXER_CHECK_NULL(pHandle);
783 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
785 *count = (new_mediademuxer->info).num_video_track +
786 (new_mediademuxer->info).num_audio_track +
787 (new_mediademuxer->info).num_subtitle_track +
788 (new_mediademuxer->info).num_other_track;
789 MEDIADEMUXER_FLEAVE();
793 int _gst_set_appsink(track *temp, int index, int loop)
795 MEDIADEMUXER_FENTER();
796 int ret = MD_ERROR_NONE;
799 while (count != index) {
803 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
804 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
805 MEDIADEMUXER_FLEAVE();
809 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
811 MEDIADEMUXER_FENTER();
812 int ret = MD_ERROR_NONE;
813 MEDIADEMUXER_CHECK_NULL(pHandle);
814 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
816 MD_I("total_tracks (%d) :: selected track (%d)", new_mediademuxer->total_tracks, track);
817 if (track >= new_mediademuxer->total_tracks || track < 0) {
818 MD_E("total_tracks is less then selected track, So not support this track");
819 ret = MD_ERROR_INVALID_ARGUMENT;
822 new_mediademuxer->selected_tracks[track] = true;
823 _gst_set_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
824 new_mediademuxer->total_tracks);
825 MEDIADEMUXER_FLEAVE();
826 return MD_ERROR_NONE;
828 MEDIADEMUXER_FLEAVE();
832 static int _gst_unlink_unselected_track(track *temp, int index)
834 MEDIADEMUXER_FENTER();
835 int ret = MD_ERROR_NONE;
837 GstPad *queue_sink_pad = NULL;
838 while (count != index) {
842 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
843 if (!queue_sink_pad) {
844 MD_E("queue_sink_pad of appsink not avaible\n");
847 if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
848 MD_W("demuxer is already unlinked from queue for track %d\n", index);
850 gst_object_unref(queue_sink_pad);
851 MEDIADEMUXER_FLEAVE();
855 static int gst_demuxer_start(MMHandleType pHandle)
857 MEDIADEMUXER_FENTER();
858 int ret = MD_ERROR_NONE;
859 MEDIADEMUXER_CHECK_NULL(pHandle);
860 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
863 for (indx = 0; indx < gst_handle->total_tracks; indx++) {
864 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
865 indx, gst_handle->selected_tracks[indx]);
867 if (gst_handle->selected_tracks[indx] == false)
868 _gst_demuxer_unset(pHandle, indx);
870 if (gst_handle->selected_tracks[indx] != true) {
871 if (_gst_unlink_unselected_track((((mdgst_handle_t *) pHandle)->info).head, indx) != MD_ERROR_NONE) {
872 MD_E("Failed to unlink unselected tracks\n");
873 ret = MD_INTERNAL_ERROR;
880 track_info *head_track = &(gst_handle->info);
881 MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
882 head_track->num_audio_track, head_track->num_video_track,
883 head_track->num_subtitle_track);
885 track *temp = head_track->head;
888 MD_I("Got one element %p\n", temp->appsink);
889 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
890 GST_STATE_CHANGE_FAILURE) {
891 MD_E("Failed to set into PLAYING state");
892 ret = MD_INTERNAL_ERROR;
895 MD_I("set the state to playing\n");
898 track *next = temp->next;
905 MD_I("gst_demuxer_start pipeine %p", gst_handle);
906 MEDIADEMUXER_FLEAVE();
909 MEDIADEMUXER_FLEAVE();
913 int _set_mime_text(media_format_h format, track *head)
915 MEDIADEMUXER_FENTER();
916 int ret = MD_ERROR_NONE;
917 GstStructure *struc = NULL;
918 struc = gst_caps_get_structure(head->caps, 0);
920 MD_E("cannot get structure from caps.\n");
923 if (gst_structure_has_name(struc, "text/x-raw")) {
924 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
927 MD_I("Text mime not supported so far\n");
931 MEDIADEMUXER_FLEAVE();
934 MEDIADEMUXER_FLEAVE();
938 int _set_mime_video(media_format_h format, track *head)
940 MEDIADEMUXER_FENTER();
941 int ret = MD_ERROR_NONE;
942 GstStructure *struc = NULL;
945 int frame_rate_numerator = 0;
946 int frame_rate_denominator = 0;
947 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
948 struc = gst_caps_get_structure(head->caps, 0);
950 MD_E("cannot get structure from caps.\n");
953 if (gst_structure_has_name(struc, "video/x-h264")) {
954 const gchar *version = gst_structure_get_string(struc, "stream-format");
955 if (strncmp(version, "avc", 3) == 0) {
956 mime_type = MEDIA_FORMAT_H264_SP;
958 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
961 } else if (gst_structure_has_name(struc, "video/x-h263")) {
962 mime_type = MEDIA_FORMAT_H263;
963 } else if (gst_structure_has_name(struc, "video/mpeg")) {
964 mime_type = MEDIA_FORMAT_MPEG4_SP;
966 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
969 if (media_format_set_video_mime(format, mime_type)) {
970 MD_E("Unable to set video mime type (%x)\n", mime_type);
973 gst_structure_get_int(struc, "width", &src_width);
974 gst_structure_get_int(struc, "height", &src_height);
975 if (media_format_set_video_width(format, src_width)) {
976 MD_E("Unable to set video width\n");
979 if (media_format_set_video_height(format, src_height)) {
980 MD_E("Unable to set video height\n");
983 gst_structure_get_fraction(struc, "framerate", &frame_rate_numerator, &frame_rate_denominator);
984 if (media_format_set_video_frame_rate(format, frame_rate_numerator)) {
985 MD_E("Unable to set video frame rate\n");
988 MEDIADEMUXER_FLEAVE();
991 MEDIADEMUXER_FLEAVE();
995 int _set_mime_audio(media_format_h format, track *head)
997 MEDIADEMUXER_FENTER();
998 int ret = MD_ERROR_NONE;
999 GstStructure *struc = NULL;
1004 const gchar *stream_format;
1005 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1007 struc = gst_caps_get_structure(head->caps, 0);
1009 MD_E("cannot get structure from caps.\n");
1013 if (gst_structure_has_name(struc, "application/x-id3"))
1015 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1018 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1019 if (mpegversion == 4 || mpegversion == 2) {
1020 mime_type = MEDIA_FORMAT_AAC_LC;
1021 stream_format = gst_structure_get_string(struc, "stream-format");
1022 if (strncmp(stream_format, "adts", 4) == 0)
1023 media_format_set_audio_aac_type(format, 1);
1025 media_format_set_audio_aac_type(format, 0);
1026 } else if (mpegversion == 1 || id3_flag) {
1027 gst_structure_get_int(struc, "layer", &layer);
1028 if ((layer == 3) || (id3_flag == 1)) {
1029 mime_type = MEDIA_FORMAT_MP3;
1031 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1035 } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1036 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1037 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1038 mime_type = MEDIA_FORMAT_AMR_NB;
1041 mime_type = MEDIA_FORMAT_AMR_WB;
1044 } else if (gst_structure_has_name(struc, "audio/AMR")) {
1045 mime_type = MEDIA_FORMAT_AMR_NB;
1046 } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1047 mime_type = MEDIA_FORMAT_AMR_WB;
1048 } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1049 mime_type = MEDIA_FORMAT_PCM;
1050 } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1051 mime_type = MEDIA_FORMAT_FLAC;
1052 } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1053 mime_type = MEDIA_FORMAT_VORBIS;
1055 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1058 if (media_format_set_audio_mime(format, mime_type))
1060 gst_structure_get_int(struc, "channels", &channels);
1061 if (channels == 0) { /* default */
1062 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1067 if (media_format_set_audio_channel(format, channels))
1070 gst_structure_get_int(struc, "rate", &rate);
1072 rate = 44100; /* default */
1073 if (media_format_set_audio_samplerate(format, rate))
1075 gst_structure_get_int(struc, "bit", &bit);
1077 bit = 16; /* default */
1078 if (media_format_set_audio_bit(format, bit))
1080 MEDIADEMUXER_FLEAVE();
1083 MEDIADEMUXER_FLEAVE();
1087 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1088 media_format_h *format, int index)
1090 MEDIADEMUXER_FENTER();
1091 int ret = MD_ERROR_NONE;
1092 MEDIADEMUXER_CHECK_NULL(pHandle);
1093 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1098 temp = (new_mediademuxer->info).head;
1099 loop = (new_mediademuxer->info).num_video_track +
1100 (new_mediademuxer->info).num_audio_track +
1101 (new_mediademuxer->info).num_subtitle_track +
1102 (new_mediademuxer->info).num_other_track;
1103 if (index >= loop || index < 0) {
1104 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1109 while (count != index) {
1113 if (temp->format != NULL) {
1114 ret = media_format_ref(temp->format);
1115 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1116 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1117 ret = MD_INTERNAL_ERROR;
1120 ret = media_format_make_writable(temp->format, format); /* copy the content */
1121 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1122 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1123 media_format_unref(temp->format);
1124 ret = MD_INTERNAL_ERROR;
1127 MEDIADEMUXER_FLEAVE();
1130 ret = media_format_create(&(temp->format));
1131 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1132 MD_E("Mediaformat creation failed. returned %d\n", ret);
1133 ret = MD_INTERNAL_ERROR;
1137 MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1138 MD_I("format ptr[%p]\n", temp->format);
1139 if (temp->caps_string[0] == 'a') {
1140 MD_I("Setting for Audio \n");
1141 _set_mime_audio(temp->format, temp);
1142 } else if (temp->caps_string[0] == 'v') {
1143 MD_I("Setting for Video \n");
1144 _set_mime_video(temp->format, temp);
1145 } else if (temp->caps_string[0] == 't') {
1146 MD_I("Setting for Subtitle\n");
1147 _set_mime_text(temp->format, temp);
1149 MD_W("Not supported so far (except audio, video and subtitle)\n");
1152 ret = media_format_ref(temp->format); /* increment the ref to retain the original content */
1153 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1154 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1155 ret = MD_INTERNAL_ERROR;
1158 ret = media_format_make_writable(temp->format, format); /* copy the content */
1159 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1160 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1161 media_format_unref(temp->format);
1162 ret = MD_INTERNAL_ERROR;
1165 MEDIADEMUXER_FLEAVE();
1168 MEDIADEMUXER_FLEAVE();
1172 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1173 GstBuffer *buffer, char *codec_data)
1175 MEDIADEMUXER_FENTER();
1176 int ret = MD_ERROR_NONE;
1177 MEDIADEMUXER_CHECK_NULL(out_pkt);
1182 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1183 MD_E("gst_buffer_map failed\n");
1184 ret = MD_ERROR_UNKNOWN;
1188 media_packet_get_buffer_size(out_pkt, &size);
1189 MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1190 if (size < (uint64_t)map.size) {
1191 MD_W("Media packet Buffer capacity[%llu] is \
1192 less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1193 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1194 media_packet_get_buffer_size(out_pkt, &size);
1195 MD_I("Media packet Buffer NEW capacity: %llu \n", size);
1197 if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1198 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1199 ret = MD_ERROR_UNKNOWN;
1202 memcpy((char *)pkt_data, map.data, map.size);
1203 if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1204 MD_E("unable to set the pts\n");
1205 ret = MD_ERROR_UNKNOWN;
1208 if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1209 MD_E("unable to set the dts\n");
1210 ret = MD_ERROR_UNKNOWN;
1213 if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1214 MD_E("unable to set the duration\n");
1215 ret = MD_ERROR_UNKNOWN;
1218 if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1219 MD_E("unable to set the buffer size\n");
1220 ret = MD_ERROR_UNKNOWN;
1223 if (media_packet_set_flags(out_pkt, GST_BUFFER_FLAGS(buffer))) {
1224 MD_E("unable to set the buffer size\n");
1225 ret = MD_ERROR_UNKNOWN;
1229 if (media_packet_set_codec_data(out_pkt, (void*) codec_data, strlen(codec_data))) {
1230 MD_E("unable to set the codec data\n");
1231 ret = MD_ERROR_UNKNOWN;
1236 gst_buffer_unmap(buffer, &map);
1237 MEDIADEMUXER_FLEAVE();
1241 static int gst_demuxer_read_sample(MMHandleType pHandle,
1242 media_packet_h *outbuf, int track_indx)
1244 MEDIADEMUXER_FENTER();
1245 int ret = MD_ERROR_NONE;
1246 MEDIADEMUXER_CHECK_NULL(pHandle);
1247 mdgst_handle_t *demuxer = (mdgst_handle_t *) pHandle;
1249 media_packet_h mediabuf = NULL;
1251 char *codec_data = NULL;
1252 char *temp_codec_data = NULL;
1255 track *atrack = demuxer->info.head;
1256 if ((demuxer->selected_tracks)[track_indx] == false) {
1257 MD_E("Track Not selected\n");
1262 if (indx == track_indx) /* Got the requird track details */
1265 track *next = atrack->next;
1268 MD_E("Invalid track Index\n");
1269 ret = MD_ERROR_INVALID_ARGUMENT;
1276 MD_E("atrack is NULL\n");
1280 if (indx != track_indx) {
1281 MD_E("Invalid track Index\n");
1282 ret = MD_ERROR_INVALID_ARGUMENT;
1285 GstElement *sink = atrack->appsink;
1286 GstSample *sample = NULL;
1288 sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1289 if (sample == NULL) {
1290 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1291 MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1292 ret = MD_ERROR_NONE;
1294 __gst_eos_callback(track_indx, demuxer);
1297 MD_E("gst_demuxer_read_sample failed\n");
1299 ret = MD_ERROR_UNKNOWN;
1304 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1305 MD_E("media_packet_create_alloc failed\n");
1310 GstBuffer *buffer = gst_sample_get_buffer(sample);
1311 if (buffer == NULL) {
1312 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1313 ret = MD_ERROR_UNKNOWN;
1317 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1318 temp_codec_data = strstr(atrack->caps_string, "codec_data");
1319 if (temp_codec_data != NULL) {
1320 while (*temp_codec_data != ')')
1322 temp_codec_data++; /* to esacpe ')' */
1323 codec_data = (char*) malloc(sizeof(char)*strlen(temp_codec_data));
1324 if (codec_data != NULL) {
1325 while (*temp_codec_data != ',') {
1326 codec_data[index++] = *temp_codec_data;
1329 codec_data[index] = '\0';
1333 /* Fill the media_packet with proper information */
1334 ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data);
1335 gst_sample_unref(sample);
1340 MEDIADEMUXER_FLEAVE();
1344 media_packet_destroy(mediabuf);
1346 MEDIADEMUXER_FLEAVE();
1350 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1352 MEDIADEMUXER_FENTER();
1353 MEDIADEMUXER_CHECK_NULL(pHandle);
1354 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1356 gint64 pos = 0, len = 0;
1358 track_info *head_track = &(gst_handle->info);
1359 track *temp = head_track->head;
1360 track *temp_track = head_track->head;
1363 /* Setting each appsink to paused state before seek */
1364 while (temp_track) {
1365 if (gst_handle->selected_tracks[indx] == true) {
1366 if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1367 MD_E("Failed to set into PAUSED state");
1370 MD_I("set the state to paused\n");
1373 if (temp_track->next) {
1374 track *next = temp_track->next;
1381 if (gst_element_query_position(gst_handle->pipeline, GST_FORMAT_TIME, &pos) &&
1382 gst_element_query_duration(gst_handle->pipeline, GST_FORMAT_TIME, &len)) {
1383 MD_I("Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
1385 GST_TIME_ARGS(len));
1387 pos1 = pos + (pos1 * GST_SECOND);
1390 MD_I("NEW Time: %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "\r",
1391 GST_TIME_ARGS(pos1), GST_TIME_ARGS(len));
1395 MD_I("Got one element %p\n", temp->appsink);
1396 if (gst_handle->selected_tracks[indx] == true) {
1397 if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1398 GST_SEEK_FLAG_FLUSH, GST_SEEK_TYPE_SET, pos1,
1399 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1400 MD_E("Seek failed!\n");
1403 MD_I("Seek success...setting appsink to playing state\n");
1404 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1405 MD_E("Failed to set into PLAYING state");
1412 track *next = temp->next;
1418 MEDIADEMUXER_FLEAVE();
1419 return MD_ERROR_NONE;
1421 MEDIADEMUXER_FLEAVE();
1425 int _gst_unset_appsink(track *temp, int index, int loop)
1427 MEDIADEMUXER_FENTER();
1428 int ret = MD_ERROR_NONE;
1431 while (count != index) {
1435 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) 0);
1436 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1437 MEDIADEMUXER_FLEAVE();
1441 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1443 MEDIADEMUXER_FENTER();
1444 int ret = MD_ERROR_NONE;
1445 MEDIADEMUXER_CHECK_NULL(pHandle);
1446 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1448 if (track >= new_mediademuxer->total_tracks || track < 0) {
1449 MD_E("total tracks is less then unselected track, So not support this track");
1450 ret = MD_ERROR_INVALID_ARGUMENT;
1453 new_mediademuxer->selected_tracks[track] = false;
1454 _gst_unset_appsink((((mdgst_handle_t *) pHandle)->info).head, track,
1455 new_mediademuxer->total_tracks);
1456 MEDIADEMUXER_FLEAVE();
1459 MEDIADEMUXER_FLEAVE();
1463 static int gst_demuxer_stop(MMHandleType pHandle)
1465 MEDIADEMUXER_FENTER();
1466 int ret = MD_ERROR_NONE;
1467 MEDIADEMUXER_CHECK_NULL(pHandle);
1468 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1470 MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1471 if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1472 GST_STATE_CHANGE_FAILURE) {
1473 MD_E("Failed to set into PAUSE state");
1474 ret = MD_INTERNAL_ERROR;
1477 MEDIADEMUXER_FLEAVE();
1480 MEDIADEMUXER_FLEAVE();
1484 void _gst_clear_struct(mdgst_handle_t *gst_handle)
1486 MEDIADEMUXER_FENTER();
1487 if (gst_handle->selected_tracks) {
1488 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1489 gst_handle->selected_tracks);
1490 g_free(gst_handle->selected_tracks);
1491 gst_handle->selected_tracks = NULL;
1493 if ((gst_handle->info).head)
1494 __gst_free_stuct(&(gst_handle->info).head);
1495 MEDIADEMUXER_FLEAVE();
1498 int _md_gst_destroy_pipeline(GstElement *pipeline)
1500 MEDIADEMUXER_FENTER();
1501 int ret = MD_ERROR_NONE;
1503 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1505 gst_object_unref(GST_OBJECT(pipeline));
1506 MEDIADEMUXER_FLEAVE();
1510 gst_object_unref(GST_OBJECT(pipeline));
1511 MEDIADEMUXER_FLEAVE();
1515 static int gst_demuxer_unprepare(MMHandleType pHandle)
1517 MEDIADEMUXER_FENTER();
1518 int ret = MD_ERROR_NONE;
1519 MEDIADEMUXER_CHECK_NULL(pHandle);
1520 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1522 _gst_clear_struct(gst_handle);
1523 if (gst_handle->bus_watch_id) {
1524 GSource *source = NULL;
1525 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1527 g_source_destroy(source);
1528 LOGD("Deallocation bus watch id");
1532 MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1533 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1537 MEDIADEMUXER_FLEAVE();
1540 MEDIADEMUXER_FLEAVE();
1544 static int gst_demuxer_destroy(MMHandleType pHandle)
1546 MEDIADEMUXER_FENTER();
1547 int ret = MD_ERROR_NONE;
1548 MEDIADEMUXER_CHECK_NULL(pHandle);
1549 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *) pHandle;
1551 MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1553 g_free(new_mediademuxer);
1554 MEDIADEMUXER_FLEAVE();
1558 int gst_set_error_cb(MMHandleType pHandle,
1559 gst_error_cb callback, void *user_data)
1561 MEDIADEMUXER_FENTER();
1562 int ret = MD_ERROR_NONE;
1563 MEDIADEMUXER_CHECK_NULL(pHandle);
1564 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1567 MD_E("fail invaild param (gst_handle)\n");
1568 ret = MD_INVALID_ARG;
1572 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1573 MD_E("Already set mediademuxer_error_cb\n");
1574 ret = MD_ERROR_INVALID_ARGUMENT;
1578 MD_E("fail invaild argument (callback)\n");
1579 ret = MD_ERROR_INVALID_ARGUMENT;
1584 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1586 gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb) callback;
1587 gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1588 MEDIADEMUXER_FLEAVE();
1589 return MD_ERROR_NONE;
1591 MEDIADEMUXER_FLEAVE();
1595 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1597 MEDIADEMUXER_FENTER();
1598 int ret = MD_ERROR_NONE;
1599 MEDIADEMUXER_CHECK_NULL(pHandle);
1600 mdgst_handle_t *gst_handle = (mdgst_handle_t *) pHandle;
1603 MD_E("fail invaild param (gst_handle)\n");
1604 ret = MD_INVALID_ARG;
1608 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1609 MD_E("Already set mediademuxer_eos_cb\n");
1610 ret = MD_ERROR_INVALID_ARGUMENT;
1614 MD_E("fail invaild argument (callback)\n");
1615 ret = MD_ERROR_INVALID_ARGUMENT;
1620 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1621 gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb) callback;
1622 gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1623 MEDIADEMUXER_FLEAVE();
1624 return MD_ERROR_NONE;
1626 MEDIADEMUXER_FLEAVE();
1630 static int __gst_eos_callback(int track_num, void* user_data)
1632 if (user_data == NULL) {
1633 MD_E("Invalid argument");
1636 mdgst_handle_t *gst_handle = (mdgst_handle_t *) user_data;
1637 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1638 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1639 gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1641 MD_E("EOS received, but callback is not set!!!");
1642 return MD_ERROR_NONE;