2 * Copyright (c) 2022 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 "WebRtcStream.h"
19 #include "WebRtcMessage.h"
20 #include "aitt_internal.h"
22 namespace AittWebRTCNamespace {
24 WebRtcStream::WebRtcStream() : webrtc_handle_(nullptr), channel_(nullptr), source_id_(0)
28 WebRtcStream::~WebRtcStream()
34 bool WebRtcStream::Create(bool is_source, bool need_display)
37 ERR("Already created %p", webrtc_handle_);
41 auto ret = webrtc_create(&webrtc_handle_);
42 if (ret != WEBRTC_ERROR_NONE) {
43 ERR("Failed to create webrtc handle");
49 webrtc_add_media_source(webrtc_handle_, WEBRTC_MEDIA_SOURCE_TYPE_NULL, &source_id_);
50 if (add_source_ret != WEBRTC_ERROR_NONE)
51 ERR("Failed to add media source");
52 auto set_transceiver_codec_ret = webrtc_media_source_set_transceiver_codec(webrtc_handle_,
53 source_id_, WEBRTC_MEDIA_TYPE_VIDEO, WEBRTC_TRANSCEIVER_CODEC_VP8);
54 if (set_transceiver_codec_ret != WEBRTC_ERROR_NONE)
55 ERR("Failed to set transceiver codec");
58 webrtc_create_data_channel(webrtc_handle_, "label", nullptr, &channel_);
59 AttachSignals(is_source, need_display);
64 void WebRtcStream::Destroy(void)
66 if (!webrtc_handle_) {
67 ERR("WebRTC handle is not created");
70 auto stop_ret = webrtc_stop(webrtc_handle_);
71 if (stop_ret != WEBRTC_ERROR_NONE)
72 ERR("Failed to stop webrtc handle");
75 auto destroy_channel_ret = webrtc_destroy_data_channel(channel_);
76 if (destroy_channel_ret != WEBRTC_ERROR_NONE)
77 ERR("Failed to destroy webrtc channel");
78 auto ret = webrtc_destroy(webrtc_handle_);
79 if (ret != WEBRTC_ERROR_NONE)
80 ERR("Failed to destroy webrtc handle");
81 webrtc_handle_ = nullptr;
83 // TODO what should be initialized?
86 bool WebRtcStream::Start(void)
88 if (!webrtc_handle_) {
89 ERR("WebRTC handle is not created");
93 auto ret = webrtc_start(webrtc_handle_);
94 if (ret != WEBRTC_ERROR_NONE)
95 ERR("Failed to start webrtc handle");
97 return ret == WEBRTC_ERROR_NONE;
100 bool WebRtcStream::Stop(void)
102 if (!webrtc_handle_) {
103 ERR("WebRTC handle is not created");
107 auto ret = webrtc_stop(webrtc_handle_);
108 if (ret != WEBRTC_ERROR_NONE)
109 ERR("Failed to stop webrtc handle");
111 // TODO what should be initialized?
112 return ret == WEBRTC_ERROR_NONE;
115 bool WebRtcStream::AttachCameraSource(void)
117 if (!webrtc_handle_) {
118 ERR("WebRTC handle is not created");
123 ERR("source already attached");
128 webrtc_add_media_source(webrtc_handle_, WEBRTC_MEDIA_SOURCE_TYPE_CAMERA, &source_id_);
129 if (ret != WEBRTC_ERROR_NONE)
130 ERR("Failed to add media source");
132 return ret == WEBRTC_ERROR_NONE;
135 bool WebRtcStream::DetachCameraSource(void)
137 if (!webrtc_handle_) {
138 ERR("WebRTC handle is not created");
143 ERR("Camera source is not attached");
147 auto ret = webrtc_remove_media_source(webrtc_handle_, source_id_);
148 if (ret != WEBRTC_ERROR_NONE)
149 ERR("Failed to remove media source");
151 return ret == WEBRTC_ERROR_NONE;
154 bool WebRtcStream::CreateOfferAsync(std::function<void(std::string)> on_created_cb)
156 if (!webrtc_handle_) {
157 ERR("WebRTC handle is not created");
160 on_offer_created_cb_ = on_created_cb;
161 auto ret = webrtc_create_offer_async(webrtc_handle_, NULL, OnOfferCreated, this);
162 if (ret != WEBRTC_ERROR_NONE)
163 ERR("Failed to create offer async");
165 return ret == WEBRTC_ERROR_NONE;
168 void WebRtcStream::OnOfferCreated(webrtc_h webrtc, const char *description, void *user_data)
172 WebRtcStream *webrtc_stream = static_cast<WebRtcStream *>(user_data);
174 if (webrtc_stream->on_offer_created_cb_)
175 webrtc_stream->on_offer_created_cb_(std::string(description));
178 bool WebRtcStream::CreateAnswerAsync(std::function<void(std::string)> on_created_cb)
180 if (!webrtc_handle_) {
181 ERR("WebRTC handle is not created");
184 on_answer_created_cb_ = on_created_cb;
185 auto ret = webrtc_create_answer_async(webrtc_handle_, NULL, OnAnswerCreated, this);
186 if (ret != WEBRTC_ERROR_NONE)
187 ERR("Failed to create answer async");
189 return ret == WEBRTC_ERROR_NONE;
192 void WebRtcStream::OnAnswerCreated(webrtc_h webrtc, const char *description, void *user_data)
197 WebRtcStream *webrtc_stream = static_cast<WebRtcStream *>(user_data);
198 if (webrtc_stream->on_answer_created_cb_)
199 webrtc_stream->on_answer_created_cb_(std::string(description));
202 bool WebRtcStream::SetLocalDescription(const std::string &description)
204 if (!webrtc_handle_) {
205 ERR("WebRTC handle is not created");
209 auto ret = webrtc_set_local_description(webrtc_handle_, description.c_str());
210 if (ret != WEBRTC_ERROR_NONE)
211 ERR("Failed to set local description");
213 local_description_ = description;
215 return ret == WEBRTC_ERROR_NONE;
218 bool WebRtcStream::SetRemoteDescription(const std::string &description)
220 if (!webrtc_handle_) {
221 ERR("WebRTC handle is not created");
225 auto ret = webrtc_set_remote_description(webrtc_handle_, description.c_str());
226 if (ret != WEBRTC_ERROR_NONE)
227 ERR("Failed to set remote description");
229 return ret == WEBRTC_ERROR_NONE;
232 void WebRtcStream::SetStreamId(const std::string &id)
237 std::string WebRtcStream::GetStreamId(void) const
242 void WebRtcStream::SetPeerId(const std::string &id)
247 std::string &WebRtcStream::GetPeerId(void)
252 bool WebRtcStream::AddIceCandidateFromMessage(const std::string &ice_message)
255 if (!webrtc_handle_) {
256 ERR("WebRTC handle is not created");
259 auto ret = webrtc_add_ice_candidate(webrtc_handle_, ice_message.c_str());
260 if (ret != WEBRTC_ERROR_NONE)
261 ERR("Failed to set add ice candidate");
263 return ret == WEBRTC_ERROR_NONE;
266 bool WebRtcStream::AddPeerInformation(const std::string &sdp,
267 const std::vector<std::string> &ice_candidates)
269 remote_description_ = sdp;
270 peer_ice_candidates_ = ice_candidates;
271 if (!IsNegotiatingState()) {
272 DBG("Not negotiable");
275 return SetPeerInformation();
278 void WebRtcStream::UpdatePeerInformation(const std::vector<std::string> &ice_candidates)
280 if (IsPlayingState()) {
281 remote_description_.clear();
282 peer_ice_candidates_.clear();
283 stored_peer_ice_candidates_.clear();
288 peer_ice_candidates_ = ice_candidates;
289 if (!IsNegotiatingState()) {
290 DBG("Not negotiable");
294 SetPeerInformation();
298 bool WebRtcStream::IsNegotiatingState(void)
300 webrtc_state_e state;
301 auto get_state_ret = webrtc_get_state(webrtc_handle_, &state);
302 if (get_state_ret != WEBRTC_ERROR_NONE) {
303 ERR("Failed to get state");
307 return state == WEBRTC_STATE_NEGOTIATING;
310 bool WebRtcStream::IsPlayingState(void)
312 webrtc_state_e state;
313 auto get_state_ret = webrtc_get_state(webrtc_handle_, &state);
314 if (get_state_ret != WEBRTC_ERROR_NONE) {
315 ERR("Failed to get state");
319 return state == WEBRTC_STATE_PLAYING;
322 bool WebRtcStream::SetPeerInformation(void)
326 res = SetPeerSDP() && SetPeerIceCandidates();
327 DBG("Peer information is now %s", res ? "Valid" : "Invalid");
331 bool WebRtcStream::SetPeerSDP(void)
335 if (remote_description_.size() == 0) {
336 DBG("Peer SDP empty");
340 if (SetRemoteDescription(remote_description_))
341 remote_description_.clear();
348 bool WebRtcStream::SetPeerIceCandidates(void)
352 for (auto itr = peer_ice_candidates_.begin(); itr != peer_ice_candidates_.end(); ++itr) {
353 if (IsRedundantCandidate(*itr))
356 if (AddIceCandidateFromMessage(*itr))
357 stored_peer_ice_candidates_.push_back(*itr);
365 bool WebRtcStream::IsRedundantCandidate(const std::string &candidate)
367 for (const auto &stored_ice_candidate : stored_peer_ice_candidates_) {
368 if (stored_ice_candidate.compare(candidate) == 0)
374 void WebRtcStream::AttachSignals(bool is_source, bool need_display)
376 if (!webrtc_handle_) {
377 ERR("WebRTC handle is not created");
381 int ret = WEBRTC_ERROR_NONE;
382 // TODO: ADHOC TV profile doesn't show DBG level log
383 ret = webrtc_set_error_cb(webrtc_handle_, OnError, this);
384 DBG("webrtc_set_error_cb %s", ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
385 ret = webrtc_set_state_changed_cb(webrtc_handle_, OnStateChanged, this);
386 DBG("webrtc_set_state_changed_cb %s", ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
387 ret = webrtc_set_signaling_state_change_cb(webrtc_handle_, OnSignalingStateChanged, this);
388 DBG("webrtc_set_signaling_state_change_cb %s",
389 ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
390 ret = webrtc_set_ice_gathering_state_change_cb(webrtc_handle_, OnIceGatheringStateChanged,
392 DBG("webrtc_set_ice_gathering_state_change_cb %s",
393 ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
394 ret = webrtc_set_ice_connection_state_change_cb(webrtc_handle_, OnIceConnectionStateChanged,
396 DBG("webrtc_set_ice_connection_state_change_cb %s",
397 ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
398 ret = webrtc_set_ice_candidate_cb(webrtc_handle_, OnIceCandiate, this);
399 DBG("webrtc_set_ice_candidate_cb %s", ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
401 if (!is_source && !need_display) {
402 ret = webrtc_set_encoded_video_frame_cb(webrtc_handle_, OnEncodedFrame, this);
403 ERR("webrtc_set_encoded_video_frame_cb %s",
404 ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
407 if (!is_source && need_display) {
408 ret = webrtc_set_track_added_cb(webrtc_handle_, OnTrackAdded, this);
409 ERR("webrtc_set_track_added_cb %s", ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
411 ret = webrtc_data_channel_set_open_cb(channel_, OnDataChannelOpen, this);
412 DBG("webrtc_data_channel_set_open_cb %s", ret == WEBRTC_ERROR_NONE ? "Succeeded" : "failed");
417 void WebRtcStream::DetachSignals(void)
419 if (!webrtc_handle_) {
420 ERR("WebRTC handle is not created");
424 webrtc_unset_error_cb(webrtc_handle_);
425 webrtc_unset_state_changed_cb(webrtc_handle_);
426 webrtc_unset_signaling_state_change_cb(webrtc_handle_);
427 webrtc_unset_ice_gathering_state_change_cb(webrtc_handle_);
428 webrtc_unset_ice_connection_state_change_cb(webrtc_handle_);
429 webrtc_unset_ice_candidate_cb(webrtc_handle_);
430 webrtc_unset_encoded_video_frame_cb(webrtc_handle_);
431 webrtc_unset_track_added_cb(webrtc_handle_);
432 webrtc_data_channel_unset_open_cb(channel_);
435 WebRtcEventHandler &WebRtcStream::GetEventHandler(void)
437 return event_handler_;
440 void WebRtcStream::OnError(webrtc_h webrtc, webrtc_error_e error, webrtc_state_e state,
447 void WebRtcStream::OnStateChanged(webrtc_h webrtc, webrtc_state_e previous, webrtc_state_e current,
451 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
452 RET_IF(webrtc_stream == nullptr);
454 if (current == WEBRTC_STATE_NEGOTIATING)
455 webrtc_stream->SetPeerSDP();
457 webrtc_stream->GetEventHandler().CallOnStateChangedCb(WebRtcState::ToStreamState(current));
460 void WebRtcStream::OnSignalingStateChanged(webrtc_h webrtc, webrtc_signaling_state_e state,
464 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
465 RET_IF(webrtc_stream == nullptr);
466 webrtc_stream->GetEventHandler().CallOnSignalingStateNotifyCb(
467 WebRtcState::ToSignalingState(state));
470 void WebRtcStream::OnIceGatheringStateChanged(webrtc_h webrtc, webrtc_ice_gathering_state_e state,
473 ERR("%s %d", __func__, state);
474 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
475 RET_IF(webrtc_stream == nullptr);
477 if (state == WEBRTC_ICE_GATHERING_STATE_COMPLETE)
478 webrtc_stream->SetPeerIceCandidates();
480 webrtc_stream->GetEventHandler().CallOnIceGatheringStateNotifyCb(
481 WebRtcState::ToIceGatheringState(state));
484 void WebRtcStream::OnIceConnectionStateChanged(webrtc_h webrtc, webrtc_ice_connection_state_e state,
487 ERR("%s %d", __func__, state);
488 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
489 RET_IF(webrtc_stream == nullptr);
491 webrtc_stream->GetEventHandler().CallOnIceConnectionStateNotifyCb(
492 WebRtcState::ToIceConnectionState(state));
495 void WebRtcStream::OnIceCandiate(webrtc_h webrtc, const char *candidate, void *user_data)
498 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
499 webrtc_stream->ice_candidates_.push_back(candidate);
500 webrtc_stream->GetEventHandler().CallOnIceCandidateCb(candidate);
503 void WebRtcStream::OnEncodedFrame(webrtc_h webrtc, webrtc_media_type_e type, unsigned int track_id,
504 media_packet_h packet, void *user_data)
507 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
508 RET_IF(webrtc_stream == nullptr);
510 if (type == WEBRTC_MEDIA_TYPE_VIDEO)
511 webrtc_stream->GetEventHandler().CallOnEncodedFrameCb();
514 void WebRtcStream::OnTrackAdded(webrtc_h webrtc, webrtc_media_type_e type, unsigned int id,
517 // type AUDIO(0), VIDEO(1)
518 INFO("Added Track : id(%d), type(%s)", id, type ? "Video" : "Audio");
521 auto webrtc_stream = static_cast<WebRtcStream *>(user_data);
522 RET_IF(webrtc_stream == nullptr);
524 if (type == WEBRTC_MEDIA_TYPE_VIDEO)
525 webrtc_stream->GetEventHandler().CallOnTrakAddedCb(id);
528 void WebRtcStream::OnDataChannelOpen(webrtc_data_channel_h channel, void *user_data)
533 } // namespace AittWebRTCNamespace