diff --git a/CHANGES.md b/CHANGES.md index ef74a6f..4fdf94e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -16,10 +16,10 @@ - @melpon - [UPDATE] SoraClientContext を利用してコードを短くする - @melpon -- [UPDATE] Sora C++ SDK を `2023.11.0` に上げる - - @melpon +- [UPDATE] Sora C++ SDK を `2023.12.0` に上げる + - @melpon - [UPDATE] libwebrtc を `m116.5845.6.1` に上げる - - @melpon + - @melpon - [ADD] 接続中にキャプチャラを切り替える機能を実装 - @melpon - [ADD] デバイスを掴まないようにする `NoVideoDevice`, `NoAudioDevice` を追加 diff --git a/VERSION b/VERSION index 9a61b40..03585f8 100644 --- a/VERSION +++ b/VERSION @@ -1,5 +1,5 @@ SORA_UNITY_SDK_VERSION=2023.3.0 -SORA_CPP_SDK_VERSION=2023.11.0 +SORA_CPP_SDK_VERSION=2023.12.0 WEBRTC_BUILD_VERSION=m116.5845.6.1 BOOST_VERSION=1.82.0 LYRA_VERSION=1.3.0 diff --git a/src/sora.cpp b/src/sora.cpp index 1572ed6..e871cde 100644 --- a/src/sora.cpp +++ b/src/sora.cpp @@ -34,9 +34,14 @@ #endif #ifdef SORA_UNITY_SDK_IOS +#include #include "mac_helper/ios_audio_init.h" #endif +#ifdef SORA_UNITY_SDK_MACOS +#include +#endif + namespace sora_unity_sdk { Sora::Sora(UnityContext* context) : unity_context_(context) { @@ -58,6 +63,11 @@ Sora::~Sora() { if (capturer_ != nullptr && capturer_type_ == 0) { static_cast(capturer_.get())->Stop(); } +#endif +#if defined(SORA_UNITY_SDK_IOS) || defined(SORA_UNITY_SDK_MACOS) + if (capturer_ != nullptr && capturer_type_ == 0) { + static_cast(capturer_.get())->Stop(); + } #endif if (capturer_ != nullptr && capturer_type_ != 0) { static_cast(capturer_.get())->Stop(); @@ -498,11 +508,10 @@ void Sora::Disconnect() { void Sora::SwitchCamera(const sora_conf::internal::CameraConfig& cc) { RTC_LOG(LS_INFO) << "SwitchCamera: " << jsonif::to_json(cc); - boost::asio::post(*ioc_, [self = shared_from_this(), cc = cc]() { - self->DoSwitchCamera(cc); - }); -} -void Sora::DoSwitchCamera(const sora_conf::internal::CameraConfig& cc) { + + // このあたりのキャプチャラ作成は、IO スレッドではなく Unity スレッドで行う。 + // (DoConnect で作成したキャプチャラは Unity スレッド上で実行されてるので、 + // 全て同じスレッドでやる必要がある) std::function on_frame; if (on_capturer_frame_) { on_frame = [on_frame = @@ -519,6 +528,11 @@ void Sora::DoSwitchCamera(const sora_conf::internal::CameraConfig& cc) { if (capturer_ != nullptr && capturer_type_ == 0) { static_cast(capturer_.get())->Stop(); } +#endif +#if defined(SORA_UNITY_SDK_IOS) || defined(SORA_UNITY_SDK_MACOS) + if (capturer_ != nullptr && capturer_type_ == 0) { + static_cast(capturer_.get())->Stop(); + } #endif if (capturer_ != nullptr && capturer_type_ != 0) { static_cast(capturer_.get())->Stop(); @@ -541,7 +555,29 @@ void Sora::DoSwitchCamera(const sora_conf::internal::CameraConfig& cc) { std::string video_track_id = rtc::CreateRandomString(16); auto video_track = sora_context_->peer_connection_factory()->CreateVideoTrack( video_track_id, capturer.get()); + + // video_track_ をこのスレッド(Unity スレッド)で設定したいので、 + // IO スレッドの実行完了を待つ + std::promise p; + std::future f = p.get_future(); + boost::asio::post(*ioc_, + [self = shared_from_this(), cc = cc, video_track, &p]() { + self->DoSwitchCamera(cc, video_track); + p.set_value(); + }); + f.wait(); + + video_track_ = video_track; +} +void Sora::DoSwitchCamera( + const sora_conf::internal::CameraConfig& cc, + rtc::scoped_refptr video_track) { if (video_track_ == nullptr) { + webrtc::RTCErrorOr> + video_result = signaling_->GetPeerConnection()->AddTrack(video_track, + {stream_id_}); + video_sender_ = video_result.value(); + auto track_id = renderer_->AddTrack(video_track.get()); PushEvent([this, track_id]() { if (on_add_track_) { @@ -552,7 +588,6 @@ void Sora::DoSwitchCamera(const sora_conf::internal::CameraConfig& cc) { renderer_->ReplaceTrack(video_track_.get(), video_track.get()); } video_sender_->SetTrack(video_track.get()); - video_track_ = video_track; } void Sora::RenderCallbackStatic(int event_id) { @@ -812,16 +847,16 @@ void Sora::OnSetOffer(std::string offer) { on_set_offer_(offer); } }); - std::string stream_id = rtc::CreateRandomString(16); + stream_id_ = rtc::CreateRandomString(16); if (audio_track_ != nullptr) { webrtc::RTCErrorOr> audio_result = signaling_->GetPeerConnection()->AddTrack(audio_track_, - {stream_id}); + {stream_id_}); } if (video_track_ != nullptr) { webrtc::RTCErrorOr> video_result = signaling_->GetPeerConnection()->AddTrack(video_track_, - {stream_id}); + {stream_id_}); video_sender_ = video_result.value(); } diff --git a/src/sora.h b/src/sora.h index f4d1a41..60898e1 100644 --- a/src/sora.h +++ b/src/sora.h @@ -96,7 +96,9 @@ class Sora : public std::enable_shared_from_this, private: void DoConnect(const sora_conf::internal::ConnectConfig& config, std::function on_disconnect); - void DoSwitchCamera(const sora_conf::internal::CameraConfig& cc); + void DoSwitchCamera( + const sora_conf::internal::CameraConfig& cc, + rtc::scoped_refptr video_track); static rtc::scoped_refptr CreateADM( webrtc::TaskQueueFactory* task_queue_factory, @@ -170,6 +172,8 @@ class Sora : public std::enable_shared_from_this, std::map connection_ids_; + std::string stream_id_; + rtc::scoped_refptr capturer_; int capturer_type_ = 0; std::shared_ptr capturer_sink_;