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, MS_PARAM_VIDEO_IN_FORMAT) ||
188 !strcmp(param->param_name, MS_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_node_check_privileges(media_streamer_node_s *node)
375 int ret = MEDIA_STREAMER_ERROR_NONE;
377 char *privilege = NULL;
379 char smackLabel[SMACK_LABEL_LEN + 1];
381 cynara *cynara_h = NULL;
385 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
387 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
388 switch (node->subtype) {
389 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
390 privilege = "http://tizen.org/privilege/internet";
392 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
393 privilege = "http://tizen.org/privilege/internet";
395 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
396 privilege = "http://tizen.org/privilege/camera";
398 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
399 privilege = "http://tizen.org/privilege/recorder";
401 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
402 privilege = "http://tizen.org/privilege/camera";
405 ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
410 if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
411 switch (node->subtype) {
412 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
413 privilege = "http://tizen.org/privilege/internet";
416 ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
421 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
422 privilege = "http://tizen.org/privilege/internet";
424 /* Skip checking for privilege permission in case of other types of Nodes */
425 if (privilege == NULL)
428 if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
429 ms_error("Failed to initialize cynara structure\n");
430 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
433 bzero(smackLabel, SMACK_LABEL_LEN + 1);
435 /* Getting smack label */
436 opened_file = fopen("/proc/self/attr/current", "r");
437 if (opened_file == NULL) {
438 ms_error("Failed to open /proc/self/attr/current\n");
439 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
441 ret_val = fread(smackLabel, sizeof(smackLabel), 1, opened_file);
444 ms_error("Failed to read /proc/self/attr/current\n");
445 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
449 snprintf(uid, sizeof(uid), "%d", getuid());
450 ms_info("%s %s %s\n", smackLabel, uid, privilege);
452 /* Checking with cynara for current session */
453 ret_val = cynara_check(cynara_h, smackLabel, "", uid, privilege);
454 ms_info("Cynara_check [%d] ", ret_val);
457 case CYNARA_API_ACCESS_ALLOWED:
458 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
460 case CYNARA_API_ACCESS_DENIED:
462 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
463 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
467 cynara_finish(cynara_h);
474 static int __ms_node_check_feature(media_streamer_node_s *node)
476 bool enabled = FALSE;
480 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
482 switch (node->type) {
483 case MEDIA_STREAMER_NODE_TYPE_WEBRTC:
484 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
485 ms_info("wifi status = %d", enabled);
487 return MEDIA_STREAMER_ERROR_NONE;
489 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
490 ms_info("telephony status = %d", enabled);
492 return MEDIA_STREAMER_ERROR_NONE;
494 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
495 ms_info("ethernet status = %d", enabled);
497 return MEDIA_STREAMER_ERROR_NONE;
499 ms_error("None of [%s] [%s] [%s] features is enabled", _FEATURE_NAME_WIFI, _FEATURE_NAME_TELEPHONY, _FEATURE_NAME_ETHERNET);
500 return MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
502 ms_debug("For current node type[%d], feature is not needed", node->type);
508 return MEDIA_STREAMER_ERROR_NONE;
511 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
513 int ret = MEDIA_STREAMER_ERROR_NONE;
514 GstCaps *sink_caps = NULL;
515 GstCaps *src_caps = NULL;
519 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
521 ret = __ms_node_check_privileges(node);
522 if (ret != MEDIA_STREAMER_ERROR_NONE) {
523 ms_error("Failed to get privilege for this node type(%d)", node->type);
527 ret = __ms_node_check_feature(node);
528 if (ret != MEDIA_STREAMER_ERROR_NONE) {
529 ms_error("Failed to get feature for this node type(%d)", node->type);
533 sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt, nodes_info[node->type].default_name) : NULL;
534 src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt, nodes_info[node->type].default_name) : NULL;
536 node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
538 ms_info("Creating node with info: klass_name[%s]; default[%s]",
539 plug_info.info->klass_name, plug_info.info->default_name);
541 node->gst_element = ms_node_element_create(&plug_info, node->type);
542 if (node->gst_element)
543 node->name = gst_element_get_name(node->gst_element);
545 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
548 gst_caps_unref(src_caps);
551 gst_caps_unref(sink_caps);
558 /* This signal callback is called when appsrc needs data, we add an idle handler
559 * to the mainloop to start pushing data into the appsrc */
560 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
562 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
563 media_streamer_callback_s *src_callback = NULL;
564 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
568 ms_retm_if(ms_src == NULL, "data is NULL");
569 ms_retm_if(pipeline == NULL, "pipeline is NULL");
571 if (ms_src->callbacks_structure != NULL) {
572 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
573 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
574 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
580 /* This callback is called when appsrc has enough data and we can stop sending.
581 * We remove the idle handler from the mainloop */
582 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
584 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
585 media_streamer_callback_s *src_callback = NULL;
586 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
590 ms_retm_if(ms_src == NULL, "data is NULL");
591 ms_retm_if(pipeline == NULL, "pipeline is NULL");
593 if (ms_src->callbacks_structure != NULL) {
594 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
595 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
596 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
602 static int __ms_src_node_check_feature(media_streamer_node_s *node)
604 int ret = MEDIA_STREAMER_ERROR_NONE;
605 bool enabled = FALSE;
606 bool supported = FALSE;
610 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
612 switch (node->subtype) {
613 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
614 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
615 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
616 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
617 ms_info("wifi status = %d", enabled);
621 ms_error("SYSTEM_INFO_ERROR");
624 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
625 ms_info("telephony status = %d", enabled);
629 ms_error("SYSTEM_INFO_ERROR");
632 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
633 ms_info("ethernet status = %d", enabled);
637 ms_error("SYSTEM_INFO_ERROR");
640 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
642 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
643 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
644 ms_info("microphone status = %d", enabled);
648 ms_error("SYSTEM_INFO_ERROR");
651 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
653 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
654 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
655 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
656 ms_info("camera status = %d", enabled);
660 ms_error("SYSTEM_INFO_ERROR");
663 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
666 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
675 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
677 int ret = MEDIA_STREAMER_ERROR_NONE;
678 bool enabled = FALSE;
679 bool supported = FALSE;
683 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
685 switch (node->subtype) {
686 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
687 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
688 /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
689 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
690 ms_info("wifi status = %d", enabled);
694 ms_error("SYSTEM_INFO_ERROR");
697 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
698 ms_info("telephony status = %d", enabled);
702 ms_error("SYSTEM_INFO_ERROR");
705 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
706 ms_info("ethernet status = %d", enabled);
710 ms_error("SYSTEM_INFO_ERROR");
713 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
716 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
725 int ms_src_node_create(media_streamer_node_s *node)
727 int ret = MEDIA_STREAMER_ERROR_NONE;
728 char *plugin_name = NULL;
732 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
734 ret = __ms_node_check_privileges(node);
735 if (ret != MEDIA_STREAMER_ERROR_NONE) {
736 ms_error("Error getting privileges for Src Node");
740 ret = __ms_src_node_check_feature(node);
741 if (ret != MEDIA_STREAMER_ERROR_NONE) {
742 ms_error("Error getting feature for Src Node");
746 switch (node->subtype) {
747 case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
748 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
749 node->gst_element = ms_element_create(plugin_name, NULL);
751 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
752 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
753 node->gst_element = ms_element_create(plugin_name, NULL);
755 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
756 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
757 node->gst_element = ms_element_create(plugin_name, NULL);
759 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
760 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
761 node->gst_element = ms_element_create(plugin_name, NULL);
763 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
764 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
765 node->gst_element = ms_element_create(plugin_name, NULL);
767 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
768 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
769 node->gst_element = ms_element_create(plugin_name, NULL);
771 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
772 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
773 node->gst_element = ms_element_create(plugin_name, NULL);
775 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
776 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
777 node->gst_element = ms_element_create(plugin_name, NULL);
779 case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
780 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
781 node->gst_element = ms_element_create(plugin_name, NULL);
782 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
783 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
784 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
786 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
787 node->gst_element = ms_adaptive_element_create();
790 ms_error("Error: invalid Src node Type [%d]", node->subtype);
794 MS_SAFE_FREE(plugin_name);
796 if (node->gst_element == NULL)
797 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
799 node->name = gst_element_get_name(node->gst_element);
801 ret = ms_node_dpm_policy_init(node);
802 if (MEDIA_STREAMER_ERROR_NONE != ret) {
803 ms_error("Failed to init DPM policy for node [%s]", node->name);
812 /* The appsink has received a buffer */
813 static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
815 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
816 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
817 media_streamer_sink_data_ready_cb data_ready_cb = NULL;
821 ms_retm_if(ms_sink == NULL, "data is NULL");
823 if (ms_sink->callbacks_structure != NULL) {
824 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
825 data_ready_cb = (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
828 data_ready_cb((media_streamer_node_h) ms_sink, sink_callbacks->data_ready_cb.user_data);
835 /* The appsink has got eos */
836 static void sink_eos(GstElement *sink, gpointer *data)
838 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
839 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
840 media_streamer_sink_eos_cb eos_cb = NULL;
844 ms_retm_if(ms_sink == NULL, "data is NULL");
846 if (ms_sink->callbacks_structure != NULL) {
847 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
848 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
851 eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
858 int ms_sink_node_create(media_streamer_node_s *node)
860 int ret = MEDIA_STREAMER_ERROR_NONE;
861 char *plugin_name = NULL;
865 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
867 ret = __ms_node_check_privileges(node);
868 if (ret != MEDIA_STREAMER_ERROR_NONE) {
869 ms_error("Error getting privileges for Sink Node");
873 ret = __ms_sink_node_check_feature(node);
874 if (ret != MEDIA_STREAMER_ERROR_NONE) {
875 ms_error("Error getting feature for Sink Node");
879 switch (node->subtype) {
880 case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
881 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
882 node->gst_element = ms_element_create(plugin_name, NULL);
884 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
885 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
886 node->gst_element = ms_element_create(plugin_name, NULL);
888 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
889 ms_error("Error: not implemented yet");
891 case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
892 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
893 node->gst_element = ms_element_create(plugin_name, NULL);
895 case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
896 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
897 node->gst_element = ms_element_create(plugin_name, NULL);
899 case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
900 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
901 node->gst_element = ms_element_create(plugin_name, NULL);
903 case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
904 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
905 node->gst_element = ms_element_create(plugin_name, NULL);
906 if (node->gst_element) {
907 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
908 ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
909 ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
912 case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
913 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
914 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
916 if (g_strrstr(plugin_name, "hlssink")) {
917 g_object_set(G_OBJECT(node->gst_element),
919 "playlist-length", 0, NULL);
923 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
927 MS_SAFE_FREE(plugin_name);
929 if (node->gst_element == NULL)
930 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
932 node->name = gst_element_get_name(node->gst_element);
939 void ms_node_destroy(media_streamer_node_s *node)
941 gchar *node_name = NULL;
945 ms_retm_if(node == NULL, "node is NULL");
946 node_name = g_strdup(node->name);
948 /* Disconnects and clean all node signals */
949 g_list_free_full(node->sig_list, ms_signal_destroy);
951 /* Deinitialize policy manager */
952 if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
953 ms_error("Failed to deinitialize DPM policy");
955 MS_SAFE_UNREF(node->gst_element);
956 MS_SAFE_FREE(node->name);
957 MS_SAFE_FREE(node->callbacks_structure);
960 ms_info("Node [%s] has been destroyed", node_name);
961 MS_SAFE_GFREE(node_name);
966 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
968 int ret = MEDIA_STREAMER_ERROR_NONE;
969 GstElement *bin = NULL;
973 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
974 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
976 ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
978 switch (node->type) {
979 case MEDIA_STREAMER_NODE_TYPE_SRC:
980 bin = ms_streamer->src_bin;
982 case MEDIA_STREAMER_NODE_TYPE_SINK:
983 bin = ms_streamer->sink_bin;
986 /* Another elements will be add into transform bin */
987 bin = ms_streamer->transform_bin;
991 if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
992 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
993 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1001 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
1005 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1006 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1007 ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
1009 if (g_hash_table_contains(nodes_table, node->name)) {
1010 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
1011 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1013 if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
1014 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
1015 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1018 ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1022 return MEDIA_STREAMER_ERROR_NONE;
1025 int ms_node_remove_from_table(GHashTable *nodes_table, media_streamer_node_s *node)
1027 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1028 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1030 /* Removal element of this node from bin will be performed
1031 * in the callback - ms_node_remove_from_table_cb(). */
1032 if (!g_hash_table_remove(nodes_table, (gpointer) node->name)) {
1033 ms_error("Failed to remove node [%s] from table", node->name);
1034 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1037 return MEDIA_STREAMER_ERROR_NONE;
1040 void ms_node_remove_from_table_cb(void *data)
1042 media_streamer_node_s *node = (media_streamer_node_s *) data;
1046 ms_retm_if(node == NULL, "data is NULL");
1048 if (ms_element_unlink(node->gst_element)) {
1049 node->linked_by_user = FALSE;
1050 node->parent_streamer = NULL;
1051 ms_bin_remove_element(node->gst_element);
1052 ms_info("Node [%s] removed from Media Streamer", node->name);
1054 ms_error("Failed to unlink element of node [%s]", node->name);
1060 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1062 gboolean ret = FALSE;
1066 if (!src_pad || gst_pad_is_linked(src_pad))
1069 GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1070 if (gst_caps_is_any(src_caps))
1073 gst_caps_unref(src_caps);
1080 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1086 for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1087 if (it_klass == element_type) {
1088 ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1095 return &nodes_info[it_klass];
1098 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1100 gboolean ret = FALSE;
1102 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1103 ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1107 ret = ms_element_lock_state(item, g_ret, user_data);
1114 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1116 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1117 GstElement *src_element = NULL;
1118 GstElement *found_element = NULL;
1119 media_streamer_node_s *node = NULL;
1120 GstPad *src_pad = NULL;
1124 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1125 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1126 ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1128 src_element = GST_ELEMENT(g_value_get_object(item));
1129 g_object_ref(src_element);
1130 g_value_set_boolean(ret, FALSE);
1132 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1133 GST_ELEMENT_NAME(src_element));
1135 /* If we fail to find corresponding node inside streamer
1136 then apparently this element doesn't require resources. */
1137 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1138 g_value_set_boolean(ret, TRUE);
1139 g_object_unref(src_element);
1143 ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1145 src_pad = gst_element_get_static_pad(src_element, "src");
1147 if (__ms_src_need_typefind(src_pad)) {
1148 ms_find_type(ms_streamer, src_element);
1149 MS_SAFE_UNREF(src_element);
1151 /* Check the source element`s pad type */
1152 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1153 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1154 if (gst_pad_is_linked(src_pad)) {
1155 MS_SAFE_UNREF(src_pad);
1156 MS_SAFE_UNREF(src_element);
1157 g_value_set_boolean(ret, TRUE);
1160 /* It is media streamer Server part */
1161 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1162 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1163 GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1164 g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1165 gst_caps_unref(videoCaps);
1167 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1168 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1169 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1171 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1172 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1173 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1174 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1176 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1177 MS_SAFE_UNREF(found_element);
1179 MS_SAFE_UNREF(src_pad);
1181 g_value_set_boolean(ret, TRUE);
1188 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1190 char *manifest_src_name = NULL;
1191 gchar *location = NULL;
1192 GstElement *manifest_src = NULL;
1194 const char *uri = NULL;
1195 gchar *protocol = NULL;
1199 ms_retvm_if(!node, NULL, "node is NULL");
1201 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1202 uri = g_value_get_string(val);
1203 protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1205 if (protocol && g_strrstr(protocol, "http")) {
1206 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1207 location = g_strdup(uri);
1208 } else if (protocol && g_strrstr(protocol, "file")) {
1209 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1210 location = gst_uri_get_location(uri);
1212 ms_error("Unsupported URI protocol... Check URI is file path");
1213 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1214 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1215 location = g_strdup(uri);
1218 ms_error("URI is not valid file path");
1224 if (manifest_src_name == NULL) {
1225 LOGE("Error empty manifest source name for adaptive source");
1230 manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1231 g_free(manifest_src_name);
1233 if (manifest_src == NULL) {
1234 LOGE("Error creating manifest source for adaptive source");
1239 g_object_set(manifest_src, "location", location, NULL);
1244 return manifest_src;
1247 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1249 char *plugin_name = NULL;
1250 GstElement *manifest_src = NULL;
1251 GstElement *plugin_elem = NULL;
1252 gboolean res = FALSE;
1257 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1260 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1261 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1262 ms_info("Creating [%s] element", plugin_name);
1263 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1264 g_free(plugin_name);
1265 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1266 "Error creating element for adaptive source");
1268 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1269 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1270 "Error adding adaptive element to bin for adaptive source");
1273 manifest_src = __ms_manifest_src_create(node);
1274 ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1275 "Error creating manifest source for adaptive source");
1277 res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1278 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1279 "Error adding manifest source to bin for adaptive source");
1282 res = gst_element_link(manifest_src, plugin_elem);
1283 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1284 "Error linking manifest source and element for adaptive source");
1287 gp = gst_element_get_static_pad(node->gst_element, "src");
1288 ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1289 "Error getting source pad for adaptive source");
1292 g_signal_connect_object(plugin_elem, "pad-added",
1293 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1295 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1296 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1301 return MEDIA_STREAMER_ERROR_NONE;
1304 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1306 int err_code = MEDIA_STREAMER_ERROR_NONE;
1307 gchar *playlist_location = NULL;
1308 char *playlist_dir = NULL;
1313 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1314 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1315 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1317 /* Create and start http server */
1318 err_code = ms_http_server_create(&ms_streamer->http_server);
1319 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1320 ms_error("Failed to create http server during prepare");
1324 ms_info("Starting http server");
1325 /* FIXME: find out how to set default port */
1326 err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1327 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1328 ms_error("Failed to start http server during prepare. Destroying http server");
1329 ms_http_server_destroy(ms_streamer->http_server);
1333 g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1334 if (!playlist_location) {
1335 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1336 ms_error("Failed to get playlist location");
1337 ms_http_server_destroy(ms_streamer->http_server);
1341 split = strrchr(playlist_location, '/');
1342 playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1344 ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1346 MS_SAFE_GFREE(playlist_location);
1356 int ms_rtp_node_prepare(media_streamer_node_s *node)
1358 GstElement *rtpbin = NULL;
1359 GstElement *rtp_el = NULL;
1360 GstElement *rtcp_el = NULL;
1362 const char *host = NULL;
1363 GstElement *video_filter = NULL;
1364 GstCaps *video_caps = NULL;
1365 GstGhostPad *ghost_pad = NULL;
1366 GstElement *audio_filter = NULL;
1367 GstCaps *audio_caps = NULL;
1371 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1373 rtpbin = ms_element_create("rtpbin", "rtpbin");
1374 ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1376 if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1377 MS_SAFE_UNREF(rtpbin);
1378 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1381 ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1383 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1384 host = g_value_get_string(val);
1386 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1387 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1388 rtp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtp");
1389 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1391 rtcp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtcp");
1392 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1394 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1395 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1396 ms_error("Failed to link pads for rtpbin sink pad 0");
1397 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1400 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1401 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1403 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_VIDEO_IN_FORMAT);
1404 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1407 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1408 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1409 rtp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtp");
1410 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1412 rtcp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtcp");
1413 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1415 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1416 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1417 ms_error("Failed to link pads for rtpbin sink pad 1");
1418 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1421 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1422 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1424 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_AUDIO_IN_FORMAT);
1425 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1428 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1429 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1430 rtp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtp");
1431 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1433 rtcp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtcp");
1434 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1436 video_filter = ms_element_create("capsfilter", NULL);
1437 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1439 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1440 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1441 gst_caps_unref(video_caps);
1443 gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0");
1445 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_VIDEO_IN);
1447 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1448 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_VIDEO_IN);
1451 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1452 !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1453 ms_error("Failed to link pads for rtpbin src pad 0");
1454 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1457 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1458 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1459 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1460 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1461 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1462 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1465 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1466 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1467 rtp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtp");
1468 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1470 rtcp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtcp");
1471 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1473 audio_filter = ms_element_create("capsfilter", NULL);
1474 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1476 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1477 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1479 gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1");
1481 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_AUDIO_IN);
1483 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1484 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_AUDIO_IN);
1487 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1488 !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1489 ms_error("Failed to link pads for rtpbin src pad 1");
1490 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1493 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1494 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1495 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1496 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1497 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1498 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1501 ms_generate_dots(node->gst_element, "rtp_prepared");
1505 return MEDIA_STREAMER_ERROR_NONE;
1508 static int __ms_webrtc_prepare_ghost_sink_pad(GstElement *webrtc_container, GstElement *webrtcbin, const char *capsfilter_name)
1510 int ret = MEDIA_STREAMER_ERROR_NONE;
1512 GstGhostPad *ghost_pad_in = NULL;
1513 GstPad *filter_sink_pad = NULL;
1515 gchar *req_pad_name;
1516 const gchar *pad_name;
1518 ms_retvm_if(!webrtc_container, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
1519 ms_retvm_if(!webrtcbin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtcbin is NULL");
1520 ms_retvm_if(!capsfilter_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "capsfilter_name is NULL");
1522 if (g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) &&
1523 g_strcmp0(capsfilter_name, _WEBRTC_VIDEO_CAPSFILTER))
1524 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1526 pad_name = !g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) ? MS_PAD_AUDIO_IN : MS_PAD_VIDEO_IN;
1528 if (!(filter = ms_find_element_in_bin_by_name(webrtc_container, capsfilter_name))) {
1529 ms_debug("No need to export the ghost sink pad for [%s]", pad_name);
1530 return MEDIA_STREAMER_ERROR_NONE;
1533 if (!(ghost_pad_in = (GstGhostPad *)gst_element_get_static_pad(webrtc_container, pad_name))) {
1534 ms_error("Failed to get ghost pad for webrtc_container");
1535 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1538 if (!gst_pad_is_linked((GstPad *)ghost_pad_in)) {
1539 ms_error("[%s] is set media format but not linked to peer node", pad_name);
1540 MS_SAFE_UNREF(ghost_pad_in);
1541 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1544 ms_info("%s is found, link it with webrtcbin and export the ghost pad[%s] of webrtc_container",
1545 capsfilter_name, pad_name);
1547 if (!(req_pad = gst_element_get_request_pad(webrtcbin, "sink_%u"))) {
1548 ms_error("Failed to get request pad");
1549 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1551 if (!(req_pad_name = gst_pad_get_name(req_pad))) {
1552 ms_error("Failed to get request pad name");
1553 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1555 if (!gst_element_link_pads(filter, "src", webrtcbin, req_pad_name)) {
1556 ms_error("Failed to link pads, %s - webrtcbin", capsfilter_name);
1557 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1561 if (!(filter_sink_pad = gst_element_get_static_pad(filter, "sink"))) {
1562 ms_error("Failed to get capsfilter sink pad in webrtc_container");
1563 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1566 if (!gst_ghost_pad_set_target(ghost_pad_in, filter_sink_pad)) {
1567 ms_info("Failed to gst_ghost_pad_set_target() for %s", pad_name);
1568 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1573 MS_SAFE_GFREE(req_pad_name);
1574 MS_SAFE_UNREF(filter_sink_pad);
1575 MS_SAFE_UNREF(ghost_pad_in);
1580 GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
1582 GstElement *webrtcbin = NULL;
1583 node_info_s *node_klass_type = NULL;
1585 ms_retvm_if(webrtc_node == NULL, NULL, "webrtc_node is NULL");
1586 ms_retvm_if(webrtc_node->gst_element == NULL, NULL, "webrtc_container is NULL");
1590 node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
1591 webrtcbin = ms_find_element_in_bin_by_type(webrtc_node->gst_element, node_klass_type);
1593 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
1600 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1602 int ret = MEDIA_STREAMER_ERROR_NONE;
1603 GstElement *webrtcbin = NULL;
1604 GObject *send_channel = NULL;
1605 gboolean is_offerer = FALSE;
1606 media_streamer_webrtc_callbacks_s *_callbacks = NULL;
1610 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1611 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1612 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
1614 if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(node)))
1615 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1617 _callbacks = (media_streamer_webrtc_callbacks_s *) node->callbacks_structure;
1618 if (!_callbacks || !(_callbacks->message_cb.callback)) {
1619 ms_error("message callback should be set before preparing");
1620 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1623 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_AUDIO_CAPSFILTER)))
1625 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
1628 if (ms_webrtc_node_is_offerer(node, &is_offerer) != MEDIA_STREAMER_ERROR_NONE) {
1629 ms_error("Failed to get peer type");
1630 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1634 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
1636 ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
1637 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
1638 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-connection-state", G_CALLBACK(ms_webrtcbin_notify_ice_connection_state_cb), node);
1640 if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
1641 ms_error("Failed to set state to READY");
1642 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1645 g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
1647 ms_info("data channel(%p) for sending is created", send_channel);
1649 ms_warning("Failed to create data channel");
1651 ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
1652 ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
1654 ms_generate_dots(node->gst_element, "webrtc_prepared");
1658 return MEDIA_STREAMER_ERROR_NONE;
1662 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1666 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1667 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1669 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
1670 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
1674 return MEDIA_STREAMER_ERROR_NONE;
1677 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
1679 GParamSpec *param_spec;
1684 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1685 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1687 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1688 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1689 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1690 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
1691 ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
1692 *param_list = g_list_append(*param_list, &(param_table[it_param]));
1695 ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
1699 return MEDIA_STREAMER_ERROR_NONE;
1702 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
1704 int ret = MEDIA_STREAMER_ERROR_NONE;
1705 Evas_Object *obj = NULL;
1706 media_streamer_wl_info_s wl_info;
1708 obj = (Evas_Object *)param_value;
1710 /* get wayland parent id */
1711 if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
1712 LOGE("failed to get wayland info");
1713 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1716 LOGD("wayland global surface id : %d", wl_info.parent_id);
1718 gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
1723 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
1726 int ret = MEDIA_STREAMER_ERROR_NONE;
1730 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1731 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1732 ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
1734 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1735 ret = __ms_rtp_node_set_property(node, param, param_value);
1740 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
1741 ret = __ms_webrtc_node_set_property(node, param, param_value);
1746 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1747 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
1748 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
1753 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
1754 int camera_id = (int)strtol(param_value, NULL, 10);
1755 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
1756 g_object_set(node->gst_element, param->origin_name, camera_id, NULL);
1757 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1758 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1759 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1760 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1761 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1762 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1763 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1764 g_object_set(node->gst_element, param->origin_name, (int)strtol(param_value, NULL, 10), NULL);
1765 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1766 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1767 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1768 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1769 g_object_set(node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
1770 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
1771 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
1772 ret = ms_util_uri_path_check(param_value);
1773 if (ret != MEDIA_STREAMER_ERROR_NONE)
1776 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1777 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1778 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1779 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1780 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1781 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1782 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1783 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1784 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY)) {
1785 ret = __ms_node_set_display(node, param_value);
1787 ms_info("Can not set parameter [%s] in the node [%s]", param->param_name, node->name);
1788 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1796 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
1798 int ret = MEDIA_STREAMER_ERROR_NONE;
1799 GList *p_list = NULL;
1800 int written_count = 0;
1801 param_s *param = NULL;
1802 GList *list_iter = NULL;
1803 char *string_val = NULL;
1807 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1808 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1810 ret = __ms_node_get_param_list(node, &p_list);
1811 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1812 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1813 param = (param_s *)list_iter->data;
1814 if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
1815 ret = ms_node_set_param_value(node, param, string_val);
1816 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1819 ms_error("failed to set param");
1825 g_list_free(p_list);
1827 ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
1828 if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
1829 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1836 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
1838 int ret = MEDIA_STREAMER_ERROR_NONE;
1839 GList *p_list = NULL;
1840 param_s *param = NULL;
1841 GList *list_iter = NULL;
1842 char *string_val = NULL;
1846 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1847 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1849 ret = __ms_node_get_param_list(node, &p_list);
1850 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1851 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1852 param = (param_s *)list_iter->data;
1854 if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
1855 bundle_add_str(param_list, param->param_name, string_val);
1856 MS_SAFE_FREE(string_val);
1861 g_list_free(p_list);
1868 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
1870 GParamSpec *param_spec;
1871 gboolean found_param = FALSE;
1876 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1877 ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
1878 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1880 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1881 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
1882 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1883 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1884 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name) ||
1885 __ms_webrtc_node_has_property(node, param_table[it_param].origin_name)) {
1886 *param = &(param_table[it_param]);
1887 ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
1893 ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
1897 return MEDIA_STREAMER_ERROR_NONE;
1900 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
1902 int ret = MEDIA_STREAMER_ERROR_NONE;
1903 char *string_val = NULL;
1904 GParamSpec *param_spec = NULL;
1905 GValue value = G_VALUE_INIT;
1909 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1910 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1911 ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
1913 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
1914 ret = __ms_rtp_node_get_property(node, param, &value);
1915 else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1916 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
1917 ret = __ms_adaptive_src_node_get_property(node, param, &value);
1919 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
1921 g_value_init(&value, param_spec->value_type);
1922 g_object_get_property(G_OBJECT(node->gst_element), param->origin_name, &value);
1924 ms_info("Got parameter [%s] for node [%s] with description [%s]", param->param_name, node->name, g_param_spec_get_blurb(param_spec));
1926 ms_error("There is no parameter [%s] for node [%s]", param->origin_name, node->name);
1927 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1931 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID) ||
1932 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1933 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1934 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1935 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
1936 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
1937 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
1938 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
1939 if (G_VALUE_HOLDS_INT(&value))
1940 string_val = g_strdup_printf("%d", g_value_get_int(&value));
1942 string_val = g_strdup_printf("%u", g_value_get_uint(&value));
1943 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1944 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1945 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1946 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1947 string_val = g_strdup(g_value_get_boolean(&value) ? "true" : "false");
1948 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI) ||
1949 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1950 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1951 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1952 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1953 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1954 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1955 string_val = g_value_dup_string(&value);
1956 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1957 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1958 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1959 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1960 string_val = g_strdup_printf("%d", g_value_get_enum(&value));
1963 *string_value = strdup(string_val);
1966 g_value_reset(&value);
1967 g_value_unset(&value);
1974 static int __ms_rtp_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
1976 int ret = MEDIA_STREAMER_ERROR_NONE;
1977 media_format_mimetype_e mime;
1978 gchar *rtp_caps_str = NULL;
1980 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1981 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
1982 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
1983 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
1987 /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
1988 if (g_strrstr(pad_name, MS_PAD_VIDEO_IN)) {
1989 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
1990 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1991 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));
1992 param_s param = {MS_PARAM_VIDEO_IN_FORMAT, MS_PARAM_VIDEO_IN_FORMAT};
1993 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
1995 } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
1996 int audio_channels, audio_samplerate;
1997 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
1998 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1999 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");
2000 param_s param = {MS_PARAM_AUDIO_IN_FORMAT, MS_PARAM_AUDIO_IN_FORMAT};
2001 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
2004 ms_error("[%s]'s pad [%s] can't be set with the given format", GST_ELEMENT_NAME(node->gst_element), pad_name);
2005 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2007 MS_SAFE_GFREE(rtp_caps_str);
2012 static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2014 int ret = MEDIA_STREAMER_ERROR_NONE;
2015 media_format_mimetype_e mime;
2016 const gchar *encoding_name = NULL;
2017 const gchar *capsfilter_name = NULL;
2018 gchar *caps_str = NULL;
2019 gchar *media = NULL;
2021 GstCaps *caps = NULL;
2022 GstElement *capsfilter = NULL;
2024 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2025 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2026 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2027 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2031 if (!g_strrstr(pad_name, MS_PAD_VIDEO_IN) && !g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
2032 ms_error("Not supported pad_name(%s)", pad_name);
2033 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2036 if (g_strrstr(pad_name, MS_PAD_VIDEO_IN) &&
2037 !media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2040 capsfilter_name = _WEBRTC_VIDEO_CAPSFILTER;
2041 } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN) &&
2042 !media_format_get_audio_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2045 capsfilter_name = _WEBRTC_AUDIO_CAPSFILTER;
2047 ms_error("Invalid media format for pad_name(%s)", pad_name);
2048 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2051 encoding_name = ms_convert_mime_to_rtp_format(mime);
2052 caps = gst_caps_new_simple("application/x-rtp",
2053 "media", G_TYPE_STRING, media,
2054 "encoding-name", G_TYPE_STRING, encoding_name,
2055 "payload", G_TYPE_INT, payload, NULL);
2057 if (!(capsfilter = ms_find_element_in_bin_by_name(node->gst_element, capsfilter_name))) {
2058 ms_debug("Create %s", capsfilter_name);
2060 if (!(capsfilter = ms_element_create("capsfilter", capsfilter_name))) {
2061 ms_error("Failed to create capsfilter element: %s", capsfilter_name);
2062 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2064 if (!ms_bin_add_element(node->gst_element, capsfilter, FALSE)) {
2065 ms_error("Failed to add capsfilter(%s) to webrtc_container", capsfilter_name);
2066 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2070 g_object_set(G_OBJECT(capsfilter), "caps", (GValue *)caps, NULL);
2072 caps_str = gst_caps_to_string(caps);
2073 ms_info("[%s] is set to [%s]", caps_str, capsfilter_name);
2074 MS_SAFE_GFREE(caps_str);
2076 gst_caps_unref(caps);
2081 static int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2083 gboolean can_accept = FALSE;
2084 GstElement *element = NULL;
2085 GstCaps *fmt_caps = NULL;
2086 GstElementFactory *factory = NULL;
2087 GstPad *node_pad = NULL;
2089 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2090 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2091 ms_retvm_if(!pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2092 ms_retvm_if(!fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2094 element = node->gst_element;
2096 fmt_caps = ms_create_caps_from_fmt(fmt, nodes_info[node->type].default_name);
2097 ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps");
2099 factory = gst_element_get_factory(element);
2100 node_pad = gst_element_get_static_pad(element, pad_name);
2102 gst_caps_unref(fmt_caps);
2103 ms_error("Failed to gst_element_get_static_pad(), pad_name[%s]", pad_name);
2104 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2107 if (GST_PAD_IS_SRC(node_pad))
2108 can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps);
2109 else if (GST_PAD_IS_SINK(node_pad))
2110 can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps);
2112 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2114 MS_SAFE_UNREF(node_pad);
2117 gst_caps_unref(fmt_caps);
2118 ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name);
2119 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2122 MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2123 gst_caps_unref(fmt_caps);
2125 ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2127 return MEDIA_STREAMER_ERROR_NONE;
2130 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2132 int ret = MEDIA_STREAMER_ERROR_NONE;
2136 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2137 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2138 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2139 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2141 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
2142 ret = __ms_rtp_node_set_pad_format(node, pad_name, fmt);
2143 else if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
2144 ret = __ms_webrtc_node_set_pad_format(node, pad_name, fmt);
2146 ret = __ms_node_set_pad_format(node, pad_name, fmt);
2153 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
2155 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2156 media_streamer_node_s *node = NULL;
2157 GstElement *element = NULL;
2161 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2162 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2163 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2165 g_value_set_boolean(ret, FALSE);
2167 element = GST_ELEMENT(g_value_get_object(item));
2168 g_object_ref(element);
2170 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2171 GST_ELEMENT_NAME(element));
2173 /* If we fail to find corresponding node inside streamer
2174 then apparently this element doesn't require resources. */
2175 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2176 g_value_set_boolean(ret, TRUE);
2177 g_object_unref(element);
2181 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
2182 ms_error("Failed to acquire resource for node [%s]", node->name);
2183 g_object_unref(element);
2187 g_value_set_boolean(ret, TRUE);
2189 g_object_unref(element);
2196 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
2198 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2199 media_streamer_node_s *node = NULL;
2200 GstElement *element = NULL;
2204 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2205 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2206 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2208 g_value_set_boolean(ret, FALSE);
2210 element = GST_ELEMENT(g_value_get_object(item));
2211 g_object_ref(element);
2213 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2214 GST_ELEMENT_NAME(element));
2216 /* If we fail to find corresponding node inside streamer
2217 then apparently this element doesn't require resources. */
2218 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2219 g_value_set_boolean(ret, TRUE);
2220 g_object_unref(element);
2224 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
2225 ms_error("Failed to release resource for node [%s]", node->name);
2226 g_object_unref(element);
2230 g_value_set_boolean(ret, TRUE);
2232 g_object_unref(element);
2239 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
2241 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2242 media_streamer_node_s *node = NULL;
2243 GstElement *element = NULL;
2244 gboolean allowed = FALSE;
2248 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2249 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2250 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2251 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2253 element = GST_ELEMENT(g_value_get_object(item));
2254 g_object_ref(element);
2256 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2257 GST_ELEMENT_NAME(element));
2259 /* If we fail to find corresponding node inside streamer
2260 then apparently this element doesn't require resources. */
2261 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2262 g_value_set_boolean(ret, TRUE);
2263 g_object_unref(element);
2267 if (ms_node_dpm_policy_check(node, &allowed)) {
2268 ms_error("Failed to check DPM policy for node [%s]", node->name);
2269 /* Note that it should be TRUE(allowed) if the DPM API failed. */
2270 g_value_set_boolean(ret, TRUE);
2271 g_object_unref(element);
2275 g_value_set_boolean(ret, allowed);
2277 g_object_unref(element);
2284 int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
2287 const gchar *type = NULL;
2289 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
2290 ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
2292 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2293 ms_error("Invalid node type");
2294 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2297 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
2299 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
2300 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2303 if (!(type = g_value_get_string(val))) {
2304 ms_error("Failed to g_value_get_string()");
2305 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2308 ms_info("peer type is [%s]", type);
2310 *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
2312 return MEDIA_STREAMER_ERROR_NONE;