2 * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include <cynara-client.h>
18 #include <system_info.h>
20 #include <gst/video/videooverlay.h>
21 #include "media_streamer_node.h"
22 #include "media_streamer_node_resources.h"
23 #include "media_streamer_node_dpm_policy.h"
24 #include "media_streamer_util.h"
25 #include "media_streamer_gst.h"
26 #include "media_streamer_gst_webrtc.h"
28 #define SMACK_LABEL_LEN 255
29 #define DEFAULT_URI_SCHEME_LENGTH 10
31 #define _FEATURE_NAME_WIFI "http://tizen.org/feature/network.wifi"
32 #define _FEATURE_NAME_TELEPHONY "http://tizen.org/feature/network.telephony"
33 #define _FEATURE_NAME_ETHERNET "http://tizen.org/feature/network.ethernet"
34 #define _FEATURE_NAME_CAMERA "http://tizen.org/feature/camera"
35 #define _FEATURE_NAME_MICROPHONE "http://tizen.org/feature/microphone"
37 static param_s param_table[] = {
38 {MEDIA_STREAMER_PARAM_CAMERA_ID, "camera-id"},
39 {MEDIA_STREAMER_PARAM_CAPTURE_WIDTH, "capture-width"},
40 {MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT, "capture-height"},
41 {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "is-live"},
42 {MEDIA_STREAMER_PARAM_IS_LIVE_STREAM, "living"},
43 {MEDIA_STREAMER_PARAM_URI, "uri"},
44 {MEDIA_STREAMER_PARAM_URI, "location"},
45 {MEDIA_STREAMER_PARAM_USER_AGENT, "user-agent"},
46 {MEDIA_STREAMER_PARAM_STREAM_TYPE, "stream-type"},
47 {MEDIA_STREAMER_PARAM_PORT, "port"},
48 {MEDIA_STREAMER_PARAM_VIDEO_IN_PORT, "video_in_port"},
49 {MEDIA_STREAMER_PARAM_AUDIO_IN_PORT, "audio_in_port"},
50 {MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT, "video_out_port"},
51 {MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT, "audio_out_port"},
52 {MEDIA_STREAMER_PARAM_IP_ADDRESS, "address"},
53 {MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, "webrtc-peer-type"},
54 {MEDIA_STREAMER_PARAM_AUDIO_DEVICE, "audio_device"},
55 {MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED, "sync"},
56 {MEDIA_STREAMER_PARAM_ROTATE, "rotate"},
57 {MEDIA_STREAMER_PARAM_FLIP, "flip"},
58 {MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD, "display-geometry-method"},
59 {MEDIA_STREAMER_PARAM_DISPLAY, "display"},
60 {MEDIA_STREAMER_PARAM_VISIBLE, "visible"},
61 {MEDIA_STREAMER_PARAM_USE_TBM, "use-tbm"},
62 {MEDIA_STREAMER_PARAM_HOST, "host"},
63 {MEDIA_STREAMER_PARAM_SEGMENT_LOCATION, "location"},
64 {MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, "playlist-location"},
68 static node_info_s nodes_info[] = {
69 {"Generic", "none"}, /* MEDIA_STREAMER_NODE_TYPE_NONE */
70 {"Source", "source"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */
71 {"Sink", "sink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */
72 {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
73 {"Codec/Decoder/Video", "video_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */
74 {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
75 {"Codec/Decoder/Audio", "audio_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */
76 {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */
77 {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */
78 {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */
79 {"Codec/Payloader/Network/RTP", "rtph263pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */
80 {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */
81 {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */
82 {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */
83 {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */
84 {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */
85 {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */
86 {"Codec/Parser", "h263parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */
87 {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */
88 {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */
89 {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */
90 {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */
91 {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
92 {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */
93 {"Generic/Bin", "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */
94 {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */
95 {MEDIA_STREAMER_STRICT, "output-selector"}, /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */
96 {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */
97 {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */
98 {"Filter/Network/WebRTC", "webrtc_container"}, /* MEDIA_STREAMER_NODE_TYPE_WEBRTC */
102 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
108 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
109 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
111 if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
114 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
118 return val ? TRUE : FALSE;
121 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
123 int ret = MEDIA_STREAMER_ERROR_NONE;
128 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
129 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
130 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
131 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
134 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
135 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
136 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
137 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
138 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
139 g_value_init(value, G_TYPE_INT);
140 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
141 g_value_init(value, G_TYPE_STRING);
143 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
145 g_value_copy(val, value);
152 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
154 int ret = MEDIA_STREAMER_ERROR_NONE;
159 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
160 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
161 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
162 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
164 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
166 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
167 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
170 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
171 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
172 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
173 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
175 g_value_init(val, G_TYPE_INT);
176 g_value_set_int(val, (int)strtol(param_value, NULL, 10));
177 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
179 g_value_init(val, G_TYPE_STRING);
180 g_value_set_string(val, param_value);
181 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT) ||
182 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT)) {
183 GstCaps *caps = gst_caps_from_string(param_value);
186 g_value_init(val, GST_TYPE_CAPS);
187 gst_value_set_caps(val, caps);
189 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
192 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
200 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
206 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
207 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
209 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
210 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
214 return val ? TRUE : FALSE;
222 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
228 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
229 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
230 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
231 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
233 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
235 ms_error("failed to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
236 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
239 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE)) {
240 if (strcmp(param_value, WEBRTC_PEER_OFFER) && strcmp(param_value, WEBRTC_PEER_ANSWER)) {
241 ms_error("failed to set property, param value should be [%s] or [%s]", WEBRTC_PEER_OFFER, WEBRTC_PEER_ANSWER);
242 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
245 g_value_init(val, G_TYPE_STRING);
246 g_value_set_string(val, param_value);
248 ms_error("failed to set property, undefined param name[%s]", param->param_name);
249 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
254 return MEDIA_STREAMER_ERROR_NONE;
257 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
263 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
264 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
266 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
267 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
268 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
272 return val ? TRUE : FALSE;
280 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
282 int ret = MEDIA_STREAMER_ERROR_NONE;
287 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
288 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
289 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
290 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
291 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
293 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
294 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI))
295 g_value_init(value, G_TYPE_STRING);
297 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
299 g_value_copy(val, value);
306 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
308 int ret = MEDIA_STREAMER_ERROR_NONE;
313 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
314 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
315 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
316 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
317 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
319 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
321 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
322 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
325 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
327 g_value_init(val, G_TYPE_STRING);
328 g_value_set_string(val, param_value);
330 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
338 static int __ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
341 const gchar *type = NULL;
343 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
344 ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
346 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
347 ms_error("Invalid node type");
348 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
351 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
353 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
354 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
357 if (!(type = g_value_get_string(val))) {
358 ms_error("Failed to g_value_get_string()");
359 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
362 ms_info("peer type is [%s]", type);
364 *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
366 return MEDIA_STREAMER_ERROR_NONE;
369 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
371 int ret = MEDIA_STREAMER_ERROR_NONE;
372 GstCaps *sink_caps = NULL;
373 GstCaps *src_caps = NULL;
377 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
379 sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt) : NULL;
380 src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt) : NULL;
382 node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
384 ms_info("Creating node with info: klass_name[%s]; default[%s]",
385 plug_info.info->klass_name, plug_info.info->default_name);
387 node->gst_element = ms_node_element_create(&plug_info, node->type);
388 if (node->gst_element)
389 node->name = gst_element_get_name(node->gst_element);
391 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
394 gst_caps_unref(src_caps);
397 gst_caps_unref(sink_caps);
404 /* This signal callback is called when appsrc needs data, we add an idle handler
405 * to the mainloop to start pushing data into the appsrc */
406 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
408 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
409 media_streamer_callback_s *src_callback = NULL;
410 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
414 ms_retm_if(ms_src == NULL, "data is NULL");
415 ms_retm_if(pipeline == NULL, "pipeline is NULL");
417 if (ms_src->callbacks_structure != NULL) {
418 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
419 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
420 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
426 /* This callback is called when appsrc has enough data and we can stop sending.
427 * We remove the idle handler from the mainloop */
428 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
430 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
431 media_streamer_callback_s *src_callback = NULL;
432 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
436 ms_retm_if(ms_src == NULL, "data is NULL");
437 ms_retm_if(pipeline == NULL, "pipeline is NULL");
439 if (ms_src->callbacks_structure != NULL) {
440 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
441 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
442 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
448 static int __ms_node_check_privileges(media_streamer_node_s *node)
450 int ret = MEDIA_STREAMER_ERROR_NONE;
452 char *privilege = NULL;
454 char smackLabel[SMACK_LABEL_LEN + 1];
456 cynara *cynara_h = NULL;
460 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
462 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
463 switch (node->subtype) {
464 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
465 privilege = "http://tizen.org/privilege/internet";
467 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
468 privilege = "http://tizen.org/privilege/internet";
470 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
471 privilege = "http://tizen.org/privilege/camera";
473 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
474 privilege = "http://tizen.org/privilege/recorder";
476 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
477 privilege = "http://tizen.org/privilege/camera";
480 ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
485 if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
486 switch (node->subtype) {
487 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
488 privilege = "http://tizen.org/privilege/internet";
491 ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
496 /* Skip checking for privilege permission in case of other types of Nodes */
497 if (privilege == NULL)
500 if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
501 ms_error("Failed to initialize cynara structure\n");
502 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
505 bzero(smackLabel, SMACK_LABEL_LEN + 1);
507 /* Getting smack label */
508 opened_file = fopen("/proc/self/attr/current", "r");
509 if (opened_file == NULL) {
510 ms_error("Failed to open /proc/self/attr/current\n");
511 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
513 ret_val = fread(smackLabel, sizeof(smackLabel), 1, opened_file);
516 ms_error("Failed to read /proc/self/attr/current\n");
517 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
521 snprintf(uid, sizeof(uid), "%d", getuid());
522 ms_info("%s %s %s\n", smackLabel, uid, privilege);
524 /* Checking with cynara for current session */
525 ret_val = cynara_check(cynara_h, smackLabel, "", uid, privilege);
526 ms_info("Cynara_check [%d] ", ret_val);
529 case CYNARA_API_ACCESS_ALLOWED:
530 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
532 case CYNARA_API_ACCESS_DENIED:
534 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
535 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
539 cynara_finish(cynara_h);
546 static int __ms_src_node_check_feature(media_streamer_node_s *node)
548 int ret = MEDIA_STREAMER_ERROR_NONE;
549 bool enabled = FALSE;
550 bool supported = FALSE;
554 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
556 switch (node->subtype) {
557 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
558 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
559 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
560 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
561 ms_info("wifi status = %d", enabled);
565 ms_error("SYSTEM_INFO_ERROR");
568 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
569 ms_info("telephony status = %d", enabled);
573 ms_error("SYSTEM_INFO_ERROR");
576 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
577 ms_info("ethernet status = %d", enabled);
581 ms_error("SYSTEM_INFO_ERROR");
584 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
586 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
587 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
588 ms_info("microphone status = %d", enabled);
592 ms_error("SYSTEM_INFO_ERROR");
595 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
597 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
598 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
599 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
600 ms_info("camera status = %d", enabled);
604 ms_error("SYSTEM_INFO_ERROR");
607 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
610 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
619 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
621 int ret = MEDIA_STREAMER_ERROR_NONE;
622 bool enabled = FALSE;
623 bool supported = FALSE;
627 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
629 switch (node->subtype) {
630 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
631 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
632 /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
633 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
634 ms_info("wifi status = %d", enabled);
638 ms_error("SYSTEM_INFO_ERROR");
641 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
642 ms_info("telephony status = %d", enabled);
646 ms_error("SYSTEM_INFO_ERROR");
649 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
650 ms_info("ethernet status = %d", enabled);
654 ms_error("SYSTEM_INFO_ERROR");
657 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
660 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
669 int ms_src_node_create(media_streamer_node_s *node)
671 int ret = MEDIA_STREAMER_ERROR_NONE;
672 char *plugin_name = NULL;
676 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
678 ret = __ms_node_check_privileges(node);
679 if (ret != MEDIA_STREAMER_ERROR_NONE) {
680 ms_error("Error getting privileges for Src Node");
684 ret = __ms_src_node_check_feature(node);
685 if (ret != MEDIA_STREAMER_ERROR_NONE) {
686 ms_error("Error getting feature for Src Node");
690 switch (node->subtype) {
691 case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
692 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
693 node->gst_element = ms_element_create(plugin_name, NULL);
695 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
696 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
697 node->gst_element = ms_element_create(plugin_name, NULL);
699 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
700 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
701 node->gst_element = ms_element_create(plugin_name, NULL);
703 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
704 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
705 node->gst_element = ms_element_create(plugin_name, NULL);
707 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
708 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
709 node->gst_element = ms_element_create(plugin_name, NULL);
711 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
712 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
713 node->gst_element = ms_element_create(plugin_name, NULL);
715 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
716 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
717 node->gst_element = ms_element_create(plugin_name, NULL);
719 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
720 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
721 node->gst_element = ms_element_create(plugin_name, NULL);
723 case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
724 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
725 node->gst_element = ms_element_create(DEFAULT_APP_SOURCE, NULL);
726 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
727 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
728 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
730 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
731 node->gst_element = ms_adaptive_element_create();
734 ms_error("Error: invalid Src node Type [%d]", node->subtype);
738 MS_SAFE_FREE(plugin_name);
740 if (node->gst_element == NULL)
741 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
743 node->name = gst_element_get_name(node->gst_element);
745 ret = ms_node_dpm_policy_init(node);
746 if (MEDIA_STREAMER_ERROR_NONE != ret) {
747 ms_error("Failed to init DPM policy for node [%s]", node->name);
756 /* The appsink has received a buffer */
757 static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
759 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
760 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
761 media_streamer_sink_data_ready_cb data_ready_cb = NULL;
765 ms_retm_if(ms_sink == NULL, "data is NULL");
767 if (ms_sink->callbacks_structure != NULL) {
768 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
769 data_ready_cb = (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
772 data_ready_cb((media_streamer_node_h) ms_sink, sink_callbacks->data_ready_cb.user_data);
779 /* The appsink has got eos */
780 static void sink_eos(GstElement *sink, gpointer *data)
782 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
783 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
784 media_streamer_sink_eos_cb eos_cb = NULL;
788 ms_retm_if(ms_sink == NULL, "data is NULL");
790 if (ms_sink->callbacks_structure != NULL) {
791 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
792 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
795 eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
802 int ms_sink_node_create(media_streamer_node_s *node)
804 int ret = MEDIA_STREAMER_ERROR_NONE;
805 char *plugin_name = NULL;
809 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
811 ret = __ms_node_check_privileges(node);
812 if (ret != MEDIA_STREAMER_ERROR_NONE) {
813 ms_error("Error getting privileges for Sink Node");
817 ret = __ms_sink_node_check_feature(node);
818 if (ret != MEDIA_STREAMER_ERROR_NONE) {
819 ms_error("Error getting feature for Sink Node");
823 switch (node->subtype) {
824 case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
825 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
826 node->gst_element = ms_element_create(plugin_name, NULL);
828 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
829 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
830 node->gst_element = ms_element_create(plugin_name, NULL);
832 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
833 ms_error("Error: not implemented yet");
835 case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
836 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
837 node->gst_element = ms_element_create(plugin_name, NULL);
839 case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
840 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
841 node->gst_element = ms_element_create(plugin_name, NULL);
843 case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
844 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
845 node->gst_element = ms_element_create(plugin_name, NULL);
847 case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
848 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
849 node->gst_element = ms_element_create(plugin_name, NULL);
850 if (node->gst_element) {
851 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
852 ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
853 ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
856 case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
857 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
858 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
860 if (g_strrstr(plugin_name, "hlssink")) {
861 g_object_set(G_OBJECT(node->gst_element),
863 "playlist-length", 0, NULL);
867 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
871 MS_SAFE_FREE(plugin_name);
873 if (node->gst_element == NULL)
874 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
876 node->name = gst_element_get_name(node->gst_element);
883 void ms_node_destroy(media_streamer_node_s *node)
885 gchar *node_name = NULL;
889 ms_retm_if(node == NULL, "node is NULL");
890 node_name = g_strdup(node->name);
892 /* Disconnects and clean all node signals */
893 g_list_free_full(node->sig_list, ms_signal_destroy);
895 /* Deinitialize policy manager */
896 if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
897 ms_error("Failed to deinitialize DPM policy");
899 MS_SAFE_UNREF(node->gst_element);
900 MS_SAFE_FREE(node->name);
901 MS_SAFE_FREE(node->callbacks_structure);
904 ms_info("Node [%s] has been destroyed", node_name);
905 MS_SAFE_GFREE(node_name);
910 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
912 int ret = MEDIA_STREAMER_ERROR_NONE;
913 GstElement *bin = NULL;
917 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
918 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
920 ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
922 switch (node->type) {
923 case MEDIA_STREAMER_NODE_TYPE_SRC:
924 bin = ms_streamer->src_bin;
926 case MEDIA_STREAMER_NODE_TYPE_SINK:
927 bin = ms_streamer->sink_bin;
930 /* Another elements will be add into transform bin */
931 bin = ms_streamer->transform_bin;
935 if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
936 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
937 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
945 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
949 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
950 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
951 ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
953 if (g_hash_table_contains(nodes_table, node->name)) {
954 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
955 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
957 if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
958 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
959 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
962 ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
966 return MEDIA_STREAMER_ERROR_NONE;
969 void ms_node_remove_from_table(void *data)
971 media_streamer_node_s *node = (media_streamer_node_s *) data;
975 ms_retm_if(node == NULL, "data is NULL");
977 if (ms_element_unlink(node->gst_element)) {
978 node->linked_by_user = FALSE;
979 node->parent_streamer = NULL;
980 ms_bin_remove_element(node->gst_element);
981 ms_info("Node [%s] removed from Media Streamer", node->name);
983 ms_error("Error: Node [%s] remove failed", node->name);
990 static gboolean __ms_src_need_typefind(GstPad *src_pad)
992 gboolean ret = FALSE;
996 if (!src_pad || gst_pad_is_linked(src_pad))
999 GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1000 if (gst_caps_is_any(src_caps))
1003 gst_caps_unref(src_caps);
1010 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1016 for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1017 if (it_klass == element_type) {
1018 ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1025 return &nodes_info[it_klass];
1028 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1030 gboolean ret = FALSE;
1032 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1033 ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1037 ret = ms_element_lock_state(item, g_ret, user_data);
1044 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1046 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1047 GstElement *src_element = NULL;
1048 GstElement *found_element = NULL;
1049 media_streamer_node_s *node = NULL;
1050 GstPad *src_pad = NULL;
1054 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1055 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1056 ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1058 src_element = GST_ELEMENT(g_value_get_object(item));
1059 g_object_ref(src_element);
1060 g_value_set_boolean(ret, FALSE);
1062 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1063 GST_ELEMENT_NAME(src_element));
1065 /* If we fail to find corresponding node inside streamer
1066 then apparently this element doesn't require resources. */
1067 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1068 g_value_set_boolean(ret, TRUE);
1069 g_object_unref(src_element);
1073 ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1075 src_pad = gst_element_get_static_pad(src_element, "src");
1077 if (__ms_src_need_typefind(src_pad)) {
1078 ms_find_type(ms_streamer, src_element);
1079 MS_SAFE_UNREF(src_element);
1081 /* Check the source element`s pad type */
1082 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1083 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1084 if (gst_pad_is_linked(src_pad)) {
1085 MS_SAFE_UNREF(src_pad);
1086 MS_SAFE_UNREF(src_element);
1087 g_value_set_boolean(ret, TRUE);
1090 /* It is media streamer Server part */
1091 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1092 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1093 GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1094 g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1095 gst_caps_unref(videoCaps);
1097 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1098 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1099 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1101 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1102 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1103 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1104 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1106 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1107 MS_SAFE_UNREF(found_element);
1109 MS_SAFE_UNREF(src_pad);
1111 g_value_set_boolean(ret, TRUE);
1118 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1120 char *manifest_src_name = NULL;
1121 gchar *location = NULL;
1122 GstElement *manifest_src = NULL;
1124 const char *uri = NULL;
1125 gchar *protocol = NULL;
1129 ms_retvm_if(!node, NULL, "node is NULL");
1131 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1132 uri = g_value_get_string(val);
1133 protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1135 if (protocol && g_strrstr(protocol, "http")) {
1136 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1137 location = g_strdup(uri);
1138 } else if (protocol && g_strrstr(protocol, "file")) {
1139 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1140 location = gst_uri_get_location(uri);
1142 ms_error("Unsupported URI protocol... Check URI is file path");
1143 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1144 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1145 location = g_strdup(uri);
1148 ms_error("URI is not valid file path");
1154 if (manifest_src_name == NULL) {
1155 LOGE("Error empty manifest source name for adaptive source");
1160 manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1161 g_free(manifest_src_name);
1163 if (manifest_src == NULL) {
1164 LOGE("Error creating manifest source for adaptive source");
1169 g_object_set(manifest_src, "location", location, NULL);
1174 return manifest_src;
1177 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1179 char *plugin_name = NULL;
1180 GstElement *manifest_src = NULL;
1181 GstElement *plugin_elem = NULL;
1182 gboolean res = FALSE;
1187 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1190 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1191 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1192 ms_info("Creating [%s] element", plugin_name);
1193 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1194 g_free(plugin_name);
1195 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1196 "Error creating element for adaptive source");
1198 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1199 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1200 "Error adding adaptive element to bin for adaptive source");
1203 manifest_src = __ms_manifest_src_create(node);
1204 ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1205 "Error creating manifest source for adaptive source");
1207 res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1208 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1209 "Error adding manifest source to bin for adaptive source");
1212 res = gst_element_link(manifest_src, plugin_elem);
1213 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1214 "Error linking manifest source and element for adaptive source");
1217 gp = gst_element_get_static_pad(node->gst_element, "src");
1218 ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1219 "Error getting source pad for adaptive source");
1222 g_signal_connect_object(plugin_elem, "pad-added",
1223 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1225 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1226 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1231 return MEDIA_STREAMER_ERROR_NONE;
1234 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1236 int err_code = MEDIA_STREAMER_ERROR_NONE;
1237 gchar *playlist_location = NULL;
1238 char *playlist_dir = NULL;
1243 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1244 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1245 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1247 /* Create and start http server */
1248 err_code = ms_http_server_create(&ms_streamer->http_server);
1249 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1250 ms_error("Failed to create http server during prepare");
1254 ms_info("Starting http server");
1255 /* FIXME: find out how to set default port */
1256 err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1257 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1258 ms_error("Failed to start http server during prepare. Destroying http server");
1259 ms_http_server_destroy(ms_streamer->http_server);
1263 g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1264 if (!playlist_location) {
1265 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1266 ms_error("Failed to get playlist location");
1267 ms_http_server_destroy(ms_streamer->http_server);
1271 split = strrchr(playlist_location, '/');
1272 playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1274 ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1276 MS_SAFE_GFREE(playlist_location);
1286 int ms_rtp_node_prepare(media_streamer_node_s *node)
1288 GstElement *rtpbin = NULL;
1289 GstElement *rtp_el = NULL;
1290 GstElement *rtcp_el = NULL;
1292 const char *host = NULL;
1293 GstElement *video_filter = NULL;
1294 GstCaps *video_caps = NULL;
1295 GstGhostPad *ghost_pad = NULL;
1296 GstElement *audio_filter = NULL;
1297 GstCaps *audio_caps = NULL;
1301 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1303 rtpbin = ms_element_create("rtpbin", "rtpbin");
1304 ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1306 if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1307 MS_SAFE_UNREF(rtpbin);
1308 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1311 ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1313 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1314 host = g_value_get_string(val);
1316 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1317 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1318 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rtp");
1319 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1321 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rctp");
1322 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1324 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1325 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1326 ms_error("Failed to link pads for rtpbin sink pad 0");
1327 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1330 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1331 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1333 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT);
1334 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1337 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1338 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1339 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rtp");
1340 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1342 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rctp");
1343 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1345 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1346 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1347 ms_error("Failed to link pads for rtpbin sink pad 1");
1348 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1351 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1352 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1354 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT);
1355 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1358 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1359 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1360 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rtp");
1361 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1363 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rctp");
1364 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1366 video_filter = ms_element_create("capsfilter", NULL);
1367 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1369 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1370 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1371 gst_caps_unref(video_caps);
1373 gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0");
1375 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_VIDEO_IN);
1377 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1378 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_VIDEO_IN);
1381 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1382 !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1383 ms_error("Failed to link pads for rtpbin src pad 0");
1384 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1387 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1388 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1389 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1390 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1391 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1392 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1395 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1396 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1397 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rtp");
1398 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1400 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rctp");
1401 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1403 audio_filter = ms_element_create("capsfilter", NULL);
1404 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1406 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1407 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1409 gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1");
1411 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_AUDIO_IN);
1413 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1414 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_AUDIO_IN);
1417 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1418 !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1419 ms_error("Failed to link pads for rtpbin src pad 1");
1420 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1423 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1424 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1425 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1426 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1427 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1428 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1431 ms_generate_dots(node->gst_element, "rtp_prepared");
1435 return MEDIA_STREAMER_ERROR_NONE;
1438 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1440 GstElement *webrtcbin = NULL;
1441 node_info_s *node_klass_type = NULL;
1442 GObject *send_channel = NULL;
1443 gboolean is_offerer = FALSE;
1447 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1448 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1449 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
1451 node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
1452 if (!(webrtcbin = ms_find_element_in_bin_by_type(node->gst_element, node_klass_type))) {
1453 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
1454 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1457 if (!node->user_cb.callback) {
1458 ms_error("message callback should be set before preparing");
1459 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1462 if (__ms_webrtc_node_is_offerer(node, &is_offerer)) {
1463 ms_error("Failed to get peer type");
1464 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1468 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
1470 ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
1471 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
1473 if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
1474 ms_error("Faild to set state to READY");
1475 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1478 g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
1480 ms_info("data channel(%p) for sending is created", send_channel);
1482 ms_warning("Failed to create data channel, is usrsctp available?");
1485 ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
1486 ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), ms_streamer);
1488 ms_generate_dots(node->gst_element, "webrtc_prepared");
1492 return MEDIA_STREAMER_ERROR_NONE;
1497 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1501 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1502 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1504 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
1505 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
1509 return MEDIA_STREAMER_ERROR_NONE;
1512 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
1514 GParamSpec *param_spec;
1519 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1520 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1522 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1523 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1524 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1525 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
1526 ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
1527 *param_list = g_list_append(*param_list, &(param_table[it_param]));
1530 ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
1534 return MEDIA_STREAMER_ERROR_NONE;
1537 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
1539 int ret = MEDIA_STREAMER_ERROR_NONE;
1540 Evas_Object *obj = NULL;
1541 media_streamer_wl_info_s wl_info;
1543 obj = (Evas_Object *)param_value;
1545 /* get wayland parent id */
1546 if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
1547 LOGE("failed to get wayland info");
1548 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1551 LOGD("wayland global surface id : %d", wl_info.parent_id);
1553 gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
1559 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
1562 int ret = MEDIA_STREAMER_ERROR_NONE;
1566 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1567 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1568 ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
1570 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1571 ret = __ms_rtp_node_set_property(node, param, param_value);
1576 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
1577 ret = __ms_webrtc_node_set_property(node, param, param_value);
1582 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1583 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
1584 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
1589 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
1590 int camera_id = (int)strtol(param_value, NULL, 10);
1591 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
1592 g_object_set(node->gst_element, param->origin_name, camera_id, NULL);
1593 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1594 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1595 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1596 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1597 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1598 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1599 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1600 g_object_set(node->gst_element, param->origin_name, (int)strtol(param_value, NULL, 10), NULL);
1601 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1602 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1603 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1604 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1605 g_object_set(node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
1606 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
1607 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
1608 ret = ms_util_uri_path_check(param_value);
1609 if (ret != MEDIA_STREAMER_ERROR_NONE)
1612 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1613 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1614 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1615 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1616 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1617 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1618 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1619 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1620 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY)) {
1621 ret = __ms_node_set_display(node, param_value);
1623 ms_info("Can not set parameter [%s] in the node [%s]", param->param_name, node->name);
1624 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1632 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
1634 int ret = MEDIA_STREAMER_ERROR_NONE;
1635 GList *p_list = NULL;
1636 int written_count = 0;
1637 param_s *param = NULL;
1638 GList *list_iter = NULL;
1639 char *string_val = NULL;
1643 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1644 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1646 ret = __ms_node_get_param_list(node, &p_list);
1647 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1648 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1649 param = (param_s *)list_iter->data;
1650 if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
1651 ret = ms_node_set_param_value(node, param, string_val);
1652 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1655 ms_error("failed to set param");
1661 g_list_free(p_list);
1663 ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
1664 if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
1665 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1672 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
1674 int ret = MEDIA_STREAMER_ERROR_NONE;
1675 GList *p_list = NULL;
1676 param_s *param = NULL;
1677 GList *list_iter = NULL;
1678 char *string_val = NULL;
1682 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1683 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1685 ret = __ms_node_get_param_list(node, &p_list);
1686 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1687 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1688 param = (param_s *)list_iter->data;
1690 if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
1691 bundle_add_str(param_list, param->param_name, string_val);
1692 MS_SAFE_FREE(string_val);
1697 g_list_free(p_list);
1704 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
1706 GParamSpec *param_spec;
1707 gboolean found_param = FALSE;
1712 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1713 ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
1714 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1716 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1717 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
1718 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1719 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1720 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name) ||
1721 __ms_webrtc_node_has_property(node, param_table[it_param].origin_name)) {
1722 *param = &(param_table[it_param]);
1723 ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
1729 ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
1733 return MEDIA_STREAMER_ERROR_NONE;
1736 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
1738 int ret = MEDIA_STREAMER_ERROR_NONE;
1739 char *string_val = NULL;
1740 GParamSpec *param_spec = NULL;
1741 GValue value = G_VALUE_INIT;
1745 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1746 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1747 ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
1749 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
1750 ret = __ms_rtp_node_get_property(node, param, &value);
1751 else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1752 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
1753 ret = __ms_adaptive_src_node_get_property(node, param, &value);
1755 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
1757 g_value_init(&value, param_spec->value_type);
1758 g_object_get_property(G_OBJECT(node->gst_element), param->origin_name, &value);
1760 ms_info("Got parameter [%s] for node [%s] with description [%s]", param->param_name, node->name, g_param_spec_get_blurb(param_spec));
1762 ms_error("There is no parameter [%s] for node [%s]", param->origin_name, node->name);
1763 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1767 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID) ||
1768 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1769 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1770 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1771 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
1772 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
1773 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
1774 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
1775 if (G_VALUE_HOLDS_INT(&value))
1776 string_val = g_strdup_printf("%d", g_value_get_int(&value));
1778 string_val = g_strdup_printf("%u", g_value_get_uint(&value));
1779 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1780 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1781 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1782 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1783 string_val = g_strdup(g_value_get_boolean(&value) ? "true" : "false");
1784 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI) ||
1785 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1786 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1787 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1788 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1789 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1790 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1791 string_val = g_value_dup_string(&value);
1792 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1793 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1794 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1795 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1796 string_val = g_strdup_printf("%d", g_value_get_enum(&value));
1799 *string_value = string_val;
1801 g_value_reset(&value);
1802 g_value_unset(&value);
1809 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
1811 int ret = MEDIA_STREAMER_ERROR_NONE;
1815 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1816 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
1817 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
1819 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1820 media_format_mimetype_e mime;
1821 gchar *rtp_caps_str = NULL;
1823 /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
1824 if (g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN)) {
1825 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
1826 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1827 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));
1828 param_s param = {MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT};
1829 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
1831 } else if (g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN)) {
1832 int audio_channels, audio_samplerate;
1833 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
1834 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1835 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");
1836 param_s param = {MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT};
1837 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
1841 MS_SAFE_GFREE(rtp_caps_str);
1843 ret = ms_element_set_fmt(node->gst_element, pad_name, fmt);
1851 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
1853 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1854 media_streamer_node_s *node = NULL;
1855 GstElement *element = NULL;
1859 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1860 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1861 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1863 g_value_set_boolean(ret, FALSE);
1865 element = GST_ELEMENT(g_value_get_object(item));
1866 g_object_ref(element);
1868 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1869 GST_ELEMENT_NAME(element));
1871 /* If we fail to find corresponding node inside streamer
1872 then apparently this element doesn't require resources. */
1873 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1874 g_value_set_boolean(ret, TRUE);
1875 g_object_unref(element);
1879 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
1880 ms_error("Failed to acquire resource for node [%s]", node->name);
1881 g_object_unref(element);
1885 g_value_set_boolean(ret, TRUE);
1887 g_object_unref(element);
1894 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
1896 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1897 media_streamer_node_s *node = NULL;
1898 GstElement *element = NULL;
1902 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1903 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1904 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1906 g_value_set_boolean(ret, FALSE);
1908 element = GST_ELEMENT(g_value_get_object(item));
1909 g_object_ref(element);
1911 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1912 GST_ELEMENT_NAME(element));
1914 /* If we fail to find corresponding node inside streamer
1915 then apparently this element doesn't require resources. */
1916 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1917 g_value_set_boolean(ret, TRUE);
1918 g_object_unref(element);
1922 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
1923 ms_error("Failed to release resource for node [%s]", node->name);
1924 g_object_unref(element);
1928 g_value_set_boolean(ret, TRUE);
1930 g_object_unref(element);
1937 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
1939 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1940 media_streamer_node_s *node = NULL;
1941 GstElement *element = NULL;
1942 gboolean allowed = FALSE;
1946 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1947 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1948 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
1949 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1951 element = GST_ELEMENT(g_value_get_object(item));
1952 g_object_ref(element);
1954 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1955 GST_ELEMENT_NAME(element));
1957 /* If we fail to find corresponding node inside streamer
1958 then apparently this element doesn't require resources. */
1959 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1960 g_value_set_boolean(ret, TRUE);
1961 g_object_unref(element);
1965 if (ms_node_dpm_policy_check(node, &allowed)) {
1966 ms_error("Failed to check DPM policy for node [%s]", node->name);
1967 /* Note that it should be TRUE(allowed) if the DPM API failed. */
1968 g_value_set_boolean(ret, TRUE);
1969 g_object_unref(element);
1973 g_value_set_boolean(ret, allowed);
1975 g_object_unref(element);