7894eb81f912fb490defc6fb643f988cb8648430
[platform/core/api/mediastreamer.git] / src / media_streamer_node.c
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <cynara-client.h>
18 #include <system_info.h>
19 #include <sys/smack.h>
20 #include <Evas.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"
28
29 #define SMACK_LABEL_LEN 255
30 #define DEFAULT_URI_SCHEME_LENGTH 10
31
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"
37
38 #define _WEBRTC_AUDIO_CAPSFILTER         "audio_capsfilter"
39 #define _WEBRTC_VIDEO_CAPSFILTER         "video_capsfilter"
40
41 static param_s param_table[] = {
42         {
43                 MEDIA_STREAMER_PARAM_CAMERA_ID,
44                 "camera-id",
45                 PROP_NAME_CAMERA_ID,
46                 PARAM_DATA_TYPE_NUMBER
47         },
48         {
49                 MEDIA_STREAMER_PARAM_CAPTURE_WIDTH,
50                 "capture-width",
51                 PROP_NAME_CAPTURE_WIDTH,
52                 PARAM_DATA_TYPE_NUMBER
53         },
54         {
55                 MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT,
56                 "capture-height",
57                 PROP_NAME_CAPTURE_HEIGHT,
58                 PARAM_DATA_TYPE_NUMBER
59         },
60         {
61                 MEDIA_STREAMER_PARAM_IS_LIVE_STREAM,
62                 "is-live",
63                 PROP_NAME_IS_LIVE,
64                 PARAM_DATA_TYPE_BOOL
65         },
66         {
67                 MEDIA_STREAMER_PARAM_IS_LIVE_STREAM,
68                 "living",
69                 PROP_NAME_LIVING,
70                 PARAM_DATA_TYPE_BOOL
71         },
72         {
73                 MEDIA_STREAMER_PARAM_URI,
74                 "uri",
75                 PROP_NAME_URI,
76                 PARAM_DATA_TYPE_STRING
77         },
78         {
79                 MEDIA_STREAMER_PARAM_URI,
80                 "location",
81                 PROP_NAME_LOCATION,
82                 PARAM_DATA_TYPE_STRING
83         },
84         {
85                 MEDIA_STREAMER_PARAM_USER_AGENT,
86                 "user-agent",
87                 PROP_NAME_USER_AGENT,
88                 PARAM_DATA_TYPE_STRING
89         },
90         {
91                 MEDIA_STREAMER_PARAM_STREAM_TYPE,
92                 "stream-type",
93                 PROP_NAME_STREAM_TYPE,
94                 PARAM_DATA_TYPE_ENUM
95         },
96         {
97                 MEDIA_STREAMER_PARAM_PORT,
98                 "port",
99                 PROP_NAME_PORT,
100                 PARAM_DATA_TYPE_NUMBER
101         },
102         {
103                 MEDIA_STREAMER_PARAM_RTP_LATENCY,
104                 "rtp-latency",
105                 PROP_NAME_RTP_LATENCY,
106                 PARAM_DATA_TYPE_NUMBER
107         },
108         {
109                 MEDIA_STREAMER_PARAM_VIDEO_IN_PORT,
110                 "video_in_port",
111                 PROP_NAME_VIDEO_IN_PORT,
112                 PARAM_DATA_TYPE_NUMBER
113         },
114         {
115                 MEDIA_STREAMER_PARAM_AUDIO_IN_PORT,
116                 "audio_in_port",
117                 PROP_NAME_AUDIO_IN_PORT,
118                 PARAM_DATA_TYPE_NUMBER
119         },
120         {
121                 MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT,
122                 "video_out_port",
123                 PROP_NAME_VIDEO_OUT_PORT,
124                 PARAM_DATA_TYPE_NUMBER
125         },
126         {
127                 MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT,
128                 "audio_out_port",
129                 PROP_NAME_AUDIO_OUT_PORT,
130                 PARAM_DATA_TYPE_NUMBER
131         },
132         {
133                 MEDIA_STREAMER_PARAM_IP_ADDRESS,
134                 "address",
135                 PROP_NAME_ADDRESS,
136                 PARAM_DATA_TYPE_STRING
137         },
138         {
139                 MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE,
140                 "webrtc-peer-type",
141                 PROP_NAME_WEBRTC_PEER_TYPE,
142                 PARAM_DATA_TYPE_STRING
143         },
144         {
145                 MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER,
146                 "webrtc-stun-server",
147                 PROP_NAME_WEBRTC_STUN_SERVER,
148                 PARAM_DATA_TYPE_STRING
149         },
150         {
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
155         },
156         {
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
161         },
162         {
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
167         },
168         {
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
173         },
174         {
175                 MEDIA_STREAMER_PARAM_AUDIO_DEVICE,
176                 "audio_device",
177                 PROP_NAME_AUDIO_DEVICE,
178                 PARAM_DATA_TYPE_STRING
179         },
180         {
181                 MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED,
182                 "sync",
183                 PROP_NAME_SYNC,
184                 PARAM_DATA_TYPE_BOOL
185         },
186         {
187                 MEDIA_STREAMER_PARAM_ROTATE,
188                 "rotate",
189                 PROP_NAME_ROTATE,
190                 PARAM_DATA_TYPE_ENUM
191         },
192         {
193                 MEDIA_STREAMER_PARAM_FLIP,
194                 "flip",
195                 PROP_NAME_FLIP,
196                 PARAM_DATA_TYPE_ENUM
197         },
198         {
199                 MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD,
200                 "display-geometry-method",
201                 PROP_NAME_DISPLAY_GEOMETRY_METHOD,
202                 PARAM_DATA_TYPE_ENUM
203         },
204         {
205                 MEDIA_STREAMER_PARAM_DISPLAY,
206                 "display",
207                 PROP_NAME_DISPLAY,
208                 PARAM_DATA_TYPE_POINTER
209         },
210         {
211                 MEDIA_STREAMER_PARAM_VISIBLE,
212                 "visible",
213                 PROP_NAME_VISIBLE,
214                 PARAM_DATA_TYPE_BOOL
215         },
216         {
217                 MEDIA_STREAMER_PARAM_USE_TBM,
218                 "use-tbm",
219                 PROP_NAME_USE_TBM,
220                 PARAM_DATA_TYPE_BOOL
221         },
222         {
223                 MEDIA_STREAMER_PARAM_HOST,
224                 "host",
225                 PROP_NAME_HOST,
226                 PARAM_DATA_TYPE_STRING
227         },
228         {
229                 MEDIA_STREAMER_PARAM_SEGMENT_LOCATION,
230                 "location",
231                 PROP_NAME_SEGMENT_LOCATION,
232                 PARAM_DATA_TYPE_STRING
233         },
234         {
235                 MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION,
236                 "playlist-location",
237                 PROP_NAME_PLAYLIST_LOCATION,
238                 PARAM_DATA_TYPE_STRING
239         },
240         {
241                 MEDIA_STREAMER_PARAM_SINK_MAX_LATENESS,
242                 "max-lateness",
243                 PROP_NAME_MAX_LATENESS,
244                 PARAM_DATA_TYPE_NUMBER
245         },
246         {
247                 NULL,
248                 NULL,
249                 PROP_NAME_MAX,
250                 PARAM_DATA_TYPE_MAX
251         }
252 };
253
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 */
285         {NULL, NULL}
286 };
287
288 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
289 {
290         GValue *val = NULL;
291
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");
295
296         if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
297                 return FALSE;
298
299         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
300
301         ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
302
303         return val ? TRUE : FALSE;
304 }
305
306 static int __ms_param_value_init(GValue *value, param_data_type_e type)
307 {
308         ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER , "value is NULL");
309
310         switch (type) {
311         case PARAM_DATA_TYPE_NUMBER:
312                 g_value_init(value, G_TYPE_INT);
313                 break;
314         case PARAM_DATA_TYPE_BOOL:
315                 g_value_init(value, G_TYPE_BOOLEAN);
316                 break;
317         case PARAM_DATA_TYPE_STRING:
318                 g_value_init(value, G_TYPE_STRING);
319                 break;
320         case PARAM_DATA_TYPE_ENUM:
321                 g_value_init(value, G_TYPE_ENUM);
322                 break;
323         case PARAM_DATA_TYPE_POINTER:
324                 g_value_init(value, G_TYPE_POINTER);
325                 break;
326         default:
327                 ms_error("not supported type[%d]", type);
328                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
329         }
330
331         return MEDIA_STREAMER_ERROR_NONE;
332 }
333
334 static int __ms_param_value_set(GValue *value, param_data_type_e type, const char *param_value)
335 {
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");
338
339         switch (type) {
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));
344                 break;
345
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);
353                 } else {
354                         ms_error("invalid parameter[%s] for PARAM_DATA_TYPE_BOOL", param_value);
355                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
356                 }
357                 break;
358
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);
363                 break;
364
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));
369                 break;
370
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);
375                 break;
376
377         default:
378                 ms_error("not supported type[%d]", type);
379                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
380         }
381
382         return MEDIA_STREAMER_ERROR_NONE;
383 }
384
385 static void __ms_param_value_print(GValue *value, param_data_type_e type)
386 {
387         ms_retm_if(!value, "value is NULL");
388
389         switch (type) {
390         case PARAM_DATA_TYPE_NUMBER:
391                 if (G_VALUE_HOLDS_INT(value))
392                         ms_debug("value[%d]", g_value_get_int(value));
393                 else
394                         ms_debug("value[%u]", g_value_get_uint(value));
395                 break;
396         case PARAM_DATA_TYPE_BOOL:
397                 ms_debug("value[%d]", g_value_get_boolean(value));
398                 break;
399         case PARAM_DATA_TYPE_STRING:
400                 ms_debug("value[%s]", g_value_get_string(value));
401                 break;
402         case PARAM_DATA_TYPE_ENUM:
403                 ms_debug("value[%d]", g_value_get_enum(value));
404                 break;
405         case PARAM_DATA_TYPE_POINTER:
406                 ms_debug("value[%p]", g_value_get_pointer(value));
407                 break;
408         default:
409                 ms_error("not supported type[%d]", type);
410                 break;
411         }
412 }
413
414 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
415 {
416         int ret = MEDIA_STREAMER_ERROR_NONE;
417         GValue *val = NULL;
418
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");
424
425         ms_debug("param[%s]", param->param_name);
426
427         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
428         if (!val) {
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;
431         }
432
433         ret = __ms_param_value_init(value, param->data_type);
434         if (ret != MEDIA_STREAMER_ERROR_NONE)
435                 return ret;
436
437         g_value_copy(val, value);
438
439         __ms_param_value_print(value, param->data_type);
440
441         return ret;
442 }
443
444 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
445 {
446         int ret = MEDIA_STREAMER_ERROR_NONE;
447         GValue *val = NULL;
448
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");
454
455         ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
456
457         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
458         if (!val) {
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;
461         }
462
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);
466                 if (caps) {
467                         g_value_unset(val);
468                         g_value_init(val, GST_TYPE_CAPS);
469                         gst_value_set_caps(val, caps);
470                 } else {
471                         ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
472                 }
473         } else {
474                 ret = __ms_param_value_set(val, param->data_type, param_value);
475         }
476
477         ms_debug_fleave();
478
479         return ret;
480 }
481
482 //LCOV_EXCL_START
483 static int __ms_node_get_rtp_latency(media_streamer_node_s *node, int *latency)
484 {
485         GValue *val = NULL;
486
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");
491
492         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_RTP_LATENCY);
493         if (!val) {
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;
496         }
497
498         if (!(*latency = g_value_get_int(val))) {
499                 ms_error("Failed to g_value_get_int()");
500                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
501         }
502
503         ms_info("RTP latency is [%d]", *latency);
504
505         return MEDIA_STREAMER_ERROR_NONE;
506 }
507
508 static int __ms_webrtc_node_check_transceiver_direction_param_value(media_streamer_node_s *node, param_s *param, const gchar *param_value)
509 {
510         GstWebRTCRTPTransceiverDirection direction;
511         GstGhostPad *ghost_pad = NULL;
512         const gchar *pad_name;
513         gboolean is_linked = FALSE;
514
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");
520
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;
525         else
526                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
527
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;
531         }
532
533         is_linked = gst_pad_is_linked((GstPad *)ghost_pad);
534         MS_SAFE_UNREF(ghost_pad);
535
536         ms_debug("[%s] %s", pad_name, is_linked ? "is linked" : "isn't linked");
537
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;
546         } else {
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;
549         }
550
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;
554         }
555
556         return MEDIA_STREAMER_ERROR_NONE;
557 }
558
559 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
560 {
561         GValue *val = NULL;
562
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");
566
567         if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC)
568                 return FALSE;
569
570         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
571
572         ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
573
574         return val ? TRUE : FALSE;
575 }
576
577 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
578 {
579         GValue *val = NULL;
580         int ret;
581
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");
587
588         ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
589
590         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
591         if (!val) {
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;
594         }
595
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;
601                 }
602                 ret = __ms_param_value_set(val, param->data_type, param_value);
603                 break;
604
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);
609                         return ret;
610                 }
611                 ret = __ms_param_value_set(val, param->data_type, param_value);
612                 break;
613
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);
618                         return ret;
619                 }
620                 ret = __ms_param_value_set(val, param->data_type, param_value);
621                 break;
622
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);
627                         return ret;
628                 }
629                 break;
630
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);
636                         return ret;
637                 }
638
639                 ret = __ms_param_value_set(val, param->data_type, param_value);
640                 break;
641
642         case PROP_NAME_RTP_LATENCY:
643                 ret = __ms_param_value_set(val, param->data_type, param_value);
644                 break;
645
646         default:
647                 ms_error("failed to set property, undefined param name[%s]", param->param_name);
648                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
649         }
650
651         return ret;
652 }
653 //LCOV_EXCL_STOP
654
655 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
656 {
657         GValue *val = NULL;
658
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");
662
663         if (node->type != MEDIA_STREAMER_NODE_TYPE_SRC ||
664                 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
665                 return FALSE;
666
667         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
668
669         ms_debug("node[%s] %s [%s]", node->name, val ? "has" : "does not have", param_name);
670
671         return val ? TRUE : FALSE;
672 }
673
674 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
675 {
676         int ret = MEDIA_STREAMER_ERROR_NONE;
677         GValue *val = NULL;
678
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");
685
686         ms_debug("param[%s]", param->param_name);
687
688         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
689         if (!val) {
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;
692         }
693
694         ret = __ms_param_value_init(value, param->data_type);
695         if (ret != MEDIA_STREAMER_ERROR_NONE)
696                 return ret;
697
698         g_value_copy(val, value);
699
700         __ms_param_value_print(value, param->data_type);
701
702         return ret;
703 }
704
705 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
706 {
707         int ret = MEDIA_STREAMER_ERROR_NONE;
708         GValue *val = NULL;
709
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");
716
717         ms_debug("param[%s] param_value[%s]", param->param_name, param_value);
718
719         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
720         if (!val) {
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;
723         }
724
725         ret = __ms_param_value_set(val, param->data_type, param_value);
726
727         return ret;
728 }
729
730 static int __ms_node_check_privileges(media_streamer_node_s *node)
731 {
732         int ret = MEDIA_STREAMER_ERROR_NONE;
733         int ret_val = 0;
734         char *privilege = NULL;
735         char uid[10];
736         cynara *cynara_h = NULL;
737         char *smack_label;
738
739         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
740
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";
745                         break;
746                 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
747                         privilege = "http://tizen.org/privilege/internet";
748                         break;
749                 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
750                         privilege = "http://tizen.org/privilege/camera";
751                         break;
752                 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
753                         privilege = "http://tizen.org/privilege/recorder";
754                         break;
755                 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
756                         privilege = "http://tizen.org/privilege/camera";
757                         break;
758                 default:
759                         ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
760                         break;
761                 }
762         }
763
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";
768                         break;
769                 default:
770                         ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
771                         break;
772                 }
773         }
774
775         if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
776                 privilege = "http://tizen.org/privilege/internet";
777
778         /* Skip checking for privilege permission in case of other types of Nodes */
779         if (privilege == NULL)
780                 return ret;
781
782         ms_retvm_if(cynara_initialize(&cynara_h, NULL) != CYNARA_API_SUCCESS, MEDIA_STREAMER_ERROR_INVALID_OPERATION,
783                 "failed to cynara_initialize()");
784
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()");
787
788         snprintf(uid, sizeof(uid), "%d", getuid());
789         ms_debug("smack_label[%s] uid[%s] privilege[%s]", smack_label, uid, privilege);
790
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);
794
795         switch (ret_val) {
796         case CYNARA_API_ACCESS_ALLOWED:
797                 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
798                 break;
799         case CYNARA_API_ACCESS_DENIED:
800         default:
801                 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
802                 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
803                 break;
804         }
805
806         cynara_finish(cynara_h);
807
808         free(smack_label);
809
810         return ret;
811 }
812
813 static int __ms_node_check_feature(media_streamer_node_s *node)
814 {
815         bool enabled = FALSE;
816
817         ms_debug_fenter();
818
819         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
820
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);
825                         if (enabled)
826                                 return MEDIA_STREAMER_ERROR_NONE;
827                 }
828                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
829                         ms_info("telephony status = %d", enabled);
830                         if (enabled)
831                                 return MEDIA_STREAMER_ERROR_NONE;
832                 }
833                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
834                         ms_info("ethernet status = %d", enabled);
835                         if (enabled)
836                                 return MEDIA_STREAMER_ERROR_NONE;
837                 }
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;
840         default:
841                 ms_debug("For current node type[%d], feature is not needed", node->type);
842                 break;
843         }
844
845         ms_debug_fleave();
846
847         return MEDIA_STREAMER_ERROR_NONE;
848 }
849
850 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
851 {
852         int ret = MEDIA_STREAMER_ERROR_NONE;
853         GstCaps *sink_caps = NULL;
854         GstCaps *src_caps = NULL;
855
856         ms_debug_fenter();
857
858         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
859
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);
863                 return ret;
864         }
865
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);
869                 return ret;
870         }
871
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;
874
875         node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL, out_fmt};
876
877         ms_info("Creating node with info: klass_name[%s]; default[%s]",
878                         plug_info.info->klass_name, plug_info.info->default_name);
879
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);
883         else
884                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
885
886         if (src_caps)
887                         gst_caps_unref(src_caps);
888
889         if (sink_caps)
890                         gst_caps_unref(sink_caps);
891
892         ms_debug_fleave();
893
894         return ret;
895 }
896
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)
900 {
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;
904
905         ms_debug_fenter();
906
907         ms_retm_if(ms_src == NULL, "data is NULL");
908         ms_retm_if(pipeline == NULL, "pipeline is NULL");
909
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);
914         }
915
916         ms_debug_fleave();
917 }
918
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)
922 {
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;
926
927         ms_debug_fenter();
928
929         ms_retm_if(ms_src == NULL, "data is NULL");
930         ms_retm_if(pipeline == NULL, "pipeline is NULL");
931
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);
936         }
937
938         ms_debug_fleave();
939 }
940
941 static int __ms_src_node_check_feature(media_streamer_node_s *node)
942 {
943         int ret = MEDIA_STREAMER_ERROR_NONE;
944         bool enabled = FALSE;
945         bool supported = FALSE;
946
947         ms_debug_fenter();
948
949         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
950
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);
957                         if (enabled)
958                                 supported = TRUE;
959                 } else {
960                         ms_error("SYSTEM_INFO_ERROR");
961                 }
962
963                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
964                         ms_info("telephony status = %d", enabled);
965                         if (enabled)
966                                 supported = TRUE;
967                 } else {
968                         ms_error("SYSTEM_INFO_ERROR");
969                 }
970
971                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
972                         ms_info("ethernet status = %d", enabled);
973                         if (enabled)
974                                 supported = TRUE;
975                 } else {
976                         ms_error("SYSTEM_INFO_ERROR");
977                 }
978                 if (!supported)
979                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
980                 break;
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);
984                         if (enabled)
985                                 supported = TRUE;
986                 } else {
987                         ms_error("SYSTEM_INFO_ERROR");
988                 }
989                 if (!supported)
990                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
991                 break;
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);
996                         if (enabled)
997                                 supported = TRUE;
998                 } else {
999                         ms_error("SYSTEM_INFO_ERROR");
1000                 }
1001                 if (!supported)
1002                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
1003                 break;
1004         default:
1005                 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
1006                 break;
1007         }
1008
1009         ms_debug_fleave();
1010
1011         return ret;
1012 }
1013
1014 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
1015 {
1016         int ret = MEDIA_STREAMER_ERROR_NONE;
1017         bool enabled = FALSE;
1018         bool supported = FALSE;
1019
1020         ms_debug_fenter();
1021
1022         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1023
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);
1030                         if (enabled)
1031                                 supported = TRUE;
1032                 } else {
1033                         ms_error("SYSTEM_INFO_ERROR");
1034                 }
1035
1036                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
1037                         ms_info("telephony status = %d", enabled);
1038                         if (enabled)
1039                                 supported = TRUE;
1040                 } else {
1041                         ms_error("SYSTEM_INFO_ERROR");
1042                 }
1043
1044                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
1045                         ms_info("ethernet status = %d", enabled);
1046                         if (enabled)
1047                                 supported = TRUE;
1048                 } else {
1049                         ms_error("SYSTEM_INFO_ERROR");
1050                 }
1051                 if (!supported)
1052                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
1053                 break;
1054         default:
1055                 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
1056                 break;
1057         }
1058
1059         ms_debug_fleave();
1060
1061         return ret;
1062 }
1063
1064 int ms_src_node_create(media_streamer_node_s *node)
1065 {
1066         int ret = MEDIA_STREAMER_ERROR_NONE;
1067         char *plugin_name = NULL;
1068
1069         ms_debug_fenter();
1070
1071         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
1072
1073         ret = __ms_node_check_privileges(node);
1074         if (ret != MEDIA_STREAMER_ERROR_NONE) {
1075                 ms_error("Error getting privileges for Src Node");
1076                 return ret;
1077         }
1078
1079         ret = __ms_src_node_check_feature(node);
1080         if (ret != MEDIA_STREAMER_ERROR_NONE) {
1081                 ms_error("Error getting feature for Src Node");
1082                 return ret;
1083         }
1084
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);
1089                 break;
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);
1093                 break;
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);
1097                 break;
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);
1101                 break;
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);
1105                 break;
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);
1109                 break;
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);
1113                 break;
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);
1117                 break;
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);
1124                 break;
1125         case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
1126                 node->gst_element = ms_adaptive_element_create();
1127                 break;
1128         default:
1129                 ms_error("Error: invalid Src node Type [%d]", node->subtype);
1130                 break;
1131         }
1132
1133         MS_SAFE_FREE(plugin_name);
1134
1135         if (node->gst_element == NULL)
1136                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1137         else
1138                 node->name = gst_element_get_name(node->gst_element);
1139
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);
1143                 return ret;
1144         }
1145
1146         ms_debug_fleave();
1147
1148         return ret;
1149 }
1150
1151 /* The appsink has received a buffer */
1152 static GstFlowReturn __ms_sink_new_sample_cb(GstElement *sink, gpointer *data)
1153 {
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;
1157
1158         ms_retvm_if(ms_sink == NULL, GST_FLOW_ERROR, "data is NULL");
1159
1160         if (!ms_sink->callbacks_structure) {
1161                 ms_debug("callbacks_structure is NULL");
1162                 return GST_FLOW_OK;
1163         }
1164
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;
1167
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");
1172         } else {
1173                 ms_debug("data ready callback is NULL");
1174         }
1175
1176         return GST_FLOW_OK;
1177 }
1178
1179 //LCOV_EXCL_START
1180 static void __ms_sink_eos_cb(GstElement *sink, gpointer *data)
1181 {
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;
1185
1186         ms_retm_if(ms_sink == NULL, "data is NULL");
1187
1188         if (!ms_sink->callbacks_structure) {
1189                 ms_debug("callbacks_structure is NULL");
1190                 return;
1191         }
1192
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;
1195
1196         if (eos_cb) {
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");
1200         } else {
1201                 ms_debug("eos callback is NULL");
1202         }
1203 }
1204 //LCOV_EXCL_STOP
1205
1206 int ms_sink_node_create(media_streamer_node_s *node)
1207 {
1208         int ret = MEDIA_STREAMER_ERROR_NONE;
1209         char *plugin_name = NULL;
1210
1211         ms_debug_fenter();
1212
1213         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1214
1215         ret = __ms_node_check_privileges(node);
1216         if (ret != MEDIA_STREAMER_ERROR_NONE) {
1217                 ms_error("Error getting privileges for Sink Node");
1218                 return ret;
1219         }
1220
1221         ret = __ms_sink_node_check_feature(node);
1222         if (ret != MEDIA_STREAMER_ERROR_NONE) {
1223                 ms_error("Error getting feature for Sink Node");
1224                 return ret;
1225         }
1226
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);
1231                 break;
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);
1235                 break;
1236         case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
1237                 ms_error("Error: not implemented yet");
1238                 break;
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);
1242                 break;
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);
1246                 break;
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);
1250                 break;
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);
1258                 }
1259                 break;
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");
1263
1264                 if (g_strrstr(plugin_name, "hlssink")) {
1265                         g_object_set(G_OBJECT(node->gst_element),
1266                                         "max-files", 0,
1267                                         "playlist-length", 0, NULL);
1268                 }
1269                 break;
1270         default:
1271                 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
1272                 break;
1273         }
1274
1275         MS_SAFE_FREE(plugin_name);
1276
1277         if (node->gst_element == NULL)
1278                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1279         else
1280                 node->name = gst_element_get_name(node->gst_element);
1281
1282         ms_debug_fleave();
1283
1284         return ret;
1285 }
1286
1287 void ms_node_destroy(media_streamer_node_s *node)
1288 {
1289         gchar *node_name = NULL;
1290
1291         ms_debug_fenter();
1292
1293         ms_retm_if(node == NULL, "node is NULL");
1294         node_name = g_strdup(node->name);
1295
1296         /* Disconnects and clean all node signals */
1297         g_list_free_full(node->sig_list, ms_signal_destroy);
1298
1299         /* Deinitialize policy manager */
1300         if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
1301                 ms_error("Failed to deinitialize DPM policy");
1302
1303         MS_SAFE_UNREF(node->gst_element);
1304         MS_SAFE_FREE(node->name);
1305         MS_SAFE_FREE(node->callbacks_structure);
1306         MS_SAFE_FREE(node);
1307
1308         ms_info("Node [%s] has been destroyed", node_name);
1309         MS_SAFE_GFREE(node_name);
1310
1311         ms_debug_fleave();
1312 }
1313
1314 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1315 {
1316         int ret = MEDIA_STREAMER_ERROR_NONE;
1317         GstElement *bin = NULL;
1318
1319         ms_debug_fenter();
1320
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");
1323
1324         ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1325
1326         switch (node->type) {
1327         case MEDIA_STREAMER_NODE_TYPE_SRC:
1328                 bin = ms_streamer->src_bin;
1329                 break;
1330         case MEDIA_STREAMER_NODE_TYPE_SINK:
1331                 bin = ms_streamer->sink_bin;
1332                 break;
1333         default:
1334                 /* Another elements will be add into transform bin */
1335                 bin = ms_streamer->transform_bin;
1336                 break;
1337         }
1338
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;
1342         }
1343
1344         ms_debug_fleave();
1345
1346         return ret;
1347 }
1348
1349 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
1350 {
1351         ms_debug_fenter();
1352
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");
1356
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;
1360         }
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;
1364         }
1365
1366         ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1367
1368         ms_debug_fleave();
1369
1370         return MEDIA_STREAMER_ERROR_NONE;
1371 }
1372
1373 int ms_node_remove_from_table(GHashTable *nodes_table, media_streamer_node_s *node)
1374 {
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");
1377
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;
1383         }
1384
1385         return MEDIA_STREAMER_ERROR_NONE;
1386 }
1387
1388 void ms_node_remove_from_table_cb(void *data)
1389 {
1390         media_streamer_node_s *node = (media_streamer_node_s *) data;
1391
1392         ms_debug_fenter();
1393
1394         ms_retm_if(node == NULL, "data is NULL");
1395
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);
1401         } else {
1402                 ms_error("Failed to unlink element of node [%s]", node->name);
1403         }
1404
1405         ms_debug_fleave();
1406 }
1407
1408 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1409 {
1410         gboolean ret = FALSE;
1411
1412         ms_debug_fenter();
1413
1414         if (!src_pad || gst_pad_is_linked(src_pad))
1415                 return FALSE;
1416
1417         GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1418         if (gst_caps_is_any(src_caps))
1419                 ret = TRUE;
1420
1421         gst_caps_unref(src_caps);
1422
1423         ms_debug_fleave();
1424
1425         return ret;
1426 }
1427
1428 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1429 {
1430         int it_klass;
1431
1432         ms_debug_fenter();
1433
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);
1437                         break;
1438                 }
1439         }
1440
1441         ms_debug_fleave();
1442
1443         return &nodes_info[it_klass];
1444 }
1445
1446 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1447 {
1448         gboolean ret = FALSE;
1449
1450         ms_retvm_if(item == NULL, FALSE, "item is NULL");
1451         ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1452
1453         ms_debug_fenter();
1454
1455         ret = ms_element_lock_state(item, g_ret, user_data);
1456
1457         ms_debug_fleave();
1458
1459         return ret;
1460 }
1461
1462 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1463 {
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;
1469
1470         ms_debug_fenter();
1471
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");
1475
1476         src_element = GST_ELEMENT(g_value_get_object(item));
1477         g_object_ref(src_element);
1478         g_value_set_boolean(ret, FALSE);
1479
1480         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1481                 GST_ELEMENT_NAME(src_element));
1482         if (!node) {
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);
1488                 return TRUE;
1489         }
1490
1491         ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1492
1493         src_pad = gst_element_get_static_pad(src_element, "src");
1494
1495         if (__ms_src_need_typefind(src_pad)) {
1496                 ms_find_type(ms_streamer, src_element);
1497                 MS_SAFE_UNREF(src_element);
1498         } else {
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);
1506                         return TRUE;
1507                 }
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);
1514
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);
1518                 }
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);
1523                 }
1524                 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1525                 MS_SAFE_UNREF(found_element);
1526         }
1527         MS_SAFE_UNREF(src_pad);
1528
1529         g_value_set_boolean(ret, TRUE);
1530
1531         ms_debug_fleave();
1532
1533         return TRUE;
1534 }
1535
1536 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1537 {
1538         char *manifest_src_name = NULL;
1539         gchar *location = NULL;
1540         GstElement *manifest_src = NULL;
1541         GValue *val = NULL;
1542         const char *uri = NULL;
1543         gchar *protocol = NULL;
1544
1545         ms_debug_fenter();
1546
1547         ms_retvm_if(!node, NULL, "node is NULL");
1548
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;
1552
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);
1559         } else {
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);
1564                 } else {
1565                         g_free(protocol);
1566                         ms_error("URI is not valid file path");
1567                         return NULL;
1568                 }
1569         }
1570         g_free(protocol);
1571
1572         if (manifest_src_name == NULL) {
1573                 LOGE("Error empty manifest source name for adaptive source");
1574                 g_free(location);
1575                 return NULL;
1576         }
1577
1578         manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1579         g_free(manifest_src_name);
1580
1581         if (manifest_src == NULL) {
1582                 LOGE("Error creating manifest source for adaptive source");
1583                 g_free(location);
1584                 return NULL;
1585         }
1586
1587         g_object_set(manifest_src, "location", location, NULL);
1588         g_free(location);
1589
1590         ms_debug_fleave();
1591
1592         return manifest_src;
1593 }
1594
1595 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1596 {
1597         char *plugin_name = NULL;
1598         GstElement *manifest_src = NULL;
1599         GstElement *plugin_elem = NULL;
1600         gboolean res = FALSE;
1601         GstPad *gp = NULL;
1602
1603         ms_debug_fenter();
1604
1605         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1606
1607         if (!auto_plug) {
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");
1615
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");
1619         }
1620
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");
1624
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");
1628
1629         if (!auto_plug) {
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");
1633         }
1634
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");
1638
1639         if (!auto_plug) {
1640                 g_signal_connect_object(plugin_elem, "pad-added",
1641                                 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1642         } else {
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);
1645         }
1646
1647         ms_debug_fleave();
1648
1649         return MEDIA_STREAMER_ERROR_NONE;
1650 }
1651
1652 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1653 {
1654         int err_code = MEDIA_STREAMER_ERROR_NONE;
1655         gchar *playlist_location = NULL;
1656         char *playlist_dir = NULL;
1657         char *split = NULL;
1658
1659         ms_debug_fenter();
1660
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");
1664
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");
1669                 goto _DONE;
1670         }
1671
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);
1678                 goto _DONE;
1679         }
1680
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);
1686                 goto _DONE;
1687         }
1688
1689         split = strrchr(playlist_location, '/');
1690         playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1691
1692         ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1693
1694         MS_SAFE_GFREE(playlist_location);
1695
1696 _DONE:
1697
1698         ms_debug_fleave();
1699
1700         return err_code;
1701 }
1702
1703 //LCOV_EXCL_START
1704 int ms_rtp_node_prepare(media_streamer_node_s *node)
1705 {
1706         GstElement *rtpbin = NULL;
1707         GstElement *rtp_el = NULL;
1708         GstElement *rtcp_el = NULL;
1709         GValue *val = 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;
1717
1718         ms_debug_fenter();
1719
1720         ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1721
1722         rtpbin = ms_element_create("rtpbin", "rtpbin");
1723         ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1724
1725         if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1726                 MS_SAFE_UNREF(rtpbin);
1727                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1728         }
1729
1730         ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1731
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;
1735         }
1736         g_object_set(G_OBJECT(rtpbin), "latency", latency, NULL);
1737
1738         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1739         host = g_value_get_string(val);
1740
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);
1745
1746                 rtcp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtcp");
1747                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1748
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;
1753                 }
1754
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);
1757
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);
1760         }
1761
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);
1766
1767                 rtcp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtcp");
1768                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1769
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;
1774                 }
1775
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);
1778
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);
1781         }
1782
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);
1787
1788                 rtcp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtcp");
1789                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1790
1791                 video_filter = ms_element_create("capsfilter", NULL);
1792                 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1793
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);
1797
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;
1801                 }
1802                 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_VIDEO_IN);
1803                 if (ghost_pad) {
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);
1806                 }
1807
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;
1812                 }
1813
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);
1820         }
1821
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);
1826
1827                 rtcp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtcp");
1828                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1829
1830                 audio_filter = ms_element_create("capsfilter", NULL);
1831                 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1832
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);
1835
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;
1839                 }
1840
1841                 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_AUDIO_IN);
1842                 if (ghost_pad) {
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);
1845                 }
1846
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;
1851                 }
1852
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);
1859         }
1860
1861         ms_generate_dots(node->gst_element, "rtp_prepared");
1862
1863         ms_debug_fleave();
1864
1865         return MEDIA_STREAMER_ERROR_NONE;
1866 }
1867
1868 static int __ms_webrtc_prepare_ghost_sink_pad(GstElement *webrtc_container, GstElement *webrtcbin, const char *capsfilter_name)
1869 {
1870         int ret = MEDIA_STREAMER_ERROR_NONE;
1871         GstElement *filter;
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;
1877
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");
1881
1882         if (g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) &&
1883                 g_strcmp0(capsfilter_name, _WEBRTC_VIDEO_CAPSFILTER))
1884                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1885
1886         pad_name = !g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) ? MS_PAD_AUDIO_IN : MS_PAD_VIDEO_IN;
1887
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;
1891         }
1892
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;
1896         }
1897
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;
1901                 goto end;
1902         }
1903
1904         ms_info("%s is found, link it with webrtcbin and export the ghost pad[%s] of webrtc_container",
1905                         capsfilter_name, pad_name);
1906
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;
1910                 goto end;
1911         }
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;
1915                 goto end;
1916         }
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;
1920                 goto end;
1921         }
1922
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;
1926                 goto end;
1927         }
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;
1931                 goto end;
1932         }
1933
1934 end:
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);
1941         }
1942         return ret;
1943 }
1944
1945 int ms_webrtc_node_check_link_condition(media_streamer_node_s *node, const char *sink_pad_name)
1946 {
1947         GValue *value = NULL;
1948         const gchar *key = NULL;
1949         const gchar *direction = NULL;
1950
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");
1955
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;
1960         } else {
1961                 ms_error("sink_pand_name[%s] is wrong", sink_pad_name);
1962                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1963         }
1964
1965         value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), key);
1966         if (!value) {
1967                 ms_error("failed to get [%s] val from [%s]", key, GST_ELEMENT_NAME(node->gst_element));
1968                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1969         }
1970
1971         if (!(direction = g_value_get_string(value))) {
1972                 ms_error("Failed to g_value_get_string()");
1973                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1974         }
1975
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;
1980         }
1981
1982         return MEDIA_STREAMER_ERROR_NONE;
1983 }
1984 static int __ms_webrtc_node_update_transceiver_direction_param_value(media_streamer_node_s *node, const gchar *param_name, const gchar *direction)
1985 {
1986         int ret = MEDIA_STREAMER_ERROR_NONE;
1987         GValue *value = NULL;
1988
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");
1993
1994         ms_debug("direction is [%s]", direction);
1995
1996         value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
1997         if (!value) {
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;
2000         }
2001
2002         ret = __ms_param_value_set(value, PARAM_DATA_TYPE_STRING, direction);
2003         if (ret != MEDIA_STREAMER_ERROR_NONE) {
2004                 return ret;
2005                 ms_info("update transceiver unknown -> sendrecv");
2006         }
2007
2008         return ret;
2009 }
2010
2011 GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
2012 {
2013         GstElement *webrtcbin = NULL;
2014         node_info_s *node_klass_type = NULL;
2015
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");
2018
2019         ms_debug_fenter();
2020
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);
2023         if (!webrtcbin)
2024                 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
2025
2026         ms_debug_fleave();
2027
2028         return webrtcbin;
2029 }
2030
2031 static int __ms_webrtc_node_set_rtp_transceiver_direction(media_streamer_node_s *webrtc_node)
2032 {
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;
2044
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");
2047         ms_debug_fenter();
2048
2049         if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(webrtc_node)))
2050                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2051
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;
2055         }
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;
2059         }
2060
2061         if ((audio_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "audio_capsfilter")))
2062                 is_linked_audio = TRUE;
2063
2064         if ((video_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "video_capsfilter")))
2065                 is_linked_video = TRUE;
2066
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;
2073                 }
2074         } else {
2075                 if (!ms_webrtc_is_valid_transceiver_direction(is_linked_audio, audio_direction))
2076                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2077
2078                 if (is_linked_audio)
2079                         ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx++, audio_direction);
2080                 else
2081                         ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_AUDIO_RTP_FORMAT, audio_direction);
2082         }
2083
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;
2088                 }
2089         } else {
2090                 if (!ms_webrtc_is_valid_transceiver_direction(is_linked_video, video_direction))
2091                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2092
2093                 if (is_linked_video)
2094                         ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx, video_direction);
2095                 else
2096                         ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_VIDEO_RTP_FORMAT, video_direction);
2097         }
2098
2099         ms_debug_fleave();
2100
2101         return ret;
2102 }
2103
2104
2105 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
2106 {
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;
2113
2114         ms_debug_fenter();
2115
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");
2119
2120         if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(node)))
2121                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2122
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;
2127         }
2128
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);
2134
2135         if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_AUDIO_CAPSFILTER)))
2136                 return ret;
2137         if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
2138                 return ret;
2139
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;
2145         }
2146
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;
2150         }
2151
2152         g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
2153         if (send_channel)
2154                 ms_info("data channel(%p) for sending is created", send_channel);
2155         else
2156                 ms_warning("Failed to create data channel");
2157
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);
2160
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;
2164         }
2165
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);
2169
2170         ms_generate_dots(node->gst_element, "webrtc_prepared");
2171
2172         ms_debug_fleave();
2173
2174         return MEDIA_STREAMER_ERROR_NONE;
2175 }
2176 //LCOV_EXCL_STOP
2177
2178 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
2179 {
2180         ms_debug_fenter();
2181
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");
2184
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);
2187
2188         ms_debug_fleave();
2189
2190         return MEDIA_STREAMER_ERROR_NONE;
2191 }
2192
2193 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
2194 {
2195         GParamSpec *param_spec;
2196         int it_param;
2197
2198         ms_debug_fenter();
2199
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");
2202
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]));
2209                 }
2210         }
2211         ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
2212
2213         ms_debug_fleave();
2214
2215         return MEDIA_STREAMER_ERROR_NONE;
2216 }
2217
2218 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
2219 {
2220         int ret = MEDIA_STREAMER_ERROR_NONE;
2221         Evas_Object *obj = NULL;
2222         media_streamer_wl_info_s wl_info;
2223
2224         obj = (Evas_Object *)param_value;
2225
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;
2230         }
2231
2232         LOGD("wayland global surface id : %d", wl_info.parent_id);
2233
2234         gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
2235
2236         return ret;
2237 }
2238
2239 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
2240 {
2241         int ret = MEDIA_STREAMER_ERROR_NONE;
2242
2243         ms_debug_fenter();
2244
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");
2248
2249         if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
2250                 ret = __ms_rtp_node_set_property(node, param, param_value);
2251                 ms_debug_fleave();
2252                 return ret;
2253         }
2254
2255         if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2256                 ret = __ms_webrtc_node_set_property(node, param, param_value);
2257                 ms_debug_fleave();
2258                 return ret;
2259         }
2260
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);
2264                 ms_debug_fleave();
2265                 return ret;
2266         }
2267
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);
2273                 break;
2274         }
2275
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);
2285                 break;
2286
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);
2292                 break;
2293
2294         case PROP_NAME_URI:
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)
2299                                 return ret;
2300                 }
2301                 g_object_set(node->gst_element, param->prop_name, param_value, NULL);
2302                 break;
2303
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);
2311                 break;
2312
2313         case PROP_NAME_DISPLAY:
2314                 ret = __ms_node_set_display(node, param_value);
2315                 break;
2316
2317         default:
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;
2320                 break;
2321         }
2322
2323         ms_debug_fleave();
2324
2325         return ret;
2326 }
2327
2328 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
2329 {
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;
2336
2337         ms_debug_fenter();
2338
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");
2341
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) {
2349                                         written_count++;
2350                                 } else {
2351                                         ms_error("failed to set param");
2352                                         break;
2353                                 }
2354                         }
2355                 }
2356         }
2357         g_list_free(p_list);
2358
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;
2362
2363         ms_debug_fleave();
2364
2365         return ret;
2366 }
2367
2368 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
2369 {
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;
2375
2376         ms_debug_fenter();
2377
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");
2380
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;
2385
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);
2389                         }
2390                 }
2391         }
2392         if (p_list)
2393                 g_list_free(p_list);
2394
2395         ms_debug_fleave();
2396
2397         return ret;
2398 }
2399
2400 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
2401 {
2402         GParamSpec *param_spec;
2403         gboolean found_param = FALSE;
2404         int it_param;
2405
2406         ms_debug_fenter();
2407
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");
2411
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);
2420                                 found_param = TRUE;
2421                                 break;
2422                         }
2423                 }
2424         }
2425         ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
2426
2427         ms_debug_fleave();
2428
2429         return MEDIA_STREAMER_ERROR_NONE;
2430 }
2431
2432 static gchar *__ms_convert_prop_value_to_string(param_s *param, const GValue *value)
2433 {
2434         ms_retvm_if(param == NULL, NULL, "param is NULL");
2435         ms_retvm_if(value == NULL, NULL, "value is NULL");
2436
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));
2441                 else
2442                         return g_strdup_printf("%u", g_value_get_uint(value));
2443
2444         case PARAM_DATA_TYPE_BOOL:
2445                 return g_strdup(g_value_get_boolean(value) ? "true" : "false");
2446
2447         case PARAM_DATA_TYPE_STRING:
2448                 return g_value_dup_string(value);
2449
2450         case PARAM_DATA_TYPE_ENUM:
2451                 return g_strdup_printf("%d", g_value_get_enum(value));
2452
2453         default:
2454                 ms_error("should not be reached here, param[name:%s, type:%d]", param->param_name, param->data_type);
2455                 return NULL;
2456         }
2457 }
2458
2459 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
2460 {
2461         int ret = MEDIA_STREAMER_ERROR_NONE;
2462         gchar *prop_val_str = NULL;
2463         GParamSpec *param_spec = NULL;
2464         GValue value = G_VALUE_INIT;
2465
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");
2469
2470         ms_debug("node[%s] prop_name[%s]", node->name, param->prop_name);
2471
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);
2477         else {
2478                 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->prop_name);
2479                 if (param_spec) {
2480                         g_value_init(&value, param_spec->value_type);
2481                         g_object_get_property(G_OBJECT(node->gst_element), param->prop_name, &value);
2482
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));
2485                 } else {
2486                         ms_error("There is no prop_name [%s] for node [%s]", param->prop_name, node->name);
2487                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2488                 }
2489         }
2490
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);
2494
2495         g_value_reset(&value);
2496         g_value_unset(&value);
2497
2498         ms_debug("string_value[%s]", *string_value);
2499
2500         return ret;
2501 }
2502
2503 static int __ms_rtp_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2504 {
2505         int ret = MEDIA_STREAMER_ERROR_NONE;
2506         media_format_mimetype_e mime;
2507         gchar *rtp_caps_str = NULL;
2508
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");
2513
2514         ms_debug_fenter();
2515
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, &param, rtp_caps_str);
2523                 }
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, &param, rtp_caps_str);
2531                 }
2532         } else {
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;
2535         }
2536         MS_SAFE_GFREE(rtp_caps_str);
2537
2538         return ret;
2539 }
2540
2541 //LCOV_EXCL_START
2542 static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2543 {
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;
2550         gint payload = 0;
2551         GstCaps *caps = NULL;
2552         GstElement *capsfilter = NULL;
2553
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");
2558
2559         ms_debug_fenter();
2560
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;
2564         }
2565
2566         if (g_strrstr(pad_name, MS_PAD_VIDEO_IN) &&
2567                 !media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2568                 media = "video";
2569                 payload = 96;
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)) {
2573                 media = "audio";
2574                 payload = 97;
2575                 capsfilter_name = _WEBRTC_AUDIO_CAPSFILTER;
2576         } else {
2577                 ms_error("Invalid media format for pad_name(%s)", pad_name);
2578                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2579         }
2580
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);
2586
2587         if (!(capsfilter = ms_find_element_in_bin_by_name(node->gst_element, capsfilter_name))) {
2588                 ms_debug("Create %s", capsfilter_name);
2589
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;
2593                 }
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;
2597                 }
2598         }
2599
2600         g_object_set(G_OBJECT(capsfilter), "caps", (GValue *)caps, NULL);
2601
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);
2605
2606         gst_caps_unref(caps);
2607
2608         return ret;
2609 }
2610 //LCOV_EXCL_STOP
2611
2612 static int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2613 {
2614         gboolean can_accept = FALSE;
2615         GstElement *element = NULL;
2616         GstCaps *fmt_caps = NULL;
2617         GstElementFactory *factory = NULL;
2618         GstPad *node_pad = NULL;
2619
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");
2624
2625         element = node->gst_element;
2626
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");
2629
2630         factory = gst_element_get_factory(element);
2631         node_pad = gst_element_get_static_pad(element, pad_name);
2632         if (!node_pad) {
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;
2636         }
2637
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);
2642         else
2643                 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2644
2645         MS_SAFE_UNREF(node_pad);
2646
2647         if (!can_accept) {
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;
2651         }
2652
2653         MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2654         gst_caps_unref(fmt_caps);
2655
2656         ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2657
2658         return MEDIA_STREAMER_ERROR_NONE;
2659 }
2660
2661 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2662 {
2663         int ret = MEDIA_STREAMER_ERROR_NONE;
2664
2665         ms_debug_fenter();
2666
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");
2671
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);
2676         else
2677                 ret = __ms_node_set_pad_format(node, pad_name, fmt);
2678
2679         ms_debug_fleave();
2680
2681         return ret;
2682 }
2683
2684 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
2685 {
2686         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2687         media_streamer_node_s *node = NULL;
2688         GstElement *element = NULL;
2689
2690         ms_debug_fenter();
2691
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");
2695
2696         g_value_set_boolean(ret, FALSE);
2697
2698         element = GST_ELEMENT(g_value_get_object(item));
2699         g_object_ref(element);
2700
2701         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2702                 GST_ELEMENT_NAME(element));
2703         if (!node) {
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);
2709                 return TRUE;
2710         }
2711
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);
2715                 return FALSE;
2716         }
2717
2718         g_value_set_boolean(ret, TRUE);
2719
2720         g_object_unref(element);
2721
2722         ms_debug_fleave();
2723
2724         return TRUE;
2725 }
2726
2727 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
2728 {
2729         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2730         media_streamer_node_s *node = NULL;
2731         GstElement *element = NULL;
2732
2733         ms_debug_fenter();
2734
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");
2738
2739         g_value_set_boolean(ret, FALSE);
2740
2741         element = GST_ELEMENT(g_value_get_object(item));
2742         g_object_ref(element);
2743
2744         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2745                 GST_ELEMENT_NAME(element));
2746         if (!node) {
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);
2752                 return TRUE;
2753         }
2754
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);
2758                 return FALSE;
2759         }
2760
2761         g_value_set_boolean(ret, TRUE);
2762
2763         g_object_unref(element);
2764
2765         ms_debug_fleave();
2766
2767         return TRUE;
2768 }
2769
2770 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
2771 {
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;
2776
2777         ms_debug_fenter();
2778
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");
2783
2784         element = GST_ELEMENT(g_value_get_object(item));
2785         g_object_ref(element);
2786
2787         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2788                 GST_ELEMENT_NAME(element));
2789         if (!node) {
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);
2795                 return TRUE;
2796         }
2797
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);
2803                 return FALSE;
2804         }
2805
2806         g_value_set_boolean(ret, allowed);
2807
2808         g_object_unref(element);
2809
2810         ms_debug_fleave();
2811
2812         return allowed;
2813 }
2814
2815 //LCOV_EXCL_START
2816 int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
2817 {
2818         GValue *val = NULL;
2819         const gchar *type = NULL;
2820
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");
2823
2824         if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2825                 ms_error("Invalid node type");
2826                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2827         }
2828
2829         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
2830         if (!val) {
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;
2833         }
2834
2835         if (!(type = g_value_get_string(val))) {
2836                 ms_error("Failed to g_value_get_string()");
2837                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2838         }
2839
2840         ms_info("peer type is [%s]", type);
2841
2842         *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
2843
2844         return MEDIA_STREAMER_ERROR_NONE;
2845 }
2846 //LCOV_EXCL_STOP