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_WEBRTC_REMOTE_SESSION_DESCRIPTION, "webrtc-remote-session-description"},
55 {MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, "webrtc-add-ice-candidate"},
56 {MEDIA_STREAMER_PARAM_AUDIO_DEVICE, "audio_device"},
57 {MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED, "sync"},
58 {MEDIA_STREAMER_PARAM_ROTATE, "rotate"},
59 {MEDIA_STREAMER_PARAM_FLIP, "flip"},
60 {MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD, "display-geometry-method"},
61 {MEDIA_STREAMER_PARAM_DISPLAY, "display"},
62 {MEDIA_STREAMER_PARAM_VISIBLE, "visible"},
63 {MEDIA_STREAMER_PARAM_USE_TBM, "use-tbm"},
64 {MEDIA_STREAMER_PARAM_HOST, "host"},
65 {MEDIA_STREAMER_PARAM_SEGMENT_LOCATION, "location"},
66 {MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, "playlist-location"},
70 static node_info_s nodes_info[] = {
71 {"Generic", "none"}, /* MEDIA_STREAMER_NODE_TYPE_NONE */
72 {"Source", "source"}, /* MEDIA_STREAMER_NODE_TYPE_SRC */
73 {"Sink", "sink"}, /* MEDIA_STREAMER_NODE_TYPE_SINK */
74 {"Codec/Encoder/Video", "video_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER */
75 {"Codec/Decoder/Video", "video_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DECODER */
76 {"Codec/Encoder/Audio", "audio_encoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER */
77 {"Codec/Decoder/Audio", "audio_decoder"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DECODER */
78 {"Filter/Converter/Video", "videoconvert"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_CONVERTER */
79 {"Filter/Converter/Audio", "audioconvert"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_CONVERTER */
80 {MEDIA_STREAMER_STRICT, "audioresample"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_RESAMPLE */
81 {"Codec/Payloader/Network/RTP", "rtph263pay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY */
82 {"Codec/Payloader/Network/RTP", "rtpamrpay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY */
83 {"Codec/Depayloader/Network/RTP", "rtph263depay"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_DEPAY */
84 {"Codec/Depayloader/Network/RTP", "rtpamrdepay"}, /* MEDIA_STREAMER_NODE_TYPE_AUDIO_DEPAY */
85 {"Filter/Effect/Video", "videorate"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_RATE */
86 {"Filter/Converter/Video/Scaler", "videoscale"}, /* MEDIA_STREAMER_NODE_TYPE_VIDEO_SCALE */
87 {MEDIA_STREAMER_STRICT, "textoverlay"}, /* MEDIA_STREAMER_NODE_TYPE_TEXT_OVERLAY */
88 {"Codec/Parser", "h263parse"}, /* MEDIA_STREAMER_NODE_TYPE_PARSER */
89 {MEDIA_STREAMER_STRICT, "capsfilter"}, /* MEDIA_STREAMER_NODE_TYPE_FILTER */
90 {MEDIA_STREAMER_STRICT, "tee"}, /* MEDIA_STREAMER_NODE_TYPE_TEE */
91 {MEDIA_STREAMER_STRICT, "queue"}, /* MEDIA_STREAMER_NODE_TYPE_QUEUE */
92 {MEDIA_STREAMER_STRICT, "multiqueue"}, /* MEDIA_STREAMER_NODE_TYPE_MQUEUE */
93 {"Codec/Muxer", "qtmux"}, /* MEDIA_STREAMER_NODE_TYPE_MUXER */
94 {"Codec/Demuxer", "qtdemux"}, /* MEDIA_STREAMER_NODE_TYPE_DEMUXER */
95 {"Generic/Bin", "rtpbin"}, /* MEDIA_STREAMER_NODE_TYPE_RTP */
96 {MEDIA_STREAMER_STRICT, "input-selector"}, /* MEDIA_STREAMER_NODE_TYPE_INPUT_SELECTOR */
97 {MEDIA_STREAMER_STRICT, "output-selector"}, /* MEDIA_STREAMER_NODE_TYPE_OUTPUT_SELECTOR */
98 {MEDIA_STREAMER_STRICT, "interleave"}, /* MEDIA_STREAMER_NODE_TYPE_INTERLEAVE */
99 {MEDIA_STREAMER_STRICT, "deinterleave"}, /* MEDIA_STREAMER_NODE_TYPE_DEINTERLEAVE */
100 {"Filter/Network/WebRTC", "webrtc_container"}, /* MEDIA_STREAMER_NODE_TYPE_WEBRTC */
104 static gboolean __ms_rtp_node_has_property(media_streamer_node_s *node, const char *param_name)
110 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
111 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
113 if (node->type != MEDIA_STREAMER_NODE_TYPE_RTP)
116 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
120 return val ? TRUE : FALSE;
123 static int __ms_rtp_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
125 int ret = MEDIA_STREAMER_ERROR_NONE;
130 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
131 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
132 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
133 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
136 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
137 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
138 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
139 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
140 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
141 g_value_init(value, G_TYPE_INT);
142 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
143 g_value_init(value, G_TYPE_STRING);
145 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
147 g_value_copy(val, value);
154 static int __ms_rtp_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
156 int ret = MEDIA_STREAMER_ERROR_NONE;
161 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
162 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_RTP, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
163 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
164 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
166 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
168 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
169 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
172 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
173 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
174 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
175 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
177 g_value_init(val, G_TYPE_INT);
178 g_value_set_int(val, (int)strtol(param_value, NULL, 10));
179 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_HOST)) {
181 g_value_init(val, G_TYPE_STRING);
182 g_value_set_string(val, param_value);
183 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT) ||
184 !strcmp(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT)) {
185 GstCaps *caps = gst_caps_from_string(param_value);
188 g_value_init(val, GST_TYPE_CAPS);
189 gst_value_set_caps(val, caps);
191 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
194 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
202 static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
208 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
209 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
211 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
212 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
216 return val ? TRUE : FALSE;
224 static int __ms_webrtc_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
231 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
232 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
233 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
234 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
236 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
238 ms_error("failed to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
239 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
242 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE)) {
243 if (strcmp(param_value, WEBRTC_PEER_OFFER) && strcmp(param_value, WEBRTC_PEER_ANSWER)) {
244 ms_error("failed to set property, param value should be [%s] or [%s]", WEBRTC_PEER_OFFER, WEBRTC_PEER_ANSWER);
245 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
248 g_value_init(val, G_TYPE_STRING);
249 g_value_set_string(val, param_value);
250 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION)) {
251 ret = ms_webrtcbin_set_remote_session_description(node, param_value);
252 if (ret != MEDIA_STREAMER_ERROR_NONE) {
253 ms_error("failed to set remote session description\n%s", param_value);
257 g_value_init(val, G_TYPE_STRING);
258 g_value_set_string(val, param_value);
259 } else if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE)) {
260 ret = ms_webrtcbin_add_ice_candidate(node, param_value);
261 if (ret != MEDIA_STREAMER_ERROR_NONE) {
262 ms_error("failed to add ICE candidate\n%s", param_value);
266 ms_error("failed to set property, undefined param name[%s]", param->param_name);
267 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
272 return MEDIA_STREAMER_ERROR_NONE;
275 static gboolean __ms_adaptive_src_node_has_property(media_streamer_node_s *node, const char *param_name)
281 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
282 ms_retvm_if(!param_name, FALSE, "Error: invalid property parameter");
284 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
285 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
286 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
290 return val ? TRUE : FALSE;
298 static int __ms_adaptive_src_node_get_property(media_streamer_node_s *node, param_s *param, GValue *value)
300 int ret = MEDIA_STREAMER_ERROR_NONE;
305 ms_retvm_if(!node || !node->gst_element, FALSE, "Error: empty node");
306 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
307 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
308 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
309 ms_retvm_if(!value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "value is NULL");
311 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
312 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI))
313 g_value_init(value, G_TYPE_STRING);
315 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
317 g_value_copy(val, value);
324 static int __ms_adaptive_src_node_set_property(media_streamer_node_s *node, param_s *param, const char *param_value)
326 int ret = MEDIA_STREAMER_ERROR_NONE;
331 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Error: empty node");
332 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_SRC &&
333 node->subtype != MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
334 ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: invalid property parameter");
335 ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
337 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param->param_name);
339 ms_error("fail to get [%s] val from [%s]", param->param_name, GST_ELEMENT_NAME(node->gst_element));
340 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
343 if (!strcmp(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
345 g_value_init(val, G_TYPE_STRING);
346 g_value_set_string(val, param_value);
348 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
356 static int __ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer)
359 const gchar *type = NULL;
361 ms_retvm_if(!node || !node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: empty node");
362 ms_retvm_if(!is_offerer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error: is_offerer is null");
364 if (node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
365 ms_error("Invalid node type");
366 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
369 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE);
371 ms_error("Failed to get [%s] val from [%s]", MEDIA_STREAMER_PARAM_WEBRTC_PEER_TYPE, GST_ELEMENT_NAME(node->gst_element));
372 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
375 if (!(type = g_value_get_string(val))) {
376 ms_error("Failed to g_value_get_string()");
377 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
380 ms_info("peer type is [%s]", type);
382 *is_offerer = (gboolean)(!strcmp(type, WEBRTC_PEER_OFFER));
384 return MEDIA_STREAMER_ERROR_NONE;
387 int ms_node_create(media_streamer_node_s *node, media_format_h in_fmt, media_format_h out_fmt)
389 int ret = MEDIA_STREAMER_ERROR_NONE;
390 GstCaps *sink_caps = NULL;
391 GstCaps *src_caps = NULL;
395 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
397 sink_caps = in_fmt ? ms_create_caps_from_fmt(in_fmt) : NULL;
398 src_caps = out_fmt ? ms_create_caps_from_fmt(out_fmt) : NULL;
400 node_plug_s plug_info = {&(nodes_info[node->type]), src_caps, sink_caps, NULL};
402 ms_info("Creating node with info: klass_name[%s]; default[%s]",
403 plug_info.info->klass_name, plug_info.info->default_name);
405 node->gst_element = ms_node_element_create(&plug_info, node->type);
406 if (node->gst_element)
407 node->name = gst_element_get_name(node->gst_element);
409 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
412 gst_caps_unref(src_caps);
415 gst_caps_unref(sink_caps);
422 /* This signal callback is called when appsrc needs data, we add an idle handler
423 * to the mainloop to start pushing data into the appsrc */
424 static void __ms_src_start_feed_cb(GstElement *pipeline, guint size, gpointer data)
426 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
427 media_streamer_callback_s *src_callback = NULL;
428 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
432 ms_retm_if(ms_src == NULL, "data is NULL");
433 ms_retm_if(pipeline == NULL, "pipeline is NULL");
435 if (ms_src->callbacks_structure != NULL) {
436 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
437 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
438 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_UNDERRUN, src_callback->user_data);
444 /* This callback is called when appsrc has enough data and we can stop sending.
445 * We remove the idle handler from the mainloop */
446 static void __ms_src_stop_feed_cb(GstElement *pipeline, gpointer data)
448 media_streamer_node_s *ms_src = (media_streamer_node_s *) data;
449 media_streamer_callback_s *src_callback = NULL;
450 media_streamer_custom_buffer_status_cb buffer_status_cb = NULL;
454 ms_retm_if(ms_src == NULL, "data is NULL");
455 ms_retm_if(pipeline == NULL, "pipeline is NULL");
457 if (ms_src->callbacks_structure != NULL) {
458 src_callback = (media_streamer_callback_s *) ms_src->callbacks_structure;
459 buffer_status_cb = (media_streamer_custom_buffer_status_cb) src_callback->callback;
460 buffer_status_cb((media_streamer_node_h) ms_src, MEDIA_STREAMER_CUSTOM_BUFFER_OVERFLOW, src_callback->user_data);
466 static int __ms_node_check_privileges(media_streamer_node_s *node)
468 int ret = MEDIA_STREAMER_ERROR_NONE;
470 char *privilege = NULL;
472 char smackLabel[SMACK_LABEL_LEN + 1];
474 cynara *cynara_h = NULL;
478 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
480 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC) {
481 switch (node->subtype) {
482 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
483 privilege = "http://tizen.org/privilege/internet";
485 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
486 privilege = "http://tizen.org/privilege/internet";
488 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
489 privilege = "http://tizen.org/privilege/camera";
491 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
492 privilege = "http://tizen.org/privilege/recorder";
494 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
495 privilege = "http://tizen.org/privilege/camera";
498 ms_info(" [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
503 if (node->type == MEDIA_STREAMER_NODE_TYPE_SINK) {
504 switch (node->subtype) {
505 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
506 privilege = "http://tizen.org/privilege/internet";
509 ms_info("For current Sink Node [%s] subtype [%d] privileges are not needed", node->name, node->subtype);
514 /* Skip checking for privilege permission in case of other types of Nodes */
515 if (privilege == NULL)
518 if (CYNARA_API_SUCCESS != cynara_initialize(&cynara_h, NULL)) {
519 ms_error("Failed to initialize cynara structure\n");
520 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
523 bzero(smackLabel, SMACK_LABEL_LEN + 1);
525 /* Getting smack label */
526 opened_file = fopen("/proc/self/attr/current", "r");
527 if (opened_file == NULL) {
528 ms_error("Failed to open /proc/self/attr/current\n");
529 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
531 ret_val = fread(smackLabel, sizeof(smackLabel), 1, opened_file);
534 ms_error("Failed to read /proc/self/attr/current\n");
535 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
539 snprintf(uid, sizeof(uid), "%d", getuid());
540 ms_info("%s %s %s\n", smackLabel, uid, privilege);
542 /* Checking with cynara for current session */
543 ret_val = cynara_check(cynara_h, smackLabel, "", uid, privilege);
544 ms_info("Cynara_check [%d] ", ret_val);
547 case CYNARA_API_ACCESS_ALLOWED:
548 ms_info("Access to Node [%s] subtype [%d] is allowed", node->name, node->subtype);
550 case CYNARA_API_ACCESS_DENIED:
552 ms_error("Access to Node [%s] subtype [%d] is denied", node->name, node->subtype);
553 ret = MEDIA_STREAMER_ERROR_PERMISSION_DENIED;
557 cynara_finish(cynara_h);
564 static int __ms_src_node_check_feature(media_streamer_node_s *node)
566 int ret = MEDIA_STREAMER_ERROR_NONE;
567 bool enabled = FALSE;
568 bool supported = FALSE;
572 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
574 switch (node->subtype) {
575 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
576 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
577 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
578 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
579 ms_info("wifi status = %d", enabled);
583 ms_error("SYSTEM_INFO_ERROR");
586 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
587 ms_info("telephony status = %d", enabled);
591 ms_error("SYSTEM_INFO_ERROR");
594 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
595 ms_info("ethernet status = %d", enabled);
599 ms_error("SYSTEM_INFO_ERROR");
602 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
604 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
605 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_MICROPHONE, &enabled)) {
606 ms_info("microphone status = %d", enabled);
610 ms_error("SYSTEM_INFO_ERROR");
613 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
615 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
616 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
617 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_CAMERA, &enabled)) {
618 ms_info("camera status = %d", enabled);
622 ms_error("SYSTEM_INFO_ERROR");
625 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
628 ms_info("For current Src Node subtype [%d] privileges are not needed", node->subtype);
637 static int __ms_sink_node_check_feature(media_streamer_node_s *node)
639 int ret = MEDIA_STREAMER_ERROR_NONE;
640 bool enabled = FALSE;
641 bool supported = FALSE;
645 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
647 switch (node->subtype) {
648 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
649 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
650 /* case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE: */
651 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_WIFI, &enabled)) {
652 ms_info("wifi status = %d", enabled);
656 ms_error("SYSTEM_INFO_ERROR");
659 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_TELEPHONY, &enabled)) {
660 ms_info("telephony status = %d", enabled);
664 ms_error("SYSTEM_INFO_ERROR");
667 if (SYSTEM_INFO_ERROR_NONE == system_info_get_platform_bool(_FEATURE_NAME_ETHERNET, &enabled)) {
668 ms_info("ethernet status = %d", enabled);
672 ms_error("SYSTEM_INFO_ERROR");
675 ret = MEDIA_STREAMER_ERROR_NOT_SUPPORTED;
678 ms_info("For current Sink Node subtype [%d] privileges are not needed", node->subtype);
687 int ms_src_node_create(media_streamer_node_s *node)
689 int ret = MEDIA_STREAMER_ERROR_NONE;
690 char *plugin_name = NULL;
694 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Handle is NULL");
696 ret = __ms_node_check_privileges(node);
697 if (ret != MEDIA_STREAMER_ERROR_NONE) {
698 ms_error("Error getting privileges for Src Node");
702 ret = __ms_src_node_check_feature(node);
703 if (ret != MEDIA_STREAMER_ERROR_NONE) {
704 ms_error("Error getting feature for Src Node");
708 switch (node->subtype) {
709 case MEDIA_STREAMER_NODE_SRC_TYPE_FILE:
710 plugin_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
711 node->gst_element = ms_element_create(plugin_name, NULL);
713 case MEDIA_STREAMER_NODE_SRC_TYPE_RTSP:
714 plugin_name = ms_ini_get_string("node type 1:rtsp", DEFAULT_UDP_SOURCE);
715 node->gst_element = ms_element_create(plugin_name, NULL);
717 case MEDIA_STREAMER_NODE_SRC_TYPE_HTTP:
718 plugin_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
719 node->gst_element = ms_element_create(plugin_name, NULL);
721 case MEDIA_STREAMER_NODE_SRC_TYPE_CAMERA:
722 plugin_name = ms_ini_get_string("node type 1:camera", DEFAULT_CAMERA_SOURCE);
723 node->gst_element = ms_element_create(plugin_name, NULL);
725 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_CAPTURE:
726 plugin_name = ms_ini_get_string("node type 1:audio capture", DEFAULT_AUDIO_SOURCE);
727 node->gst_element = ms_element_create(plugin_name, NULL);
729 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_CAPTURE:
730 plugin_name = ms_ini_get_string("node type 1:video capture", DEFAULT_VIDEO_SOURCE);
731 node->gst_element = ms_element_create(plugin_name, NULL);
733 case MEDIA_STREAMER_NODE_SRC_TYPE_VIDEO_TEST:
734 plugin_name = ms_ini_get_string("node type 1:video test", DEFAULT_VIDEO_TEST_SOURCE);
735 node->gst_element = ms_element_create(plugin_name, NULL);
737 case MEDIA_STREAMER_NODE_SRC_TYPE_AUDIO_TEST:
738 plugin_name = ms_ini_get_string("node type 1:audio test", DEFAULT_AUDIO_TEST_SOURCE);
739 node->gst_element = ms_element_create(plugin_name, NULL);
741 case MEDIA_STREAMER_NODE_SRC_TYPE_CUSTOM:
742 plugin_name = ms_ini_get_string("node type 1:custom", DEFAULT_APP_SOURCE);
743 node->gst_element = ms_element_create(DEFAULT_APP_SOURCE, NULL);
744 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
745 ms_signal_create(&node->sig_list, node->gst_element, "need-data", G_CALLBACK(__ms_src_start_feed_cb), node);
746 ms_signal_create(&node->sig_list, node->gst_element, "enough-data", G_CALLBACK(__ms_src_stop_feed_cb), node);
748 case MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE:
749 node->gst_element = ms_adaptive_element_create();
752 ms_error("Error: invalid Src node Type [%d]", node->subtype);
756 MS_SAFE_FREE(plugin_name);
758 if (node->gst_element == NULL)
759 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
761 node->name = gst_element_get_name(node->gst_element);
763 ret = ms_node_dpm_policy_init(node);
764 if (MEDIA_STREAMER_ERROR_NONE != ret) {
765 ms_error("Failed to init DPM policy for node [%s]", node->name);
774 /* The appsink has received a buffer */
775 static void __ms_sink_new_buffer_cb(GstElement *sink, gpointer *data)
777 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
778 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
779 media_streamer_sink_data_ready_cb data_ready_cb = NULL;
783 ms_retm_if(ms_sink == NULL, "data is NULL");
785 if (ms_sink->callbacks_structure != NULL) {
786 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
787 data_ready_cb = (media_streamer_sink_data_ready_cb) sink_callbacks->data_ready_cb.callback;
790 data_ready_cb((media_streamer_node_h) ms_sink, sink_callbacks->data_ready_cb.user_data);
797 /* The appsink has got eos */
798 static void sink_eos(GstElement *sink, gpointer *data)
800 media_streamer_node_s *ms_sink = (media_streamer_node_s *) data;
801 media_streamer_sink_callbacks_s *sink_callbacks = NULL;
802 media_streamer_sink_eos_cb eos_cb = NULL;
806 ms_retm_if(ms_sink == NULL, "data is NULL");
808 if (ms_sink->callbacks_structure != NULL) {
809 sink_callbacks = (media_streamer_sink_callbacks_s *) ms_sink->callbacks_structure;
810 eos_cb = (media_streamer_sink_eos_cb) sink_callbacks->eos_cb.callback;
813 eos_cb((media_streamer_node_h) ms_sink, sink_callbacks->eos_cb.user_data);
820 int ms_sink_node_create(media_streamer_node_s *node)
822 int ret = MEDIA_STREAMER_ERROR_NONE;
823 char *plugin_name = NULL;
827 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
829 ret = __ms_node_check_privileges(node);
830 if (ret != MEDIA_STREAMER_ERROR_NONE) {
831 ms_error("Error getting privileges for Sink Node");
835 ret = __ms_sink_node_check_feature(node);
836 if (ret != MEDIA_STREAMER_ERROR_NONE) {
837 ms_error("Error getting feature for Sink Node");
841 switch (node->subtype) {
842 case MEDIA_STREAMER_NODE_SINK_TYPE_FILE:
843 plugin_name = ms_ini_get_string("node type 2:file", DEFAULT_FILE_SINK);
844 node->gst_element = ms_element_create(plugin_name, NULL);
846 case MEDIA_STREAMER_NODE_SINK_TYPE_RTSP:
847 plugin_name = ms_ini_get_string("node type 2:rtsp", DEFAULT_UDP_SINK);
848 node->gst_element = ms_element_create(plugin_name, NULL);
850 case MEDIA_STREAMER_NODE_SINK_TYPE_HTTP:
851 ms_error("Error: not implemented yet");
853 case MEDIA_STREAMER_NODE_SINK_TYPE_AUDIO:
854 plugin_name = ms_ini_get_string("node type 2:audio", DEFAULT_AUDIO_SINK);
855 node->gst_element = ms_element_create(plugin_name, NULL);
857 case MEDIA_STREAMER_NODE_SINK_TYPE_OVERLAY:
858 plugin_name = ms_ini_get_string("node type 2:overlay", DEFAULT_VIDEO_SINK);
859 node->gst_element = ms_element_create(plugin_name, NULL);
861 case MEDIA_STREAMER_NODE_SINK_TYPE_FAKE:
862 plugin_name = ms_ini_get_string("node type 2:fake", DEFAULT_FAKE_SINK);
863 node->gst_element = ms_element_create(plugin_name, NULL);
865 case MEDIA_STREAMER_NODE_SINK_TYPE_CUSTOM:
866 plugin_name = ms_ini_get_string("node type 2:custom", DEFAULT_APP_SINK);
867 node->gst_element = ms_element_create(plugin_name, NULL);
868 if (node->gst_element) {
869 g_object_set(G_OBJECT(node->gst_element), "emit-signals", TRUE, NULL);
870 ms_signal_create(&node->sig_list, node->gst_element, "new-sample", G_CALLBACK(__ms_sink_new_buffer_cb), node);
871 ms_signal_create(&node->sig_list, node->gst_element, "eos", G_CALLBACK(sink_eos), node);
874 case MEDIA_STREAMER_NODE_SINK_TYPE_ADAPTIVE:
875 plugin_name = ms_ini_get_string("node type 2:adaptive", DEFAULT_ADAPTIVE_SINK);
876 node->gst_element = ms_element_create(plugin_name, "adaptive_sink");
878 if (g_strrstr(plugin_name, "hlssink")) {
879 g_object_set(G_OBJECT(node->gst_element),
881 "playlist-length", 0, NULL);
885 ms_error("Error: invalid Sink node Type [%d]", node->subtype);
889 MS_SAFE_FREE(plugin_name);
891 if (node->gst_element == NULL)
892 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
894 node->name = gst_element_get_name(node->gst_element);
901 void ms_node_destroy(media_streamer_node_s *node)
903 gchar *node_name = NULL;
907 ms_retm_if(node == NULL, "node is NULL");
908 node_name = g_strdup(node->name);
910 /* Disconnects and clean all node signals */
911 g_list_free_full(node->sig_list, ms_signal_destroy);
913 /* Deinitialize policy manager */
914 if (MEDIA_STREAMER_ERROR_NONE != ms_node_dpm_policy_deinit(node))
915 ms_error("Failed to deinitialize DPM policy");
917 MS_SAFE_UNREF(node->gst_element);
918 MS_SAFE_FREE(node->name);
919 MS_SAFE_FREE(node->callbacks_structure);
922 ms_info("Node [%s] has been destroyed", node_name);
923 MS_SAFE_GFREE(node_name);
928 int ms_add_node_into_bin(media_streamer_s *ms_streamer, media_streamer_node_s *node)
930 int ret = MEDIA_STREAMER_ERROR_NONE;
931 GstElement *bin = NULL;
935 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Handle is NULL");
936 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "node is NULL");
938 ms_info("Try to add [%s] node into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
940 switch (node->type) {
941 case MEDIA_STREAMER_NODE_TYPE_SRC:
942 bin = ms_streamer->src_bin;
944 case MEDIA_STREAMER_NODE_TYPE_SINK:
945 bin = ms_streamer->sink_bin;
948 /* Another elements will be add into transform bin */
949 bin = ms_streamer->transform_bin;
953 if (!ms_bin_add_element(bin, node->gst_element, TRUE)) {
954 ms_error("Failed to add Element [%s] into [%s] bin.", node->name, GST_ELEMENT_NAME(bin));
955 ret = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
963 int ms_node_insert_into_table(GHashTable *nodes_table, media_streamer_node_s *node)
967 ms_retvm_if(nodes_table == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "nodes_table is NULL");
968 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
969 ms_retvm_if(node->name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->name is NULL");
971 if (g_hash_table_contains(nodes_table, node->name)) {
972 ms_debug("Current Node [%s] already added into Media Streamer", node->name);
973 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
975 if (!g_hash_table_insert(nodes_table, (gpointer) node->name, (gpointer) node)) {
976 ms_debug("Error: Failed to add node [%s] into Media Streamer", node->name);
977 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
980 ms_info("Node [%s] added into streamer, node type/subtype [%d/%d]", node->name, node->type, node->subtype);
984 return MEDIA_STREAMER_ERROR_NONE;
987 void ms_node_remove_from_table(void *data)
989 media_streamer_node_s *node = (media_streamer_node_s *) data;
993 ms_retm_if(node == NULL, "data is NULL");
995 if (ms_element_unlink(node->gst_element)) {
996 node->linked_by_user = FALSE;
997 node->parent_streamer = NULL;
998 ms_bin_remove_element(node->gst_element);
999 ms_info("Node [%s] removed from Media Streamer", node->name);
1001 ms_error("Error: Node [%s] remove failed", node->name);
1008 static gboolean __ms_src_need_typefind(GstPad *src_pad)
1010 gboolean ret = FALSE;
1014 if (!src_pad || gst_pad_is_linked(src_pad))
1017 GstCaps *src_caps = gst_pad_query_caps(src_pad, NULL);
1018 if (gst_caps_is_any(src_caps))
1021 gst_caps_unref(src_caps);
1028 node_info_s * ms_node_get_klass_by_its_type(media_streamer_node_type_e element_type)
1034 for (it_klass = 0; nodes_info[it_klass].klass_name != NULL; it_klass++) {
1035 if (it_klass == element_type) {
1036 ms_info("Next node`s type klass is [%s]", nodes_info[it_klass].klass_name);
1043 return &nodes_info[it_klass];
1046 gboolean ms_sink_node_prepare_iter(const GValue *item, GValue *g_ret, gpointer user_data)
1048 gboolean ret = FALSE;
1050 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1051 ms_retvm_if(g_ret == NULL, FALSE, "ret is NULL");
1055 ret = ms_element_lock_state(item, g_ret, user_data);
1062 gboolean ms_src_node_prepare_iter(const GValue *item, GValue *ret, gpointer user_data)
1064 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1065 GstElement *src_element = NULL;
1066 GstElement *found_element = NULL;
1067 media_streamer_node_s *node = NULL;
1068 GstPad *src_pad = NULL;
1072 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1073 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1074 ms_retvm_if(ms_streamer == NULL, FALSE, "user_data is NULL");
1076 src_element = GST_ELEMENT(g_value_get_object(item));
1077 g_object_ref(src_element);
1078 g_value_set_boolean(ret, FALSE);
1080 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1081 GST_ELEMENT_NAME(src_element));
1083 /* If we fail to find corresponding node inside streamer
1084 then apparently this element doesn't require resources. */
1085 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(src_element));
1086 g_value_set_boolean(ret, TRUE);
1087 g_object_unref(src_element);
1091 ms_debug("Autoplug: found src element [%s]", GST_ELEMENT_NAME(src_element));
1093 src_pad = gst_element_get_static_pad(src_element, "src");
1095 if (__ms_src_need_typefind(src_pad)) {
1096 ms_find_type(ms_streamer, src_element);
1097 MS_SAFE_UNREF(src_element);
1099 /* Check the source element`s pad type */
1100 const gchar *new_pad_type = ms_get_pad_type(src_pad);
1101 /* If SRC Element linked by user, don`t consider the following nodes` managing */
1102 if (gst_pad_is_linked(src_pad)) {
1103 MS_SAFE_UNREF(src_pad);
1104 MS_SAFE_UNREF(src_element);
1105 g_value_set_boolean(ret, TRUE);
1108 /* It is media streamer Server part */
1109 if (MS_ELEMENT_IS_VIDEO(new_pad_type) || MS_ELEMENT_IS_IMAGE(new_pad_type)) {
1110 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_FILTER);
1111 GstCaps *videoCaps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT);
1112 g_object_set(G_OBJECT(found_element), "caps", videoCaps, NULL);
1113 gst_caps_unref(videoCaps);
1115 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_ENCODER);
1116 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_VIDEO_PAY);
1117 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1119 if (MS_ELEMENT_IS_AUDIO(new_pad_type)) {
1120 found_element = ms_combine_next_element(src_element, src_pad, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_ENCODER);
1121 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_AUDIO_PAY);
1122 found_element = ms_combine_next_element(found_element, NULL, ms_streamer->transform_bin, MEDIA_STREAMER_NODE_TYPE_RTP);
1124 ms_generate_dots(ms_streamer->pipeline, "after_connecting_rtp");
1125 MS_SAFE_UNREF(found_element);
1127 MS_SAFE_UNREF(src_pad);
1129 g_value_set_boolean(ret, TRUE);
1136 static GstElement *__ms_manifest_src_create(media_streamer_node_s *node)
1138 char *manifest_src_name = NULL;
1139 gchar *location = NULL;
1140 GstElement *manifest_src = NULL;
1142 const char *uri = NULL;
1143 gchar *protocol = NULL;
1147 ms_retvm_if(!node, NULL, "node is NULL");
1149 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_URI);
1150 uri = g_value_get_string(val);
1151 protocol = gst_uri_is_valid(uri) ? gst_uri_get_protocol(uri) : NULL;
1153 if (protocol && g_strrstr(protocol, "http")) {
1154 manifest_src_name = ms_ini_get_string("node type 1:http", DEFAULT_HTTP_SOURCE);
1155 location = g_strdup(uri);
1156 } else if (protocol && g_strrstr(protocol, "file")) {
1157 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1158 location = gst_uri_get_location(uri);
1160 ms_error("Unsupported URI protocol... Check URI is file path");
1161 if (ms_util_uri_path_check(uri) == MEDIA_STREAMER_ERROR_NONE) {
1162 manifest_src_name = ms_ini_get_string("node type 1:file", DEFAULT_FILE_SOURCE);
1163 location = g_strdup(uri);
1166 ms_error("URI is not valid file path");
1172 if (manifest_src_name == NULL) {
1173 LOGE("Error empty manifest source name for adaptive source");
1178 manifest_src = gst_element_factory_make(manifest_src_name, NULL);
1179 g_free(manifest_src_name);
1181 if (manifest_src == NULL) {
1182 LOGE("Error creating manifest source for adaptive source");
1187 g_object_set(manifest_src, "location", location, NULL);
1192 return manifest_src;
1195 int ms_adaptive_src_node_prepare(media_streamer_node_s *node, bool auto_plug)
1197 char *plugin_name = NULL;
1198 GstElement *manifest_src = NULL;
1199 GstElement *plugin_elem = NULL;
1200 gboolean res = FALSE;
1205 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1208 plugin_name = ms_ini_get_string("node type 1:adaptive", DEFAULT_ADAPTIVE_SOURCE);
1209 ms_retvm_if(plugin_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Error empty plugin name for adaptive source");
1210 ms_info("Creating [%s] element", plugin_name);
1211 plugin_elem = gst_element_factory_make(plugin_name, NULL);
1212 g_free(plugin_name);
1213 ms_retvm_if(plugin_elem == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1214 "Error creating element for adaptive source");
1216 res = gst_bin_add(GST_BIN(node->gst_element), plugin_elem);
1217 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1218 "Error adding adaptive element to bin for adaptive source");
1221 manifest_src = __ms_manifest_src_create(node);
1222 ms_retvm_if(manifest_src == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1223 "Error creating manifest source for adaptive source");
1225 res = gst_bin_add(GST_BIN(node->gst_element), manifest_src);
1226 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1227 "Error adding manifest source to bin for adaptive source");
1230 res = gst_element_link(manifest_src, plugin_elem);
1231 ms_retvm_if(res == FALSE, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1232 "Error linking manifest source and element for adaptive source");
1235 gp = gst_element_get_static_pad(node->gst_element, "src");
1236 ms_retvm_if(gp == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER,
1237 "Error getting source pad for adaptive source");
1240 g_signal_connect_object(plugin_elem, "pad-added",
1241 G_CALLBACK(ms_hlsdemux_pad_added_cb), gp, 0);
1243 GstPad *manifest_src_pad = gst_element_get_static_pad(manifest_src, "src");
1244 gst_ghost_pad_set_target(GST_GHOST_PAD(gp), manifest_src_pad);
1249 return MEDIA_STREAMER_ERROR_NONE;
1252 int ms_adaptive_sink_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1254 int err_code = MEDIA_STREAMER_ERROR_NONE;
1255 gchar *playlist_location = NULL;
1256 char *playlist_dir = NULL;
1261 ms_retvm_if(ms_streamer == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1262 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1263 ms_retvm_if(node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node->gst_element is NULL");
1265 /* Create and start http server */
1266 err_code = ms_http_server_create(&ms_streamer->http_server);
1267 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1268 ms_error("Failed to create http server during prepare");
1272 ms_info("Starting http server");
1273 /* FIXME: find out how to set default port */
1274 err_code = ms_http_server_start(ms_streamer->http_server, DEFAULT_HTTP_PORT);
1275 if (MEDIA_STREAMER_ERROR_NONE != err_code) {
1276 ms_error("Failed to start http server during prepare. Destroying http server");
1277 ms_http_server_destroy(ms_streamer->http_server);
1281 g_object_get(node->gst_element, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION, &playlist_location, NULL);
1282 if (!playlist_location) {
1283 err_code = MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1284 ms_error("Failed to get playlist location");
1285 ms_http_server_destroy(ms_streamer->http_server);
1289 split = strrchr(playlist_location, '/');
1290 playlist_dir = g_strndup(playlist_location, split - playlist_location + 1);
1292 ms_http_server_register_uri(ms_streamer->http_server, "adaptive_path", playlist_dir);
1294 MS_SAFE_GFREE(playlist_location);
1304 int ms_rtp_node_prepare(media_streamer_node_s *node)
1306 GstElement *rtpbin = NULL;
1307 GstElement *rtp_el = NULL;
1308 GstElement *rtcp_el = NULL;
1310 const char *host = NULL;
1311 GstElement *video_filter = NULL;
1312 GstCaps *video_caps = NULL;
1313 GstGhostPad *ghost_pad = NULL;
1314 GstElement *audio_filter = NULL;
1315 GstCaps *audio_caps = NULL;
1319 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1321 rtpbin = ms_element_create("rtpbin", "rtpbin");
1322 ms_retvm_if(!rtpbin, FALSE, "Error: creating elements for rtp container");
1324 if (!ms_bin_add_element(node->gst_element, rtpbin, FALSE)) {
1325 MS_SAFE_UNREF(rtpbin);
1326 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1329 ms_signal_create(&node->sig_list, rtpbin, "pad-added", G_CALLBACK(ms_rtpbin_pad_added_cb), node);
1331 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_HOST);
1332 host = g_value_get_string(val);
1334 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_PORT);
1335 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1336 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rtp");
1337 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1339 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_VIDEO_IN"_rctp");
1340 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1342 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_0") ||
1343 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_0")) {
1344 ms_error("Failed to link pads for rtpbin sink pad 0");
1345 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1348 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1349 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1351 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT);
1352 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1355 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_PORT);
1356 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1357 rtp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rtp");
1358 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1360 rtcp_el = ms_element_create("udpsrc", MS_RTP_PAD_AUDIO_IN"_rctp");
1361 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1363 if (!gst_element_link_pads(rtp_el, "src", rtpbin, "recv_rtp_sink_1") ||
1364 !gst_element_link_pads(rtcp_el, "src", rtpbin, "recv_rtcp_sink_1")) {
1365 ms_error("Failed to link pads for rtpbin sink pad 1");
1366 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1369 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1370 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1372 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT);
1373 g_object_set_property(G_OBJECT(rtp_el), "caps", val);
1376 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT);
1377 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1378 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rtp");
1379 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1381 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_VIDEO_OUT"_rctp");
1382 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1384 video_filter = ms_element_create("capsfilter", NULL);
1385 ms_bin_add_element(node->gst_element, video_filter, FALSE);
1387 video_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_VIDEO_RTP_FORMAT);
1388 g_object_set(G_OBJECT(video_filter), "caps", video_caps, NULL);
1389 gst_caps_unref(video_caps);
1391 gst_element_link_pads(video_filter, "src", rtpbin, "send_rtp_sink_0");
1393 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_VIDEO_IN);
1395 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(video_filter, "sink")))
1396 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_VIDEO_IN);
1399 if (!gst_element_link_pads(rtpbin, "send_rtp_src_0", rtp_el, "sink") ||
1400 !gst_element_link_pads(rtpbin, "send_rtcp_src_0", rtcp_el, "sink")) {
1401 ms_error("Failed to link pads for rtpbin src pad 0");
1402 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1405 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1406 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1407 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1408 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1409 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1410 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1413 val = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT);
1414 if (g_value_get_int(val) > RTP_STREAM_DISABLED) {
1415 rtp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rtp");
1416 ms_bin_add_element(node->gst_element, rtp_el, FALSE);
1418 rtcp_el = ms_element_create("udpsink", MS_RTP_PAD_AUDIO_OUT"_rctp");
1419 ms_bin_add_element(node->gst_element, rtcp_el, FALSE);
1421 audio_filter = ms_element_create("capsfilter", NULL);
1422 ms_bin_add_element(node->gst_element, audio_filter, FALSE);
1424 audio_caps = gst_caps_from_string(MEDIA_STREAMER_DEFAULT_AUDIO_RTP_FORMAT);
1425 g_object_set(G_OBJECT(audio_filter), "caps", audio_caps, NULL);
1427 gst_element_link_pads(audio_filter, "src", rtpbin, "send_rtp_sink_1");
1429 ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, MS_RTP_PAD_AUDIO_IN);
1431 if (gst_ghost_pad_set_target(ghost_pad, gst_element_get_static_pad(audio_filter, "sink")))
1432 ms_info(" Capsfilter for [%s] in RTP is set and linked", MS_RTP_PAD_AUDIO_IN);
1435 if (!gst_element_link_pads(rtpbin, "send_rtp_src_1", rtp_el, "sink") ||
1436 !gst_element_link_pads(rtpbin, "send_rtcp_src_1", rtcp_el, "sink")) {
1437 ms_error("Failed to link pads for rtpbin src pad 1");
1438 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1441 g_object_set_property(G_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_PORT, val);
1442 g_object_set(GST_OBJECT(rtp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1443 g_object_set(G_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_PORT, (g_value_get_int(val) + 1), NULL);
1444 g_object_set(GST_OBJECT(rtcp_el), "sync", FALSE, NULL);
1445 g_object_set(GST_OBJECT(rtcp_el), "async", FALSE, NULL);
1446 g_object_set(GST_OBJECT(rtcp_el), MEDIA_STREAMER_PARAM_HOST, host, NULL);
1449 ms_generate_dots(node->gst_element, "rtp_prepared");
1453 return MEDIA_STREAMER_ERROR_NONE;
1456 int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1458 GstElement *webrtcbin = NULL;
1459 node_info_s *node_klass_type = NULL;
1460 GObject *send_channel = NULL;
1461 gboolean is_offerer = FALSE;
1462 media_streamer_webrtc_callbacks_s *_callbacks = NULL;
1466 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1467 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1468 ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is not WebRTC");
1470 node_klass_type = ms_node_get_klass_by_its_type(MEDIA_STREAMER_NODE_TYPE_WEBRTC);
1471 if (!(webrtcbin = ms_find_element_in_bin_by_type(node->gst_element, node_klass_type))) {
1472 ms_error("Could not find webrtcbin by type[%s, %s]", node_klass_type->klass_name, node_klass_type->default_name);
1473 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1476 _callbacks = (media_streamer_webrtc_callbacks_s *) node->callbacks_structure;
1477 if (!_callbacks || !(_callbacks->message_cb.callback)) {
1478 ms_error("message callback should be set before preparing");
1479 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1482 if (__ms_webrtc_node_is_offerer(node, &is_offerer)) {
1483 ms_error("Failed to get peer type");
1484 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1488 ms_signal_create(&node->sig_list, webrtcbin, "on-negotiation-needed", G_CALLBACK(ms_webrtcbin_on_negotiation_needed_cb), node);
1490 ms_signal_create(&node->sig_list, webrtcbin, "on-ice-candidate", G_CALLBACK(ms_webrtcbin_on_ice_candidate_cb), node);
1491 ms_signal_create(&node->sig_list, webrtcbin, "notify::ice-gathering-state", G_CALLBACK(ms_webrtcbin_notify_ice_gathering_state_cb), NULL);
1493 if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
1494 ms_error("Faild to set state to READY");
1495 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1498 g_signal_emit_by_name (webrtcbin, "create-data-channel", "channel", NULL, &send_channel);
1500 ms_info("data channel(%p) for sending is created", send_channel);
1502 ms_warning("Failed to create data channel");
1504 ms_signal_create(&node->sig_list, webrtcbin, "on-data-channel", G_CALLBACK(ms_webrtcbin_on_data_channel_cb), ms_streamer);
1505 ms_signal_create(&node->sig_list, webrtcbin, "pad-added", G_CALLBACK(ms_webrtcbin_pad_added_cb), node);
1507 ms_generate_dots(node->gst_element, "webrtc_prepared");
1511 return MEDIA_STREAMER_ERROR_NONE;
1516 int ms_demux_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
1520 ms_retvm_if(!ms_streamer, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "ms_streamer is NULL");
1521 ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1523 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "pad-added", G_CALLBACK(ms_demux_pad_added_cb), ms_streamer);
1524 ms_signal_create(&ms_streamer->autoplug_sig_list, node->gst_element, "no-more-pads", G_CALLBACK(ms_demux_nomore_pads_cb), ms_streamer);
1528 return MEDIA_STREAMER_ERROR_NONE;
1531 static int __ms_node_get_param_list(media_streamer_node_s *node, GList **param_list)
1533 GParamSpec *param_spec;
1538 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1539 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1541 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1542 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1543 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1544 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name)) {
1545 ms_info("Got parameter [%s] for node [%s]", param_table[it_param].param_name, node->name);
1546 *param_list = g_list_append(*param_list, &(param_table[it_param]));
1549 ms_retvm_if(!(*param_list), MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have any params.", node->name);
1553 return MEDIA_STREAMER_ERROR_NONE;
1556 static int __ms_node_set_display(media_streamer_node_s *node, const char *param_value)
1558 int ret = MEDIA_STREAMER_ERROR_NONE;
1559 Evas_Object *obj = NULL;
1560 media_streamer_wl_info_s wl_info;
1562 obj = (Evas_Object *)param_value;
1564 /* get wayland parent id */
1565 if (ms_get_wl_info(obj, &wl_info) != MEDIA_STREAMER_ERROR_NONE) {
1566 LOGE("failed to get wayland info");
1567 return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
1570 LOGD("wayland global surface id : %d", wl_info.parent_id);
1572 gst_video_overlay_set_wl_window_wl_surface_id(GST_VIDEO_OVERLAY(node->gst_element), wl_info.parent_id);
1577 int ms_node_set_param_value(media_streamer_node_s *node, param_s *param, const char *param_value)
1580 int ret = MEDIA_STREAMER_ERROR_NONE;
1584 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1585 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1586 ms_retvm_if(param_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
1588 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1589 ret = __ms_rtp_node_set_property(node, param, param_value);
1594 if (node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
1595 ret = __ms_webrtc_node_set_property(node, param, param_value);
1600 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1601 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE) {
1602 ret = __ms_adaptive_src_node_set_property(node, param, param_value);
1607 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID)) {
1608 int camera_id = (int)strtol(param_value, NULL, 10);
1609 ms_retvm_if(camera_id == -1, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid %s value", param->param_name);
1610 g_object_set(node->gst_element, param->origin_name, camera_id, NULL);
1611 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1612 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1613 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1614 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1615 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1616 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1617 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1618 g_object_set(node->gst_element, param->origin_name, (int)strtol(param_value, NULL, 10), NULL);
1619 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1620 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1621 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1622 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1623 g_object_set(node->gst_element, param->origin_name, !g_ascii_strcasecmp(param_value, "true"), NULL);
1624 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI)) {
1625 if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC && node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_FILE) {
1626 ret = ms_util_uri_path_check(param_value);
1627 if (ret != MEDIA_STREAMER_ERROR_NONE)
1630 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1631 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1632 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1633 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1634 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1635 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1636 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1637 g_object_set(node->gst_element, param->origin_name, param_value, NULL);
1638 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY)) {
1639 ret = __ms_node_set_display(node, param_value);
1641 ms_info("Can not set parameter [%s] in the node [%s]", param->param_name, node->name);
1642 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1650 int ms_node_set_params_from_bundle(media_streamer_node_s *node, bundle *param_list)
1652 int ret = MEDIA_STREAMER_ERROR_NONE;
1653 GList *p_list = NULL;
1654 int written_count = 0;
1655 param_s *param = NULL;
1656 GList *list_iter = NULL;
1657 char *string_val = NULL;
1661 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1662 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1664 ret = __ms_node_get_param_list(node, &p_list);
1665 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1666 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1667 param = (param_s *)list_iter->data;
1668 if (bundle_get_str(param_list, param->param_name, &string_val) != BUNDLE_ERROR_KEY_NOT_AVAILABLE) {
1669 ret = ms_node_set_param_value(node, param, string_val);
1670 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1673 ms_error("failed to set param");
1679 g_list_free(p_list);
1681 ms_info("Set [%d] parameters of [%d]", written_count, bundle_get_count(param_list));
1682 if (ret == MEDIA_STREAMER_ERROR_NONE && written_count == 0)
1683 ret = MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1690 int ms_node_write_params_into_bundle(media_streamer_node_s *node, bundle *param_list)
1692 int ret = MEDIA_STREAMER_ERROR_NONE;
1693 GList *p_list = NULL;
1694 param_s *param = NULL;
1695 GList *list_iter = NULL;
1696 char *string_val = NULL;
1700 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1701 ms_retvm_if(param_list == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_list is NULL");
1703 ret = __ms_node_get_param_list(node, &p_list);
1704 if (ret == MEDIA_STREAMER_ERROR_NONE) {
1705 for (list_iter = p_list; list_iter != NULL; list_iter = list_iter->next) {
1706 param = (param_s *)list_iter->data;
1708 if (ms_node_get_param_value(node, param, &string_val) == MEDIA_STREAMER_ERROR_NONE) {
1709 bundle_add_str(param_list, param->param_name, string_val);
1710 MS_SAFE_FREE(string_val);
1715 g_list_free(p_list);
1722 int ms_node_get_param(media_streamer_node_s *node, const char *param_name, param_s **param)
1724 GParamSpec *param_spec;
1725 gboolean found_param = FALSE;
1730 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1731 ms_retvm_if(param_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_name is NULL");
1732 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1734 for (it_param = 0; param_table[it_param].param_name != NULL; it_param++) {
1735 if (!g_strcmp0(param_name, param_table[it_param].param_name)) {
1736 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param_table[it_param].origin_name);
1737 if (param_spec || __ms_rtp_node_has_property(node, param_table[it_param].origin_name) ||
1738 __ms_adaptive_src_node_has_property(node, param_table[it_param].origin_name) ||
1739 __ms_webrtc_node_has_property(node, param_table[it_param].origin_name)) {
1740 *param = &(param_table[it_param]);
1741 ms_info("Got parameter [%s] for node [%s]", (*param)->param_name, node->name);
1747 ms_retvm_if(!found_param, MEDIA_STREAMER_ERROR_INVALID_OPERATION, "Node [%s] doesn't have param [%s].", node->name, param_name);
1751 return MEDIA_STREAMER_ERROR_NONE;
1754 int ms_node_get_param_value(media_streamer_node_s *node, param_s *param, char **string_value)
1756 int ret = MEDIA_STREAMER_ERROR_NONE;
1757 char *string_val = NULL;
1758 GParamSpec *param_spec = NULL;
1759 GValue value = G_VALUE_INIT;
1763 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1764 ms_retvm_if(param == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
1765 ms_retvm_if(string_value == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "string_value is NULL");
1767 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP)
1768 ret = __ms_rtp_node_get_property(node, param, &value);
1769 else if (node->type == MEDIA_STREAMER_NODE_TYPE_SRC &&
1770 node->subtype == MEDIA_STREAMER_NODE_SRC_TYPE_ADAPTIVE)
1771 ret = __ms_adaptive_src_node_get_property(node, param, &value);
1773 param_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(node->gst_element), param->origin_name);
1775 g_value_init(&value, param_spec->value_type);
1776 g_object_get_property(G_OBJECT(node->gst_element), param->origin_name, &value);
1778 ms_info("Got parameter [%s] for node [%s] with description [%s]", param->param_name, node->name, g_param_spec_get_blurb(param_spec));
1780 ms_error("There is no parameter [%s] for node [%s]", param->origin_name, node->name);
1781 return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
1785 if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAMERA_ID) ||
1786 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_WIDTH) ||
1787 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CAPTURE_HEIGHT) ||
1788 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PORT) ||
1789 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_IN_PORT) ||
1790 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_IN_PORT) ||
1791 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VIDEO_OUT_PORT) ||
1792 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_OUT_PORT)) {
1793 if (G_VALUE_HOLDS_INT(&value))
1794 string_val = g_strdup_printf("%d", g_value_get_int(&value));
1796 string_val = g_strdup_printf("%u", g_value_get_uint(&value));
1797 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IS_LIVE_STREAM) ||
1798 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_CLOCK_SYNCHRONIZED) ||
1799 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USE_TBM) ||
1800 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_VISIBLE)) {
1801 string_val = g_strdup(g_value_get_boolean(&value) ? "true" : "false");
1802 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_URI) ||
1803 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_USER_AGENT) ||
1804 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_IP_ADDRESS) ||
1805 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_AUDIO_DEVICE) ||
1806 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_HOST) ||
1807 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_SEGMENT_LOCATION) ||
1808 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_PLAYLIST_LOCATION)) {
1809 string_val = g_value_dup_string(&value);
1810 } else if (!g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_STREAM_TYPE) ||
1811 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_ROTATE) ||
1812 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_FLIP) ||
1813 !g_strcmp0(param->param_name, MEDIA_STREAMER_PARAM_DISPLAY_GEOMETRY_METHOD)) {
1814 string_val = g_strdup_printf("%d", g_value_get_enum(&value));
1817 *string_value = string_val;
1819 g_value_reset(&value);
1820 g_value_unset(&value);
1827 int ms_node_set_pad_format(media_streamer_node_s *node, const char *pad_name, media_format_h fmt)
1829 int ret = MEDIA_STREAMER_ERROR_NONE;
1833 ms_retvm_if(node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
1834 ms_retvm_if(pad_name == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "pad_name is NULL");
1835 ms_retvm_if(fmt == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "fmt is NULL");
1837 if (node->type == MEDIA_STREAMER_NODE_TYPE_RTP) {
1838 media_format_mimetype_e mime;
1839 gchar *rtp_caps_str = NULL;
1841 /* It is needed to set 'application/x-rtp' for audio and video udpsrc */
1842 if (g_strrstr(pad_name, MS_RTP_PAD_VIDEO_IN)) {
1843 ret = media_format_get_video_info(fmt, &mime, NULL, NULL, NULL, NULL);
1844 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1845 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));
1846 param_s param = {MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT, MEDIA_STREAMER_PARAM_VIDEO_IN_FORMAT};
1847 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
1849 } else if (g_strrstr(pad_name, MS_RTP_PAD_AUDIO_IN)) {
1850 int audio_channels, audio_samplerate;
1851 ret = media_format_get_audio_info(fmt, &mime, &audio_channels, &audio_samplerate, NULL, NULL);
1852 if (MEDIA_FORMAT_ERROR_NONE == ret) {
1853 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");
1854 param_s param = {MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT, MEDIA_STREAMER_PARAM_AUDIO_IN_FORMAT};
1855 ret = ms_node_set_param_value(node, ¶m, rtp_caps_str);
1859 MS_SAFE_GFREE(rtp_caps_str);
1861 ret = ms_element_set_fmt(node->gst_element, pad_name, fmt);
1869 gboolean ms_node_resources_acquire_iter(const GValue *item, GValue *ret, gpointer user_data)
1871 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1872 media_streamer_node_s *node = NULL;
1873 GstElement *element = NULL;
1877 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1878 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1879 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1881 g_value_set_boolean(ret, FALSE);
1883 element = GST_ELEMENT(g_value_get_object(item));
1884 g_object_ref(element);
1886 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1887 GST_ELEMENT_NAME(element));
1889 /* If we fail to find corresponding node inside streamer
1890 then apparently this element doesn't require resources. */
1891 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1892 g_value_set_boolean(ret, TRUE);
1893 g_object_unref(element);
1897 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_acquire(node)) {
1898 ms_error("Failed to acquire resource for node [%s]", node->name);
1899 g_object_unref(element);
1903 g_value_set_boolean(ret, TRUE);
1905 g_object_unref(element);
1912 gboolean ms_node_resources_release_iter(const GValue *item, GValue *ret, gpointer user_data)
1914 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1915 media_streamer_node_s *node = NULL;
1916 GstElement *element = NULL;
1920 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1921 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1922 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1924 g_value_set_boolean(ret, FALSE);
1926 element = GST_ELEMENT(g_value_get_object(item));
1927 g_object_ref(element);
1929 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1930 GST_ELEMENT_NAME(element));
1932 /* If we fail to find corresponding node inside streamer
1933 then apparently this element doesn't require resources. */
1934 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1935 g_value_set_boolean(ret, TRUE);
1936 g_object_unref(element);
1940 if (MEDIA_STREAMER_ERROR_NONE != ms_node_resource_release(node)) {
1941 ms_error("Failed to release resource for node [%s]", node->name);
1942 g_object_unref(element);
1946 g_value_set_boolean(ret, TRUE);
1948 g_object_unref(element);
1955 gboolean ms_node_dpm_policy_check_iter(const GValue *item, GValue *ret, gpointer user_data)
1957 media_streamer_s *ms_streamer = (media_streamer_s *) user_data;
1958 media_streamer_node_s *node = NULL;
1959 GstElement *element = NULL;
1960 gboolean allowed = FALSE;
1964 ms_retvm_if(item == NULL, FALSE, "item is NULL");
1965 ms_retvm_if(ms_streamer == NULL, FALSE, "ms_streamer is NULL");
1966 ms_retvm_if(ms_streamer->nodes_table == NULL, FALSE, "ms_streamer->nodes_table is NULL");
1967 ms_retvm_if(ret == NULL, FALSE, "ret is NULL");
1969 element = GST_ELEMENT(g_value_get_object(item));
1970 g_object_ref(element);
1972 node = (media_streamer_node_s *) g_hash_table_lookup(ms_streamer->nodes_table,
1973 GST_ELEMENT_NAME(element));
1975 /* If we fail to find corresponding node inside streamer
1976 then apparently this element doesn't require resources. */
1977 ms_debug("Could not find corresponding node [%s] inside streamer, skip it", GST_ELEMENT_NAME(element));
1978 g_value_set_boolean(ret, TRUE);
1979 g_object_unref(element);
1983 if (ms_node_dpm_policy_check(node, &allowed)) {
1984 ms_error("Failed to check DPM policy for node [%s]", node->name);
1985 /* Note that it should be TRUE(allowed) if the DPM API failed. */
1986 g_value_set_boolean(ret, TRUE);
1987 g_object_unref(element);
1991 g_value_set_boolean(ret, allowed);
1993 g_object_unref(element);