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
25 #include <mediademuxer_error.h>
26 #include <mediademuxer_private.h>
27 #include <mediademuxer_port.h>
28 #include <mediademuxer_port_gst.h>
29 #include <media_packet_internal.h>
31 static int gst_demuxer_init(MMHandleType *pHandle);
32 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri);
33 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count);
34 static int gst_demuxer_set_track(MMHandleType pHandle, int track);
35 static int gst_demuxer_start(MMHandleType pHandle);
36 static int gst_demuxer_read_sample(MMHandleType pHandle,
37 media_packet_h *outbuf, int track_indx);
38 static int gst_demuxer_get_track_info(MMHandleType pHandle,
39 media_format_h *format, int index);
40 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1);
41 static int gst_demuxer_unset_track(MMHandleType pHandle, int track);
42 static int gst_demuxer_stop(MMHandleType pHandle);
43 static int gst_demuxer_unprepare(MMHandleType pHandle);
44 static int gst_demuxer_destroy(MMHandleType pHandle);
45 static int gst_set_error_cb(MMHandleType pHandle,
46 gst_error_cb callback, void *user_data);
47 static int gst_set_eos_cb(MMHandleType pHandle,
48 gst_eos_cb callback, void *user_data);
49 static int __gst_eos_callback(int track_num, void *user_data);
51 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code);
52 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code);
53 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code);
54 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message);
55 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error);
57 /* Media Demuxer API common */
58 static media_port_demuxer_ops def_demux_ops = {
60 .init = gst_demuxer_init,
61 .prepare = gst_demuxer_prepare,
62 .get_track_count = gst_demuxer_get_data_count,
63 .set_track = gst_demuxer_set_track,
64 .start = gst_demuxer_start,
65 .get_track_info = gst_demuxer_get_track_info,
66 .read_sample = gst_demuxer_read_sample,
67 .seek = gst_demuxer_seek,
68 .unset_track = gst_demuxer_unset_track,
69 .stop = gst_demuxer_stop,
70 .unprepare = gst_demuxer_unprepare,
71 .destroy = gst_demuxer_destroy,
72 .set_error_cb = gst_set_error_cb,
73 .set_eos_cb = gst_set_eos_cb,
76 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code)
78 gint trans_err = MEDIADEMUXER_ERROR_NONE;
80 MEDIADEMUXER_CHECK_NULL(gst_handle);
83 case GST_CORE_ERROR_MISSING_PLUGIN:
84 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
85 case GST_CORE_ERROR_STATE_CHANGE:
86 case GST_CORE_ERROR_SEEK:
87 case GST_CORE_ERROR_NOT_IMPLEMENTED:
88 case GST_CORE_ERROR_FAILED:
89 case GST_CORE_ERROR_TOO_LAZY:
90 case GST_CORE_ERROR_PAD:
91 case GST_CORE_ERROR_THREAD:
92 case GST_CORE_ERROR_NEGOTIATION:
93 case GST_CORE_ERROR_EVENT:
94 case GST_CORE_ERROR_CAPS:
95 case GST_CORE_ERROR_TAG:
96 case GST_CORE_ERROR_CLOCK:
97 case GST_CORE_ERROR_DISABLED:
99 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
106 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code)
108 gint trans_err = MEDIADEMUXER_ERROR_NONE;
110 MEDIADEMUXER_CHECK_NULL(gst_handle);
113 case GST_LIBRARY_ERROR_FAILED:
114 case GST_LIBRARY_ERROR_TOO_LAZY:
115 case GST_LIBRARY_ERROR_INIT:
116 case GST_LIBRARY_ERROR_SHUTDOWN:
117 case GST_LIBRARY_ERROR_SETTINGS:
118 case GST_LIBRARY_ERROR_ENCODE:
120 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
128 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code)
130 gint trans_err = MEDIADEMUXER_ERROR_NONE;
132 MEDIADEMUXER_CHECK_NULL(gst_handle);
135 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
136 trans_err = MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
138 case GST_RESOURCE_ERROR_WRITE:
139 case GST_RESOURCE_ERROR_FAILED:
140 case GST_RESOURCE_ERROR_SEEK:
141 case GST_RESOURCE_ERROR_TOO_LAZY:
142 case GST_RESOURCE_ERROR_BUSY:
143 case GST_RESOURCE_ERROR_OPEN_WRITE:
144 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
145 case GST_RESOURCE_ERROR_CLOSE:
146 case GST_RESOURCE_ERROR_SYNC:
147 case GST_RESOURCE_ERROR_SETTINGS:
149 trans_err = MEDIADEMUXER_ERROR_RESOURCE_LIMIT;
156 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message)
158 gint trans_err = MEDIADEMUXER_ERROR_NONE;
160 MEDIADEMUXER_CHECK_NULL(gst_handle);
161 MEDIADEMUXER_CHECK_NULL(error);
162 MEDIADEMUXER_CHECK_NULL(message);
164 switch (error->code) {
165 case GST_STREAM_ERROR_FAILED:
166 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
167 case GST_STREAM_ERROR_DECODE:
168 case GST_STREAM_ERROR_WRONG_TYPE:
169 case GST_STREAM_ERROR_DECRYPT:
170 case GST_STREAM_ERROR_DECRYPT_NOKEY:
171 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
172 trans_err = __gst_transform_gsterror(gst_handle, message, error);
175 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
176 case GST_STREAM_ERROR_TOO_LAZY:
177 case GST_STREAM_ERROR_ENCODE:
178 case GST_STREAM_ERROR_DEMUX:
179 case GST_STREAM_ERROR_MUX:
180 case GST_STREAM_ERROR_FORMAT:
182 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
189 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error)
191 gchar *src_element_name = NULL;
192 GstElement *src_element = NULL;
193 GstElementFactory *factory = NULL;
194 const gchar *klass = NULL;
196 MEDIADEMUXER_CHECK_NULL(gst_handle);
198 src_element = GST_ELEMENT_CAST(message->src);
202 src_element_name = GST_ELEMENT_NAME(src_element);
203 if (!src_element_name)
206 factory = gst_element_get_factory(src_element);
210 klass = gst_element_factory_get_klass(factory);
214 MD_I("error code=%d, msg=%s, src element=%s, class=%s\n",
215 error->code, error->message, src_element_name, klass);
217 switch (error->code) {
218 case GST_STREAM_ERROR_DECODE:
219 case GST_STREAM_ERROR_FAILED:
220 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
223 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
224 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
225 case GST_STREAM_ERROR_WRONG_TYPE:
226 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
230 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
234 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
237 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
241 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
243 MEDIADEMUXER_FENTER();
244 int ret = MD_ERROR_NONE;
245 MEDIADEMUXER_CHECK_NULL(pOps);
246 def_demux_ops.n_size = sizeof(def_demux_ops);
248 memcpy((char *)pOps + sizeof(pOps->n_size),
249 (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
250 pOps->n_size - sizeof(pOps->n_size));
252 MEDIADEMUXER_FLEAVE();
256 static int gst_demuxer_init(MMHandleType *pHandle)
258 MEDIADEMUXER_FENTER();
259 int ret = MD_ERROR_NONE;
260 mdgst_handle_t *new_mediademuxer = NULL;
261 new_mediademuxer = (mdgst_handle_t *)g_malloc(sizeof(mdgst_handle_t));
262 MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
263 if (!new_mediademuxer) {
264 MD_E("Cannot allocate memory for demuxer\n");
268 memset(new_mediademuxer, 0, sizeof(mdgst_handle_t));
269 new_mediademuxer->is_prepared = false;
270 (new_mediademuxer->info).num_audio_track = 0;
271 (new_mediademuxer->info).num_video_track = 0;
272 (new_mediademuxer->info).num_subtitle_track = 0;
273 (new_mediademuxer->info).num_other_track = 0;
274 (new_mediademuxer->info).head = NULL;
275 *pHandle = (MMHandleType)new_mediademuxer;
276 new_mediademuxer->total_tracks = 0;
277 MEDIADEMUXER_FLEAVE();
280 MEDIADEMUXER_FLEAVE();
284 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
286 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
287 MEDIADEMUXER_FENTER();
288 int ret = MD_ERROR_NONE;
289 switch (GST_MESSAGE_TYPE(msg)) {
290 case GST_MESSAGE_EOS: {
294 case GST_MESSAGE_ERROR: {
295 GError *error = NULL;
296 gst_message_parse_error(msg, &error, NULL);
298 MD_I("GST error message parsing failed");
302 if (error->domain == GST_STREAM_ERROR)
303 ret = __gst_handle_stream_error(gst_handle, error, msg);
304 else if (error->domain == GST_RESOURCE_ERROR)
305 ret = __gst_handle_resource_error(gst_handle, error->code);
306 else if (error->domain == GST_LIBRARY_ERROR)
307 ret = __gst_handle_library_error(gst_handle, error->code);
308 else if (error->domain == GST_CORE_ERROR)
309 ret = __gst_handle_core_error(gst_handle, error->code);
311 MD_W("Unexpected error has occured");
313 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
314 ((mediademuxer_error_cb)gst_handle->user_cb[_GST_EVENT_TYPE_ERROR])
315 (ret, gst_handle->user_data[_GST_EVENT_TYPE_ERROR]);
316 MD_W("Error : (ox%08x)", ret);
318 MD_E("Error: %s\n", error->message);
325 MEDIADEMUXER_FLEAVE();
329 static void __gst_no_more_pad(GstElement *element, gpointer data)
331 MEDIADEMUXER_FENTER();
332 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
334 track_info *head_track = &(gst_handle->info);
335 track *head = head_track->head;
336 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
337 gst_handle->selected_tracks =
338 (bool *) g_malloc(sizeof(bool) * (gst_handle->total_tracks));
339 MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
340 if (!gst_handle->selected_tracks) {
341 MD_E("[%s]Memory allocation failed\n", __FUNCTION__);
344 for (loop_track = 0; loop_track < gst_handle->total_tracks;
346 gst_handle->selected_tracks[loop_track] = false;
348 MD_I("Number of video tracks are %d\n", head_track->num_video_track);
349 MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
350 MD_I("Number of subtitle tracks are %d\n",
351 head_track->num_subtitle_track);
352 MD_I("Number of other tracks are %d\n", head_track->num_other_track);
354 MD_I("track caps[%s]\n", head->caps_string);
357 gst_handle->is_prepared = true;
358 MD_I("core->is_prepared: ");
359 gst_handle->is_prepared ? MD_I("true\n") : MD_I("false\n");
360 MEDIADEMUXER_FLEAVE();
363 void __gst_free_stuct(track **head)
365 MEDIADEMUXER_FENTER();
371 MD_I("unref GST_PAD %p\n", temp->pad);
372 gst_object_unref(temp->pad);
375 MD_I("unref GST_PAD caps %p\n", temp->caps);
376 gst_caps_unref(temp->caps);
378 if (temp->caps_string) {
379 MD_I("deallocate GST_PAD caps_string %p\n",
381 g_free(temp->caps_string);
384 MD_I("unref media_format %p\n", temp->format);
385 media_format_unref(temp->format);
388 track *next = temp->next;
389 MD_I("deallocate memory %p\n", temp);
393 MD_I("deallocate memory %p\n", temp);
399 MEDIADEMUXER_FLEAVE();
402 int __gst_add_track_info(GstPad *pad, GstCaps *caps, track **head,
403 GstElement *pipeline)
405 MEDIADEMUXER_FENTER();
406 GstPad *apppad = NULL;
407 GstPad *queue_sink_pad = NULL;
408 GstPad *queue_src_pad = NULL;
409 GstCaps *outcaps = NULL;
410 GstPad *parse_sink_pad = NULL;
411 GstElement *parse_element = NULL;
412 GstElement *id3tag = NULL;
413 GstPad *id3_sinkpad = NULL;
414 GstPad *id3_srcpad = NULL;
417 temp = (track *)(g_malloc(sizeof(track)));
419 MD_E("Not able to allocate memory");
422 MD_I("allocate memory %p", temp);
424 memset(temp, 0x00, sizeof(track));
426 temp->pad = gst_object_ref(pad);
427 temp->caps = gst_caps_ref(caps);
428 temp->caps_string = gst_caps_to_string(caps);
431 temp->need_codec_data = TRUE;
433 MD_I("track caps(%s)", temp->caps_string ? temp->caps_string : "NULL");
435 /* Link demuxer - queue */
436 temp->queue = gst_element_factory_make("queue", NULL);
438 MD_E("factory not able to make queue");
442 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
443 gst_object_unref(temp->queue);
444 MD_E("fail add queue in pipeline");
447 MD_I("added queue element in pipeline.");
449 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
450 if (!queue_sink_pad) {
451 MD_E("sink pad of queue not avaible");
455 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
456 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->queue, ERROR);
458 temp->appsink = gst_element_factory_make("appsink", NULL);
459 if (!temp->appsink) {
460 MD_E("factory not able to make appsink");
463 g_object_set(G_OBJECT(temp->appsink), "wait-on-eos", TRUE, NULL);
465 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
466 gst_object_unref(temp->appsink);
467 MD_E("fail add appsink in pipeline");
470 MD_I("added appsink element in pipeline.");
472 gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
473 gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
475 queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
476 if (!queue_src_pad) {
477 MD_E("src pad of queue not avaible");
480 apppad = gst_element_get_static_pad(temp->appsink, "sink");
482 MD_E("sink pad of appsink not avaible");
485 /* Check for type video and it should be h264 */
486 if (temp->caps_string && strstr(temp->caps_string, "video")) {
487 if (strstr(temp->caps_string, "h264")) {
488 parse_element = gst_element_factory_make("h264parse", NULL);
489 if (!parse_element) {
490 MD_E("factory not able to make h264parse");
493 } else if (strstr(temp->caps_string, "mpeg")) {
494 parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
495 if (!parse_element) {
496 MD_E("factory not able to make h264parse");
499 g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
503 MD_I("add video parse element(%s).", GST_ELEMENT_NAME(parse_element));
504 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
505 gst_object_unref(parse_element);
506 MD_E("fail add video parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
509 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
510 if (!parse_sink_pad) {
511 MD_E("sink pad of video parse(%s) not available", GST_ELEMENT_NAME(parse_element));
514 /* Link demuxer pad with sink pad of parse element */
515 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
517 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
519 if (strstr(temp->caps_string, "h264")) {
520 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
521 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
522 gst_caps_unref(outcaps);
523 temp->need_codec_data = FALSE;
524 } else if (strstr(temp->caps_string, "mpeg")) {
525 gst_element_link(parse_element, temp->appsink);
527 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
530 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
532 } else if (temp->caps_string && (strstr(temp->caps_string, "audio") || strstr(temp->caps_string, "x-id3"))) {
533 if (strstr(temp->caps_string, "audio/mpeg")) {
535 GstStructure *structure = NULL;
536 structure = gst_caps_get_structure(temp->caps, 0);
537 gst_structure_get_int (structure, "mpegversion", &mpegversion);
538 if (mpegversion == 2 || mpegversion == 4) {
539 parse_element = gst_element_factory_make("aacparse", NULL);
540 if (!parse_element) {
541 MD_E("factory not able to make aacparse");
544 } else if (mpegversion == 1) {
545 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
546 if (!parse_element) {
547 MD_E("factory not able to make mpegaudioparse");
551 } else if (strstr(temp->caps_string, "application/x-id3")) {
552 id3tag = gst_element_factory_make("id3demux", NULL);
554 MD_E("factory not able to make id3demux");
557 if (!gst_bin_add(GST_BIN(pipeline), id3tag)) {
558 gst_object_unref(id3tag);
559 MD_E("fail add id3tag element in pipeline");
562 id3_sinkpad = gst_element_get_static_pad(id3tag, "sink");
564 MD_E("fail to get id3demux sink pad.\n");
567 MEDIADEMUXER_LINK_PAD(queue_src_pad, id3_sinkpad, ERROR);
568 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(id3tag, ERROR);
569 id3_srcpad = gst_element_get_static_pad(id3tag, "src");
571 MD_E("fail to get id3demux src pad.\n");
574 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
575 if (!parse_element) {
576 MD_E("factory not able to make mpegaudioparse");
579 } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
580 || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
581 parse_element = gst_element_factory_make("amrparse", NULL);
582 if (!parse_element) {
583 MD_E("factory not able to make amrparse");
586 } else if (strstr(temp->caps_string, "audio/x-wav")) {
587 parse_element = gst_element_factory_make("wavparse", NULL);
588 if (!parse_element) {
589 MD_E("factory not able to make wavparse");
592 } else if (strstr(temp->caps_string, "audio/x-flac")) {
593 parse_element = gst_element_factory_make("flacparse", NULL);
594 if (!parse_element) {
595 MD_E("factory not able to make flacparse");
601 MD_I("add audio parse element(%s).", GST_ELEMENT_NAME(parse_element));
602 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
603 gst_object_unref(parse_element);
604 MD_E("fail add audio parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
607 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
608 if (!parse_sink_pad) {
609 MD_E("sink pad of audio parse(%s) not available", GST_ELEMENT_NAME(parse_element));
613 /* Link demuxer pad with sink pad of parse element */
615 MEDIADEMUXER_LINK_PAD(id3_srcpad, parse_sink_pad, ERROR);
617 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
619 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
621 /* Link src pad with appSink element */
622 gst_element_link(parse_element, temp->appsink);
624 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
627 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
630 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->appsink, ERROR);
631 /* gst_pad_link(pad, fpad) */
641 gst_object_unref(queue_sink_pad);
643 gst_object_unref(queue_src_pad);
645 gst_object_unref(apppad);
647 gst_object_unref(parse_sink_pad);
649 gst_object_unref(id3_sinkpad);
651 gst_object_unref(id3_srcpad);
652 MEDIADEMUXER_FLEAVE();
653 return MD_ERROR_NONE;
656 __gst_free_stuct(&temp);
658 gst_object_unref(queue_sink_pad);
660 gst_object_unref(queue_src_pad);
662 gst_object_unref(apppad);
664 gst_object_unref(parse_sink_pad);
666 gst_object_unref(id3_sinkpad);
668 gst_object_unref(id3_srcpad);
669 __gst_free_stuct(head);
670 MEDIADEMUXER_FLEAVE();
674 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
676 MEDIADEMUXER_FENTER();
677 MD_I("Dynamic pad created, linking demuxer/decoder\n");
679 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
680 track_info *head_track = &(gst_handle->info);
681 GstCaps *caps = NULL;
682 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
683 caps = gst_pad_get_current_caps(pad);
685 MD_E("caps is NULL");
688 gst_handle->total_tracks++;
689 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline)
691 MD_E("unable to added track info");
692 head_track->num_audio_track = 0;
693 head_track->num_video_track = 0;
694 head_track->num_subtitle_track = 0;
695 head_track->num_other_track = 0;
696 gst_caps_unref(caps);
697 __gst_free_stuct(&(head_track->head));
700 gst_caps_unref(caps);
701 tmp = head_track->head;
704 MD_I("trak is NULL\n");
705 MEDIADEMUXER_FLEAVE();
713 MD_I("trak is NULL\n");
714 MEDIADEMUXER_FLEAVE();
718 if (!tmp->caps_string) {
719 MD_I("trak caps_string is NULL\n");
720 MEDIADEMUXER_FLEAVE();
724 if (tmp->caps_string[0] == 'v') {
725 MD_I("found Video Pad\n");
726 (head_track->num_video_track)++;
727 } else if (tmp->caps_string[0] == 'a') {
728 MD_I("found Audio Pad\n");
729 (head_track->num_audio_track)++;
730 } else if (tmp->caps_string[0] == 's') {
731 MD_I("found subtitle(or Text) Pad\n");
732 (head_track->num_subtitle_track)++;
734 MD_W("found Pad, caps: %s\n", tmp->caps_string);
735 (head_track->num_other_track)++;
737 MEDIADEMUXER_FLEAVE();
740 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
742 MEDIADEMUXER_FENTER();
743 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
745 track_info *head_track = &(gst_handle->info);
747 gst_handle->is_valid_container = true;
749 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
751 MD_E("fail to get typefind src pad.\n");
755 gst_handle->total_tracks++;
756 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
757 MD_E("unable to added track info");
758 head_track->num_audio_track = 0;
759 head_track->num_video_track = 0;
760 head_track->num_subtitle_track = 0;
761 head_track->num_other_track = 0;
762 __gst_free_stuct(&(head_track->head));
766 (head_track->num_audio_track)++;
770 gst_object_unref(pad);
772 /* In the case of audio only, there is no gst_handle->demux. So we pass NULL */
773 __gst_no_more_pad(NULL, data);
775 MEDIADEMUXER_FLEAVE();
776 return MD_ERROR_NONE;
779 gst_handle->is_valid_container = false;
782 gst_object_unref(pad);
784 MEDIADEMUXER_FLEAVE();
788 static void __gst_cb_typefind(GstElement *tf, guint probability,
789 GstCaps *caps, gpointer data)
791 MEDIADEMUXER_FENTER();
792 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
794 GstPad *demuxer_pad = NULL;
795 GstPad *fake_pad = NULL;
797 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
798 type = gst_caps_to_string(caps);
801 MD_E("Fail to get caps string");
805 MD_I("Media type %s found, probability %d%%\n", type, probability);
806 if (strstr(type, "quicktime") || strstr(type, "audio/x-m4a") ||
807 strstr(type, "x-3gp") || strstr(type, "ogg") ||
808 strstr(type, "flv") || strstr(type, "x-msvideo")) {
809 gst_handle->is_valid_container = true;
810 if (strstr(type, "ogg"))
811 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
812 else if (strstr(type, "flv"))
813 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
814 else if (strstr(type, "x-msvideo"))
815 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
817 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
819 if (!gst_handle->demux) {
820 gst_handle->is_valid_container = false;
821 MD_E("factory not able to create qtdemux\n");
824 g_signal_connect(gst_handle->demux, "pad-added",
825 G_CALLBACK(__gst_on_pad_added), gst_handle);
826 g_signal_connect(gst_handle->demux, "no-more-pads",
827 G_CALLBACK(__gst_no_more_pad), gst_handle);
828 gst_element_set_locked_state(gst_handle->demux, TRUE);
829 if (!gst_bin_add(GST_BIN(gst_handle->pipeline), gst_handle->demux)) {
830 MD_E("fail add demuxer(%s) in pipeline",
831 GST_ELEMENT_NAME(gst_handle->demux));
832 gst_object_unref(gst_handle->demux);
833 gst_handle->demux = NULL;
837 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
839 MD_E("fail to get typefind src pad.\n");
842 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
844 MD_E("fail to get qtdemuc sink pad.\n");
847 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
849 MD_E("fail to get fakesink sink pad.\n");
852 gst_pad_unlink(pad, fake_pad);
853 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
855 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(gst_handle->demux, ERROR);
856 gst_element_set_locked_state(gst_handle->demux, FALSE);
858 gst_object_unref(pad);
860 gst_object_unref(demuxer_pad);
862 gst_object_unref(fake_pad);
864 } else if ((strstr(type, "adts"))
865 || (strstr(type, "audio/mpeg"))
866 || (strstr(type, "audio/x-wav"))
867 || (strstr(type, "audio/x-flac"))
868 || (strstr(type, "application/x-id3"))
869 || (strstr(type, "audio/x-amr-nb-sh"))
870 || (strstr(type, "audio/x-amr-wb-sh"))) {
871 MD_I("Audio only format is found\n");
872 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
874 MD_E("fail to get typefind src pad.\n");
877 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
879 MD_E("fail to get fakesink sink pad.\n");
882 gst_pad_unlink(pad, fake_pad);
884 gst_object_unref(pad);
886 gst_object_unref(fake_pad);
888 __gst_create_audio_only_pipeline(data, caps);
890 gst_handle->is_valid_container = false;
891 MD_E("Not supported container %s\n", type);
895 MEDIADEMUXER_FLEAVE();
899 gst_handle->is_valid_container = false;
902 if (gst_handle->demux)
903 gst_element_set_locked_state(gst_handle->demux, FALSE);
905 gst_object_unref(pad);
907 gst_object_unref(demuxer_pad);
909 gst_object_unref(fake_pad);
910 MEDIADEMUXER_FLEAVE();
914 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
916 MEDIADEMUXER_FENTER();
917 int ret = MD_ERROR_NONE;
920 #ifdef TIZEN_FEATURE_STREAMING
921 int remote_streaming = 0;
923 GstState element_state = GST_STATE_VOID_PENDING;
924 GstState element_pending_state = GST_STATE_VOID_PENDING;
926 /* Initialize GStreamer */
927 /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
928 gst_init(NULL, NULL);
930 /* Create the empty pipeline */
931 gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
932 if (!gst_handle->pipeline) {
933 MD_E("pipeline create fail");
938 /* Create the elements */
939 if ((path = strstr(uri, "http://"))) {
940 #ifdef TIZEN_FEATURE_STREAMING
941 gst_handle->filesrc = gst_element_factory_make("souphttpsrc", NULL);
942 remote_streaming = 1;
943 MD_I("Source is http stream. \n");
945 MD_I("Source is http stream. Didn't support streaming\n");
949 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
950 MD_I("Source is file stream \n");
952 if (!gst_handle->filesrc) {
953 MD_E("filesrc creation failed");
958 /* Modify the source's properties */
959 #ifdef TIZEN_FEATURE_STREAMING
960 if (remote_streaming == 1)
961 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
964 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
965 gst_handle->typefind = gst_element_factory_make("typefind", NULL);
966 if (!gst_handle->typefind) {
967 MD_E("typefind creation failed");
971 g_signal_connect(gst_handle->typefind, "have-type",
972 G_CALLBACK(__gst_cb_typefind), gst_handle);
973 gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
974 if (!gst_handle->fakesink) {
975 MD_E("fakesink creation failed");
980 /* Build the pipeline */
981 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
983 gst_handle->typefind,
984 gst_handle->fakesink,
986 gst_element_link_many(gst_handle->filesrc,
987 gst_handle->typefind,
988 gst_handle->fakesink,
991 /* connect signals, bus watcher */
992 bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
993 gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
994 gst_handle->thread_default = g_main_context_get_thread_default();
995 gst_object_unref(GST_OBJECT(bus));
997 /* set pipeline state to PAUSED */
998 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
1000 if (gst_element_get_state(gst_handle->pipeline, &element_state, &element_pending_state, 1 * GST_SECOND)
1001 == GST_STATE_CHANGE_FAILURE) {
1002 MD_E(" [%s] state : %s pending : %s \n",
1003 GST_ELEMENT_NAME(gst_handle->pipeline),
1004 gst_element_state_get_name(element_state),
1005 gst_element_state_get_name(element_pending_state));
1010 if (gst_handle->is_prepared != true) {
1011 MD_E("Error occure");
1016 MEDIADEMUXER_FLEAVE();
1019 MEDIADEMUXER_FLEAVE();
1023 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
1025 MEDIADEMUXER_FENTER();
1026 int ret = MD_ERROR_NONE;
1027 MEDIADEMUXER_CHECK_NULL(pHandle);
1028 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1030 MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
1031 ret = _gst_create_pipeline(new_mediademuxer, uri);
1032 if (ret != MD_ERROR_NONE) {
1033 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
1036 MEDIADEMUXER_FLEAVE();
1039 MEDIADEMUXER_FLEAVE();
1043 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
1045 MEDIADEMUXER_FENTER();
1046 int ret = MD_ERROR_NONE;
1047 MEDIADEMUXER_CHECK_NULL(pHandle);
1048 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1050 *count = (new_mediademuxer->info).num_video_track +
1051 (new_mediademuxer->info).num_audio_track +
1052 (new_mediademuxer->info).num_subtitle_track +
1053 (new_mediademuxer->info).num_other_track;
1054 MEDIADEMUXER_FLEAVE();
1058 int _gst_set_appsink(track *temp, int index, int loop)
1060 MEDIADEMUXER_FENTER();
1061 int ret = MD_ERROR_NONE;
1064 while (count != index) {
1068 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
1069 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
1070 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), true);
1071 MEDIADEMUXER_FLEAVE();
1075 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
1077 MEDIADEMUXER_FENTER();
1078 int ret = MD_ERROR_NONE;
1079 MEDIADEMUXER_CHECK_NULL(pHandle);
1080 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1082 MD_I("total_tracks (%d) :: selected track (%d)", new_mediademuxer->total_tracks, track);
1083 if (track >= new_mediademuxer->total_tracks || track < 0) {
1084 MD_E("total_tracks is less then selected track, So not support this track");
1085 ret = MD_ERROR_INVALID_ARGUMENT;
1088 new_mediademuxer->selected_tracks[track] = true;
1089 _gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1090 new_mediademuxer->total_tracks);
1091 MEDIADEMUXER_FLEAVE();
1092 return MD_ERROR_NONE;
1094 MEDIADEMUXER_FLEAVE();
1098 static int _gst_unlink_unselected_track(track *temp, int index)
1100 MEDIADEMUXER_FENTER();
1101 int ret = MD_ERROR_NONE;
1103 GstPad *queue_sink_pad = NULL;
1104 while (count != index) {
1108 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
1109 if (!queue_sink_pad) {
1110 MD_E("queue_sink_pad of appsink not avaible\n");
1113 if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
1114 MD_W("demuxer is already unlinked from queue for track %d\n", index);
1116 gst_object_unref(queue_sink_pad);
1117 MEDIADEMUXER_FLEAVE();
1121 static int gst_demuxer_start(MMHandleType pHandle)
1123 MEDIADEMUXER_FENTER();
1124 int ret = MD_ERROR_NONE;
1125 MEDIADEMUXER_CHECK_NULL(pHandle);
1126 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1129 for (indx = 0; indx < gst_handle->total_tracks; indx++) {
1130 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
1131 indx, gst_handle->selected_tracks[indx]);
1133 if (gst_handle->selected_tracks[indx] == false)
1134 _gst_demuxer_unset(pHandle, indx);
1136 if (gst_handle->selected_tracks[indx] != true) {
1137 if (_gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
1138 MD_E("Failed to unlink unselected tracks\n");
1139 ret = MD_INTERNAL_ERROR;
1146 track_info *head_track = &(gst_handle->info);
1147 MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
1148 head_track->num_audio_track, head_track->num_video_track,
1149 head_track->num_subtitle_track);
1151 track *temp = head_track->head;
1154 MD_I("Got one element %p\n", temp->appsink);
1155 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
1156 GST_STATE_CHANGE_FAILURE) {
1157 MD_E("Failed to set into PLAYING state");
1158 ret = MD_INTERNAL_ERROR;
1161 MD_I("set the state to playing\n");
1164 track *next = temp->next;
1171 MD_I("gst_demuxer_start pipeine %p", gst_handle);
1172 MEDIADEMUXER_FLEAVE();
1175 MEDIADEMUXER_FLEAVE();
1179 int _set_mime_text(media_format_h format, track *head)
1181 MEDIADEMUXER_FENTER();
1182 int ret = MD_ERROR_NONE;
1183 GstStructure *struc = NULL;
1184 struc = gst_caps_get_structure(head->caps, 0);
1186 MD_E("cannot get structure from caps.\n");
1189 if (gst_structure_has_name(struc, "text/x-raw")) {
1190 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
1193 MD_I("Text mime not supported so far\n");
1197 MEDIADEMUXER_FLEAVE();
1200 MEDIADEMUXER_FLEAVE();
1204 int _set_mime_video(media_format_h format, track *head)
1206 MEDIADEMUXER_FENTER();
1207 int ret = MD_ERROR_NONE;
1208 GstStructure *struc = NULL;
1211 int frame_rate_numerator = 0;
1212 int frame_rate_denominator = 0;
1214 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1215 struc = gst_caps_get_structure(head->caps, 0);
1217 MD_E("cannot get structure from caps.\n");
1220 if (gst_structure_has_name(struc, "video/x-h264")) {
1221 mime_type = MEDIA_FORMAT_H264_SP;
1222 } else if (gst_structure_has_name(struc, "video/x-h263")) {
1223 mime_type = MEDIA_FORMAT_H263;
1224 } else if (gst_structure_has_name(struc, "video/mpeg")) {
1225 mime_type = MEDIA_FORMAT_MPEG4_SP;
1227 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
1230 if (media_format_set_video_mime(format, mime_type)) {
1231 MD_E("Unable to set video mime type (%x)\n", mime_type);
1234 gst_structure_get_int(struc, "width", &src_width);
1235 gst_structure_get_int(struc, "height", &src_height);
1236 if (media_format_set_video_width(format, src_width)) {
1237 MD_E("Unable to set video width\n");
1240 if (media_format_set_video_height(format, src_height)) {
1241 MD_E("Unable to set video height\n");
1244 gst_structure_get_fraction(struc, "framerate", &frame_rate_numerator, &frame_rate_denominator);
1246 /* Round off the framerate */
1247 if (frame_rate_denominator)
1248 frame_rate = (int)floor(((gdouble)frame_rate_numerator / frame_rate_denominator) + 0.5);
1250 MD_I("set frame rate %d", frame_rate);
1251 if (media_format_set_video_frame_rate(format, frame_rate)) {
1252 MD_E("Unable to set video frame rate\n");
1255 MEDIADEMUXER_FLEAVE();
1258 MEDIADEMUXER_FLEAVE();
1262 int _set_mime_audio(media_format_h format, track *head)
1264 MEDIADEMUXER_FENTER();
1265 int ret = MD_ERROR_NONE;
1266 GstStructure *struc = NULL;
1271 const gchar *stream_format = NULL;
1272 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1274 struc = gst_caps_get_structure(head->caps, 0);
1276 MD_E("cannot get structure from caps.\n");
1280 if (gst_structure_has_name(struc, "application/x-id3"))
1282 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1285 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1286 if (mpegversion == 4 || mpegversion == 2) {
1287 mime_type = MEDIA_FORMAT_AAC_LC;
1288 if (media_format_set_audio_mime(format, mime_type))
1290 stream_format = gst_structure_get_string(struc, "stream-format");
1292 if (stream_format) {
1293 if (strncmp(stream_format, "adts", 4) == 0)
1294 media_format_set_audio_aac_type(format, 1);
1296 media_format_set_audio_aac_type(format, 0);
1299 } else if (mpegversion == 1 || id3_flag) {
1300 gst_structure_get_int(struc, "layer", &layer);
1301 if ((layer == 3) || (id3_flag == 1)) {
1302 mime_type = MEDIA_FORMAT_MP3;
1304 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1308 } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1309 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1310 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1311 mime_type = MEDIA_FORMAT_AMR_NB;
1314 mime_type = MEDIA_FORMAT_AMR_WB;
1317 } else if (gst_structure_has_name(struc, "audio/AMR")) {
1318 mime_type = MEDIA_FORMAT_AMR_NB;
1319 } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1320 mime_type = MEDIA_FORMAT_AMR_WB;
1321 } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1322 mime_type = MEDIA_FORMAT_PCM;
1323 } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1324 mime_type = MEDIA_FORMAT_FLAC;
1325 } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1326 mime_type = MEDIA_FORMAT_VORBIS;
1328 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1331 if (media_format_set_audio_mime(format, mime_type))
1333 gst_structure_get_int(struc, "channels", &channels);
1334 if (channels == 0) { /* default */
1335 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1340 if (media_format_set_audio_channel(format, channels))
1343 gst_structure_get_int(struc, "rate", &rate);
1345 rate = 44100; /* default */
1346 if (media_format_set_audio_samplerate(format, rate))
1348 gst_structure_get_int(struc, "bit", &bit);
1350 bit = 16; /* default */
1351 if (media_format_set_audio_bit(format, bit))
1353 MEDIADEMUXER_FLEAVE();
1356 MEDIADEMUXER_FLEAVE();
1360 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1361 media_format_h *format, int index)
1363 MEDIADEMUXER_FENTER();
1364 int ret = MD_ERROR_NONE;
1365 MEDIADEMUXER_CHECK_NULL(pHandle);
1366 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1371 temp = (new_mediademuxer->info).head;
1372 loop = (new_mediademuxer->info).num_video_track +
1373 (new_mediademuxer->info).num_audio_track +
1374 (new_mediademuxer->info).num_subtitle_track +
1375 (new_mediademuxer->info).num_other_track;
1376 if (index >= loop || index < 0) {
1377 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1382 while (count != index) {
1386 if (temp->format != NULL) {
1387 ret = media_format_ref(temp->format);
1388 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1389 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1390 ret = MD_INTERNAL_ERROR;
1393 ret = media_format_make_writable(temp->format, format); /* copy the content */
1394 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1395 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1396 media_format_unref(temp->format);
1397 ret = MD_INTERNAL_ERROR;
1400 MEDIADEMUXER_FLEAVE();
1403 ret = media_format_create(&(temp->format));
1404 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1405 MD_E("Mediaformat creation failed. returned %d\n", ret);
1406 ret = MD_INTERNAL_ERROR;
1410 MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1411 MD_I("format ptr[%p]\n", temp->format);
1412 if (temp->caps_string[0] == 'a') {
1413 MD_I("Setting for Audio \n");
1414 _set_mime_audio(temp->format, temp);
1415 } else if (temp->caps_string[0] == 'v') {
1416 MD_I("Setting for Video \n");
1417 _set_mime_video(temp->format, temp);
1418 } else if (temp->caps_string[0] == 't') {
1419 MD_I("Setting for Subtitle\n");
1420 _set_mime_text(temp->format, temp);
1422 MD_W("Not supported so far (except audio, video and subtitle)\n");
1425 ret = media_format_ref(temp->format); /* increment the ref to retain the original content */
1426 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1427 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1428 ret = MD_INTERNAL_ERROR;
1431 ret = media_format_make_writable(temp->format, format); /* copy the content */
1432 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1433 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1434 media_format_unref(temp->format);
1435 ret = MD_INTERNAL_ERROR;
1438 MEDIADEMUXER_FLEAVE();
1441 MEDIADEMUXER_FLEAVE();
1445 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1446 GstBuffer *buffer, GstBuffer *codec_data)
1448 MEDIADEMUXER_FENTER();
1449 int ret = MD_ERROR_NONE;
1450 MEDIADEMUXER_CHECK_NULL(out_pkt);
1455 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1456 MD_E("gst_buffer_map failed\n");
1457 ret = MD_ERROR_UNKNOWN;
1461 media_packet_get_buffer_size(out_pkt, &size);
1462 MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1463 if (size < (uint64_t)map.size) {
1464 MD_W("Media packet Buffer capacity[%llu] is \
1465 less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1466 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1467 media_packet_get_buffer_size(out_pkt, &size);
1468 MD_I("Media packet Buffer NEW capacity: %llu \n", size);
1470 if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1471 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1472 ret = MD_ERROR_UNKNOWN;
1475 memcpy((char *)pkt_data, map.data, map.size);
1476 if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1477 MD_E("unable to set the pts\n");
1478 ret = MD_ERROR_UNKNOWN;
1481 if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1482 MD_E("unable to set the dts\n");
1483 ret = MD_ERROR_UNKNOWN;
1486 if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1487 MD_E("unable to set the duration\n");
1488 ret = MD_ERROR_UNKNOWN;
1491 if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1492 MD_E("unable to set the buffer size\n");
1493 ret = MD_ERROR_UNKNOWN;
1496 if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
1497 if (media_packet_set_flags(out_pkt, MEDIA_PACKET_SYNC_FRAME)) {
1498 MD_E("unable to set the buffer flag\n");
1499 ret = MD_ERROR_UNKNOWN;
1503 /* set codec data into media packet */
1505 GstMapInfo codec_data_map;
1506 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1507 MD_E("codec data buffer map failed\n");
1508 ret = MD_ERROR_UNKNOWN;
1511 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1512 (unsigned int)codec_data_map.size)) {
1513 MD_E("unable to set the codec data\n");
1514 ret = MD_ERROR_UNKNOWN;
1515 gst_buffer_unmap(codec_data, &codec_data_map);
1518 gst_buffer_unmap(codec_data, &codec_data_map);
1520 media_buffer_flags_e flags;
1521 media_packet_get_flags(out_pkt, &flags);
1522 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1525 gst_buffer_unmap(buffer, &map);
1526 MEDIADEMUXER_FLEAVE();
1530 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1532 media_packet_h mediabuf = NULL;
1533 int ret = MD_ERROR_NONE;
1535 MEDIADEMUXER_FENTER();
1536 if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1537 MD_E("media_packet_create_alloc failed\n");
1542 if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1543 MD_E("unable to set EOS flag\n");
1544 ret = MD_ERROR_UNKNOWN;
1549 MEDIADEMUXER_FLEAVE();
1554 media_packet_destroy(mediabuf);
1556 MEDIADEMUXER_FLEAVE();
1560 static int gst_demuxer_read_sample(MMHandleType pHandle,
1561 media_packet_h *outbuf, int track_indx)
1563 MEDIADEMUXER_FENTER();
1564 int ret = MD_ERROR_NONE;
1565 MEDIADEMUXER_CHECK_NULL(pHandle);
1566 mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1568 media_packet_h mediabuf = NULL;
1571 track *atrack = demuxer->info.head;
1572 if ((demuxer->selected_tracks)[track_indx] == false) {
1573 MD_E("Track Not selected\n");
1578 if (indx == track_indx) /* Got the requird track details */
1581 track *next = atrack->next;
1584 MD_E("Invalid track Index\n");
1585 ret = MD_ERROR_INVALID_ARGUMENT;
1592 MD_E("atrack is NULL\n");
1596 if (indx != track_indx) {
1597 MD_E("Invalid track Index\n");
1598 ret = MD_ERROR_INVALID_ARGUMENT;
1601 GstElement *sink = atrack->appsink;
1602 GstSample *sample = NULL;
1604 sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1605 if (sample == NULL) {
1606 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1607 MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1608 ret = MD_ERROR_NONE;
1610 __gst_eos_callback(track_indx, demuxer);
1613 _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1616 MD_E("gst_demuxer_read_sample failed\n");
1618 ret = MD_ERROR_UNKNOWN;
1623 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1624 MD_E("media_packet_create_alloc failed\n");
1629 GstBuffer *buffer = gst_sample_get_buffer(sample);
1630 if (buffer == NULL) {
1631 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1632 ret = MD_ERROR_UNKNOWN;
1636 GstBuffer *codec_data_buffer = NULL;
1637 /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1638 if (atrack->need_codec_data) {
1639 atrack->need_codec_data = FALSE;
1640 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1641 GstStructure *structure = NULL;
1642 const GValue *value = NULL;
1644 structure = gst_caps_get_structure(atrack->caps, 0);
1645 /* get codec data from caps*/
1646 value = gst_structure_get_value(structure, "codec_data");
1648 codec_data_buffer = gst_value_get_buffer(value);
1651 /* Fill the media_packet with proper information */
1652 ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1653 gst_sample_unref(sample);
1656 MEDIADEMUXER_FLEAVE();
1660 media_packet_destroy(mediabuf);
1662 MEDIADEMUXER_FLEAVE();
1666 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1668 MEDIADEMUXER_FENTER();
1669 MEDIADEMUXER_CHECK_NULL(pHandle);
1670 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1674 track_info *head_track = &(gst_handle->info);
1675 track *temp = head_track->head;
1676 track *temp_track = head_track->head;
1678 bool is_seek = FALSE;
1680 /* Setting each appsink to paused state before seek */
1681 while (temp_track) {
1682 if (gst_handle->selected_tracks[indx] == true) {
1683 if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1684 MD_E("Failed to set into PAUSED state");
1687 MD_I("set the state to paused\n");
1690 if (temp_track->next) {
1691 track *next = temp_track->next;
1698 pos = pos1 * GST_MSECOND;
1700 MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1704 MD_I("Got one element %p {%s}\n", temp->appsink, GST_ELEMENT_NAME(temp->appsink));
1705 if (gst_handle->selected_tracks[indx] == true) {
1706 temp->need_codec_data = TRUE;
1709 if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1710 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1711 GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1712 MD_E("Seek failed!\n");
1717 MD_I("Seek success...setting appsink to playing state\n");
1718 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1719 MD_E("Failed to set into PLAYING state");
1725 track *next = temp->next;
1732 MEDIADEMUXER_FLEAVE();
1733 return MD_ERROR_NONE;
1735 MEDIADEMUXER_FLEAVE();
1739 int _gst_unset_appsink(track *temp, int index, int loop)
1741 MEDIADEMUXER_FENTER();
1742 int ret = MD_ERROR_NONE;
1745 while (count != index) {
1749 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1750 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1751 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), false);
1752 MEDIADEMUXER_FLEAVE();
1756 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1758 MEDIADEMUXER_FENTER();
1759 int ret = MD_ERROR_NONE;
1760 MEDIADEMUXER_CHECK_NULL(pHandle);
1761 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1763 if (track >= new_mediademuxer->total_tracks || track < 0) {
1764 MD_E("total tracks is less then unselected track, So not support this track");
1765 ret = MD_ERROR_INVALID_ARGUMENT;
1768 new_mediademuxer->selected_tracks[track] = false;
1769 _gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1770 new_mediademuxer->total_tracks);
1771 MEDIADEMUXER_FLEAVE();
1774 MEDIADEMUXER_FLEAVE();
1778 static int gst_demuxer_stop(MMHandleType pHandle)
1780 MEDIADEMUXER_FENTER();
1781 int ret = MD_ERROR_NONE;
1782 MEDIADEMUXER_CHECK_NULL(pHandle);
1783 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1785 MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1786 if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1787 GST_STATE_CHANGE_FAILURE) {
1788 MD_E("Failed to set into PAUSE state");
1789 ret = MD_INTERNAL_ERROR;
1792 MEDIADEMUXER_FLEAVE();
1795 MEDIADEMUXER_FLEAVE();
1799 void _gst_clear_struct(mdgst_handle_t *gst_handle)
1801 MEDIADEMUXER_FENTER();
1802 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
1803 if (gst_handle->selected_tracks) {
1804 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1805 gst_handle->selected_tracks);
1806 g_free(gst_handle->selected_tracks);
1807 gst_handle->selected_tracks = NULL;
1809 if ((gst_handle->info).head)
1810 __gst_free_stuct(&(gst_handle->info).head);
1811 MEDIADEMUXER_FLEAVE();
1814 int _md_gst_destroy_pipeline(GstElement *pipeline)
1816 MEDIADEMUXER_FENTER();
1817 int ret = MD_ERROR_NONE;
1819 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1821 gst_object_unref(GST_OBJECT(pipeline));
1822 MEDIADEMUXER_FLEAVE();
1826 gst_object_unref(GST_OBJECT(pipeline));
1827 MEDIADEMUXER_FLEAVE();
1831 static int gst_demuxer_unprepare(MMHandleType pHandle)
1833 MEDIADEMUXER_FENTER();
1834 int ret = MD_ERROR_NONE;
1835 MEDIADEMUXER_CHECK_NULL(pHandle);
1836 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1838 /*Modification : Fix pipeline state change was block by appsink When EOS received and appsink also has many datas*/
1840 track *atrack = gst_handle->info.head;
1842 if ((gst_handle->selected_tracks)[indx] == false) {
1843 MD_I("Track [%d] Not selected\n", indx);
1845 MD_I("Track [%d] to unset appsink...\n", indx);
1846 gst_demuxer_unset_track(pHandle, indx);
1849 track *next = atrack->next;
1857 _gst_clear_struct(gst_handle);
1858 if (gst_handle->bus_watch_id) {
1859 GSource *source = NULL;
1860 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1862 g_source_destroy(source);
1863 LOGD("Deallocation bus watch id");
1867 MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1868 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1872 MEDIADEMUXER_FLEAVE();
1875 MEDIADEMUXER_FLEAVE();
1879 static int gst_demuxer_destroy(MMHandleType pHandle)
1881 MEDIADEMUXER_FENTER();
1882 int ret = MD_ERROR_NONE;
1883 MEDIADEMUXER_CHECK_NULL(pHandle);
1884 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1886 MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1888 g_free(new_mediademuxer);
1889 MEDIADEMUXER_FLEAVE();
1893 int gst_set_error_cb(MMHandleType pHandle,
1894 gst_error_cb callback, void *user_data)
1896 MEDIADEMUXER_FENTER();
1897 int ret = MD_ERROR_NONE;
1898 MEDIADEMUXER_CHECK_NULL(pHandle);
1899 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1901 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1902 MD_E("Already set mediademuxer_error_cb\n");
1903 ret = MD_ERROR_INVALID_ARGUMENT;
1907 MD_E("fail invaild argument (callback)\n");
1908 ret = MD_ERROR_INVALID_ARGUMENT;
1913 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1915 gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1916 gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1917 MEDIADEMUXER_FLEAVE();
1918 return MD_ERROR_NONE;
1920 MEDIADEMUXER_FLEAVE();
1924 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1926 MEDIADEMUXER_FENTER();
1927 int ret = MD_ERROR_NONE;
1928 MEDIADEMUXER_CHECK_NULL(pHandle);
1929 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1931 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1932 MD_E("Already set mediademuxer_eos_cb\n");
1933 ret = MD_ERROR_INVALID_ARGUMENT;
1937 MD_E("fail invaild argument (callback)\n");
1938 ret = MD_ERROR_INVALID_ARGUMENT;
1943 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1944 gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1945 gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1946 MEDIADEMUXER_FLEAVE();
1947 return MD_ERROR_NONE;
1949 MEDIADEMUXER_FLEAVE();
1953 static int __gst_eos_callback(int track_num, void* user_data)
1955 if (user_data == NULL) {
1956 MD_E("Invalid argument");
1959 mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1960 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1961 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1962 gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1964 MD_E("EOS received, but callback is not set!!!");
1965 return MD_ERROR_NONE;