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 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code);
54 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code);
55 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code);
56 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message);
57 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error);
59 /* Media Demuxer API common */
60 static media_port_demuxer_ops def_demux_ops = {
62 .init = gst_demuxer_init,
63 .prepare = gst_demuxer_prepare,
64 .get_track_count = gst_demuxer_get_data_count,
65 .set_track = gst_demuxer_set_track,
66 .start = gst_demuxer_start,
67 .get_track_info = gst_demuxer_get_track_info,
68 .read_sample = gst_demuxer_read_sample,
69 .seek = gst_demuxer_seek,
70 .unset_track = gst_demuxer_unset_track,
71 .stop = gst_demuxer_stop,
72 .unprepare = gst_demuxer_unprepare,
73 .destroy = gst_demuxer_destroy,
74 .set_error_cb = gst_set_error_cb,
75 .set_eos_cb = gst_set_eos_cb,
78 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code)
80 gint trans_err = MEDIADEMUXER_ERROR_NONE;
82 MEDIADEMUXER_CHECK_NULL(gst_handle);
85 case GST_CORE_ERROR_MISSING_PLUGIN:
86 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
87 case GST_CORE_ERROR_STATE_CHANGE:
88 case GST_CORE_ERROR_SEEK:
89 case GST_CORE_ERROR_NOT_IMPLEMENTED:
90 case GST_CORE_ERROR_FAILED:
91 case GST_CORE_ERROR_TOO_LAZY:
92 case GST_CORE_ERROR_PAD:
93 case GST_CORE_ERROR_THREAD:
94 case GST_CORE_ERROR_NEGOTIATION:
95 case GST_CORE_ERROR_EVENT:
96 case GST_CORE_ERROR_CAPS:
97 case GST_CORE_ERROR_TAG:
98 case GST_CORE_ERROR_CLOCK:
99 case GST_CORE_ERROR_DISABLED:
101 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
108 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code)
110 gint trans_err = MEDIADEMUXER_ERROR_NONE;
112 MEDIADEMUXER_CHECK_NULL(gst_handle);
115 case GST_LIBRARY_ERROR_FAILED:
116 case GST_LIBRARY_ERROR_TOO_LAZY:
117 case GST_LIBRARY_ERROR_INIT:
118 case GST_LIBRARY_ERROR_SHUTDOWN:
119 case GST_LIBRARY_ERROR_SETTINGS:
120 case GST_LIBRARY_ERROR_ENCODE:
122 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
130 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code)
132 gint trans_err = MEDIADEMUXER_ERROR_NONE;
134 MEDIADEMUXER_CHECK_NULL(gst_handle);
137 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
138 trans_err = MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
140 case GST_RESOURCE_ERROR_WRITE:
141 case GST_RESOURCE_ERROR_FAILED:
142 case GST_RESOURCE_ERROR_SEEK:
143 case GST_RESOURCE_ERROR_TOO_LAZY:
144 case GST_RESOURCE_ERROR_BUSY:
145 case GST_RESOURCE_ERROR_OPEN_WRITE:
146 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
147 case GST_RESOURCE_ERROR_CLOSE:
148 case GST_RESOURCE_ERROR_SYNC:
149 case GST_RESOURCE_ERROR_SETTINGS:
151 trans_err = MEDIADEMUXER_ERROR_RESOURCE_LIMIT;
158 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message)
160 gint trans_err = MEDIADEMUXER_ERROR_NONE;
162 MEDIADEMUXER_CHECK_NULL(gst_handle);
163 MEDIADEMUXER_CHECK_NULL(error);
164 MEDIADEMUXER_CHECK_NULL(message);
166 switch (error->code) {
167 case GST_STREAM_ERROR_FAILED:
168 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
169 case GST_STREAM_ERROR_DECODE:
170 case GST_STREAM_ERROR_WRONG_TYPE:
171 case GST_STREAM_ERROR_DECRYPT:
172 case GST_STREAM_ERROR_DECRYPT_NOKEY:
173 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
174 trans_err = __gst_transform_gsterror(gst_handle, message, error);
177 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
178 case GST_STREAM_ERROR_TOO_LAZY:
179 case GST_STREAM_ERROR_ENCODE:
180 case GST_STREAM_ERROR_DEMUX:
181 case GST_STREAM_ERROR_MUX:
182 case GST_STREAM_ERROR_FORMAT:
184 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
191 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error)
193 gchar *src_element_name = NULL;
194 GstElement *src_element = NULL;
195 GstElementFactory *factory = NULL;
196 const gchar *klass = NULL;
198 MEDIADEMUXER_CHECK_NULL(gst_handle);
200 src_element = GST_ELEMENT_CAST(message->src);
204 src_element_name = GST_ELEMENT_NAME(src_element);
205 if (!src_element_name)
208 factory = gst_element_get_factory(src_element);
212 klass = gst_element_factory_get_klass(factory);
216 MD_I("error code=%d, msg=%s, src element=%s, class=%s\n",
217 error->code, error->message, src_element_name, klass);
219 switch (error->code) {
220 case GST_STREAM_ERROR_DECODE:
221 case GST_STREAM_ERROR_FAILED:
222 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
225 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
226 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
227 case GST_STREAM_ERROR_WRONG_TYPE:
228 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
232 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
236 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
239 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
243 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
245 MEDIADEMUXER_FENTER();
246 int ret = MD_ERROR_NONE;
247 MEDIADEMUXER_CHECK_NULL(pOps);
248 def_demux_ops.n_size = sizeof(def_demux_ops);
250 memcpy((char *)pOps + sizeof(pOps->n_size),
251 (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
252 pOps->n_size - sizeof(pOps->n_size));
254 MEDIADEMUXER_FLEAVE();
258 static int gst_demuxer_init(MMHandleType *pHandle)
260 MEDIADEMUXER_FENTER();
261 int ret = MD_ERROR_NONE;
262 mdgst_handle_t *new_mediademuxer = NULL;
263 new_mediademuxer = (mdgst_handle_t *)g_try_malloc0(sizeof(mdgst_handle_t));
264 if (!new_mediademuxer) {
265 MD_E("Cannot allocate memory for demuxer\n");
269 MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
270 new_mediademuxer->is_prepared = false;
271 (new_mediademuxer->info).num_audio_track = 0;
272 (new_mediademuxer->info).num_video_track = 0;
273 (new_mediademuxer->info).num_subtitle_track = 0;
274 (new_mediademuxer->info).num_other_track = 0;
275 (new_mediademuxer->info).head = NULL;
276 *pHandle = (MMHandleType)new_mediademuxer;
277 new_mediademuxer->total_tracks = 0;
278 MEDIADEMUXER_FLEAVE();
281 MEDIADEMUXER_FLEAVE();
285 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
287 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
288 MEDIADEMUXER_FENTER();
289 int ret = MD_ERROR_NONE;
290 switch (GST_MESSAGE_TYPE(msg)) {
291 case GST_MESSAGE_EOS: {
295 case GST_MESSAGE_ERROR: {
296 GError *error = NULL;
297 gst_message_parse_error(msg, &error, NULL);
299 MD_I("GST error message parsing failed");
303 if (error->domain == GST_STREAM_ERROR)
304 ret = __gst_handle_stream_error(gst_handle, error, msg);
305 else if (error->domain == GST_RESOURCE_ERROR)
306 ret = __gst_handle_resource_error(gst_handle, error->code);
307 else if (error->domain == GST_LIBRARY_ERROR)
308 ret = __gst_handle_library_error(gst_handle, error->code);
309 else if (error->domain == GST_CORE_ERROR)
310 ret = __gst_handle_core_error(gst_handle, error->code);
312 MD_W("Unexpected error has occurred");
314 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
315 ((mediademuxer_error_cb)gst_handle->user_cb[_GST_EVENT_TYPE_ERROR])
316 (ret, gst_handle->user_data[_GST_EVENT_TYPE_ERROR]);
317 MD_W("Error : (ox%08x)", ret);
319 MD_E("Error: %s\n", error->message);
326 MEDIADEMUXER_FLEAVE();
330 static void __gst_no_more_pad(GstElement *element, gpointer data)
332 MEDIADEMUXER_FENTER();
333 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_malloc0_n(sizeof(bool), gst_handle->total_tracks);
339 MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
340 MD_I("Number of video tracks are %d\n", head_track->num_video_track);
341 MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
342 MD_I("Number of subtitle tracks are %d\n",
343 head_track->num_subtitle_track);
344 MD_I("Number of other tracks are %d\n", head_track->num_other_track);
346 MD_I("track caps[%s]\n", head->caps_string);
349 gst_handle->is_prepared = true;
350 MD_I("core->is_prepared: true");
351 MEDIADEMUXER_FLEAVE();
354 void __gst_free_stuct(track **head)
356 MEDIADEMUXER_FENTER();
362 MD_I("unref GST_PAD %p\n", temp->pad);
363 gst_object_unref(temp->pad);
366 MD_I("unref GST_PAD caps %p\n", temp->caps);
367 gst_caps_unref(temp->caps);
369 if (temp->caps_string) {
370 MD_I("deallocate GST_PAD caps_string %p\n",
372 g_free(temp->caps_string);
375 MD_I("unref media_format %p\n", temp->format);
376 media_format_unref(temp->format);
379 track *next = temp->next;
380 MD_I("deallocate memory %p\n", temp);
384 MD_I("deallocate memory %p\n", temp);
390 MEDIADEMUXER_FLEAVE();
393 int __gst_add_track_info(GstPad *pad, GstCaps *caps, track **head,
394 GstElement *pipeline)
396 MEDIADEMUXER_FENTER();
397 GstPad *apppad = NULL;
398 GstPad *queue_sink_pad = NULL;
399 GstPad *queue_src_pad = NULL;
400 GstCaps *outcaps = NULL;
401 GstPad *parse_sink_pad = NULL;
402 GstElement *parse_element = NULL;
403 GstElement *id3tag = NULL;
404 GstPad *id3_sinkpad = NULL;
405 GstPad *id3_srcpad = NULL;
408 temp = (track *)(g_malloc0(sizeof(track)));
409 MD_I("allocate memory %p", temp);
411 temp->pad = gst_object_ref(pad);
412 temp->caps = gst_caps_ref(caps);
413 temp->caps_string = gst_caps_to_string(caps);
416 temp->need_codec_data = TRUE;
418 MD_I("track caps(%s)", temp->caps_string ? temp->caps_string : "NULL");
420 /* Link demuxer - queue */
421 temp->queue = gst_element_factory_make("queue", NULL);
423 MD_E("factory not able to make queue");
427 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
428 gst_object_unref(temp->queue);
429 MD_E("fail add queue in pipeline");
432 MD_I("added queue element in pipeline.");
434 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
435 if (!queue_sink_pad) {
436 MD_E("sink pad of queue not available");
440 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
441 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->queue, ERROR);
443 temp->appsink = gst_element_factory_make("appsink", NULL);
444 if (!temp->appsink) {
445 MD_E("factory not able to make appsink");
448 g_object_set(G_OBJECT(temp->appsink), "wait-on-eos", TRUE, NULL);
450 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
451 gst_object_unref(temp->appsink);
452 MD_E("fail add appsink in pipeline");
455 MD_I("added appsink element in pipeline.");
457 gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
458 gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
460 queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
461 if (!queue_src_pad) {
462 MD_E("src pad of queue not available");
465 apppad = gst_element_get_static_pad(temp->appsink, "sink");
467 MD_E("sink pad of appsink not available");
470 /* Check for type video and it should be h264 */
471 if (temp->caps_string && strstr(temp->caps_string, "video")) {
472 if (strstr(temp->caps_string, "h264")) {
473 parse_element = gst_element_factory_make("h264parse", NULL);
474 if (!parse_element) {
475 MD_E("factory not able to make h264parse");
478 } else if (strstr(temp->caps_string, "mpeg")) {
479 parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
480 if (!parse_element) {
481 MD_E("factory not able to make h264parse");
484 g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
488 MD_I("add video parse element(%s).", GST_ELEMENT_NAME(parse_element));
489 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
490 gst_object_unref(parse_element);
491 MD_E("fail add video parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
494 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
495 if (!parse_sink_pad) {
496 MD_E("sink pad of video parse(%s) not available", GST_ELEMENT_NAME(parse_element));
499 /* Link demuxer pad with sink pad of parse element */
500 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
502 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
504 if (strstr(temp->caps_string, "h264")) {
505 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
506 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
507 gst_caps_unref(outcaps);
508 temp->need_codec_data = FALSE;
509 } else if (strstr(temp->caps_string, "mpeg")) {
510 gst_element_link(parse_element, temp->appsink);
512 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
515 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
517 } else if (temp->caps_string && (strstr(temp->caps_string, "audio") || strstr(temp->caps_string, "x-id3"))) {
518 if (strstr(temp->caps_string, "audio/mpeg")) {
520 GstStructure *structure = NULL;
521 structure = gst_caps_get_structure(temp->caps, 0);
522 gst_structure_get_int (structure, "mpegversion", &mpegversion);
523 if (mpegversion == 2 || mpegversion == 4) {
524 parse_element = gst_element_factory_make("aacparse", NULL);
525 if (!parse_element) {
526 MD_E("factory not able to make aacparse");
529 } else if (mpegversion == 1) {
530 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
531 if (!parse_element) {
532 MD_E("factory not able to make mpegaudioparse");
536 } else if (strstr(temp->caps_string, "application/x-id3")) {
537 id3tag = gst_element_factory_make("id3demux", NULL);
539 MD_E("factory not able to make id3demux");
542 if (!gst_bin_add(GST_BIN(pipeline), id3tag)) {
543 gst_object_unref(id3tag);
544 MD_E("fail add id3tag element in pipeline");
547 id3_sinkpad = gst_element_get_static_pad(id3tag, "sink");
549 MD_E("fail to get id3demux sink pad.\n");
552 MEDIADEMUXER_LINK_PAD(queue_src_pad, id3_sinkpad, ERROR);
553 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(id3tag, ERROR);
554 id3_srcpad = gst_element_get_static_pad(id3tag, "src");
556 MD_E("fail to get id3demux src pad.\n");
559 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
560 if (!parse_element) {
561 MD_E("factory not able to make mpegaudioparse");
564 } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
565 || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
566 parse_element = gst_element_factory_make("amrparse", NULL);
567 if (!parse_element) {
568 MD_E("factory not able to make amrparse");
571 } else if (strstr(temp->caps_string, "audio/x-wav")) {
572 parse_element = gst_element_factory_make("wavparse", NULL);
573 if (!parse_element) {
574 MD_E("factory not able to make wavparse");
577 } else if (strstr(temp->caps_string, "audio/x-flac")) {
578 parse_element = gst_element_factory_make("flacparse", NULL);
579 if (!parse_element) {
580 MD_E("factory not able to make flacparse");
586 MD_I("add audio parse element(%s).", GST_ELEMENT_NAME(parse_element));
587 if (!gst_bin_add(GST_BIN(pipeline), parse_element)) {
588 gst_object_unref(parse_element);
589 MD_E("fail add audio parse(%s) in pipeline", GST_ELEMENT_NAME(parse_element));
592 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
593 if (!parse_sink_pad) {
594 MD_E("sink pad of audio parse(%s) not available", GST_ELEMENT_NAME(parse_element));
598 /* Link demuxer pad with sink pad of parse element */
600 MEDIADEMUXER_LINK_PAD(id3_srcpad, parse_sink_pad, ERROR);
602 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
604 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(parse_element, ERROR);
606 /* Link src pad with appSink element */
607 gst_element_link(parse_element, temp->appsink);
609 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
612 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
615 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(temp->appsink, ERROR);
616 /* gst_pad_link(pad, fpad) */
626 gst_object_unref(queue_sink_pad);
628 gst_object_unref(queue_src_pad);
630 gst_object_unref(apppad);
632 gst_object_unref(parse_sink_pad);
634 gst_object_unref(id3_sinkpad);
636 gst_object_unref(id3_srcpad);
637 MEDIADEMUXER_FLEAVE();
638 return MD_ERROR_NONE;
641 __gst_free_stuct(&temp);
643 gst_object_unref(queue_sink_pad);
645 gst_object_unref(queue_src_pad);
647 gst_object_unref(apppad);
649 gst_object_unref(parse_sink_pad);
651 gst_object_unref(id3_sinkpad);
653 gst_object_unref(id3_srcpad);
654 __gst_free_stuct(head);
655 MEDIADEMUXER_FLEAVE();
659 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
661 MEDIADEMUXER_FENTER();
662 MD_I("Dynamic pad created, linking demuxer/decoder\n");
664 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
665 track_info *head_track = &(gst_handle->info);
666 GstCaps *caps = NULL;
667 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
668 caps = gst_pad_get_current_caps(pad);
670 MD_E("caps is NULL");
673 gst_handle->total_tracks++;
674 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline)
676 MD_E("unable to added track info");
677 head_track->num_audio_track = 0;
678 head_track->num_video_track = 0;
679 head_track->num_subtitle_track = 0;
680 head_track->num_other_track = 0;
681 gst_caps_unref(caps);
682 __gst_free_stuct(&(head_track->head));
685 gst_caps_unref(caps);
686 tmp = head_track->head;
689 MD_I("track is NULL\n");
690 MEDIADEMUXER_FLEAVE();
697 if (!tmp->caps_string) {
698 MD_I("track caps_string is NULL\n");
699 MEDIADEMUXER_FLEAVE();
703 if (tmp->caps_string[0] == 'v') {
704 MD_I("found Video Pad\n");
705 (head_track->num_video_track)++;
706 } else if (tmp->caps_string[0] == 'a') {
707 MD_I("found Audio Pad\n");
708 (head_track->num_audio_track)++;
709 } else if (tmp->caps_string[0] == 's') {
710 MD_I("found subtitle(or Text) Pad\n");
711 (head_track->num_subtitle_track)++;
713 MD_W("found Pad, caps: %s\n", tmp->caps_string);
714 (head_track->num_other_track)++;
716 MEDIADEMUXER_FLEAVE();
719 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
721 MEDIADEMUXER_FENTER();
722 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
724 track_info *head_track = &(gst_handle->info);
726 gst_handle->is_valid_container = true;
728 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
730 MD_E("fail to get typefind src pad.\n");
734 gst_handle->total_tracks++;
735 if (__gst_add_track_info(pad, caps, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
736 MD_E("unable to added track info");
737 head_track->num_audio_track = 0;
738 head_track->num_video_track = 0;
739 head_track->num_subtitle_track = 0;
740 head_track->num_other_track = 0;
741 __gst_free_stuct(&(head_track->head));
745 (head_track->num_audio_track)++;
749 gst_object_unref(pad);
751 /* In the case of audio only, there is no gst_handle->demux. So we pass NULL */
752 __gst_no_more_pad(NULL, data);
754 MEDIADEMUXER_FLEAVE();
755 return MD_ERROR_NONE;
758 gst_handle->is_valid_container = false;
761 gst_object_unref(pad);
763 MEDIADEMUXER_FLEAVE();
767 static void __gst_cb_typefind(GstElement *tf, guint probability,
768 GstCaps *caps, gpointer data)
770 MEDIADEMUXER_FENTER();
771 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
773 GstPad *demuxer_pad = NULL;
774 GstPad *fake_pad = NULL;
776 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
777 type = gst_caps_to_string(caps);
780 MD_E("Fail to get caps string");
784 MD_I("Media type %s found, probability %d%%\n", type, probability);
785 if (strstr(type, "quicktime") || strstr(type, "audio/x-m4a") ||
786 strstr(type, "x-3gp") || strstr(type, "ogg") ||
787 strstr(type, "flv") || strstr(type, "x-msvideo")) {
788 gst_handle->is_valid_container = true;
789 if (strstr(type, "ogg"))
790 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
791 else if (strstr(type, "flv"))
792 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
793 else if (strstr(type, "x-msvideo"))
794 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
796 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
798 if (!gst_handle->demux) {
799 gst_handle->is_valid_container = false;
800 MD_E("factory not able to create qtdemux\n");
803 g_signal_connect(gst_handle->demux, "pad-added",
804 G_CALLBACK(__gst_on_pad_added), gst_handle);
805 g_signal_connect(gst_handle->demux, "no-more-pads",
806 G_CALLBACK(__gst_no_more_pad), gst_handle);
807 gst_element_set_locked_state(gst_handle->demux, TRUE);
808 if (!gst_bin_add(GST_BIN(gst_handle->pipeline), gst_handle->demux)) {
809 MD_E("fail add demuxer(%s) in pipeline",
810 GST_ELEMENT_NAME(gst_handle->demux));
811 gst_object_unref(gst_handle->demux);
812 gst_handle->demux = NULL;
816 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
818 MD_E("fail to get typefind src pad.\n");
821 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
823 MD_E("fail to get qtdemux sink pad.\n");
826 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
828 MD_E("fail to get fakesink sink pad.\n");
831 gst_pad_unlink(pad, fake_pad);
832 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
834 MEDIADEMUXER_SYNC_STATE_WITH_PARENT(gst_handle->demux, ERROR);
835 gst_element_set_locked_state(gst_handle->demux, FALSE);
837 gst_object_unref(pad);
839 gst_object_unref(demuxer_pad);
841 gst_object_unref(fake_pad);
843 } else if ((strstr(type, "adts"))
844 || (strstr(type, "audio/mpeg"))
845 || (strstr(type, "audio/x-wav"))
846 || (strstr(type, "audio/x-flac"))
847 || (strstr(type, "application/x-id3"))
848 || (strstr(type, "audio/x-amr-nb-sh"))
849 || (strstr(type, "audio/x-amr-wb-sh"))) {
850 MD_I("Audio only format is found\n");
851 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
853 MD_E("fail to get typefind src pad.\n");
856 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
858 MD_E("fail to get fakesink sink pad.\n");
861 gst_pad_unlink(pad, fake_pad);
863 gst_object_unref(pad);
865 gst_object_unref(fake_pad);
867 __gst_create_audio_only_pipeline(data, caps);
869 gst_handle->is_valid_container = false;
870 MD_E("Not supported container %s\n", type);
874 MEDIADEMUXER_FLEAVE();
878 gst_handle->is_valid_container = false;
881 if (gst_handle->demux)
882 gst_element_set_locked_state(gst_handle->demux, FALSE);
884 gst_object_unref(pad);
886 gst_object_unref(demuxer_pad);
888 gst_object_unref(fake_pad);
889 MEDIADEMUXER_FLEAVE();
893 static int _gst_create_pipeline(mdgst_handle_t *gst_handle, char *uri)
895 MEDIADEMUXER_FENTER();
896 int ret = MD_ERROR_NONE;
899 #ifdef TIZEN_FEATURE_STREAMING
900 int remote_streaming = 0;
902 GstState element_state = GST_STATE_VOID_PENDING;
903 GstState element_pending_state = GST_STATE_VOID_PENDING;
905 /* Initialize GStreamer */
906 /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
907 gst_init(NULL, NULL);
909 /* Create the empty pipeline */
910 gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
911 if (!gst_handle->pipeline) {
912 MD_E("pipeline create fail");
917 /* Create the elements */
918 if ((path = strstr(uri, "http://"))) {
919 #ifdef TIZEN_FEATURE_STREAMING
920 gst_handle->filesrc = gst_element_factory_make("souphttpsrc", NULL);
921 remote_streaming = 1;
922 MD_I("Source is http stream. \n");
924 MD_I("Source is http stream. Didn't support streaming\n");
928 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
929 MD_I("Source is file stream \n");
931 if (!gst_handle->filesrc) {
932 MD_E("filesrc creation failed");
937 /* Modify the source's properties */
938 #ifdef TIZEN_FEATURE_STREAMING
939 if (remote_streaming == 1)
940 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
943 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
944 gst_handle->typefind = gst_element_factory_make("typefind", NULL);
945 if (!gst_handle->typefind) {
946 MD_E("typefind creation failed");
950 g_signal_connect(gst_handle->typefind, "have-type",
951 G_CALLBACK(__gst_cb_typefind), gst_handle);
952 gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
953 if (!gst_handle->fakesink) {
954 MD_E("fakesink creation failed");
959 /* Build the pipeline */
960 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
962 gst_handle->typefind,
963 gst_handle->fakesink,
965 gst_element_link_many(gst_handle->filesrc,
966 gst_handle->typefind,
967 gst_handle->fakesink,
970 /* connect signals, bus watcher */
971 bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
972 gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
973 gst_handle->thread_default = g_main_context_get_thread_default();
974 gst_object_unref(GST_OBJECT(bus));
976 /* set pipeline state to PAUSED */
977 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
979 if (gst_element_get_state(gst_handle->pipeline, &element_state, &element_pending_state, 1 * GST_SECOND)
980 == GST_STATE_CHANGE_FAILURE) {
981 MD_E(" [%s] state : %s pending : %s \n",
982 GST_ELEMENT_NAME(gst_handle->pipeline),
983 gst_element_state_get_name(element_state),
984 gst_element_state_get_name(element_pending_state));
989 if (gst_handle->is_prepared != true) {
995 MEDIADEMUXER_FLEAVE();
998 MEDIADEMUXER_FLEAVE();
1002 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
1004 MEDIADEMUXER_FENTER();
1005 int ret = MD_ERROR_NONE;
1006 MEDIADEMUXER_CHECK_NULL(pHandle);
1007 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1009 MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
1010 ret = _gst_create_pipeline(new_mediademuxer, uri);
1011 if (ret != MD_ERROR_NONE) {
1012 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
1015 MEDIADEMUXER_FLEAVE();
1018 MEDIADEMUXER_FLEAVE();
1022 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
1024 MEDIADEMUXER_FENTER();
1025 int ret = MD_ERROR_NONE;
1026 MEDIADEMUXER_CHECK_NULL(pHandle);
1027 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1029 *count = (new_mediademuxer->info).num_video_track +
1030 (new_mediademuxer->info).num_audio_track +
1031 (new_mediademuxer->info).num_subtitle_track +
1032 (new_mediademuxer->info).num_other_track;
1033 MEDIADEMUXER_FLEAVE();
1037 int _gst_set_appsink(track *temp, int index, int loop)
1039 MEDIADEMUXER_FENTER();
1040 int ret = MD_ERROR_NONE;
1043 while (count != index) {
1047 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
1048 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
1049 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), true);
1050 MEDIADEMUXER_FLEAVE();
1054 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
1056 MEDIADEMUXER_FENTER();
1057 int ret = MD_ERROR_NONE;
1058 MEDIADEMUXER_CHECK_NULL(pHandle);
1059 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1061 MD_I("total_tracks (%d) :: selected track (%d)", new_mediademuxer->total_tracks, track);
1062 if (track >= new_mediademuxer->total_tracks || track < 0) {
1063 MD_E("total_tracks is less then selected track, So not support this track");
1064 ret = MD_ERROR_INVALID_ARGUMENT;
1067 new_mediademuxer->selected_tracks[track] = true;
1068 _gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1069 new_mediademuxer->total_tracks);
1070 MEDIADEMUXER_FLEAVE();
1071 return MD_ERROR_NONE;
1073 MEDIADEMUXER_FLEAVE();
1077 static int _gst_unlink_unselected_track(track *temp, int index)
1079 MEDIADEMUXER_FENTER();
1080 int ret = MD_ERROR_NONE;
1082 GstPad *queue_sink_pad = NULL;
1083 while (count != index) {
1087 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
1088 if (!queue_sink_pad) {
1089 MD_E("queue_sink_pad of appsink not available\n");
1092 if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
1093 MD_W("demuxer is already unlinked from queue for track %d\n", index);
1095 gst_object_unref(queue_sink_pad);
1096 MEDIADEMUXER_FLEAVE();
1100 static int gst_demuxer_start(MMHandleType pHandle)
1102 MEDIADEMUXER_FENTER();
1103 int ret = MD_ERROR_NONE;
1104 MEDIADEMUXER_CHECK_NULL(pHandle);
1105 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1108 for (indx = 0; indx < gst_handle->total_tracks; indx++) {
1109 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
1110 indx, gst_handle->selected_tracks[indx]);
1112 if (gst_handle->selected_tracks[indx] == false)
1113 _gst_demuxer_unset(pHandle, indx);
1115 if (gst_handle->selected_tracks[indx] != true) {
1116 if (_gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
1117 MD_E("Failed to unlink unselected tracks\n");
1118 ret = MD_INTERNAL_ERROR;
1125 track_info *head_track = &(gst_handle->info);
1126 MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
1127 head_track->num_audio_track, head_track->num_video_track,
1128 head_track->num_subtitle_track);
1130 track *temp = head_track->head;
1133 MD_I("Got one element %p\n", temp->appsink);
1134 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
1135 GST_STATE_CHANGE_FAILURE) {
1136 MD_E("Failed to set into PLAYING state");
1137 ret = MD_INTERNAL_ERROR;
1140 MD_I("set the state to playing\n");
1143 track *next = temp->next;
1150 MD_I("gst_demuxer_start pipeline %p", gst_handle);
1151 MEDIADEMUXER_FLEAVE();
1154 MEDIADEMUXER_FLEAVE();
1158 int _set_mime_text(media_format_h format, track *head)
1160 MEDIADEMUXER_FENTER();
1161 int ret = MD_ERROR_NONE;
1162 GstStructure *struc = NULL;
1163 struc = gst_caps_get_structure(head->caps, 0);
1165 MD_E("cannot get structure from caps.\n");
1168 if (gst_structure_has_name(struc, "text/x-raw")) {
1169 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
1172 MD_I("Text mime not supported so far\n");
1176 MEDIADEMUXER_FLEAVE();
1179 MEDIADEMUXER_FLEAVE();
1183 int _set_mime_video(media_format_h format, track *head)
1185 MEDIADEMUXER_FENTER();
1186 int ret = MD_ERROR_NONE;
1187 GstStructure *struc = NULL;
1190 int frame_rate_numerator = 0;
1191 int frame_rate_denominator = 0;
1193 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1194 struc = gst_caps_get_structure(head->caps, 0);
1196 MD_E("cannot get structure from caps.\n");
1199 if (gst_structure_has_name(struc, "video/x-h264")) {
1200 mime_type = MEDIA_FORMAT_H264_SP;
1201 } else if (gst_structure_has_name(struc, "video/x-h263")) {
1202 mime_type = MEDIA_FORMAT_H263;
1203 } else if (gst_structure_has_name(struc, "video/mpeg")) {
1204 mime_type = MEDIA_FORMAT_MPEG4_SP;
1206 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
1209 if (media_format_set_video_mime(format, mime_type)) {
1210 MD_E("Unable to set video mime type (%x)\n", mime_type);
1213 gst_structure_get_int(struc, "width", &src_width);
1214 gst_structure_get_int(struc, "height", &src_height);
1215 if (media_format_set_video_width(format, src_width)) {
1216 MD_E("Unable to set video width\n");
1219 if (media_format_set_video_height(format, src_height)) {
1220 MD_E("Unable to set video height\n");
1223 gst_structure_get_fraction(struc, "framerate", &frame_rate_numerator, &frame_rate_denominator);
1225 /* Round off the framerate */
1226 if (frame_rate_denominator)
1227 frame_rate = (int)floor(((gdouble)frame_rate_numerator / frame_rate_denominator) + 0.5);
1229 MD_I("set frame rate %d", frame_rate);
1230 if (media_format_set_video_frame_rate(format, frame_rate)) {
1231 MD_E("Unable to set video frame rate\n");
1234 MEDIADEMUXER_FLEAVE();
1237 MEDIADEMUXER_FLEAVE();
1241 int _set_mime_audio(media_format_h format, track *head)
1243 MEDIADEMUXER_FENTER();
1244 int ret = MD_ERROR_NONE;
1245 GstStructure *struc = NULL;
1250 const gchar *stream_format = NULL;
1251 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1253 struc = gst_caps_get_structure(head->caps, 0);
1255 MD_E("cannot get structure from caps.\n");
1259 if (gst_structure_has_name(struc, "application/x-id3"))
1261 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1264 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1265 if (mpegversion == 4 || mpegversion == 2) {
1266 mime_type = MEDIA_FORMAT_AAC_LC;
1267 if (media_format_set_audio_mime(format, mime_type))
1269 stream_format = gst_structure_get_string(struc, "stream-format");
1271 if (stream_format) {
1272 if (strncmp(stream_format, "adts", 4) == 0)
1273 media_format_set_audio_aac_type(format, 1);
1275 media_format_set_audio_aac_type(format, 0);
1278 } else if (mpegversion == 1 || id3_flag) {
1279 gst_structure_get_int(struc, "layer", &layer);
1280 if ((layer == 3) || (id3_flag == 1)) {
1281 mime_type = MEDIA_FORMAT_MP3;
1283 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1287 } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1288 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1289 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1290 mime_type = MEDIA_FORMAT_AMR_NB;
1293 mime_type = MEDIA_FORMAT_AMR_WB;
1296 } else if (gst_structure_has_name(struc, "audio/AMR")) {
1297 mime_type = MEDIA_FORMAT_AMR_NB;
1298 } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1299 mime_type = MEDIA_FORMAT_AMR_WB;
1300 } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1301 mime_type = MEDIA_FORMAT_PCM;
1302 } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1303 mime_type = MEDIA_FORMAT_FLAC;
1304 } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1305 mime_type = MEDIA_FORMAT_VORBIS;
1307 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1310 if (media_format_set_audio_mime(format, mime_type))
1312 gst_structure_get_int(struc, "channels", &channels);
1313 if (channels == 0) { /* default */
1314 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1319 if (media_format_set_audio_channel(format, channels))
1322 gst_structure_get_int(struc, "rate", &rate);
1324 rate = 44100; /* default */
1325 if (media_format_set_audio_samplerate(format, rate))
1327 gst_structure_get_int(struc, "bit", &bit);
1329 bit = 16; /* default */
1330 if (media_format_set_audio_bit(format, bit))
1332 MEDIADEMUXER_FLEAVE();
1335 MEDIADEMUXER_FLEAVE();
1339 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1340 media_format_h *format, int index)
1342 MEDIADEMUXER_FENTER();
1343 int ret = MD_ERROR_NONE;
1344 MEDIADEMUXER_CHECK_NULL(pHandle);
1345 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1350 temp = (new_mediademuxer->info).head;
1351 loop = (new_mediademuxer->info).num_video_track +
1352 (new_mediademuxer->info).num_audio_track +
1353 (new_mediademuxer->info).num_subtitle_track +
1354 (new_mediademuxer->info).num_other_track;
1355 if (index >= loop || index < 0) {
1356 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1361 while (count != index) {
1365 if (temp->format != NULL) {
1366 ret = media_format_ref(temp->format);
1367 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1368 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1369 ret = MD_INTERNAL_ERROR;
1372 ret = media_format_make_writable(temp->format, format); /* copy the content */
1373 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1374 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1375 media_format_unref(temp->format);
1376 ret = MD_INTERNAL_ERROR;
1379 MEDIADEMUXER_FLEAVE();
1382 ret = media_format_create(&(temp->format));
1383 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1384 MD_E("Mediaformat creation failed. returned %d\n", ret);
1385 ret = MD_INTERNAL_ERROR;
1389 MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1390 MD_I("format ptr[%p]\n", temp->format);
1391 if (temp->caps_string[0] == 'a') {
1392 MD_I("Setting for Audio \n");
1393 _set_mime_audio(temp->format, temp);
1394 } else if (temp->caps_string[0] == 'v') {
1395 MD_I("Setting for Video \n");
1396 _set_mime_video(temp->format, temp);
1397 } else if (temp->caps_string[0] == 't') {
1398 MD_I("Setting for Subtitle\n");
1399 _set_mime_text(temp->format, temp);
1401 MD_W("Not supported so far (except audio, video and subtitle)\n");
1404 ret = media_format_ref(temp->format); /* increment the ref to retain the original content */
1405 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1406 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1407 ret = MD_INTERNAL_ERROR;
1410 ret = media_format_make_writable(temp->format, format); /* copy the content */
1411 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1412 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1413 media_format_unref(temp->format);
1414 ret = MD_INTERNAL_ERROR;
1417 MEDIADEMUXER_FLEAVE();
1420 MEDIADEMUXER_FLEAVE();
1424 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1425 GstBuffer *buffer, GstBuffer *codec_data)
1427 MEDIADEMUXER_FENTER();
1428 int ret = MD_ERROR_NONE;
1429 MEDIADEMUXER_CHECK_NULL(out_pkt);
1434 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1435 MD_E("gst_buffer_map failed\n");
1436 ret = MD_ERROR_UNKNOWN;
1440 media_packet_get_buffer_size(out_pkt, &size);
1441 MD_I("Media packet Buffer capacity: %"PRIu64" GST Buffer size = %"G_GSIZE_FORMAT"\n", size, map.size);
1442 if (size < (uint64_t)map.size) {
1443 MD_W("Media packet Buffer capacity[%"PRIu64"] is \
1444 less than the GST Buffer size[%"G_GSIZE_FORMAT"]. Resizing...\n", size, map.size);
1445 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1446 media_packet_get_buffer_size(out_pkt, &size);
1447 MD_I("Media packet Buffer NEW capacity: %"PRIu64"\n", size);
1449 if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1450 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1451 ret = MD_ERROR_UNKNOWN;
1454 memcpy((char *)pkt_data, map.data, map.size);
1455 if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1456 MD_E("unable to set the pts\n");
1457 ret = MD_ERROR_UNKNOWN;
1460 if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1461 MD_E("unable to set the dts\n");
1462 ret = MD_ERROR_UNKNOWN;
1465 if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1466 MD_E("unable to set the duration\n");
1467 ret = MD_ERROR_UNKNOWN;
1470 if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1471 MD_E("unable to set the buffer size\n");
1472 ret = MD_ERROR_UNKNOWN;
1475 if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
1476 if (media_packet_set_flags(out_pkt, MEDIA_PACKET_SYNC_FRAME)) {
1477 MD_E("unable to set the buffer flag\n");
1478 ret = MD_ERROR_UNKNOWN;
1482 /* set codec data into media packet */
1484 GstMapInfo codec_data_map;
1485 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1486 MD_E("codec data buffer map failed\n");
1487 ret = MD_ERROR_UNKNOWN;
1490 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1491 (unsigned int)codec_data_map.size)) {
1492 MD_E("unable to set the codec data\n");
1493 ret = MD_ERROR_UNKNOWN;
1494 gst_buffer_unmap(codec_data, &codec_data_map);
1497 gst_buffer_unmap(codec_data, &codec_data_map);
1499 media_buffer_flags_e flags;
1500 media_packet_get_flags(out_pkt, &flags);
1501 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1504 gst_buffer_unmap(buffer, &map);
1505 MEDIADEMUXER_FLEAVE();
1509 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1511 media_packet_h mediabuf = NULL;
1512 int ret = MD_ERROR_NONE;
1514 MEDIADEMUXER_FENTER();
1515 if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1516 MD_E("media_packet_create_alloc failed\n");
1521 if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1522 MD_E("unable to set EOS flag\n");
1523 ret = MD_ERROR_UNKNOWN;
1528 MEDIADEMUXER_FLEAVE();
1533 media_packet_destroy(mediabuf);
1535 MEDIADEMUXER_FLEAVE();
1539 static int gst_demuxer_read_sample(MMHandleType pHandle,
1540 media_packet_h *outbuf, int track_indx)
1542 MEDIADEMUXER_FENTER();
1543 int ret = MD_ERROR_NONE;
1544 MEDIADEMUXER_CHECK_NULL(pHandle);
1545 mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1547 media_packet_h mediabuf = NULL;
1550 track *atrack = demuxer->info.head;
1551 if ((demuxer->selected_tracks)[track_indx] == false) {
1552 MD_E("Track Not selected\n");
1557 if (indx == track_indx) /* Got the required track details */
1560 track *next = atrack->next;
1563 MD_E("Invalid track Index\n");
1564 ret = MD_ERROR_INVALID_ARGUMENT;
1571 MD_E("atrack is NULL\n");
1575 if (indx != track_indx) {
1576 MD_E("Invalid track Index\n");
1577 ret = MD_ERROR_INVALID_ARGUMENT;
1580 GstElement *sink = atrack->appsink;
1581 GstSample *sample = NULL;
1583 sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1584 if (sample == NULL) {
1585 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1586 MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1587 ret = MD_ERROR_NONE;
1589 __gst_eos_callback(track_indx, demuxer);
1592 _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1595 MD_E("gst_demuxer_read_sample failed\n");
1597 ret = MD_ERROR_UNKNOWN;
1602 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1603 MD_E("media_packet_create_alloc failed\n");
1608 GstBuffer *buffer = gst_sample_get_buffer(sample);
1609 if (buffer == NULL) {
1610 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1611 ret = MD_ERROR_UNKNOWN;
1615 GstBuffer *codec_data_buffer = NULL;
1616 /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1617 if (atrack->need_codec_data) {
1618 atrack->need_codec_data = FALSE;
1619 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1620 GstStructure *structure = NULL;
1621 const GValue *value = NULL;
1623 structure = gst_caps_get_structure(atrack->caps, 0);
1624 /* get codec data from caps*/
1625 value = gst_structure_get_value(structure, "codec_data");
1627 codec_data_buffer = gst_value_get_buffer(value);
1630 /* Fill the media_packet with proper information */
1631 ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1632 gst_sample_unref(sample);
1635 MEDIADEMUXER_FLEAVE();
1639 media_packet_destroy(mediabuf);
1641 MEDIADEMUXER_FLEAVE();
1645 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1647 MEDIADEMUXER_FENTER();
1648 MEDIADEMUXER_CHECK_NULL(pHandle);
1649 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1653 track_info *head_track = &(gst_handle->info);
1654 track *temp = head_track->head;
1655 track *temp_track = head_track->head;
1657 bool is_seek = FALSE;
1659 /* Setting each appsink to paused state before seek */
1660 while (temp_track) {
1661 if (gst_handle->selected_tracks[indx] == true) {
1662 if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1663 MD_E("Failed to set into PAUSED state");
1666 MD_I("set the state to paused\n");
1669 if (temp_track->next) {
1670 track *next = temp_track->next;
1677 pos = pos1 * GST_MSECOND;
1679 MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1683 MD_I("Got one element %p {%s}\n", temp->appsink, GST_ELEMENT_NAME(temp->appsink));
1684 if (gst_handle->selected_tracks[indx] == true) {
1685 temp->need_codec_data = TRUE;
1688 if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1689 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1690 GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1691 MD_E("Seek failed!\n");
1696 MD_I("Seek success...setting appsink to playing state\n");
1697 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1698 MD_E("Failed to set into PLAYING state");
1704 track *next = temp->next;
1711 MEDIADEMUXER_FLEAVE();
1712 return MD_ERROR_NONE;
1714 MEDIADEMUXER_FLEAVE();
1718 int _gst_unset_appsink(track *temp, int index, int loop)
1720 MEDIADEMUXER_FENTER();
1721 int ret = MD_ERROR_NONE;
1724 while (count != index) {
1728 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1729 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1730 gst_app_sink_set_wait_on_eos((GstAppSink *)(temp->appsink), false);
1731 MEDIADEMUXER_FLEAVE();
1735 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1737 MEDIADEMUXER_FENTER();
1738 int ret = MD_ERROR_NONE;
1739 MEDIADEMUXER_CHECK_NULL(pHandle);
1740 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1742 if (track >= new_mediademuxer->total_tracks || track < 0) {
1743 MD_E("total tracks is less then unselected track, So not support this track");
1744 ret = MD_ERROR_INVALID_ARGUMENT;
1747 new_mediademuxer->selected_tracks[track] = false;
1748 _gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1749 new_mediademuxer->total_tracks);
1750 MEDIADEMUXER_FLEAVE();
1753 MEDIADEMUXER_FLEAVE();
1757 static int gst_demuxer_stop(MMHandleType pHandle)
1759 MEDIADEMUXER_FENTER();
1760 int ret = MD_ERROR_NONE;
1761 MEDIADEMUXER_CHECK_NULL(pHandle);
1762 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1764 MD_I("gst_demuxer_stop pipeline %p", gst_handle);
1765 if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1766 GST_STATE_CHANGE_FAILURE) {
1767 MD_E("Failed to set into PAUSE state");
1768 ret = MD_INTERNAL_ERROR;
1771 MEDIADEMUXER_FLEAVE();
1774 MEDIADEMUXER_FLEAVE();
1778 void _gst_clear_struct(mdgst_handle_t *gst_handle)
1780 MEDIADEMUXER_FENTER();
1781 MEDIADEMUXER_CHECK_NULL_VOID(gst_handle);
1782 if (gst_handle->selected_tracks) {
1783 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1784 gst_handle->selected_tracks);
1785 g_free(gst_handle->selected_tracks);
1786 gst_handle->selected_tracks = NULL;
1788 if ((gst_handle->info).head)
1789 __gst_free_stuct(&(gst_handle->info).head);
1790 MEDIADEMUXER_FLEAVE();
1793 int _md_gst_destroy_pipeline(GstElement *pipeline)
1795 MEDIADEMUXER_FENTER();
1796 int ret = MD_ERROR_NONE;
1798 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1800 gst_object_unref(GST_OBJECT(pipeline));
1801 MEDIADEMUXER_FLEAVE();
1805 gst_object_unref(GST_OBJECT(pipeline));
1806 MEDIADEMUXER_FLEAVE();
1810 static int gst_demuxer_unprepare(MMHandleType pHandle)
1812 MEDIADEMUXER_FENTER();
1813 int ret = MD_ERROR_NONE;
1814 MEDIADEMUXER_CHECK_NULL(pHandle);
1815 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1817 /* disconnect signal handler */
1818 if (gst_handle->demux) {
1819 g_signal_handlers_disconnect_by_func(gst_handle->demux, __gst_on_pad_added, gst_handle);
1820 g_signal_handlers_disconnect_by_func(gst_handle->demux, __gst_no_more_pad, gst_handle);
1823 /* Modification : Fix pipeline state change was block by appsink When EOS received and appsink also has many data */
1825 track *atrack = gst_handle->info.head;
1827 if ((gst_handle->selected_tracks)[indx] == false) {
1828 MD_I("Track [%d] Not selected\n", indx);
1830 MD_I("Track [%d] to unset appsink...\n", indx);
1831 gst_demuxer_unset_track(pHandle, indx);
1834 track *next = atrack->next;
1842 _gst_clear_struct(gst_handle);
1843 if (gst_handle->bus_watch_id) {
1844 GSource *source = NULL;
1845 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1847 g_source_destroy(source);
1848 MD_I("Deallocation bus watch id");
1850 gst_handle->bus_watch_id = 0;
1853 MD_I("gst_demuxer_stop pipeline %p\n", gst_handle->pipeline);
1854 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1858 MEDIADEMUXER_FLEAVE();
1861 MEDIADEMUXER_FLEAVE();
1865 static int gst_demuxer_destroy(MMHandleType pHandle)
1867 MEDIADEMUXER_FENTER();
1868 int ret = MD_ERROR_NONE;
1869 MEDIADEMUXER_CHECK_NULL(pHandle);
1870 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1872 MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1874 g_free(new_mediademuxer);
1875 MEDIADEMUXER_FLEAVE();
1879 int gst_set_error_cb(MMHandleType pHandle,
1880 gst_error_cb callback, void *user_data)
1882 MEDIADEMUXER_FENTER();
1883 int ret = MD_ERROR_NONE;
1884 MEDIADEMUXER_CHECK_NULL(pHandle);
1885 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1887 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1888 MD_E("Already set mediademuxer_error_cb\n");
1889 ret = MD_ERROR_INVALID_ARGUMENT;
1893 MD_E("fail invalid argument (callback)\n");
1894 ret = MD_ERROR_INVALID_ARGUMENT;
1899 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1901 gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1902 gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1903 MEDIADEMUXER_FLEAVE();
1904 return MD_ERROR_NONE;
1906 MEDIADEMUXER_FLEAVE();
1910 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1912 MEDIADEMUXER_FENTER();
1913 int ret = MD_ERROR_NONE;
1914 MEDIADEMUXER_CHECK_NULL(pHandle);
1915 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1917 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1918 MD_E("Already set mediademuxer_eos_cb\n");
1919 ret = MD_ERROR_INVALID_ARGUMENT;
1923 MD_E("fail invalid argument (callback)\n");
1924 ret = MD_ERROR_INVALID_ARGUMENT;
1929 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1930 gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1931 gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1932 MEDIADEMUXER_FLEAVE();
1933 return MD_ERROR_NONE;
1935 MEDIADEMUXER_FLEAVE();
1939 static int __gst_eos_callback(int track_num, void* user_data)
1941 if (user_data == NULL) {
1942 MD_E("Invalid argument");
1945 mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1946 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1947 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1948 gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1950 MD_E("EOS received, but callback is not set!!!");
1951 return MD_ERROR_NONE;