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