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
26 #include <mediademuxer_error.h>
27 #include <mediademuxer_private.h>
28 #include <mediademuxer_port.h>
29 #include <mediademuxer_port_gst.h>
30 #include <media_packet_internal.h>
33 static int __gst_demuxer_init(MMHandleType *pHandle);
34 static int __gst_demuxer_prepare(MMHandleType pHandle, char *uri);
35 static int __gst_demuxer_get_data_count(MMHandleType pHandle, int *count);
36 static int __gst_demuxer_set_track(MMHandleType pHandle, int track);
37 static int __gst_demuxer_start(MMHandleType pHandle);
38 static int __gst_demuxer_read_sample(MMHandleType pHandle,
39 media_packet_h *outbuf, int track_indx);
40 static int __gst_demuxer_get_track_info(MMHandleType pHandle,
41 media_format_h *format, int index);
42 static int __gst_demuxer_seek(MMHandleType pHandle, gint64 pos1);
43 static int __gst_demuxer_unset_track(MMHandleType pHandle, int track);
44 static int __gst_demuxer_stop(MMHandleType pHandle);
45 static int __gst_demuxer_unprepare(MMHandleType pHandle);
46 static int __gst_demuxer_destroy(MMHandleType pHandle);
47 static int __gst_set_error_cb(MMHandleType pHandle,
48 gst_error_cb callback, void *user_data);
49 static int __gst_set_eos_cb(MMHandleType pHandle,
50 gst_eos_cb callback, void *user_data);
51 static int __gst_eos_callback(int track_num, void *user_data);
53 /* Media Demuxer API common */
54 static media_port_demuxer_ops def_demux_ops = {
56 .init = __gst_demuxer_init,
57 .prepare = __gst_demuxer_prepare,
58 .get_track_count = __gst_demuxer_get_data_count,
59 .set_track = __gst_demuxer_set_track,
60 .start = __gst_demuxer_start,
61 .get_track_info = __gst_demuxer_get_track_info,
62 .read_sample = __gst_demuxer_read_sample,
63 .seek = __gst_demuxer_seek,
64 .unset_track = __gst_demuxer_unset_track,
65 .stop = __gst_demuxer_stop,
66 .unprepare = __gst_demuxer_unprepare,
67 .destroy = __gst_demuxer_destroy,
68 .set_error_cb = __gst_set_error_cb,
69 .set_eos_cb = __gst_set_eos_cb,
72 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code)
74 gint trans_err = MEDIADEMUXER_ERROR_NONE;
76 MEDIADEMUXER_CHECK_NULL(gst_handle);
79 case GST_CORE_ERROR_MISSING_PLUGIN:
80 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
81 case GST_CORE_ERROR_STATE_CHANGE:
82 case GST_CORE_ERROR_SEEK:
83 case GST_CORE_ERROR_NOT_IMPLEMENTED:
84 case GST_CORE_ERROR_FAILED:
85 case GST_CORE_ERROR_TOO_LAZY:
86 case GST_CORE_ERROR_PAD:
87 case GST_CORE_ERROR_THREAD:
88 case GST_CORE_ERROR_NEGOTIATION:
89 case GST_CORE_ERROR_EVENT:
90 case GST_CORE_ERROR_CAPS:
91 case GST_CORE_ERROR_TAG:
92 case GST_CORE_ERROR_CLOCK:
93 case GST_CORE_ERROR_DISABLED:
95 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
102 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code)
104 gint trans_err = MEDIADEMUXER_ERROR_NONE;
106 MEDIADEMUXER_CHECK_NULL(gst_handle);
109 case GST_LIBRARY_ERROR_FAILED:
110 case GST_LIBRARY_ERROR_TOO_LAZY:
111 case GST_LIBRARY_ERROR_INIT:
112 case GST_LIBRARY_ERROR_SHUTDOWN:
113 case GST_LIBRARY_ERROR_SETTINGS:
114 case GST_LIBRARY_ERROR_ENCODE:
116 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
124 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code)
126 gint trans_err = MEDIADEMUXER_ERROR_NONE;
128 MEDIADEMUXER_CHECK_NULL(gst_handle);
131 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
132 trans_err = MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
134 case GST_RESOURCE_ERROR_WRITE:
135 case GST_RESOURCE_ERROR_FAILED:
136 case GST_RESOURCE_ERROR_SEEK:
137 case GST_RESOURCE_ERROR_TOO_LAZY:
138 case GST_RESOURCE_ERROR_BUSY:
139 case GST_RESOURCE_ERROR_OPEN_WRITE:
140 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
141 case GST_RESOURCE_ERROR_CLOSE:
142 case GST_RESOURCE_ERROR_SYNC:
143 case GST_RESOURCE_ERROR_SETTINGS:
145 trans_err = MEDIADEMUXER_ERROR_RESOURCE_LIMIT;
152 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error)
154 gchar *src_element_name = NULL;
155 GstElement *src_element = NULL;
156 GstElementFactory *factory = NULL;
157 const gchar *klass = NULL;
159 MEDIADEMUXER_CHECK_NULL(gst_handle);
161 src_element = GST_ELEMENT_CAST(message->src);
165 src_element_name = GST_ELEMENT_NAME(src_element);
166 if (!src_element_name)
169 factory = gst_element_get_factory(src_element);
173 klass = gst_element_factory_get_klass(factory);
177 MD_I("error code=%d, msg=%s, src element=%s, class=%s\n",
178 error->code, error->message, src_element_name, klass);
180 switch (error->code) {
181 case GST_STREAM_ERROR_DECODE:
182 case GST_STREAM_ERROR_FAILED:
183 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
186 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
187 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
188 case GST_STREAM_ERROR_WRONG_TYPE:
189 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
193 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
197 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
200 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
203 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message)
205 gint trans_err = MEDIADEMUXER_ERROR_NONE;
207 MEDIADEMUXER_CHECK_NULL(gst_handle);
208 MEDIADEMUXER_CHECK_NULL(error);
209 MEDIADEMUXER_CHECK_NULL(message);
211 switch (error->code) {
212 case GST_STREAM_ERROR_FAILED:
213 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
214 case GST_STREAM_ERROR_DECODE:
215 case GST_STREAM_ERROR_WRONG_TYPE:
216 case GST_STREAM_ERROR_DECRYPT:
217 case GST_STREAM_ERROR_DECRYPT_NOKEY:
218 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
219 trans_err = __gst_transform_gsterror(gst_handle, message, error);
222 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
223 case GST_STREAM_ERROR_TOO_LAZY:
224 case GST_STREAM_ERROR_ENCODE:
225 case GST_STREAM_ERROR_DEMUX:
226 case GST_STREAM_ERROR_MUX:
227 case GST_STREAM_ERROR_FORMAT:
229 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
236 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
238 MEDIADEMUXER_FENTER();
239 int ret = MD_ERROR_NONE;
240 MEDIADEMUXER_CHECK_NULL(pOps);
241 def_demux_ops.n_size = sizeof(def_demux_ops);
243 memcpy((char *)pOps + sizeof(pOps->n_size),
244 (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
245 pOps->n_size - sizeof(pOps->n_size));
247 MEDIADEMUXER_FLEAVE();
251 static int __gst_demuxer_init(MMHandleType *pHandle)
253 MEDIADEMUXER_FENTER();
254 int ret = MD_ERROR_NONE;
255 mdgst_handle_t *new_mediademuxer = NULL;
256 new_mediademuxer = (mdgst_handle_t *)g_try_malloc0(sizeof(mdgst_handle_t));
257 if (!new_mediademuxer) {
258 MD_E("Cannot allocate memory for demuxer\n");
262 MD_I("__gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
263 new_mediademuxer->is_prepared = false;
264 (new_mediademuxer->info).num_audio_track = 0;
265 (new_mediademuxer->info).num_video_track = 0;
266 (new_mediademuxer->info).num_subtitle_track = 0;
267 (new_mediademuxer->info).num_other_track = 0;
268 (new_mediademuxer->info).head = NULL;
269 *pHandle = (MMHandleType)new_mediademuxer;
270 new_mediademuxer->total_tracks = 0;
271 MEDIADEMUXER_FLEAVE();
274 MEDIADEMUXER_FLEAVE();
278 static gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
280 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
281 MEDIADEMUXER_FENTER();
282 int ret = MD_ERROR_NONE;
283 switch (GST_MESSAGE_TYPE(msg)) {
284 case GST_MESSAGE_EOS: {
288 case GST_MESSAGE_ERROR: {
289 GError *error = NULL;
290 gst_message_parse_error(msg, &error, NULL);
292 MD_I("GST error message parsing failed");
296 if (error->domain == GST_STREAM_ERROR)
297 ret = __gst_handle_stream_error(gst_handle, error, msg);
298 else if (error->domain == GST_RESOURCE_ERROR)
299 ret = __gst_handle_resource_error(gst_handle, error->code);
300 else if (error->domain == GST_LIBRARY_ERROR)
301 ret = __gst_handle_library_error(gst_handle, error->code);
302 else if (error->domain == GST_CORE_ERROR)
303 ret = __gst_handle_core_error(gst_handle, error->code);
305 MD_W("Unexpected error has occurred");
307 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
308 ((mediademuxer_error_cb)gst_handle->user_cb[_GST_EVENT_TYPE_ERROR])
309 (ret, gst_handle->user_data[_GST_EVENT_TYPE_ERROR]);
310 MD_W("Error : (ox%08x)", ret);
312 MD_E("Error: %s\n", error->message);
319 MEDIADEMUXER_FLEAVE();
323 static void __gst_no_more_pad(GstElement *element, gpointer data)
325 MEDIADEMUXER_FENTER();
326 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
327 track_info *head_track = &(gst_handle->info);
328 track *head = head_track->head;
329 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
330 gst_handle->selected_tracks =
331 (bool *) g_malloc0_n(sizeof(bool), gst_handle->total_tracks);
332 MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
333 MD_I("Number of video tracks are %d\n", head_track->num_video_track);
334 MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
335 MD_I("Number of subtitle tracks are %d\n",
336 head_track->num_subtitle_track);
337 MD_I("Number of other tracks are %d\n", head_track->num_other_track);
339 MD_I("track caps[%s]\n", head->caps_string);
342 gst_handle->is_prepared = true;
343 MD_I("core->is_prepared: true");
344 MEDIADEMUXER_FLEAVE();
347 static void __gst_free_stuct(track **head)
349 MEDIADEMUXER_FENTER();
355 MD_I("unref GST_PAD %p\n", temp->pad);
356 gst_object_unref(temp->pad);
359 MD_I("unref GST_PAD caps %p\n", temp->caps);
360 gst_caps_unref(temp->caps);
362 if (temp->caps_string) {
363 MD_I("deallocate GST_PAD caps_string %p\n",
365 g_free(temp->caps_string);
368 MD_I("unref media_format %p\n", temp->format);
369 media_format_unref(temp->format);
372 track *next = temp->next;
373 MD_I("deallocate memory %p\n", temp);
377 MD_I("deallocate memory %p\n", temp);
383 MEDIADEMUXER_FLEAVE();
386 static int __gst_add_track_info(GstPad *pad, GstCaps *caps, track **head,
387 GstElement *pipeline)
389 MEDIADEMUXER_FENTER();
390 GstPad *apppad = NULL;
391 GstPad *queue_sink_pad = NULL;
392 GstPad *queue_src_pad = NULL;
393 GstCaps *outcaps = NULL;
394 GstPad *parse_sink_pad = NULL;
395 GstElement *parse_element = NULL;
396 GstElement *id3tag = NULL;
397 GstPad *id3_sinkpad = NULL;
398 GstPad *id3_srcpad = NULL;
401 temp = (track *)(g_malloc0(sizeof(track)));
402 MD_I("allocate memory %p", temp);
404 temp->pad = gst_object_ref(pad);
405 temp->caps = gst_caps_ref(caps);
406 temp->caps_string = gst_caps_to_string(caps);
409 temp->need_codec_data = TRUE;
411 MD_I("track caps(%s)", temp->caps_string ? temp->caps_string : "NULL");
413 /* Link demuxer - queue */
414 temp->queue = gst_element_factory_make("queue", NULL);
416 MD_E("factory not able to make queue");
420 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
421 gst_object_unref(temp->queue);
422 MD_E("fail add queue in pipeline");
425 MD_I("added queue element in pipeline.");
427 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
428 if (!queue_sink_pad) {
429 MD_E("sink pad of queue not available");
433 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
434 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->queue, ERROR);
436 temp->appsink = gst_element_factory_make("appsink", NULL);
437 if (!temp->appsink) {
438 MD_E("factory not able to make appsink");
441 g_object_set(G_OBJECT(temp->appsink), "wait-on-eos", TRUE, NULL);
443 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
444 gst_object_unref(temp->appsink);
445 MD_E("fail add appsink in pipeline");
448 MD_I("added appsink element in pipeline.");
450 gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
451 gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
453 queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
454 if (!queue_src_pad) {
455 MD_E("src pad of queue not available");
458 apppad = gst_element_get_static_pad(temp->appsink, "sink");
460 MD_E("sink pad of appsink not available");
463 /* Check for type video and it should be h264 */
464 if (temp->caps_string && strstr(temp->caps_string, "video")) {
465 if (strstr(temp->caps_string, "h264")) {
466 parse_element = gst_element_factory_make("h264parse", NULL);
467 if (!parse_element) {
468 MD_E("factory not able to make h264parse");
471 } else if (strstr(temp->caps_string, "mpeg")) {
472 parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
473 if (!parse_element) {
474 MD_E("factory not able to make h264parse");
477 g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
481 MD_I("add video parse element(%s).", GST_ELEMENT_NAME(parse_element));
482 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
483 gst_object_unref(parse_element);
484 MD_E("fail add video parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
487 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
488 if (!parse_sink_pad) {
489 MD_E("sink pad of video parse(%s) not available", GST_ELEMENT_NAME(parse_element));
492 /* Link demuxer pad with sink pad of parse element */
493 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
495 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
497 if (strstr(temp->caps_string, "h264")) {
498 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
499 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
500 gst_caps_unref(outcaps);
501 temp->need_codec_data = FALSE;
502 } else if (strstr(temp->caps_string, "mpeg")) {
503 if (!gst_element_link(parse_element, temp->appsink)) {
504 MD_E("failed to link parse element to appsink");
508 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
511 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
513 } else if (temp->caps_string && (strstr(temp->caps_string, "audio") || strstr(temp->caps_string, "x-id3"))) {
514 if (strstr(temp->caps_string, "audio/mpeg")) {
516 GstStructure *structure = NULL;
517 structure = gst_caps_get_structure(temp->caps, 0);
518 gst_structure_get_int (structure, "mpegversion", &mpegversion);
519 if (mpegversion == 2 || mpegversion == 4) {
520 parse_element = gst_element_factory_make("aacparse", NULL);
521 if (!parse_element) {
522 MD_E("factory not able to make aacparse");
525 } else if (mpegversion == 1) {
526 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
527 if (!parse_element) {
528 MD_E("factory not able to make mpegaudioparse");
532 } else if (strstr(temp->caps_string, "application/x-id3")) {
533 id3tag = gst_element_factory_make("id3demux", NULL);
535 MD_E("factory not able to make id3demux");
538 if (!gst_bin_add(GST_BIN(pipeline), id3tag)) {
539 gst_object_unref(id3tag);
540 MD_E("fail add id3tag element in pipeline");
543 id3_sinkpad = gst_element_get_static_pad(id3tag, "sink");
545 MD_E("fail to get id3demux sink pad.\n");
548 MEDIADEMUXER_LINK_PAD(queue_src_pad, id3_sinkpad, ERROR);
549 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(id3tag, ERROR);
550 id3_srcpad = gst_element_get_static_pad(id3tag, "src");
552 MD_E("fail to get id3demux src pad.\n");
555 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
556 if (!parse_element) {
557 MD_E("factory not able to make mpegaudioparse");
560 } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
561 || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
562 parse_element = gst_element_factory_make("amrparse", NULL);
563 if (!parse_element) {
564 MD_E("factory not able to make amrparse");
567 } else if (strstr(temp->caps_string, "audio/x-wav")) {
568 parse_element = gst_element_factory_make("wavparse", NULL);
569 if (!parse_element) {
570 MD_E("factory not able to make wavparse");
573 } else if (strstr(temp->caps_string, "audio/x-flac")) {
574 parse_element = gst_element_factory_make("flacparse", NULL);
575 if (!parse_element) {
576 MD_E("factory not able to make flacparse");
582 MD_I("add audio parse element(%s).", GST_ELEMENT_NAME(parse_element));
583 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
584 gst_object_unref(parse_element);
585 MD_E("fail add audio parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
588 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
589 if (!parse_sink_pad) {
590 MD_E("sink pad of audio parse(%s) not available", GST_ELEMENT_NAME(parse_element));
594 /* Link demuxer pad with sink pad of parse element */
596 MEDIADEMUXER_LINK_PAD(id3_srcpad, parse_sink_pad, ERROR);
598 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
600 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
602 /* Link src pad with appSink element */
603 if (!gst_element_link(parse_element, temp->appsink)) {
604 MD_E("failed to link parse element to appsink");
608 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
611 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
614 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->appsink, ERROR);
615 /* gst_pad_link(pad, fpad) */
625 gst_object_unref(queue_sink_pad);
627 gst_object_unref(queue_src_pad);
629 gst_object_unref(apppad);
631 gst_object_unref(parse_sink_pad);
633 gst_object_unref(id3_sinkpad);
635 gst_object_unref(id3_srcpad);
636 MEDIADEMUXER_FLEAVE();
637 return MD_ERROR_NONE;
640 __gst_free_stuct(&temp);
642 gst_object_unref(queue_sink_pad);
644 gst_object_unref(queue_src_pad);
646 gst_object_unref(apppad);
648 gst_object_unref(parse_sink_pad);
650 gst_object_unref(id3_sinkpad);
652 gst_object_unref(id3_srcpad);
653 __gst_free_stuct(head);
654 MEDIADEMUXER_FLEAVE();
658 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
660 MEDIADEMUXER_FENTER();
661 MD_I("Dynamic pad created, linking demuxer/decoder\n");
663 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
664 track_info *head_track = &(gst_handle->info);
665 GstCaps *caps = NULL;
666 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
667 caps = gst_pad_get_current_caps(pad);
669 MD_E("caps is NULL");
672 gst_handle->total_tracks++;
673 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline)
675 MD_E("unable to added track info");
676 head_track->num_audio_track = 0;
677 head_track->num_video_track = 0;
678 head_track->num_subtitle_track = 0;
679 head_track->num_other_track = 0;
680 gst_caps_unref(caps);
681 __gst_free_stuct(&(head_track->head));
684 gst_caps_unref(caps);
685 tmp = head_track->head;
688 MD_I("track is NULL\n");
689 MEDIADEMUXER_FLEAVE();
696 if (!tmp->caps_string) {
697 MD_I("track caps_string is NULL\n");
698 MEDIADEMUXER_FLEAVE();
702 if (tmp->caps_string[0] == 'v') {
703 MD_I("found Video Pad\n");
704 (head_track->num_video_track)++;
705 } else if (tmp->caps_string[0] == 'a') {
706 MD_I("found Audio Pad\n");
707 (head_track->num_audio_track)++;
708 } else if (tmp->caps_string[0] == 's') {
709 MD_I("found subtitle(or Text) Pad\n");
710 (head_track->num_subtitle_track)++;
712 MD_W("found Pad, caps: %s\n", tmp->caps_string);
713 (head_track->num_other_track)++;
715 MEDIADEMUXER_FLEAVE();
718 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
720 MEDIADEMUXER_FENTER();
721 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
723 track_info *head_track = &(gst_handle->info);
725 gst_handle->is_valid_container = true;
727 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
729 MD_E("fail to get typefind src pad.\n");
733 gst_handle->total_tracks++;
734 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
735 MD_E("unable to added track info");
736 head_track->num_audio_track = 0;
737 head_track->num_video_track = 0;
738 head_track->num_subtitle_track = 0;
739 head_track->num_other_track = 0;
740 __gst_free_stuct(&(head_track->head));
744 (head_track->num_audio_track)++;
748 gst_object_unref(pad);
750 /* In the case of audio only, there is no gst_handle->demux. So we pass NULL */
751 __gst_no_more_pad(NULL, data);
753 MEDIADEMUXER_FLEAVE();
754 return MD_ERROR_NONE;
757 gst_handle->is_valid_container = false;
760 gst_object_unref(pad);
762 MEDIADEMUXER_FLEAVE();
766 static void __gst_cb_typefind(GstElement *tf, guint probability,
767 GstCaps *caps, gpointer data)
769 MEDIADEMUXER_FENTER();
770 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
772 GstPad *demuxer_pad = NULL;
773 GstPad *fake_pad = NULL;
775 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
776 type = gst_caps_to_string(caps);
779 MD_E("Fail to get caps string");
783 MD_I("Media type %s found, probability %d%%\n", type, probability);
784 if (strstr(type, "quicktime") || strstr(type, "audio/x-m4a") ||
785 strstr(type, "x-3gp") || strstr(type, "ogg") ||
786 strstr(type, "flv") || strstr(type, "x-msvideo")) {
787 gst_handle->is_valid_container = true;
788 if (strstr(type, "ogg"))
789 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
790 else if (strstr(type, "flv"))
791 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
792 else if (strstr(type, "x-msvideo"))
793 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
795 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
797 if (!gst_handle->demux) {
798 gst_handle->is_valid_container = false;
799 MD_E("factory not able to create qtdemux\n");
802 g_signal_connect(gst_handle->demux, "pad-added",
803 G_CALLBACK(__gst_on_pad_added), gst_handle);
804 g_signal_connect(gst_handle->demux, "no-more-pads",
805 G_CALLBACK(__gst_no_more_pad), gst_handle);
806 gst_element_set_locked_state(gst_handle->demux, TRUE);
807 if (!gst_bin_add(GST_BIN(gst_handle->pipeline), gst_handle->demux)) {
808 MD_E("fail add demuxer(%s) in pipeline",
809 GST_ELEMENT_NAME(gst_handle->demux));
810 gst_object_unref(gst_handle->demux);
811 gst_handle->demux = NULL;
815 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
817 MD_E("fail to get typefind src pad.\n");
820 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
822 MD_E("fail to get qtdemux sink pad.\n");
825 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
827 MD_E("fail to get fakesink sink pad.\n");
830 gst_pad_unlink(pad, fake_pad);
831 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
833 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(gst_handle->demux, ERROR);
834 gst_element_set_locked_state(gst_handle->demux, FALSE);
836 gst_object_unref(pad);
838 gst_object_unref(demuxer_pad);
840 gst_object_unref(fake_pad);
842 } else if ((strstr(type, "adts"))
843 || (strstr(type, "audio/mpeg"))
844 || (strstr(type, "audio/x-wav"))
845 || (strstr(type, "audio/x-flac"))
846 || (strstr(type, "application/x-id3"))
847 || (strstr(type, "audio/x-amr-nb-sh"))
848 || (strstr(type, "audio/x-amr-wb-sh"))) {
849 MD_I("Audio only format is found\n");
850 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
852 MD_E("fail to get typefind src pad.\n");
855 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
857 MD_E("fail to get fakesink sink pad.\n");
860 gst_pad_unlink(pad, fake_pad);
862 gst_object_unref(pad);
864 gst_object_unref(fake_pad);
866 __gst_create_audio_only_pipeline(data, caps);
868 gst_handle->is_valid_container = false;
869 MD_E("Not supported container %s\n", type);
873 MEDIADEMUXER_FLEAVE();
877 gst_handle->is_valid_container = false;
880 if (gst_handle->demux)
881 gst_element_set_locked_state(gst_handle->demux, FALSE);
883 gst_object_unref(pad);
885 gst_object_unref(demuxer_pad);
887 gst_object_unref(fake_pad);
888 MEDIADEMUXER_FLEAVE();
892 static int __gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
894 MEDIADEMUXER_FENTER();
895 int ret = MD_ERROR_NONE;
898 #ifdef TIZEN_FEATURE_STREAMING
899 int remote_streaming = 0;
901 GstState element_state = GST_STATE_VOID_PENDING;
902 GstState element_pending_state = GST_STATE_VOID_PENDING;
904 /* Initialize GStreamer */
905 /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
906 gst_init(NULL, NULL);
908 /* Create the empty pipeline */
909 gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
910 if (!gst_handle->pipeline) {
911 MD_E("pipeline create fail");
916 /* Create the elements */
917 if ((path = strstr(uri, "http://"))) {
918 #ifdef TIZEN_FEATURE_STREAMING
919 gst_handle->filesrc = gst_element_factory_make("souphttpsrc", NULL);
920 remote_streaming = 1;
921 MD_I("Source is http stream. \n");
923 MD_I("Source is http stream. Didn't support streaming\n");
927 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
928 MD_I("Source is file stream \n");
930 if (!gst_handle->filesrc) {
931 MD_E("filesrc creation failed");
936 /* Modify the source's properties */
937 #ifdef TIZEN_FEATURE_STREAMING
938 if (remote_streaming == 1)
939 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
942 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
943 gst_handle->typefind = gst_element_factory_make("typefind", NULL);
944 if (!gst_handle->typefind) {
945 MD_E("typefind creation failed");
949 g_signal_connect(gst_handle->typefind, "have-type",
950 G_CALLBACK(__gst_cb_typefind), gst_handle);
951 gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
952 if (!gst_handle->fakesink) {
953 MD_E("fakesink creation failed");
958 /* Build the pipeline */
959 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
961 gst_handle->typefind,
962 gst_handle->fakesink,
964 gst_element_link_many(gst_handle->filesrc,
965 gst_handle->typefind,
966 gst_handle->fakesink,
969 /* connect signals, bus watcher */
970 bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
971 gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
972 gst_handle->thread_default = g_main_context_get_thread_default();
973 gst_object_unref(GST_OBJECT(bus));
975 /* set pipeline state to PAUSED */
976 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
978 if (gst_element_get_state(gst_handle->pipeline, &element_state, &element_pending_state, 1 * GST_SECOND)
979 == GST_STATE_CHANGE_FAILURE) {
980 MD_E(" [%s] state : %s pending : %s \n",
981 GST_ELEMENT_NAME(gst_handle->pipeline),
982 gst_element_state_get_name(element_state),
983 gst_element_state_get_name(element_pending_state));
988 if (gst_handle->is_prepared != true) {
994 MEDIADEMUXER_FLEAVE();
997 MEDIADEMUXER_FLEAVE();
1001 static int __gst_demuxer_prepare(MMHandleType pHandle, char *uri)
1003 MEDIADEMUXER_FENTER();
1004 int ret = MD_ERROR_NONE;
1005 MEDIADEMUXER_CHECK_NULL(pHandle);
1006 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1008 MD_I("__gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
1009 ret = __gst_create_pipeline(new_mediademuxer, uri);
1010 if (ret != MD_ERROR_NONE) {
1011 MD_E("__gst_create_pipeline() failed. returned %d\n", ret);
1014 MEDIADEMUXER_FLEAVE();
1017 MEDIADEMUXER_FLEAVE();
1021 static int __gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
1023 MEDIADEMUXER_FENTER();
1024 int ret = MD_ERROR_NONE;
1025 MEDIADEMUXER_CHECK_NULL(pHandle);
1026 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1028 *count = (new_mediademuxer->info).num_video_track +
1029 (new_mediademuxer->info).num_audio_track +
1030 (new_mediademuxer->info).num_subtitle_track +
1031 (new_mediademuxer->info).num_other_track;
1032 MEDIADEMUXER_FLEAVE();
1036 static int __gst_set_appsink(track *temp, int index, int loop)
1038 MEDIADEMUXER_FENTER();
1039 int ret = MD_ERROR_NONE;
1042 while (count != index) {
1046 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
1047 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
1048 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), true);
1049 MEDIADEMUXER_FLEAVE();
1053 static int __gst_demuxer_set_track(MMHandleType pHandle, int track)
1055 MEDIADEMUXER_FENTER();
1056 int ret = MD_ERROR_NONE;
1057 MEDIADEMUXER_CHECK_NULL(pHandle);
1058 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1060 MD_I("total_tracks (%d) :: selected track (%d)", new_mediademuxer->total_tracks, track);
1061 if (track >= new_mediademuxer->total_tracks || track < 0) {
1062 MD_E("total_tracks is less then selected track, So not support this track");
1063 ret = MD_ERROR_INVALID_ARGUMENT;
1066 new_mediademuxer->selected_tracks[track] = true;
1067 __gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1068 new_mediademuxer->total_tracks);
1069 MEDIADEMUXER_FLEAVE();
1070 return MD_ERROR_NONE;
1072 MEDIADEMUXER_FLEAVE();
1076 static int __gst_unlink_unselected_track(track *temp, int index)
1078 MEDIADEMUXER_FENTER();
1079 int ret = MD_ERROR_NONE;
1081 GstPad *queue_sink_pad = NULL;
1082 while (count != index) {
1086 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
1087 if (!queue_sink_pad) {
1088 MD_E("queue_sink_pad of appsink not available\n");
1091 if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
1092 MD_W("demuxer is already unlinked from queue for track %d\n", index);
1094 gst_object_unref(queue_sink_pad);
1095 MEDIADEMUXER_FLEAVE();
1099 static int __gst_demuxer_start(MMHandleType pHandle)
1101 MEDIADEMUXER_FENTER();
1102 int ret = MD_ERROR_NONE;
1103 MEDIADEMUXER_CHECK_NULL(pHandle);
1104 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1107 for (indx = 0; indx < gst_handle->total_tracks; indx++) {
1108 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
1109 indx, gst_handle->selected_tracks[indx]);
1111 if (gst_handle->selected_tracks[indx] == false)
1112 _gst_demuxer_unset(pHandle, indx);
1114 if (gst_handle->selected_tracks[indx] != true) {
1115 if (__gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
1116 MD_E("Failed to unlink unselected tracks\n");
1117 ret = MD_INTERNAL_ERROR;
1124 track_info *head_track = &(gst_handle->info);
1125 MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
1126 head_track->num_audio_track, head_track->num_video_track,
1127 head_track->num_subtitle_track);
1129 track *temp = head_track->head;
1132 MD_I("Got one element %p\n", temp->appsink);
1133 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
1134 GST_STATE_CHANGE_FAILURE) {
1135 MD_E("Failed to set into PLAYING state");
1136 ret = MD_INTERNAL_ERROR;
1139 MD_I("set the state to playing\n");
1142 track *next = temp->next;
1149 MD_I("__gst_demuxer_start pipeline %p", gst_handle);
1150 MEDIADEMUXER_FLEAVE();
1153 MEDIADEMUXER_FLEAVE();
1157 int _set_mime_text(media_format_h format, track *head)
1159 MEDIADEMUXER_FENTER();
1160 int ret = MD_ERROR_NONE;
1161 GstStructure *struc = NULL;
1162 struc = gst_caps_get_structure(head->caps, 0);
1164 MD_E("cannot get structure from caps.\n");
1167 if (gst_structure_has_name(struc, "text/x-raw")) {
1168 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
1171 MD_I("Text mime not supported so far\n");
1175 MEDIADEMUXER_FLEAVE();
1178 MEDIADEMUXER_FLEAVE();
1182 int _set_mime_video(media_format_h format, track *head)
1184 MEDIADEMUXER_FENTER();
1185 int ret = MD_ERROR_NONE;
1186 GstStructure *struc = NULL;
1189 int frame_rate_numerator = 0;
1190 int frame_rate_denominator = 0;
1192 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1193 struc = gst_caps_get_structure(head->caps, 0);
1195 MD_E("cannot get structure from caps.\n");
1198 if (gst_structure_has_name(struc, "video/x-h264")) {
1199 mime_type = MEDIA_FORMAT_H264_SP;
1200 } else if (gst_structure_has_name(struc, "video/x-h263")) {
1201 mime_type = MEDIA_FORMAT_H263;
1202 } else if (gst_structure_has_name(struc, "video/mpeg")) {
1203 mime_type = MEDIA_FORMAT_MPEG4_SP;
1205 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
1208 if (media_format_set_video_mime(format, mime_type)) {
1209 MD_E("Unable to set video mime type (%x)\n", mime_type);
1212 gst_structure_get_int(struc, "width", &src_width);
1213 gst_structure_get_int(struc, "height", &src_height);
1214 if (media_format_set_video_width(format, src_width)) {
1215 MD_E("Unable to set video width\n");
1218 if (media_format_set_video_height(format, src_height)) {
1219 MD_E("Unable to set video height\n");
1222 gst_structure_get_fraction(struc, "framerate", &frame_rate_numerator, &frame_rate_denominator);
1224 /* Round off the framerate */
1225 if (frame_rate_denominator)
1226 frame_rate = (int)floor(((gdouble)frame_rate_numerator / frame_rate_denominator) + 0.5);
1228 MD_I("set frame rate %d", frame_rate);
1229 if (media_format_set_video_frame_rate(format, frame_rate)) {
1230 MD_E("Unable to set video frame rate\n");
1233 MEDIADEMUXER_FLEAVE();
1236 MEDIADEMUXER_FLEAVE();
1240 int _set_mime_audio(media_format_h format, track *head)
1242 MEDIADEMUXER_FENTER();
1243 int ret = MD_ERROR_NONE;
1244 GstStructure *struc = NULL;
1249 const gchar *stream_format = NULL;
1250 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1252 struc = gst_caps_get_structure(head->caps, 0);
1254 MD_E("cannot get structure from caps.\n");
1258 if (gst_structure_has_name(struc, "application/x-id3"))
1260 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1263 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1264 if (mpegversion == 4 || mpegversion == 2) {
1265 mime_type = MEDIA_FORMAT_AAC_LC;
1266 if (media_format_set_audio_mime(format, mime_type))
1268 stream_format = gst_structure_get_string(struc, "stream-format");
1270 if (stream_format) {
1271 if (strncmp(stream_format, "adts", 4) == 0)
1272 media_format_set_audio_aac_type(format, 1);
1274 media_format_set_audio_aac_type(format, 0);
1277 } else if (mpegversion == 1 || id3_flag) {
1278 gst_structure_get_int(struc, "layer", &layer);
1279 if ((layer == 3) || (id3_flag == 1)) {
1280 mime_type = MEDIA_FORMAT_MP3;
1282 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1286 } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1287 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1288 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1289 mime_type = MEDIA_FORMAT_AMR_NB;
1292 mime_type = MEDIA_FORMAT_AMR_WB;
1295 } else if (gst_structure_has_name(struc, "audio/AMR")) {
1296 mime_type = MEDIA_FORMAT_AMR_NB;
1297 } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1298 mime_type = MEDIA_FORMAT_AMR_WB;
1299 } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1300 mime_type = MEDIA_FORMAT_PCM;
1301 } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1302 mime_type = MEDIA_FORMAT_FLAC;
1303 } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1304 mime_type = MEDIA_FORMAT_VORBIS;
1306 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1309 if (media_format_set_audio_mime(format, mime_type))
1311 gst_structure_get_int(struc, "channels", &channels);
1312 if (channels == 0) { /* default */
1313 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1318 if (media_format_set_audio_channel(format, channels))
1321 gst_structure_get_int(struc, "rate", &rate);
1323 rate = 44100; /* default */
1324 if (media_format_set_audio_samplerate(format, rate))
1326 gst_structure_get_int(struc, "bit", &bit);
1328 bit = 16; /* default */
1329 if (media_format_set_audio_bit(format, bit))
1331 MEDIADEMUXER_FLEAVE();
1334 MEDIADEMUXER_FLEAVE();
1338 static int __gst_demuxer_get_track_info(MMHandleType pHandle,
1339 media_format_h *format, int index)
1341 MEDIADEMUXER_FENTER();
1342 int ret = MD_ERROR_NONE;
1343 MEDIADEMUXER_CHECK_NULL(pHandle);
1344 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1349 temp = (new_mediademuxer->info).head;
1350 loop = (new_mediademuxer->info).num_video_track +
1351 (new_mediademuxer->info).num_audio_track +
1352 (new_mediademuxer->info).num_subtitle_track +
1353 (new_mediademuxer->info).num_other_track;
1354 if (index >= loop || index < 0) {
1355 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1360 while (count != index) {
1364 if (temp->format != NULL) {
1365 ret = media_format_ref(temp->format);
1366 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1367 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1368 ret = MD_INTERNAL_ERROR;
1371 ret = media_format_make_writable(temp->format, format); /* copy the content */
1372 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1373 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1374 media_format_unref(temp->format);
1375 ret = MD_INTERNAL_ERROR;
1378 MEDIADEMUXER_FLEAVE();
1381 ret = media_format_create(&(temp->format));
1382 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1383 MD_E("Mediaformat creation failed. returned %d\n", ret);
1384 ret = MD_INTERNAL_ERROR;
1388 MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1389 MD_I("format ptr[%p]\n", temp->format);
1390 if (temp->caps_string[0] == 'a') {
1391 MD_I("Setting for Audio \n");
1392 _set_mime_audio(temp->format, temp);
1393 } else if (temp->caps_string[0] == 'v') {
1394 MD_I("Setting for Video \n");
1395 _set_mime_video(temp->format, temp);
1396 } else if (temp->caps_string[0] == 't') {
1397 MD_I("Setting for Subtitle\n");
1398 _set_mime_text(temp->format, temp);
1400 MD_W("Not supported so far (except audio, video and subtitle)\n");
1403 ret = media_format_ref(temp->format); /* increment the ref to retain the original content */
1404 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1405 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1406 ret = MD_INTERNAL_ERROR;
1409 ret = media_format_make_writable(temp->format, format); /* copy the content */
1410 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1411 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1412 media_format_unref(temp->format);
1413 ret = MD_INTERNAL_ERROR;
1416 MEDIADEMUXER_FLEAVE();
1419 MEDIADEMUXER_FLEAVE();
1423 static int __gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1424 GstBuffer *buffer, GstBuffer *codec_data)
1426 MEDIADEMUXER_FENTER();
1427 int ret = MD_ERROR_NONE;
1428 MEDIADEMUXER_CHECK_NULL(out_pkt);
1433 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1434 MD_E("gst_buffer_map failed\n");
1435 ret = MD_ERROR_UNKNOWN;
1439 media_packet_get_buffer_size(out_pkt, &size);
1440 MD_I("Media packet Buffer capacity: %"PRIu64" GST Buffer size = %"G_GSIZE_FORMAT"\n", size, map.size);
1441 if (size < (uint64_t)map.size) {
1442 MD_W("Media packet Buffer capacity[%"PRIu64"] is \
1443 less than the GST Buffer size[%"G_GSIZE_FORMAT"]. Resizing...\n", size, map.size);
1444 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1445 media_packet_get_buffer_size(out_pkt, &size);
1446 MD_I("Media packet Buffer NEW capacity: %"PRIu64"\n", size);
1448 if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1449 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1450 ret = MD_ERROR_UNKNOWN;
1453 memcpy((char *)pkt_data, map.data, map.size);
1454 if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1455 MD_E("unable to set the pts\n");
1456 ret = MD_ERROR_UNKNOWN;
1459 if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1460 MD_E("unable to set the dts\n");
1461 ret = MD_ERROR_UNKNOWN;
1464 if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1465 MD_E("unable to set the duration\n");
1466 ret = MD_ERROR_UNKNOWN;
1469 if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1470 MD_E("unable to set the buffer size\n");
1471 ret = MD_ERROR_UNKNOWN;
1474 if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
1475 if (media_packet_set_flags(out_pkt, MEDIA_PACKET_SYNC_FRAME)) {
1476 MD_E("unable to set the buffer flag\n");
1477 ret = MD_ERROR_UNKNOWN;
1481 /* set codec data into media packet */
1483 GstMapInfo codec_data_map;
1484 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1485 MD_E("codec data buffer map failed\n");
1486 ret = MD_ERROR_UNKNOWN;
1489 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1490 (unsigned int)codec_data_map.size)) {
1491 MD_E("unable to set the codec data\n");
1492 ret = MD_ERROR_UNKNOWN;
1493 gst_buffer_unmap(codec_data, &codec_data_map);
1496 gst_buffer_unmap(codec_data, &codec_data_map);
1498 media_buffer_flags_e flags;
1499 media_packet_get_flags(out_pkt, &flags);
1500 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1503 gst_buffer_unmap(buffer, &map);
1504 MEDIADEMUXER_FLEAVE();
1508 static int __gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1510 media_packet_h mediabuf = NULL;
1511 int ret = MD_ERROR_NONE;
1513 MEDIADEMUXER_FENTER();
1514 if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1515 MD_E("media_packet_create_alloc failed\n");
1520 if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1521 MD_E("unable to set EOS flag\n");
1522 ret = MD_ERROR_UNKNOWN;
1527 MEDIADEMUXER_FLEAVE();
1532 media_packet_destroy(mediabuf);
1534 MEDIADEMUXER_FLEAVE();
1538 static int __gst_demuxer_read_sample(MMHandleType pHandle,
1539 media_packet_h *outbuf, int track_indx)
1541 MEDIADEMUXER_FENTER();
1542 int ret = MD_ERROR_NONE;
1543 MEDIADEMUXER_CHECK_NULL(pHandle);
1544 mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1546 media_packet_h mediabuf = NULL;
1549 track *atrack = demuxer->info.head;
1550 if ((demuxer->selected_tracks)[track_indx] == false) {
1551 MD_E("Track Not selected\n");
1556 if (indx == track_indx) /* Got the required track details */
1559 track *next = atrack->next;
1562 MD_E("Invalid track Index\n");
1563 ret = MD_ERROR_INVALID_ARGUMENT;
1570 MD_E("atrack is NULL\n");
1574 if (indx != track_indx) {
1575 MD_E("Invalid track Index\n");
1576 ret = MD_ERROR_INVALID_ARGUMENT;
1579 GstElement *sink = atrack->appsink;
1580 GstSample *sample = NULL;
1582 sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1583 if (sample == NULL) {
1584 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1585 MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1586 ret = MD_ERROR_NONE;
1588 __gst_eos_callback(track_indx, demuxer);
1591 __gst_demuxer_create_eos_packet(atrack->format, outbuf);
1594 MD_E("__gst_demuxer_read_sample failed\n");
1596 ret = MD_ERROR_UNKNOWN;
1601 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1602 MD_E("media_packet_create_alloc failed\n");
1607 GstBuffer *buffer = gst_sample_get_buffer(sample);
1608 if (buffer == NULL) {
1609 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1610 ret = MD_ERROR_UNKNOWN;
1614 GstBuffer *codec_data_buffer = NULL;
1615 /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1616 if (atrack->need_codec_data) {
1617 atrack->need_codec_data = FALSE;
1618 /* Create the codec data and pass to __gst_copy_buf_to_media_packet() to add into the media packet */
1619 GstStructure *structure = NULL;
1620 const GValue *value = NULL;
1622 structure = gst_caps_get_structure(atrack->caps, 0);
1623 /* get codec data from caps*/
1624 value = gst_structure_get_value(structure, "codec_data");
1626 codec_data_buffer = gst_value_get_buffer(value);
1629 /* Fill the media_packet with proper information */
1630 ret = __gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1631 gst_sample_unref(sample);
1634 MEDIADEMUXER_FLEAVE();
1638 media_packet_destroy(mediabuf);
1640 MEDIADEMUXER_FLEAVE();
1644 static int __gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1646 MEDIADEMUXER_FENTER();
1647 MEDIADEMUXER_CHECK_NULL(pHandle);
1648 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1652 track_info *head_track = &(gst_handle->info);
1653 track *temp = head_track->head;
1654 track *temp_track = head_track->head;
1656 bool is_seek = FALSE;
1658 /* Setting each appsink to paused state before seek */
1659 while (temp_track) {
1660 if (gst_handle->selected_tracks[indx] == true) {
1661 if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1662 MD_E("Failed to set into PAUSED state");
1665 MD_I("set the state to paused\n");
1668 if (temp_track->next) {
1669 track *next = temp_track->next;
1676 pos = pos1 * GST_MSECOND;
1678 MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1682 MD_I("Got one element %p {%s}\n", temp->appsink, GST_ELEMENT_NAME(temp->appsink));
1683 if (gst_handle->selected_tracks[indx] == true) {
1684 temp->need_codec_data = TRUE;
1687 if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1688 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1689 GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1690 MD_E("Seek failed!\n");
1695 MD_I("Seek success...setting appsink to playing state\n");
1696 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1697 MD_E("Failed to set into PLAYING state");
1703 track *next = temp->next;
1710 MEDIADEMUXER_FLEAVE();
1711 return MD_ERROR_NONE;
1713 MEDIADEMUXER_FLEAVE();
1717 static int __gst_unset_appsink(track *temp, int index, int loop)
1719 MEDIADEMUXER_FENTER();
1720 int ret = MD_ERROR_NONE;
1723 while (count != index) {
1727 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1728 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1729 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), false);
1730 MEDIADEMUXER_FLEAVE();
1734 static int __gst_demuxer_unset_track(MMHandleType pHandle, int track)
1736 MEDIADEMUXER_FENTER();
1737 int ret = MD_ERROR_NONE;
1738 MEDIADEMUXER_CHECK_NULL(pHandle);
1739 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1741 if (track >= new_mediademuxer->total_tracks || track < 0) {
1742 MD_E("total tracks is less then unselected track, So not support this track");
1743 ret = MD_ERROR_INVALID_ARGUMENT;
1746 new_mediademuxer->selected_tracks[track] = false;
1747 __gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1748 new_mediademuxer->total_tracks);
1749 MEDIADEMUXER_FLEAVE();
1752 MEDIADEMUXER_FLEAVE();
1756 static int __gst_demuxer_stop(MMHandleType pHandle)
1758 MEDIADEMUXER_FENTER();
1759 int ret = MD_ERROR_NONE;
1760 MEDIADEMUXER_CHECK_NULL(pHandle);
1761 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1763 MD_I("__gst_demuxer_stop pipeline %p", gst_handle);
1764 if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1765 GST_STATE_CHANGE_FAILURE) {
1766 MD_E("Failed to set into PAUSE state");
1767 ret = MD_INTERNAL_ERROR;
1770 MEDIADEMUXER_FLEAVE();
1773 MEDIADEMUXER_FLEAVE();
1777 static void __gst_clear_struct(mdgst_handle_t *gst_handle)
1779 MEDIADEMUXER_FENTER();
1780 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
1781 if (gst_handle->selected_tracks) {
1782 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1783 gst_handle->selected_tracks);
1784 g_free(gst_handle->selected_tracks);
1785 gst_handle->selected_tracks = NULL;
1787 if ((gst_handle->info).head)
1788 __gst_free_stuct(&(gst_handle->info).head);
1789 MEDIADEMUXER_FLEAVE();
1792 int _md_gst_destroy_pipeline(GstElement *pipeline)
1794 MEDIADEMUXER_FENTER();
1795 int ret = MD_ERROR_NONE;
1797 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1799 gst_object_unref(GST_OBJECT(pipeline));
1800 MEDIADEMUXER_FLEAVE();
1804 gst_object_unref(GST_OBJECT(pipeline));
1805 MEDIADEMUXER_FLEAVE();
1809 static int __gst_demuxer_unprepare(MMHandleType pHandle)
1811 MEDIADEMUXER_FENTER();
1812 int ret = MD_ERROR_NONE;
1813 MEDIADEMUXER_CHECK_NULL(pHandle);
1814 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1816 /* disconnect signal handler */
1817 if (gst_handle->demux) {
1818 g_signal_handlers_disconnect_by_func(gst_handle->demux, __gst_on_pad_added, gst_handle);
1819 g_signal_handlers_disconnect_by_func(gst_handle->demux, __gst_no_more_pad, gst_handle);
1822 /* Modification : Fix pipeline state change was block by appsink When EOS received and appsink also has many data */
1824 track *atrack = gst_handle->info.head;
1826 if ((gst_handle->selected_tracks)[indx] == false) {
1827 MD_I("Track [%d] Not selected\n", indx);
1829 MD_I("Track [%d] to unset appsink...\n", indx);
1830 __gst_demuxer_unset_track(pHandle, indx);
1833 track *next = atrack->next;
1841 __gst_clear_struct(gst_handle);
1842 if (gst_handle->bus_watch_id) {
1843 GSource *source = NULL;
1844 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1846 g_source_destroy(source);
1847 MD_I("Deallocation bus watch id");
1849 gst_handle->bus_watch_id = 0;
1852 MD_I("__gst_demuxer_stop pipeline %p\n", gst_handle->pipeline);
1853 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1857 MEDIADEMUXER_FLEAVE();
1860 MEDIADEMUXER_FLEAVE();
1864 static int __gst_demuxer_destroy(MMHandleType pHandle)
1866 MEDIADEMUXER_FENTER();
1867 int ret = MD_ERROR_NONE;
1868 MEDIADEMUXER_CHECK_NULL(pHandle);
1869 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1871 MD_I("__gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1873 g_free(new_mediademuxer);
1874 MEDIADEMUXER_FLEAVE();
1878 int __gst_set_error_cb(MMHandleType pHandle,
1879 gst_error_cb callback, void *user_data)
1881 MEDIADEMUXER_FENTER();
1882 int ret = MD_ERROR_NONE;
1883 MEDIADEMUXER_CHECK_NULL(pHandle);
1884 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1886 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1887 MD_E("Already set mediademuxer_error_cb\n");
1888 ret = MD_ERROR_INVALID_ARGUMENT;
1892 MD_E("fail invalid argument (callback)\n");
1893 ret = MD_ERROR_INVALID_ARGUMENT;
1898 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1900 gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1901 gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1902 MEDIADEMUXER_FLEAVE();
1903 return MD_ERROR_NONE;
1905 MEDIADEMUXER_FLEAVE();
1909 int __gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1911 MEDIADEMUXER_FENTER();
1912 int ret = MD_ERROR_NONE;
1913 MEDIADEMUXER_CHECK_NULL(pHandle);
1914 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1916 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1917 MD_E("Already set mediademuxer_eos_cb\n");
1918 ret = MD_ERROR_INVALID_ARGUMENT;
1922 MD_E("fail invalid argument (callback)\n");
1923 ret = MD_ERROR_INVALID_ARGUMENT;
1928 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1929 gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1930 gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1931 MEDIADEMUXER_FLEAVE();
1932 return MD_ERROR_NONE;
1934 MEDIADEMUXER_FLEAVE();
1938 static int __gst_eos_callback(int track_num, void* user_data)
1940 if (user_data == NULL) {
1941 MD_E("Invalid argument");
1944 mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1945 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1946 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1947 gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1949 MD_E("EOS received, but callback is not set!!!");
1950 return MD_ERROR_NONE;