2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * @file mediademuxer_port_gst.c
19 * @brief Handling for GStreamer Port, defined function and there implementation
24 #include <mediademuxer_error.h>
25 #include <mediademuxer_private.h>
26 #include <mediademuxer_port.h>
27 #include <mediademuxer_port_gst.h>
28 #include <media_packet_internal.h>
30 static int gst_demuxer_init(MMHandleType *pHandle);
31 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri);
32 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count);
33 static int gst_demuxer_set_track(MMHandleType pHandle, int track);
34 static int gst_demuxer_start(MMHandleType pHandle);
35 static int gst_demuxer_read_sample(MMHandleType pHandle,
36 media_packet_h *outbuf, int track_indx);
37 static int gst_demuxer_get_track_info(MMHandleType pHandle,
38 media_format_h *format, int index);
39 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1);
40 static int gst_demuxer_unset_track(MMHandleType pHandle, int track);
41 static int gst_demuxer_stop(MMHandleType pHandle);
42 static int gst_demuxer_unprepare(MMHandleType pHandle);
43 static int gst_demuxer_destroy(MMHandleType pHandle);
44 static int gst_set_error_cb(MMHandleType pHandle,
45 gst_error_cb callback, void *user_data);
46 static int gst_set_eos_cb(MMHandleType pHandle,
47 gst_eos_cb callback, void *user_data);
48 static int __gst_eos_callback(int track_num, void *user_data);
50 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code);
51 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code);
52 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code);
53 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message);
54 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error);
56 /* Media Demuxer API common */
57 static media_port_demuxer_ops def_demux_ops = {
59 .init = gst_demuxer_init,
60 .prepare = gst_demuxer_prepare,
61 .get_track_count = gst_demuxer_get_data_count,
62 .set_track = gst_demuxer_set_track,
63 .start = gst_demuxer_start,
64 .get_track_info = gst_demuxer_get_track_info,
65 .read_sample = gst_demuxer_read_sample,
66 .seek = gst_demuxer_seek,
67 .unset_track = gst_demuxer_unset_track,
68 .stop = gst_demuxer_stop,
69 .unprepare = gst_demuxer_unprepare,
70 .destroy = gst_demuxer_destroy,
71 .set_error_cb = gst_set_error_cb,
72 .set_eos_cb = gst_set_eos_cb,
75 static gint __gst_handle_core_error(mdgst_handle_t *gst_handle, int code)
77 gint trans_err = MEDIADEMUXER_ERROR_NONE;
79 MEDIADEMUXER_CHECK_NULL(gst_handle);
82 case GST_CORE_ERROR_MISSING_PLUGIN:
83 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
84 case GST_CORE_ERROR_STATE_CHANGE:
85 case GST_CORE_ERROR_SEEK:
86 case GST_CORE_ERROR_NOT_IMPLEMENTED:
87 case GST_CORE_ERROR_FAILED:
88 case GST_CORE_ERROR_TOO_LAZY:
89 case GST_CORE_ERROR_PAD:
90 case GST_CORE_ERROR_THREAD:
91 case GST_CORE_ERROR_NEGOTIATION:
92 case GST_CORE_ERROR_EVENT:
93 case GST_CORE_ERROR_CAPS:
94 case GST_CORE_ERROR_TAG:
95 case GST_CORE_ERROR_CLOCK:
96 case GST_CORE_ERROR_DISABLED:
98 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
105 static gint __gst_handle_library_error(mdgst_handle_t *gst_handle, int code)
107 gint trans_err = MEDIADEMUXER_ERROR_NONE;
109 MEDIADEMUXER_CHECK_NULL(gst_handle);
112 case GST_LIBRARY_ERROR_FAILED:
113 case GST_LIBRARY_ERROR_TOO_LAZY:
114 case GST_LIBRARY_ERROR_INIT:
115 case GST_LIBRARY_ERROR_SHUTDOWN:
116 case GST_LIBRARY_ERROR_SETTINGS:
117 case GST_LIBRARY_ERROR_ENCODE:
119 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
127 static gint __gst_handle_resource_error(mdgst_handle_t *gst_handle, int code)
129 gint trans_err = MEDIADEMUXER_ERROR_NONE;
131 MEDIADEMUXER_CHECK_NULL(gst_handle);
134 case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
135 trans_err = MEDIADEMUXER_ERROR_OUT_OF_MEMORY;
137 case GST_RESOURCE_ERROR_WRITE:
138 case GST_RESOURCE_ERROR_FAILED:
139 case GST_RESOURCE_ERROR_SEEK:
140 case GST_RESOURCE_ERROR_TOO_LAZY:
141 case GST_RESOURCE_ERROR_BUSY:
142 case GST_RESOURCE_ERROR_OPEN_WRITE:
143 case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
144 case GST_RESOURCE_ERROR_CLOSE:
145 case GST_RESOURCE_ERROR_SYNC:
146 case GST_RESOURCE_ERROR_SETTINGS:
148 trans_err = MEDIADEMUXER_ERROR_RESOURCE_LIMIT;
155 static gint __gst_handle_stream_error(mdgst_handle_t *gst_handle, GError *error, GstMessage *message)
157 gint trans_err = MEDIADEMUXER_ERROR_NONE;
159 MEDIADEMUXER_CHECK_NULL(gst_handle);
160 MEDIADEMUXER_CHECK_NULL(error);
161 MEDIADEMUXER_CHECK_NULL(message);
163 switch (error->code) {
164 case GST_STREAM_ERROR_FAILED:
165 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
166 case GST_STREAM_ERROR_DECODE:
167 case GST_STREAM_ERROR_WRONG_TYPE:
168 case GST_STREAM_ERROR_DECRYPT:
169 case GST_STREAM_ERROR_DECRYPT_NOKEY:
170 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
171 trans_err = __gst_transform_gsterror(gst_handle, message, error);
174 case GST_STREAM_ERROR_NOT_IMPLEMENTED:
175 case GST_STREAM_ERROR_TOO_LAZY:
176 case GST_STREAM_ERROR_ENCODE:
177 case GST_STREAM_ERROR_DEMUX:
178 case GST_STREAM_ERROR_MUX:
179 case GST_STREAM_ERROR_FORMAT:
181 trans_err = MEDIADEMUXER_ERROR_INVALID_OPERATION;
188 static gint __gst_transform_gsterror(mdgst_handle_t *gst_handle, GstMessage *message, GError *error)
190 gchar *src_element_name = NULL;
191 GstElement *src_element = NULL;
192 GstElementFactory *factory = NULL;
193 const gchar *klass = NULL;
195 MEDIADEMUXER_CHECK_NULL(gst_handle);
197 src_element = GST_ELEMENT_CAST(message->src);
201 src_element_name = GST_ELEMENT_NAME(src_element);
202 if (!src_element_name)
205 factory = gst_element_get_factory(src_element);
209 klass = gst_element_factory_get_klass(factory);
213 MD_I("error code=%d, msg=%s, src element=%s, class=%s\n",
214 error->code, error->message, src_element_name, klass);
216 switch (error->code) {
217 case GST_STREAM_ERROR_DECODE:
218 case GST_STREAM_ERROR_FAILED:
219 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
222 case GST_STREAM_ERROR_CODEC_NOT_FOUND:
223 case GST_STREAM_ERROR_TYPE_NOT_FOUND:
224 case GST_STREAM_ERROR_WRONG_TYPE:
225 return MEDIADEMUXER_ERROR_NOT_SUPPORTED;
229 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
233 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
236 return MEDIADEMUXER_ERROR_INVALID_PARAMETER;
240 int gst_mediademxer_port_register(media_port_demuxer_ops *pOps)
242 MEDIADEMUXER_FENTER();
243 int ret = MD_ERROR_NONE;
244 MEDIADEMUXER_CHECK_NULL(pOps);
245 def_demux_ops.n_size = sizeof(def_demux_ops);
247 memcpy((char *)pOps + sizeof(pOps->n_size),
248 (char *)&def_demux_ops + sizeof(def_demux_ops.n_size),
249 pOps->n_size - sizeof(pOps->n_size));
251 MEDIADEMUXER_FLEAVE();
255 static int gst_demuxer_init(MMHandleType *pHandle)
257 MEDIADEMUXER_FENTER();
258 int ret = MD_ERROR_NONE;
259 mdgst_handle_t *new_mediademuxer = NULL;
260 new_mediademuxer = (mdgst_handle_t *)g_malloc(sizeof(mdgst_handle_t));
261 MD_I("gst_demuxer_init allocating new_mediademuxer:%p\n", new_mediademuxer);
262 if (!new_mediademuxer) {
263 MD_E("Cannot allocate memory for demuxer\n");
267 memset(new_mediademuxer, 0, sizeof(mdgst_handle_t));
268 new_mediademuxer->is_prepared = false;
269 (new_mediademuxer->info).num_audio_track = 0;
270 (new_mediademuxer->info).num_video_track = 0;
271 (new_mediademuxer->info).num_subtitle_track = 0;
272 (new_mediademuxer->info).num_other_track = 0;
273 (new_mediademuxer->info).head = NULL;
274 *pHandle = (MMHandleType)new_mediademuxer;
275 new_mediademuxer->total_tracks = 0;
276 MEDIADEMUXER_FLEAVE();
279 MEDIADEMUXER_FLEAVE();
283 gboolean __gst_bus_call(GstBus *bus, GstMessage *msg, gpointer data)
285 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
286 MEDIADEMUXER_FENTER();
287 int ret = MD_ERROR_NONE;
288 switch (GST_MESSAGE_TYPE(msg)) {
289 case GST_MESSAGE_EOS: {
293 case GST_MESSAGE_ERROR: {
294 GError *error = NULL;
295 gst_message_parse_error(msg, &error, NULL);
297 MD_I("GST error message parsing failed");
301 if (error->domain == GST_STREAM_ERROR)
302 ret = __gst_handle_stream_error(gst_handle, error, msg);
303 else if (error->domain == GST_RESOURCE_ERROR)
304 ret = __gst_handle_resource_error(gst_handle, error->code);
305 else if (error->domain == GST_LIBRARY_ERROR)
306 ret = __gst_handle_library_error(gst_handle, error->code);
307 else if (error->domain == GST_CORE_ERROR)
308 ret = __gst_handle_core_error(gst_handle, error->code);
310 MD_W("Unexpected error has occured");
312 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
313 ((mediademuxer_error_cb)gst_handle->user_cb[_GST_EVENT_TYPE_ERROR])
314 (ret, gst_handle->user_data[_GST_EVENT_TYPE_ERROR]);
315 MD_W("Error : (ox%08x)", ret);
317 MD_E("Error: %s\n", error->message);
324 MEDIADEMUXER_FLEAVE();
328 static void __gst_no_more_pad(GstElement *element, gpointer data)
330 MEDIADEMUXER_FENTER();
331 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
333 track_info *head_track = &(gst_handle->info);
334 track *head = head_track->head;
335 gst_handle->selected_tracks =
336 (bool *) g_malloc(sizeof(bool) * (gst_handle->total_tracks));
337 MD_I("Allocating %p to core->selected_tracks \n", gst_handle->selected_tracks);
338 if (!gst_handle->selected_tracks) {
339 MD_E("[%s]Memory allocation failed\n", __FUNCTION__);
342 for (loop_track = 0; loop_track < gst_handle->total_tracks;
344 gst_handle->selected_tracks[loop_track] = false;
346 MD_I("Number of video tracks are %d\n", head_track->num_video_track);
347 MD_I("Number of audio tracks are %d\n", head_track->num_audio_track);
348 MD_I("Number of subtitle tracks are %d\n",
349 head_track->num_subtitle_track);
350 MD_I("Number of other tracks are %d\n", head_track->num_other_track);
352 MD_I("track caps[%s]\n", head->caps_string);
355 gst_handle->is_prepared = true;
356 MD_I("core->is_prepared: ");
357 gst_handle->is_prepared ? MD_I("true\n") : MD_I("false\n");
358 MEDIADEMUXER_FLEAVE();
361 void __gst_free_stuct(track **head)
363 MEDIADEMUXER_FENTER();
369 MD_I("deallocate GST_PAD %p\n", temp->pad);
370 gst_object_unref(temp->pad);
373 MD_I("deallocate GST_PAD caps_ %p\n", temp->caps);
374 gst_caps_unref(temp->caps);
377 MD_I("deallocate GST_PAD name %p\n", temp->name);
380 if (temp->caps_string) {
381 MD_I("deallocate GST_PAD caps_string %p\n",
383 g_free(temp->caps_string);
386 MD_I("unref media_format %p\n", temp->format);
387 media_format_unref(temp->format);
390 track *next = temp->next;
391 MD_I("deallocate memory %p\n", temp);
395 MD_I("deallocate memory %p\n", temp);
401 MEDIADEMUXER_FLEAVE();
404 int __gst_add_track_info(GstPad *pad, gchar *name, track **head,
405 GstElement *pipeline)
407 MEDIADEMUXER_FENTER();
408 GstPad *apppad = NULL;
409 GstPad *queue_sink_pad = NULL;
410 GstPad *queue_src_pad = NULL;
411 GstCaps *outcaps = NULL;
412 GstPad *parse_sink_pad = NULL;
413 GstElement *parse_element = NULL;
416 temp = (track *)(g_malloc(sizeof(track)));
418 MD_E("Not able to allocate memory");
421 MD_I("allocate memory %p", temp);
424 temp->caps = gst_pad_get_current_caps(pad);
426 temp->name = g_strndup(name, strlen(name));
429 temp->caps_string = gst_caps_to_string(temp->caps);
432 temp->need_codec_data = TRUE;
434 /* Link demuxer - queue */
435 temp->queue = gst_element_factory_make("queue", NULL);
437 MD_E("factory not able to make queue");
441 if (!gst_bin_add(GST_BIN(pipeline), temp->queue)) {
442 MD_E("fail add queue in pipeline");
446 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
447 if (!queue_sink_pad) {
448 MD_E("queue_sink_pad of appsink not avaible");
452 MEDIADEMUXER_SET_STATE(temp->queue, GST_STATE_PAUSED, ERROR);
453 MEDIADEMUXER_LINK_PAD(pad, queue_sink_pad, ERROR);
455 temp->appsink = gst_element_factory_make("appsink", NULL);
456 if (!temp->appsink) {
457 MD_E("factory not able to make appsink");
461 if (!gst_bin_add(GST_BIN(pipeline), temp->appsink)) {
462 MD_E("fail add queue in pipeline");
466 gst_app_sink_set_max_buffers((GstAppSink *) temp->appsink, (guint) 0);
467 gst_app_sink_set_drop((GstAppSink *) temp->appsink, true);
468 MEDIADEMUXER_SET_STATE(temp->appsink, GST_STATE_PAUSED, ERROR);
470 queue_src_pad = gst_element_get_static_pad(temp->queue, "src");
471 if (!queue_src_pad) {
472 MD_E("queue_src_pad of appsink not avaible");
475 apppad = gst_element_get_static_pad(temp->appsink, "sink");
477 MD_E("sink pad of appsink not avaible");
480 /* Check for type video and it should be h264 */
481 if (temp->name && strstr(temp->name, "video")) {
482 if (strstr(temp->caps_string, "h264")) {
483 parse_element = gst_element_factory_make("h264parse", NULL);
484 if (!parse_element) {
485 MD_E("factory not able to make h264parse");
488 } else if (strstr(temp->caps_string, "mpeg")) {
489 parse_element = gst_element_factory_make("mpeg4videoparse", NULL);
490 if (!parse_element) {
491 MD_E("factory not able to make h264parse");
494 g_object_set(G_OBJECT(parse_element), "config-interval", 1, NULL);
498 gst_bin_add(GST_BIN(pipeline), parse_element);
499 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
500 if (!parse_sink_pad) {
501 gst_object_unref(parse_element);
502 MD_E("sink pad of h264parse not available");
505 MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
506 /* Link demuxer pad with sink pad of parse element */
507 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
509 if (strstr(temp->caps_string, "h264")) {
510 outcaps = gst_caps_new_simple("video/x-h264", "stream-format", G_TYPE_STRING, "byte-stream", NULL);
511 gst_element_link_filtered(parse_element, temp->appsink, outcaps);
512 gst_caps_unref(outcaps);
513 } else if (strstr(temp->caps_string, "mpeg")) {
514 gst_element_link(parse_element, temp->appsink);
516 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
519 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
521 } else if (temp->name && strstr(temp->name, "audio")) {
523 if (strstr(temp->caps_string, "audio/mpeg")) {
525 GstStructure *structure = NULL;
526 structure = gst_caps_get_structure(temp->caps, 0);
527 gst_structure_get_int (structure, "mpegversion", &mpegversion);
528 if (mpegversion == 2 || mpegversion == 4)
529 parse_element = gst_element_factory_make("aacparse", NULL);
530 else if (mpegversion == 1)
531 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
532 } else if (strstr(temp->caps_string, "application/x-id3")) {
533 parse_element = gst_element_factory_make("mpegaudioparse", NULL);
534 } else if (strstr(temp->caps_string, "audio/x-amr-nb-sh")
535 || strstr(temp->caps_string, "audio/x-amr-wb-sh")) {
536 parse_element = gst_element_factory_make("amrparse", NULL);
537 } else if (strstr(temp->caps_string, "audio/x-wav")) {
538 parse_element = gst_element_factory_make("wavparse", NULL);
539 } else if (strstr(temp->caps_string, "audio/x-flac")) {
540 parse_element = gst_element_factory_make("flacparse", NULL);
544 gst_bin_add(GST_BIN(pipeline), parse_element);
545 parse_sink_pad = gst_element_get_static_pad(parse_element, "sink");
546 if (!parse_sink_pad) {
547 gst_object_unref(parse_element);
548 MD_E("sink pad of h264parse not available");
551 MEDIADEMUXER_SET_STATE(parse_element, GST_STATE_PAUSED, ERROR);
553 /* Link demuxer pad with sink pad of parse element */
554 MEDIADEMUXER_LINK_PAD(queue_src_pad, parse_sink_pad, ERROR);
556 /* Link src pad with appSink element */
557 gst_element_link(parse_element, temp->appsink);
559 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
562 MEDIADEMUXER_LINK_PAD(queue_src_pad, apppad, ERROR);
564 /* gst_pad_link(pad, fpad) */
574 gst_object_unref(queue_sink_pad);
576 gst_object_unref(queue_src_pad);
578 gst_object_unref(apppad);
580 gst_object_unref(parse_sink_pad);
581 MEDIADEMUXER_FLEAVE();
582 return MD_ERROR_NONE;
586 gst_object_unref(parse_element);
588 gst_object_unref(temp->caps);
589 if (temp->caps_string)
590 g_free(temp->caps_string);
592 gst_object_unref(temp->queue);
594 gst_object_unref(temp->appsink);
596 gst_object_unref(queue_sink_pad);
598 gst_object_unref(queue_src_pad);
600 gst_object_unref(apppad);
602 gst_object_unref(parse_sink_pad);
603 __gst_free_stuct(head);
604 MEDIADEMUXER_FLEAVE();
608 static void __gst_on_pad_added(GstElement *element, GstPad *pad, gpointer data)
610 MEDIADEMUXER_FENTER();
611 MD_I("Dynamic pad created, linking demuxer/decoder\n");
613 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
614 track_info *head_track = &(gst_handle->info);
615 gchar *name = gst_pad_get_name(pad);
616 gst_handle->total_tracks++;
617 if (__gst_add_track_info(pad, name, &(head_track->head), gst_handle->pipeline)
619 MD_E("unable to added track info");
620 head_track->num_audio_track = 0;
621 head_track->num_video_track = 0;
622 head_track->num_subtitle_track = 0;
623 head_track->num_other_track = 0;
624 __gst_free_stuct(&(head_track->head));
627 tmp = head_track->head;
630 if (!tmp || !tmp->caps_string) {
631 MD_I("trak or trak caps_string is NULL\n");
632 MEDIADEMUXER_FLEAVE();
635 if (tmp->caps_string[0] == 'v') {
636 MD_I("found Video Pad\n");
637 (head_track->num_video_track)++;
638 } else if (tmp->caps_string[0] == 'a') {
639 MD_I("found Audio Pad\n");
640 (head_track->num_audio_track)++;
641 } else if (tmp->caps_string[0] == 's') {
642 MD_I("found subtitle(or Text) Pad\n");
643 (head_track->num_subtitle_track)++;
645 MD_W("found Pad %s\n", name);
646 (head_track->num_other_track)++;
648 MEDIADEMUXER_FLEAVE();
651 static int __gst_create_audio_only_pipeline(gpointer data, GstCaps *caps)
653 MEDIADEMUXER_FENTER();
654 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
656 GstPad *aud_pad = NULL;
657 GstPad *aud_srcpad = NULL;
658 GstPad *fake_pad = NULL;
659 GstElement *id3tag = NULL;
662 track_info *head_track = &(gst_handle->info);
663 track *tmp_track = NULL;
665 gst_handle->is_valid_container = true;
667 type = gst_caps_to_string(caps);
669 if (strstr(type, "adts") || strstr(type, "adif")) {
670 gst_handle->demux = gst_element_factory_make("aacparse", NULL);
671 } else if (strstr(type, "audio/mpeg")) {
672 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
673 } else if (strstr(type, "application/x-id3")) {
674 id3tag = gst_element_factory_make("id3demux", NULL);
675 gst_handle->demux = gst_element_factory_make("mpegaudioparse", NULL);
676 } else if (strstr(type, "audio/x-amr-nb-sh")
677 || strstr(type, "audio/x-amr-wb-sh")) {
678 gst_handle->demux = gst_element_factory_make("amrparse", NULL);
679 } else if (strstr(type, "audio/x-wav")) {
680 gst_handle->demux = gst_element_factory_make("wavparse", NULL);
681 } else if (strstr(type, "audio/x-flac")) {
682 gst_handle->demux = gst_element_factory_make("flacparse", NULL);
685 if (!gst_handle->demux) {
686 gst_handle->is_valid_container = false;
687 MD_E("factory not able to create audio parse element\n");
690 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
691 gst_handle->demux, id3tag, NULL);
692 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
694 MD_E("fail to get typefind src pad.\n");
698 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
700 MD_E("fail to get fakesink sink pad.\n");
703 gst_pad_unlink(pad, fake_pad);
706 gst_object_unref(fake_pad);
709 aud_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
711 aud_pad = gst_element_get_static_pad(id3tag, "sink");
713 MD_E("fail to get audio parse sink pad.\n");
717 MEDIADEMUXER_LINK_PAD(pad, aud_pad, ERROR);
719 gst_object_unref(pad);
721 gst_object_unref(aud_pad);
724 MEDIADEMUXER_SET_STATE(gst_handle->demux, GST_STATE_PAUSED, ERROR);
726 MEDIADEMUXER_SET_STATE(id3tag, GST_STATE_PAUSED, ERROR);
727 MEDIADEMUXER_SET_STATE(gst_handle->demux, GST_STATE_PAUSED, ERROR);
728 gst_element_link(id3tag, gst_handle->demux);
732 gst_handle->total_tracks++;
734 aud_srcpad = gst_element_get_static_pad(gst_handle->demux, "src");
736 MD_E("fail to get audioparse source pad.\n");
740 name = gst_pad_get_name(aud_srcpad);
741 if (__gst_add_track_info(aud_srcpad, name, &(head_track->head), gst_handle->pipeline) != MD_ERROR_NONE) {
742 MD_E("unable to added track info");
743 head_track->num_audio_track = 0;
744 head_track->num_video_track = 0;
745 head_track->num_subtitle_track = 0;
746 head_track->num_other_track = 0;
747 __gst_free_stuct(&(head_track->head));
751 tmp_track = head_track->head;
752 while (tmp_track != NULL && aud_srcpad != tmp_track->pad)
753 tmp_track = tmp_track->next;
755 if (tmp_track != NULL) {
757 gst_caps_unref(tmp_track->caps);
758 tmp_track->caps = gst_caps_copy(caps);
759 if (tmp_track->caps_string)
760 g_free(tmp_track->caps_string);
761 tmp_track->caps_string = gst_caps_to_string(tmp_track->caps);
762 MD_I("caps set to %s\n", tmp_track->caps_string);
764 g_free(tmp_track->name);
765 tmp_track->name = g_strndup("audio", strlen("audio"));
768 (head_track->num_audio_track)++;
772 gst_object_unref(aud_srcpad);
774 __gst_no_more_pad(gst_handle->demux, data);
777 MEDIADEMUXER_FLEAVE();
778 return MD_ERROR_NONE;
781 gst_handle->is_valid_container = false;
782 if (gst_handle->demux)
783 gst_object_unref(gst_handle->demux);
785 gst_object_unref(pad);
787 gst_object_unref(aud_pad);
789 gst_object_unref(fake_pad);
791 gst_object_unref(aud_srcpad);
795 MEDIADEMUXER_FLEAVE();
799 static void __gst_cb_typefind(GstElement *tf, guint probability,
800 GstCaps *caps, gpointer data)
802 MEDIADEMUXER_FENTER();
803 mdgst_handle_t *gst_handle = (mdgst_handle_t *)data;
805 GstPad *demuxer_pad = NULL;
806 GstPad *fake_pad = NULL;
808 type = gst_caps_to_string(caps);
810 MD_I("Media type %s found, probability %d%%\n", type, probability);
811 if (strstr(type, "quicktime") || (strstr(type, "audio/x-m4a")) || strstr(type, "x-3gp")
812 || strstr(type, "ogg") || strstr(type, "flv") || strstr(type, "x-msvideo")) {
813 gst_handle->is_valid_container = true;
814 if (strstr(type, "ogg"))
815 gst_handle->demux = gst_element_factory_make("oggdemux", NULL);
816 else if (strstr(type, "flv"))
817 gst_handle->demux = gst_element_factory_make("flvdemux", NULL);
818 else if (strstr(type, "x-msvideo"))
819 gst_handle->demux = gst_element_factory_make("avidemux", NULL);
821 gst_handle->demux = gst_element_factory_make("qtdemux", NULL);
823 if (!gst_handle->demux) {
824 gst_handle->is_valid_container = false;
825 MD_E("factory not able to create qtdemux\n");
828 g_signal_connect(gst_handle->demux, "pad-added",
829 G_CALLBACK(__gst_on_pad_added), gst_handle);
830 g_signal_connect(gst_handle->demux, "no-more-pads",
831 G_CALLBACK(__gst_no_more_pad), gst_handle);
832 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
833 gst_handle->demux, NULL);
834 pad = gst_element_get_static_pad(gst_handle->typefind, "src");
836 MD_E("fail to get typefind src pad.\n");
839 demuxer_pad = gst_element_get_static_pad(gst_handle->demux, "sink");
841 MD_E("fail to get qtdemuc sink pad.\n");
844 fake_pad = gst_element_get_static_pad(gst_handle->fakesink, "sink");
846 MD_E("fail to get fakesink sink pad.\n");
849 gst_pad_unlink(pad, fake_pad);
850 MEDIADEMUXER_LINK_PAD(pad, demuxer_pad, ERROR);
851 MEDIADEMUXER_SET_STATE(gst_handle->demux,
852 GST_STATE_PAUSED, ERROR);
854 gst_object_unref(pad);
856 gst_object_unref(demuxer_pad);
858 gst_object_unref(fake_pad);
860 } else if ((strstr(type, "adts"))
861 || (strstr(type, "audio/mpeg"))
862 || (strstr(type, "audio/x-wav"))
863 || (strstr(type, "audio/x-flac"))
864 || (strstr(type, "application/x-id3"))
865 || (strstr(type, "audio/x-amr-nb-sh"))
866 || (strstr(type, "audio/x-amr-wb-sh"))) {
867 MD_I("Audio only format is found\n");
868 __gst_create_audio_only_pipeline(data, caps);
870 gst_handle->is_valid_container = false;
871 MD_E("Not supported container %s\n", type);
875 MEDIADEMUXER_FLEAVE();
878 gst_handle->is_valid_container = false;
879 if (gst_handle->demux)
880 gst_object_unref(gst_handle->demux);
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 int remote_streaming = 0;
900 /* Initialize GStreamer */
901 /* Note: Replace the arguments of gst_init to pass the command line args to GStreamer. */
902 gst_init(NULL, NULL);
904 /* Create the empty pipeline */
905 gst_handle->pipeline = gst_pipeline_new("Demuxer Gst pipeline");
906 if (!gst_handle->pipeline) {
907 MD_E("pipeline create fail");
912 /* Create the elements */
913 if ((path = strstr(uri, "http://"))) {
914 gst_handle->filesrc = gst_element_factory_make("souphttpsrc", NULL);
915 remote_streaming = 1;
916 MD_I("Source is http stream. \n");
918 gst_handle->filesrc = gst_element_factory_make("filesrc", NULL);
919 MD_I("Source is file stream \n");
921 if (!gst_handle->filesrc) {
922 MD_E("filesrc creation failed");
927 /* Modify the source's properties */
928 if (remote_streaming == 1)
929 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri, NULL);
931 g_object_set(G_OBJECT(gst_handle->filesrc), "location", uri + 7, NULL);
932 gst_handle->typefind = gst_element_factory_make("typefind", NULL);
933 if (!gst_handle->typefind) {
934 MD_E("typefind creation failed");
938 g_signal_connect(gst_handle->typefind, "have-type",
939 G_CALLBACK(__gst_cb_typefind), gst_handle);
940 gst_handle->fakesink = gst_element_factory_make("fakesink", NULL);
941 if (!gst_handle->fakesink) {
942 MD_E("fakesink creation failed");
947 /* Build the pipeline */
948 gst_bin_add_many(GST_BIN(gst_handle->pipeline),
950 gst_handle->typefind,
951 gst_handle->fakesink,
953 gst_element_link_many(gst_handle->filesrc,
954 gst_handle->typefind,
955 gst_handle->fakesink,
958 /* connect signals, bus watcher */
959 bus = gst_pipeline_get_bus(GST_PIPELINE(gst_handle->pipeline));
960 gst_handle->bus_watch_id = gst_bus_add_watch(bus, __gst_bus_call, gst_handle);
961 gst_handle->thread_default = g_main_context_get_thread_default();
962 gst_object_unref(GST_OBJECT(bus));
964 /* set pipeline state to PAUSED */
965 MEDIADEMUXER_SET_STATE(gst_handle->pipeline, GST_STATE_PAUSED, ERROR);
968 while (gst_handle->is_prepared != true) {
970 usleep(POLLING_INTERVAL);
971 MD_I("Inside while loop\n");
972 if (count > POLLING_INTERVAL) {
973 MD_E("Error occure\n");
979 MEDIADEMUXER_FLEAVE();
982 MEDIADEMUXER_FLEAVE();
986 static int gst_demuxer_prepare(MMHandleType pHandle, char *uri)
988 MEDIADEMUXER_FENTER();
989 int ret = MD_ERROR_NONE;
990 MEDIADEMUXER_CHECK_NULL(pHandle);
991 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
993 MD_I("gst_demuxer_prepare Creating pipeline %p", new_mediademuxer);
994 ret = _gst_create_pipeline(new_mediademuxer, uri);
995 if (ret != MD_ERROR_NONE) {
996 MD_E("_gst_create_pipeline() failed. returned %d\n", ret);
999 MEDIADEMUXER_FLEAVE();
1002 MEDIADEMUXER_FLEAVE();
1006 static int gst_demuxer_get_data_count(MMHandleType pHandle, int *count)
1008 MEDIADEMUXER_FENTER();
1009 int ret = MD_ERROR_NONE;
1010 MEDIADEMUXER_CHECK_NULL(pHandle);
1011 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1013 *count = (new_mediademuxer->info).num_video_track +
1014 (new_mediademuxer->info).num_audio_track +
1015 (new_mediademuxer->info).num_subtitle_track +
1016 (new_mediademuxer->info).num_other_track;
1017 MEDIADEMUXER_FLEAVE();
1021 int _gst_set_appsink(track *temp, int index, int loop)
1023 MEDIADEMUXER_FENTER();
1024 int ret = MD_ERROR_NONE;
1027 while (count != index) {
1031 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint) MAX_APP_BUFFER);
1032 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), false);
1033 MEDIADEMUXER_FLEAVE();
1037 static int gst_demuxer_set_track(MMHandleType pHandle, int track)
1039 MEDIADEMUXER_FENTER();
1040 int ret = MD_ERROR_NONE;
1041 MEDIADEMUXER_CHECK_NULL(pHandle);
1042 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1044 MD_I("total_tracks (%d) :: selected track (%d)", new_mediademuxer->total_tracks, track);
1045 if (track >= new_mediademuxer->total_tracks || track < 0) {
1046 MD_E("total_tracks is less then selected track, So not support this track");
1047 ret = MD_ERROR_INVALID_ARGUMENT;
1050 new_mediademuxer->selected_tracks[track] = true;
1051 _gst_set_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1052 new_mediademuxer->total_tracks);
1053 MEDIADEMUXER_FLEAVE();
1054 return MD_ERROR_NONE;
1056 MEDIADEMUXER_FLEAVE();
1060 static int _gst_unlink_unselected_track(track *temp, int index)
1062 MEDIADEMUXER_FENTER();
1063 int ret = MD_ERROR_NONE;
1065 GstPad *queue_sink_pad = NULL;
1066 while (count != index) {
1070 queue_sink_pad = gst_element_get_static_pad(temp->queue, "sink");
1071 if (!queue_sink_pad) {
1072 MD_E("queue_sink_pad of appsink not avaible\n");
1075 if (gst_pad_unlink(temp->pad, queue_sink_pad) != TRUE)
1076 MD_W("demuxer is already unlinked from queue for track %d\n", index);
1078 gst_object_unref(queue_sink_pad);
1079 MEDIADEMUXER_FLEAVE();
1083 static int gst_demuxer_start(MMHandleType pHandle)
1085 MEDIADEMUXER_FENTER();
1086 int ret = MD_ERROR_NONE;
1087 MEDIADEMUXER_CHECK_NULL(pHandle);
1088 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1091 for (indx = 0; indx < gst_handle->total_tracks; indx++) {
1092 MD_I("track indx[%d] is marked as [%d]. (0- not selected, 1= selected)\n",
1093 indx, gst_handle->selected_tracks[indx]);
1095 if (gst_handle->selected_tracks[indx] == false)
1096 _gst_demuxer_unset(pHandle, indx);
1098 if (gst_handle->selected_tracks[indx] != true) {
1099 if (_gst_unlink_unselected_track((((mdgst_handle_t *)pHandle)->info).head, indx) != MD_ERROR_NONE) {
1100 MD_E("Failed to unlink unselected tracks\n");
1101 ret = MD_INTERNAL_ERROR;
1108 track_info *head_track = &(gst_handle->info);
1109 MD_I("Total Audio track=%d, Video track=%d, text track=%d\n",
1110 head_track->num_audio_track, head_track->num_video_track,
1111 head_track->num_subtitle_track);
1113 track *temp = head_track->head;
1116 MD_I("Got one element %p\n", temp->appsink);
1117 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) ==
1118 GST_STATE_CHANGE_FAILURE) {
1119 MD_E("Failed to set into PLAYING state");
1120 ret = MD_INTERNAL_ERROR;
1123 MD_I("set the state to playing\n");
1126 track *next = temp->next;
1133 MD_I("gst_demuxer_start pipeine %p", gst_handle);
1134 MEDIADEMUXER_FLEAVE();
1137 MEDIADEMUXER_FLEAVE();
1141 int _set_mime_text(media_format_h format, track *head)
1143 MEDIADEMUXER_FENTER();
1144 int ret = MD_ERROR_NONE;
1145 GstStructure *struc = NULL;
1146 struc = gst_caps_get_structure(head->caps, 0);
1148 MD_E("cannot get structure from caps.\n");
1151 if (gst_structure_has_name(struc, "text/x-raw")) {
1152 if (media_format_set_text_mime(format, MEDIA_FORMAT_TEXT_MP4))
1155 MD_I("Text mime not supported so far\n");
1159 MEDIADEMUXER_FLEAVE();
1162 MEDIADEMUXER_FLEAVE();
1166 int _set_mime_video(media_format_h format, track *head)
1168 MEDIADEMUXER_FENTER();
1169 int ret = MD_ERROR_NONE;
1170 GstStructure *struc = NULL;
1173 int frame_rate_numerator = 0;
1174 int frame_rate_denominator = 0;
1175 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1176 struc = gst_caps_get_structure(head->caps, 0);
1178 MD_E("cannot get structure from caps.\n");
1181 if (gst_structure_has_name(struc, "video/x-h264")) {
1182 mime_type = MEDIA_FORMAT_H264_SP;
1183 } else if (gst_structure_has_name(struc, "video/x-h263")) {
1184 mime_type = MEDIA_FORMAT_H263;
1185 } else if (gst_structure_has_name(struc, "video/mpeg")) {
1186 mime_type = MEDIA_FORMAT_MPEG4_SP;
1188 MD_W("Video mime (%s) not supported so far\n", gst_structure_get_name(struc));
1191 if (media_format_set_video_mime(format, mime_type)) {
1192 MD_E("Unable to set video mime type (%x)\n", mime_type);
1195 gst_structure_get_int(struc, "width", &src_width);
1196 gst_structure_get_int(struc, "height", &src_height);
1197 if (media_format_set_video_width(format, src_width)) {
1198 MD_E("Unable to set video width\n");
1201 if (media_format_set_video_height(format, src_height)) {
1202 MD_E("Unable to set video height\n");
1205 gst_structure_get_fraction(struc, "framerate", &frame_rate_numerator, &frame_rate_denominator);
1206 if (media_format_set_video_frame_rate(format, frame_rate_numerator)) {
1207 MD_E("Unable to set video frame rate\n");
1210 MEDIADEMUXER_FLEAVE();
1213 MEDIADEMUXER_FLEAVE();
1217 int _set_mime_audio(media_format_h format, track *head)
1219 MEDIADEMUXER_FENTER();
1220 int ret = MD_ERROR_NONE;
1221 GstStructure *struc = NULL;
1226 const gchar *stream_format;
1227 media_format_mimetype_e mime_type = MEDIA_FORMAT_MAX;
1229 struc = gst_caps_get_structure(head->caps, 0);
1231 MD_E("cannot get structure from caps.\n");
1235 if (gst_structure_has_name(struc, "application/x-id3"))
1237 if (gst_structure_has_name(struc, "audio/mpeg") || id3_flag) {
1240 gst_structure_get_int(struc, "mpegversion", &mpegversion);
1241 if (mpegversion == 4 || mpegversion == 2) {
1242 mime_type = MEDIA_FORMAT_AAC_LC;
1243 if (media_format_set_audio_mime(format, mime_type))
1245 stream_format = gst_structure_get_string(struc, "stream-format");
1247 if (strncmp(stream_format, "adts", 4) == 0)
1248 media_format_set_audio_aac_type(format, 1);
1250 media_format_set_audio_aac_type(format, 0);
1252 } else if (mpegversion == 1 || id3_flag) {
1253 gst_structure_get_int(struc, "layer", &layer);
1254 if ((layer == 3) || (id3_flag == 1)) {
1255 mime_type = MEDIA_FORMAT_MP3;
1257 MD_I("No Support for MPEG%d Layer %d media\n", mpegversion, layer);
1261 } else if (gst_structure_has_name(struc, "audio/x-amr-nb-sh") ||
1262 gst_structure_has_name(struc, "audio/x-amr-wb-sh")) {
1263 if (gst_structure_has_name(struc, "audio/x-amr-nb-sh")) {
1264 mime_type = MEDIA_FORMAT_AMR_NB;
1267 mime_type = MEDIA_FORMAT_AMR_WB;
1270 } else if (gst_structure_has_name(struc, "audio/AMR")) {
1271 mime_type = MEDIA_FORMAT_AMR_NB;
1272 } else if (gst_structure_has_name(struc, "audio/AMR-WB")) {
1273 mime_type = MEDIA_FORMAT_AMR_WB;
1274 } else if (gst_structure_has_name(struc, "audio/x-wav")) {
1275 mime_type = MEDIA_FORMAT_PCM;
1276 } else if (gst_structure_has_name(struc, "audio/x-flac")) {
1277 mime_type = MEDIA_FORMAT_FLAC;
1278 } else if (gst_structure_has_name(struc, "audio/x-vorbis")) {
1279 mime_type = MEDIA_FORMAT_VORBIS;
1281 MD_W("Audio mime (%s) not supported so far\n", gst_structure_get_name(struc));
1284 if (media_format_set_audio_mime(format, mime_type))
1286 gst_structure_get_int(struc, "channels", &channels);
1287 if (channels == 0) { /* default */
1288 if (mime_type == MEDIA_FORMAT_AMR_NB || mime_type == MEDIA_FORMAT_AMR_WB)
1293 if (media_format_set_audio_channel(format, channels))
1296 gst_structure_get_int(struc, "rate", &rate);
1298 rate = 44100; /* default */
1299 if (media_format_set_audio_samplerate(format, rate))
1301 gst_structure_get_int(struc, "bit", &bit);
1303 bit = 16; /* default */
1304 if (media_format_set_audio_bit(format, bit))
1306 MEDIADEMUXER_FLEAVE();
1309 MEDIADEMUXER_FLEAVE();
1313 static int gst_demuxer_get_track_info(MMHandleType pHandle,
1314 media_format_h *format, int index)
1316 MEDIADEMUXER_FENTER();
1317 int ret = MD_ERROR_NONE;
1318 MEDIADEMUXER_CHECK_NULL(pHandle);
1319 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1324 temp = (new_mediademuxer->info).head;
1325 loop = (new_mediademuxer->info).num_video_track +
1326 (new_mediademuxer->info).num_audio_track +
1327 (new_mediademuxer->info).num_subtitle_track +
1328 (new_mediademuxer->info).num_other_track;
1329 if (index >= loop || index < 0) {
1330 MD_E("total tracks(loop) is less then selected track(index), So not support this track");
1335 while (count != index) {
1339 if (temp->format != NULL) {
1340 ret = media_format_ref(temp->format);
1341 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1342 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1343 ret = MD_INTERNAL_ERROR;
1346 ret = media_format_make_writable(temp->format, format); /* copy the content */
1347 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1348 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1349 media_format_unref(temp->format);
1350 ret = MD_INTERNAL_ERROR;
1353 MEDIADEMUXER_FLEAVE();
1356 ret = media_format_create(&(temp->format));
1357 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1358 MD_E("Mediaformat creation failed. returned %d\n", ret);
1359 ret = MD_INTERNAL_ERROR;
1363 MD_I("CAPS for selected track [%d] is [%s]\n", index, temp->caps_string);
1364 MD_I("format ptr[%p]\n", temp->format);
1365 if (temp->caps_string[0] == 'a') {
1366 MD_I("Setting for Audio \n");
1367 _set_mime_audio(temp->format, temp);
1368 } else if (temp->caps_string[0] == 'v') {
1369 MD_I("Setting for Video \n");
1370 _set_mime_video(temp->format, temp);
1371 } else if (temp->caps_string[0] == 't') {
1372 MD_I("Setting for Subtitle\n");
1373 _set_mime_text(temp->format, temp);
1375 MD_W("Not supported so far (except audio, video and subtitle)\n");
1378 ret = media_format_ref(temp->format); /* increment the ref to retain the original content */
1379 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1380 MD_E("Mediaformat reference count increment failed. returned %d\n", ret);
1381 ret = MD_INTERNAL_ERROR;
1384 ret = media_format_make_writable(temp->format, format); /* copy the content */
1385 if (ret != MEDIA_FORMAT_ERROR_NONE) {
1386 MD_E("Mediaformat create copy failed. returned %d\n", ret);
1387 media_format_unref(temp->format);
1388 ret = MD_INTERNAL_ERROR;
1391 MEDIADEMUXER_FLEAVE();
1394 MEDIADEMUXER_FLEAVE();
1398 static int _gst_copy_buf_to_media_packet(media_packet_h out_pkt,
1399 GstBuffer *buffer, GstBuffer *codec_data)
1401 MEDIADEMUXER_FENTER();
1402 int ret = MD_ERROR_NONE;
1403 MEDIADEMUXER_CHECK_NULL(out_pkt);
1408 if (!gst_buffer_map(buffer, &map, GST_MAP_READ)) {
1409 MD_E("gst_buffer_map failed\n");
1410 ret = MD_ERROR_UNKNOWN;
1414 media_packet_get_buffer_size(out_pkt, &size);
1415 MD_I("Media packet Buffer capacity: %llu GST Buffer size = %d\n", size, map.size);
1416 if (size < (uint64_t)map.size) {
1417 MD_W("Media packet Buffer capacity[%llu] is \
1418 less than the GST Buffer size[%d]. Resizing...\n", size, map.size);
1419 ret = media_packet_set_buffer_size(out_pkt, (uint64_t)map.size);
1420 media_packet_get_buffer_size(out_pkt, &size);
1421 MD_I("Media packet Buffer NEW capacity: %llu \n", size);
1423 if (media_packet_get_buffer_data_ptr(out_pkt, &pkt_data)) {
1424 MD_E("unable to get the buffer pointer from media_packet_get_buffer_data_ptr\n");
1425 ret = MD_ERROR_UNKNOWN;
1428 memcpy((char *)pkt_data, map.data, map.size);
1429 if (media_packet_set_pts(out_pkt, GST_BUFFER_PTS(buffer))) {
1430 MD_E("unable to set the pts\n");
1431 ret = MD_ERROR_UNKNOWN;
1434 if (media_packet_set_dts(out_pkt, GST_BUFFER_DTS(buffer))) {
1435 MD_E("unable to set the dts\n");
1436 ret = MD_ERROR_UNKNOWN;
1439 if (media_packet_set_duration(out_pkt, GST_BUFFER_DURATION(buffer))) {
1440 MD_E("unable to set the duration\n");
1441 ret = MD_ERROR_UNKNOWN;
1444 if (media_packet_set_buffer_size(out_pkt, gst_buffer_get_size(buffer))) {
1445 MD_E("unable to set the buffer size\n");
1446 ret = MD_ERROR_UNKNOWN;
1449 if (media_packet_set_flags(out_pkt, GST_BUFFER_FLAGS(buffer))) {
1450 MD_E("unable to set the buffer size\n");
1451 ret = MD_ERROR_UNKNOWN;
1454 /* set codec data into media packet */
1456 GstMapInfo codec_data_map;
1457 if (!gst_buffer_map(codec_data, &codec_data_map, GST_MAP_READ)) {
1458 MD_E("codec data buffer map failed\n");
1459 ret = MD_ERROR_UNKNOWN;
1462 if (media_packet_set_codec_data(out_pkt, (void *)codec_data_map.data,
1463 (unsigned int)codec_data_map.size)) {
1464 MD_E("unable to set the codec data\n");
1465 ret = MD_ERROR_UNKNOWN;
1466 gst_buffer_unmap(codec_data, &codec_data_map);
1469 gst_buffer_unmap(codec_data, &codec_data_map);
1471 media_buffer_flags_e flags;
1472 media_packet_get_flags(out_pkt, &flags);
1473 media_packet_set_flags(out_pkt, flags | MEDIA_PACKET_CODEC_CONFIG);
1476 gst_buffer_unmap(buffer, &map);
1477 MEDIADEMUXER_FLEAVE();
1481 static int _gst_demuxer_create_eos_packet(media_format_h fmt, media_packet_h *outbuf)
1483 media_packet_h mediabuf = NULL;
1484 int ret = MD_ERROR_NONE;
1486 MEDIADEMUXER_FENTER();
1487 if (media_packet_create_alloc(fmt, NULL, NULL, &mediabuf)) {
1488 MD_E("media_packet_create_alloc failed\n");
1493 if (media_packet_set_flags(mediabuf, MEDIA_PACKET_END_OF_STREAM)) {
1494 MD_E("unable to set EOS flag\n");
1495 ret = MD_ERROR_UNKNOWN;
1500 MEDIADEMUXER_FLEAVE();
1505 media_packet_destroy(mediabuf);
1507 MEDIADEMUXER_FLEAVE();
1511 static int gst_demuxer_read_sample(MMHandleType pHandle,
1512 media_packet_h *outbuf, int track_indx)
1514 MEDIADEMUXER_FENTER();
1515 int ret = MD_ERROR_NONE;
1516 MEDIADEMUXER_CHECK_NULL(pHandle);
1517 mdgst_handle_t *demuxer = (mdgst_handle_t *)pHandle;
1519 media_packet_h mediabuf = NULL;
1522 track *atrack = demuxer->info.head;
1523 if ((demuxer->selected_tracks)[track_indx] == false) {
1524 MD_E("Track Not selected\n");
1529 if (indx == track_indx) /* Got the requird track details */
1532 track *next = atrack->next;
1535 MD_E("Invalid track Index\n");
1536 ret = MD_ERROR_INVALID_ARGUMENT;
1543 MD_E("atrack is NULL\n");
1547 if (indx != track_indx) {
1548 MD_E("Invalid track Index\n");
1549 ret = MD_ERROR_INVALID_ARGUMENT;
1552 GstElement *sink = atrack->appsink;
1553 GstSample *sample = NULL;
1555 sample = gst_app_sink_pull_sample((GstAppSink *) sink);
1556 if (sample == NULL) {
1557 if (gst_app_sink_is_eos((GstAppSink *) sink)) {
1558 MD_W("End of stream (EOS) reached, triggering the eos callback\n");
1559 ret = MD_ERROR_NONE;
1561 __gst_eos_callback(track_indx, demuxer);
1564 _gst_demuxer_create_eos_packet(atrack->format, outbuf);
1567 MD_E("gst_demuxer_read_sample failed\n");
1569 ret = MD_ERROR_UNKNOWN;
1574 if (media_packet_create_alloc(atrack->format, NULL, NULL, &mediabuf)) {
1575 MD_E("media_packet_create_alloc failed\n");
1580 GstBuffer *buffer = gst_sample_get_buffer(sample);
1581 if (buffer == NULL) {
1582 MD_E("gst_sample_get_buffer returned NULL pointer\n");
1583 ret = MD_ERROR_UNKNOWN;
1587 GstBuffer *codec_data_buffer = NULL;
1588 /* Need to Check : Only the first frame need set codec_data, what about Resolution changed instance ...*/
1589 if (atrack->need_codec_data) {
1590 atrack->need_codec_data = FALSE;
1591 /* Create the codec data and pass to _gst_copy_buf_to_media_packet() to add into the media packet */
1592 GstStructure *structure = NULL;
1593 const GValue *value = NULL;
1595 structure = gst_caps_get_structure(atrack->caps, 0);
1596 /* get codec data from caps*/
1597 value = gst_structure_get_value(structure, "codec_data");
1599 codec_data_buffer = gst_value_get_buffer(value);
1602 /* Fill the media_packet with proper information */
1603 ret = _gst_copy_buf_to_media_packet(mediabuf, buffer, codec_data_buffer);
1604 gst_sample_unref(sample);
1607 MEDIADEMUXER_FLEAVE();
1611 media_packet_destroy(mediabuf);
1613 MEDIADEMUXER_FLEAVE();
1617 static int gst_demuxer_seek(MMHandleType pHandle, gint64 pos1)
1619 MEDIADEMUXER_FENTER();
1620 MEDIADEMUXER_CHECK_NULL(pHandle);
1621 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1625 track_info *head_track = &(gst_handle->info);
1626 track *temp = head_track->head;
1627 track *temp_track = head_track->head;
1630 /* Setting each appsink to paused state before seek */
1631 while (temp_track) {
1632 if (gst_handle->selected_tracks[indx] == true) {
1633 if (gst_element_set_state(temp_track->appsink, GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) {
1634 MD_E("Failed to set into PAUSED state");
1637 MD_I("set the state to paused\n");
1640 if (temp_track->next) {
1641 track *next = temp_track->next;
1648 pos = pos1 * GST_MSECOND;
1650 MD_I("NEW Time: %" GST_TIME_FORMAT, GST_TIME_ARGS(pos));
1654 MD_I("Got one element %p\n", temp->appsink);
1655 if (gst_handle->selected_tracks[indx] == true) {
1656 temp->need_codec_data = TRUE;
1657 if (!gst_element_seek(temp->appsink, rate, GST_FORMAT_TIME,
1658 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_SNAP_BEFORE,
1659 GST_SEEK_TYPE_SET, pos, GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
1660 MD_E("Seek failed!\n");
1663 MD_I("Seek success...setting appsink to playing state\n");
1664 if (gst_element_set_state(temp->appsink, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
1665 MD_E("Failed to set into PLAYING state");
1672 track *next = temp->next;
1678 MEDIADEMUXER_FLEAVE();
1679 return MD_ERROR_NONE;
1681 MEDIADEMUXER_FLEAVE();
1685 int _gst_unset_appsink(track *temp, int index, int loop)
1687 MEDIADEMUXER_FENTER();
1688 int ret = MD_ERROR_NONE;
1691 while (count != index) {
1695 gst_app_sink_set_max_buffers((GstAppSink *)(temp->appsink), (guint)0);
1696 gst_app_sink_set_drop((GstAppSink *)(temp->appsink), true);
1697 MEDIADEMUXER_FLEAVE();
1701 static int gst_demuxer_unset_track(MMHandleType pHandle, int track)
1703 MEDIADEMUXER_FENTER();
1704 int ret = MD_ERROR_NONE;
1705 MEDIADEMUXER_CHECK_NULL(pHandle);
1706 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1708 if (track >= new_mediademuxer->total_tracks || track < 0) {
1709 MD_E("total tracks is less then unselected track, So not support this track");
1710 ret = MD_ERROR_INVALID_ARGUMENT;
1713 new_mediademuxer->selected_tracks[track] = false;
1714 _gst_unset_appsink((((mdgst_handle_t *)pHandle)->info).head, track,
1715 new_mediademuxer->total_tracks);
1716 MEDIADEMUXER_FLEAVE();
1719 MEDIADEMUXER_FLEAVE();
1723 static int gst_demuxer_stop(MMHandleType pHandle)
1725 MEDIADEMUXER_FENTER();
1726 int ret = MD_ERROR_NONE;
1727 MEDIADEMUXER_CHECK_NULL(pHandle);
1728 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1730 MD_I("gst_demuxer_stop pipeine %p", gst_handle);
1731 if (gst_element_set_state(gst_handle->pipeline, GST_STATE_PAUSED) ==
1732 GST_STATE_CHANGE_FAILURE) {
1733 MD_E("Failed to set into PAUSE state");
1734 ret = MD_INTERNAL_ERROR;
1737 MEDIADEMUXER_FLEAVE();
1740 MEDIADEMUXER_FLEAVE();
1744 void _gst_clear_struct(mdgst_handle_t *gst_handle)
1746 MEDIADEMUXER_FENTER();
1747 if (gst_handle->selected_tracks) {
1748 MD_I("Deallocating gst_handle->selected_tracks %p\n",
1749 gst_handle->selected_tracks);
1750 g_free(gst_handle->selected_tracks);
1751 gst_handle->selected_tracks = NULL;
1753 if ((gst_handle->info).head)
1754 __gst_free_stuct(&(gst_handle->info).head);
1755 MEDIADEMUXER_FLEAVE();
1758 int _md_gst_destroy_pipeline(GstElement *pipeline)
1760 MEDIADEMUXER_FENTER();
1761 int ret = MD_ERROR_NONE;
1763 MEDIADEMUXER_SET_STATE(pipeline, GST_STATE_NULL, ERROR);
1765 gst_object_unref(GST_OBJECT(pipeline));
1766 MEDIADEMUXER_FLEAVE();
1770 gst_object_unref(GST_OBJECT(pipeline));
1771 MEDIADEMUXER_FLEAVE();
1775 static int gst_demuxer_unprepare(MMHandleType pHandle)
1777 MEDIADEMUXER_FENTER();
1778 int ret = MD_ERROR_NONE;
1779 MEDIADEMUXER_CHECK_NULL(pHandle);
1780 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1782 _gst_clear_struct(gst_handle);
1783 if (gst_handle->bus_watch_id) {
1784 GSource *source = NULL;
1785 source = g_main_context_find_source_by_id(gst_handle->thread_default, gst_handle->bus_watch_id);
1787 g_source_destroy(source);
1788 LOGD("Deallocation bus watch id");
1792 MD_I("gst_demuxer_stop pipeine %p\n", gst_handle->pipeline);
1793 if (_md_gst_destroy_pipeline(gst_handle->pipeline) != MD_ERROR_NONE) {
1797 MEDIADEMUXER_FLEAVE();
1800 MEDIADEMUXER_FLEAVE();
1804 static int gst_demuxer_destroy(MMHandleType pHandle)
1806 MEDIADEMUXER_FENTER();
1807 int ret = MD_ERROR_NONE;
1808 MEDIADEMUXER_CHECK_NULL(pHandle);
1809 mdgst_handle_t *new_mediademuxer = (mdgst_handle_t *)pHandle;
1811 MD_I("gst_demuxer_destroy deallocating new_mediademuxer:%p\n",
1813 g_free(new_mediademuxer);
1814 MEDIADEMUXER_FLEAVE();
1818 int gst_set_error_cb(MMHandleType pHandle,
1819 gst_error_cb callback, void *user_data)
1821 MEDIADEMUXER_FENTER();
1822 int ret = MD_ERROR_NONE;
1823 MEDIADEMUXER_CHECK_NULL(pHandle);
1824 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1826 if (gst_handle->user_cb[_GST_EVENT_TYPE_ERROR]) {
1827 MD_E("Already set mediademuxer_error_cb\n");
1828 ret = MD_ERROR_INVALID_ARGUMENT;
1832 MD_E("fail invaild argument (callback)\n");
1833 ret = MD_ERROR_INVALID_ARGUMENT;
1838 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1840 gst_handle->user_cb[_GST_EVENT_TYPE_ERROR] = (gst_error_cb)callback;
1841 gst_handle->user_data[_GST_EVENT_TYPE_ERROR] = user_data;
1842 MEDIADEMUXER_FLEAVE();
1843 return MD_ERROR_NONE;
1845 MEDIADEMUXER_FLEAVE();
1849 int gst_set_eos_cb(MMHandleType pHandle, gst_eos_cb callback, void *user_data)
1851 MEDIADEMUXER_FENTER();
1852 int ret = MD_ERROR_NONE;
1853 MEDIADEMUXER_CHECK_NULL(pHandle);
1854 mdgst_handle_t *gst_handle = (mdgst_handle_t *)pHandle;
1856 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS]) {
1857 MD_E("Already set mediademuxer_eos_cb\n");
1858 ret = MD_ERROR_INVALID_ARGUMENT;
1862 MD_E("fail invaild argument (callback)\n");
1863 ret = MD_ERROR_INVALID_ARGUMENT;
1868 MD_I("Set event handler callback(cb = %p, data = %p)\n", callback, user_data);
1869 gst_handle->user_cb[_GST_EVENT_TYPE_EOS] = (gst_eos_cb)callback;
1870 gst_handle->user_data[_GST_EVENT_TYPE_EOS] = user_data;
1871 MEDIADEMUXER_FLEAVE();
1872 return MD_ERROR_NONE;
1874 MEDIADEMUXER_FLEAVE();
1878 static int __gst_eos_callback(int track_num, void* user_data)
1880 if (user_data == NULL) {
1881 MD_E("Invalid argument");
1884 mdgst_handle_t *gst_handle = (mdgst_handle_t *)user_data;
1885 if (gst_handle->user_cb[_GST_EVENT_TYPE_EOS])
1886 ((gst_eos_cb)gst_handle->user_cb[_GST_EVENT_TYPE_EOS])(track_num,
1887 gst_handle->user_data[_GST_EVENT_TYPE_EOS]);
1889 MD_E("EOS received, but callback is not set!!!");
1890 return MD_ERROR_NONE;