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.
17 #include <cynara-client.h>
18 #include <system_info.h>
20 #include <gst/video/videooverlay.h>
21 #include "media_streamer_node.h"
22 #include "media_streamer_node_resources.h"
23 #include "media_streamer_node_dpm_policy.h"
24 #include "media_streamer_util.h"
25 #include "media_streamer_gst.h"
26 #include "media_streamer_gst_webrtc.h"
28 #define SMACK_LABEL_LEN 255
29 #define DEFAULT_URI_SCHEME_LENGTH 10
31 #define _FEATURE_NAME_WIFI "http://tizen.org/feature/network.wifi"
32 #define _FEATURE_NAME_TELEPHONY "http://tizen.org/feature/network.telephony"
33 #define _FEATURE_NAME_ETHERNET "http://tizen.org/feature/network.ethernet"
34 #define _FEATURE_NAME_CAMERA "http://tizen.org/feature/camera"
35 #define _FEATURE_NAME_MICROPHONE "http://tizen.org/feature/microphone"
37 #define _WEBRTC_AUDIO_CAPSFILTER "audio_capsfilter"
38 #define _WEBRTC_VIDEO_CAPSFILTER "video_capsfilter"
40 static param_s param_table[] = {
41 {MEDIA_STREAMER_PARAM_CAMERA_ID, "camera-id"},
42 {MEDIA_STREAMER_PARAM_CAPTURE_WIDTH, "capture-width"},
43 {MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT, "capture-height"},
44 {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "is-live"},
45 {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "living"},
46 {MEDIA_STREAMER_PARAM_URI, "uri"},
47 {MEDIA_STREAMER_PARAM_URI, "location"},
48 {MEDIA_STREAMER_PARAM_USER_AGENT, "user-agent"},
49 {MEDIA_STREAMER_PARAM_STREAM_TYPE, "stream-type"},
50 {MEDIA_STREAMER_PARAM_PORT, "port"},
51 {MEDIA_STREAMER_PARAM_VIDEO_IN_PORT, "video_in_port"},
52 {MEDIA_STREAMER_PARAM_AUDIO_IN_PORT, "audio_in_port"},
53 {MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, "video_out_port"},
54 {MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT, "audio_out_port"},
55 {MEDIA_STREAMER_PARAM_IP_ADDRESS, "address"},
56 {MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, "webrtc-peer-type"},
57 {MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER, "webrtc-stun-server"},
58 {MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION, "webrtc-remote-session-description"},
59 {MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, "webrtc-add-ice-candidate"},
60 {MEDIA_STREAMER_PARAM_AUDIO_DEVICE, "audio_device"},
61 {MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED, "sync"},
62 {MEDIA_STREAMER_PARAM_ROTATE, "rotate"},
63 {MEDIA_STREAMER_PARAM_FLIP, "flip"},
64 {MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD, "display-geometry-method"},
65 {MEDIA_STREAMER_PARAM_DISPLAY, "display"},
66 {MEDIA_STREAMER_PARAM_VISIBLE, "visible"},
67 {MEDIA_STREAMER_PARAM_USE_TBM, "use-tbm"},
68 {MEDIA_STREAMER_PARAM_HOST, "host"},
69 {MEDIA_STREAMER_PARAM_SEGMENT_LOCATION, "location"},
70 {MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, "playlist-location"},
74 static node_info_s nodes_info[] = {
75 {"Generic", "none"}, /* MEDIA_STREAMER_NODE_TYPE_NONE */
76 {"Source", "source"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */
77 {"Sink", "sink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */
78 {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
79 {"Codec/Decoder/Video", "video_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */
80 {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
81 {"Codec/Decoder/Audio", "audio_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */
82 {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */
83 {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */
84 {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */
85 {"Codec/Payloader/Network/RTP", "rtph263pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */
86 {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */
87 {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */
88 {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */
89 {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */
90 {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */
91 {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */
92 {"Codec/Parser", "h263parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */
93 {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */
94 {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */
95 {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */
96 {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */
97 {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
98 {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */
99 {"Generic/Bin", "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */
100 {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */
101 {MEDIA_STREAMER_STRICT, "output-selector"}, /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */
102 {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */
103 {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */
104 {"Filter/Network/WebRTC", "webrtc_container"}, /* MEDIA_STREAMER_NODE_TYPE_WEBRTC */
108 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
114 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
115 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
117 if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
120 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
124 return val ? TRUE : FALSE;
127 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
129 int ret = MEDIA_STREAMER_ERROR_NONE;
134 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
135 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
136 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
137 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
140 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
141 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
142 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
143 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
144 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
145 g_value_init(value, G_TYPE_INT);
146 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
147 g_value_init(value, G_TYPE_STRING);
149 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
151 g_value_copy(val, value);
158 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
160 int ret = MEDIA_STREAMER_ERROR_NONE;
165 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
166 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
167 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
168 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
170 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
172 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
173 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
176 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
177 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
178 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
179 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
181 g_value_init(val, G_TYPE_INT);
182 g_value_set_int(val, (int)strtol(param_value, NULL, 10));
183 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
185 g_value_init(val, G_TYPE_STRING);
186 g_value_set_string(val, param_value);
187 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT) ||
188 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT)) {
189 GstCaps *caps = gst_caps_from_string(param_value);
192 g_value_init(val, GST_TYPE_CAPS);
193 gst_value_set_caps(val, caps);
195 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
198 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
206 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
212 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
213 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
215 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
216 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
220 return val ? TRUE : FALSE;
228 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
235 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
236 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
237 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
238 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
240 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
242 ms_error("failed to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
243 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
246 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE)) {
247 if (strcmp(param_value, WEBRTC_PEER_OFFER) && strcmp(param_value, WEBRTC_PEER_ANSWER)) {
248 ms_error("failed to set property, param value should be [%s] or [%s]", WEBRTC_PEER_OFFER, WEBRTC_PEER_ANSWER);
249 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
252 g_value_init(val, G_TYPE_STRING);
253 g_value_set_string(val, param_value);
255 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER)) {
256 ret = ms_webrtcbin_set_stun_server(node, param_value);
257 if (ret != MEDIA_STREAMER_ERROR_NONE) {
258 ms_error("failed to set STUN server: %s", param_value);
262 g_value_init(val, G_TYPE_STRING);
263 g_value_set_string(val, param_value);
265 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION)) {
266 ret = ms_webrtcbin_set_remote_session_description(node, param_value);
267 if (ret != MEDIA_STREAMER_ERROR_NONE) {
268 ms_error("failed to set remote session description:\n%s", param_value);
272 g_value_init(val, G_TYPE_STRING);
273 g_value_set_string(val, param_value);
275 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE)) {
276 ret = ms_webrtcbin_add_ice_candidate(node, param_value);
277 if (ret != MEDIA_STREAMER_ERROR_NONE) {
278 ms_error("failed to add ICE candidate: %s", param_value);
283 ms_error("failed to set property, undefined param name[%s]", param->param_name);
284 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
289 return MEDIA_STREAMER_ERROR_NONE;
292 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
298 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
299 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
301 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
302 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
303 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
307 return val ? TRUE : FALSE;
315 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
317 int ret = MEDIA_STREAMER_ERROR_NONE;
322 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
323 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
324 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
325 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
326 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
328 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
329 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI))
330 g_value_init(value, G_TYPE_STRING);
332 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
334 g_value_copy(val, value);
341 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
343 int ret = MEDIA_STREAMER_ERROR_NONE;
348 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
349 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
350 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
351 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
352 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
354 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
356 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
357 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
360 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
362 g_value_init(val, G_TYPE_STRING);
363 g_value_set_string(val, param_value);
365 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
373 static int __ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
376 const gchar *type = NULL;
378 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
379 ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
381 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
382 ms_error("Invalid node type");
383 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
386 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
388 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
389 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
392 if (!(type = g_value_get_string(val))) {
393 ms_error("Failed to g_value_get_string()");
394 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
397 ms_info("peer type is [%s]", type);
399 *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
401 return MEDIA_STREAMER_ERROR_NONE;
404 static int __ms_node_check_privileges(media_streamer_node_s *node)
406 int ret = MEDIA_STREAMER_ERROR_NONE;
408 char *privilege = NULL;
410 char smackLabel[SMACK_LABEL_LEN + 1];
412 cynara *cynara_h = NULL;
416 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
418 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
419 switch (node->subtype) {
420 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
421 privilege = "http://tizen.org/privilege/internet";
423 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
424 privilege = "http://tizen.org/privilege/internet";
426 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
427 privilege = "http://tizen.org/privilege/camera";
429 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
430 privilege = "http://tizen.org/privilege/recorder";
432 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
433 privilege = "http://tizen.org/privilege/camera";
436 ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
441 if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
442 switch (node->subtype) {
443 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
444 privilege = "http://tizen.org/privilege/internet";
447 ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
452 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
453 privilege = "http://tizen.org/privilege/internet";
455 /* Skip checking for privilege permission in case of other types of Nodes */
456 if (privilege == NULL)
459 if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
460 ms_error("Failed to initialize cynara structure\n");
461 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
464 bzero(smackLabel, SMACK_LABEL_LEN + 1);
466 /* Getting smack label */
467 opened_file = fopen("/proc/self/attr/current", "r");
468 if (opened_file == NULL) {
469 ms_error("Failed to open /proc/self/attr/current\n");
470 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
472 ret_val = fread(smackLabel, sizeof(smackLabel), 1, opened_file);
475 ms_error("Failed to read /proc/self/attr/current\n");
476 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
480 snprintf(uid, sizeof(uid), "%d", getuid());
481 ms_info("%s %s %s\n", smackLabel, uid, privilege);
483 /* Checking with cynara for current session */
484 ret_val = cynara_check(cynara_h, smackLabel, "", uid, privilege);
485 ms_info("Cynara_check [%d] ", ret_val);
488 case CYNARA_API_ACCESS_ALLOWED:
489 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
491 case CYNARA_API_ACCESS_DENIED:
493 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
494 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
498 cynara_finish(cynara_h);
505 static int __ms_node_check_feature(media_streamer_node_s *node)
507 bool enabled = FALSE;
511 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
513 switch (node->type) {
514 case MEDIA_STREAMER_NODE_TYPE_WEBRTC:
515 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
516 ms_info("wifi status = %d", enabled);
518 return MEDIA_STREAMER_ERROR_NONE;
520 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
521 ms_info("telephony status = %d", enabled);
523 return MEDIA_STREAMER_ERROR_NONE;
525 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
526 ms_info("ethernet status = %d", enabled);
528 return MEDIA_STREAMER_ERROR_NONE;
530 ms_error("None of [%s] [%s] [%s] features is enabled", _FEATURE_NAME_WIFI, _FEATURE_NAME_TELEPHONY, _FEATURE_NAME_ETHERNET);
531 return MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
533 ms_debug("For current node type[%d], feature is not needed", node->type);
539 return MEDIA_STREAMER_ERROR_NONE;
542 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
544 int ret = MEDIA_STREAMER_ERROR_NONE;
545 GstCaps *sink_caps = NULL;
546 GstCaps *src_caps = NULL;
550 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
552 ret = __ms_node_check_privileges(node);
553 if (ret != MEDIA_STREAMER_ERROR_NONE) {
554 ms_error("Failed to get privilege for this node type(%d)", node->type);
558 ret = __ms_node_check_feature(node);
559 if (ret != MEDIA_STREAMER_ERROR_NONE) {
560 ms_error("Failed to get feature for this node type(%d)", node->type);
564 sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt) : NULL;
565 src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt) : NULL;
567 node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
569 ms_info("Creating node with info: klass_name[%s]; default[%s]",
570 plug_info.info->klass_name, plug_info.info->default_name);
572 node->gst_element = ms_node_element_create(&plug_info, node->type);
573 if (node->gst_element)
574 node->name = gst_element_get_name(node->gst_element);
576 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
579 gst_caps_unref(src_caps);
582 gst_caps_unref(sink_caps);
589 /* This signal callback is called when appsrc needs data, we add an idle handler
590 * to the mainloop to start pushing data into the appsrc */
591 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
593 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
594 media_streamer_callback_s *src_callback = NULL;
595 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
599 ms_retm_if(ms_src == NULL, "data is NULL");
600 ms_retm_if(pipeline == NULL, "pipeline is NULL");
602 if (ms_src->callbacks_structure != NULL) {
603 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
604 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
605 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
611 /* This callback is called when appsrc has enough data and we can stop sending.
612 * We remove the idle handler from the mainloop */
613 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
615 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
616 media_streamer_callback_s *src_callback = NULL;
617 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
621 ms_retm_if(ms_src == NULL, "data is NULL");
622 ms_retm_if(pipeline == NULL, "pipeline is NULL");
624 if (ms_src->callbacks_structure != NULL) {
625 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
626 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
627 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
633 static int __ms_src_node_check_feature(media_streamer_node_s *node)
635 int ret = MEDIA_STREAMER_ERROR_NONE;
636 bool enabled = FALSE;
637 bool supported = FALSE;
641 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
643 switch (node->subtype) {
644 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
645 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
646 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
647 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
648 ms_info("wifi status = %d", enabled);
652 ms_error("SYSTEM_INFO_ERROR");
655 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
656 ms_info("telephony status = %d", enabled);
660 ms_error("SYSTEM_INFO_ERROR");
663 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
664 ms_info("ethernet status = %d", enabled);
668 ms_error("SYSTEM_INFO_ERROR");
671 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
673 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
674 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
675 ms_info("microphone status = %d", enabled);
679 ms_error("SYSTEM_INFO_ERROR");
682 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
684 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
685 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
686 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
687 ms_info("camera status = %d", enabled);
691 ms_error("SYSTEM_INFO_ERROR");
694 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
697 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
706 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
708 int ret = MEDIA_STREAMER_ERROR_NONE;
709 bool enabled = FALSE;
710 bool supported = FALSE;
714 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
716 switch (node->subtype) {
717 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
718 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
719 /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
720 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
721 ms_info("wifi status = %d", enabled);
725 ms_error("SYSTEM_INFO_ERROR");
728 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
729 ms_info("telephony status = %d", enabled);
733 ms_error("SYSTEM_INFO_ERROR");
736 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
737 ms_info("ethernet status = %d", enabled);
741 ms_error("SYSTEM_INFO_ERROR");
744 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
747 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
756 int ms_src_node_create(media_streamer_node_s *node)
758 int ret = MEDIA_STREAMER_ERROR_NONE;
759 char *plugin_name = NULL;
763 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
765 ret = __ms_node_check_privileges(node);
766 if (ret != MEDIA_STREAMER_ERROR_NONE) {
767 ms_error("Error getting privileges for Src Node");
771 ret = __ms_src_node_check_feature(node);
772 if (ret != MEDIA_STREAMER_ERROR_NONE) {
773 ms_error("Error getting feature for Src Node");
777 switch (node->subtype) {
778 case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
779 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
780 node->gst_element = ms_element_create(plugin_name, NULL);
782 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
783 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
784 node->gst_element = ms_element_create(plugin_name, NULL);
786 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
787 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
788 node->gst_element = ms_element_create(plugin_name, NULL);
790 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
791 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
792 node->gst_element = ms_element_create(plugin_name, NULL);
794 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
795 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
796 node->gst_element = ms_element_create(plugin_name, NULL);
798 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
799 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
800 node->gst_element = ms_element_create(plugin_name, NULL);
802 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
803 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
804 node->gst_element = ms_element_create(plugin_name, NULL);
806 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
807 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
808 node->gst_element = ms_element_create(plugin_name, NULL);
810 case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
811 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
812 node->gst_element = ms_element_create(plugin_name, NULL);
813 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
814 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
815 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
817 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
818 node->gst_element = ms_adaptive_element_create();
821 ms_error("Error: invalid Src node Type [%d]", node->subtype);
825 MS_SAFE_FREE(plugin_name);
827 if (node->gst_element == NULL)
828 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
830 node->name = gst_element_get_name(node->gst_element);
832 ret = ms_node_dpm_policy_init(node);
833 if (MEDIA_STREAMER_ERROR_NONE != ret) {
834 ms_error("Failed to init DPM policy for node [%s]", node->name);
843 /* The appsink has received a buffer */
844 static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
846 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
847 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
848 media_streamer_sink_data_ready_cb data_ready_cb = NULL;
852 ms_retm_if(ms_sink == NULL, "data is NULL");
854 if (ms_sink->callbacks_structure != NULL) {
855 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
856 data_ready_cb = (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
859 data_ready_cb((media_streamer_node_h) ms_sink, sink_callbacks->data_ready_cb.user_data);
866 /* The appsink has got eos */
867 static void sink_eos(GstElement *sink, gpointer *data)
869 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
870 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
871 media_streamer_sink_eos_cb eos_cb = NULL;
875 ms_retm_if(ms_sink == NULL, "data is NULL");
877 if (ms_sink->callbacks_structure != NULL) {
878 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
879 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
882 eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
889 int ms_sink_node_create(media_streamer_node_s *node)
891 int ret = MEDIA_STREAMER_ERROR_NONE;
892 char *plugin_name = NULL;
896 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
898 ret = __ms_node_check_privileges(node);
899 if (ret != MEDIA_STREAMER_ERROR_NONE) {
900 ms_error("Error getting privileges for Sink Node");
904 ret = __ms_sink_node_check_feature(node);
905 if (ret != MEDIA_STREAMER_ERROR_NONE) {
906 ms_error("Error getting feature for Sink Node");
910 switch (node->subtype) {
911 case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
912 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
913 node->gst_element = ms_element_create(plugin_name, NULL);
915 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
916 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
917 node->gst_element = ms_element_create(plugin_name, NULL);
919 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
920 ms_error("Error: not implemented yet");
922 case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
923 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
924 node->gst_element = ms_element_create(plugin_name, NULL);
926 case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
927 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
928 node->gst_element = ms_element_create(plugin_name, NULL);
930 case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
931 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
932 node->gst_element = ms_element_create(plugin_name, NULL);
934 case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
935 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
936 node->gst_element = ms_element_create(plugin_name, NULL);
937 if (node->gst_element) {
938 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
939 ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
940 ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
943 case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
944 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
945 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
947 if (g_strrstr(plugin_name, "hlssink")) {
948 g_object_set(G_OBJECT(node->gst_element),
950 "playlist-length", 0, NULL);
954 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
958 MS_SAFE_FREE(plugin_name);
960 if (node->gst_element == NULL)
961 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
963 node->name = gst_element_get_name(node->gst_element);
970 void ms_node_destroy(media_streamer_node_s *node)
972 gchar *node_name = NULL;
976 ms_retm_if(node == NULL, "node is NULL");
977 node_name = g_strdup(node->name);
979 /* Disconnects and clean all node signals */
980 g_list_free_full(node->sig_list, ms_signal_destroy);
982 /* Deinitialize policy manager */
983 if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
984 ms_error("Failed to deinitialize DPM policy");
986 MS_SAFE_UNREF(node->gst_element);
987 MS_SAFE_FREE(node->name);
988 MS_SAFE_FREE(node->callbacks_structure);
991 ms_info("Node [%s] has been destroyed", node_name);
992 MS_SAFE_GFREE(node_name);
997 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
999 int ret = MEDIA_STREAMER_ERROR_NONE;
1000 GstElement *bin = NULL;
1004 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
1005 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
1007 ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1009 switch (node->type) {
1010 case MEDIA_STREAMER_NODE_TYPE_SRC:
1011 bin = ms_streamer->src_bin;
1013 case MEDIA_STREAMER_NODE_TYPE_SINK:
1014 bin = ms_streamer->sink_bin;
1017 /* Another elements will be add into transform bin */
1018 bin = ms_streamer->transform_bin;
1022 if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
1023 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
1024 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1032 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
1036 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1037 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1038 ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
1040 if (g_hash_table_contains(nodes_table, node->name)) {
1041 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
1042 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1044 if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
1045 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
1046 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1049 ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1053 return MEDIA_STREAMER_ERROR_NONE;
1056 int ms_node_remove_from_table(GHashTable *nodes_table, media_streamer_node_s *node)
1058 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1059 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1061 /* Removal element of this node from bin will be performed
1062 * in the callback - ms_node_remove_from_table_cb(). */
1063 if (!g_hash_table_remove(nodes_table, (gpointer) node->name)) {
1064 ms_error("Failed to remove node [%s] from table", node->name);
1065 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1068 return MEDIA_STREAMER_ERROR_NONE;
1071 void ms_node_remove_from_table_cb(void *data)
1073 media_streamer_node_s *node = (media_streamer_node_s *) data;
1077 ms_retm_if(node == NULL, "data is NULL");
1079 if (ms_element_unlink(node->gst_element)) {
1080 node->linked_by_user = FALSE;
1081 node->parent_streamer = NULL;
1082 ms_bin_remove_element(node->gst_element);
1083 ms_info("Node [%s] removed from Media Streamer", node->name);
1085 ms_error("Failed to unlink element of node [%s]", node->name);
1091 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1093 gboolean ret = FALSE;
1097 if (!src_pad || gst_pad_is_linked(src_pad))
1100 GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1101 if (gst_caps_is_any(src_caps))
1104 gst_caps_unref(src_caps);
1111 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1117 for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1118 if (it_klass == element_type) {
1119 ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1126 return &nodes_info[it_klass];
1129 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1131 gboolean ret = FALSE;
1133 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1134 ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1138 ret = ms_element_lock_state(item, g_ret, user_data);
1145 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1147 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1148 GstElement *src_element = NULL;
1149 GstElement *found_element = NULL;
1150 media_streamer_node_s *node = NULL;
1151 GstPad *src_pad = NULL;
1155 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1156 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1157 ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1159 src_element = GST_ELEMENT(g_value_get_object(item));
1160 g_object_ref(src_element);
1161 g_value_set_boolean(ret, FALSE);
1163 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1164 GST_ELEMENT_NAME(src_element));
1166 /* If we fail to find corresponding node inside streamer
1167 then apparently this element doesn't require resources. */
1168 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1169 g_value_set_boolean(ret, TRUE);
1170 g_object_unref(src_element);
1174 ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1176 src_pad = gst_element_get_static_pad(src_element, "src");
1178 if (__ms_src_need_typefind(src_pad)) {
1179 ms_find_type(ms_streamer, src_element);
1180 MS_SAFE_UNREF(src_element);
1182 /* Check the source element`s pad type */
1183 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1184 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1185 if (gst_pad_is_linked(src_pad)) {
1186 MS_SAFE_UNREF(src_pad);
1187 MS_SAFE_UNREF(src_element);
1188 g_value_set_boolean(ret, TRUE);
1191 /* It is media streamer Server part */
1192 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1193 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1194 GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1195 g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1196 gst_caps_unref(videoCaps);
1198 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1199 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1200 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1202 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1203 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1204 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1205 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1207 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1208 MS_SAFE_UNREF(found_element);
1210 MS_SAFE_UNREF(src_pad);
1212 g_value_set_boolean(ret, TRUE);
1219 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1221 char *manifest_src_name = NULL;
1222 gchar *location = NULL;
1223 GstElement *manifest_src = NULL;
1225 const char *uri = NULL;
1226 gchar *protocol = NULL;
1230 ms_retvm_if(!node, NULL, "node is NULL");
1232 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1233 uri = g_value_get_string(val);
1234 protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1236 if (protocol && g_strrstr(protocol, "http")) {
1237 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1238 location = g_strdup(uri);
1239 } else if (protocol && g_strrstr(protocol, "file")) {
1240 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1241 location = gst_uri_get_location(uri);
1243 ms_error("Unsupported URI protocol... Check URI is file path");
1244 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1245 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1246 location = g_strdup(uri);
1249 ms_error("URI is not valid file path");
1255 if (manifest_src_name == NULL) {
1256 LOGE("Error empty manifest source name for adaptive source");
1261 manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1262 g_free(manifest_src_name);
1264 if (manifest_src == NULL) {
1265 LOGE("Error creating manifest source for adaptive source");
1270 g_object_set(manifest_src, "location", location, NULL);
1275 return manifest_src;
1278 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1280 char *plugin_name = NULL;
1281 GstElement *manifest_src = NULL;
1282 GstElement *plugin_elem = NULL;
1283 gboolean res = FALSE;
1288 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1291 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1292 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1293 ms_info("Creating [%s] element", plugin_name);
1294 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1295 g_free(plugin_name);
1296 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1297 "Error creating element for adaptive source");
1299 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1300 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1301 "Error adding adaptive element to bin for adaptive source");
1304 manifest_src = __ms_manifest_src_create(node);
1305 ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1306 "Error creating manifest source for adaptive source");
1308 res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1309 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1310 "Error adding manifest source to bin for adaptive source");
1313 res = gst_element_link(manifest_src, plugin_elem);
1314 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1315 "Error linking manifest source and element for adaptive source");
1318 gp = gst_element_get_static_pad(node->gst_element, "src");
1319 ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1320 "Error getting source pad for adaptive source");
1323 g_signal_connect_object(plugin_elem, "pad-added",
1324 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1326 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1327 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1332 return MEDIA_STREAMER_ERROR_NONE;
1335 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1337 int err_code = MEDIA_STREAMER_ERROR_NONE;
1338 gchar *playlist_location = NULL;
1339 char *playlist_dir = NULL;
1344 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1345 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1346 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1348 /* Create and start http server */
1349 err_code = ms_http_server_create(&ms_streamer->http_server);
1350 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1351 ms_error("Failed to create http server during prepare");
1355 ms_info("Starting http server");
1356 /* FIXME: find out how to set default port */
1357 err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1358 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1359 ms_error("Failed to start http server during prepare. Destroying http server");
1360 ms_http_server_destroy(ms_streamer->http_server);
1364 g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1365 if (!playlist_location) {
1366 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1367 ms_error("Failed to get playlist location");
1368 ms_http_server_destroy(ms_streamer->http_server);
1372 split = strrchr(playlist_location, '/');
1373 playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1375 ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1377 MS_SAFE_GFREE(playlist_location);
1387 int ms_rtp_node_prepare(media_streamer_node_s *node)
1389 GstElement *rtpbin = NULL;
1390 GstElement *rtp_el = NULL;
1391 GstElement *rtcp_el = NULL;
1393 const char *host = NULL;
1394 GstElement *video_filter = NULL;
1395 GstCaps *video_caps = NULL;
1396 GstGhostPad *ghost_pad = NULL;
1397 GstElement *audio_filter = NULL;
1398 GstCaps *audio_caps = NULL;
1402 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1404 rtpbin = ms_element_create("rtpbin", "rtpbin");
1405 ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1407 if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1408 MS_SAFE_UNREF(rtpbin);
1409 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1412 ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1414 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1415 host = g_value_get_string(val);
1417 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1418 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1419 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rtp");
1420 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1422 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rctp");
1423 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1425 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1426 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1427 ms_error("Failed to link pads for rtpbin sink pad 0");
1428 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1431 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1432 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1434 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT);
1435 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1438 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1439 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1440 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rtp");
1441 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1443 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rctp");
1444 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1446 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1447 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1448 ms_error("Failed to link pads for rtpbin sink pad 1");
1449 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1452 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1453 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1455 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT);
1456 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1459 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1460 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1461 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rtp");
1462 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1464 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rctp");
1465 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1467 video_filter = ms_element_create("capsfilter", NULL);
1468 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1470 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1471 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1472 gst_caps_unref(video_caps);
1474 gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0");
1476 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_VIDEO_IN);
1478 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1479 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_VIDEO_IN);
1482 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1483 !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1484 ms_error("Failed to link pads for rtpbin src pad 0");
1485 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1488 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1489 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1490 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1491 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1492 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1493 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1496 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1497 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1498 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rtp");
1499 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1501 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rctp");
1502 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1504 audio_filter = ms_element_create("capsfilter", NULL);
1505 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1507 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1508 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1510 gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1");
1512 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_AUDIO_IN);
1514 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1515 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_AUDIO_IN);
1518 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1519 !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1520 ms_error("Failed to link pads for rtpbin src pad 1");
1521 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1524 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1525 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1526 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1527 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1528 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1529 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1532 ms_generate_dots(node->gst_element, "rtp_prepared");
1536 return MEDIA_STREAMER_ERROR_NONE;
1539 static int __ms_webrtc_prepare_ghost_sink_pad(GstElement *webrtc_container, GstElement *webrtcbin, const char *capsfilter_name)
1541 int ret = MEDIA_STREAMER_ERROR_NONE;
1543 GstGhostPad *ghost_pad_in = NULL;
1544 GstPad *filter_sink_pad = NULL;
1546 gchar *req_pad_name;
1547 const gchar *pad_name;
1549 ms_retvm_if(!webrtc_container, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
1550 ms_retvm_if(!webrtcbin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtcbin is NULL");
1551 ms_retvm_if(!capsfilter_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "capsfilter_name is NULL");
1553 if (g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) &&
1554 g_strcmp0(capsfilter_name, _WEBRTC_VIDEO_CAPSFILTER))
1555 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1557 pad_name = !g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) ? MS_RTP_PAD_AUDIO_IN : MS_RTP_PAD_VIDEO_IN;
1559 if (!(filter = ms_find_element_in_bin_by_name(webrtc_container, capsfilter_name))) {
1560 ms_debug("No need to export the ghost sink pad for [%s]", pad_name);
1561 return MEDIA_STREAMER_ERROR_NONE;
1564 if (!(ghost_pad_in = (GstGhostPad *)gst_element_get_static_pad(webrtc_container, pad_name))) {
1565 ms_error("Failed to get ghost pad for webrtc_container");
1566 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1569 if (!gst_pad_is_linked((GstPad *)ghost_pad_in)) {
1570 ms_error("[%s] is set media format but not linked to peer node", pad_name);
1571 MS_SAFE_UNREF(ghost_pad_in);
1572 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1575 ms_info("%s is found, link it with webrtcbin and export the ghost pad[%s] of webrtc_container",
1576 capsfilter_name, pad_name);
1578 if (!(req_pad = gst_element_get_request_pad(webrtcbin, "sink_%u"))) {
1579 ms_error("Failed to get request pad");
1580 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1582 if (!(req_pad_name = gst_pad_get_name(req_pad))) {
1583 ms_error("Failed to get request pad name");
1584 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1586 if (!gst_element_link_pads(filter, "src", webrtcbin, req_pad_name)) {
1587 ms_error("Failed to link pads, %s - webrtcbin", capsfilter_name);
1588 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1592 if (!(filter_sink_pad = gst_element_get_static_pad(filter, "sink"))) {
1593 ms_error("Failed to get capsfilter sink pad in webrtc_container");
1594 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1597 if (!gst_ghost_pad_set_target(ghost_pad_in, filter_sink_pad)) {
1598 ms_info("Failed to gst_ghost_pad_set_target() for %s", pad_name);
1599 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1604 MS_SAFE_GFREE(req_pad_name);
1605 MS_SAFE_UNREF(filter_sink_pad);
1606 MS_SAFE_UNREF(ghost_pad_in);
1611 GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
1613 GstElement *webrtcbin = NULL;
1614 node_info_s *node_klass_type = NULL;
1616 ms_retvm_if(webrtc_node == NULL, NULL, "webrtc_node is NULL");
1617 ms_retvm_if(webrtc_node->gst_element == NULL, NULL, "webrtc_container is NULL");
1621 node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
1622 webrtcbin = ms_find_element_in_bin_by_type(webrtc_node->gst_element, node_klass_type);
1624 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
1631 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1633 int ret = MEDIA_STREAMER_ERROR_NONE;
1634 GstElement *webrtcbin = NULL;
1635 GObject *send_channel = NULL;
1636 gboolean is_offerer = FALSE;
1637 media_streamer_webrtc_callbacks_s *_callbacks = NULL;
1641 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1642 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1643 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
1645 if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(node)))
1646 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1648 _callbacks = (media_streamer_webrtc_callbacks_s *) node->callbacks_structure;
1649 if (!_callbacks || !(_callbacks->message_cb.callback)) {
1650 ms_error("message callback should be set before preparing");
1651 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1654 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_AUDIO_CAPSFILTER)))
1656 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
1659 if (__ms_webrtc_node_is_offerer(node, &is_offerer)) {
1660 ms_error("Failed to get peer type");
1661 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1665 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
1667 ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
1668 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
1669 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-connection-state", G_CALLBACK(ms_webrtcbin_notify_ice_connection_state_cb), node);
1671 if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
1672 ms_error("Failed to set state to READY");
1673 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1676 g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
1678 ms_info("data channel(%p) for sending is created", send_channel);
1680 ms_warning("Failed to create data channel");
1682 ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
1683 ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
1685 ms_generate_dots(node->gst_element, "webrtc_prepared");
1689 return MEDIA_STREAMER_ERROR_NONE;
1693 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1697 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1698 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1700 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
1701 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
1705 return MEDIA_STREAMER_ERROR_NONE;
1708 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
1710 GParamSpec *param_spec;
1715 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1716 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1718 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1719 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1720 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1721 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
1722 ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
1723 *param_list = g_list_append(*param_list, &(param_table[it_param]));
1726 ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
1730 return MEDIA_STREAMER_ERROR_NONE;
1733 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
1735 int ret = MEDIA_STREAMER_ERROR_NONE;
1736 Evas_Object *obj = NULL;
1737 media_streamer_wl_info_s wl_info;
1739 obj = (Evas_Object *)param_value;
1741 /* get wayland parent id */
1742 if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
1743 LOGE("failed to get wayland info");
1744 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1747 LOGD("wayland global surface id : %d", wl_info.parent_id);
1749 gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
1754 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
1757 int ret = MEDIA_STREAMER_ERROR_NONE;
1761 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1762 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1763 ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
1765 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1766 ret = __ms_rtp_node_set_property(node, param, param_value);
1771 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
1772 ret = __ms_webrtc_node_set_property(node, param, param_value);
1777 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1778 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
1779 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
1784 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
1785 int camera_id = (int)strtol(param_value, NULL, 10);
1786 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
1787 g_object_set(node->gst_element, param->origin_name, camera_id, NULL);
1788 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1789 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1790 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1791 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1792 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1793 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1794 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1795 g_object_set(node->gst_element, param->origin_name, (int)strtol(param_value, NULL, 10), NULL);
1796 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1797 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1798 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1799 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1800 g_object_set(node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
1801 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
1802 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
1803 ret = ms_util_uri_path_check(param_value);
1804 if (ret != MEDIA_STREAMER_ERROR_NONE)
1807 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1808 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1809 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1810 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1811 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1812 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1813 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1814 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1815 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY)) {
1816 ret = __ms_node_set_display(node, param_value);
1818 ms_info("Can not set parameter [%s] in the node [%s]", param->param_name, node->name);
1819 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1827 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
1829 int ret = MEDIA_STREAMER_ERROR_NONE;
1830 GList *p_list = NULL;
1831 int written_count = 0;
1832 param_s *param = NULL;
1833 GList *list_iter = NULL;
1834 char *string_val = NULL;
1838 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1839 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1841 ret = __ms_node_get_param_list(node, &p_list);
1842 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1843 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1844 param = (param_s *)list_iter->data;
1845 if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
1846 ret = ms_node_set_param_value(node, param, string_val);
1847 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1850 ms_error("failed to set param");
1856 g_list_free(p_list);
1858 ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
1859 if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
1860 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1867 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
1869 int ret = MEDIA_STREAMER_ERROR_NONE;
1870 GList *p_list = NULL;
1871 param_s *param = NULL;
1872 GList *list_iter = NULL;
1873 char *string_val = NULL;
1877 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1878 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1880 ret = __ms_node_get_param_list(node, &p_list);
1881 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1882 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1883 param = (param_s *)list_iter->data;
1885 if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
1886 bundle_add_str(param_list, param->param_name, string_val);
1887 MS_SAFE_FREE(string_val);
1892 g_list_free(p_list);
1899 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
1901 GParamSpec *param_spec;
1902 gboolean found_param = FALSE;
1907 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1908 ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
1909 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1911 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1912 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
1913 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1914 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1915 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name) ||
1916 __ms_webrtc_node_has_property(node, param_table[it_param].origin_name)) {
1917 *param = &(param_table[it_param]);
1918 ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
1924 ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
1928 return MEDIA_STREAMER_ERROR_NONE;
1931 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
1933 int ret = MEDIA_STREAMER_ERROR_NONE;
1934 char *string_val = NULL;
1935 GParamSpec *param_spec = NULL;
1936 GValue value = G_VALUE_INIT;
1940 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1941 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1942 ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
1944 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
1945 ret = __ms_rtp_node_get_property(node, param, &value);
1946 else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1947 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
1948 ret = __ms_adaptive_src_node_get_property(node, param, &value);
1950 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
1952 g_value_init(&value, param_spec->value_type);
1953 g_object_get_property(G_OBJECT(node->gst_element), param->origin_name, &value);
1955 ms_info("Got parameter [%s] for node [%s] with description [%s]", param->param_name, node->name, g_param_spec_get_blurb(param_spec));
1957 ms_error("There is no parameter [%s] for node [%s]", param->origin_name, node->name);
1958 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1962 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID) ||
1963 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1964 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1965 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1966 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
1967 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
1968 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
1969 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
1970 if (G_VALUE_HOLDS_INT(&value))
1971 string_val = g_strdup_printf("%d", g_value_get_int(&value));
1973 string_val = g_strdup_printf("%u", g_value_get_uint(&value));
1974 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1975 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1976 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1977 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1978 string_val = g_strdup(g_value_get_boolean(&value) ? "true" : "false");
1979 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI) ||
1980 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1981 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1982 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1983 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1984 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1985 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1986 string_val = g_value_dup_string(&value);
1987 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1988 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1989 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1990 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1991 string_val = g_strdup_printf("%d", g_value_get_enum(&value));
1994 *string_value = strdup(string_val);
1997 g_value_reset(&value);
1998 g_value_unset(&value);
2005 static int __ms_rtp_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2007 int ret = MEDIA_STREAMER_ERROR_NONE;
2008 media_format_mimetype_e mime;
2009 gchar *rtp_caps_str = NULL;
2011 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2012 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2013 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2014 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2018 /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
2019 if (g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN)) {
2020 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
2021 if (MEDIA_FORMAT_ERROR_NONE == ret) {
2022 rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=%s", ms_convert_mime_to_rtp_format(mime));
2023 param_s param = {MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT};
2024 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
2026 } else if (g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN)) {
2027 int audio_channels, audio_samplerate;
2028 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
2029 if (MEDIA_FORMAT_ERROR_NONE == ret) {
2030 rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1");
2031 param_s param = {MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT};
2032 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
2035 ms_error("[%s]'s pad [%s] can't be set with the given format", GST_ELEMENT_NAME(node->gst_element), pad_name);
2036 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2038 MS_SAFE_GFREE(rtp_caps_str);
2043 static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2045 int ret = MEDIA_STREAMER_ERROR_NONE;
2046 media_format_mimetype_e mime;
2047 const gchar *encoding_name = NULL;
2048 const gchar *capsfilter_name = NULL;
2049 gchar *caps_str = NULL;
2050 gchar *media = NULL;
2052 GstCaps *caps = NULL;
2053 GstElement *capsfilter = NULL;
2055 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2056 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2057 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2058 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2062 if (!g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN) && !g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN)) {
2063 ms_error("Not supported pad_name(%s)", pad_name);
2064 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2067 if (g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN) &&
2068 !media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2071 capsfilter_name = _WEBRTC_VIDEO_CAPSFILTER;
2072 } else if (g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN) &&
2073 !media_format_get_audio_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2076 capsfilter_name = _WEBRTC_AUDIO_CAPSFILTER;
2078 ms_error("Invalid media format for pad_name(%s)", pad_name);
2079 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2082 encoding_name = ms_convert_mime_to_rtp_format(mime);
2083 caps = gst_caps_new_simple("application/x-rtp",
2084 "media", G_TYPE_STRING, media,
2085 "encoding-name", G_TYPE_STRING, encoding_name,
2086 "payload", G_TYPE_INT, payload, NULL);
2088 if (!(capsfilter = ms_find_element_in_bin_by_name(node->gst_element, capsfilter_name))) {
2089 ms_debug("Create %s", capsfilter_name);
2091 if (!(capsfilter = ms_element_create("capsfilter", capsfilter_name))) {
2092 ms_error("Failed to create capsfilter element: %s", capsfilter_name);
2093 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2095 if (!ms_bin_add_element(node->gst_element, capsfilter, FALSE)) {
2096 ms_error("Failed to add capsfilter(%s) to webrtc_container", capsfilter_name);
2097 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2101 g_object_set(G_OBJECT(capsfilter), "caps", (GValue *)caps, NULL);
2103 caps_str = gst_caps_to_string(caps);
2104 ms_info("[%s] is set to [%s]", caps_str, capsfilter_name);
2105 MS_SAFE_GFREE(caps_str);
2107 gst_caps_unref(caps);
2112 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2114 int ret = MEDIA_STREAMER_ERROR_NONE;
2118 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2119 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2120 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2121 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2123 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
2124 ret = __ms_rtp_node_set_pad_format(node, pad_name, fmt);
2125 else if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
2126 ret = __ms_webrtc_node_set_pad_format(node, pad_name, fmt);
2128 ret = ms_element_set_fmt(node->gst_element, pad_name, fmt);
2135 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
2137 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2138 media_streamer_node_s *node = NULL;
2139 GstElement *element = NULL;
2143 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2144 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2145 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2147 g_value_set_boolean(ret, FALSE);
2149 element = GST_ELEMENT(g_value_get_object(item));
2150 g_object_ref(element);
2152 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2153 GST_ELEMENT_NAME(element));
2155 /* If we fail to find corresponding node inside streamer
2156 then apparently this element doesn't require resources. */
2157 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2158 g_value_set_boolean(ret, TRUE);
2159 g_object_unref(element);
2163 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
2164 ms_error("Failed to acquire resource for node [%s]", node->name);
2165 g_object_unref(element);
2169 g_value_set_boolean(ret, TRUE);
2171 g_object_unref(element);
2178 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
2180 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2181 media_streamer_node_s *node = NULL;
2182 GstElement *element = NULL;
2186 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2187 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2188 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2190 g_value_set_boolean(ret, FALSE);
2192 element = GST_ELEMENT(g_value_get_object(item));
2193 g_object_ref(element);
2195 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2196 GST_ELEMENT_NAME(element));
2198 /* If we fail to find corresponding node inside streamer
2199 then apparently this element doesn't require resources. */
2200 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2201 g_value_set_boolean(ret, TRUE);
2202 g_object_unref(element);
2206 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
2207 ms_error("Failed to release resource for node [%s]", node->name);
2208 g_object_unref(element);
2212 g_value_set_boolean(ret, TRUE);
2214 g_object_unref(element);
2221 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
2223 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2224 media_streamer_node_s *node = NULL;
2225 GstElement *element = NULL;
2226 gboolean allowed = FALSE;
2230 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2231 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2232 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2233 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2235 element = GST_ELEMENT(g_value_get_object(item));
2236 g_object_ref(element);
2238 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2239 GST_ELEMENT_NAME(element));
2241 /* If we fail to find corresponding node inside streamer
2242 then apparently this element doesn't require resources. */
2243 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2244 g_value_set_boolean(ret, TRUE);
2245 g_object_unref(element);
2249 if (ms_node_dpm_policy_check(node, &allowed)) {
2250 ms_error("Failed to check DPM policy for node [%s]", node->name);
2251 /* Note that it should be TRUE(allowed) if the DPM API failed. */
2252 g_value_set_boolean(ret, TRUE);
2253 g_object_unref(element);
2257 g_value_set_boolean(ret, allowed);
2259 g_object_unref(element);