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 #include "media_streamer_gst.h"
19 #include "media_streamer_node.h"
21 #define MS_PADS_UNLINK(pad, peer) GST_PAD_IS_SRC(pad) ? \
22 gst_pad_unlink(pad, peer) : \
23 gst_pad_unlink(peer, pad)
24 #define H264_PARSER_CONFIG_INTERVAL 5
25 #define H264_ENCODER_ZEROLATENCY 0x00000004
27 #define MEDIASTREAMER_DECODEBIN_TYPE_DECODER "video_decoder"
30 MEDIA_STREAMER_SINK_BIN_NORMAL,
31 MEDIA_STREAMER_SINK_BIN_RTP_SERVER,
32 MEDIA_STREAMER_SINK_BIN_ADAPTIVE,
33 } media_streamer_sink_bin_type_e;
35 static int __ms_adaptive_sink_prepare(media_streamer_s *ms_streamer);
37 void ms_generate_dots(GstElement *bin, gchar *name_tag)
40 ms_retm_if(bin == NULL, "bin is NULL");
43 dot_name = g_strdup(DOT_FILE_NAME);
45 dot_name = g_strconcat(DOT_FILE_NAME, ".", name_tag, NULL);
47 GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS(GST_BIN(bin), GST_DEBUG_GRAPH_SHOW_ALL, dot_name);
49 MS_SAFE_GFREE(dot_name);
52 static int __ms_add_no_target_ghostpad(GstElement *gst_bin, const char *ghost_pad_name, GstPadDirection pad_direction)
54 int ret = MEDIA_STREAMER_ERROR_NONE;
55 gchar *bin_name = NULL;
56 GstPad *ghost_pad = NULL;
60 ms_retvm_if(gst_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_bin is NULL");
62 bin_name = gst_element_get_name(gst_bin);
63 ghost_pad = gst_ghost_pad_new_no_target(ghost_pad_name, pad_direction);
64 if (gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad)) {
65 gst_pad_set_active(ghost_pad, TRUE);
66 ms_info("Added [%s] empty ghostpad into [%s]", ghost_pad_name, bin_name);
68 ms_info("Error: Failed to add empty [%s] ghostpad into [%s]", ghost_pad_name, bin_name);
69 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
72 MS_SAFE_GFREE(bin_name);
79 static gboolean __ms_add_ghostpad(GstElement *gst_element, const char *pad_name, GstElement *gst_bin, const char *ghost_pad_name)
82 GstPad *ghost_pad = NULL;
83 GstPad *element_pad = NULL;
87 ms_retvm_if(!gst_element, FALSE, "gst_element is NULL");
88 ms_retvm_if(!pad_name, FALSE, "pad_name is NULL");
89 ms_retvm_if(!gst_bin, FALSE, "gst_bin is NULL");
91 element_pad = gst_element_get_static_pad(gst_element, pad_name);
93 /* Check, if pad is not static, get it by request */
94 if (element_pad == NULL)
95 element_pad = gst_element_get_request_pad(gst_element, pad_name);
97 ghost_pad = gst_ghost_pad_new(ghost_pad_name, element_pad);
98 ms_retvm_if(!ghost_pad, FALSE, "ghost_pad is NULL");
100 gst_pad_set_active(ghost_pad, TRUE);
102 ret = gst_element_add_pad(GST_ELEMENT(gst_bin), ghost_pad);
105 ms_info("Added %s ghostpad from [%s] into [%s]", pad_name, GST_ELEMENT_NAME(gst_element), GST_ELEMENT_NAME(gst_bin));
107 ms_error("Error: element [%s] does not have valid [%s] pad for adding into [%s] bin", GST_ELEMENT_NAME(gst_element), pad_name, GST_ELEMENT_NAME(gst_bin));
109 MS_SAFE_UNREF(element_pad);
116 /* This unlinks from its peer and ghostpads on its way */
117 static gboolean __ms_pad_peer_unlink(GstPad *pad)
120 GstPad *peer_pad = NULL;
124 ms_retvm_if(!pad, FALSE, "pad is NULL");
126 if (!gst_pad_is_linked(pad))
129 peer_pad = gst_pad_get_peer(pad);
130 ms_retvm_if(!peer_pad, FALSE, "Fail to get peer pad");
132 if (GST_IS_PROXY_PAD(peer_pad)) {
134 GstObject *ghost_object = gst_pad_get_parent(peer_pad);
135 if (GST_IS_GHOST_PAD(ghost_object)) {
136 GstPad *ghost_pad = GST_PAD(ghost_object);
137 GstPad *target_pad = gst_pad_get_peer(ghost_pad);
139 if (target_pad && GST_IS_GHOST_PAD(target_pad))
140 ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(target_pad)), target_pad);
142 /* This is a usual static pad */
144 ret = ret && MS_PADS_UNLINK(ghost_pad, target_pad);
146 ms_info("Ghost Pad [%s] does not have target.", GST_PAD_NAME(ghost_pad));
148 ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(ghost_pad)), ghost_pad);
150 MS_SAFE_UNREF(target_pad);
151 MS_SAFE_UNREF(ghost_pad);
153 MS_SAFE_UNREF(ghost_object);
155 } else if (GST_IS_GHOST_PAD(peer_pad)) {
156 ret = ret && gst_element_remove_pad(GST_ELEMENT(GST_PAD_PARENT(peer_pad)), peer_pad);
158 /* This is a usual static pad */
159 ret = ret && MS_PADS_UNLINK(pad, peer_pad);
162 MS_SAFE_UNREF(peer_pad);
169 static GstElement *__ms_pad_get_peer_element(GstPad *pad)
171 GstPad *peer_pad = NULL;
172 GstElement *ret = NULL;
176 ms_retvm_if(!pad, NULL, "pad is NULL");
178 if (!gst_pad_is_linked(pad)) {
179 ms_info("Pad [%s:%s] is not linked yet", GST_DEBUG_PAD_NAME(pad));
183 peer_pad = gst_pad_get_peer(pad);
184 ms_retvm_if(!peer_pad, NULL, "Fail to get peer pad");
186 ret = gst_pad_get_parent_element(peer_pad);
188 if (GST_IS_PROXY_PAD(peer_pad)) {
189 GstPad *ghost_pad = GST_PAD(gst_pad_get_parent(peer_pad));
190 GstPad *target_pad = gst_pad_get_peer(ghost_pad);
191 if (GST_GHOST_PAD(target_pad)) {
192 GstPad *element_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(target_pad));
193 ret = gst_pad_get_parent_element(element_pad);
194 MS_SAFE_UNREF(element_pad);
196 /* This is a usual static pad */
197 ret = gst_pad_get_parent_element(target_pad);
200 MS_SAFE_UNREF(target_pad);
201 MS_SAFE_UNREF(ghost_pad);
202 } else if (GST_IS_GHOST_PAD(peer_pad)) {
203 GstPad *element_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(peer_pad));
204 ret = gst_pad_get_parent_element(element_pad);
205 MS_SAFE_UNREF(element_pad);
207 /* This is a usual static pad */
208 ret = gst_pad_get_parent_element(peer_pad);
211 MS_SAFE_UNREF(peer_pad);
218 gboolean ms_element_unlink(GstElement *element)
222 GValue elem = G_VALUE_INIT;
223 GstIterator *pad_iterator = NULL;
227 ms_retvm_if(!element, FALSE, "element is NULL");
229 pad_iterator = gst_element_iterate_pads(element);
230 while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &elem)) {
231 pad = (GstPad *) g_value_get_object(&elem);
232 ret = ret && __ms_pad_peer_unlink(pad);
233 g_value_reset(&elem);
235 g_value_unset(&elem);
236 gst_iterator_free(pad_iterator);
243 gboolean ms_bin_remove_element(GstElement *element)
245 GstElement *parent = NULL;
246 gboolean ret = FALSE;
250 ms_retvm_if(!element, FALSE, "element is NULL");
252 parent = (GstElement *) gst_element_get_parent(element);
254 /* Remove node's element from bin that decreases ref count */
255 if (parent != NULL) {
256 ret = gst_bin_remove(GST_BIN(parent), element);
258 ms_debug("Element [%s] removed from [%s] bin", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(parent));
261 MS_SAFE_UNREF(parent);
268 gboolean ms_bin_add_element(GstElement *bin, GstElement *element, gboolean do_ref)
270 GstElement *parent = NULL;
271 gboolean ret = FALSE;
275 ms_retvm_if(!bin, FALSE, "bin is NULL");
276 ms_retvm_if(!element, FALSE, "element is NULL");
278 parent = (GstElement *) gst_element_get_parent(element);
280 /* Add node's element into bin and increases ref count if needed */
281 if (parent == NULL) {
282 ret = gst_bin_add(GST_BIN(bin), element);
284 ms_debug("Element [%s] added into [%s] bin", GST_ELEMENT_NAME(element), GST_ELEMENT_NAME(bin));
285 gst_object_ref(element);
289 MS_SAFE_UNREF(parent);
296 const gchar *ms_get_pad_type(GstPad *element_pad)
298 const gchar *pad_type = NULL;
299 GstCaps *pad_caps = NULL;
303 ms_retvm_if(!element_pad, NULL, "element_pad is NULL");
305 pad_caps = gst_pad_query_caps(element_pad, 0);
306 MS_GET_CAPS_TYPE(pad_caps, pad_type);
307 gst_caps_unref(pad_caps);
314 static GstElement *__ms_find_peer_element_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, node_info_s *node_klass_type)
316 GstElement *peer_element = NULL;
317 GstIterator *src_pad_iterator = NULL;
318 GValue src_pad_value = G_VALUE_INIT;
319 const gchar *found_klass = NULL;
323 ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
324 ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
325 ms_retvm_if(!node_klass_type->klass_name, NULL, "node_klass_type->klass_name is NULL");
326 ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
328 if (prev_elem_src_pad) {
330 /* Check if previous element`s source pad is connected with element */
331 peer_element = __ms_pad_get_peer_element(prev_elem_src_pad);
333 found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element));
334 if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name))
335 ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element));
337 MS_SAFE_UNREF(peer_element);
341 /* Check if any of previous element`s source pads is connected with element */
342 src_pad_iterator = gst_element_iterate_src_pads(previous_element);
343 while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) {
344 GstPad *src_pad = (GstPad *) g_value_get_object(&src_pad_value);
345 peer_element = __ms_pad_get_peer_element(src_pad);
347 found_klass = gst_element_factory_get_klass(gst_element_get_factory(peer_element));
348 if (g_strrstr(found_klass, node_klass_type->klass_name) || g_strrstr(GST_ELEMENT_NAME(peer_element), node_klass_type->default_name)) {
349 ms_info(" Found peer element [%s] ", GST_ELEMENT_NAME(peer_element));
350 g_value_reset(&src_pad_value);
353 MS_SAFE_UNREF(peer_element);
355 g_value_reset(&src_pad_value);
357 g_value_unset(&src_pad_value);
358 gst_iterator_free(src_pad_iterator);
362 ms_info(" Element [%s] is not connected", GST_ELEMENT_NAME(previous_element));
369 static gboolean __ms_link_two_elements(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *found_element)
371 GValue src_pad_value = G_VALUE_INIT;
372 gboolean elements_linked = FALSE;
373 GstPad * found_sink_pad = NULL;
374 GstElement *peer_element = NULL;
375 GstIterator *src_pad_iterator = NULL;
376 GstPad *src_pad = NULL;
380 ms_retvm_if(!previous_element, FALSE, "previous_element is NULL");
381 ms_retvm_if(!found_element, FALSE, "found_element is NULL");
383 if (prev_elem_src_pad) {
384 peer_element = __ms_pad_get_peer_element(prev_elem_src_pad);
385 if (!gst_pad_is_linked(prev_elem_src_pad)) {
387 /* Check compatibility of previous element and unlinked found element */
388 found_sink_pad = gst_element_get_compatible_pad(found_element, prev_elem_src_pad, NULL);
390 elements_linked = gst_element_link_pads(previous_element, GST_PAD_NAME(prev_elem_src_pad), found_element, GST_PAD_NAME(found_sink_pad));
391 } else if (peer_element == found_element) {
392 elements_linked = TRUE;
394 MS_SAFE_UNREF(peer_element);
397 /* Check if previous element has any unlinked src pad */
398 src_pad_iterator = gst_element_iterate_src_pads(previous_element);
399 while (GST_ITERATOR_OK == gst_iterator_next(src_pad_iterator, &src_pad_value)) {
400 src_pad = (GstPad *) g_value_get_object(&src_pad_value);
401 GstElement *peer_element = __ms_pad_get_peer_element(src_pad);
402 if (!gst_pad_is_linked(src_pad)) {
404 /* Check compatibility of previous element and unlinked found element */
405 found_sink_pad = gst_element_get_compatible_pad(found_element, src_pad, NULL);
406 if (found_sink_pad) {
407 elements_linked = gst_element_link_pads(previous_element, GST_PAD_NAME(src_pad), found_element, GST_PAD_NAME(found_sink_pad));
408 if (elements_linked) {
409 g_value_reset(&src_pad_value);
410 MS_SAFE_UNREF(peer_element);
414 } else if (peer_element == found_element) {
415 elements_linked = TRUE;
417 MS_SAFE_UNREF(peer_element);
418 g_value_reset(&src_pad_value);
420 g_value_unset(&src_pad_value);
421 gst_iterator_free(src_pad_iterator);
424 if (found_sink_pad) {
426 ms_info("Succeeded to link [%s] -> [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element));
428 ms_debug("Failed to link [%s] and [%s]", GST_ELEMENT_NAME(previous_element), GST_ELEMENT_NAME(found_element));
430 ms_info("Element [%s] has no free compatible pad to be connected with [%s] or linked", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(previous_element));
432 MS_SAFE_UNREF(found_sink_pad);
436 return elements_linked;
439 static GstElement *__ms_bin_find_element_and_link_by_type(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *search_bin, node_info_s *node_klass_type)
441 GValue element_value = G_VALUE_INIT;
442 GstElement *found_element = NULL;
443 gboolean elements_linked = FALSE;
444 const gchar *found_klass = NULL;
445 GstIterator *bin_iterator = NULL;
449 ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
450 ms_retvm_if(!search_bin, NULL, "search_bin is NULL");
451 ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
452 ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
454 bin_iterator = gst_bin_iterate_sorted(GST_BIN(search_bin));
456 while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &element_value)) {
457 found_element = (GstElement *) g_value_get_object(&element_value);
458 found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
460 /* Check if found element is of appropriate needed plugin class */
461 if (g_strrstr(found_klass, node_klass_type->klass_name) ||
462 g_strrstr(GST_ELEMENT_NAME(found_element), node_klass_type->default_name)) {
463 ms_info("Found element by type [%s]", GST_ELEMENT_NAME(found_element));
464 if (__ms_link_two_elements(previous_element, prev_elem_src_pad, found_element)) {
465 elements_linked = TRUE;
466 g_value_reset(&element_value);
467 g_object_ref(found_element);
471 g_value_reset(&element_value);
474 g_value_unset(&element_value);
475 gst_iterator_free(bin_iterator);
479 return elements_linked ? found_element : NULL;
482 GstElement *ms_find_element_in_bin_by_type(GstElement *bin, node_info_s *node_klass_type)
484 GValue element_value = G_VALUE_INIT;
485 GstElement *found_element = NULL;
486 GstElement *next_element = NULL;
487 const gchar *found_klass = NULL;
488 GstIterator *bin_iterator = NULL;
492 ms_retvm_if(!bin, NULL, "bin is NULL");
493 ms_retvm_if(!node_klass_type, NULL, "node_klass_type is NULL");
494 ms_retvm_if(!node_klass_type->default_name, NULL, "node_klass_type->default_name is NULL");
496 bin_iterator = gst_bin_iterate_sorted(GST_BIN(bin));
498 while (GST_ITERATOR_OK == gst_iterator_next(bin_iterator, &element_value)) {
499 next_element = (GstElement *) g_value_get_object(&element_value);
500 found_klass = gst_element_factory_get_klass(gst_element_get_factory(found_element));
502 /* Check if found element is of appropriate needed plugin class */
503 if (g_strrstr(found_klass, node_klass_type->klass_name) ||
504 g_strrstr(GST_ELEMENT_NAME(next_element), node_klass_type->default_name)) {
505 ms_info("Found element by type [%s]", GST_ELEMENT_NAME(next_element));
506 found_element = next_element;
510 g_value_reset(&element_value);
513 gst_iterator_free(bin_iterator);
517 return found_element;
520 static int __ms_factory_rank_compare(GstPluginFeature *first_feature, GstPluginFeature *second_feature)
523 guint first_rank = 0, second_rank = 0;
525 first_rank = gst_plugin_feature_get_rank(first_feature);
526 second_rank = gst_plugin_feature_get_rank(second_feature);
527 ms_debug("second[%s]_rank(%d) - first[%s]_rank(%d) = (%d)",
528 GST_OBJECT_NAME(GST_ELEMENT_FACTORY(second_feature)), second_rank,
529 GST_OBJECT_NAME(GST_ELEMENT_FACTORY(first_feature)), first_rank, second_rank - first_rank);
532 return second_rank - first_rank;
535 GstElement *ms_combine_next_element(GstElement *previous_element, GstPad *prev_elem_src_pad, GstElement *bin_to_find_in, media_streamer_node_type_e node_type)
537 GstCaps *prev_caps = NULL;
538 GstElement *found_element = NULL;
539 node_info_s *node_klass_type = NULL;
541 ms_retvm_if(!previous_element, NULL, "previous_element is NULL");
542 ms_retvm_if(!bin_to_find_in, NULL, "bin_to_find_in is NULL");
546 node_klass_type = ms_node_get_klass_by_its_type(node_type);
548 /* - 1 - If previous element is linked - check for peer element */
549 found_element = __ms_find_peer_element_by_type(GST_ELEMENT(previous_element), prev_elem_src_pad, node_klass_type);
551 /* - 2 - If previous element is not linked - find in bin by type */
553 found_element = __ms_bin_find_element_and_link_by_type(previous_element, prev_elem_src_pad, bin_to_find_in, node_klass_type);
555 /* - 3 - If element by type is not found in bin - create element by type */
556 if (!found_element) {
558 /* Create Node type information for a New element */
559 if (prev_elem_src_pad)
560 prev_caps = gst_pad_query_caps(prev_elem_src_pad, 0);
562 GstPad *src_pad = gst_element_get_static_pad(previous_element, "src");
564 prev_caps = gst_pad_query_caps(src_pad, 0);
565 MS_SAFE_UNREF(src_pad);
567 node_plug_s plug_info = {node_klass_type, NULL, prev_caps, NULL};
569 /* Create Node by ini or registry */
570 found_element = ms_node_element_create(&plug_info, node_type);
572 ms_info("New Element [%s] is created ", GST_ELEMENT_NAME(found_element));
574 /* Add created element */
575 if (ms_bin_add_element(bin_to_find_in, found_element, TRUE)) {
576 gst_element_sync_state_with_parent(found_element);
577 __ms_link_two_elements(previous_element, prev_elem_src_pad, found_element);
578 ms_generate_dots(bin_to_find_in, GST_ELEMENT_NAME(found_element));
580 ms_error("Element [%s] was not added into [%s] bin", GST_ELEMENT_NAME(found_element), GST_ELEMENT_NAME(bin_to_find_in));
581 MS_SAFE_UNREF(found_element);
584 ms_info("New Element is not created ");
586 ms_info("Next element is not combined");
588 MS_SAFE_UNREF(previous_element);
592 return found_element;
595 static gint __decodebin_autoplug_select_cb(GstElement *bin, GstPad *pad, GstCaps *caps, GstElementFactory *factory, gpointer data)
597 /* NOTE : GstAutoplugSelectResult is defined in gstplay-enum.h but not exposed */
599 GST_AUTOPLUG_SELECT_TRY,
600 GST_AUTOPLUG_SELECT_EXPOSE,
601 GST_AUTOPLUG_SELECT_SKIP
602 } GstAutoplugSelectResult;
605 gchar *factory_name = NULL;
606 const gchar *klass = NULL;
607 GstAutoplugSelectResult result = GST_AUTOPLUG_SELECT_TRY;
608 media_streamer_s *ms_streamer = (media_streamer_s *) data;
612 ms_retvm_if(!factory, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "factory is NULL");
613 ms_retvm_if(!ms_streamer, GST_AUTOPLUG_SELECT_TRY, "data is NULL");
615 factory_name = GST_OBJECT_NAME(factory);
616 klass = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS);
618 ms_debug("Decodebin: found new element [%s] to link [%s]", factory_name, klass);
620 if (ms_streamer->ini.exclude_elem_names) {
621 /* Search if such plugin must be excluded */
622 for (index = 0; ms_streamer->ini.exclude_elem_names[index]; ++index) {
623 if (g_strrstr(factory_name, ms_streamer->ini.exclude_elem_names[index])) {
624 ms_debug("Decodebin: skipping [%s] as excluded", factory_name);
627 return GST_AUTOPLUG_SELECT_SKIP;
633 if (ms_streamer->ini.resource_required_elem_names) {
634 /* Try to acquire resources before adding element */
635 for (index = 0; ms_streamer->ini.resource_required_elem_names[index]; ++index) {
636 if (g_strrstr(factory_name, ms_streamer->ini.resource_required_elem_names[index])) {
637 ms_debug("Decodebin: trying to acquire resource for [%s] element", factory_name);
639 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
640 mm_resource_manager_mark_for_acquire(ms_streamer->resource_manager,
641 MM_RESOURCE_MANAGER_RES_TYPE_VIDEO_DECODER,
642 MM_RESOURCE_MANAGER_RES_VOLUME_FULL,
643 &ms_streamer->video_decoder_resource)) {
644 ms_error("Failed to mark resources for acquire in [%s] element", factory_name);
645 return GST_AUTOPLUG_SELECT_SKIP;
648 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
649 mm_resource_manager_commit(ms_streamer->resource_manager)) {
650 ms_error("Failed to acquire resources for [%s] element", factory_name);
652 if (MM_RESOURCE_MANAGER_ERROR_NONE !=
653 mm_resource_manager_mark_for_release(
654 ms_streamer->resource_manager,
655 ms_streamer->video_decoder_resource))
656 ms_error("Failed to mark resources for release in [%s] element", factory_name);
658 return GST_AUTOPLUG_SELECT_SKIP;
669 static gint __pad_type_compare(gconstpointer a, gconstpointer b)
671 GstPad *a_pad = NULL;
672 GstPad *b_pad = NULL;
673 const gchar *a_pad_type = NULL;
674 const gchar *b_pad_type = NULL;
678 ms_retvm_if(!a, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "a is NULL");
679 ms_retvm_if(!b, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "b is NULL");
684 a_pad_type = ms_get_pad_type(a_pad);
685 b_pad_type = ms_get_pad_type(b_pad);
689 if (MS_ELEMENT_IS_TEXT(a_pad_type))
691 else if (MS_ELEMENT_IS_TEXT(b_pad_type))
697 static void __decodebin_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
699 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
703 ms_retm_if(new_pad == NULL, "new_pad is NULL");
704 ms_retm_if(ms_streamer == NULL, "user_data is NULL");
706 g_mutex_lock(&ms_streamer->mutex_lock);
708 g_object_ref(new_pad);
710 ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare);
712 g_mutex_unlock(&ms_streamer->mutex_lock);
717 static void __decodebin_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer, media_streamer_sink_bin_type_e sink_bin_type)
719 GstElement *found_element = NULL;
720 const gchar *new_pad_type = NULL;
721 GstCaps *caps = NULL;
722 gchar *caps_str = NULL;
726 ms_retm_if(src_pad == NULL, "src_pad is NULL");
727 ms_retm_if(ms_streamer == NULL, "ms_streamer is NULL");
729 found_element = gst_pad_get_parent_element(src_pad);
730 new_pad_type = ms_get_pad_type(src_pad);
732 if (MS_ELEMENT_IS_VIDEO(new_pad_type)) {
733 if (__ms_bin_find_element_and_link_by_type(found_element, src_pad, ms_streamer->transform_bin,
734 ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY))) {
735 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
738 if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
739 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
740 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
741 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
742 } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
743 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
744 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
745 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
747 caps = gst_pad_query_caps(src_pad, NULL);
748 caps_str = gst_caps_to_string(caps);
749 if (caps_str && (g_strrstr(caps_str, "ST12") || g_strrstr(caps_str, "SN12") ||
750 g_strrstr(caps_str, "SN21") || g_strrstr(caps_str, "S420") || g_strrstr(caps_str, "SR32"))) {
751 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
753 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER);
754 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
756 MS_SAFE_GFREE(caps_str);
757 gst_caps_unref(caps);
759 } else if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
760 if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_RTP_SERVER) {
761 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
762 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
763 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
764 } else if (sink_bin_type == MEDIA_STREAMER_SINK_BIN_ADAPTIVE) {
765 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
766 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_MUXER);
767 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
769 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER);
770 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
772 } else if (MS_ELEMENT_IS_TEXT(new_pad_type)) {
773 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
775 ms_error("Unsupported pad type [%s]!", new_pad_type);
778 ms_generate_dots(ms_streamer->pipeline, "after_sink_linked");
779 gst_object_unref(found_element);
784 static void __decodebin_nomore_pads_cb(GstElement *decodebin, gpointer user_data)
786 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
787 media_streamer_sink_bin_type_e sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
788 media_streamer_node_s *rtp_node = NULL;
789 media_streamer_node_s *adaptive_sink = NULL;
790 char *decodebin_name = NULL;
791 char *param_value = NULL;
792 GList *iterator = NULL;
794 GstPad *src_pad = NULL;
798 ms_retm_if(decodebin == NULL, "decodebin is NULL");
799 ms_retm_if(ms_streamer == NULL, "user_data is NULL");
801 g_mutex_lock(&ms_streamer->mutex_lock);
803 rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
804 adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
807 g_object_get(G_OBJECT(decodebin), "name", &decodebin_name, NULL);
809 /* FIXME: This case may be not general */
810 if (g_strrstr(decodebin_name, MEDIASTREAMER_DECODEBIN_TYPE_DECODER)) {
811 sink_bin_type = MEDIA_STREAMER_SINK_BIN_NORMAL;
812 MS_SAFE_FREE(decodebin_name);
814 /* It`s server part of Streaming Scenario*/
815 media_streamer_node_get_param(rtp_node, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, ¶m_value);
816 if (param_value && (strtol(param_value, NULL, 10) > 0))
817 sink_bin_type = MEDIA_STREAMER_SINK_BIN_RTP_SERVER;
819 MS_SAFE_FREE(param_value);
821 } else if (adaptive_sink) {
822 __ms_adaptive_sink_prepare(ms_streamer);
823 sink_bin_type = MEDIA_STREAMER_SINK_BIN_ADAPTIVE;
827 list = ms_streamer->pads_types_list;
828 for (iterator = list; iterator; iterator = iterator->next) {
829 src_pad = GST_PAD(iterator->data);
830 __decodebin_nomore_pads_combine(src_pad, ms_streamer, sink_bin_type);
833 g_mutex_unlock(&ms_streamer->mutex_lock);
838 static GstElement *__ms_decodebin_create(media_streamer_s *ms_streamer, char *name)
840 GstElement *decodebin = NULL;
844 ms_retvm_if(!ms_streamer, NULL, "ms_streamer is NULL");
846 decodebin = ms_element_create(DEFAULT_DECODEBIN, name);
847 ms_bin_add_element(ms_streamer->transform_bin, decodebin, TRUE);
848 gst_element_sync_state_with_parent(decodebin);
850 ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "pad-added", G_CALLBACK(__decodebin_pad_added_cb), ms_streamer);
851 ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "autoplug-select", G_CALLBACK(__decodebin_autoplug_select_cb), ms_streamer);
852 ms_signal_create(&ms_streamer->autoplug_sig_list, decodebin, "no-more-pads", G_CALLBACK(__decodebin_nomore_pads_cb), ms_streamer);
860 static gboolean __ms_sink_bin_prepare(media_streamer_s *ms_streamer, GstPad *src_pad, const gchar *src_pad_type)
862 GstElement *decoder_element = NULL;
863 GstElement *found_element = NULL;
864 GstElement *parent_rtp_element = NULL;
868 ms_retvm_if(!ms_streamer, FALSE, "ms_streamer is NULL");
869 ms_retvm_if(!src_pad, FALSE, "src_pad is NULL");
871 /* Getting Depayloader */
872 parent_rtp_element = gst_pad_get_parent_element(src_pad);
874 if (MS_ELEMENT_IS_VIDEO(src_pad_type)) {
875 gst_object_ref(parent_rtp_element);
876 found_element = ms_combine_next_element(parent_rtp_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY);
877 decoder_element = __ms_bin_find_element_and_link_by_type(found_element, NULL, ms_streamer->transform_bin,
878 ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER));
880 if (!decoder_element) {
881 if (ms_streamer->ini.use_decodebin) {
882 decoder_element = __ms_decodebin_create(ms_streamer, MEDIASTREAMER_DECODEBIN_TYPE_DECODER);
883 gst_object_ref(found_element);
884 __ms_link_two_elements(found_element, NULL, decoder_element);
885 MS_SAFE_UNREF(decoder_element);
891 gst_object_ref(found_element);
892 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
893 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
896 __ms_link_two_elements(found_element, NULL, decoder_element);
897 found_element = ms_combine_next_element(decoder_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
899 } else if (MS_ELEMENT_IS_AUDIO(src_pad_type)) {
900 gst_object_ref(parent_rtp_element);
901 found_element = ms_combine_next_element(parent_rtp_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY);
902 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
903 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->sink_bin, MEDIA_STREAMER_NODE_TYPE_SINK);
905 ms_info("Unknown media type received from rtp element!");
907 MS_SAFE_UNREF(found_element);
908 MS_SAFE_UNREF(parent_rtp_element);
915 void ms_rtpbin_pad_added_cb(GstElement *src, GstPad *new_pad, gpointer user_data)
917 media_streamer_s *ms_streamer = NULL;
918 GstPad *target_pad = NULL;
919 GstCaps *src_pad_caps = NULL;
920 gchar *src_pad_name = NULL;
921 GstStructure *src_pad_struct = NULL;
922 const gchar *src_pad_type = NULL;
923 GstPad *src_pad = NULL;
924 media_streamer_node_s *ms_node = (media_streamer_node_s *) user_data;
928 ms_retm_if(new_pad == NULL, "new_pad is NULL");
929 ms_retm_if(ms_node == NULL, "ms_node is NULL");
930 ms_debug("Pad [%s] added on [%s]", GST_PAD_NAME(new_pad), GST_ELEMENT_NAME(src));
932 if (g_str_has_prefix(GST_PAD_NAME(new_pad), "recv_rtp_src")) {
933 ms_streamer = ms_node->parent_streamer;
934 ms_retm_if(ms_streamer == NULL, "Node's parent streamer handle is NULL");
935 g_mutex_lock(&ms_streamer->mutex_lock);
937 target_pad = gst_ghost_pad_get_target(GST_GHOST_PAD(new_pad));
938 src_pad_caps = gst_pad_query_caps(target_pad, NULL);
939 src_pad_struct = gst_caps_get_structure(src_pad_caps, 0);
940 src_pad_type = gst_structure_get_string(src_pad_struct, "media");
941 ms_debug("type is [%s]", src_pad_type);
943 if (MS_ELEMENT_IS_VIDEO(src_pad_type))
944 src_pad_name = g_strdup_printf("%s_out", "video");
945 else if (MS_ELEMENT_IS_AUDIO(src_pad_type))
946 src_pad_name = g_strdup_printf("%s_out", "audio");
948 if (src_pad_name != NULL) {
950 src_pad = gst_element_get_static_pad(ms_node->gst_element, src_pad_name);
953 gst_ghost_pad_set_target(GST_GHOST_PAD(src_pad), new_pad);
955 if (src_pad && __ms_sink_bin_prepare(ms_streamer, src_pad, src_pad_type)) {
956 ms_element_set_state(ms_node->gst_element, GST_STATE_PLAYING);
957 ms_generate_dots(ms_streamer->pipeline, "rtpbin_playing");
959 ms_error("Failed to prepare sink_bin for pad type [%s]", src_pad_type);
962 MS_SAFE_GFREE(src_pad_name);
964 g_mutex_unlock(&ms_node->parent_streamer->mutex_lock);
966 gst_caps_unref(src_pad_caps);
967 MS_SAFE_UNREF(target_pad);
974 void ms_demux_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
976 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
980 ms_retm_if(ms_streamer == NULL, "user_data is NULL");
981 ms_retm_if(new_pad == NULL, "new_pad is NULL");
983 g_mutex_lock(&ms_streamer->mutex_lock);
985 g_object_ref(new_pad);
987 ms_streamer->pads_types_list = g_list_insert_sorted(ms_streamer->pads_types_list, new_pad, __pad_type_compare);
989 g_mutex_unlock(&ms_streamer->mutex_lock);
994 void ms_hlsdemux_pad_added_cb(GstElement *element, GstPad *new_pad, gpointer user_data)
1000 gp = GST_PAD(user_data);
1001 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), new_pad);
1006 static void __demux_nomore_pads_combine(GstPad *src_pad, media_streamer_s *ms_streamer)
1008 GstElement *found_element = NULL;
1009 const gchar *new_pad_type = NULL;
1013 found_element = gst_pad_get_parent_element(src_pad);
1014 new_pad_type = ms_get_pad_type(src_pad);
1016 if (MS_ELEMENT_IS_VIDEO(new_pad_type))
1017 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1018 else if (MS_ELEMENT_IS_AUDIO(new_pad_type))
1019 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1020 else if (MS_ELEMENT_IS_TEXT(new_pad_type))
1021 found_element = ms_combine_next_element(found_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY);
1023 ms_error("Unsupported pad type [%s]!", new_pad_type);
1025 ms_generate_dots(ms_streamer->pipeline, "after_demux_linked");
1026 gst_object_unref(found_element);
1031 void ms_demux_nomore_pads_cb(GstElement *element, gpointer user_data)
1033 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1034 GList *iterator = NULL;
1039 ms_retm_if(ms_streamer == NULL, "Handle is NULL");
1041 g_mutex_lock(&ms_streamer->mutex_lock);
1043 list = ms_streamer->pads_types_list;
1044 for (iterator = list; iterator; iterator = iterator->next) {
1045 GstPad *src_pad = GST_PAD(iterator->data);
1046 __demux_nomore_pads_combine(src_pad, ms_streamer);
1049 g_mutex_unlock(&ms_streamer->mutex_lock);
1054 int ms_element_set_state(GstElement *element, GstState state)
1056 GstStateChangeReturn ret_state;
1060 ms_retvm_if(element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "element is NULL");
1062 ret_state = gst_element_set_state(element, state);
1064 if (ret_state == GST_STATE_CHANGE_FAILURE) {
1065 ms_error("Failed to set element [%s] into %s state", GST_ELEMENT_NAME(element), gst_element_state_get_name(state));
1066 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1071 return MEDIA_STREAMER_ERROR_NONE;
1074 GstElement *ms_element_create(const char *plugin_name, const char *name)
1076 GstElement *plugin_elem = NULL;
1080 ms_retvm_if(plugin_name == NULL, (GstElement *) NULL, "Error empty plugin name");
1082 ms_info("Creating [%s] element", plugin_name);
1084 plugin_elem = gst_element_factory_make(plugin_name, name);
1085 ms_retvm_if(plugin_elem == NULL, (GstElement *) NULL, "Error creating element [%s]", plugin_name);
1092 static int __ms_adaptive_sink_prepare(media_streamer_s *ms_streamer)
1094 static node_info_s nodes_info[] = {
1095 {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
1096 {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
1097 {"Codec/Muxer", "mpegtsmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
1100 GstCaps *video_enc_src_caps = NULL;
1101 GstCaps *video_enc_sink_caps = NULL;
1102 GstCaps *audio_enc_src_caps = NULL;
1103 GstCaps *audio_enc_sink_caps = NULL;
1104 GstElement *audio_enc = NULL;
1105 GstElement *video_enc = NULL;
1106 GstCaps *muxer_src_caps = NULL;
1107 GstElement *muxer = NULL;
1108 node_plug_s video_enc_plug_info = {0, };
1109 node_plug_s audio_enc_plug_info = {0, };
1110 node_plug_s mux_plug_info = {0, };
1114 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1116 video_enc_src_caps = gst_caps_new_simple("video/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
1117 video_enc_sink_caps = gst_caps_new_empty_simple("video/x-raw");
1118 video_enc_plug_info.info = &(nodes_info[0]);
1119 video_enc_plug_info.src_caps = video_enc_src_caps;
1120 video_enc_plug_info.sink_caps = video_enc_sink_caps;
1121 video_enc = ms_node_element_create(&video_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1123 audio_enc_src_caps = gst_caps_new_simple("audio/mpeg", "mpegversion", G_TYPE_INT, 4, NULL);
1124 audio_enc_sink_caps = gst_caps_new_empty_simple("audio/x-raw");
1125 audio_enc_plug_info.info = &(nodes_info[1]);
1126 audio_enc_plug_info.src_caps = audio_enc_src_caps;
1127 audio_enc_plug_info.sink_caps = audio_enc_sink_caps;
1128 audio_enc = ms_node_element_create(&audio_enc_plug_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1130 muxer_src_caps = gst_caps_new_empty_simple("video/mpegts");
1131 mux_plug_info.info = &(nodes_info[2]);
1132 mux_plug_info.src_caps = muxer_src_caps;
1133 muxer = ms_node_element_create(&mux_plug_info, MEDIA_STREAMER_NODE_TYPE_MUXER);
1135 ms_bin_add_element(ms_streamer->transform_bin, muxer, FALSE);
1136 gst_element_sync_state_with_parent(muxer);
1137 ms_bin_add_element(ms_streamer->transform_bin, video_enc, FALSE);
1138 gst_element_sync_state_with_parent(video_enc);
1139 ms_bin_add_element(ms_streamer->transform_bin, audio_enc, FALSE);
1140 gst_element_sync_state_with_parent(audio_enc);
1144 return MEDIA_STREAMER_ERROR_NONE;
1147 GstElement *ms_adaptive_element_create(void)
1149 GstElement *adaptive_bin = NULL;
1153 adaptive_bin = gst_bin_new("adaptive_src");
1154 ms_retvm_if(!adaptive_bin, (GstElement *) NULL, "Error: creating elements for adaptive source");
1156 __ms_add_no_target_ghostpad(adaptive_bin, "src", GST_PAD_SRC);
1158 /* Add adaptive node parameters as GObject data with destroy function */
1159 MS_SET_INT_STATIC_STRING_PARAM(adaptive_bin, MEDIA_STREAMER_PARAM_URI, "http://localhost");
1163 return adaptive_bin;
1167 static gboolean __ms_feature_node_filter(GstPluginFeature *feature, gpointer data)
1169 node_plug_s *plug_info = (node_plug_s*)data;
1170 gboolean can_accept = FALSE;
1171 gboolean src_can_accept = FALSE;
1172 gboolean sink_can_accept = FALSE;
1173 GstElementFactory *factory = NULL;
1174 const gchar *factory_klass = NULL;
1176 if (!GST_IS_ELEMENT_FACTORY(feature))
1179 factory = GST_ELEMENT_FACTORY(feature);
1180 factory_klass = gst_element_factory_get_klass(factory);
1182 if (plug_info && g_strrstr(factory_klass, plug_info->info->klass_name)) {
1183 if (GST_IS_CAPS(plug_info->src_caps))
1184 src_can_accept = gst_element_factory_can_src_any_caps(factory, plug_info->src_caps);
1186 if (GST_IS_CAPS(plug_info->sink_caps))
1187 sink_can_accept = gst_element_factory_can_sink_any_caps(factory, plug_info->sink_caps);
1189 if (GST_IS_CAPS(plug_info->src_caps) && GST_IS_CAPS(plug_info->sink_caps)) {
1190 if (src_can_accept && sink_can_accept)
1192 } else if (src_can_accept || sink_can_accept)
1197 for ( ; plug_info->exclude_names && plug_info->exclude_names[index]; ++index) {
1198 if (g_strrstr(GST_OBJECT_NAME(factory), plug_info->exclude_names[index])) {
1199 ms_debug("Skipping compatible factory [%s] as excluded.", GST_OBJECT_NAME(factory));
1204 ms_info("[INFO] Found compatible factory [%s] for klass [%s]",
1205 GST_OBJECT_NAME(factory), factory_klass);
1214 static GstElement *ms_element_create_from_ini(node_plug_s *plug_info, media_streamer_node_type_e type)
1216 const gchar *src_type, *sink_type;
1217 const gchar *format_type;
1218 GstElement *gst_element = NULL;
1219 gchar conf_key[INI_MAX_STRLEN] = {0,};
1220 gchar *plugin_name = NULL;
1224 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1226 MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1227 MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1229 ms_info("Specified node formats types: in[%s] - out[%s]", sink_type, src_type);
1231 if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER) {
1232 format_type = src_type;
1234 MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type);
1235 } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER) {
1236 format_type = src_type;
1238 MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type);
1239 } else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER) {
1240 format_type = sink_type;
1242 MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT), format_type);
1243 } else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER) {
1244 format_type = sink_type;
1246 MS_GET_CAPS_TYPE(gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT), format_type);
1248 format_type = sink_type ? sink_type : src_type;
1250 if (snprintf(conf_key, INI_MAX_STRLEN, "node type %d:%s", type, format_type) >= INI_MAX_STRLEN) {
1251 ms_error("Failed to generate config field name, size >= %d", INI_MAX_STRLEN);
1255 plugin_name = ms_ini_get_string(conf_key, NULL);
1258 gst_element = ms_element_create(plugin_name, NULL);
1259 MS_SAFE_GFREE(plugin_name);
1267 static GstElement *ms_element_create_by_registry(node_plug_s *plug_info, media_streamer_node_type_e type)
1269 GstElement *gst_element = NULL;
1270 const gchar *src_type = NULL;
1271 const gchar *sink_type = NULL;
1272 GList *factories = NULL;
1273 GstElementFactory *factory = NULL;
1277 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1279 MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1280 MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1282 ms_ini_read_list("general:exclude elements", &plug_info->exclude_names);
1284 factories = gst_registry_feature_filter(gst_registry_get(),
1285 __ms_feature_node_filter, FALSE, plug_info);
1286 factories = g_list_sort(factories, (GCompareFunc) __ms_factory_rank_compare);
1289 factory = GST_ELEMENT_FACTORY(factories->data);
1290 ms_info("Sorted result element is [%s]", GST_OBJECT_NAME(factory));
1291 gst_element = ms_element_create(GST_OBJECT_NAME(factory), NULL);
1293 ms_debug("Could not find any compatible element for node [%d]: in[%s] - out[%s]",
1294 type, sink_type, src_type);
1297 g_strfreev(plug_info->exclude_names);
1298 gst_plugin_list_free(factories);
1305 static GstElement *__ms_video_encoder_element_create(node_plug_s *plug_info)
1307 GstElement *video_scale = NULL;
1308 GstElement *video_convert = NULL;
1309 GstElement *encoder_elem = NULL;
1310 GstElement *encoder_parser = NULL;
1311 GstElement *encoder_bin = NULL;
1312 gboolean gst_ret = FALSE;
1313 const gchar *src_type = NULL;
1314 node_plug_s encoder_info = {0,};
1315 node_plug_s parser_info = {0,};
1316 node_info_s node_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER};
1317 media_format_mimetype_e encoder_type = MEDIA_FORMAT_MAX;
1318 GstCaps *enc_caps = NULL;
1322 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1324 enc_caps = plug_info->src_caps;
1326 enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1327 ms_debug("No Video encoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1330 /* Creating Scaler, Converter */
1331 video_scale = ms_element_create(DEFAULT_VIDEO_SCALE, NULL);
1332 video_convert = ms_element_create(DEFAULT_VIDEO_CONVERT, NULL);
1334 /* Creating Video Encoder */
1335 encoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1336 encoder_info.src_caps = enc_caps;
1337 encoder_info.sink_caps = plug_info->sink_caps;
1338 encoder_info.exclude_names = NULL;
1340 encoder_elem = ms_element_create_from_ini(&encoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1342 encoder_elem = ms_element_create_by_registry(&encoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1344 /* Creating bin - Video Encoder */
1345 encoder_bin = gst_bin_new("video_encoder");
1347 if (!video_convert || !video_scale || !encoder_elem || !encoder_bin) {
1351 MS_GET_CAPS_TYPE(enc_caps, src_type);
1352 encoder_type = ms_convert_string_format_to_media_format(src_type);
1354 if (encoder_type == MEDIA_FORMAT_VP8) {
1355 /* VP8 does not have parser */
1356 g_object_set(G_OBJECT(encoder_elem), "deadline", 1, NULL);
1358 /* Adding elements to bin Video Encoder */
1359 gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, NULL);
1360 gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, NULL);
1361 if (gst_ret != TRUE) {
1362 ms_error("Failed to link elements into encoder_bin");
1363 MS_SAFE_UNREF(encoder_bin);
1366 __ms_add_ghostpad(encoder_elem, "src", encoder_bin, "src");
1368 /* Creating Video Parser */
1369 parser_info.info = &node_info;
1370 parser_info.src_caps = enc_caps;
1371 parser_info.sink_caps = enc_caps;
1372 parser_info.exclude_names = NULL;
1374 encoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1375 if (!encoder_parser)
1376 encoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1377 if (!encoder_parser)
1380 /* Settings if H264 format is set*/
1381 if (encoder_type == MEDIA_FORMAT_H264_SP) {
1382 g_object_set(GST_OBJECT(encoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL);
1383 g_object_set(G_OBJECT(encoder_elem), "tune", H264_ENCODER_ZEROLATENCY, NULL);
1384 g_object_set(G_OBJECT(encoder_elem), "byte-stream", TRUE, NULL);
1385 g_object_set(G_OBJECT(encoder_elem), "bitrate", 3000, NULL);
1386 g_object_set(G_OBJECT(encoder_elem), "threads", 2, NULL);
1389 /* Adding elements to bin Video Encoder */
1390 gst_bin_add_many(GST_BIN(encoder_bin), video_convert, video_scale, encoder_elem, encoder_parser, NULL);
1391 gst_ret = gst_element_link_many(video_convert, video_scale, encoder_elem, encoder_parser, NULL);
1392 if (gst_ret != TRUE) {
1393 ms_error("Failed to link elements into encoder_bin");
1394 MS_SAFE_UNREF(encoder_bin);
1397 __ms_add_ghostpad(encoder_parser, "src", encoder_bin, "src");
1399 __ms_add_ghostpad(video_convert, "sink", encoder_bin, "sink");
1406 ms_error("Error: creating elements for video encoder bin");
1407 MS_SAFE_UNREF(video_convert);
1408 MS_SAFE_UNREF(video_scale);
1409 MS_SAFE_UNREF(encoder_elem);
1410 MS_SAFE_UNREF(encoder_parser);
1411 MS_SAFE_UNREF(encoder_bin);
1418 static GstElement *__ms_video_decoder_element_create(node_plug_s *plug_info)
1420 gboolean is_hw_codec = FALSE;
1421 GstElement *last_elem = NULL;
1422 GstElement *decoder_elem = NULL;
1423 GstElement *decoder_parser = NULL;
1424 GstElement *decoder_queue = NULL;
1425 GstElement *video_conv = NULL;
1426 GstElement *video_scale = NULL;
1427 GstElement *decoder_bin = NULL;
1428 node_plug_s decoder_info = {0,};
1429 node_plug_s parser_info = {0,};
1430 node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_VIDEO_PARSER};
1431 media_format_mimetype_e decoder_type = MEDIA_FORMAT_MAX;
1432 gboolean gst_ret = FALSE;
1433 const gchar *sink_type = NULL;
1434 GstCaps *dec_caps = NULL;
1435 gchar *codec_name = NULL;
1439 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1441 dec_caps = plug_info->sink_caps;
1443 dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1444 ms_debug("No Video decoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_VIDEO_FORMAT);
1447 /* Creating Video Decoder */
1448 decoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1449 decoder_info.src_caps = plug_info->src_caps;
1450 decoder_info.sink_caps = dec_caps;
1451 decoder_info.exclude_names = NULL;
1453 decoder_elem = ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1455 decoder_elem = ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER);
1457 /* Creating Video Parser */
1458 parser_info.info = &nodes_info;
1459 parser_info.src_caps = dec_caps;
1460 parser_info.sink_caps = dec_caps;
1461 parser_info.exclude_names = NULL;
1463 decoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1464 if (!decoder_parser)
1465 decoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1467 /* Settings if H264 format is set*/
1468 MS_GET_CAPS_TYPE(dec_caps, sink_type);
1469 decoder_type = ms_convert_string_format_to_media_format(sink_type);
1470 if (decoder_type == MEDIA_FORMAT_H264_SP)
1471 g_object_set(G_OBJECT(decoder_parser), "config-interval", H264_PARSER_CONFIG_INTERVAL, NULL);
1473 /* Creating bin - Video Decoder */
1474 decoder_queue = ms_element_create("queue", NULL);
1475 decoder_bin = gst_bin_new("video_decoder");
1477 if (!decoder_elem || !decoder_queue || !decoder_parser || !decoder_bin) {
1478 ms_error("Error: creating elements for video decoder bin");
1482 codec_name = GST_OBJECT_NAME(decoder_elem);
1483 if (g_strrstr(codec_name, "omx") || g_strrstr(codec_name, "sprd"))
1486 /* Adding elements to bin Audio Encoder */
1487 gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
1488 gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
1489 if (gst_ret != TRUE) {
1490 ms_error("Failed to link elements into decoder_bin");
1491 MS_SAFE_UNREF(decoder_bin);
1495 last_elem = decoder_elem;
1498 video_conv = ms_element_create("videoconvert", NULL);
1499 video_scale = ms_element_create("videoscale", NULL);
1500 if (!video_conv || !video_scale) {
1501 ms_error("Error: creating elements for video decoder bin");
1505 gst_bin_add_many(GST_BIN(decoder_bin), video_conv, video_scale, NULL);
1506 gst_ret = gst_element_link_many(decoder_elem, video_conv, video_scale, NULL);
1507 if (gst_ret != TRUE) {
1508 ms_error("Failed to link elements into decoder_bin");
1509 MS_SAFE_UNREF(decoder_bin);
1512 last_elem = video_scale;
1515 __ms_add_ghostpad(last_elem, "src", decoder_bin, "src");
1516 __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
1524 MS_SAFE_UNREF(decoder_elem);
1525 MS_SAFE_UNREF(decoder_queue);
1526 MS_SAFE_UNREF(decoder_parser);
1527 MS_SAFE_UNREF(video_conv);
1528 MS_SAFE_UNREF(video_scale);
1529 MS_SAFE_UNREF(decoder_bin);
1536 static GstElement *__ms_audio_encoder_element_create(node_plug_s *plug_info)
1538 gboolean gst_ret = FALSE;
1539 GstElement *audio_convert = NULL;
1540 GstElement *audio_resample = NULL;
1541 GstElement *audio_filter = NULL;
1542 GstElement *audio_postenc_convert = NULL;
1543 GstElement *audio_encoder = NULL;
1544 GstElement *audio_enc_bin = NULL;
1545 node_plug_s plug_info_encoder = {0,};
1546 gchar *encoder_name = NULL;
1547 GstCaps *audioCaps = NULL;
1548 GstCaps *enc_caps = NULL;
1552 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1554 enc_caps = plug_info->src_caps;
1556 enc_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1557 ms_debug("No Audio encoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1560 /* Creating Converter, Resampler, Filter */
1561 audio_convert = ms_element_create(DEFAULT_AUDIO_CONVERT, NULL);
1562 audio_resample = ms_element_create(DEFAULT_AUDIO_RESAMPLE, NULL);
1563 audio_filter = ms_element_create(DEFAULT_FILTER, NULL);
1564 audio_postenc_convert = ms_element_create(DEFAULT_AUDIO_CONVERT, NULL);
1566 /* Creating Audio Encoder */
1567 plug_info_encoder.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1568 plug_info_encoder.src_caps = enc_caps;
1569 plug_info_encoder.sink_caps = plug_info->sink_caps;
1570 plug_info_encoder.exclude_names = NULL;
1572 audio_encoder = ms_element_create_from_ini(&plug_info_encoder, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1574 audio_encoder = ms_element_create_by_registry(&plug_info_encoder, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1576 encoder_name = gst_element_get_name(audio_encoder);
1577 if (encoder_name && g_strrstr(encoder_name, "aac"))
1578 g_object_set(audio_encoder, "compliance", -2, NULL);
1579 MS_SAFE_GFREE(encoder_name);
1581 /* Creating bin - Audio Encoder */
1582 audio_enc_bin = gst_bin_new("audio_encoder");
1583 if (!audio_convert || !audio_postenc_convert || !audio_filter || !audio_resample || !audio_encoder || !audio_enc_bin) {
1584 ms_error("Error: creating elements for audio encoder bin");
1588 audioCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT);
1589 g_object_set(G_OBJECT(audio_filter), "caps", audioCaps, NULL);
1590 gst_caps_unref(audioCaps);
1592 /* Adding elements to bin Audio Encoder */
1593 gst_bin_add_many(GST_BIN(audio_enc_bin), audio_convert, audio_postenc_convert, audio_filter, audio_resample, audio_encoder, NULL);
1594 gst_ret = gst_element_link_many(audio_convert, audio_resample, audio_filter, audio_postenc_convert, audio_encoder, NULL);
1595 if (gst_ret != TRUE) {
1596 ms_error("Failed to link elements into decoder_bin");
1597 MS_SAFE_UNREF(audio_enc_bin);
1600 __ms_add_ghostpad(audio_encoder, "src", audio_enc_bin, "src");
1601 __ms_add_ghostpad(audio_convert, "sink", audio_enc_bin, "sink");
1605 return audio_enc_bin;
1609 MS_SAFE_UNREF(audio_convert);
1610 MS_SAFE_UNREF(audio_resample);
1611 MS_SAFE_UNREF(audio_postenc_convert);
1612 MS_SAFE_UNREF(audio_filter);
1613 MS_SAFE_UNREF(audio_encoder);
1614 MS_SAFE_UNREF(audio_enc_bin);
1622 static GstElement *__ms_audio_decoder_element_create(node_plug_s *plug_info)
1624 gboolean gst_ret = FALSE;
1625 GstElement *decoder_bin = NULL;
1626 GstElement *decoder_elem = NULL;
1627 GstElement *decoder_parser = NULL;
1628 GstElement *decoder_queue = NULL;
1629 GstElement *audio_conv = NULL;
1630 GstElement *audio_resample = NULL;
1631 node_plug_s decoder_info = {0,};
1632 node_plug_s parser_info = {0,};
1633 node_info_s nodes_info = {MEDIA_STREAMER_PARSER_KLASS, DEFAULT_AUDIO_PARSER};
1634 GstCaps *dec_caps = NULL;
1638 dec_caps = plug_info->sink_caps;
1640 dec_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1641 ms_debug("No Audio decoding format is set! Default will be: [%s]", MEDIA_STREAMER_DEFAULT_AUDIO_FORMAT);
1644 /* Creating Audio Decoder */
1645 decoder_info.info = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1646 decoder_info.src_caps = plug_info->src_caps;
1647 decoder_info.sink_caps = dec_caps;
1648 decoder_info.exclude_names = NULL;
1650 decoder_elem = ms_element_create_from_ini(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1652 decoder_elem = ms_element_create_by_registry(&decoder_info, MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER);
1654 /* Creating Audio Parser */
1655 parser_info.info = &nodes_info;
1656 parser_info.src_caps = dec_caps;
1657 parser_info.sink_caps = dec_caps;
1658 parser_info.exclude_names = NULL;
1660 decoder_parser = ms_element_create_from_ini(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1661 if (!decoder_parser)
1662 decoder_parser = ms_element_create_by_registry(&parser_info, MEDIA_STREAMER_NODE_TYPE_PARSER);
1664 /* Creating bin - Audio Decoder */
1665 decoder_bin = gst_bin_new("audio_decoder");
1666 decoder_queue = ms_element_create("queue", NULL);
1667 if (!decoder_elem || !decoder_queue || !decoder_parser || !decoder_bin) {
1668 ms_error("Error: creating elements for audio decoder bin");
1672 /* Adding elements to bin Audio Encoder */
1673 gst_bin_add_many(GST_BIN(decoder_bin), decoder_queue, decoder_elem, decoder_parser, NULL);
1674 gst_ret = gst_element_link_many(decoder_queue, decoder_parser, decoder_elem, NULL);
1675 if (gst_ret != TRUE) {
1676 ms_error("Failed to link elements into decoder_bin");
1677 MS_SAFE_UNREF(decoder_bin);
1681 audio_conv = ms_element_create("audioconvert", NULL);
1682 audio_resample = ms_element_create("audioresample", NULL);
1683 if (!audio_conv || !audio_resample) {
1684 ms_error("Error: creating elements for audio decoder bin");
1688 gst_bin_add_many(GST_BIN(decoder_bin), audio_conv, audio_resample, NULL);
1689 gst_ret = gst_element_link_many(decoder_elem, audio_conv, audio_resample, NULL);
1690 if (gst_ret != TRUE) {
1691 ms_error("Failed to link elements into decoder_bin");
1692 MS_SAFE_UNREF(decoder_bin);
1696 __ms_add_ghostpad(audio_resample, "src", decoder_bin, "src");
1697 __ms_add_ghostpad(decoder_queue, "sink", decoder_bin, "sink");
1705 MS_SAFE_UNREF(decoder_elem);
1706 MS_SAFE_UNREF(decoder_queue);
1707 MS_SAFE_UNREF(decoder_parser);
1708 MS_SAFE_UNREF(audio_conv);
1709 MS_SAFE_UNREF(audio_resample);
1710 MS_SAFE_UNREF(decoder_bin);
1717 GstElement *ms_node_element_create(node_plug_s *plug_info, media_streamer_node_type_e type)
1719 GstElement *gst_element = NULL;
1720 const gchar *src_type = NULL;
1721 const gchar *sink_type = NULL;
1725 ms_retvm_if(plug_info == NULL, NULL, "plug_info is NULL");
1727 MS_GET_CAPS_TYPE(plug_info->src_caps, src_type);
1728 MS_GET_CAPS_TYPE(plug_info->sink_caps, sink_type);
1730 /* 1. Main priority:
1731 * If Node klass defined as MEDIA_STREAMER_STRICT or ENCODER/DECODER or CONVERTER types,
1732 * element will be created immediately by format or name */
1733 if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER)
1734 gst_element = __ms_audio_encoder_element_create(plug_info);
1735 else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER)
1736 gst_element = __ms_audio_decoder_element_create(plug_info);
1737 else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER)
1738 gst_element = __ms_video_encoder_element_create(plug_info);
1739 else if (type == MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER)
1740 gst_element = __ms_video_decoder_element_create(plug_info);
1741 else if (type == MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER || type == MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER)
1742 gst_element = ms_element_create(plug_info->info->default_name, NULL);
1743 else if (g_strrstr(MEDIA_STREAMER_STRICT, plug_info->info->klass_name) || (!src_type && !sink_type)) {
1744 if (type == MEDIA_STREAMER_NODE_TYPE_RTP)
1745 gst_element = ms_rtp_element_create();
1747 gst_element = ms_element_create(plug_info->info->default_name, NULL);
1750 /* 2. Second priority:
1751 * Try to get plugin name that defined in ini file
1752 * according with node type and specified format. */
1753 gst_element = ms_element_create_from_ini(plug_info, type);
1756 /* 3. Third priority:
1757 * If previous cases did not create a valid gst_element,
1758 * try to find compatible plugin in gstreamer registry.
1759 * Elements that are compatible but defined as excluded will be skipped*/
1761 /* Read exclude elements list */
1762 gst_element = ms_element_create_by_registry(plug_info, type);
1765 if (type == MEDIA_STREAMER_NODE_TYPE_FILTER) {
1766 if (plug_info->src_caps)
1767 g_object_set(G_OBJECT(gst_element), "caps", plug_info->src_caps, NULL);
1775 GstElement *ms_rtp_element_create(void)
1777 GstElement *rtp_container = NULL;
1781 rtp_container = gst_bin_new("rtp_container");
1782 ms_retvm_if(!rtp_container, (GstElement *) NULL, "Error: creating elements for rtp container");
1784 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_OUT, GST_PAD_SRC);
1785 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_OUT, GST_PAD_SRC);
1786 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_IN, GST_PAD_SINK);
1787 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_IN, GST_PAD_SINK);
1789 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_VIDEO_IN"_rtp", GST_PAD_SINK);
1790 __ms_add_no_target_ghostpad(rtp_container, MS_RTP_PAD_AUDIO_IN"_rtp", GST_PAD_SINK);
1792 /* Add RTP node parameters as GObject data with destroy function */
1793 MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT, RTP_STREAM_DISABLED);
1794 MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT, RTP_STREAM_DISABLED);
1795 MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, RTP_STREAM_DISABLED);
1796 MS_SET_INT_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT, RTP_STREAM_DISABLED);
1797 MS_SET_INT_STATIC_STRING_PARAM(rtp_container, MEDIA_STREAMER_PARAM_HOST, "localhost");
1798 MS_SET_INT_CAPS_PARAM(rtp_container, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, gst_caps_new_any());
1799 MS_SET_INT_CAPS_PARAM(rtp_container, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, gst_caps_new_any());
1803 return rtp_container;
1807 static gboolean __ms_parse_gst_error(media_streamer_s *ms_streamer, GstMessage *message, GError *error)
1809 media_streamer_error_e ret_error = MEDIA_STREAMER_ERROR_NONE;
1813 ms_retvm_if(!ms_streamer, FALSE, "Error: invalid Media Streamer handle.");
1814 ms_retvm_if(!message, FALSE, "Error: invalid bus message handle.");
1815 ms_retvm_if(!error, FALSE, "Error: invalid error handle.");
1817 if (error->domain == GST_CORE_ERROR)
1818 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1819 else if (error->domain == GST_LIBRARY_ERROR)
1820 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1821 else if (error->domain == GST_RESOURCE_ERROR)
1822 ret_error = MEDIA_STREAMER_ERROR_RESOURCE_CONFLICT;
1823 else if (error->domain == GST_STREAM_ERROR)
1824 ret_error = MEDIA_STREAMER_ERROR_CONNECTION_FAILED;
1826 ret_error = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1828 /* post error to application */
1829 if (ms_streamer->error_cb.callback) {
1830 media_streamer_error_cb error_cb = (media_streamer_error_cb) ms_streamer->error_cb.callback;
1831 error_cb((media_streamer_h) ms_streamer, ret_error, ms_streamer->error_cb.user_data);
1840 static GstPadProbeReturn __ms_element_event_probe(GstPad * pad, GstPadProbeInfo *info, gpointer user_data)
1842 GstElement *parent_element = NULL;
1843 GstEvent *event = NULL;
1845 parent_element = gst_pad_get_parent_element(pad);
1846 if (!parent_element) {
1847 ms_error("filed to get parent_elem");
1848 return GST_PAD_PROBE_PASS;
1851 event = GST_PAD_PROBE_INFO_EVENT(info);
1853 if (GST_PAD_PROBE_INFO_TYPE(info) & GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM) {
1854 if (GST_EVENT_TYPE(event) == GST_EVENT_BUFFERSIZE) {
1855 GValue *val_ = (GValue *) g_object_get_data(G_OBJECT(parent_element), "pad_sink");
1856 ms_info("Set locking probe [%d] on [%s] pad of [%s] element", g_value_get_int(val_), GST_PAD_NAME(pad), GST_ELEMENT_NAME(parent_element));
1857 MS_SAFE_UNREF(parent_element);
1858 return GST_PAD_PROBE_OK;
1862 MS_SAFE_UNREF(parent_element);
1864 return GST_PAD_PROBE_PASS;
1867 gboolean ms_element_lock_state(const GValue *item, GValue *ret, gpointer user_data)
1869 GstElement *sink_element = NULL;
1870 GstPad *sink_pad = NULL;
1875 sink_element = GST_ELEMENT(g_value_get_object(item));
1876 ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
1878 g_value_set_boolean(ret, FALSE);
1880 sink_pad = gst_element_get_static_pad(sink_element, "sink");
1882 ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
1885 if (!gst_pad_is_blocked(sink_pad)) {
1886 probe_id = gst_pad_add_probe(sink_pad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, __ms_element_event_probe, NULL, NULL);
1887 MS_SET_INT_PARAM(sink_element, "pad_sink", probe_id);
1888 ms_info("Added locking probe [%d] on pad [%s] of element [%s]", probe_id, GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1890 ms_info("Pad [%s] of element [%s] is already locked", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1892 MS_SAFE_UNREF(sink_pad);
1894 g_value_set_boolean(ret, TRUE);
1901 gboolean ms_element_unlock_state(const GValue *item, GValue *ret, gpointer user_data)
1903 GstElement *sink_element = NULL;
1905 GstPad *sink_pad = NULL;
1909 g_value_set_boolean(ret, FALSE);
1910 sink_element = GST_ELEMENT(g_value_get_object(item));
1911 ms_retvm_if(!sink_element, FALSE, "Handle is NULL");
1913 val = (GValue *) g_object_get_data(G_OBJECT(sink_element), "pad_sink");
1915 sink_pad = gst_element_get_static_pad(sink_element, "sink");
1917 ms_info("Failed to get static pad of element [%s]", GST_ELEMENT_NAME(sink_element));
1920 if (gst_pad_is_blocked(sink_pad)) {
1921 ms_info("Removing locking probe [%d] ID on [%s] pad of [%s] element", g_value_get_int(val), GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1922 gst_pad_remove_probe(sink_pad, g_value_get_int(val));
1924 ms_info("No locking Probe on pad [%s] of element [%s]", GST_PAD_NAME(sink_pad), GST_ELEMENT_NAME(sink_element));
1926 MS_SAFE_UNREF(sink_pad);
1929 g_value_set_boolean(ret, TRUE);
1936 static gboolean __ms_bus_cb(GstBus *bus, GstMessage *message, gpointer userdata)
1938 int ret = MEDIA_STREAMER_ERROR_NONE;
1939 media_streamer_s *ms_streamer = NULL;
1941 gchar *debug = NULL;
1942 gchar *state_transition_name = NULL;
1943 GstState state_old = 0, state_new = 0, state_pending = 0;
1945 ms_streamer = (media_streamer_s *) userdata;
1946 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
1947 ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_STATE, "Pipeline doesn`t exist");
1950 if (message != NULL) {
1951 switch (GST_MESSAGE_TYPE(message)) {
1952 case GST_MESSAGE_ERROR:{
1953 gst_message_parse_error(message, &err, &debug);
1955 /* Transform gst error code to media streamer error code.
1956 * then post it to application if needed */
1957 __ms_parse_gst_error(ms_streamer, message, err);
1959 ms_error("[Source: %s] Error: %s", GST_OBJECT_NAME(GST_OBJECT_CAST(GST_ELEMENT(GST_MESSAGE_SRC(message)))), err->message);
1962 MS_SAFE_GFREE(debug);
1966 case GST_MESSAGE_STATE_CHANGED:{
1967 if (GST_MESSAGE_SRC(message) == GST_OBJECT(ms_streamer->pipeline)) {
1968 gst_message_parse_state_changed(message, &state_old, &state_new, &state_pending);
1969 state_transition_name = g_strdup_printf("Old_[%s]_New_[%s]_Pending_[%s]", gst_element_state_get_name(state_old),
1970 gst_element_state_get_name(state_new), gst_element_state_get_name(state_pending));
1971 ms_info("GST_MESSAGE_STATE_CHANGED: [%s] %s. ", GST_OBJECT_NAME(GST_MESSAGE_SRC(message)), state_transition_name);
1972 ms_generate_dots(ms_streamer->pipeline, state_transition_name);
1973 MS_SAFE_GFREE(state_transition_name);
1975 media_streamer_state_e old_state = ms_streamer->state;
1976 if (state_new >= GST_STATE_PAUSED) {
1977 if ((old_state == MEDIA_STREAMER_STATE_PLAYING) && (state_new <= GST_STATE_PAUSED))
1978 ms_streamer->pend_state = MEDIA_STREAMER_STATE_PAUSED;
1980 if (ms_streamer->pend_state != ms_streamer->state) {
1982 g_mutex_lock(&ms_streamer->mutex_lock);
1983 ms_streamer->state = ms_streamer->pend_state;
1984 g_mutex_unlock(&ms_streamer->mutex_lock);
1986 ms_info("Media streamer state changed to [%d] [%d]", old_state, ms_streamer->state);
1987 if (ms_streamer->state_changed_cb.callback) {
1988 media_streamer_state_changed_cb cb = (media_streamer_state_changed_cb) ms_streamer->state_changed_cb.callback;
1989 cb((media_streamer_h) ms_streamer, old_state, ms_streamer->state, ms_streamer->state_changed_cb.user_data);
1997 case GST_MESSAGE_ASYNC_DONE:{
1998 ms_debug("GST_MESSAGE_ASYNC_DONE");
1999 if (GST_MESSAGE_SRC(message) == GST_OBJECT(ms_streamer->pipeline)
2000 && ms_streamer->is_seeking) {
2002 g_mutex_lock(&ms_streamer->mutex_lock);
2003 ms_streamer->pend_state = MEDIA_STREAMER_STATE_SEEKING;
2004 g_mutex_unlock(&ms_streamer->mutex_lock);
2006 if (ms_streamer->seek_done_cb.callback) {
2007 media_streamer_position_changed_cb cb = (media_streamer_position_changed_cb) ms_streamer->seek_done_cb.callback;
2008 cb(ms_streamer->seek_done_cb.user_data);
2011 g_mutex_lock(&ms_streamer->mutex_lock);
2012 ms_streamer->is_seeking = FALSE;
2013 ms_streamer->pend_state = MEDIA_STREAMER_STATE_PLAYING;
2014 ms_streamer->seek_done_cb.callback = NULL;
2015 ms_streamer->seek_done_cb.user_data = NULL;
2016 g_mutex_unlock(&ms_streamer->mutex_lock);
2020 case GST_MESSAGE_EOS:{
2021 ms_info("GST_MESSAGE_EOS end-of-stream");
2022 ret = ms_element_set_state(ms_streamer->pipeline, GST_STATE_PAUSED);
2023 if (ret != MEDIA_STREAMER_ERROR_NONE) {
2024 ms_error("ERROR - Pause Pipeline");
2037 static int __ms_gstreamer_init(media_streamer_s *ms_streamer)
2039 int ret = MEDIA_STREAMER_ERROR_NONE;
2043 gboolean gst_ret = 0;
2048 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2050 argc = (int *)malloc(sizeof(int));
2052 ms_error("Error allocation memory");
2053 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2056 /* get argc(number of command line option), argc is always one without option */
2058 if (ms_streamer->ini.gst_args)
2059 (*argc) += g_strv_length(ms_streamer->ini.gst_args); /* default is "--gst-debug = 2 */
2061 argv = (char **)calloc(*argc, sizeof(char*));
2064 ms_error("Error allocation memory");
2065 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2068 argv[0] = g_strdup("MediaStreamer");
2070 if (ms_streamer->ini.gst_args) {
2071 for ( ; ms_streamer->ini.gst_args[i]; ++i) {
2073 ms_error("need to check, prevent overrun");
2076 argv[i+1] = ms_streamer->ini.gst_args[i];
2077 ms_debug("Add [%s] gstreamer parameter.", argv[i+1]);
2081 gst_ret = gst_init_check(argc, &argv, &err);
2083 /* Clean memory of gstreamer arguments*/
2084 g_strfreev(ms_streamer->ini.gst_args);
2085 ms_streamer->ini.gst_args = NULL;
2087 for (i = 1; i < *argc; i++)
2090 MS_SAFE_FREE(argv[0]);
2095 ms_error("Error: Failed to initialize GStreamer [%s].", err->message);
2096 g_clear_error(&err);
2097 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2105 int ms_pipeline_create(media_streamer_s *ms_streamer)
2107 int ret = MEDIA_STREAMER_ERROR_NONE;
2111 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2113 /* initialize gstreamer with configured parameter */
2114 ret = __ms_gstreamer_init(ms_streamer);
2115 if (ret != MEDIA_STREAMER_ERROR_NONE)
2118 ms_streamer->pipeline = gst_pipeline_new(MEDIA_STREAMER_PIPELINE_NAME);
2119 ms_retvm_if(ms_streamer->pipeline == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating pipeline");
2121 ms_streamer->bus = gst_pipeline_get_bus(GST_PIPELINE(ms_streamer->pipeline));
2122 ms_retvm_if(ms_streamer->bus == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error getting the bus of the pipeline");
2124 ms_streamer->bus_watcher = gst_bus_add_watch(ms_streamer->bus, (GstBusFunc) __ms_bus_cb, ms_streamer);
2126 ms_streamer->src_bin = gst_bin_new(MEDIA_STREAMER_SRC_BIN_NAME);
2127 ms_retvm_if(ms_streamer->src_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Src bin");
2129 ms_streamer->sink_bin = gst_bin_new(MEDIA_STREAMER_SINK_BIN_NAME);
2130 ms_retvm_if(ms_streamer->sink_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Sink bin");
2132 ms_streamer->transform_bin = gst_bin_new(MEDIA_STREAMER_TRANSFORM_BIN_NAME);
2133 ms_retvm_if(ms_streamer->transform_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error creating Transform bin");
2135 gst_bin_add_many(GST_BIN(ms_streamer->pipeline), ms_streamer->src_bin, ms_streamer->sink_bin, ms_streamer->transform_bin, NULL);
2136 ms_info("Media streamer pipeline created successfully.");
2143 static gboolean __find_node(gpointer key, gpointer value, gpointer user_data)
2145 gchar *node_name = (gchar *)user_data;
2147 return g_strrstr((char *)key, node_name) != NULL;
2150 static void __ms_pending_pads_remove(void *data)
2156 ms_retm_if(data == NULL, "data is NULL");
2158 pad = GST_PAD(data);
2164 static gboolean __ms_bin_unprepare(media_streamer_s *ms_streamer, GstElement *bin)
2166 GValue element = G_VALUE_INIT;
2167 GstIterator *bin_iterator = NULL;
2168 gboolean ret = TRUE; /* If the bin doesn't have any elements, it returns TRUE */
2169 GstElement *found_element = NULL;
2170 GstIteratorResult it_res = GST_ITERATOR_ERROR;
2171 media_streamer_node_s *found_node = NULL;
2175 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2176 ms_retvm_if(bin == NULL, FALSE, "bin is NULL");
2177 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2179 bin_iterator = gst_bin_iterate_elements(GST_BIN(bin));
2180 it_res = gst_iterator_next(bin_iterator, &element);
2182 while (GST_ITERATOR_OK == it_res) {
2183 found_element = (GstElement *) g_value_get_object(&element);
2185 /* Get node of this element if it appears as node */
2186 found_node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table, GST_ELEMENT_NAME(found_element));
2188 if (!found_node->linked_by_user)
2189 ret = ret && ms_element_unlink(found_element);
2191 ms_info("Unprepare skipped user-linked node [%s]", found_node->name);
2192 ms_generate_dots(ms_streamer->pipeline, GST_ELEMENT_NAME(found_element));
2194 ret = ret && ms_bin_remove_element(found_element);
2197 g_value_reset(&element);
2199 it_res = gst_iterator_next(bin_iterator, &element);
2200 if (GST_ITERATOR_RESYNC == it_res) {
2201 gst_iterator_resync(bin_iterator);
2202 it_res = gst_iterator_next(bin_iterator, &element);
2206 g_value_unset(&element);
2207 gst_iterator_free(bin_iterator);
2214 int ms_pipeline_prepare(media_streamer_s *ms_streamer)
2216 int ret = MEDIA_STREAMER_ERROR_NONE;
2217 media_streamer_node_s *rtp = NULL;
2218 media_streamer_node_s *demux = NULL;
2219 media_streamer_node_s *adaptive_src = NULL;
2220 media_streamer_node_s *adaptive_sink = NULL;
2221 gchar *find_node_name = "demux";
2225 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2226 ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->nodes_table is NULL");
2227 ms_retvm_if(ms_streamer->src_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->src_bin is NULL");
2228 ms_retvm_if(ms_streamer->transform_bin == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->transform_bin is NULL");
2230 rtp = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
2231 demux = (media_streamer_node_s *)g_hash_table_find(ms_streamer->nodes_table, (GHRFunc)__find_node, find_node_name);
2232 adaptive_src = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_src");
2233 adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
2236 ret = ms_rtp_node_prepare(rtp);
2238 ret = ms_demux_node_prepare(ms_streamer, demux);
2239 if (MEDIA_STREAMER_ERROR_NONE != ret)
2240 ms_error("Failed to prepare demux element");
2242 GstBin *nodes_bin = GST_BIN(ms_streamer->src_bin);
2243 if (nodes_bin->numchildren == 0) {
2244 ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->src_bin));
2245 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2247 nodes_bin = GST_BIN(ms_streamer->sink_bin);
2248 if (nodes_bin->numchildren == 0) {
2249 ms_debug(" No any node is added to [%s]", GST_ELEMENT_NAME(ms_streamer->sink_bin));
2250 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2255 if (GST_BIN(ms_streamer->transform_bin)->numchildren == 0)
2256 ret = ms_adaptive_src_node_prepare(adaptive_src, true);
2258 ret = ms_adaptive_src_node_prepare(adaptive_src, false);
2262 ret = ms_adaptive_sink_node_prepare(ms_streamer, adaptive_sink);
2264 if (ret != MEDIA_STREAMER_ERROR_NONE)
2267 ret = ms_bin_foreach_elements(GST_BIN(ms_streamer->sink_bin), ms_sink_node_prepare_iter, ms_streamer);
2268 if (MEDIA_STREAMER_ERROR_NONE != ret) {
2269 ms_error("Failed to prepare nodes within sink bin");
2273 ret = ms_bin_foreach_elements(GST_BIN(ms_streamer->src_bin), ms_src_node_prepare_iter, ms_streamer);
2274 if (MEDIA_STREAMER_ERROR_NONE != ret) {
2275 ms_error("Failed to prepare nodes within src bin");
2279 ret = ms_set_state(ms_streamer, MEDIA_STREAMER_STATE_READY);
2280 if (ret != MEDIA_STREAMER_ERROR_NONE)
2288 ms_pipeline_unprepare(ms_streamer);
2292 int ms_pipeline_unprepare(media_streamer_s *ms_streamer)
2294 int ret = MEDIA_STREAMER_ERROR_NONE;
2298 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2299 ms_retvm_if(ms_streamer->nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer->nodes_table is NULL");
2301 ret = ms_set_state(ms_streamer, MEDIA_STREAMER_STATE_IDLE);
2302 if (ret != MEDIA_STREAMER_ERROR_NONE)
2303 ms_error("Failed to unprepare pipeline");
2305 if (!ms_streamer->is_interrupted) {
2306 /* FIXME: it seems possible to move codes below to ms_set_state(), need to check the history. */
2307 /* Unprepare resources in case of failure */
2308 if (ms_streamer->video_decoder_resource != NULL) {
2309 ret = mm_resource_manager_mark_for_release(ms_streamer->resource_manager,
2310 ms_streamer->video_decoder_resource);
2311 if (ret != MM_RESOURCE_MANAGER_ERROR_NONE)
2312 ms_error("Failed to mark resources for release");
2314 ret = mm_resource_manager_commit(ms_streamer->resource_manager);
2315 if (ret != MEDIA_STREAMER_ERROR_NONE)
2316 ms_error("Failed to release resources");
2318 ms_streamer->video_decoder_resource = NULL;
2322 /* Disconnects and clean all autoplug signals */
2323 g_list_free_full(ms_streamer->autoplug_sig_list, ms_signal_destroy);
2324 ms_streamer->autoplug_sig_list = NULL;
2326 /* Removes all pending pads according to list */
2327 g_list_free_full(ms_streamer->pads_types_list, __ms_pending_pads_remove);
2328 ms_streamer->pads_types_list = NULL;
2330 media_streamer_node_s *rtp_node = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "rtp_container");
2332 g_list_free_full(rtp_node->sig_list, ms_signal_destroy);
2333 rtp_node->sig_list = NULL;
2334 __ms_bin_unprepare(ms_streamer, rtp_node->gst_element);
2337 __ms_bin_unprepare(ms_streamer, ms_streamer->src_bin);
2338 __ms_bin_unprepare(ms_streamer, ms_streamer->transform_bin);
2339 __ms_bin_unprepare(ms_streamer, ms_streamer->sink_bin);
2346 void ms_pipeline_get_state(media_streamer_s *ms_streamer)
2348 GstState state_old = GST_STATE_NULL, state_new = GST_STATE_NULL;
2349 GstStateChangeReturn ret_state = -1;
2353 ms_retm_if(ms_streamer == NULL, "ms_streamer is NULL");
2354 ms_retm_if(ms_streamer->pipeline == NULL, "ms_streamer->pipeline is NULL");
2356 ret_state = gst_element_get_state(ms_streamer->pipeline, &state_old, &state_new, GST_CLOCK_TIME_NONE);
2357 if (ret_state == GST_STATE_CHANGE_SUCCESS)
2358 ms_info("Got state for [%s]: old [%s], new [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline), gst_element_state_get_name(state_old), gst_element_state_get_name(state_new));
2360 ms_error("Couldn`t get state for [%s]", GST_ELEMENT_NAME(ms_streamer->pipeline));
2365 GstCaps *ms_create_caps_from_fmt(media_format_h fmt)
2367 GstCaps *caps = NULL;
2368 gchar *caps_name = NULL;
2369 media_format_mimetype_e mime;
2370 int width, height, avg_bps, max_bps, channel, samplerate, bit;
2374 if (!media_format_get_audio_info(fmt, &mime, &channel, &samplerate, &bit, &avg_bps)) {
2375 if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW)) {
2376 caps = gst_caps_new_simple("audio/x-raw", "format", G_TYPE_STRING, ms_convert_mime_to_string_format(mime), NULL);
2377 } else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED)) {
2378 if (mime == MEDIA_FORMAT_AAC)
2379 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "mpegversion", G_TYPE_INT, 4, NULL);
2380 else if (mime == MEDIA_FORMAT_MP3)
2381 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "mpegversion", G_TYPE_INT, 1, NULL);
2383 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "channels", G_TYPE_INT, channel, "rate", G_TYPE_INT, samplerate, NULL);
2385 caps_name = gst_caps_to_string(caps);
2386 ms_info("Creating Audio Caps from media format [%s]", caps_name);
2388 } else if (!media_format_get_video_info(fmt, &mime, &width, &height, &avg_bps, &max_bps)) {
2389 if (MEDIA_FORMAT_RAW == (mime & MEDIA_FORMAT_RAW))
2390 caps = gst_caps_new_simple("video/x-raw", "framerate", GST_TYPE_FRACTION, max_bps,
2391 avg_bps, "format", G_TYPE_STRING, ms_convert_mime_to_string_format(mime), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
2392 else if (MEDIA_FORMAT_ENCODED == (mime & MEDIA_FORMAT_ENCODED))
2393 caps = gst_caps_new_simple(ms_convert_mime_to_string_format(mime), "framerate", GST_TYPE_FRACTION, max_bps,
2394 avg_bps, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
2395 caps_name = gst_caps_to_string(caps);
2396 ms_info("Creating Video Caps from media format [%s]", caps_name);
2398 } else if (!media_format_get_container_mime(fmt, &mime)) {
2399 caps = gst_caps_new_empty_simple(ms_convert_mime_to_string_format(mime));
2400 caps_name = gst_caps_to_string(caps);
2401 ms_info("Creating Video Caps from media format [%s]", caps_name);
2404 ms_error("Error getting media format information");
2406 MS_SAFE_GFREE(caps_name);
2413 static media_format_h __ms_create_fmt_from_caps(GstCaps *caps)
2416 GstStructure *pad_struct;
2417 int fmt_ret = MEDIA_FORMAT_ERROR_NONE;
2418 const gchar *pad_type = NULL;
2419 const gchar *pad_format = NULL;
2420 int channels = 0, bps = 0;
2421 int width = 0, height = 0, avg_bps = 0, max_bps = 0;
2425 ms_retvm_if(caps == NULL, NULL, "Error: empty caps!");
2427 if (gst_caps_is_any(caps)) {
2428 ms_debug("Can not get format info from any caps!");
2432 fmt_ret = media_format_create(&fmt);
2433 ms_retvm_if(fmt_ret != MEDIA_FORMAT_ERROR_NONE, NULL, "Error: while creating media format object, err[%d]!", fmt_ret);
2435 pad_struct = gst_caps_get_structure(caps, 0);
2436 pad_type = gst_structure_get_name(pad_struct);
2437 pad_format = pad_type;
2439 /* Got raw format type if needed */
2440 if (g_strrstr(pad_type, "/x-raw"))
2441 pad_format = gst_structure_get_string(pad_struct, "format");
2443 ms_debug("Pad type is [%s], format: [%s]", pad_type, pad_format);
2445 if (MS_ELEMENT_IS_VIDEO(pad_type)) {
2446 gst_structure_get_int(pad_struct, "width", &width);
2447 gst_structure_get_fraction(pad_struct, "framerate", &max_bps, &avg_bps);
2448 gst_structure_get_int(pad_struct, "height", &height);
2450 media_format_set_video_mime(fmt, ms_convert_string_format_to_media_format(pad_format));
2451 media_format_set_video_width(fmt, width);
2452 media_format_set_video_height(fmt, height);
2453 media_format_set_video_avg_bps(fmt, avg_bps);
2454 media_format_set_video_max_bps(fmt, max_bps);
2455 } else if (MS_ELEMENT_IS_AUDIO(pad_type)) {
2456 media_format_set_audio_mime(fmt, ms_convert_string_format_to_media_format(pad_format));
2457 gst_structure_get_int(pad_struct, "channels", &channels);
2458 media_format_set_audio_channel(fmt, channels);
2459 gst_structure_get_int(pad_struct, "rate", &bps);
2460 media_format_set_audio_avg_bps(fmt, bps);
2468 int ms_element_pad_names(GstElement *gst_element, GstPadDirection pad_type, char ***pad_name_array, int *pads_count)
2470 int ret = MEDIA_STREAMER_ERROR_NONE;
2472 GValue elem = G_VALUE_INIT;
2474 char **pad_names = NULL;
2475 GstIterator *pad_iterator = NULL;
2476 gchar *pad_name = NULL;
2480 ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2481 ms_retvm_if(pad_name_array == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name_array is NULL");
2482 ms_retvm_if(pads_count == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pads_count is NULL");
2484 if (pad_type == GST_PAD_SRC) {
2485 pad_iterator = gst_element_iterate_src_pads(gst_element);
2486 } else if (pad_type == GST_PAD_SINK) {
2487 pad_iterator = gst_element_iterate_sink_pads(gst_element);
2489 pad_iterator = gst_element_iterate_pads(gst_element);
2490 ms_info("Iterating all pads of the Gst element");
2493 while (GST_ITERATOR_OK == gst_iterator_next(pad_iterator, &elem)) {
2494 pad = (GstPad *) g_value_get_object(&elem);
2496 pad_names = (char **)realloc(pad_names, sizeof(char *) * (pad_number + 1));
2498 ms_error("Error allocation memory");
2499 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2501 MS_SAFE_FREE(pad_names);
2505 pad_name = gst_pad_get_name(pad);
2506 pad_names[pad_number] = pad_name;
2510 g_value_reset(&elem);
2513 g_value_unset(&elem);
2514 gst_iterator_free(pad_iterator);
2516 *pad_name_array = pad_names;
2517 *pads_count = pad_number;
2519 MS_SAFE_FREE(pad_names);
2526 int ms_element_get_pad_fmt(GstElement *gst_element, const char *pad_name, media_format_h *fmt)
2528 int ret = MEDIA_STREAMER_ERROR_NONE;
2529 GstCaps *allowed_caps = NULL;
2530 GstCaps *format_caps = NULL;
2532 GValue *value = NULL;
2536 ms_retvm_if(gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2537 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2538 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2541 pad = gst_element_get_static_pad(gst_element, pad_name);
2542 ms_retvm_if(pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Fail to get pad [%s] from element [%s].", pad_name, GST_ELEMENT_NAME(gst_element));
2544 value = (GValue *) g_object_get_data(G_OBJECT(gst_element), pad_name);
2546 format_caps = GST_CAPS(gst_value_get_caps(value));
2548 ms_info(" No any format is set for pad [%s]", pad_name);
2550 allowed_caps = gst_pad_get_allowed_caps(pad);
2552 if (gst_caps_is_empty(allowed_caps) || gst_caps_is_any(allowed_caps)) {
2554 *fmt = __ms_create_fmt_from_caps(format_caps);
2556 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2558 *fmt = __ms_create_fmt_from_caps(allowed_caps);
2562 *fmt = __ms_create_fmt_from_caps(format_caps);
2564 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2568 gst_caps_unref(allowed_caps);
2577 int ms_element_set_fmt(GstElement *element, const char *pad_name, media_format_h fmt)
2579 gboolean can_accept = FALSE;
2580 GstCaps *fmt_caps = NULL;
2581 GstElementFactory *factory = NULL;
2582 GstPad *node_pad = NULL;
2586 ms_retvm_if(!element || !pad_name || !fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2588 fmt_caps = ms_create_caps_from_fmt(fmt);
2589 ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps");
2591 factory = gst_element_get_factory(element);
2592 node_pad = gst_element_get_static_pad(element, pad_name);
2594 if (node_pad && GST_PAD_IS_SRC(node_pad))
2595 can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps);
2596 else if (node_pad && GST_PAD_IS_SINK(node_pad))
2597 can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps);
2599 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2603 gst_caps_unref(fmt_caps);
2604 ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name);
2605 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2607 MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2608 ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2611 MS_SAFE_UNREF(node_pad);
2615 return MEDIA_STREAMER_ERROR_NONE;
2618 gboolean ms_gst_seek(GstElement *element, gint64 g_time, GstSeekFlags seek_flag)
2620 gboolean result = FALSE;
2621 GstEvent *event = NULL;
2625 ms_retvm_if(element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Element is NULL");
2627 event = gst_event_new_seek(1.0, GST_FORMAT_TIME, seek_flag,
2628 GST_SEEK_TYPE_SET, g_time,
2629 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
2631 result = gst_element_send_event(element, event);
2638 int ms_element_push_packet(GstElement *src_element, media_packet_h packet)
2640 GstBuffer *buffer = NULL;
2641 GstFlowReturn gst_ret = GST_FLOW_OK;
2642 guchar *buffer_data = NULL;
2646 ms_retvm_if(src_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2648 if (packet == NULL) {
2649 g_signal_emit_by_name(G_OBJECT(src_element), "end-of-stream", &gst_ret, NULL);
2650 return MEDIA_STREAMER_ERROR_NONE;
2653 media_packet_get_buffer_data_ptr(packet, (void **)&buffer_data);
2655 if (buffer_data != NULL) {
2656 GstMapInfo buff_info = GST_MAP_INFO_INIT;
2658 guint64 duration = 0;
2661 media_packet_get_buffer_size(packet, &size);
2663 buffer = gst_buffer_new_and_alloc(size);
2665 ms_error("Failed to allocate memory for push buffer");
2666 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2669 if (gst_buffer_map(buffer, &buff_info, GST_MAP_READWRITE)) {
2670 memcpy(buff_info.data, buffer_data, size);
2671 buff_info.size = size;
2672 gst_buffer_unmap(buffer, &buff_info);
2675 media_packet_get_pts(packet, &pts);
2676 GST_BUFFER_PTS(buffer) = pts;
2678 media_packet_get_duration(packet, &duration);
2679 GST_BUFFER_DURATION(buffer) = duration;
2681 g_signal_emit_by_name(G_OBJECT(src_element), "push-buffer", buffer, &gst_ret, NULL);
2682 gst_buffer_unref(buffer);
2685 g_signal_emit_by_name(G_OBJECT(src_element), "end-of-stream", &gst_ret, NULL);
2688 if (gst_ret != GST_FLOW_OK)
2689 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2693 return MEDIA_STREAMER_ERROR_NONE;
2696 int ms_element_pull_packet(GstElement *sink_element, media_packet_h *packet)
2698 int ret = MEDIA_STREAMER_ERROR_NONE;
2699 GstSample *sample = NULL;
2700 media_format_h fmt = NULL;
2701 guint8 *buffer_res = NULL;
2702 GstMapInfo map = {0,};
2703 GstBuffer *buffer = NULL;
2707 ms_retvm_if(sink_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2708 ms_retvm_if(packet == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
2710 /* Retrieve the buffer */
2711 g_signal_emit_by_name(sink_element, "pull-sample", &sample, NULL);
2712 ms_retvm_if(sample == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Pull sample failed!");
2714 ret = ms_element_get_pad_fmt(sink_element, "sink", &fmt);
2715 if (ret == MEDIA_STREAMER_ERROR_NONE) {
2716 buffer = gst_sample_get_buffer(sample);
2718 ms_error("Failed to get buffer from sample");
2719 media_format_unref(fmt);
2720 gst_sample_unref(sample);
2721 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2723 gst_buffer_map(buffer, &map, GST_MAP_READ);
2725 buffer_res = (guint8 *) malloc(map.size * sizeof(guint8));
2726 if (buffer_res != NULL) {
2727 memcpy(buffer_res, map.data, map.size);
2729 media_packet_create_from_external_memory(fmt, (void *)buffer_res, map.size, NULL, NULL, packet);
2730 media_packet_set_pts(*packet, GST_BUFFER_PTS(buffer));
2731 media_packet_set_dts(*packet, GST_BUFFER_DTS(buffer));
2732 media_packet_set_pts(*packet, GST_BUFFER_DURATION(buffer));
2734 ms_error("Error allocation memory for packet data");
2735 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2737 gst_buffer_unmap(buffer, &map);
2740 media_format_unref(fmt);
2741 gst_sample_unref(sample);
2748 static void __ms_typefound_cb(GstElement *typefind, guint probability, GstCaps *caps, gpointer data)
2750 media_streamer_s *ms_streamer = (media_streamer_s *) data;
2751 GstElement *decodebin = NULL;
2752 media_streamer_node_s *adaptive_sink = NULL;
2754 GstPad *src_pad = NULL;
2758 ms_retm_if(!typefind, "typefind is NULL");
2759 ms_retm_if(!ms_streamer, "data is NULL");
2761 adaptive_sink = (media_streamer_node_s *)g_hash_table_lookup(ms_streamer->nodes_table, "adaptive_sink");
2762 src_pad = gst_element_get_static_pad(typefind, "src");
2764 type = gst_caps_to_string(caps);
2765 if (g_strrstr(type, "video/mpegts") && adaptive_sink) {
2766 __ms_link_two_elements(typefind, src_pad, adaptive_sink->gst_element);
2768 decodebin = __ms_decodebin_create(ms_streamer, NULL);
2769 __ms_link_two_elements(typefind, src_pad, decodebin);
2772 MS_SAFE_UNREF(src_pad);
2778 int ms_find_type(media_streamer_s *ms_streamer, GstElement *src_element)
2780 GstElement *typefind = NULL;
2781 GstPad *src_pad = NULL;
2785 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2786 ms_retvm_if(!src_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "src_element is NULL");
2788 src_pad = gst_element_get_static_pad(src_element, "src");
2789 ms_retvm_if(src_pad == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
2790 "Error getting static_pad [src_pad]");
2792 typefind = gst_element_factory_make("typefind", "typefinder");
2793 ms_retvm_if(typefind == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
2794 "Error creating element [typefind]");
2796 ms_bin_add_element(ms_streamer->transform_bin, typefind, TRUE);
2798 gst_element_sync_state_with_parent(typefind);
2800 g_signal_connect(typefind, "have-type", G_CALLBACK(__ms_typefound_cb), ms_streamer);
2802 __ms_link_two_elements(src_element, src_pad, typefind);
2804 MS_SAFE_UNREF(src_pad);
2808 return MEDIA_STREAMER_ERROR_NONE;