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>
19 #include <sys/smack.h>
21 #include <gst/video/videooverlay.h>
22 #include "media_streamer_node.h"
23 #include "media_streamer_node_resources.h"
24 #include "media_streamer_node_dpm_policy.h"
25 #include "media_streamer_util.h"
26 #include "media_streamer_gst.h"
27 #include "media_streamer_gst_webrtc.h"
29 #define SMACK_LABEL_LEN 255
30 #define DEFAULT_URI_SCHEME_LENGTH 10
32 #define _FEATURE_NAME_WIFI "http://tizen.org/feature/network.wifi"
33 #define _FEATURE_NAME_TELEPHONY "http://tizen.org/feature/network.telephony"
34 #define _FEATURE_NAME_ETHERNET "http://tizen.org/feature/network.ethernet"
35 #define _FEATURE_NAME_CAMERA "http://tizen.org/feature/camera"
36 #define _FEATURE_NAME_MICROPHONE "http://tizen.org/feature/microphone"
38 #define _WEBRTC_AUDIO_CAPSFILTER "audio_capsfilter"
39 #define _WEBRTC_VIDEO_CAPSFILTER "video_capsfilter"
41 static param_s param_table[] = {
43 MEDIA_STREAMER_PARAM_CAMERA_ID,
46 PARAM_DATA_TYPE_NUMBER
49 MEDIA_STREAMER_PARAM_CAPTURE_WIDTH,
51 PROP_NAME_CAPTURE_WIDTH,
52 PARAM_DATA_TYPE_NUMBER
55 MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT,
57 PROP_NAME_CAPTURE_HEIGHT,
58 PARAM_DATA_TYPE_NUMBER
61 MEDIA_STREAMER_PARAM_IS_LIVE_STREAM,
67 MEDIA_STREAMER_PARAM_IS_LIVE_STREAM,
73 MEDIA_STREAMER_PARAM_URI,
76 PARAM_DATA_TYPE_STRING
79 MEDIA_STREAMER_PARAM_URI,
82 PARAM_DATA_TYPE_STRING
85 MEDIA_STREAMER_PARAM_USER_AGENT,
88 PARAM_DATA_TYPE_STRING
91 MEDIA_STREAMER_PARAM_STREAM_TYPE,
93 PROP_NAME_STREAM_TYPE,
97 MEDIA_STREAMER_PARAM_PORT,
100 PARAM_DATA_TYPE_NUMBER
103 MEDIA_STREAMER_PARAM_RTP_LATENCY,
105 PROP_NAME_RTP_LATENCY,
106 PARAM_DATA_TYPE_NUMBER
109 MEDIA_STREAMER_PARAM_VIDEO_IN_PORT,
111 PROP_NAME_VIDEO_IN_PORT,
112 PARAM_DATA_TYPE_NUMBER
115 MEDIA_STREAMER_PARAM_AUDIO_IN_PORT,
117 PROP_NAME_AUDIO_IN_PORT,
118 PARAM_DATA_TYPE_NUMBER
121 MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT,
123 PROP_NAME_VIDEO_OUT_PORT,
124 PARAM_DATA_TYPE_NUMBER
127 MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT,
129 PROP_NAME_AUDIO_OUT_PORT,
130 PARAM_DATA_TYPE_NUMBER
133 MEDIA_STREAMER_PARAM_IP_ADDRESS,
136 PARAM_DATA_TYPE_STRING
139 MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE,
141 PROP_NAME_WEBRTC_PEER_TYPE,
142 PARAM_DATA_TYPE_STRING
145 MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER,
146 "webrtc-stun-server",
147 PROP_NAME_WEBRTC_STUN_SERVER,
148 PARAM_DATA_TYPE_STRING
151 MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION,
152 "webrtc-remote-session-description",
153 PROP_NAME_WEBRTC_REMOTE_SESSION_DESCRIPTION,
154 PARAM_DATA_TYPE_STRING
157 MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE,
158 "webrtc-add-ice-candidate",
159 PROP_NAME_WEBRTC_ADD_ICE_CANDIDATE,
160 PARAM_DATA_TYPE_STRING
163 MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO,
164 "webrtc-rtp-transceiver-direction-for-audio",
165 PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO,
166 PARAM_DATA_TYPE_STRING
169 MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO,
170 "webrtc-rtp-transceiver-direction-for-video",
171 PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO,
172 PARAM_DATA_TYPE_STRING
175 MEDIA_STREAMER_PARAM_AUDIO_DEVICE,
177 PROP_NAME_AUDIO_DEVICE,
178 PARAM_DATA_TYPE_STRING
181 MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED,
187 MEDIA_STREAMER_PARAM_ROTATE,
193 MEDIA_STREAMER_PARAM_FLIP,
199 MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD,
200 "display-geometry-method",
201 PROP_NAME_DISPLAY_GEOMETRY_METHOD,
205 MEDIA_STREAMER_PARAM_DISPLAY,
208 PARAM_DATA_TYPE_POINTER
211 MEDIA_STREAMER_PARAM_VISIBLE,
217 MEDIA_STREAMER_PARAM_USE_TBM,
223 MEDIA_STREAMER_PARAM_HOST,
226 PARAM_DATA_TYPE_STRING
229 MEDIA_STREAMER_PARAM_SEGMENT_LOCATION,
231 PROP_NAME_SEGMENT_LOCATION,
232 PARAM_DATA_TYPE_STRING
235 MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION,
237 PROP_NAME_PLAYLIST_LOCATION,
238 PARAM_DATA_TYPE_STRING
241 MEDIA_STREAMER_PARAM_SINK_MAX_LATENESS,
243 PROP_NAME_MAX_LATENESS,
244 PARAM_DATA_TYPE_NUMBER
254 static node_info_s nodes_info[] = {
255 {"Generic", "none"}, /* MEDIA_STREAMER_NODE_TYPE_NONE */
256 {"Source", "source"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */
257 {"Sink", "sink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */
258 {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
259 {"Codec/Decoder/Video", "video_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */
260 {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
261 {"Codec/Decoder/Audio", "audio_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */
262 {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */
263 {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */
264 {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */
265 {"Codec/Payloader/Network/RTP", "rtph263pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */
266 {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */
267 {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */
268 {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */
269 {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */
270 {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */
271 {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */
272 {"Codec/Parser", "h263parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */
273 {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */
274 {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */
275 {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */
276 {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */
277 {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
278 {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */
279 {"Generic/Bin", "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */
280 {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */
281 {MEDIA_STREAMER_STRICT, "output-selector"}, /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */
282 {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */
283 {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */
284 {"Filter/Network/WebRTC", "webrtc_container"}, /* MEDIA_STREAMER_NODE_TYPE_WEBRTC */
288 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
292 ms_retvm_if(!node, FALSE, "node is NULL");
293 ms_retvm_if(!node->gst_element, FALSE, "gst_element is NULL");
294 ms_retvm_if(!param_name, FALSE, "param_name is NULL");
296 if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
299 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
301 ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
303 return val ? TRUE : FALSE;
306 static int __ms_param_value_init(GValue *value, param_data_type_e type)
308 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER , "value is NULL");
311 case PARAM_DATA_TYPE_NUMBER:
312 g_value_init(value, G_TYPE_INT);
314 case PARAM_DATA_TYPE_BOOL:
315 g_value_init(value, G_TYPE_BOOLEAN);
317 case PARAM_DATA_TYPE_STRING:
318 g_value_init(value, G_TYPE_STRING);
320 case PARAM_DATA_TYPE_ENUM:
321 g_value_init(value, G_TYPE_ENUM);
323 case PARAM_DATA_TYPE_POINTER:
324 g_value_init(value, G_TYPE_POINTER);
327 ms_error("not supported type[%d]", type);
328 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
331 return MEDIA_STREAMER_ERROR_NONE;
334 static int __ms_param_value_set(GValue *value, param_data_type_e type, const char *param_value)
336 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER , "value is NULL");
337 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER , "param_value is NULL");
340 case PARAM_DATA_TYPE_NUMBER:
341 g_value_unset(value);
342 g_value_init(value, G_TYPE_INT);
343 g_value_set_int(value, ms_get_number_from_string(param_value));
346 case PARAM_DATA_TYPE_BOOL:
347 g_value_unset(value);
348 g_value_init(value, G_TYPE_BOOLEAN);
349 if (!strcmp(param_value, "true") || !strcmp(param_value, "TRUE")) {
350 g_value_set_boolean(value, TRUE);
351 } else if (!strcmp(param_value, "false") || !strcmp(param_value, "FALSE")) {
352 g_value_set_boolean(value, FALSE);
354 ms_error("invalid parameter[%s] for PARAM_DATA_TYPE_BOOL", param_value);
355 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
359 case PARAM_DATA_TYPE_STRING:
360 g_value_unset(value);
361 g_value_init(value, G_TYPE_STRING);
362 g_value_set_string(value, param_value);
365 case PARAM_DATA_TYPE_ENUM:
366 g_value_unset(value);
367 g_value_init(value, G_TYPE_ENUM);
368 g_value_set_enum(value, ms_get_number_from_string(param_value));
371 case PARAM_DATA_TYPE_POINTER:
372 g_value_unset(value);
373 g_value_init(value, G_TYPE_POINTER);
374 g_value_set_pointer(value, (void*) param_value);
378 ms_error("not supported type[%d]", type);
379 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
382 return MEDIA_STREAMER_ERROR_NONE;
385 static void __ms_param_value_print(GValue *value, param_data_type_e type)
387 ms_retm_if(!value, "value is NULL");
390 case PARAM_DATA_TYPE_NUMBER:
391 if (G_VALUE_HOLDS_INT(value))
392 ms_debug("value[%d]", g_value_get_int(value));
394 ms_debug("value[%u]", g_value_get_uint(value));
396 case PARAM_DATA_TYPE_BOOL:
397 ms_debug("value[%d]", g_value_get_boolean(value));
399 case PARAM_DATA_TYPE_STRING:
400 ms_debug("value[%s]", g_value_get_string(value));
402 case PARAM_DATA_TYPE_ENUM:
403 ms_debug("value[%d]", g_value_get_enum(value));
405 case PARAM_DATA_TYPE_POINTER:
406 ms_debug("value[%p]", g_value_get_pointer(value));
409 ms_error("not supported type[%d]", type);
414 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
416 int ret = MEDIA_STREAMER_ERROR_NONE;
419 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
420 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
421 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
422 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
423 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
425 ms_debug("param[%s]", param->param_name);
427 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
429 ms_error("fail to get [%s] value from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
430 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
433 ret = __ms_param_value_init(value, param->data_type);
434 if (ret != MEDIA_STREAMER_ERROR_NONE)
437 g_value_copy(val, value);
439 __ms_param_value_print(value, param->data_type);
444 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
446 int ret = MEDIA_STREAMER_ERROR_NONE;
449 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
450 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
451 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
452 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
453 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
455 ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
457 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
459 ms_error("fail to get [%s] value from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
460 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
463 if (!strcmp(param->param_name, MS_PARAM_VIDEO_IN_FORMAT) ||
464 !strcmp(param->param_name, MS_PARAM_AUDIO_IN_FORMAT)) {
465 GstCaps *caps = gst_caps_from_string(param_value);
468 g_value_init(val, GST_TYPE_CAPS);
469 gst_value_set_caps(val, caps);
471 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
474 ret = __ms_param_value_set(val, param->data_type, param_value);
483 static int __ms_node_get_rtp_latency(media_streamer_node_s *node, int *latency)
487 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is null");
488 ms_retvm_if(!latency, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "latency is null");
489 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC &&
490 node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
492 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_RTP_LATENCY);
494 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_RTP_LATENCY, GST_ELEMENT_NAME(node->gst_element));
495 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
498 if (!(*latency = g_value_get_int(val))) {
499 ms_error("Failed to g_value_get_int()");
500 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
503 ms_info("RTP latency is [%d]", *latency);
505 return MEDIA_STREAMER_ERROR_NONE;
508 static int __ms_webrtc_node_check_transceiver_direction_param_value(media_streamer_node_s *node, param_s *param, const gchar *param_value)
510 GstWebRTCRTPTransceiverDirection direction;
511 GstGhostPad *ghost_pad = NULL;
512 const gchar *pad_name;
513 gboolean is_linked = FALSE;
515 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
516 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
517 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
518 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
519 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
521 if (param->prop_enum == PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO)
522 pad_name = MS_PAD_AUDIO_IN;
523 else if (param->prop_enum == PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO)
524 pad_name = MS_PAD_VIDEO_IN;
526 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
528 if (!(ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, pad_name))) {
529 ms_error("Failed to get ghost pad for webrtc_container");
530 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
533 is_linked = gst_pad_is_linked((GstPad *)ghost_pad);
534 MS_SAFE_UNREF(ghost_pad);
536 ms_debug("[%s] %s", pad_name, is_linked ? "is linked" : "isn't linked");
538 if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV)) {
539 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
540 } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY)) {
541 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
542 } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY)) {
543 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
544 } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE)) {
545 direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE;
547 ms_error("failed to set property, param value should be sendrecv or sendonly or recvonly or inactive");
548 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
551 if (!ms_webrtc_is_valid_transceiver_direction(is_linked, direction)) {
552 ms_error("%s is not valid transceiver direction", param_value);
553 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
556 return MEDIA_STREAMER_ERROR_NONE;
559 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
563 ms_retvm_if(!node, FALSE, "node is NULL");
564 ms_retvm_if(!node->gst_element, FALSE, "gst_element is NULL");
565 ms_retvm_if(!param_name, FALSE, "param_name is NULL");
567 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC)
570 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
572 ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
574 return val ? TRUE : FALSE;
577 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
582 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
583 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
584 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
585 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
586 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
588 ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
590 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
592 ms_error("failed to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
593 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
596 switch (param->prop_enum) {
597 case PROP_NAME_WEBRTC_PEER_TYPE:
598 if (strcmp(param_value, WEBRTC_PEER_OFFER) && strcmp(param_value, WEBRTC_PEER_ANSWER)) {
599 ms_error("failed to set property, param value should be [%s] or [%s]", WEBRTC_PEER_OFFER, WEBRTC_PEER_ANSWER);
600 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
602 ret = __ms_param_value_set(val, param->data_type, param_value);
605 case PROP_NAME_WEBRTC_STUN_SERVER:
606 ret = ms_webrtcbin_set_stun_server(node, param_value);
607 if (ret != MEDIA_STREAMER_ERROR_NONE) {
608 ms_error("failed to set STUN server: %s", param_value);
611 ret = __ms_param_value_set(val, param->data_type, param_value);
614 case PROP_NAME_WEBRTC_REMOTE_SESSION_DESCRIPTION:
615 ret = ms_webrtcbin_set_remote_session_description(node, param_value);
616 if (ret != MEDIA_STREAMER_ERROR_NONE) {
617 ms_error("failed to set remote session description:\n%s", param_value);
620 ret = __ms_param_value_set(val, param->data_type, param_value);
623 case PROP_NAME_WEBRTC_ADD_ICE_CANDIDATE:
624 ret = ms_webrtcbin_add_ice_candidate(node, param_value);
625 if (ret != MEDIA_STREAMER_ERROR_NONE) {
626 ms_error("failed to add ICE candidate: %s", param_value);
631 case PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO:
632 case PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO:
633 ret = __ms_webrtc_node_check_transceiver_direction_param_value(node, param, param_value);
634 if (ret != MEDIA_STREAMER_ERROR_NONE) {
635 ms_error("failed to set transceiver direction: %s", param_value);
639 ret = __ms_param_value_set(val, param->data_type, param_value);
642 case PROP_NAME_RTP_LATENCY:
643 ret = __ms_param_value_set(val, param->data_type, param_value);
647 ms_error("failed to set property, undefined param name[%s]", param->param_name);
648 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
655 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
659 ms_retvm_if(!node, FALSE, "node is NULL");
660 ms_retvm_if(!node->gst_element, FALSE, "gst_element is NULL");
661 ms_retvm_if(!param_name, FALSE, "param_name is NULL");
663 if (node->type != MEDIA_STREAMER_NODE_TYPE_SRC ||
664 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
667 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
669 ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
671 return val ? TRUE : FALSE;
674 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
676 int ret = MEDIA_STREAMER_ERROR_NONE;
679 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
680 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
681 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
682 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
683 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
684 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
686 ms_debug("param[%s]", param->param_name);
688 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
690 ms_error("fail to get [%s] value from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
691 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
694 ret = __ms_param_value_init(value, param->data_type);
695 if (ret != MEDIA_STREAMER_ERROR_NONE)
698 g_value_copy(val, value);
700 __ms_param_value_print(value, param->data_type);
705 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
707 int ret = MEDIA_STREAMER_ERROR_NONE;
710 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
711 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
712 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
713 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
714 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
715 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
717 ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
719 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
721 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
722 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
725 ret = __ms_param_value_set(val, param->data_type, param_value);
730 static int __ms_node_check_privileges(media_streamer_node_s *node)
732 int ret = MEDIA_STREAMER_ERROR_NONE;
734 char *privilege = NULL;
736 cynara *cynara_h = NULL;
739 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
741 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
742 switch (node->subtype) {
743 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
744 privilege = "http://tizen.org/privilege/internet";
746 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
747 privilege = "http://tizen.org/privilege/internet";
749 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
750 privilege = "http://tizen.org/privilege/camera";
752 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
753 privilege = "http://tizen.org/privilege/recorder";
755 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
756 privilege = "http://tizen.org/privilege/camera";
759 ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
764 if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
765 switch (node->subtype) {
766 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
767 privilege = "http://tizen.org/privilege/internet";
770 ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
775 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
776 privilege = "http://tizen.org/privilege/internet";
778 /* Skip checking for privilege permission in case of other types of Nodes */
779 if (privilege == NULL)
782 ms_retvm_if(cynara_initialize(&cynara_h, NULL) != CYNARA_API_SUCCESS, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
783 "failed to cynara_initialize()");
785 ms_retvm_if(smack_new_label_from_self(&smack_label) == -1, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
786 "failed to smack_new_label_from_self()");
788 snprintf(uid, sizeof(uid), "%d", getuid());
789 ms_debug("smack_label[%s] uid[%s] privilege[%s]", smack_label, uid, privilege);
791 /* Checking with cynara for current session */
792 ret_val = cynara_check(cynara_h, smack_label, "", uid, privilege);
793 ms_info("Cynara_check [%d] ", ret_val);
796 case CYNARA_API_ACCESS_ALLOWED:
797 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
799 case CYNARA_API_ACCESS_DENIED:
801 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
802 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
806 cynara_finish(cynara_h);
813 static int __ms_node_check_feature(media_streamer_node_s *node)
815 bool enabled = FALSE;
819 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
821 switch (node->type) {
822 case MEDIA_STREAMER_NODE_TYPE_WEBRTC:
823 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
824 ms_info("wifi status = %d", enabled);
826 return MEDIA_STREAMER_ERROR_NONE;
828 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
829 ms_info("telephony status = %d", enabled);
831 return MEDIA_STREAMER_ERROR_NONE;
833 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
834 ms_info("ethernet status = %d", enabled);
836 return MEDIA_STREAMER_ERROR_NONE;
838 ms_error("None of [%s] [%s] [%s] features is enabled", _FEATURE_NAME_WIFI, _FEATURE_NAME_TELEPHONY, _FEATURE_NAME_ETHERNET);
839 return MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
841 ms_debug("For current node type[%d], feature is not needed", node->type);
847 return MEDIA_STREAMER_ERROR_NONE;
850 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
852 int ret = MEDIA_STREAMER_ERROR_NONE;
853 GstCaps *sink_caps = NULL;
854 GstCaps *src_caps = NULL;
858 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
860 ret = __ms_node_check_privileges(node);
861 if (ret != MEDIA_STREAMER_ERROR_NONE) {
862 ms_error("Failed to get privilege for this node type(%d)", node->type);
866 ret = __ms_node_check_feature(node);
867 if (ret != MEDIA_STREAMER_ERROR_NONE) {
868 ms_error("Failed to get feature for this node type(%d)", node->type);
872 sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt, nodes_info[node->type].default_name) : NULL;
873 src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt, nodes_info[node->type].default_name) : NULL;
875 node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL, out_fmt};
877 ms_info("Creating node with info: klass_name[%s]; default[%s]",
878 plug_info.info->klass_name, plug_info.info->default_name);
880 node->gst_element = ms_node_element_create(&plug_info, node->type);
881 if (node->gst_element)
882 node->name = gst_element_get_name(node->gst_element);
884 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
887 gst_caps_unref(src_caps);
890 gst_caps_unref(sink_caps);
897 /* This signal callback is called when appsrc needs data, we add an idle handler
898 * to the mainloop to start pushing data into the appsrc */
899 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
901 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
902 media_streamer_callback_s *src_callback = NULL;
903 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
907 ms_retm_if(ms_src == NULL, "data is NULL");
908 ms_retm_if(pipeline == NULL, "pipeline is NULL");
910 if (ms_src->callbacks_structure != NULL) {
911 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
912 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
913 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
919 /* This callback is called when appsrc has enough data and we can stop sending.
920 * We remove the idle handler from the mainloop */
921 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
923 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
924 media_streamer_callback_s *src_callback = NULL;
925 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
929 ms_retm_if(ms_src == NULL, "data is NULL");
930 ms_retm_if(pipeline == NULL, "pipeline is NULL");
932 if (ms_src->callbacks_structure != NULL) {
933 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
934 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
935 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
941 static int __ms_src_node_check_feature(media_streamer_node_s *node)
943 int ret = MEDIA_STREAMER_ERROR_NONE;
944 bool enabled = FALSE;
945 bool supported = FALSE;
949 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
951 switch (node->subtype) {
952 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
953 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
954 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
955 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
956 ms_info("wifi status = %d", enabled);
960 ms_error("SYSTEM_INFO_ERROR");
963 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
964 ms_info("telephony status = %d", enabled);
968 ms_error("SYSTEM_INFO_ERROR");
971 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
972 ms_info("ethernet status = %d", enabled);
976 ms_error("SYSTEM_INFO_ERROR");
979 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
981 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
982 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
983 ms_info("microphone status = %d", enabled);
987 ms_error("SYSTEM_INFO_ERROR");
990 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
992 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
993 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
994 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
995 ms_info("camera status = %d", enabled);
999 ms_error("SYSTEM_INFO_ERROR");
1002 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
1005 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
1014 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
1016 int ret = MEDIA_STREAMER_ERROR_NONE;
1017 bool enabled = FALSE;
1018 bool supported = FALSE;
1022 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1024 switch (node->subtype) {
1025 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
1026 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
1027 /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
1028 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
1029 ms_info("wifi status = %d", enabled);
1033 ms_error("SYSTEM_INFO_ERROR");
1036 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
1037 ms_info("telephony status = %d", enabled);
1041 ms_error("SYSTEM_INFO_ERROR");
1044 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
1045 ms_info("ethernet status = %d", enabled);
1049 ms_error("SYSTEM_INFO_ERROR");
1052 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
1055 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
1064 int ms_src_node_create(media_streamer_node_s *node)
1066 int ret = MEDIA_STREAMER_ERROR_NONE;
1067 char *plugin_name = NULL;
1071 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
1073 ret = __ms_node_check_privileges(node);
1074 if (ret != MEDIA_STREAMER_ERROR_NONE) {
1075 ms_error("Error getting privileges for Src Node");
1079 ret = __ms_src_node_check_feature(node);
1080 if (ret != MEDIA_STREAMER_ERROR_NONE) {
1081 ms_error("Error getting feature for Src Node");
1085 switch (node->subtype) {
1086 case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
1087 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1088 node->gst_element = ms_element_create(plugin_name, NULL);
1090 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
1091 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
1092 node->gst_element = ms_element_create(plugin_name, NULL);
1094 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
1095 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1096 node->gst_element = ms_element_create(plugin_name, NULL);
1098 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
1099 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
1100 node->gst_element = ms_element_create(plugin_name, NULL);
1102 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
1103 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
1104 node->gst_element = ms_element_create(plugin_name, NULL);
1106 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
1107 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
1108 node->gst_element = ms_element_create(plugin_name, NULL);
1110 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
1111 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
1112 node->gst_element = ms_element_create(plugin_name, NULL);
1114 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
1115 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
1116 node->gst_element = ms_element_create(plugin_name, NULL);
1118 case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
1119 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
1120 node->gst_element = ms_element_create(plugin_name, "custom_src");
1121 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
1122 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
1123 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
1125 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
1126 node->gst_element = ms_adaptive_element_create();
1129 ms_error("Error: invalid Src node Type [%d]", node->subtype);
1133 MS_SAFE_FREE(plugin_name);
1135 if (node->gst_element == NULL)
1136 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1138 node->name = gst_element_get_name(node->gst_element);
1140 ret = ms_node_dpm_policy_init(node);
1141 if (MEDIA_STREAMER_ERROR_NONE != ret) {
1142 ms_error("Failed to init DPM policy for node [%s]", node->name);
1151 /* The appsink has received a buffer */
1152 static GstFlowReturn __ms_sink_new_sample_cb(GstElement *sink, gpointer *data)
1154 media_streamer_node_s *ms_sink = (media_streamer_node_s *)data;
1155 media_streamer_sink_callbacks_s *sink_callbacks;
1156 media_streamer_sink_data_ready_cb data_ready_cb;
1158 ms_retvm_if(ms_sink == NULL, GST_FLOW_ERROR, "data is NULL");
1160 if (!ms_sink->callbacks_structure) {
1161 ms_debug("callbacks_structure is NULL");
1165 sink_callbacks = (media_streamer_sink_callbacks_s *)ms_sink->callbacks_structure;
1166 data_ready_cb = (media_streamer_sink_data_ready_cb)sink_callbacks->data_ready_cb.callback;
1168 if (data_ready_cb) {
1169 ms_debug("=====> invoke data ready callback(%p)", data_ready_cb);
1170 data_ready_cb((media_streamer_node_h)ms_sink, sink_callbacks->data_ready_cb.user_data);
1171 ms_debug("<===== end of the callback");
1173 ms_debug("data ready callback is NULL");
1180 static void __ms_sink_eos_cb(GstElement *sink, gpointer *data)
1182 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
1183 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
1184 media_streamer_sink_eos_cb eos_cb = NULL;
1186 ms_retm_if(ms_sink == NULL, "data is NULL");
1188 if (!ms_sink->callbacks_structure) {
1189 ms_debug("callbacks_structure is NULL");
1193 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
1194 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
1197 ms_debug("=====> invoke eos callback(%p)", eos_cb);
1198 eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
1199 ms_debug("<===== end of the callback");
1201 ms_debug("eos callback is NULL");
1206 int ms_sink_node_create(media_streamer_node_s *node)
1208 int ret = MEDIA_STREAMER_ERROR_NONE;
1209 char *plugin_name = NULL;
1213 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1215 ret = __ms_node_check_privileges(node);
1216 if (ret != MEDIA_STREAMER_ERROR_NONE) {
1217 ms_error("Error getting privileges for Sink Node");
1221 ret = __ms_sink_node_check_feature(node);
1222 if (ret != MEDIA_STREAMER_ERROR_NONE) {
1223 ms_error("Error getting feature for Sink Node");
1227 switch (node->subtype) {
1228 case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
1229 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
1230 node->gst_element = ms_element_create(plugin_name, NULL);
1232 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
1233 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
1234 node->gst_element = ms_element_create(plugin_name, NULL);
1236 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
1237 ms_error("Error: not implemented yet");
1239 case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
1240 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
1241 node->gst_element = ms_element_create(plugin_name, NULL);
1243 case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
1244 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
1245 node->gst_element = ms_element_create(plugin_name, NULL);
1247 case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
1248 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
1249 node->gst_element = ms_element_create(plugin_name, NULL);
1251 case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
1252 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
1253 node->gst_element = ms_element_create(plugin_name, NULL);
1254 if (node->gst_element) {
1255 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
1256 ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_sample_cb), node);
1257 ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(__ms_sink_eos_cb), node);
1260 case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
1261 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
1262 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
1264 if (g_strrstr(plugin_name, "hlssink")) {
1265 g_object_set(G_OBJECT(node->gst_element),
1267 "playlist-length", 0, NULL);
1271 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
1275 MS_SAFE_FREE(plugin_name);
1277 if (node->gst_element == NULL)
1278 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1280 node->name = gst_element_get_name(node->gst_element);
1287 void ms_node_destroy(media_streamer_node_s *node)
1289 gchar *node_name = NULL;
1293 ms_retm_if(node == NULL, "node is NULL");
1294 node_name = g_strdup(node->name);
1296 /* Disconnects and clean all node signals */
1297 g_list_free_full(node->sig_list, ms_signal_destroy);
1299 /* Deinitialize policy manager */
1300 if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
1301 ms_error("Failed to deinitialize DPM policy");
1303 MS_SAFE_UNREF(node->gst_element);
1304 MS_SAFE_FREE(node->name);
1305 MS_SAFE_FREE(node->callbacks_structure);
1308 ms_info("Node [%s] has been destroyed", node_name);
1309 MS_SAFE_GFREE(node_name);
1314 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1316 int ret = MEDIA_STREAMER_ERROR_NONE;
1317 GstElement *bin = NULL;
1321 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
1322 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
1324 ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1326 switch (node->type) {
1327 case MEDIA_STREAMER_NODE_TYPE_SRC:
1328 bin = ms_streamer->src_bin;
1330 case MEDIA_STREAMER_NODE_TYPE_SINK:
1331 bin = ms_streamer->sink_bin;
1334 /* Another elements will be add into transform bin */
1335 bin = ms_streamer->transform_bin;
1339 if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
1340 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
1341 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1349 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
1353 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1354 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1355 ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
1357 if (g_hash_table_contains(nodes_table, node->name)) {
1358 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
1359 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1361 if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
1362 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
1363 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1366 ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1370 return MEDIA_STREAMER_ERROR_NONE;
1373 int ms_node_remove_from_table(GHashTable *nodes_table, media_streamer_node_s *node)
1375 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1376 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1378 /* Removal element of this node from bin will be performed
1379 * in the callback - ms_node_remove_from_table_cb(). */
1380 if (!g_hash_table_remove(nodes_table, (gpointer) node->name)) {
1381 ms_error("Failed to remove node [%s] from table", node->name);
1382 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1385 return MEDIA_STREAMER_ERROR_NONE;
1388 void ms_node_remove_from_table_cb(void *data)
1390 media_streamer_node_s *node = (media_streamer_node_s *) data;
1394 ms_retm_if(node == NULL, "data is NULL");
1396 if (ms_element_unlink(node->gst_element)) {
1397 node->linked_by_user = FALSE;
1398 node->parent_streamer = NULL;
1399 ms_bin_remove_element(node->gst_element);
1400 ms_info("Node [%s] removed from Media Streamer", node->name);
1402 ms_error("Failed to unlink element of node [%s]", node->name);
1408 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1410 gboolean ret = FALSE;
1414 if (!src_pad || gst_pad_is_linked(src_pad))
1417 GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1418 if (gst_caps_is_any(src_caps))
1421 gst_caps_unref(src_caps);
1428 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1434 for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1435 if (it_klass == element_type) {
1436 ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1443 return &nodes_info[it_klass];
1446 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1448 gboolean ret = FALSE;
1450 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1451 ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1455 ret = ms_element_lock_state(item, g_ret, user_data);
1462 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1464 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1465 GstElement *src_element = NULL;
1466 GstElement *found_element = NULL;
1467 media_streamer_node_s *node = NULL;
1468 GstPad *src_pad = NULL;
1472 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1473 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1474 ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1476 src_element = GST_ELEMENT(g_value_get_object(item));
1477 g_object_ref(src_element);
1478 g_value_set_boolean(ret, FALSE);
1480 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1481 GST_ELEMENT_NAME(src_element));
1483 /* If we fail to find corresponding node inside streamer
1484 then apparently this element doesn't require resources. */
1485 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1486 g_value_set_boolean(ret, TRUE);
1487 g_object_unref(src_element);
1491 ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1493 src_pad = gst_element_get_static_pad(src_element, "src");
1495 if (__ms_src_need_typefind(src_pad)) {
1496 ms_find_type(ms_streamer, src_element);
1497 MS_SAFE_UNREF(src_element);
1499 /* Check the source element`s pad type */
1500 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1501 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1502 if (gst_pad_is_linked(src_pad)) {
1503 MS_SAFE_UNREF(src_pad);
1504 MS_SAFE_UNREF(src_element);
1505 g_value_set_boolean(ret, TRUE);
1508 /* It is media streamer Server part */
1509 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1510 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1511 GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1512 g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1513 gst_caps_unref(videoCaps);
1515 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1516 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1517 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1519 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1520 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1521 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1522 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1524 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1525 MS_SAFE_UNREF(found_element);
1527 MS_SAFE_UNREF(src_pad);
1529 g_value_set_boolean(ret, TRUE);
1536 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1538 char *manifest_src_name = NULL;
1539 gchar *location = NULL;
1540 GstElement *manifest_src = NULL;
1542 const char *uri = NULL;
1543 gchar *protocol = NULL;
1547 ms_retvm_if(!node, NULL, "node is NULL");
1549 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1550 uri = g_value_get_string(val);
1551 protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1553 if (protocol && g_strrstr(protocol, "http")) {
1554 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1555 location = g_strdup(uri);
1556 } else if (protocol && g_strrstr(protocol, "file")) {
1557 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1558 location = gst_uri_get_location(uri);
1560 ms_error("Unsupported URI protocol... Check URI is file path");
1561 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1562 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1563 location = g_strdup(uri);
1566 ms_error("URI is not valid file path");
1572 if (manifest_src_name == NULL) {
1573 LOGE("Error empty manifest source name for adaptive source");
1578 manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1579 g_free(manifest_src_name);
1581 if (manifest_src == NULL) {
1582 LOGE("Error creating manifest source for adaptive source");
1587 g_object_set(manifest_src, "location", location, NULL);
1592 return manifest_src;
1595 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1597 char *plugin_name = NULL;
1598 GstElement *manifest_src = NULL;
1599 GstElement *plugin_elem = NULL;
1600 gboolean res = FALSE;
1605 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1608 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1609 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1610 ms_info("Creating [%s] element", plugin_name);
1611 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1612 g_free(plugin_name);
1613 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1614 "Error creating element for adaptive source");
1616 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1617 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1618 "Error adding adaptive element to bin for adaptive source");
1621 manifest_src = __ms_manifest_src_create(node);
1622 ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1623 "Error creating manifest source for adaptive source");
1625 res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1626 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1627 "Error adding manifest source to bin for adaptive source");
1630 res = gst_element_link(manifest_src, plugin_elem);
1631 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1632 "Error linking manifest source and element for adaptive source");
1635 gp = gst_element_get_static_pad(node->gst_element, "src");
1636 ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1637 "Error getting source pad for adaptive source");
1640 g_signal_connect_object(plugin_elem, "pad-added",
1641 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1643 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1644 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1649 return MEDIA_STREAMER_ERROR_NONE;
1652 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1654 int err_code = MEDIA_STREAMER_ERROR_NONE;
1655 gchar *playlist_location = NULL;
1656 char *playlist_dir = NULL;
1661 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1662 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1663 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1665 /* Create and start http server */
1666 err_code = ms_http_server_create(&ms_streamer->http_server);
1667 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1668 ms_error("Failed to create http server during prepare");
1672 ms_info("Starting http server");
1673 /* FIXME: find out how to set default port */
1674 err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1675 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1676 ms_error("Failed to start http server during prepare. Destroying http server");
1677 ms_http_server_destroy(ms_streamer->http_server);
1681 g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1682 if (!playlist_location) {
1683 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1684 ms_error("Failed to get playlist location");
1685 ms_http_server_destroy(ms_streamer->http_server);
1689 split = strrchr(playlist_location, '/');
1690 playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1692 ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1694 MS_SAFE_GFREE(playlist_location);
1704 int ms_rtp_node_prepare(media_streamer_node_s *node)
1706 GstElement *rtpbin = NULL;
1707 GstElement *rtp_el = NULL;
1708 GstElement *rtcp_el = NULL;
1710 const char *host = NULL;
1711 GstElement *video_filter = NULL;
1712 GstCaps *video_caps = NULL;
1713 GstGhostPad *ghost_pad = NULL;
1714 GstElement *audio_filter = NULL;
1715 GstCaps *audio_caps = NULL;
1716 gint latency = DEFAULT_MEDIA_STREAMER_RTP_LATENCY;
1720 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1722 rtpbin = ms_element_create("rtpbin", "rtpbin");
1723 ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1725 if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1726 MS_SAFE_UNREF(rtpbin);
1727 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1730 ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1732 if (__ms_node_get_rtp_latency(node, &latency) != MEDIA_STREAMER_ERROR_NONE) {
1733 ms_error("Failed to get rtp latency");
1734 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1736 g_object_set(G_OBJECT(rtpbin), "latency", latency, NULL);
1738 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1739 host = g_value_get_string(val);
1741 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1742 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1743 rtp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtp");
1744 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1746 rtcp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtcp");
1747 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1749 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1750 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1751 ms_error("Failed to link pads for rtpbin sink pad 0");
1752 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1755 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1756 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1758 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_VIDEO_IN_FORMAT);
1759 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1762 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1763 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1764 rtp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtp");
1765 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1767 rtcp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtcp");
1768 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1770 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1771 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1772 ms_error("Failed to link pads for rtpbin sink pad 1");
1773 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1776 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1777 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1779 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_AUDIO_IN_FORMAT);
1780 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1783 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1784 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1785 rtp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtp");
1786 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1788 rtcp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtcp");
1789 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1791 video_filter = ms_element_create("capsfilter", NULL);
1792 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1794 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1795 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1796 gst_caps_unref(video_caps);
1798 if (!gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0")) {
1799 ms_error("Failed to link pads for send_rtp_sink_0");
1800 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1802 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_VIDEO_IN);
1804 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1805 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_VIDEO_IN);
1808 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1809 !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1810 ms_error("Failed to link pads for rtpbin src pad 0");
1811 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1814 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1815 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1816 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1817 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1818 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1819 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1822 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1823 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1824 rtp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtp");
1825 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1827 rtcp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtcp");
1828 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1830 audio_filter = ms_element_create("capsfilter", NULL);
1831 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1833 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1834 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1836 if (!gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1")) {
1837 ms_error("Failed to link pads for send_rtp_sink_1");
1838 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1841 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_AUDIO_IN);
1843 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1844 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_AUDIO_IN);
1847 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1848 !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1849 ms_error("Failed to link pads for rtpbin src pad 1");
1850 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1853 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1854 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1855 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1856 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1857 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1858 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1861 ms_generate_dots(node->gst_element, "rtp_prepared");
1865 return MEDIA_STREAMER_ERROR_NONE;
1868 static int __ms_webrtc_prepare_ghost_sink_pad(GstElement *webrtc_container, GstElement *webrtcbin, const char *capsfilter_name)
1870 int ret = MEDIA_STREAMER_ERROR_NONE;
1872 GstGhostPad *ghost_pad_in = NULL;
1873 GstPad *filter_sink_pad = NULL;
1874 GstPad *req_pad = NULL;
1875 gchar *req_pad_name = NULL;
1876 const gchar *pad_name;
1878 ms_retvm_if(!webrtc_container, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
1879 ms_retvm_if(!webrtcbin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtcbin is NULL");
1880 ms_retvm_if(!capsfilter_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "capsfilter_name is NULL");
1882 if (g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) &&
1883 g_strcmp0(capsfilter_name, _WEBRTC_VIDEO_CAPSFILTER))
1884 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1886 pad_name = !g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) ? MS_PAD_AUDIO_IN : MS_PAD_VIDEO_IN;
1888 if (!(filter = ms_find_element_in_bin_by_name(webrtc_container, capsfilter_name))) {
1889 ms_debug("No need to export the ghost sink pad for [%s]", pad_name);
1890 return MEDIA_STREAMER_ERROR_NONE;
1893 if (!(ghost_pad_in = (GstGhostPad *)gst_element_get_static_pad(webrtc_container, pad_name))) {
1894 ms_error("Failed to get ghost pad for webrtc_container");
1895 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1898 if (!gst_pad_is_linked((GstPad *)ghost_pad_in)) {
1899 ms_error("[%s] is set media format but not linked to peer node", pad_name);
1900 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1904 ms_info("%s is found, link it with webrtcbin and export the ghost pad[%s] of webrtc_container",
1905 capsfilter_name, pad_name);
1907 if (!(req_pad = gst_element_request_pad_simple(webrtcbin, "sink_%u"))) {
1908 ms_error("Failed to get request pad");
1909 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1912 if (!(req_pad_name = gst_pad_get_name(req_pad))) {
1913 ms_error("Failed to get request pad name");
1914 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1917 if (!gst_element_link_pads(filter, "src", webrtcbin, req_pad_name)) {
1918 ms_error("Failed to link pads, %s - webrtcbin", capsfilter_name);
1919 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1923 if (!(filter_sink_pad = gst_element_get_static_pad(filter, "sink"))) {
1924 ms_error("Failed to get capsfilter sink pad in webrtc_container");
1925 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1928 if (!gst_ghost_pad_set_target(ghost_pad_in, filter_sink_pad)) {
1929 ms_info("Failed to gst_ghost_pad_set_target() for %s", pad_name);
1930 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1935 MS_SAFE_GFREE(req_pad_name);
1936 MS_SAFE_UNREF(filter_sink_pad);
1937 MS_SAFE_UNREF(ghost_pad_in);
1938 if (ret != MEDIA_STREAMER_ERROR_NONE && req_pad) {
1939 gst_element_release_request_pad(webrtcbin, req_pad);
1940 g_object_unref(req_pad);
1945 int ms_webrtc_node_check_link_condition(media_streamer_node_s *node, const char *sink_pad_name)
1947 GValue *value = NULL;
1948 const gchar *key = NULL;
1949 const gchar *direction = NULL;
1951 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1952 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
1953 ms_retvm_if(!sink_pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "sink_pad_name is NULL");
1954 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type is not webrtc");
1956 if (!strcmp(sink_pad_name, MEDIA_STREAMER_NODE_PAD_AUDIO_SINK)) {
1957 key = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO;
1958 } else if (!strcmp(sink_pad_name, MEDIA_STREAMER_NODE_PAD_VIDEO_SINK)) {
1959 key = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO;
1961 ms_error("sink_pand_name[%s] is wrong", sink_pad_name);
1962 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1965 value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), key);
1967 ms_error("failed to get [%s] val from [%s]", key, GST_ELEMENT_NAME(node->gst_element));
1968 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1971 if (!(direction = g_value_get_string(value))) {
1972 ms_error("Failed to g_value_get_string()");
1973 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1976 if (!strcmp(direction, WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY) ||
1977 !strcmp(direction, WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE)) {
1978 ms_error("Could not link to [%s] in %s", sink_pad_name, direction);
1979 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1982 return MEDIA_STREAMER_ERROR_NONE;
1984 static int __ms_webrtc_node_update_transceiver_direction_param_value(media_streamer_node_s *node, const gchar *param_name, const gchar *direction)
1986 int ret = MEDIA_STREAMER_ERROR_NONE;
1987 GValue *value = NULL;
1989 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1990 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
1991 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type is not webrtc");
1992 ms_retvm_if(!direction, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "direction is NULL");
1994 ms_debug("direction is [%s]", direction);
1996 value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
1998 ms_error("failed to get [%s] val from [%s]", param_name, GST_ELEMENT_NAME(node->gst_element));
1999 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2002 ret = __ms_param_value_set(value, PARAM_DATA_TYPE_STRING, direction);
2003 if (ret != MEDIA_STREAMER_ERROR_NONE) {
2005 ms_info("update transceiver unknown -> sendrecv");
2011 GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
2013 GstElement *webrtcbin = NULL;
2014 node_info_s *node_klass_type = NULL;
2016 ms_retvm_if(webrtc_node == NULL, NULL, "webrtc_node is NULL");
2017 ms_retvm_if(webrtc_node->gst_element == NULL, NULL, "webrtc_container is NULL");
2021 node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
2022 webrtcbin = ms_find_element_in_bin_by_type(webrtc_node->gst_element, node_klass_type);
2024 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
2031 static int __ms_webrtc_node_set_rtp_transceiver_direction(media_streamer_node_s *webrtc_node)
2033 int ret = MEDIA_STREAMER_ERROR_NONE;
2034 GstElement *webrtcbin = NULL;
2035 GstElement *video_filter = NULL;
2036 GstElement *audio_filter = NULL;
2037 gint transceiver_idx = 0;
2038 gboolean is_linked_video = FALSE;
2039 gboolean is_linked_audio = FALSE;
2040 GstWebRTCRTPTransceiverDirection audio_direction;
2041 GstWebRTCRTPTransceiverDirection video_direction;
2042 const gchar *audio_param_name = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO;
2043 const gchar *video_param_name = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO;
2045 ms_retvm_if(webrtc_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_node is NULL");
2046 ms_retvm_if(webrtc_node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
2049 if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(webrtc_node)))
2050 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2052 if (ms_webrtc_node_get_rtp_transceiver_direction(webrtc_node, audio_param_name, &audio_direction)) {
2053 ms_error("Failed to get WebRTC audio RTP transceiver direction");
2054 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2056 if (ms_webrtc_node_get_rtp_transceiver_direction(webrtc_node, video_param_name, &video_direction)) {
2057 ms_error("Failed to get WebRTC video RTP transceiver direction");
2058 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2061 if ((audio_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "audio_capsfilter")))
2062 is_linked_audio = TRUE;
2064 if ((video_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "video_capsfilter")))
2065 is_linked_video = TRUE;
2067 /* GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE indicates that transceiver direction was not set by user,
2068 it will be changed to sendrecv. */
2069 if (audio_direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE) {
2070 if (is_linked_audio) {
2071 if (__ms_webrtc_node_update_transceiver_direction_param_value(webrtc_node, audio_param_name, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV))
2072 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2075 if (!ms_webrtc_is_valid_transceiver_direction(is_linked_audio, audio_direction))
2076 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2078 if (is_linked_audio)
2079 ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx++, audio_direction);
2081 ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_AUDIO_RTP_FORMAT, audio_direction);
2084 if (video_direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE) {
2085 if (is_linked_video) {
2086 if (__ms_webrtc_node_update_transceiver_direction_param_value(webrtc_node, video_param_name, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV))
2087 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2090 if (!ms_webrtc_is_valid_transceiver_direction(is_linked_video, video_direction))
2091 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2093 if (is_linked_video)
2094 ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx, video_direction);
2096 ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_VIDEO_RTP_FORMAT, video_direction);
2105 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
2107 int ret = MEDIA_STREAMER_ERROR_NONE;
2108 GstElement *webrtcbin = NULL;
2109 GstElement *rtpbin = NULL;
2110 GObject *send_channel = NULL;
2111 gint latency = DEFAULT_MEDIA_STREAMER_RTP_LATENCY;
2112 media_streamer_webrtc_callbacks_s *_callbacks = NULL;
2116 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2117 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2118 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
2120 if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(node)))
2121 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2123 _callbacks = (media_streamer_webrtc_callbacks_s *) node->callbacks_structure;
2124 if (!_callbacks || !(_callbacks->message_cb.callback)) {
2125 ms_error("message callback should be set before preparing");
2126 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2129 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
2130 ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
2131 ms_signal_create(&node->sig_list, webrtcbin, "on-new-transceiver", G_CALLBACK(ms_webrtcbin_on_new_transceiver_cb), NULL);
2132 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
2133 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-connection-state", G_CALLBACK(ms_webrtcbin_notify_ice_connection_state_cb), node);
2135 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_AUDIO_CAPSFILTER)))
2137 if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
2140 /* The transceiver is added when the ghost pad is linked to webrtcbin. Therefore,
2141 the transceiver direction must be update after __ms_webrtc_prepare_ghost_sink_pad(). */
2142 if (__ms_webrtc_node_set_rtp_transceiver_direction(node) != MEDIA_STREAMER_ERROR_NONE) {
2143 ms_error("Failed to set WebRTC RTP transceiver direction");
2144 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2147 if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
2148 ms_error("Failed to set state to READY");
2149 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2152 g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
2154 ms_info("data channel(%p) for sending is created", send_channel);
2156 ms_warning("Failed to create data channel");
2158 ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
2159 ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
2161 if (__ms_node_get_rtp_latency(node, &latency) != MEDIA_STREAMER_ERROR_NONE) {
2162 ms_error("Failed to get rtp latency");
2163 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2166 rtpbin = gst_bin_get_by_name(GST_BIN(webrtcbin), "rtpbin");
2167 g_object_set(G_OBJECT(rtpbin), "latency", latency, NULL);
2168 gst_object_unref(rtpbin);
2170 ms_generate_dots(node->gst_element, "webrtc_prepared");
2174 return MEDIA_STREAMER_ERROR_NONE;
2178 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
2182 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
2183 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2185 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
2186 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
2190 return MEDIA_STREAMER_ERROR_NONE;
2193 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
2195 GParamSpec *param_spec;
2200 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2201 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
2203 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
2204 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].prop_name);
2205 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].prop_name) ||
2206 __ms_adaptive_src_node_has_property(node, param_table[it_param].prop_name)) {
2207 ms_info("param [%s, prop:%s] for node [%s]", param_table[it_param].param_name, param_table[it_param].prop_name, node->name);
2208 *param_list = g_list_append(*param_list, &(param_table[it_param]));
2211 ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
2215 return MEDIA_STREAMER_ERROR_NONE;
2218 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
2220 int ret = MEDIA_STREAMER_ERROR_NONE;
2221 Evas_Object *obj = NULL;
2222 media_streamer_wl_info_s wl_info;
2224 obj = (Evas_Object *)param_value;
2226 /* get wayland parent id */
2227 if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
2228 LOGE("failed to get wayland info");
2229 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2232 LOGD("wayland global surface id : %d", wl_info.parent_id);
2234 gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
2239 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
2241 int ret = MEDIA_STREAMER_ERROR_NONE;
2245 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2246 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
2247 ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
2249 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
2250 ret = __ms_rtp_node_set_property(node, param, param_value);
2255 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2256 ret = __ms_webrtc_node_set_property(node, param, param_value);
2261 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
2262 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
2263 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
2268 switch (param->prop_enum) {
2269 case PROP_NAME_CAMERA_ID: {
2270 int camera_id = ms_get_number_from_string(param_value);
2271 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
2272 g_object_set(node->gst_element, param->prop_name, camera_id, NULL);
2276 case PROP_NAME_CAPTURE_WIDTH:
2277 case PROP_NAME_CAPTURE_HEIGHT:
2278 case PROP_NAME_STREAM_TYPE:
2279 case PROP_NAME_PORT:
2280 case PROP_NAME_ROTATE:
2281 case PROP_NAME_FLIP:
2282 case PROP_NAME_DISPLAY_GEOMETRY_METHOD:
2283 case PROP_NAME_MAX_LATENESS:
2284 g_object_set(node->gst_element, param->prop_name, ms_get_number_from_string(param_value), NULL);
2287 case PROP_NAME_IS_LIVE:
2288 case PROP_NAME_SYNC:
2289 case PROP_NAME_USE_TBM:
2290 case PROP_NAME_VISIBLE:
2291 g_object_set(node->gst_element, param->prop_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
2295 case PROP_NAME_LOCATION:
2296 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
2297 ret = ms_util_uri_path_check(param_value);
2298 if (ret != MEDIA_STREAMER_ERROR_NONE)
2301 g_object_set(node->gst_element, param->prop_name, param_value, NULL);
2304 case PROP_NAME_USER_AGENT:
2305 case PROP_NAME_ADDRESS:
2306 case PROP_NAME_AUDIO_DEVICE:
2307 case PROP_NAME_HOST:
2308 case PROP_NAME_SEGMENT_LOCATION:
2309 case PROP_NAME_PLAYLIST_LOCATION:
2310 g_object_set(node->gst_element, param->prop_name, param_value, NULL);
2313 case PROP_NAME_DISPLAY:
2314 ret = __ms_node_set_display(node, param_value);
2318 ms_info("Can not set parameter [%s, prop:%s] in the node [%s]", param->param_name, param->prop_name, node->name);
2319 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2328 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
2330 int ret = MEDIA_STREAMER_ERROR_NONE;
2331 GList *p_list = NULL;
2332 int written_count = 0;
2333 param_s *param = NULL;
2334 GList *list_iter = NULL;
2335 char *string_val = NULL;
2339 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2340 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
2342 ret = __ms_node_get_param_list(node, &p_list);
2343 if (ret == MEDIA_STREAMER_ERROR_NONE) {
2344 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
2345 param = (param_s *)list_iter->data;
2346 if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
2347 ret = ms_node_set_param_value(node, param, string_val);
2348 if (ret == MEDIA_STREAMER_ERROR_NONE) {
2351 ms_error("failed to set param");
2357 g_list_free(p_list);
2359 ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
2360 if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
2361 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2368 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
2370 int ret = MEDIA_STREAMER_ERROR_NONE;
2371 GList *p_list = NULL;
2372 param_s *param = NULL;
2373 GList *list_iter = NULL;
2374 char *string_val = NULL;
2378 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2379 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
2381 ret = __ms_node_get_param_list(node, &p_list);
2382 if (ret == MEDIA_STREAMER_ERROR_NONE) {
2383 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
2384 param = (param_s *)list_iter->data;
2386 if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
2387 bundle_add_str(param_list, param->param_name, string_val);
2388 MS_SAFE_FREE(string_val);
2393 g_list_free(p_list);
2400 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
2402 GParamSpec *param_spec;
2403 gboolean found_param = FALSE;
2408 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2409 ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
2410 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
2412 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
2413 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
2414 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].prop_name);
2415 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].prop_name) ||
2416 __ms_adaptive_src_node_has_property(node, param_table[it_param].prop_name) ||
2417 __ms_webrtc_node_has_property(node, param_table[it_param].prop_name)) {
2418 *param = &(param_table[it_param]);
2419 ms_info("param [%s, prop:%s] for node [%s]", (*param)->param_name, (*param)->prop_name, node->name);
2425 ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
2429 return MEDIA_STREAMER_ERROR_NONE;
2432 static gchar *__ms_convert_prop_value_to_string(param_s *param, const GValue *value)
2434 ms_retvm_if(param == NULL, NULL, "param is NULL");
2435 ms_retvm_if(value == NULL, NULL, "value is NULL");
2437 switch (param->data_type) {
2438 case PARAM_DATA_TYPE_NUMBER:
2439 if (G_VALUE_HOLDS_INT(value))
2440 return g_strdup_printf("%d", g_value_get_int(value));
2442 return g_strdup_printf("%u", g_value_get_uint(value));
2444 case PARAM_DATA_TYPE_BOOL:
2445 return g_strdup(g_value_get_boolean(value) ? "true" : "false");
2447 case PARAM_DATA_TYPE_STRING:
2448 return g_value_dup_string(value);
2450 case PARAM_DATA_TYPE_ENUM:
2451 return g_strdup_printf("%d", g_value_get_enum(value));
2454 ms_error("should not be reached here, param[name:%s, type:%d]", param->param_name, param->data_type);
2459 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
2461 int ret = MEDIA_STREAMER_ERROR_NONE;
2462 gchar *prop_val_str = NULL;
2463 GParamSpec *param_spec = NULL;
2464 GValue value = G_VALUE_INIT;
2466 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2467 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
2468 ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
2470 ms_debug("node[%s] prop_name[%s]", node->name, param->prop_name);
2472 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
2473 ret = __ms_rtp_node_get_property(node, param, &value);
2474 else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
2475 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
2476 ret = __ms_adaptive_src_node_get_property(node, param, &value);
2478 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->prop_name);
2480 g_value_init(&value, param_spec->value_type);
2481 g_object_get_property(G_OBJECT(node->gst_element), param->prop_name, &value);
2483 ms_info("param [%s, prop:%s] for node [%s] with description [%s]",
2484 param->param_name, param->prop_name, node->name, g_param_spec_get_blurb(param_spec));
2486 ms_error("There is no prop_name [%s] for node [%s]", param->prop_name, node->name);
2487 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2491 prop_val_str = __ms_convert_prop_value_to_string(param, &value);
2492 *string_value = prop_val_str ? strdup(prop_val_str) : NULL;
2493 g_free(prop_val_str);
2495 g_value_reset(&value);
2496 g_value_unset(&value);
2498 ms_debug("string_value[%s]", *string_value);
2503 static int __ms_rtp_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2505 int ret = MEDIA_STREAMER_ERROR_NONE;
2506 media_format_mimetype_e mime;
2507 gchar *rtp_caps_str = NULL;
2509 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2510 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2511 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2512 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2516 /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
2517 if (g_strrstr(pad_name, MS_PAD_VIDEO_IN)) {
2518 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
2519 if (MEDIA_FORMAT_ERROR_NONE == ret) {
2520 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));
2521 param_s param = {MS_PARAM_VIDEO_IN_FORMAT, MS_PARAM_VIDEO_IN_FORMAT};
2522 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
2524 } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
2525 int audio_channels, audio_samplerate;
2526 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
2527 if (MEDIA_FORMAT_ERROR_NONE == ret) {
2528 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");
2529 param_s param = {MS_PARAM_AUDIO_IN_FORMAT, MS_PARAM_AUDIO_IN_FORMAT};
2530 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
2533 ms_error("[%s]'s pad [%s] can't be set with the given format", GST_ELEMENT_NAME(node->gst_element), pad_name);
2534 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2536 MS_SAFE_GFREE(rtp_caps_str);
2542 static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2544 int ret = MEDIA_STREAMER_ERROR_NONE;
2545 media_format_mimetype_e mime;
2546 const gchar *encoding_name = NULL;
2547 const gchar *capsfilter_name = NULL;
2548 gchar *caps_str = NULL;
2549 gchar *media = NULL;
2551 GstCaps *caps = NULL;
2552 GstElement *capsfilter = NULL;
2554 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2555 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2556 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2557 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2561 if (!g_strrstr(pad_name, MS_PAD_VIDEO_IN) && !g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
2562 ms_error("Not supported pad_name(%s)", pad_name);
2563 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2566 if (g_strrstr(pad_name, MS_PAD_VIDEO_IN) &&
2567 !media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2570 capsfilter_name = _WEBRTC_VIDEO_CAPSFILTER;
2571 } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN) &&
2572 !media_format_get_audio_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2575 capsfilter_name = _WEBRTC_AUDIO_CAPSFILTER;
2577 ms_error("Invalid media format for pad_name(%s)", pad_name);
2578 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2581 encoding_name = ms_convert_mime_to_rtp_format(mime);
2582 caps = gst_caps_new_simple("application/x-rtp",
2583 "media", G_TYPE_STRING, media,
2584 "encoding-name", G_TYPE_STRING, encoding_name,
2585 "payload", G_TYPE_INT, payload, NULL);
2587 if (!(capsfilter = ms_find_element_in_bin_by_name(node->gst_element, capsfilter_name))) {
2588 ms_debug("Create %s", capsfilter_name);
2590 if (!(capsfilter = ms_element_create("capsfilter", capsfilter_name))) {
2591 ms_error("Failed to create capsfilter element: %s", capsfilter_name);
2592 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2594 if (!ms_bin_add_element(node->gst_element, capsfilter, FALSE)) {
2595 ms_error("Failed to add capsfilter(%s) to webrtc_container", capsfilter_name);
2596 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2600 g_object_set(G_OBJECT(capsfilter), "caps", (GValue *)caps, NULL);
2602 caps_str = gst_caps_to_string(caps);
2603 ms_info("[%s] is set to [%s]", caps_str, capsfilter_name);
2604 MS_SAFE_GFREE(caps_str);
2606 gst_caps_unref(caps);
2612 static int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2614 gboolean can_accept = FALSE;
2615 GstElement *element = NULL;
2616 GstCaps *fmt_caps = NULL;
2617 GstElementFactory *factory = NULL;
2618 GstPad *node_pad = NULL;
2620 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2621 ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2622 ms_retvm_if(!pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2623 ms_retvm_if(!fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2625 element = node->gst_element;
2627 fmt_caps = ms_create_caps_from_fmt(fmt, nodes_info[node->type].default_name);
2628 ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps");
2630 factory = gst_element_get_factory(element);
2631 node_pad = gst_element_get_static_pad(element, pad_name);
2633 gst_caps_unref(fmt_caps);
2634 ms_error("Failed to gst_element_get_static_pad(), pad_name[%s]", pad_name);
2635 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2638 if (GST_PAD_IS_SRC(node_pad))
2639 can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps);
2640 else if (GST_PAD_IS_SINK(node_pad))
2641 can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps);
2643 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2645 MS_SAFE_UNREF(node_pad);
2648 gst_caps_unref(fmt_caps);
2649 ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name);
2650 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2653 MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2654 gst_caps_unref(fmt_caps);
2656 ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2658 return MEDIA_STREAMER_ERROR_NONE;
2661 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2663 int ret = MEDIA_STREAMER_ERROR_NONE;
2667 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2668 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2669 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2670 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2672 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
2673 ret = __ms_rtp_node_set_pad_format(node, pad_name, fmt);
2674 else if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
2675 ret = __ms_webrtc_node_set_pad_format(node, pad_name, fmt);
2677 ret = __ms_node_set_pad_format(node, pad_name, fmt);
2684 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
2686 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2687 media_streamer_node_s *node = NULL;
2688 GstElement *element = NULL;
2692 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2693 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2694 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2696 g_value_set_boolean(ret, FALSE);
2698 element = GST_ELEMENT(g_value_get_object(item));
2699 g_object_ref(element);
2701 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2702 GST_ELEMENT_NAME(element));
2704 /* If we fail to find corresponding node inside streamer
2705 then apparently this element doesn't require resources. */
2706 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2707 g_value_set_boolean(ret, TRUE);
2708 g_object_unref(element);
2712 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
2713 ms_error("Failed to acquire resource for node [%s]", node->name);
2714 g_object_unref(element);
2718 g_value_set_boolean(ret, TRUE);
2720 g_object_unref(element);
2727 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
2729 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2730 media_streamer_node_s *node = NULL;
2731 GstElement *element = NULL;
2735 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2736 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2737 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2739 g_value_set_boolean(ret, FALSE);
2741 element = GST_ELEMENT(g_value_get_object(item));
2742 g_object_ref(element);
2744 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2745 GST_ELEMENT_NAME(element));
2747 /* If we fail to find corresponding node inside streamer
2748 then apparently this element doesn't require resources. */
2749 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2750 g_value_set_boolean(ret, TRUE);
2751 g_object_unref(element);
2755 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
2756 ms_error("Failed to release resource for node [%s]", node->name);
2757 g_object_unref(element);
2761 g_value_set_boolean(ret, TRUE);
2763 g_object_unref(element);
2770 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
2772 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2773 media_streamer_node_s *node = NULL;
2774 GstElement *element = NULL;
2775 gboolean allowed = FALSE;
2779 ms_retvm_if(item == NULL, FALSE, "item is NULL");
2780 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2781 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2782 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2784 element = GST_ELEMENT(g_value_get_object(item));
2785 g_object_ref(element);
2787 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2788 GST_ELEMENT_NAME(element));
2790 /* If we fail to find corresponding node inside streamer
2791 then apparently this element doesn't require resources. */
2792 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2793 g_value_set_boolean(ret, TRUE);
2794 g_object_unref(element);
2798 if (ms_node_dpm_policy_check(node, &allowed)) {
2799 ms_error("Failed to check DPM policy for node [%s]", node->name);
2800 /* Note that it should be TRUE(allowed) if the DPM API failed. */
2801 g_value_set_boolean(ret, TRUE);
2802 g_object_unref(element);
2806 g_value_set_boolean(ret, allowed);
2808 g_object_unref(element);
2816 int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
2819 const gchar *type = NULL;
2821 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
2822 ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
2824 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2825 ms_error("Invalid node type");
2826 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2829 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
2831 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
2832 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2835 if (!(type = g_value_get_string(val))) {
2836 ms_error("Failed to g_value_get_string()");
2837 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2840 ms_info("peer type is [%s]", type);
2842 *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
2844 return MEDIA_STREAMER_ERROR_NONE;