Improve zerocopy format selection logic
[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 <Evas.h>
20 #include <gst/video/videooverlay.h>
21 #include "media_streamer_node.h"
22 #include "media_streamer_node_resources.h"
23 #include "media_streamer_node_dpm_policy.h"
24 #include "media_streamer_util.h"
25 #include "media_streamer_gst.h"
26 #include "media_streamer_gst_webrtc.h"
27
28 #define SMACK_LABEL_LEN 255
29 #define DEFAULT_URI_SCHEME_LENGTH 10
30
31 #define _FEATURE_NAME_WIFI               "http://tizen.org/feature/network.wifi"
32 #define _FEATURE_NAME_TELEPHONY          "http://tizen.org/feature/network.telephony"
33 #define _FEATURE_NAME_ETHERNET           "http://tizen.org/feature/network.ethernet"
34 #define _FEATURE_NAME_CAMERA             "http://tizen.org/feature/camera"
35 #define _FEATURE_NAME_MICROPHONE         "http://tizen.org/feature/microphone"
36
37 #define _WEBRTC_AUDIO_CAPSFILTER         "audio_capsfilter"
38 #define _WEBRTC_VIDEO_CAPSFILTER         "video_capsfilter"
39
40 static param_s param_table[] = {
41         {MEDIA_STREAMER_PARAM_CAMERA_ID, "camera-id"},
42         {MEDIA_STREAMER_PARAM_CAPTURE_WIDTH, "capture-width"},
43         {MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT, "capture-height"},
44         {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "is-live"},
45         {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "living"},
46         {MEDIA_STREAMER_PARAM_URI, "uri"},
47         {MEDIA_STREAMER_PARAM_URI, "location"},
48         {MEDIA_STREAMER_PARAM_USER_AGENT, "user-agent"},
49         {MEDIA_STREAMER_PARAM_STREAM_TYPE, "stream-type"},
50         {MEDIA_STREAMER_PARAM_PORT, "port"},
51         {MEDIA_STREAMER_PARAM_VIDEO_IN_PORT, "video_in_port"},
52         {MEDIA_STREAMER_PARAM_AUDIO_IN_PORT, "audio_in_port"},
53         {MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, "video_out_port"},
54         {MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT, "audio_out_port"},
55         {MEDIA_STREAMER_PARAM_IP_ADDRESS, "address"},
56         {MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, "webrtc-peer-type"},
57         {MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER, "webrtc-stun-server"},
58         {MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION, "webrtc-remote-session-description"},
59         {MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, "webrtc-add-ice-candidate"},
60         {MEDIA_STREAMER_PARAM_AUDIO_DEVICE, "audio_device"},
61         {MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED, "sync"},
62         {MEDIA_STREAMER_PARAM_ROTATE, "rotate"},
63         {MEDIA_STREAMER_PARAM_FLIP, "flip"},
64         {MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD, "display-geometry-method"},
65         {MEDIA_STREAMER_PARAM_DISPLAY, "display"},
66         {MEDIA_STREAMER_PARAM_VISIBLE, "visible"},
67         {MEDIA_STREAMER_PARAM_USE_TBM, "use-tbm"},
68         {MEDIA_STREAMER_PARAM_HOST, "host"},
69         {MEDIA_STREAMER_PARAM_SEGMENT_LOCATION, "location"},
70         {MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, "playlist-location"},
71         {NULL, NULL}
72 };
73
74 static node_info_s nodes_info[] = {
75         {"Generic", "none"},                               /* MEDIA_STREAMER_NODE_TYPE_NONE */
76         {"Source", "source"},                              /* MEDIA_STREAMER_NODE_TYPE_SRC */
77         {"Sink", "sink"},                                  /* MEDIA_STREAMER_NODE_TYPE_SINK */
78         {"Codec/Encoder/Video", "video_encoder"},          /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
79         {"Codec/Decoder/Video", "video_decoder"},          /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */
80         {"Codec/Encoder/Audio", "audio_encoder"},          /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
81         {"Codec/Decoder/Audio", "audio_decoder"},          /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */
82         {"Filter/Converter/Video", "videoconvert"},        /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */
83         {"Filter/Converter/Audio", "audioconvert"},        /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */
84         {MEDIA_STREAMER_STRICT, "audioresample"},          /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */
85         {"Codec/Payloader/Network/RTP", "rtph263pay"},     /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */
86         {"Codec/Payloader/Network/RTP", "rtpamrpay"},      /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */
87         {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */
88         {"Codec/Depayloader/Network/RTP", "rtpamrdepay"},  /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */
89         {"Filter/Effect/Video", "videorate"},              /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */
90         {"Filter/Converter/Video/Scaler", "videoscale"},   /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */
91         {MEDIA_STREAMER_STRICT, "textoverlay"},            /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */
92         {"Codec/Parser", "h263parse"},                     /* MEDIA_STREAMER_NODE_TYPE_PARSER */
93         {MEDIA_STREAMER_STRICT, "capsfilter"},             /* MEDIA_STREAMER_NODE_TYPE_FILTER */
94         {MEDIA_STREAMER_STRICT, "tee"},                    /* MEDIA_STREAMER_NODE_TYPE_TEE */
95         {MEDIA_STREAMER_STRICT, "queue"},                  /* MEDIA_STREAMER_NODE_TYPE_QUEUE */
96         {MEDIA_STREAMER_STRICT, "multiqueue"},             /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */
97         {"Codec/Muxer", "qtmux"},                          /* MEDIA_STREAMER_NODE_TYPE_MUXER */
98         {"Codec/Demuxer", "qtdemux"},                      /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */
99         {"Generic/Bin", "rtpbin"},                         /* MEDIA_STREAMER_NODE_TYPE_RTP */
100         {MEDIA_STREAMER_STRICT, "input-selector"},         /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */
101         {MEDIA_STREAMER_STRICT, "output-selector"},        /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */
102         {MEDIA_STREAMER_STRICT, "interleave"},             /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */
103         {MEDIA_STREAMER_STRICT, "deinterleave"},           /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */
104         {"Filter/Network/WebRTC", "webrtc_container"},     /* MEDIA_STREAMER_NODE_TYPE_WEBRTC */
105         {NULL, NULL}
106 };
107
108 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
109 {
110         GValue *val = NULL;
111
112         ms_debug_fenter();
113
114         ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
115         ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
116
117         if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
118                 return FALSE;
119
120         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
121
122         ms_debug_fleave();
123
124         return val ? TRUE : FALSE;
125 }
126
127 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
128 {
129         int ret = MEDIA_STREAMER_ERROR_NONE;
130         GValue *val = NULL;
131
132         ms_debug_fenter();
133
134         ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
135         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
136         ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
137         ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
138
139
140         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
141         if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
142                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
143                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
144                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
145                 g_value_init(value, G_TYPE_INT);
146         } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
147                 g_value_init(value, G_TYPE_STRING);
148         } else
149                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
150
151         g_value_copy(val, value);
152
153         ms_debug_fleave();
154
155         return ret;
156 }
157
158 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
159 {
160         int ret = MEDIA_STREAMER_ERROR_NONE;
161         GValue *val = NULL;
162
163         ms_debug_fenter();
164
165         ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
166         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
167         ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
168         ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
169
170         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
171         if (!val) {
172                 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
173                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
174         }
175
176         if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
177                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
178                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
179                 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
180                 g_value_unset(val);
181                 g_value_init(val, G_TYPE_INT);
182                 g_value_set_int(val, (int)strtol(param_value, NULL, 10));
183         } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
184                 g_value_unset(val);
185                 g_value_init(val, G_TYPE_STRING);
186                 g_value_set_string(val, param_value);
187         } else if (!strcmp(param->param_name, MS_PARAM_VIDEO_IN_FORMAT) ||
188                            !strcmp(param->param_name, MS_PARAM_AUDIO_IN_FORMAT)) {
189                 GstCaps *caps = gst_caps_from_string(param_value);
190                 if (caps) {
191                         g_value_unset(val);
192                         g_value_init(val, GST_TYPE_CAPS);
193                         gst_value_set_caps(val, caps);
194                 } else {
195                         ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
196                 }
197         } else {
198                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
199         }
200
201         ms_debug_fleave();
202
203         return ret;
204 }
205
206 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
207 {
208         GValue *val = NULL;
209
210         ms_debug_fenter();
211
212         ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
213         ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
214
215         if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
216                 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
217
218                 ms_debug_fleave();
219
220                 return val ? TRUE : FALSE;
221         }
222
223         ms_debug_fleave();
224
225         return FALSE;
226 }
227
228 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
229 {
230         GValue *val = NULL;
231         int ret;
232
233         ms_debug_fenter();
234
235         ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
236         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
237         ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
238         ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
239
240         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
241         if (!val) {
242                 ms_error("failed to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
243                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
244         }
245
246         if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE)) {
247                 if (strcmp(param_value, WEBRTC_PEER_OFFER) && strcmp(param_value, WEBRTC_PEER_ANSWER)) {
248                         ms_error("failed to set property, param value should be [%s] or [%s]", WEBRTC_PEER_OFFER, WEBRTC_PEER_ANSWER);
249                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
250                 }
251                 g_value_unset(val);
252                 g_value_init(val, G_TYPE_STRING);
253                 g_value_set_string(val, param_value);
254
255         } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER)) {
256                 ret = ms_webrtcbin_set_stun_server(node, param_value);
257                 if (ret != MEDIA_STREAMER_ERROR_NONE) {
258                         ms_error("failed to set STUN server: %s", param_value);
259                         return ret;
260                 }
261                 g_value_unset(val);
262                 g_value_init(val, G_TYPE_STRING);
263                 g_value_set_string(val, param_value);
264
265         } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION)) {
266                 ret = ms_webrtcbin_set_remote_session_description(node, param_value);
267                 if (ret != MEDIA_STREAMER_ERROR_NONE) {
268                         ms_error("failed to set remote session description:\n%s", param_value);
269                         return ret;
270                 }
271                 g_value_unset(val);
272                 g_value_init(val, G_TYPE_STRING);
273                 g_value_set_string(val, param_value);
274
275         } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE)) {
276                 ret = ms_webrtcbin_add_ice_candidate(node, param_value);
277                 if (ret != MEDIA_STREAMER_ERROR_NONE) {
278                         ms_error("failed to add ICE candidate: %s", param_value);
279                         return ret;
280                 }
281
282         } else {
283                 ms_error("failed to set property, undefined param name[%s]", param->param_name);
284                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
285         }
286
287         ms_debug_fleave();
288
289         return MEDIA_STREAMER_ERROR_NONE;
290 }
291
292 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
293 {
294         GValue *val = NULL;
295
296         ms_debug_fenter();
297
298         ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
299         ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
300
301         if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
302                 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
303                 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
304
305                 ms_debug_fleave();
306
307                 return val ? TRUE : FALSE;
308         }
309
310         ms_debug_fleave();
311
312         return FALSE;
313 }
314
315 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
316 {
317         int ret = MEDIA_STREAMER_ERROR_NONE;
318         GValue *val = NULL;
319
320         ms_debug_fenter();
321
322         ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
323         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
324                         node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
325         ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
326         ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
327
328         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
329         if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI))
330                 g_value_init(value, G_TYPE_STRING);
331         else
332                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
333
334         g_value_copy(val, value);
335
336         ms_debug_fleave();
337
338         return ret;
339 }
340
341 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
342 {
343         int ret = MEDIA_STREAMER_ERROR_NONE;
344         GValue *val = NULL;
345
346         ms_debug_fenter();
347
348         ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
349         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
350                         node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
351         ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
352         ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
353
354         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
355         if (!val) {
356                 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
357                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
358         }
359
360         if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
361                 g_value_unset(val);
362                 g_value_init(val, G_TYPE_STRING);
363                 g_value_set_string(val, param_value);
364         } else {
365                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
366         }
367
368         ms_debug_fleave();
369
370         return ret;
371 }
372
373 static int __ms_node_check_privileges(media_streamer_node_s *node)
374 {
375         int ret = MEDIA_STREAMER_ERROR_NONE;
376         int ret_val = 0;
377         char *privilege = NULL;
378         FILE* opened_file;
379         char smackLabel[SMACK_LABEL_LEN + 1];
380         char uid[10];
381         cynara *cynara_h = NULL;
382
383         ms_debug_fenter();
384
385         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
386
387         if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
388                 switch (node->subtype) {
389                 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
390                         privilege = "http://tizen.org/privilege/internet";
391                         break;
392                 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
393                         privilege = "http://tizen.org/privilege/internet";
394                         break;
395                 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
396                         privilege = "http://tizen.org/privilege/camera";
397                         break;
398                 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
399                         privilege = "http://tizen.org/privilege/recorder";
400                         break;
401                 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
402                         privilege = "http://tizen.org/privilege/camera";
403                         break;
404                 default:
405                         ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
406                         break;
407                 }
408         }
409
410         if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
411                 switch (node->subtype) {
412                 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
413                         privilege = "http://tizen.org/privilege/internet";
414                         break;
415                 default:
416                         ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
417                         break;
418                 }
419         }
420
421         if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
422                 privilege = "http://tizen.org/privilege/internet";
423
424         /* Skip checking for privilege permission in case of other types of Nodes */
425         if (privilege == NULL)
426                 return ret;
427
428         if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
429                 ms_error("Failed to initialize cynara structure\n");
430                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
431         }
432
433         bzero(smackLabel, SMACK_LABEL_LEN + 1);
434
435         /* Getting smack label */
436         opened_file = fopen("/proc/self/attr/current", "r");
437         if (opened_file == NULL) {
438                 ms_error("Failed to open /proc/self/attr/current\n");
439                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
440         }
441         ret_val = fread(smackLabel, sizeof(smackLabel), 1, opened_file);
442         fclose(opened_file);
443         if (ret_val < 0) {
444                 ms_error("Failed to read /proc/self/attr/current\n");
445                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
446         }
447
448         /* Getting uid */
449         snprintf(uid, sizeof(uid), "%d", getuid());
450         ms_info("%s %s %s\n", smackLabel, uid, privilege);
451
452         /* Checking with cynara for current session */
453         ret_val = cynara_check(cynara_h, smackLabel, "", uid, privilege);
454         ms_info("Cynara_check [%d] ", ret_val);
455
456         switch (ret_val) {
457         case CYNARA_API_ACCESS_ALLOWED:
458                 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
459                 break;
460         case CYNARA_API_ACCESS_DENIED:
461         default:
462                 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
463                 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
464                 break;
465         }
466
467         cynara_finish(cynara_h);
468
469         ms_debug_fleave();
470
471         return ret;
472 }
473
474 static int __ms_node_check_feature(media_streamer_node_s *node)
475 {
476         bool enabled = FALSE;
477
478         ms_debug_fenter();
479
480         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
481
482         switch (node->type) {
483         case MEDIA_STREAMER_NODE_TYPE_WEBRTC:
484                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
485                         ms_info("wifi status = %d", enabled);
486                         if (enabled)
487                                 return MEDIA_STREAMER_ERROR_NONE;
488                 }
489                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
490                         ms_info("telephony status = %d", enabled);
491                         if (enabled)
492                                 return MEDIA_STREAMER_ERROR_NONE;
493                 }
494                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
495                         ms_info("ethernet status = %d", enabled);
496                         if (enabled)
497                                 return MEDIA_STREAMER_ERROR_NONE;
498                 }
499                 ms_error("None of [%s] [%s] [%s] features is enabled", _FEATURE_NAME_WIFI, _FEATURE_NAME_TELEPHONY, _FEATURE_NAME_ETHERNET);
500                 return MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
501         default:
502                 ms_debug("For current node type[%d], feature is not needed", node->type);
503                 break;
504         }
505
506         ms_debug_fleave();
507
508         return MEDIA_STREAMER_ERROR_NONE;
509 }
510
511 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
512 {
513         int ret = MEDIA_STREAMER_ERROR_NONE;
514         GstCaps *sink_caps = NULL;
515         GstCaps *src_caps = NULL;
516
517         ms_debug_fenter();
518
519         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
520
521         ret = __ms_node_check_privileges(node);
522         if (ret != MEDIA_STREAMER_ERROR_NONE) {
523                 ms_error("Failed to get privilege for this node type(%d)", node->type);
524                 return ret;
525         }
526
527         ret = __ms_node_check_feature(node);
528         if (ret != MEDIA_STREAMER_ERROR_NONE) {
529                 ms_error("Failed to get feature for this node type(%d)", node->type);
530                 return ret;
531         }
532
533         sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt, nodes_info[node->type].default_name) : NULL;
534         src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt, nodes_info[node->type].default_name) : NULL;
535
536         node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
537
538         ms_info("Creating node with info: klass_name[%s]; default[%s]",
539                         plug_info.info->klass_name, plug_info.info->default_name);
540
541         node->gst_element = ms_node_element_create(&plug_info, node->type);
542         if (node->gst_element)
543                 node->name = gst_element_get_name(node->gst_element);
544         else
545                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
546
547         if (src_caps)
548                         gst_caps_unref(src_caps);
549
550         if (sink_caps)
551                         gst_caps_unref(sink_caps);
552
553         ms_debug_fleave();
554
555         return ret;
556 }
557
558 /* This signal callback is called when appsrc needs data, we add an idle handler
559  * to the mainloop to start pushing data into the appsrc */
560 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
561 {
562         media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
563         media_streamer_callback_s *src_callback = NULL;
564         media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
565
566         ms_debug_fenter();
567
568         ms_retm_if(ms_src == NULL, "data is NULL");
569         ms_retm_if(pipeline == NULL, "pipeline is NULL");
570
571         if (ms_src->callbacks_structure != NULL) {
572                 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
573                 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
574                 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
575         }
576
577         ms_debug_fleave();
578 }
579
580 /* This callback is called when appsrc has enough data and we can stop sending.
581  * We remove the idle handler from the mainloop */
582 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
583 {
584         media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
585         media_streamer_callback_s *src_callback = NULL;
586         media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
587
588         ms_debug_fenter();
589
590         ms_retm_if(ms_src == NULL, "data is NULL");
591         ms_retm_if(pipeline == NULL, "pipeline is NULL");
592
593         if (ms_src->callbacks_structure != NULL) {
594                 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
595                 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
596                 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
597         }
598
599         ms_debug_fleave();
600 }
601
602 static int __ms_src_node_check_feature(media_streamer_node_s *node)
603 {
604         int ret = MEDIA_STREAMER_ERROR_NONE;
605         bool enabled = FALSE;
606         bool supported = FALSE;
607
608         ms_debug_fenter();
609
610         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
611
612         switch (node->subtype) {
613         case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
614         case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
615         case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
616                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
617                         ms_info("wifi status = %d", enabled);
618                         if (enabled)
619                                 supported = TRUE;
620                 } else {
621                         ms_error("SYSTEM_INFO_ERROR");
622                 }
623
624                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
625                         ms_info("telephony status = %d", enabled);
626                         if (enabled)
627                                 supported = TRUE;
628                 } else {
629                         ms_error("SYSTEM_INFO_ERROR");
630                 }
631
632                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
633                         ms_info("ethernet status = %d", enabled);
634                         if (enabled)
635                                 supported = TRUE;
636                 } else {
637                         ms_error("SYSTEM_INFO_ERROR");
638                 }
639                 if (!supported)
640                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
641                 break;
642         case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
643                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
644                         ms_info("microphone status = %d", enabled);
645                         if (enabled)
646                                 supported = TRUE;
647                 } else {
648                         ms_error("SYSTEM_INFO_ERROR");
649                 }
650                 if (!supported)
651                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
652                 break;
653         case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
654         case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
655                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
656                         ms_info("camera status = %d", enabled);
657                         if (enabled)
658                                 supported = TRUE;
659                 } else {
660                         ms_error("SYSTEM_INFO_ERROR");
661                 }
662                 if (!supported)
663                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
664                 break;
665         default:
666                 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
667                 break;
668         }
669
670         ms_debug_fleave();
671
672         return ret;
673 }
674
675 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
676 {
677         int ret = MEDIA_STREAMER_ERROR_NONE;
678         bool enabled = FALSE;
679         bool supported = FALSE;
680
681         ms_debug_fenter();
682
683         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
684
685         switch (node->subtype) {
686         case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
687         case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
688         /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
689                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
690                         ms_info("wifi status = %d", enabled);
691                         if (enabled)
692                                 supported = TRUE;
693                 } else {
694                         ms_error("SYSTEM_INFO_ERROR");
695                 }
696
697                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
698                         ms_info("telephony status = %d", enabled);
699                         if (enabled)
700                                 supported = TRUE;
701                 } else {
702                         ms_error("SYSTEM_INFO_ERROR");
703                 }
704
705                 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
706                         ms_info("ethernet status = %d", enabled);
707                         if (enabled)
708                                 supported = TRUE;
709                 } else {
710                         ms_error("SYSTEM_INFO_ERROR");
711                 }
712                 if (!supported)
713                         ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
714                 break;
715         default:
716                 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
717                 break;
718         }
719
720         ms_debug_fleave();
721
722         return ret;
723 }
724
725 int ms_src_node_create(media_streamer_node_s *node)
726 {
727         int ret = MEDIA_STREAMER_ERROR_NONE;
728         char *plugin_name = NULL;
729
730         ms_debug_fenter();
731
732         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
733
734         ret = __ms_node_check_privileges(node);
735         if (ret != MEDIA_STREAMER_ERROR_NONE) {
736                 ms_error("Error getting privileges for Src Node");
737                 return ret;
738         }
739
740         ret = __ms_src_node_check_feature(node);
741         if (ret != MEDIA_STREAMER_ERROR_NONE) {
742                 ms_error("Error getting feature for Src Node");
743                 return ret;
744         }
745
746         switch (node->subtype) {
747         case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
748                 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
749                 node->gst_element = ms_element_create(plugin_name, NULL);
750                 break;
751         case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
752                 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
753                 node->gst_element = ms_element_create(plugin_name, NULL);
754                 break;
755         case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
756                 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
757                 node->gst_element = ms_element_create(plugin_name, NULL);
758                 break;
759         case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
760                 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
761                 node->gst_element = ms_element_create(plugin_name, NULL);
762                 break;
763         case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
764                 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
765                 node->gst_element = ms_element_create(plugin_name, NULL);
766                 break;
767         case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
768                 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
769                 node->gst_element = ms_element_create(plugin_name, NULL);
770                 break;
771         case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
772                 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
773                 node->gst_element = ms_element_create(plugin_name, NULL);
774                 break;
775         case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
776                 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
777                 node->gst_element = ms_element_create(plugin_name, NULL);
778                 break;
779         case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
780                 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
781                 node->gst_element = ms_element_create(plugin_name, NULL);
782                 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
783                 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
784                 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
785                 break;
786         case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
787                 node->gst_element = ms_adaptive_element_create();
788                 break;
789         default:
790                 ms_error("Error: invalid Src node Type [%d]", node->subtype);
791                 break;
792         }
793
794         MS_SAFE_FREE(plugin_name);
795
796         if (node->gst_element == NULL)
797                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
798         else
799                 node->name = gst_element_get_name(node->gst_element);
800
801         ret = ms_node_dpm_policy_init(node);
802         if (MEDIA_STREAMER_ERROR_NONE != ret) {
803                 ms_error("Failed to init DPM policy for node [%s]", node->name);
804                 return ret;
805         }
806
807         ms_debug_fleave();
808
809         return ret;
810 }
811
812 /* The appsink has received a buffer */
813 static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
814 {
815         media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
816         media_streamer_sink_callbacks_s *sink_callbacks = NULL;
817         media_streamer_sink_data_ready_cb data_ready_cb = NULL;
818
819         ms_debug_fenter();
820
821         ms_retm_if(ms_sink == NULL, "data is NULL");
822
823         if (ms_sink->callbacks_structure != NULL) {
824                 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
825                 data_ready_cb = (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
826
827                 if (data_ready_cb)
828                         data_ready_cb((media_streamer_node_h) ms_sink, sink_callbacks->data_ready_cb.user_data);
829         }
830
831         ms_debug_fleave();
832 }
833
834 //LCOV_EXCL_START
835 /* The appsink has got eos */
836 static void sink_eos(GstElement *sink, gpointer *data)
837 {
838         media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
839         media_streamer_sink_callbacks_s *sink_callbacks = NULL;
840         media_streamer_sink_eos_cb eos_cb = NULL;
841
842         ms_debug_fenter();
843
844         ms_retm_if(ms_sink == NULL, "data is NULL");
845
846         if (ms_sink->callbacks_structure != NULL) {
847                 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
848                 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
849
850                 if (eos_cb)
851                         eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
852         }
853
854         ms_debug_fleave();
855 }
856 //LCOV_EXCL_STOP
857
858 int ms_sink_node_create(media_streamer_node_s *node)
859 {
860         int ret = MEDIA_STREAMER_ERROR_NONE;
861         char *plugin_name = NULL;
862
863         ms_debug_fenter();
864
865         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
866
867         ret = __ms_node_check_privileges(node);
868         if (ret != MEDIA_STREAMER_ERROR_NONE) {
869                 ms_error("Error getting privileges for Sink Node");
870                 return ret;
871         }
872
873         ret = __ms_sink_node_check_feature(node);
874         if (ret != MEDIA_STREAMER_ERROR_NONE) {
875                 ms_error("Error getting feature for Sink Node");
876                 return ret;
877         }
878
879         switch (node->subtype) {
880         case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
881                 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
882                 node->gst_element = ms_element_create(plugin_name, NULL);
883                 break;
884         case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
885                 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
886                 node->gst_element = ms_element_create(plugin_name, NULL);
887                 break;
888         case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
889                 ms_error("Error: not implemented yet");
890                 break;
891         case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
892                 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
893                 node->gst_element = ms_element_create(plugin_name, NULL);
894                 break;
895         case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
896                 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
897                 node->gst_element = ms_element_create(plugin_name, NULL);
898                 break;
899         case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
900                 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
901                 node->gst_element = ms_element_create(plugin_name, NULL);
902                 break;
903         case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
904                 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
905                 node->gst_element = ms_element_create(plugin_name, NULL);
906                 if (node->gst_element) {
907                         g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
908                         ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
909                         ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
910                 }
911                 break;
912         case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
913                 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
914                 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
915
916                 if (g_strrstr(plugin_name, "hlssink")) {
917                         g_object_set(G_OBJECT(node->gst_element),
918                                         "max-files", 0,
919                                         "playlist-length", 0, NULL);
920                 }
921                 break;
922         default:
923                 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
924                 break;
925         }
926
927         MS_SAFE_FREE(plugin_name);
928
929         if (node->gst_element == NULL)
930                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
931         else
932                 node->name = gst_element_get_name(node->gst_element);
933
934         ms_debug_fleave();
935
936         return ret;
937 }
938
939 void ms_node_destroy(media_streamer_node_s *node)
940 {
941         gchar *node_name = NULL;
942
943         ms_debug_fenter();
944
945         ms_retm_if(node == NULL, "node is NULL");
946         node_name = g_strdup(node->name);
947
948         /* Disconnects and clean all node signals */
949         g_list_free_full(node->sig_list, ms_signal_destroy);
950
951         /* Deinitialize policy manager */
952         if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
953                 ms_error("Failed to deinitialize DPM policy");
954
955         MS_SAFE_UNREF(node->gst_element);
956         MS_SAFE_FREE(node->name);
957         MS_SAFE_FREE(node->callbacks_structure);
958         MS_SAFE_FREE(node);
959
960         ms_info("Node [%s] has been destroyed", node_name);
961         MS_SAFE_GFREE(node_name);
962
963         ms_debug_fleave();
964 }
965
966 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
967 {
968         int ret = MEDIA_STREAMER_ERROR_NONE;
969         GstElement *bin = NULL;
970
971         ms_debug_fenter();
972
973         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
974         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
975
976         ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
977
978         switch (node->type) {
979         case MEDIA_STREAMER_NODE_TYPE_SRC:
980                 bin = ms_streamer->src_bin;
981                 break;
982         case MEDIA_STREAMER_NODE_TYPE_SINK:
983                 bin = ms_streamer->sink_bin;
984                 break;
985         default:
986                 /* Another elements will be add into transform bin */
987                 bin = ms_streamer->transform_bin;
988                 break;
989         }
990
991         if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
992                 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
993                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
994         }
995
996         ms_debug_fleave();
997
998         return ret;
999 }
1000
1001 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
1002 {
1003         ms_debug_fenter();
1004
1005         ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1006         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1007         ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
1008
1009         if (g_hash_table_contains(nodes_table, node->name)) {
1010                 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
1011                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1012         }
1013         if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
1014                 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
1015                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1016         }
1017
1018         ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
1019
1020         ms_debug_fleave();
1021
1022         return MEDIA_STREAMER_ERROR_NONE;
1023 }
1024
1025 int ms_node_remove_from_table(GHashTable *nodes_table, media_streamer_node_s *node)
1026 {
1027         ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
1028         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1029
1030         /* Removal element of this node from bin will be performed
1031          * in the callback - ms_node_remove_from_table_cb(). */
1032         if (!g_hash_table_remove(nodes_table, (gpointer) node->name)) {
1033                 ms_error("Failed to remove node [%s] from table", node->name);
1034                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1035         }
1036
1037         return MEDIA_STREAMER_ERROR_NONE;
1038 }
1039
1040 void ms_node_remove_from_table_cb(void *data)
1041 {
1042         media_streamer_node_s *node = (media_streamer_node_s *) data;
1043
1044         ms_debug_fenter();
1045
1046         ms_retm_if(node == NULL, "data is NULL");
1047
1048         if (ms_element_unlink(node->gst_element)) {
1049                 node->linked_by_user = FALSE;
1050                 node->parent_streamer = NULL;
1051                 ms_bin_remove_element(node->gst_element);
1052                 ms_info("Node [%s] removed from Media Streamer", node->name);
1053         } else {
1054                 ms_error("Failed to unlink element of node [%s]", node->name);
1055         }
1056
1057         ms_debug_fleave();
1058 }
1059
1060 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1061 {
1062         gboolean ret = FALSE;
1063
1064         ms_debug_fenter();
1065
1066         if (!src_pad || gst_pad_is_linked(src_pad))
1067                 return FALSE;
1068
1069         GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1070         if (gst_caps_is_any(src_caps))
1071                 ret = TRUE;
1072
1073         gst_caps_unref(src_caps);
1074
1075         ms_debug_fleave();
1076
1077         return ret;
1078 }
1079
1080 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1081 {
1082         int it_klass;
1083
1084         ms_debug_fenter();
1085
1086         for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1087                 if (it_klass == element_type) {
1088                         ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1089                         break;
1090                 }
1091         }
1092
1093         ms_debug_fleave();
1094
1095         return &nodes_info[it_klass];
1096 }
1097
1098 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1099 {
1100         gboolean ret = FALSE;
1101
1102         ms_retvm_if(item == NULL, FALSE, "item is NULL");
1103         ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1104
1105         ms_debug_fenter();
1106
1107         ret = ms_element_lock_state(item, g_ret, user_data);
1108
1109         ms_debug_fleave();
1110
1111         return ret;
1112 }
1113
1114 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1115 {
1116         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1117         GstElement *src_element = NULL;
1118         GstElement *found_element = NULL;
1119         media_streamer_node_s *node = NULL;
1120         GstPad *src_pad = NULL;
1121
1122         ms_debug_fenter();
1123
1124         ms_retvm_if(item == NULL, FALSE, "item is NULL");
1125         ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1126         ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1127
1128         src_element = GST_ELEMENT(g_value_get_object(item));
1129         g_object_ref(src_element);
1130         g_value_set_boolean(ret, FALSE);
1131
1132         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1133                 GST_ELEMENT_NAME(src_element));
1134         if (!node) {
1135                 /* If we fail to find corresponding node inside streamer
1136                         then apparently this element doesn't require resources. */
1137                 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1138                 g_value_set_boolean(ret, TRUE);
1139                 g_object_unref(src_element);
1140                 return TRUE;
1141         }
1142
1143         ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1144
1145         src_pad = gst_element_get_static_pad(src_element, "src");
1146
1147         if (__ms_src_need_typefind(src_pad)) {
1148                 ms_find_type(ms_streamer, src_element);
1149                 MS_SAFE_UNREF(src_element);
1150         } else {
1151                 /* Check the source element`s pad type */
1152                 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1153                 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1154                 if (gst_pad_is_linked(src_pad)) {
1155                         MS_SAFE_UNREF(src_pad);
1156                         MS_SAFE_UNREF(src_element);
1157                         g_value_set_boolean(ret, TRUE);
1158                         return TRUE;
1159                 }
1160                 /* It is media streamer Server part */
1161                 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1162                         found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1163                         GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1164                         g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1165                         gst_caps_unref(videoCaps);
1166
1167                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1168                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1169                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1170                 }
1171                 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1172                         found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1173                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1174                         found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1175                 }
1176                 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1177                 MS_SAFE_UNREF(found_element);
1178         }
1179         MS_SAFE_UNREF(src_pad);
1180
1181         g_value_set_boolean(ret, TRUE);
1182
1183         ms_debug_fleave();
1184
1185         return TRUE;
1186 }
1187
1188 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1189 {
1190         char *manifest_src_name = NULL;
1191         gchar *location = NULL;
1192         GstElement *manifest_src = NULL;
1193         GValue *val = NULL;
1194         const char *uri = NULL;
1195         gchar *protocol = NULL;
1196
1197         ms_debug_fenter();
1198
1199         ms_retvm_if(!node, NULL, "node is NULL");
1200
1201         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1202         uri = g_value_get_string(val);
1203         protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1204
1205         if (protocol && g_strrstr(protocol, "http")) {
1206                 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1207                 location = g_strdup(uri);
1208         } else if (protocol && g_strrstr(protocol, "file")) {
1209                 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1210                 location = gst_uri_get_location(uri);
1211         } else {
1212                 ms_error("Unsupported URI protocol... Check URI is file path");
1213                 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1214                         manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1215                         location = g_strdup(uri);
1216                 } else {
1217                         g_free(protocol);
1218                         ms_error("URI is not valid file path");
1219                         return NULL;
1220                 }
1221         }
1222         g_free(protocol);
1223
1224         if (manifest_src_name == NULL) {
1225                 LOGE("Error empty manifest source name for adaptive source");
1226                 g_free(location);
1227                 return NULL;
1228         }
1229
1230         manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1231         g_free(manifest_src_name);
1232
1233         if (manifest_src == NULL) {
1234                 LOGE("Error creating manifest source for adaptive source");
1235                 g_free(location);
1236                 return NULL;
1237         }
1238
1239         g_object_set(manifest_src, "location", location, NULL);
1240         g_free(location);
1241
1242         ms_debug_fleave();
1243
1244         return manifest_src;
1245 }
1246
1247 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1248 {
1249         char *plugin_name = NULL;
1250         GstElement *manifest_src = NULL;
1251         GstElement *plugin_elem = NULL;
1252         gboolean res = FALSE;
1253         GstPad *gp = NULL;
1254
1255         ms_debug_fenter();
1256
1257         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1258
1259         if (!auto_plug) {
1260                 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1261                 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1262                 ms_info("Creating [%s] element", plugin_name);
1263                 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1264                 g_free(plugin_name);
1265                 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1266                                 "Error creating element for adaptive source");
1267
1268                 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1269                 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1270                                 "Error adding adaptive element to bin for adaptive source");
1271         }
1272
1273         manifest_src = __ms_manifest_src_create(node);
1274         ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1275                         "Error creating manifest source for adaptive source");
1276
1277         res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1278         ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1279                         "Error adding manifest source to bin for adaptive source");
1280
1281         if (!auto_plug) {
1282                 res = gst_element_link(manifest_src, plugin_elem);
1283                 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1284                                 "Error linking manifest source and element for adaptive source");
1285         }
1286
1287         gp = gst_element_get_static_pad(node->gst_element, "src");
1288         ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1289                         "Error getting source pad for adaptive source");
1290
1291         if (!auto_plug) {
1292                 g_signal_connect_object(plugin_elem, "pad-added",
1293                                 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1294         } else {
1295                 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1296                 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1297         }
1298
1299         ms_debug_fleave();
1300
1301         return MEDIA_STREAMER_ERROR_NONE;
1302 }
1303
1304 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1305 {
1306         int err_code = MEDIA_STREAMER_ERROR_NONE;
1307         gchar *playlist_location = NULL;
1308         char *playlist_dir = NULL;
1309         char *split = NULL;
1310
1311         ms_debug_fenter();
1312
1313         ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1314         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1315         ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1316
1317         /* Create and start http server */
1318         err_code = ms_http_server_create(&ms_streamer->http_server);
1319         if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1320                 ms_error("Failed to create http server during prepare");
1321                 goto _DONE;
1322         }
1323
1324         ms_info("Starting http server");
1325         /* FIXME: find out how to set default port */
1326         err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1327         if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1328                 ms_error("Failed to start http server during prepare. Destroying http server");
1329                 ms_http_server_destroy(ms_streamer->http_server);
1330                 goto _DONE;
1331         }
1332
1333         g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1334         if (!playlist_location) {
1335                 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1336                 ms_error("Failed to get playlist location");
1337                 ms_http_server_destroy(ms_streamer->http_server);
1338                 goto _DONE;
1339         }
1340
1341         split = strrchr(playlist_location, '/');
1342         playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1343
1344         ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1345
1346         MS_SAFE_GFREE(playlist_location);
1347
1348 _DONE:
1349
1350         ms_debug_fleave();
1351
1352         return err_code;
1353 }
1354
1355 //LCOV_EXCL_START
1356 int ms_rtp_node_prepare(media_streamer_node_s *node)
1357 {
1358         GstElement *rtpbin = NULL;
1359         GstElement *rtp_el = NULL;
1360         GstElement *rtcp_el = NULL;
1361         GValue *val = NULL;
1362         const char *host = NULL;
1363         GstElement *video_filter = NULL;
1364         GstCaps *video_caps = NULL;
1365         GstGhostPad *ghost_pad = NULL;
1366         GstElement *audio_filter = NULL;
1367         GstCaps *audio_caps = NULL;
1368
1369         ms_debug_fenter();
1370
1371         ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1372
1373         rtpbin = ms_element_create("rtpbin", "rtpbin");
1374         ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1375
1376         if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1377                 MS_SAFE_UNREF(rtpbin);
1378                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1379         }
1380
1381         ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1382
1383         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1384         host = g_value_get_string(val);
1385
1386         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1387         if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1388                 rtp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtp");
1389                 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1390
1391                 rtcp_el = ms_element_create("udpsrc", MS_PAD_VIDEO_IN"-rtcp");
1392                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1393
1394                 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1395                         !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1396                         ms_error("Failed to link pads for rtpbin sink pad 0");
1397                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1398                 }
1399
1400                 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1401                 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1402
1403                 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_VIDEO_IN_FORMAT);
1404                 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1405         }
1406
1407         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1408         if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1409                 rtp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtp");
1410                 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1411
1412                 rtcp_el = ms_element_create("udpsrc", MS_PAD_AUDIO_IN"-rtcp");
1413                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1414
1415                 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1416                         !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1417                         ms_error("Failed to link pads for rtpbin sink pad 1");
1418                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1419                 }
1420
1421                 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1422                 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1423
1424                 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MS_PARAM_AUDIO_IN_FORMAT);
1425                 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1426         }
1427
1428         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1429         if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1430                 rtp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtp");
1431                 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1432
1433                 rtcp_el = ms_element_create("udpsink", MS_PAD_VIDEO_OUT"-rtcp");
1434                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1435
1436                 video_filter = ms_element_create("capsfilter", NULL);
1437                 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1438
1439                 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1440                 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1441                 gst_caps_unref(video_caps);
1442
1443                 gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0");
1444
1445                 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_VIDEO_IN);
1446                 if (ghost_pad) {
1447                         if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1448                                 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_VIDEO_IN);
1449                 }
1450
1451                 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1452                         !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1453                         ms_error("Failed to link pads for rtpbin src pad 0");
1454                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1455                 }
1456
1457                 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1458                 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1459                 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1460                 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1461                 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1462                 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1463         }
1464
1465         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1466         if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1467                 rtp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtp");
1468                 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1469
1470                 rtcp_el = ms_element_create("udpsink", MS_PAD_AUDIO_OUT"-rtcp");
1471                 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1472
1473                 audio_filter = ms_element_create("capsfilter", NULL);
1474                 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1475
1476                 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1477                 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1478
1479                 gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1");
1480
1481                 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_PAD_AUDIO_IN);
1482                 if (ghost_pad) {
1483                         if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1484                                 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_PAD_AUDIO_IN);
1485                 }
1486
1487                 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1488                         !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1489                         ms_error("Failed to link pads for rtpbin src pad 1");
1490                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1491                 }
1492
1493                 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1494                 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1495                 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1496                 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1497                 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1498                 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1499         }
1500
1501         ms_generate_dots(node->gst_element, "rtp_prepared");
1502
1503         ms_debug_fleave();
1504
1505         return MEDIA_STREAMER_ERROR_NONE;
1506 }
1507
1508 static int __ms_webrtc_prepare_ghost_sink_pad(GstElement *webrtc_container, GstElement *webrtcbin, const char *capsfilter_name)
1509 {
1510         int ret = MEDIA_STREAMER_ERROR_NONE;
1511         GstElement *filter;
1512         GstGhostPad *ghost_pad_in = NULL;
1513         GstPad *filter_sink_pad = NULL;
1514         GstPad *req_pad;
1515         gchar *req_pad_name;
1516         const gchar *pad_name;
1517
1518         ms_retvm_if(!webrtc_container, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
1519         ms_retvm_if(!webrtcbin, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtcbin is NULL");
1520         ms_retvm_if(!capsfilter_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "capsfilter_name is NULL");
1521
1522         if (g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) &&
1523                 g_strcmp0(capsfilter_name, _WEBRTC_VIDEO_CAPSFILTER))
1524                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1525
1526         pad_name = !g_strcmp0(capsfilter_name, _WEBRTC_AUDIO_CAPSFILTER) ? MS_PAD_AUDIO_IN : MS_PAD_VIDEO_IN;
1527
1528         if (!(filter = ms_find_element_in_bin_by_name(webrtc_container, capsfilter_name))) {
1529                 ms_debug("No need to export the ghost sink pad for [%s]", pad_name);
1530                 return MEDIA_STREAMER_ERROR_NONE;
1531         }
1532
1533         if (!(ghost_pad_in = (GstGhostPad *)gst_element_get_static_pad(webrtc_container, pad_name))) {
1534                 ms_error("Failed to get ghost pad for webrtc_container");
1535                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1536         }
1537
1538         if (!gst_pad_is_linked((GstPad *)ghost_pad_in)) {
1539                 ms_error("[%s] is set media format but not linked to peer node", pad_name);
1540                 MS_SAFE_UNREF(ghost_pad_in);
1541                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1542         }
1543
1544         ms_info("%s is found, link it with webrtcbin and export the ghost pad[%s] of webrtc_container",
1545                         capsfilter_name, pad_name);
1546
1547         if (!(req_pad = gst_element_get_request_pad(webrtcbin, "sink_%u"))) {
1548                 ms_error("Failed to get request pad");
1549                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1550         }
1551         if (!(req_pad_name = gst_pad_get_name(req_pad))) {
1552                 ms_error("Failed to get request pad name");
1553                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1554         }
1555         if (!gst_element_link_pads(filter, "src", webrtcbin, req_pad_name)) {
1556                 ms_error("Failed to link pads, %s - webrtcbin", capsfilter_name);
1557                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1558                 goto end;
1559         }
1560
1561         if (!(filter_sink_pad = gst_element_get_static_pad(filter, "sink"))) {
1562                 ms_error("Failed to get capsfilter sink pad in webrtc_container");
1563                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1564                 goto end;
1565         }
1566         if (!gst_ghost_pad_set_target(ghost_pad_in, filter_sink_pad)) {
1567                 ms_info("Failed to gst_ghost_pad_set_target() for %s", pad_name);
1568                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1569                 goto end;
1570         }
1571
1572 end:
1573         MS_SAFE_GFREE(req_pad_name);
1574         MS_SAFE_UNREF(filter_sink_pad);
1575         MS_SAFE_UNREF(ghost_pad_in);
1576
1577         return ret;
1578 }
1579
1580 GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
1581 {
1582         GstElement *webrtcbin = NULL;
1583         node_info_s *node_klass_type = NULL;
1584
1585         ms_retvm_if(webrtc_node == NULL, NULL, "webrtc_node is NULL");
1586         ms_retvm_if(webrtc_node->gst_element == NULL, NULL, "webrtc_container is NULL");
1587
1588         ms_debug_fenter();
1589
1590         node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
1591         webrtcbin = ms_find_element_in_bin_by_type(webrtc_node->gst_element, node_klass_type);
1592         if (!webrtcbin)
1593                 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
1594
1595         ms_debug_fleave();
1596
1597         return webrtcbin;
1598 }
1599
1600 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1601 {
1602         int ret = MEDIA_STREAMER_ERROR_NONE;
1603         GstElement *webrtcbin = NULL;
1604         GObject *send_channel = NULL;
1605         gboolean is_offerer = FALSE;
1606         media_streamer_webrtc_callbacks_s *_callbacks = NULL;
1607
1608         ms_debug_fenter();
1609
1610         ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1611         ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1612         ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
1613
1614         if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(node)))
1615                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1616
1617         _callbacks = (media_streamer_webrtc_callbacks_s *) node->callbacks_structure;
1618         if (!_callbacks || !(_callbacks->message_cb.callback)) {
1619                 ms_error("message callback should be set before preparing");
1620                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1621         }
1622
1623         if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_AUDIO_CAPSFILTER)))
1624                 return ret;
1625         if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
1626                 return ret;
1627
1628         if (ms_webrtc_node_is_offerer(node, &is_offerer) != MEDIA_STREAMER_ERROR_NONE) {
1629                 ms_error("Failed to get peer type");
1630                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1631         }
1632
1633         if (is_offerer)
1634                 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
1635
1636         ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
1637         ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
1638         ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-connection-state", G_CALLBACK(ms_webrtcbin_notify_ice_connection_state_cb), node);
1639
1640         if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
1641                 ms_error("Failed to set state to READY");
1642                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1643         }
1644
1645         g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
1646         if (send_channel)
1647                 ms_info("data channel(%p) for sending is created", send_channel);
1648         else
1649                 ms_warning("Failed to create data channel");
1650
1651         ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
1652         ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
1653
1654         ms_generate_dots(node->gst_element, "webrtc_prepared");
1655
1656         ms_debug_fleave();
1657
1658         return MEDIA_STREAMER_ERROR_NONE;
1659 }
1660 //LCOV_EXCL_STOP
1661
1662 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1663 {
1664         ms_debug_fenter();
1665
1666         ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1667         ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1668
1669         ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
1670         ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
1671
1672         ms_debug_fleave();
1673
1674         return MEDIA_STREAMER_ERROR_NONE;
1675 }
1676
1677 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
1678 {
1679         GParamSpec *param_spec;
1680         int it_param;
1681
1682         ms_debug_fenter();
1683
1684         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1685         ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1686
1687         for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1688                 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1689                 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1690                                 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
1691                         ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
1692                         *param_list = g_list_append(*param_list, &(param_table[it_param]));
1693                 }
1694         }
1695         ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
1696
1697         ms_debug_fleave();
1698
1699         return MEDIA_STREAMER_ERROR_NONE;
1700 }
1701
1702 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
1703 {
1704         int ret = MEDIA_STREAMER_ERROR_NONE;
1705         Evas_Object *obj = NULL;
1706         media_streamer_wl_info_s wl_info;
1707
1708         obj = (Evas_Object *)param_value;
1709
1710         /* get wayland parent id */
1711         if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
1712                 LOGE("failed to get wayland info");
1713                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1714         }
1715
1716         LOGD("wayland global surface id : %d", wl_info.parent_id);
1717
1718         gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
1719
1720         return ret;
1721 }
1722
1723 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
1724 {
1725
1726         int ret = MEDIA_STREAMER_ERROR_NONE;
1727
1728         ms_debug_fenter();
1729
1730         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1731         ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1732         ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
1733
1734         if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1735                 ret = __ms_rtp_node_set_property(node, param, param_value);
1736                 ms_debug_fleave();
1737                 return ret;
1738         }
1739
1740         if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
1741                 ret = __ms_webrtc_node_set_property(node, param, param_value);
1742                 ms_debug_fleave();
1743                 return ret;
1744         }
1745
1746         if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1747                         node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
1748                 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
1749                 ms_debug_fleave();
1750                 return ret;
1751         }
1752
1753         if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
1754                 int camera_id = (int)strtol(param_value, NULL, 10);
1755                 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
1756                 g_object_set(node->gst_element, param->origin_name, camera_id, NULL);
1757         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1758                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1759                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1760                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1761                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1762                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1763                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1764                 g_object_set(node->gst_element, param->origin_name, (int)strtol(param_value, NULL, 10), NULL);
1765         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1766                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1767                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1768                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1769                 g_object_set(node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
1770         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
1771                 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
1772                         ret = ms_util_uri_path_check(param_value);
1773                         if (ret != MEDIA_STREAMER_ERROR_NONE)
1774                                 return ret;
1775                 }
1776                 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1777         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1778                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1779                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1780                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1781                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1782                                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1783                 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1784         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY)) {
1785                 ret = __ms_node_set_display(node, param_value);
1786         } else {
1787                 ms_info("Can not set parameter [%s] in the node [%s]", param->param_name, node->name);
1788                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1789         }
1790
1791         ms_debug_fleave();
1792
1793         return ret;
1794 }
1795
1796 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
1797 {
1798         int ret = MEDIA_STREAMER_ERROR_NONE;
1799         GList *p_list = NULL;
1800         int written_count = 0;
1801         param_s *param = NULL;
1802         GList *list_iter = NULL;
1803         char *string_val = NULL;
1804
1805         ms_debug_fenter();
1806
1807         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1808         ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1809
1810         ret = __ms_node_get_param_list(node, &p_list);
1811         if (ret == MEDIA_STREAMER_ERROR_NONE) {
1812                 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1813                         param = (param_s *)list_iter->data;
1814                         if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
1815                                 ret = ms_node_set_param_value(node, param, string_val);
1816                                 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1817                                         written_count++;
1818                                 } else {
1819                                         ms_error("failed to set param");
1820                                         break;
1821                                 }
1822                         }
1823                 }
1824         }
1825         g_list_free(p_list);
1826
1827         ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
1828         if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
1829                 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1830
1831         ms_debug_fleave();
1832
1833         return ret;
1834 }
1835
1836 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
1837 {
1838         int ret = MEDIA_STREAMER_ERROR_NONE;
1839         GList *p_list = NULL;
1840         param_s *param = NULL;
1841         GList *list_iter = NULL;
1842         char *string_val = NULL;
1843
1844         ms_debug_fenter();
1845
1846         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1847         ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1848
1849         ret = __ms_node_get_param_list(node, &p_list);
1850         if (ret == MEDIA_STREAMER_ERROR_NONE) {
1851                 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1852                         param = (param_s *)list_iter->data;
1853
1854                         if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
1855                                 bundle_add_str(param_list, param->param_name, string_val);
1856                                 MS_SAFE_FREE(string_val);
1857                         }
1858                 }
1859         }
1860         if (p_list)
1861                 g_list_free(p_list);
1862
1863         ms_debug_fleave();
1864
1865         return ret;
1866 }
1867
1868 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
1869 {
1870         GParamSpec *param_spec;
1871         gboolean found_param = FALSE;
1872         int it_param;
1873
1874         ms_debug_fenter();
1875
1876         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1877         ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
1878         ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1879
1880         for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1881                 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
1882                         param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1883                         if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1884                                         __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name) ||
1885                                         __ms_webrtc_node_has_property(node, param_table[it_param].origin_name)) {
1886                                 *param = &(param_table[it_param]);
1887                                 ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
1888                                 found_param = TRUE;
1889                                 break;
1890                         }
1891                 }
1892         }
1893         ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
1894
1895         ms_debug_fleave();
1896
1897         return MEDIA_STREAMER_ERROR_NONE;
1898 }
1899
1900 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
1901 {
1902         int ret = MEDIA_STREAMER_ERROR_NONE;
1903         char *string_val = NULL;
1904         GParamSpec *param_spec = NULL;
1905         GValue value = G_VALUE_INIT;
1906
1907         ms_debug_fenter();
1908
1909         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1910         ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1911         ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
1912
1913         if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
1914                 ret = __ms_rtp_node_get_property(node, param, &value);
1915         else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1916                                 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
1917                 ret = __ms_adaptive_src_node_get_property(node, param, &value);
1918         else {
1919                 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
1920                 if (param_spec) {
1921                         g_value_init(&value, param_spec->value_type);
1922                         g_object_get_property(G_OBJECT(node->gst_element), param->origin_name, &value);
1923
1924                         ms_info("Got parameter [%s] for node [%s] with description [%s]", param->param_name, node->name, g_param_spec_get_blurb(param_spec));
1925                 } else {
1926                         ms_error("There is no parameter [%s] for node [%s]", param->origin_name, node->name);
1927                         return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1928                 }
1929         }
1930
1931         if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID) ||
1932                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1933                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1934                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1935                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
1936                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
1937                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
1938                         !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
1939                 if (G_VALUE_HOLDS_INT(&value))
1940                         string_val = g_strdup_printf("%d", g_value_get_int(&value));
1941                 else
1942                         string_val = g_strdup_printf("%u", g_value_get_uint(&value));
1943         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1944                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1945                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1946                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1947                 string_val = g_strdup(g_value_get_boolean(&value) ? "true" : "false");
1948         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI) ||
1949                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1950                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1951                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1952                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1953                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1954                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1955                 string_val = g_value_dup_string(&value);
1956         } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1957                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1958                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1959                                 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1960                 string_val = g_strdup_printf("%d", g_value_get_enum(&value));
1961         }
1962
1963         *string_value = strdup(string_val);
1964         g_free(string_val);
1965
1966         g_value_reset(&value);
1967         g_value_unset(&value);
1968
1969         ms_debug_fleave();
1970
1971         return ret;
1972 }
1973
1974 static int __ms_rtp_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
1975 {
1976         int ret = MEDIA_STREAMER_ERROR_NONE;
1977         media_format_mimetype_e mime;
1978         gchar *rtp_caps_str = NULL;
1979
1980         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1981         ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
1982         ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
1983         ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
1984
1985         ms_debug_fenter();
1986
1987         /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
1988         if (g_strrstr(pad_name, MS_PAD_VIDEO_IN)) {
1989                 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
1990                 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1991                         rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=%s", ms_convert_mime_to_rtp_format(mime));
1992                         param_s param = {MS_PARAM_VIDEO_IN_FORMAT, MS_PARAM_VIDEO_IN_FORMAT};
1993                         ret = ms_node_set_param_value(node, &param, rtp_caps_str);
1994                 }
1995         } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
1996                 int audio_channels, audio_samplerate;
1997                 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
1998                 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1999                         rtp_caps_str = g_strdup_printf("application/x-rtp,media=(string)audio,clock-rate=(int)8000,encoding-name=(string)AMR,encoding-params=(string)1,octet-align=(string)1");
2000                         param_s param = {MS_PARAM_AUDIO_IN_FORMAT, MS_PARAM_AUDIO_IN_FORMAT};
2001                         ret = ms_node_set_param_value(node, &param, rtp_caps_str);
2002                 }
2003         } else {
2004                 ms_error("[%s]'s pad [%s] can't be set with the given format", GST_ELEMENT_NAME(node->gst_element), pad_name);
2005                 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2006         }
2007         MS_SAFE_GFREE(rtp_caps_str);
2008
2009         return ret;
2010 }
2011
2012 static int __ms_webrtc_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2013 {
2014         int ret = MEDIA_STREAMER_ERROR_NONE;
2015         media_format_mimetype_e mime;
2016         const gchar *encoding_name = NULL;
2017         const gchar *capsfilter_name = NULL;
2018         gchar *caps_str = NULL;
2019         gchar *media = NULL;
2020         gint payload = 0;
2021         GstCaps *caps = NULL;
2022         GstElement *capsfilter = NULL;
2023
2024         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2025         ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2026         ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2027         ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2028
2029         ms_debug_fenter();
2030
2031         if (!g_strrstr(pad_name, MS_PAD_VIDEO_IN) && !g_strrstr(pad_name, MS_PAD_AUDIO_IN)) {
2032                 ms_error("Not supported pad_name(%s)", pad_name);
2033                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2034         }
2035
2036         if (g_strrstr(pad_name, MS_PAD_VIDEO_IN) &&
2037                 !media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2038                 media = "video";
2039                 payload = 96;
2040                 capsfilter_name = _WEBRTC_VIDEO_CAPSFILTER;
2041         } else if (g_strrstr(pad_name, MS_PAD_AUDIO_IN) &&
2042                 !media_format_get_audio_info(fmt, &mime, NULL, NULL, NULL, NULL)) {
2043                 media = "audio";
2044                 payload = 97;
2045                 capsfilter_name = _WEBRTC_AUDIO_CAPSFILTER;
2046         } else {
2047                 ms_error("Invalid media format for pad_name(%s)", pad_name);
2048                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2049         }
2050
2051         encoding_name = ms_convert_mime_to_rtp_format(mime);
2052         caps = gst_caps_new_simple("application/x-rtp",
2053                                                                 "media", G_TYPE_STRING, media,
2054                                                                 "encoding-name", G_TYPE_STRING, encoding_name,
2055                                                                 "payload", G_TYPE_INT, payload, NULL);
2056
2057         if (!(capsfilter = ms_find_element_in_bin_by_name(node->gst_element, capsfilter_name))) {
2058                 ms_debug("Create %s", capsfilter_name);
2059
2060                 if (!(capsfilter = ms_element_create("capsfilter", capsfilter_name))) {
2061                         ms_error("Failed to create capsfilter element: %s", capsfilter_name);
2062                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2063                 }
2064                 if (!ms_bin_add_element(node->gst_element, capsfilter, FALSE)) {
2065                         ms_error("Failed to add capsfilter(%s) to webrtc_container", capsfilter_name);
2066                         return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2067                 }
2068         }
2069
2070         g_object_set(G_OBJECT(capsfilter), "caps", (GValue *)caps, NULL);
2071
2072         caps_str = gst_caps_to_string(caps);
2073         ms_info("[%s] is set to [%s]", caps_str, capsfilter_name);
2074         MS_SAFE_GFREE(caps_str);
2075
2076         gst_caps_unref(caps);
2077
2078         return ret;
2079 }
2080
2081 static int __ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2082 {
2083         gboolean can_accept = FALSE;
2084         GstElement *element = NULL;
2085         GstCaps *fmt_caps = NULL;
2086         GstElementFactory *factory = NULL;
2087         GstPad *node_pad = NULL;
2088
2089         ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2090         ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
2091         ms_retvm_if(!pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2092         ms_retvm_if(!fmt, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2093
2094         element = node->gst_element;
2095
2096         fmt_caps = ms_create_caps_from_fmt(fmt, nodes_info[node->type].default_name);
2097         ms_retvm_if(!fmt_caps, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Can't convert fmt into Caps");
2098
2099         factory = gst_element_get_factory(element);
2100         node_pad = gst_element_get_static_pad(element, pad_name);
2101         if (!node_pad) {
2102                 gst_caps_unref(fmt_caps);
2103                 ms_error("Failed to gst_element_get_static_pad(), pad_name[%s]", pad_name);
2104                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2105         }
2106
2107         if (GST_PAD_IS_SRC(node_pad))
2108                 can_accept = gst_element_factory_can_src_any_caps(factory, fmt_caps);
2109         else if (GST_PAD_IS_SINK(node_pad))
2110                 can_accept = gst_element_factory_can_sink_any_caps(factory, fmt_caps);
2111         else
2112                 ms_error("[%s] doesn`t have valid pad [%s]", GST_ELEMENT_NAME(element), pad_name);
2113
2114         MS_SAFE_UNREF(node_pad);
2115
2116         if (!can_accept) {
2117                 gst_caps_unref(fmt_caps);
2118                 ms_error("[%s]'s pad [%s] can`t be set with the given format", GST_ELEMENT_NAME(element), pad_name);
2119                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2120         }
2121
2122         MS_SET_INT_CAPS_PARAM(element, pad_name, fmt_caps);
2123         gst_caps_unref(fmt_caps);
2124
2125         ms_info("[%s]'s pad [%s] was set with given format", GST_ELEMENT_NAME(element), pad_name);
2126
2127         return MEDIA_STREAMER_ERROR_NONE;
2128 }
2129
2130 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
2131 {
2132         int ret = MEDIA_STREAMER_ERROR_NONE;
2133
2134         ms_debug_fenter();
2135
2136         ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
2137         ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node's element is NULL");
2138         ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
2139         ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
2140
2141         if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
2142                 ret = __ms_rtp_node_set_pad_format(node, pad_name, fmt);
2143         else if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC)
2144                 ret = __ms_webrtc_node_set_pad_format(node, pad_name, fmt);
2145         else
2146                 ret = __ms_node_set_pad_format(node, pad_name, fmt);
2147
2148         ms_debug_fleave();
2149
2150         return ret;
2151 }
2152
2153 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
2154 {
2155         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2156         media_streamer_node_s *node = NULL;
2157         GstElement *element = NULL;
2158
2159         ms_debug_fenter();
2160
2161         ms_retvm_if(item == NULL, FALSE, "item is NULL");
2162         ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2163         ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2164
2165         g_value_set_boolean(ret, FALSE);
2166
2167         element = GST_ELEMENT(g_value_get_object(item));
2168         g_object_ref(element);
2169
2170         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2171                 GST_ELEMENT_NAME(element));
2172         if (!node) {
2173                 /* If we fail to find corresponding node inside streamer
2174                         then apparently this element doesn't require resources. */
2175                 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2176                 g_value_set_boolean(ret, TRUE);
2177                 g_object_unref(element);
2178                 return TRUE;
2179         }
2180
2181         if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
2182                 ms_error("Failed to acquire resource for node [%s]", node->name);
2183                 g_object_unref(element);
2184                 return FALSE;
2185         }
2186
2187         g_value_set_boolean(ret, TRUE);
2188
2189         g_object_unref(element);
2190
2191         ms_debug_fleave();
2192
2193         return TRUE;
2194 }
2195
2196 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
2197 {
2198         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2199         media_streamer_node_s *node = NULL;
2200         GstElement *element = NULL;
2201
2202         ms_debug_fenter();
2203
2204         ms_retvm_if(item == NULL, FALSE, "item is NULL");
2205         ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2206         ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2207
2208         g_value_set_boolean(ret, FALSE);
2209
2210         element = GST_ELEMENT(g_value_get_object(item));
2211         g_object_ref(element);
2212
2213         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2214                 GST_ELEMENT_NAME(element));
2215         if (!node) {
2216                 /* If we fail to find corresponding node inside streamer
2217                         then apparently this element doesn't require resources. */
2218                 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2219                 g_value_set_boolean(ret, TRUE);
2220                 g_object_unref(element);
2221                 return TRUE;
2222         }
2223
2224         if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
2225                 ms_error("Failed to release resource for node [%s]", node->name);
2226                 g_object_unref(element);
2227                 return FALSE;
2228         }
2229
2230         g_value_set_boolean(ret, TRUE);
2231
2232         g_object_unref(element);
2233
2234         ms_debug_fleave();
2235
2236         return TRUE;
2237 }
2238
2239 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
2240 {
2241         media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
2242         media_streamer_node_s *node = NULL;
2243         GstElement *element = NULL;
2244         gboolean allowed = FALSE;
2245
2246         ms_debug_fenter();
2247
2248         ms_retvm_if(item == NULL, FALSE, "item is NULL");
2249         ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
2250         ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
2251         ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
2252
2253         element = GST_ELEMENT(g_value_get_object(item));
2254         g_object_ref(element);
2255
2256         node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
2257                 GST_ELEMENT_NAME(element));
2258         if (!node) {
2259                 /* If we fail to find corresponding node inside streamer
2260                         then apparently this element doesn't require resources. */
2261                 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
2262                 g_value_set_boolean(ret, TRUE);
2263                 g_object_unref(element);
2264                 return TRUE;
2265         }
2266
2267         if (ms_node_dpm_policy_check(node, &allowed)) {
2268                 ms_error("Failed to check DPM policy for node [%s]", node->name);
2269                 /* Note that it should be TRUE(allowed) if the DPM API failed. */
2270                 g_value_set_boolean(ret, TRUE);
2271                 g_object_unref(element);
2272                 return FALSE;
2273         }
2274
2275         g_value_set_boolean(ret, allowed);
2276
2277         g_object_unref(element);
2278
2279         ms_debug_fleave();
2280
2281         return allowed;
2282 }
2283
2284 int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
2285 {
2286         GValue *val = NULL;
2287         const gchar *type = NULL;
2288
2289         ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
2290         ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
2291
2292         if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
2293                 ms_error("Invalid node type");
2294                 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
2295         }
2296
2297         val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
2298         if (!val) {
2299                 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
2300                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2301         }
2302
2303         if (!(type = g_value_get_string(val))) {
2304                 ms_error("Failed to g_value_get_string()");
2305                 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
2306         }
2307
2308         ms_info("peer type is [%s]", type);
2309
2310         *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
2311
2312         return MEDIA_STREAMER_ERROR_NONE;
2313 }