*/
typedef void *webrtc_data_channel_h;
+/**
+ * @brief WebRTC bytes data handle type.
+ * @since_tizen 6.5
+ */
+typedef void *webrtc_bytes_data_h;
+
/**
* @brief Enumeration for WebRTC error.
* @since_tizen 6.5
/**
* @brief Called when the data channel is created to the connection by the remote peer.
* @since_tizen 6.5
- * @remarks The @a webrtc is the same object for which the callback was set.\nThe @a webrtc should not be released.
- * @remarks The @a channel should not be released.
+ * @remarks The @a webrtc is the same object for which the callback was set.\nThe @a webrtc should not be released.\n
+ * The @a channel should not be released.
+ * @param[in] webrtc WebRTC handle
* @param[in] channel WebRTC data channel handle
* @param[in] user_data The user data passed from the callback registration function
* @see webrtc_data_channel_set_open_cb()
/**
* @brief Called when a message is received from other peer via the data channel.
* @since_tizen 6.5
- * @remarks The @a channel is the same object for which the callback was set.\nThe @a channel should not be released.
+ * @remarks The @a channel is the same object for which the callback was set.\nThe @a channel should not be released.\n
+ * When @a type is #WEBRTC_DATA_CHANNEL_TYPE_STRING, @a message should be casted to char pointer.\n
+ * When @a type is #WEBRTC_DATA_CHANNEL_TYPE_BYTES, @a message should be casted to #webrtc_bytes_data_h.\n
+ * In this case, webrtc_get_data() can be used to get the data and its size inside of this callback.
+ * The @a message should not be released.
* @param[in] channel WebRTC data channel handle
* @param[in] type The data type
- * @param[in] message The messsage from the remote peer
+ * @param[in] message The message from the remote peer
* @param[in] user_data The user data passed from the callback registration function
* @see webrtc_data_channel_create()
* @see webrtc_data_channel_destroy()
* @see webrtc_data_channel_set_message_cb()
* @see webrtc_data_channel_unset_message_cb()
+ * @see webrtc_get_data()
*/
typedef void (*webrtc_data_channel_message_cb)(webrtc_data_channel_h channel, webrtc_data_channel_type_e type, void *message, void *user_data);
* @retval #WEBRTC_ERROR_INVALID_STATE Invalid state
* @pre @a channel should be opened before calling this function.
* @see webrtc_data_channel_open_cb()
+ * @see webrtc_data_channel_send_bytes()
*/
int webrtc_data_channel_send_string(webrtc_data_channel_h channel, const char *string);
+/**
+ * @brief Sends byte data across the data channel to the remote peer.
+ * @since_tizen 6.5
+ * @param[in] channel Data channel handle
+ * @param[in] data Byte data to send
+ * @param[in] size Size of the data
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @retval #WEBRTC_ERROR_INVALID_STATE Invalid state
+ * @pre @a channel should be opened before calling this function.
+ * @see webrtc_data_channel_open_cb()
+ * @see webrtc_data_channel_send_string()
+ */
+int webrtc_data_channel_send_bytes(webrtc_data_channel_h channel, const char *data, unsigned int size);
+
+/**
+ * @brief Gets data pointer and its size.
+ * @since_tizen 6.5
+ * @remarks This function must be called inside of the webrtc_data_channel_message_cb().\n
+ * @a bytes and @a data are managed by the platform and will be released when after the webrtc_data_channel_message_cb() is ended.
+ * @param[in] bytes Bytes data handle
+ * @param[out] data Data pointer
+ * @param[out] size Size of the data
+ * @return @c 0 on success,
+ * otherwise a negative error value
+ * @retval #WEBRTC_ERROR_NONE Successful
+ * @retval #WEBRTC_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval #WEBRTC_ERROR_INVALID_OPERATION Invalid operation
+ * @see webrtc_data_channel_message_cb()
+ */
+int webrtc_get_data(webrtc_bytes_data_h bytes, const char **data, unsigned int *size);
+
/**
* @}
*/
webrtc_callbacks_s close_cb;
} webrtc_data_channel_s;
+typedef struct _webrtc_bytes_data_s {
+ void *data;
+ unsigned int size;
+} webrtc_bytes_data_s;
+
typedef struct _element_info_s {
const gchar *klass_name;
GstCaps *src_caps;
int _create_data_channel(webrtc_s *webrtc, const char *label, webrtc_data_channel_s **channel);
int _destroy_data_channel(webrtc_data_channel_s *channel);
int _data_channel_send_string(webrtc_data_channel_s *channel, const char *string);
+int _data_channel_send_bytes(webrtc_data_channel_s *channel, const char *data, unsigned int size);
#ifdef __cplusplus
}
Name: capi-media-webrtc
Summary: A WebRTC library in Tizen Native API
-Version: 0.1.53
+Version: 0.1.54
Release: 0
Group: Multimedia/API
License: Apache-2.0
int webrtc_data_channel_send_string(webrtc_data_channel_h channel, const char *string)
{
- webrtc_data_channel_s *_channel = (webrtc_data_channel_s*)channel;
int ret = WEBRTC_ERROR_NONE;
+ webrtc_data_channel_s *_channel = (webrtc_data_channel_s*)channel;
RET_VAL_IF(_channel == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "channel is NULL");
RET_VAL_IF(string == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "string is NULL");
g_mutex_unlock(&_channel->mutex);
return ret;
+}
+
+int webrtc_data_channel_send_bytes(webrtc_data_channel_h channel, const char *data, unsigned int size)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ webrtc_data_channel_s *_channel = (webrtc_data_channel_s*)channel;
+
+ RET_VAL_IF(_channel == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "channel is NULL");
+ RET_VAL_IF(data == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "data is NULL");
+ RET_VAL_IF(size == 0, WEBRTC_ERROR_INVALID_PARAMETER, "size is 0");
+ RET_VAL_IF(_channel->channel == NULL, WEBRTC_ERROR_INVALID_OPERATION, "data_channel is NULL");
+
+ g_mutex_lock(&_channel->mutex);
+
+ ret = _data_channel_send_bytes(channel, data, size);
+
+ g_mutex_unlock(&_channel->mutex);
+
+ return ret;
+}
+
+int webrtc_get_data(webrtc_bytes_data_h bytes, const char **data, unsigned int *size)
+{
+ webrtc_bytes_data_s *_bytes = (webrtc_bytes_data_s*)bytes;
+
+ RET_VAL_IF(bytes == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "bytes is NULL");
+ RET_VAL_IF(data == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "data is NULL");
+ RET_VAL_IF(size == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "size is NULL");
+
+ *data = (const char*)_bytes->data;
+ *size = _bytes->size;
+
+ LOG_INFO("data[%p] size[%u]", *data, *size);
+
+ return WEBRTC_ERROR_NONE;
}
\ No newline at end of file
}
}
-static void __data_channel_on_message_data_cb(GObject *data_channel, GBytes *data, gpointer user_data)
+static void __data_channel_on_message_data_cb(GObject *data_channel, GBytes *bytes, gpointer user_data)
{
webrtc_data_channel_s *channel = (webrtc_data_channel_s *)user_data;
RET_IF(channel == NULL, "channel is NULL");
- LOG_DEBUG("data_channel[%s] data[%p, size:%u] user_data[%p]", GST_OBJECT_NAME(data_channel), data, g_bytes_get_size(data), user_data);
+ LOG_DEBUG("data_channel[%s] bytes[%p, size:%u] user_data[%p]", GST_OBJECT_NAME(data_channel), bytes, g_bytes_get_size(bytes), user_data);
if (channel->message_cb.callback) {
+ webrtc_bytes_data_s data = { 0, };
+ data.data = (void*)g_bytes_get_data(bytes, &data.size);
+
LOG_DEBUG(">>> callback[%p] user_data[%p]", channel->message_cb.callback, channel->message_cb.user_data);
- ((webrtc_data_channel_message_cb)(channel->message_cb.callback))((webrtc_data_channel_h)channel, WEBRTC_DATA_CHANNEL_TYPE_BYTES, data, channel->message_cb.user_data);
+ ((webrtc_data_channel_message_cb)(channel->message_cb.callback))((webrtc_data_channel_h)channel, WEBRTC_DATA_CHANNEL_TYPE_BYTES, &data, channel->message_cb.user_data);
LOG_DEBUG("<<< end of the callback");
}
}
return WEBRTC_ERROR_NONE;
}
+
+int _data_channel_send_bytes(webrtc_data_channel_s *channel, const char *data, unsigned int size)
+{
+ GstWebRTCDataChannelState state;
+ GBytes *bytes;
+
+ RET_VAL_IF(channel == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "channel is NULL");
+ RET_VAL_IF(data == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "data is NULL");
+ RET_VAL_IF(size == 0, WEBRTC_ERROR_INVALID_PARAMETER, "size is 0");
+ RET_VAL_IF(channel->channel == NULL, WEBRTC_ERROR_INVALID_OPERATION, "data_channel is NULL");
+
+ g_object_get(channel->channel, "ready-state", &state, NULL);
+
+ RET_VAL_IF(state != GST_WEBRTC_DATA_CHANNEL_STATE_OPEN, WEBRTC_ERROR_INVALID_STATE, "channel is not opened");
+
+ bytes = g_bytes_new((gconstpointer)data, (gsize)size);
+
+ g_signal_emit_by_name(channel->channel, "send-data", bytes);
+
+ LOG_INFO("data_channel[%s] >>>>> [%p, size:%u]", GST_OBJECT_NAME(channel->channel), data, size);
+
+ g_bytes_unref(bytes);
+
+ return WEBRTC_ERROR_NONE;
+}
\ No newline at end of file
CURRENT_STATUS_GET_TRANSCEIVER_DIRECTION,
CURRENT_STATUS_SET_TRANSCEIVER_DIRECTION,
CURRENT_STATUS_DATA_CHANNEL_SEND_STRING,
+ CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES,
CURRENT_STATUS_SET_STUN_SERVER,
CURRENT_STATUS_SET_LOCAL_DESCRIPTION,
CURRENT_STATUS_SET_REMOTE_DESCRIPTION,
else
g_print("webrtc_data_channel_send_string() success, string[%s]\n", string);
}
+}
+
+static void _webrtc_data_channel_send_bytes(const char *string)
+{
+ int ret = WEBRTC_ERROR_NONE;
+ int i;
for (i = 0; i < MAX_CHANNEL_LEN; i++) {
- if (g_recv_channels[i] == NULL)
+ if (g_channels[i] == NULL)
continue;
- g_print("received data_channel[%p], index[%d]: ", g_recv_channels[i], i);
- ret = webrtc_data_channel_send_string(g_recv_channels[i], string);
+ g_print("data_channel[%p], index[%d]: ", g_channels[i], i);
+ ret = webrtc_data_channel_send_bytes(g_channels[i], (void*)string, strlen(string));
if (ret != WEBRTC_ERROR_NONE)
- g_print("failed to webrtc_data_channel_send_string(), string[%s]\n", string);
+ g_print("failed to webrtc_data_channel_send_bytes(), string[%s]\n", string);
else
- g_print("webrtc_data_channel_send_string() success, string[%s]\n", string);
+ g_print("webrtc_data_channel_send_bytes() success, string[%s]\n", string);
}
}
static void __data_channel_message_cb(webrtc_data_channel_h channel, webrtc_data_channel_type_e type, void *message, void *user_data)
{
g_print("__data_channel_message_cb() is called, channel[%p], type[%d], ", channel, type);
- if (type == WEBRTC_DATA_CHANNEL_TYPE_STRING)
+ if (type == WEBRTC_DATA_CHANNEL_TYPE_STRING) {
g_print("string message[%s]\n", (char *)message);
- else if (type == WEBRTC_DATA_CHANNEL_TYPE_BYTES)
- g_print("bytes message[%p, size:%u]\n", message, g_bytes_get_size(message));
+ } else if (type == WEBRTC_DATA_CHANNEL_TYPE_BYTES) {
+ webrtc_bytes_data_h *data = message;
+ const char *data_p;
+ unsigned int size;
+ int i = 0;
+ webrtc_get_data(data, &data_p, &size);
+ g_print("bytes message[%p, size:%u]\n", data_p, size);
+ for (i = 0; i < size; i++)
+ g_print("%c", data_p[i]);
+ g_print("\n");
+ }
}
static void __data_channel_error_cb(webrtc_data_channel_h channel, webrtc_error_e error, void *user_data)
} else {
g_print("webrtc_create_data_channel() success, channel[%p], index[%d]\n", g_channels[g_channel_index], g_channel_index);
webrtc_data_channel_set_open_cb(g_channels[g_channel_index], __data_channel_open_cb, g_webrtc);
- webrtc_data_channel_set_message_cb(g_channels[g_channel_index], __data_channel_message_cb, g_webrtc);
webrtc_data_channel_set_error_cb(g_channels[g_channel_index], __data_channel_error_cb, g_webrtc);
webrtc_data_channel_set_close_cb(g_channels[g_channel_index], __data_channel_close_cb, g_webrtc);
g_channel_index++;
} else if (strncmp(cmd, "zs", 2) == 0) {
g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_STRING;
+ } else if (strncmp(cmd, "zb", 2) == 0) {
+ g_menu_state = CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES;
+
} else if (strncmp(cmd, "se", 2) == 0) {
_webrtc_set_error_cb();
g_print("td. Set transceiver direction\n");
g_print("cd. Create data channel\t");
g_print("dd. Destroy data channel\n");
- g_print("zs. Send string via data channel\n");
+ g_print("zs. Send string via data channel\t");
+ g_print("zb. Send bytes data via data channel\n");
g_print("------------------------------------- Callbacks -----------------------------------------\n");
g_print("se. Set error callback\t");
g_print("ue. Unset error callback\n");
} else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_STRING) {
g_print("*** input string to send.\n");
+ } else if (g_menu_state == CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES) {
+ g_print("*** input string to send.(it will be converted to bytes data)\n");
+
} else if (g_menu_state == CURRENT_STATUS_SET_STUN_SERVER) {
g_print("*** input STUN server address.\n");
g_print("*** input remote peer id.\n");
} else if (g_menu_state == CURRENT_STATUS_SEND_LOCAL_DESCRIPTION) {
- g_print("*** input type of local description to send to the sever.(1:offer, 2:answer)\n");
+ g_print("*** input type of local description to send to the server.(1:offer, 2:answer)\n");
} else {
g_print("*** unknown status.\n");
reset_menu_state();
break;
}
+ case CURRENT_STATUS_DATA_CHANNEL_SEND_BYTES: {
+ _webrtc_data_channel_send_bytes(cmd);
+ reset_menu_state();
+ break;
+ }
case CURRENT_STATUS_SET_STUN_SERVER: {
_webrtc_set_stun_server(cmd);
reset_menu_state();