#define MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE "webrtc-add-ice-candidate"
/**
+ * @brief Definition for WebRTC RTP transceiver direction for audio.
+ * @details WebRTC Transceiver direction to send audio RTP.\n
+ * It can be "sendrecv" or "sendonly" or "recvonly" or "inactive".
+ * @since_tizen 6.0
+ * @remarks "sendrecv": local peer will offer to send RTP, and send RTP if remote peer accepts,
+ * and will offer receive RTP, and will receive RTP if remote peer accepts.\n
+ * "sendonly": local peer will offer to send RTP and will not suggest to receive RTP,
+ * and will not offer to send RTP and will not receive RTP if remote peer accepts.\n
+ * "recvonly": local peer will not offer to send RTP, and will not send RTP,
+ * and will offer to receive RTP, and will receive RTP if remote peer accepts.\n
+ * "inactive": local peer will not offer to send RTP, and will not send RTP,
+ * and will not offer to receive RTP, and will not receive RTP.
+ * @see media_streamer_node_get_params()
+ */
+#define MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO "webrtc-rtp-transceiver-direction-for-audio"
+
+/**
+ * @brief Definition for WebRTC RTP transceiver direction for video.
+ * @details WebRTC Transceiver direction to send video RTP.\n
+ * It can be "sendrecv" or "sendonly" or "recvonly" or "inactive".
+ * @since_tizen 6.0
+ * @remarks "sendrecv": local peer will offer to send RTP, and send RTP if remote peer accepts,
+ * and will offer receive RTP, and will receive RTP if remote peer accepts.\n
+ * "sendonly": local peer will offer to send RTP and will not suggest to receive RTP,
+ * and will not offer to send RTP and will not receive RTP if remote peer accepts.\n
+ * "recvonly": local peer will not offer to send RTP, and will not send RTP,
+ * and will offer to receive RTP, and will receive RTP if remote peer accepts.\n
+ * "inactive": local peer will not offer to send RTP, and will not send RTP,
+ * and will not offer to receive RTP, and will not receive RTP.
+ * @see media_streamer_node_get_params()
+ */
+#define MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO "webrtc-rtp-transceiver-direction-for-video"
+
+/**
* @brief Definition for audio device name parameter of source or sink node.
* @details ALSA device, as defined in an asound configuration file.\n
* ex) "hw:0,0", "hw:0,1"\n
int ms_webrtcbin_set_stun_server(media_streamer_node_s *webrtc_node, const char *stun_server_url);
+void ms_webrtc_set_rtp_transceiver_direction_with_index(GstElement *webrtcbin, gint transceiver_idx, GstWebRTCRTPTransceiverDirection direction);
+
+void ms_webrtc_set_rtp_transceiver_direction_with_caps(GstElement *webrtcbin, const gchar *caps_str, GstWebRTCRTPTransceiverDirection direction);
+
+gboolean ms_webrtc_is_valid_transceiver_direction(gboolean is_linked, GstWebRTCRTPTransceiverDirection direction);
+
+int ms_webrtc_node_get_rtp_transceiver_direction(media_streamer_node_s *webrtc_node, const gchar *param_name, GstWebRTCRTPTransceiverDirection *direction);
+
#ifdef __cplusplus
}
#endif
#define __TIZEN_MEDIA_STREAMER_NODE_H__
#include "media_streamer_priv.h"
-
#ifdef __cplusplus
extern "C" {
#endif
void ms_node_remove_from_table_cb(void *data);
GstElement *ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node);
int ms_webrtc_node_is_offerer(media_streamer_node_s *node, gboolean *is_offerer);
-
+int ms_webrtc_node_check_link_condition(media_streamer_node_s *node, const char *sink_pad_name);
#ifdef __cplusplus
}
#endif
PROP_NAME_WEBRTC_STUN_SERVER,
PROP_NAME_WEBRTC_REMOTE_SESSION_DESCRIPTION,
PROP_NAME_WEBRTC_ADD_ICE_CANDIDATE,
+ PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO,
+ PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO,
PROP_NAME_AUDIO_DEVICE,
PROP_NAME_SYNC,
PROP_NAME_ROTATE,
#define WEBRTC_PEER_OFFER "offer"
#define DEFAULT_WEBRTC_PEER WEBRTC_PEER_ANSWER
#define DEFAULT_WEBRTC_STUN_SERVER "stun://stun.l.google.com:19302"
+#define WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV "sendrecv"
+#define WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY "sendonly"
+#define WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY "recvonly"
+#define WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE "inactive"
+#define WEBRTC_RTP_TRANSCEIVER_DIRECTION_UNKNOWN "unknown"
+#define DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION WEBRTC_RTP_TRANSCEIVER_DIRECTION_UNKNOWN
+#define WEBRTC_DEFAULT_VIDEO_RTP_FORMAT "application/x-rtp,media=video,encoding-name=VP8,payload=96"
+#define WEBRTC_DEFAULT_AUDIO_RTP_FORMAT "application/x-rtp,media=audio,encoding-name=OPUS,payload=97"
#define MEDIA_STREAMER_DEFAULT_CAMERA_FORMAT "video/x-raw,format=I420,width=352,height=288"
#define MEDIA_STREAMER_DEFAULT_AUDIO_RAW_FORMAT "audio/x-raw,channels=1,rate=8000,format=S16LE"
#define MEDIA_STREAMER_DEFAULT_DOT_DIR "/tmp"
+
+#define MS_SET_BOOLEAN_PARAM(obj, key, value) \
+ do { \
+ GValue *val = g_malloc0(sizeof(GValue)); \
+ g_value_init(val, G_TYPE_BOOLEAN); \
+ g_value_set_boolean(val, value); \
+ g_object_set_data_full(G_OBJECT(obj), key, (gpointer)val, ms_param_value_destroy); \
+ } while (0)
+
#define MS_SET_INT_PARAM(obj, key, value) \
do { \
GValue *val = g_malloc0(sizeof(GValue)); \
Name: capi-media-streamer
Summary: A Media Streamer API
-Version: 0.1.109
+Version: 0.1.110
Release: 0
Group: Multimedia/API
License: Apache-2.0
ms_retvm_if(ms_src_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node1 is NULL");
ms_retvm_if(ms_dest_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node2 is NULL");
+ if (ms_dest_node->type == MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
+ if (ms_webrtc_node_check_link_condition(ms_dest_node, sink_pad_name) != MEDIA_STREAMER_ERROR_NONE) {
+ ms_error("Can not link [%s]:%s pad to [%s]:%s pad", ms_src_node->name, src_pad_name, ms_dest_node->name, sink_pad_name);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ }
+
link_ret = gst_element_link_pads(ms_src_node->gst_element, src_pad_name, ms_dest_node->gst_element, sink_pad_name);
if (!link_ret) {
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
#include "media_streamer_util.h"
#include "media_streamer_priv.h"
#include "media_streamer_gst.h"
ms_debug_fleave();
}
+void ms_webrtc_set_rtp_transceiver_direction_with_index(GstElement *webrtcbin, gint transceiver_idx, GstWebRTCRTPTransceiverDirection direction)
+{
+ GstWebRTCRTPTransceiver *trans = NULL;
+ GArray *transceivers = NULL;
+ ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
+
+ g_signal_emit_by_name (webrtcbin, "get-transceivers", &transceivers);
+ if (transceivers != NULL && transceivers->len > 0) {
+ trans = g_array_index (transceivers, GstWebRTCRTPTransceiver *, transceiver_idx);
+ trans->direction = direction;
+ g_array_unref (transceivers);
+ ms_info("Set transceiver direction(%d) to transceiver_%d", trans->direction, transceiver_idx);
+ } else {
+ ms_error("Could not set transceiver direction(%d) in transceiver_%d", direction, transceiver_idx);
+ }
+}
+
+void ms_webrtc_set_rtp_transceiver_direction_with_caps(GstElement *webrtcbin, const gchar *caps_str, GstWebRTCRTPTransceiverDirection direction)
+{
+ GstWebRTCRTPTransceiver *trans = NULL;
+ GstCaps *caps = NULL;
+
+ ms_retm_if(webrtcbin == NULL, "webrtcbin is NULL");
+ caps = gst_caps_from_string (caps_str);
+ g_signal_emit_by_name (webrtcbin, "add-transceiver", direction, caps, &trans);
+ gst_caps_unref (caps);
+ if (trans) {
+ ms_info("Set transceiver direction(%d) with caps(%s)", trans->direction, caps_str);
+ gst_object_unref (trans);
+ } else {
+ ms_error("Could not set transceivers direction(%d) with caps(%s)", direction, caps_str);
+ }
+}
+
+gboolean ms_webrtc_is_valid_transceiver_direction(gboolean is_linked, GstWebRTCRTPTransceiverDirection direction)
+{
+ if (is_linked) {
+ if ((direction != GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV) &&
+ (direction != GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY)) {
+ ms_error("To use recvonly or inactive, don't create and link input stream to WebRTC node");
+ return FALSE;
+ }
+ } else {
+ if ((direction != GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY) &&
+ (direction != GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE)) {
+ ms_error("To use sendonly or sendrecv, create and link input stream to WebRTC node");
+ return FALSE;
+ }
+ }
+
+ ms_debug("Checked transceiver direction[%d] validity with link status(%s)",direction, (is_linked)? "TRUE": "FALSE");
+
+ return TRUE;
+}
+
+int ms_webrtc_node_get_rtp_transceiver_direction(media_streamer_node_s *webrtc_node, const gchar *param_name, GstWebRTCRTPTransceiverDirection *direction)
+{
+ GValue *val = NULL;
+ const gchar *direction_str = NULL;
+
+ ms_retvm_if(!webrtc_node || !webrtc_node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_node is null");
+ ms_retvm_if(!direction, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "transceiver_direction is null");
+
+ if (strcmp(param_name, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO) &&
+ strcmp(param_name, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO)) {
+ ms_error("Invalid param name");
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+
+ if (webrtc_node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC) {
+ ms_error("Invalid node type");
+ return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
+ }
+
+ val = (GValue *)g_object_get_data(G_OBJECT(webrtc_node->gst_element), param_name);
+ if (!val) {
+ ms_error("Failed to get [%s] val from [%s]", param_name, GST_ELEMENT_NAME(webrtc_node->gst_element));
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (!(direction_str = g_value_get_string(val))) {
+ ms_error("Failed to g_value_get_string()");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (!strcmp(direction_str, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV))
+ *direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
+ else if (!strcmp(direction_str, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY))
+ *direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
+ else if (!strcmp(direction_str, WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY))
+ *direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
+ else if (!strcmp(direction_str, WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE))
+ *direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE;
+ else if (!strcmp(direction_str, WEBRTC_RTP_TRANSCEIVER_DIRECTION_UNKNOWN))
+ *direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE;
+ else
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
int ms_webrtcbin_set_remote_session_description(media_streamer_node_s *webrtc_node, const char *sdp_msg)
{
GstSDPMessage *gst_sdp;
MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_STUN_SERVER, DEFAULT_WEBRTC_STUN_SERVER);
MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_REMOTE_SESSION_DESCRIPTION, NULL);
MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_ADD_ICE_CANDIDATE, NULL);
+ MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO, DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION);
+ MS_SET_INT_STATIC_STRING_PARAM(webrtc_container, MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO, DEFAULT_WEBRTC_RTP_TRANSCEIVER_DIRECTION);
if (!(webrtcbin = ms_element_create("webrtcbin", NULL))) {
ms_error("Failed to create webrtcbin element");
PARAM_DATA_TYPE_STRING
},
{
+ MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO,
+ "webrtc-rtp-transceiver-direction-for-audio",
+ PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO,
+ PARAM_DATA_TYPE_STRING
+ },
+ {
+ MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO,
+ "webrtc-rtp-transceiver-direction-for-video",
+ PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO,
+ PARAM_DATA_TYPE_STRING
+ },
+ {
MEDIA_STREAMER_PARAM_AUDIO_DEVICE,
"audio_device",
PROP_NAME_AUDIO_DEVICE,
return ret;
}
+static int __ms_webrtc_node_check_transceiver_direction_param_value(media_streamer_node_s *node, param_s *param, const gchar *param_value)
+{
+ GstWebRTCRTPTransceiverDirection direction;
+ GstGhostPad *ghost_pad = NULL;
+ const gchar *pad_name;
+ gboolean is_linked = FALSE;
+
+ ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+ ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
+ ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Invalid node type");
+ ms_retvm_if(!param, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param is NULL");
+ ms_retvm_if(!param_value, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "param_value is NULL");
+
+ if (param->prop_enum == PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO)
+ pad_name = MS_PAD_AUDIO_IN;
+ else if (param->prop_enum == PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO)
+ pad_name = MS_PAD_VIDEO_IN;
+ else
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+
+ if (!(ghost_pad = (GstGhostPad *)gst_element_get_static_pad(node->gst_element, pad_name))) {
+ ms_error("Failed to get ghost pad for webrtc_container");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ is_linked = gst_pad_is_linked((GstPad *)ghost_pad);
+ MS_SAFE_UNREF(ghost_pad);
+
+ ms_debug("[%s] %s", pad_name, is_linked ? "is linked" : "isn't linked");
+
+ if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV)) {
+ direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV;
+ } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY)) {
+ direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDONLY;
+ } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY)) {
+ direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY;
+ } else if (!strcmp(param_value, WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE)) {
+ direction = GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE;
+ } else {
+ ms_error("failed to set property, param value should be sendrecv or sendonly or recvonly or inactive");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (!ms_webrtc_is_valid_transceiver_direction(is_linked, direction)) {
+ ms_error("%s is not valid transceiver direction", param_value);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+
static gboolean __ms_webrtc_node_has_property(media_streamer_node_s *node, const char *param_name)
{
GValue *val = NULL;
}
break;
+ case PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO:
+ case PROP_NAME_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO:
+ ret = __ms_webrtc_node_check_transceiver_direction_param_value(node, param, param_value);
+ if (ret != MEDIA_STREAMER_ERROR_NONE) {
+ ms_error("failed to set transceiver direction: %s", param_value);
+ return ret;
+ }
+
+ ret = __ms_param_value_set(val, param->data_type, param_value);
+ break;
+
default:
ms_error("failed to set property, undefined param name[%s]", param->param_name);
return MEDIA_STREAMER_ERROR_INVALID_PARAMETER;
return ret;
}
+int ms_webrtc_node_check_link_condition(media_streamer_node_s *node, const char *sink_pad_name)
+{
+ GValue *value = NULL;
+ const gchar *key = NULL;
+ const gchar *direction = NULL;
+
+ ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+ ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
+ ms_retvm_if(!sink_pad_name, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "sink_pad_name is NULL");
+ ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type is not webrtc");
+
+ if (!strcmp(sink_pad_name, MEDIA_STREAMER_NODE_PAD_AUDIO_SINK)) {
+ key = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO;
+ } else if (!strcmp(sink_pad_name, MEDIA_STREAMER_NODE_PAD_VIDEO_SINK)) {
+ key = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO;
+ } else {
+ ms_error("sink_pand_name[%s] is wrong", sink_pad_name);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), key);
+ if (!value) {
+ ms_error("failed to get [%s] val from [%s]", key, GST_ELEMENT_NAME(node->gst_element));
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (!(direction = g_value_get_string(value))) {
+ ms_error("Failed to g_value_get_string()");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if (!strcmp(direction, WEBRTC_RTP_TRANSCEIVER_DIRECTION_RECVONLY) &&
+ !strcmp(direction, WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE)) {
+ ms_error("Could not link to [%s] in %s", sink_pad_name, direction);
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ return MEDIA_STREAMER_ERROR_NONE;
+}
+static int __ms_webrtc_node_update_transceiver_direction_param_value(media_streamer_node_s *node, const gchar *param_name, const gchar *direction)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ GValue *value = NULL;
+
+ ms_retvm_if(!node, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "node is NULL");
+ ms_retvm_if(!node->gst_element, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "gst_element is NULL");
+ ms_retvm_if(node->type != MEDIA_STREAMER_NODE_TYPE_WEBRTC, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "Node type is not webrtc");
+ ms_retvm_if(!direction, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "direction is NULL");
+
+ ms_debug("direction is [%s]", direction);
+
+ value = (GValue *)g_object_get_data(G_OBJECT(node->gst_element), param_name);
+ if (!value) {
+ ms_error("failed to get [%s] val from [%s]", param_name, GST_ELEMENT_NAME(node->gst_element));
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ ret = __ms_param_value_set(value, PARAM_DATA_TYPE_STRING, direction);
+ if (ret != MEDIA_STREAMER_ERROR_NONE) {
+ return ret;
+ ms_info("update transceiver unknown -> sendrecv");
+ }
+
+ return ret;
+}
+
GstElement * ms_webrtc_node_get_webrtcbin(media_streamer_node_s *webrtc_node)
{
GstElement *webrtcbin = NULL;
return webrtcbin;
}
+static int __ms_webrtc_node_set_rtp_transceiver_direction(media_streamer_node_s *webrtc_node)
+{
+ int ret = MEDIA_STREAMER_ERROR_NONE;
+ GstElement *webrtcbin = NULL;
+ GstElement *video_filter = NULL;
+ GstElement *audio_filter = NULL;
+ gint transceiver_idx = 0;
+ gboolean is_linked_video = FALSE;
+ gboolean is_linked_audio = FALSE;
+ GstWebRTCRTPTransceiverDirection audio_direction;
+ GstWebRTCRTPTransceiverDirection video_direction;
+ const gchar *audio_param_name = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_AUDIO;
+ const gchar *video_param_name = MEDIA_STREAMER_PARAM_WEBRTC_RTP_TRANSCEIVER_DIRECTION_FOR_VIDEO;
+
+ ms_retvm_if(webrtc_node == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_node is NULL");
+ ms_retvm_if(webrtc_node->gst_element == NULL, MEDIA_STREAMER_ERROR_INVALID_PARAMETER, "webrtc_container is NULL");
+ ms_debug_fenter();
+
+ if (!(webrtcbin = ms_webrtc_node_get_webrtcbin(webrtc_node)))
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+
+ if (ms_webrtc_node_get_rtp_transceiver_direction(webrtc_node, audio_param_name, &audio_direction)) {
+ ms_error("Failed to get WebRTC audio RTP transceiver direction");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ if (ms_webrtc_node_get_rtp_transceiver_direction(webrtc_node, video_param_name, &video_direction)) {
+ ms_error("Failed to get WebRTC video RTP transceiver direction");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
+ if ((audio_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "audio_capsfilter")))
+ is_linked_audio = TRUE;
+
+ if ((video_filter = ms_find_element_in_bin_by_name(webrtc_node->gst_element, "video_capsfilter")))
+ is_linked_video = TRUE;
+
+ /* GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE indicates that transceiver direction was not set by user,
+ it will be changed to sendrecv. */
+ if (audio_direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE) {
+ if (is_linked_audio) {
+ if (__ms_webrtc_node_update_transceiver_direction_param_value(webrtc_node, audio_param_name, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV))
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ if (!ms_webrtc_is_valid_transceiver_direction(is_linked_audio, audio_direction))
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+
+ if (is_linked_audio)
+ ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx++, audio_direction);
+ else
+ ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_AUDIO_RTP_FORMAT, audio_direction);
+ }
+
+ if (video_direction == GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_NONE) {
+ if (is_linked_video) {
+ if (__ms_webrtc_node_update_transceiver_direction_param_value(webrtc_node, video_param_name, WEBRTC_RTP_TRANSCEIVER_DIRECTION_SENDRECV))
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+ } else {
+ if (!ms_webrtc_is_valid_transceiver_direction(is_linked_video, video_direction))
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+
+ if (is_linked_video)
+ ms_webrtc_set_rtp_transceiver_direction_with_index(webrtcbin, transceiver_idx, video_direction);
+ else
+ ms_webrtc_set_rtp_transceiver_direction_with_caps(webrtcbin, WEBRTC_DEFAULT_VIDEO_RTP_FORMAT, video_direction);
+ }
+
+ ms_debug_fleave();
+
+ return ret;
+}
+
+
int ms_webrtc_node_prepare(media_streamer_s *ms_streamer, media_streamer_node_s *node)
{
int ret = MEDIA_STREAMER_ERROR_NONE;
if ((ret = __ms_webrtc_prepare_ghost_sink_pad(node->gst_element, webrtcbin, _WEBRTC_VIDEO_CAPSFILTER)))
return ret;
+ /* The transceiver is added when the ghost pad is linked to webrtcbin. Therefore,
+ the transceiver direction must be update after __ms_webrtc_prepare_ghost_sink_pad(). */
+ if (__ms_webrtc_node_set_rtp_transceiver_direction(node) != MEDIA_STREAMER_ERROR_NONE) {
+ ms_error("Failed to set WebRTC RTP transceiver direction");
+ return MEDIA_STREAMER_ERROR_INVALID_OPERATION;
+ }
+
if (ms_element_set_state(webrtcbin, GST_STATE_READY)) {
ms_error("Failed to set state to READY");
return MEDIA_STREAMER_ERROR_INVALID_OPERATION;