*/
static void webrtcIceCandidateCB(webrtc_h webrtc, const char *candidate, void *user_data)
{
+ GList **candidates = (GList **)user_data;
+
FPRINTF("[Line : %d][%s] Callback webrtcIceCandidateCB called\\n", __LINE__, API_NAMESPACE);
+ dlog_print(DLOG_DEBUG, "NativeTCT", "[%s(%d)] webrtc[%p], candidate[%p]", __FUNCTION__, __LINE__, webrtc, candidates);
+
+ if (candidates)
+ *candidates = g_list_append(*candidates, strdup(candidate));
}
/**
QUIT_LOOP(cb_data->mainloop);
}
+/**
+* @function webrtcTrackAddedCB
+* @parameter webrtc_h webrtc, webrtc_media_type_e type, unsigned int track_id, void *user_data
+* @return NA
+*/
+static void webrtcTrackAddedCB(webrtc_h webrtc, webrtc_media_type_e type, unsigned int track_id, void *user_data)
+{
+ callback_data *cb_data = (callback_data *)user_data;
+
+ FPRINTF("[Line : %d][%s] Callback webrtcTrackAddedCB called\\n", __LINE__, API_NAMESPACE);
+
+ if (!cb_data)
+ return;
+ cb_data->is_invoked = true;
+ QUIT_LOOP(cb_data->mainloop);
+}
+
/**
* @function webrtcSignalingStateChangeCB
* @parameter webrtc_h webrtc, webrtc_signaling_state_e state, void *user_data
FPRINTF("[Line : %d][%s] Callback webrtcSignalingStateChangeCB called\\n", __LINE__, API_NAMESPACE);
+ if (!cb_data || state != WEBRTC_SIGNALING_STATE_HAVE_REMOTE_OFFER)
+ return;
+
+ cb_data->is_invoked = true;
+ QUIT_LOOP(cb_data->mainloop);
+}
+
+static void __foreach_ice_candidate(gpointer data, gpointer user_data)
+{
+ webrtc_add_ice_candidate((webrtc_h)user_data, (const char *)data);
+ FPRINTF("[Line : %d][%s] add ice candidate: %s\\n", __LINE__, API_NAMESPACE, (const char *)data);
+ dlog_print(DLOG_DEBUG, "NativeTCT", "[%s(%d)] add ice candidate: %s", __FUNCTION__, __LINE__, (const char *)data);
+}
+
+/**
+* @function webrtcIceGatheringStateChangeCB
+* @parameter webrtc_h webrtc, webrtc_ice_gathering_state_e state, void *user_data
+* @return NA
+*/
+static void webrtcIceGatheringStateChangeCB(webrtc_h webrtc, webrtc_ice_gathering_state_e state, void *user_data)
+{
+ callback_data *cb_data = (callback_data *)user_data;
+
+ FPRINTF("[Line : %d][%s] Callback webrtcIceGatheringStateChangeCB called, state[%d]\\n", __LINE__, API_NAMESPACE, state);
+ dlog_print(DLOG_DEBUG, "NativeTCT", "[%s(%d)] webrtc[%p], state[%d]", __FUNCTION__, __LINE__, webrtc, state);
+
if (!cb_data)
return;
+ if (state != WEBRTC_ICE_GATHERING_STATE_COMPLETE)
+ return;
cb_data->is_invoked = true;
QUIT_LOOP(cb_data->mainloop);
}
* @description Creates and Destroy an instance of WebRTC
* @scenario Creates and Destroy an instance of WebRTC
* @apicovered webrtc_create,webrtc_destroy
-* @passcase If webrtc_create,webrtc_destroy is successfull
+* @passcase If webrtc_create,webrtc_destroy is successful
* @failcase If webrtc_create,webrtc_destroy fails
* @precondition NA
* @postcondition NA
* @description Starts and Stops the WebRTC.
* @scenario Starts and Stops the WebRTC.
* @apicovered webrtc_start,webrtc_stop
-* @passcase If webrtc_start,webrtc_stop is successfull
+* @passcase If webrtc_start,webrtc_stop is successful
* @failcase If webrtc_start,webrtc_stop fails
* @precondition NA
* @postcondition NA
* @description Gets the WebRTC state.
* @scenario Gets the WebRTC state.
* @apicovered webrtc_get_state
-* @passcase If webrtc_get_state is successfull
+* @passcase If webrtc_get_state is successful
* @failcase If webrtc_get_state fails
* @precondition NA
* @postcondition NA
* @description Adds and Removes a media source.
* @scenario Adds and Removes a media source.
* @apicovered webrtc_add_media_source, webrtc_remove_media_source
-* @passcase If webrtc_add_media_source, webrtc_remove_media_source is successfull
+* @passcase If webrtc_add_media_source, webrtc_remove_media_source is successful
* @failcase If webrtc_add_media_source,webrtc_remove_media_source fails
* @precondition NA
* @postcondition NA
* @description Gets the peer connection state.
* @scenario Gets the peer connection state.
* @apicovered webrtc_get_peer_connection_state
-* @passcase If webrtc_get_peer_connection_state is successfull
+* @passcase If webrtc_get_peer_connection_state is successful
* @failcase If webrtc_get_peer_connection_state fails
* @precondition NA
* @postcondition NA
* @description Gets the signaling state.
* @scenario Gets the signaling state.
* @apicovered webrtc_get_signaling_state
-* @passcase If webrtc_get_signaling_state is successfull
+* @passcase If webrtc_get_signaling_state is successful
* @failcase If webrtc_get_signaling_state fails
* @precondition NA
* @postcondition NA
* @description Gets the ICE gathering state.
* @scenario Gets the ICE gathering state.
* @apicovered webrtc_get_ice_gathering_state
-* @passcase If webrtc_get_ice_gathering_state is successfull
+* @passcase If webrtc_get_ice_gathering_state is successful
* @failcase If webrtc_get_ice_gathering_state fails
* @precondition NA
* @postcondition NA
* @description Gets the ICE connection state
* @scenario Gets the ICE connection state
* @apicovered webrtc_get_ice_connection_state
-* @passcase If webrtc_get_ice_connection_state is successfull
+* @passcase If webrtc_get_ice_connection_state is successful
* @failcase If webrtc_get_ice_connection_state fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets the transceiver direction to the media source with specified media type.
* @scenario Sets and Gets the transceiver direction to the media source with specified media type.
* @apicovered webrtc_media_source_set_transceiver_direction,webrtc_media_source_get_transceiver_direction
-* @passcase If webrtc_media_source_set_transceiver_direction,webrtc_media_source_get_transceiver_direction is successfull
+* @passcase If webrtc_media_source_set_transceiver_direction,webrtc_media_source_get_transceiver_direction is successful
* @failcase If webrtc_media_source_set_transceiver_direction,webrtc_media_source_get_transceiver_direction fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets pause to the media source.
* @scenario Sets and Gets pause to the media source.
* @apicovered webrtc_media_source_set_pause,webrtc_media_source_get_pause
-* @passcase If webrtc_media_source_set_pause,webrtc_media_source_get_pause is successfull
+* @passcase If webrtc_media_source_set_pause,webrtc_media_source_get_pause is successful
* @failcase If webrtc_media_source_set_pause,webrtc_media_source_get_pause fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets mute to the media source.
* @scenario Sets and Gets mute to the media source.
* @apicovered webrtc_media_source_set_mute,webrtc_media_source_get_mute
-* @passcase If webrtc_media_source_set_mute,webrtc_media_source_get_mute is successfull
+* @passcase If webrtc_media_source_set_mute,webrtc_media_source_get_mute is successful
* @failcase If webrtc_media_source_set_mute,webrtc_media_source_get_mute fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets the video resolution of the media source.
* @scenario Sets and Gets the video resolution of the media source.
* @apicovered webrtc_media_source_set_video_resolution,webrtc_media_source_get_video_resolution
-* @passcase If webrtc_media_source_set_video_resolution,webrtc_media_source_get_video_resolution is successfull
+* @passcase If webrtc_media_source_set_video_resolution,webrtc_media_source_get_video_resolution is successful
* @failcase If webrtc_media_source_set_video_resolution,webrtc_media_source_get_video_resolution fails
* @precondition NA
* @postcondition NA
* @description Sets the mic source's sound manager stream information.
* @scenario Sets the mic source's sound manager stream information.
* @apicovered webrtc_mic_source_set_sound_stream_info
-* @passcase If webrtc_mic_source_set_sound_stream_info is successfull
+* @passcase If webrtc_mic_source_set_sound_stream_info is successful
* @failcase If webrtc_mic_source_set_sound_stream_info fails
* @precondition NA
* @postcondition NA
* @description Sets media format to the media packet source.
* @scenario Sets media format to the media packet source.
* @apicovered webrtc_media_packet_source_set_format
-* @passcase If webrtc_media_packet_source_set_format is successfull
+* @passcase If webrtc_media_packet_source_set_format is successful
* @failcase If webrtc_media_packet_source_set_format fails
* @precondition NA
* @postcondition NA
* @description Pushes media packet to the media packet source.
* @scenario Pushes media packet to the media packet source.
* @apicovered webrtc_media_packet_source_push_packet
-* @passcase If webrtc_media_packet_source_push_packet is successfull
+* @passcase If webrtc_media_packet_source_push_packet is successful
* @failcase If webrtc_media_packet_source_push_packet fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets the STUN server URL.
* @scenario Sets and Gets the STUN server URL.
* @apicovered webrtc_set_stun_server,webrtc_get_stun_server
-* @passcase If webrtc_set_stun_server,webrtc_get_stun_server is successfull
+* @passcase If webrtc_set_stun_server,webrtc_get_stun_server is successful
* @failcase If webrtc_set_stun_server,webrtc_get_stun_server fails
* @precondition NA
* @postcondition NA
* @description Adds a TURN server URL.
* @scenario Adds a TURN server URL.
* @apicovered webrtc_add_turn_server
-* @passcase If webrtc_add_turn_server is successfull
+* @passcase If webrtc_add_turn_server is successful
* @failcase If webrtc_add_turn_server fails
* @precondition NA
* @postcondition NA
* @description Retrieves all the TURN server URLs.
* @scenario Retrieves all the TURN server URLs.
* @apicovered webrtc_foreach_turn_server
-* @passcase If webrtc_foreach_turn_server is successfull
+* @passcase If webrtc_foreach_turn_server is successful
* @failcase If webrtc_foreach_turn_server fails
* @precondition NA
* @postcondition NA
* @description Creates SDP offer and answer to start a new WebRTC connection to a remote peer.
* @scenario Creates SDP offer and answer to start a new WebRTC connection to a remote peer.
* @apicovered webrtc_create_offer,webrtc_create_answer
-* @passcase If webrtc_create_offer,webrtc_create_answer is successfull
+* @passcase If webrtc_create_offer,webrtc_create_answer is successful
* @failcase If webrtc_create_offer,webrtc_create_answer fails
* @precondition NA
* @postcondition NA
* @description Sets the session description for a local peer associated with a WebRTC connection.
* @scenario Sets the session description for a local peer associated with a WebRTC connection.
* @apicovered webrtc_set_local_description
-* @passcase If webrtc_set_local_description is successfull
+* @passcase If webrtc_set_local_description is successful
* @failcase If webrtc_set_local_description fails
* @precondition NA
* @postcondition NA
* @description Sets the session description of the remote peer's current offer or answer.
* @scenario Sets the session description of the remote peer's current offer or answer.
* @apicovered webrtc_set_remote_description
-* @passcase If webrtc_set_remote_description is successfull
+* @passcase If webrtc_set_remote_description is successful
* @failcase If webrtc_set_remote_description fails
* @precondition NA
* @postcondition NA
* @description Adds a new ICE candidate from the remote peer over its signaling channel.
* @scenario Adds a new ICE candidate from the remote peer over its signaling channel.
* @apicovered webrtc_add_ice_candidate
-* @passcase If webrtc_add_ice_candidate is successfull
+* @passcase If webrtc_add_ice_candidate is successful
* @failcase If webrtc_add_ice_candidate fails
* @precondition NA
* @postcondition NA
* @description Creates and Destroys the data channel.
* @scenario Creates and Destroys the data channel.
* @apicovered webrtc_create_data_channel,webrtc_destroy_data_channel
-* @passcase If webrtc_create_data_channel,webrtc_destroy_data_channel is successfull
+* @passcase If webrtc_create_data_channel,webrtc_destroy_data_channel is successful
* @failcase If webrtc_create_data_channel,webrtc_destroy_data_channel fails
* @precondition NA
* @postcondition NA
* @description Gets data pointer and its size.
* @scenario Gets data pointer and its size.
* @apicovered webrtc_get_data
-* @passcase If webrtc_get_data is successfull
+* @passcase If webrtc_get_data is successful
* @failcase If webrtc_get_data fails
* @precondition NA
* @postcondition NA
* @description Sends a string data across the data channel to the remote peer.
* @scenario Sends a string data across the data channel to the remote peer.
* @apicovered webrtc_data_channel_send_string
-* @passcase If webrtc_data_channel_send_string is successfull
+* @passcase If webrtc_data_channel_send_string is successful
* @failcase If webrtc_data_channel_send_string fails
* @precondition NA
* @postcondition NA
* @description Sends byte data across the data channel to the remote peer.
* @scenario Sends byte data across the data channel to the remote peer.
* @apicovered webrtc_data_channel_send_bytes
-* @passcase If webrtc_data_channel_send_bytes is successfull
+* @passcase If webrtc_data_channel_send_bytes is successful
* @failcase If webrtc_data_channel_send_bytes fails
* @precondition NA
* @postcondition NA
* @description Gets the channel label.
* @scenario Gets the channel label.
* @apicovered webrtc_data_channel_get_label
-* @passcase If webrtc_data_channel_get_label is successfull
+* @passcase If webrtc_data_channel_get_label is successful
* @failcase If webrtc_data_channel_get_label fails
* @precondition NA
* @postcondition NA
* @description Creates SDP offer asynchronously to start a new WebRTC connection to a remote peer.
* @scenario Creates SDP offer asynchronously to start a new WebRTC connection to a remote peer.
* @apicovered webrtc_create_offer_async
-* @passcase If webrtc_create_offer_async is successfull
+* @passcase If webrtc_create_offer_async is successful
* @failcase If webrtc_create_offer_async fails
* @precondition NA
* @postcondition NA
* @description Creates SDP answer asynchronously to an offer received from a remote peer during the negotiation of a WebRTC connection.
* @scenario Creates SDP answer asynchronously to an offer received from a remote peer during the negotiation of a WebRTC connection.
* @apicovered webrtc_create_answer_async
-* @passcase If webrtc_create_answer_async is successfull
+* @passcase If webrtc_create_answer_async is successful
* @failcase If webrtc_create_answer_async fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets an audio loopback to render the audio frames of the media source.
* @scenario Sets and Gets an audio loopback to render the audio frames of the media source.
* @apicovered webrtc_media_source_set_audio_loopback
-* @passcase If webrtc_media_source_set_audio_loopback is successfull
+* @passcase If webrtc_media_source_set_audio_loopback is successful
* @failcase If webrtc_media_source_set_audio_loopback fails
* @precondition NA
* @postcondition NA
* @description Sets a video loopback to render the video frames of the media source.
* @scenario Sets a video loopback to render the video frames of the media source.
* @apicovered webrtc_media_source_set_video_loopback
-* @passcase If webrtc_media_source_set_video_loopback is successfull
+* @passcase If webrtc_media_source_set_video_loopback is successful
* @failcase If webrtc_media_source_set_video_loopback fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets the display mode of the video track.
* @scenario Sets and Gets the display mode of the video track.
* @apicovered webrtc_set_display_mode,webrtc_get_display_mode
-* @passcase If webrtc_set_display_mode,webrtc_get_display_mode is successfull
+* @passcase If webrtc_set_display_mode,webrtc_get_display_mode is successful
* @failcase If webrtc_set_display_mode,webrtc_get_display_mode fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets the display visibleness of the video track.
* @scenario Sets and Gets the display visibleness of the video track.
* @apicovered webrtc_set_display_visible,webrtc_get_display_visible
-* @passcase If webrtc_set_display_visible,webrtc_get_display_visible is successfull
+* @passcase If webrtc_set_display_visible,webrtc_get_display_visible is successful
* @failcase If webrtc_set_display_visible,webrtc_get_display_visible fails
* @precondition NA
* @postcondition NA
* @description Sets and Gets a ICE transport policy that represents which candidates the ICE Agent is allowed to use.
* @scenario Sets and Gets a ICE transport policy that represents which candidates the ICE Agent is allowed to use.
* @apicovered webrtc_set_ice_transport_policy,webrtc_get_ice_transport_policy
-* @passcase If webrtc_set_ice_transport_policy,webrtc_get_ice_transport_policy is successfull
+* @passcase If webrtc_set_ice_transport_policy,webrtc_get_ice_transport_policy is successful
* @failcase If webrtc_set_ice_transport_policy,webrtc_get_ice_transport_policy fails
* @precondition NA
* @postcondition NA
destroyWindow();
return 0;
}
+
+//& purpose: Starts and finishes negotiation by setting local and remote descriptions to two handles.
+//& type: auto
+/**
+* @testcase ITc_media_webrtc_start_and_finish_negotiation_p
+* @since_tizen 6.5
+* @author SR(sc11.lee)
+* @reviewer SR(seungbae.shin)
+* @type auto
+* @description Starts and finishes negotiation by setting local and remote descriptions to two handles.
+* @scenario Starts and finishes negotiation by setting local and remote descriptions to two handles.
+* @apicovered webrtc_start,webrtc_create_offer,webrtc_create_answer,webrtc_set_local_description,webrtc_set_remote_description
+* @passcase If webrtc_start,webrtc_create_offer,webrtc_create_answer,webrtc_set_local_description,webrtc_set_remote_description is successful
+* @failcase If webrtc_start,webrtc_create_offer,webrtc_create_answer,webrtc_set_local_description,webrtc_set_remote_description fails
+* @precondition NA
+* @postcondition NA
+*/
+int ITc_media_webrtc_start_and_finish_negotiation_p(void)
+{
+ webrtc_h webrtcOfferer;
+ webrtc_h webrtcAnswerer;
+ int nRet;
+ unsigned int nId;
+ char *offerSDP;
+ char *answerSDP;
+ GList *offerICECandidates = NULL;
+ GList *answerICECandidates = NULL;
+ callback_data cb_data = { .mainloop = NULL, .is_invoked = false };
+ callback_data cb_data2 = { .mainloop = NULL, .is_invoked = false };
+
+ START_TEST;
+
+ nRet = webrtc_create(&webrtcOfferer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_create", WebRtcGetError(nRet));
+
+ nRet = webrtc_add_media_source(webrtcOfferer, WEBRTC_MEDIA_SOURCE_TYPE_VIDEOTEST, &nId);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_add_media_source", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_ice_candidate_cb(webrtcOfferer, webrtcIceCandidateCB, &offerICECandidates);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_ice_candidate_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_state_changed_cb(webrtcOfferer, webrtcStateChangedCB, &cb_data);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_state_changed_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_signaling_state_change_cb(webrtcOfferer, webrtcSignalingStateChangeCB, NULL);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_signaling_state_change_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_ice_gathering_state_change_cb(webrtcOfferer, webrtcIceGatheringStateChangeCB, &cb_data);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_ice_gathering_state_change_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_start(webrtcOfferer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_start", WebRtcGetError(nRet));
+
+ RUN_POLLING_LOOP(cb_data.mainloop, cb_data.is_invoked);
+ if (!cb_data.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcStateChangedCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+ cb_data.is_invoked = false;
+
+ nRet = webrtc_create(&webrtcAnswerer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_create", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_ice_candidate_cb(webrtcAnswerer, webrtcIceCandidateCB, &answerICECandidates);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_ice_candidate_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_state_changed_cb(webrtcAnswerer, webrtcStateChangedCB, &cb_data);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_state_changed_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_signaling_state_change_cb(webrtcAnswerer, webrtcSignalingStateChangeCB, &cb_data);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_signaling_state_change_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_ice_gathering_state_change_cb(webrtcAnswerer, webrtcIceGatheringStateChangeCB, &cb_data);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_ice_gathering_state_change_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_track_added_cb(webrtcAnswerer, webrtcTrackAddedCB, &cb_data2);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_track_added_cb", WebRtcGetError(nRet));
+
+ nRet = webrtc_start(webrtcAnswerer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_start", WebRtcGetError(nRet));
+ RUN_POLLING_LOOP(cb_data.mainloop, cb_data.is_invoked);
+ if (!cb_data.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcStateChangedCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+ cb_data.is_invoked = false;
+
+ nRet = webrtc_create_offer(webrtcOfferer, NULL, &offerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_create_offer", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_local_description(webrtcOfferer, offerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_local_description", WebRtcGetError(nRet));
+
+ RUN_POLLING_LOOP(cb_data.mainloop, cb_data.is_invoked);
+ if (!cb_data.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcIceGatheringStateChangeCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+ cb_data.is_invoked = false;
+
+ nRet = webrtc_set_remote_description(webrtcAnswerer, offerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_remote_description", WebRtcGetError(nRet));
+ FREE_MEMORY(offerSDP);
+
+ RUN_POLLING_LOOP(cb_data.mainloop, cb_data.is_invoked);
+ if (!cb_data.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcSignalingStateChangeCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+ cb_data.is_invoked = false;
+
+ nRet = webrtc_create_answer(webrtcAnswerer, NULL, &answerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_create_answer", WebRtcGetError(nRet));
+
+ nRet = webrtc_set_local_description(webrtcAnswerer, answerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_local_description", WebRtcGetError(nRet));
+
+ RUN_POLLING_LOOP(cb_data.mainloop, cb_data.is_invoked);
+ if (!cb_data.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcIceGatheringStateChangeCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+
+ g_list_foreach(offerICECandidates, __foreach_ice_candidate, webrtcAnswerer);
+ g_list_foreach(answerICECandidates, __foreach_ice_candidate, webrtcOfferer);
+
+ nRet = webrtc_set_remote_description(webrtcOfferer, answerSDP);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_set_remote_description", WebRtcGetError(nRet));
+ FREE_MEMORY(answerSDP);
+
+ /* wait for track added callback of answerer */
+ RUN_POLLING_LOOP(cb_data2.mainloop, cb_data2.is_invoked);
+ if (!cb_data2.is_invoked) {
+ FPRINTF("[Line : %d][%s] Callback webrtcTrackAddedCB not invoked\\n", __LINE__, API_NAMESPACE);
+ return 1;
+ }
+
+ nRet = webrtc_stop(webrtcOfferer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_stop", WebRtcGetError(nRet));
+
+ nRet = webrtc_destroy(webrtcOfferer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_destroy", WebRtcGetError(nRet));
+
+ nRet = webrtc_stop(webrtcAnswerer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_stop", WebRtcGetError(nRet));
+
+ nRet = webrtc_destroy(webrtcAnswerer);
+ PRINT_RESULT(WEBRTC_ERROR_NONE, nRet, "webrtc_destroy", WebRtcGetError(nRet));
+
+ g_list_free_full(offerICECandidates, free);
+ g_list_free_full(answerICECandidates, free);
+
+ return 0;
+}
/** @} */
/** @} */