*/
int webrtc_screen_source_unset_crop(webrtc_h webrtc, unsigned int source_id);
+/**
+ * @brief Starts the media source.
+ * @since_tizen 9.0
+ * @remarks This function will be used after adding a media source during state of #WEBRTC_STATE_NEGOTIATING or #WEBRTC_STATE_PLAYING.\n
+ * If the state is #WEBRTC_STATE_IDLE, this function will have no effect. Rather webrtc_start() will start media sources later.
+ * @param[in] webrtc WebRTC handle
+ * @param[in] source_id The media source id
+ * @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_add_media_source()
+ * @see webrtc_remove_media_source()
+ * @see webrtc_start()
+ */
+int webrtc_start_media_source(webrtc_h webrtc, unsigned int source_id);
+
/**
* @}
*/
int _set_payload_type(webrtc_s *webrtc, webrtc_gst_slot_s *source, int av_idx, const gchar *media_type);
int _get_fixed_payload_type(const gchar *media_type);
void _return_payload_type(webrtc_s *webrtc, unsigned int payload_type);
-void _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source);
+int _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source);
int _add_transceiver(webrtc_gst_slot_s *source, webrtc_media_type_e media_type, rtp_payload_info_s *payload_info);
int _set_transceiver_direction(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_direction_e direction);
int _get_transceiver_direction(webrtc_s *webrtc, unsigned int source_id, webrtc_media_type_e media_type, webrtc_transceiver_direction_e *direction);
void _source_slot_destroy_cb(gpointer data);
int _add_media_source(webrtc_s *webrtc, int type, unsigned int *source_id);
int _add_media_source_internal(webrtc_s *webrtc, int type, unsigned int *source_id);
+int _start_media_source(webrtc_s *webrtc, unsigned int source_id);
int _remove_media_source(webrtc_s *webrtc, unsigned int source_id);
bool _check_if_codec_is_set_to_null_sources(webrtc_s *webrtc);
bool _check_if_format_is_set_to_packet_sources(webrtc_s *webrtc);
Name: capi-media-webrtc
Summary: A WebRTC library in Tizen Native API
-Version: 1.0.5
+Version: 1.1.0
Release: 0
Group: Multimedia/API
License: Apache-2.0
return _get_filesrc_looping(_webrtc, source_id, looping);
}
-//LCOV_EXCL_START
int webrtc_screen_source_set_crop(webrtc_h webrtc, unsigned int source_id, int x, int y, int width, int height)
{
g_autoptr(GMutexLocker) locker = NULL;
return WEBRTC_ERROR_INVALID_OPERATION;
#endif
}
-//LCOV_EXCL_STOP
+
+int webrtc_start_media_source(webrtc_h webrtc, unsigned int source_id)
+{
+ g_autoptr(GMutexLocker) locker = NULL;
+ webrtc_s *_webrtc = (webrtc_s *)webrtc;
+
+ RET_VAL_IF(_webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+
+ locker = g_mutex_locker_new(&_webrtc->mutex);
+
+ if (_webrtc->state == WEBRTC_STATE_IDLE) {
+ LOG_DEBUG("webrtc_start() will take charge of starting media sources");
+ return WEBRTC_ERROR_NONE;
+ }
+
+ return _start_media_source(webrtc, source_id);
+}
int webrtc_set_sound_stream_info(webrtc_h webrtc, unsigned int track_id, sound_stream_info_h stream_info)
{
int webrtc_add_media_source_internal(webrtc_h webrtc, webrtc_media_source_type_internal_e type, unsigned int *source_id)
{
- int ret = WEBRTC_ERROR_NONE;
g_autoptr(GMutexLocker) locker = NULL;
webrtc_s *_webrtc = (webrtc_s *)webrtc;
locker = g_mutex_locker_new(&_webrtc->mutex);
- ret = _add_media_source_internal(webrtc, type, source_id);
- if (ret == WEBRTC_ERROR_NONE)
- LOG_INFO("source_id[%u]", *source_id);
-
- return ret;
+ return _add_media_source_internal(webrtc, type, source_id);
}
int webrtc_media_source_set_payload_type(webrtc_h webrtc, unsigned int source_id, webrtc_media_type_e media_type, unsigned int pt)
return WEBRTC_ERROR_INVALID_OPERATION;
}
+static int __complete_source(webrtc_s *webrtc, webrtc_gst_slot_s *source)
+{
+ int ret;
+
+ RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
+ RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
+
+ LOG_DEBUG("source[id:%u, type:%d, media_types:0x%x]", source->id, source->type, source->media_types);
+
+ if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE)
+ return WEBRTC_ERROR_NONE;
+
+ if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
+ source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL)
+ goto add_transceiver;
+
+ ret = (source->media_types == MEDIA_TYPE_AUDIO) ?
+ __complete_rest_of_audiosrc(webrtc, source) : __complete_rest_of_videosrc(webrtc, source);
+ if (ret != WEBRTC_ERROR_NONE)
+ return ret;
+ if (!gst_element_sync_state_with_parent(GST_ELEMENT(source->bin))) {
+ LOG_ERROR("failed to gst_element_sync_state_with_parent() for [%s]", GST_ELEMENT_NAME(source->bin));
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+
+add_transceiver:
+ return _check_and_add_recvonly_transceiver(source);
+}
+
int _complete_sources(webrtc_s *webrtc)
{
int i;
+ int ret;
webrtc_gst_slot_s *source;
RET_VAL_IF(webrtc == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "webrtc is NULL");
if (!(source = webrtc->gst.sources[i]))
continue;
- LOG_DEBUG("source[id:%u, type:%d, media_types:0x%x]", source->id, source->type, source->media_types);
+ if ((ret = __complete_source(webrtc, source)) != WEBRTC_ERROR_NONE)
+ return ret;
+ }
- if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_FILE)
- continue;
+ return WEBRTC_ERROR_NONE;
+}
- if (source->type == WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET ||
- source->type == WEBRTC_MEDIA_SOURCE_TYPE_NULL) {
- goto add_transceiver;
- }
+int _start_media_source(webrtc_s *webrtc, unsigned int source_id)
+{
+ int ret;
+ webrtc_gst_slot_s *source;
- if (source->media_types == MEDIA_TYPE_AUDIO)
- __complete_rest_of_audiosrc(webrtc, source);
- else
- __complete_rest_of_videosrc(webrtc, source);
+ ASSERT(webrtc);
-add_transceiver:
- _check_and_add_recvonly_transceiver(source);
+ RET_VAL_IF(source_id == 0, WEBRTC_ERROR_INVALID_PARAMETER, "source_id is 0");
+ RET_VAL_IF((source = _get_slot_by_id(webrtc->gst.source_slots, source_id)) == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "could not find source");
+
+ switch (source->type) {
+ case WEBRTC_MEDIA_SOURCE_TYPE_MEDIA_PACKET:
+ if (!source->media_format) {
+ LOG_ERROR("media format must be set to the media packet");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ break;
+ case WEBRTC_MEDIA_SOURCE_TYPE_FILE: {
+ gchar *location = NULL;
+ g_object_get(G_OBJECT(gst_bin_get_by_name(GST_BIN(source->filesrc_pipeline), ELEMENT_NAME_FILE_SRC)), "location", &location, NULL);
+ if (!location) {
+ LOG_ERROR("location must be set to the file source");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ g_free(location);
+ break;
+ }
+ case WEBRTC_MEDIA_SOURCE_TYPE_NULL: {
+ int i;
+ bool found = false;
+ for (i = 0; i < AV_IDX_MAX; i++) {
+ if (source->av[i].codec) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ LOG_ERROR("codec must be set to the null source");
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ }
+ break;
+ }
}
+ /* TODO: add resource check */
+
+ ret = __complete_source(webrtc, source);
+ RET_VAL_IF(ret != WEBRTC_ERROR_NONE, ret, "failed to complete sources");
+
+ LOG_INFO("webrtc[%p] source[type:%d, id:%u]", webrtc, source->type, source_id);
+
return WEBRTC_ERROR_NONE;
}
{
webrtc_gst_slot_s *source = (webrtc_gst_slot_s *)user_data;
GstPad *peer = gst_pad_get_peer(pad);
+ GstWebRTCRTPTransceiver *transceiver;
RET_VAL_IF(source == NULL, FALSE, "source is NULL");
RET_VAL_IF(source->webrtc == NULL, FALSE, "webrtc is NULL");
LOG_DEBUG("about to release request pad[%s]", GST_PAD_NAME(peer));
+ /* Should it be done manually? */
+ g_object_get(peer, "transceiver", &transceiver, NULL);
+ g_object_set(transceiver, "direction", GST_WEBRTC_RTP_TRANSCEIVER_DIRECTION_INACTIVE, NULL);
+
+ gst_pad_unlink(pad, peer);
+ LOG_DEBUG("unlink pads[%s - %s]", GST_PAD_NAME(pad), GST_PAD_NAME(peer));
+
+ /* FIXME: setting gst state to NULL when WEBRTC_STATE_NEGOTIATING occurs a blocking issue. */
+ if (source->webrtc->state == WEBRTC_STATE_PLAYING)
+ gst_element_set_state(GST_ELEMENT(source->bin), GST_STATE_NULL);
+
gst_element_release_request_pad(source->webrtc->gst.webrtcbin, peer);
/* Two unrefing here, one for getting request pad, another one for getting peer pad */
return WEBRTC_ERROR_NONE;
}
-void _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source)
+int _check_and_add_recvonly_transceiver(webrtc_gst_slot_s *source)
{
rtp_payload_info_s *payload_info = NULL;
+ int i;
+ webrtc_media_type_e media_type;
- RET_IF(source == NULL, "source is NULL");
-
- if (source->av[AV_IDX_AUDIO].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[AV_IDX_AUDIO].codec) {
- if (g_hash_table_size(source->av[AV_IDX_AUDIO].encodings) > 0)
- __add_transceiver_for_simulcast(source, WEBRTC_MEDIA_TYPE_AUDIO);
- else if ((payload_info = __get_payload_info_by_encoding_name(source->av[AV_IDX_AUDIO].codec)))
- _add_transceiver(source, WEBRTC_MEDIA_TYPE_AUDIO, payload_info);
- }
+ RET_VAL_IF(source == NULL, WEBRTC_ERROR_INVALID_PARAMETER, "source is NULL");
- if (source->av[AV_IDX_VIDEO].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[AV_IDX_VIDEO].codec) {
- if (g_hash_table_size(source->av[AV_IDX_VIDEO].encodings) > 0)
- __add_transceiver_for_simulcast(source, WEBRTC_MEDIA_TYPE_VIDEO);
- else if ((payload_info = __get_payload_info_by_encoding_name(source->av[AV_IDX_VIDEO].codec)))
- _add_transceiver(source, WEBRTC_MEDIA_TYPE_VIDEO, payload_info);
+ for (i = AV_IDX_AUDIO; i < AV_IDX_MAX; i++) {
+ media_type = (i == AV_IDX_AUDIO) ? WEBRTC_MEDIA_TYPE_AUDIO : WEBRTC_MEDIA_TYPE_VIDEO;
+ if (source->av[i].direction == WEBRTC_TRANSCEIVER_DIRECTION_RECVONLY && source->av[i].codec) {
+ if (g_hash_table_size(source->av[i].encodings) > 0)
+ __add_transceiver_for_simulcast(source, media_type);
+ else if (!(payload_info = __get_payload_info_by_encoding_name(source->av[i].codec)))
+ return WEBRTC_ERROR_INVALID_OPERATION;
+ _add_transceiver(source, media_type, payload_info);
+ }
}
+ return WEBRTC_ERROR_NONE;
}
static GstCaps *__make_transceiver_caps(rtp_payload_info_s *payload_info)