diff --git a/CMakeLists.txt b/CMakeLists.txt index 7271f72..ecb89ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,9 +81,11 @@ add_custom_command( OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/proto/cpp/sora_conf.json.h" "${CMAKE_CURRENT_BINARY_DIR}/proto/cpp/sora_conf_internal.json.h" + "${CMAKE_CURRENT_BINARY_DIR}/proto/cpp/rtc.json.h" "${CMAKE_CURRENT_SOURCE_DIR}/Sora/Generated/SoraConf.cs" "${CMAKE_CURRENT_SOURCE_DIR}/Sora/Generated/SoraConfInternal.cs" "${CMAKE_CURRENT_SOURCE_DIR}/Sora/Generated/Jsonif.cs" + "${CMAKE_CURRENT_SOURCE_DIR}/Sora/Generated/Rtc.cs" COMMAND "${PROTOBUF_DIR}/bin/protoc${EXE_EXT}" ARGS @@ -94,6 +96,7 @@ add_custom_command( -I "${CMAKE_CURRENT_SOURCE_DIR}/proto/" "${CMAKE_CURRENT_SOURCE_DIR}/proto/sora_conf.proto" "${CMAKE_CURRENT_SOURCE_DIR}/proto/sora_conf_internal.proto" + "${CMAKE_CURRENT_SOURCE_DIR}/proto/rtc.proto" DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/proto/sora_conf.proto" "${CMAKE_CURRENT_SOURCE_DIR}/proto/sora_conf_internal.proto" diff --git a/Sora/Sora.cs b/Sora/Sora.cs index 81ef6cb..c81f776 100644 --- a/Sora/Sora.cs +++ b/Sora/Sora.cs @@ -867,6 +867,12 @@ public void GetStats(Action onGetStats) sora_get_stats(p, StatsCallback, GCHandle.ToIntPtr(handle)); } + public (bool, string) GetTrackId(uint trackId) { + IntPtr p = get_track_id(trackId); + bool found = p != IntPtr.Zero; + return (found, found ? Marshal.PtrToStringAnsi(p) : ""); + } + /// /// 指定した label のデータチャンネルに buf を送信します。 /// @@ -1096,6 +1102,8 @@ public string ConnectedSignalingURL private static extern void sora_get_selected_signaling_url(IntPtr p, [Out] byte[] buf, int size); [DllImport(DllName)] private static extern void sora_get_connected_signaling_url(IntPtr p, [Out] byte[] buf, int size); + [DllImport(DllName, CharSet=CharSet.Ansi)] + private static extern IntPtr get_track_id(uint track_id); public class AudioOutputHelper : IDisposable { diff --git a/proto/rtc.proto b/proto/rtc.proto new file mode 100644 index 0000000..7d6c86f --- /dev/null +++ b/proto/rtc.proto @@ -0,0 +1,18 @@ +syntax = "proto3"; + +package rtc; + +enum TrackKind { + VIDEO = 0; + AUDIO = 1; +} + +message Track { + TrackKind kind = 1; + string track_id = 2; + string connection_id = 3; +} + +message Tracks { + repeated Track track = 1; +} \ No newline at end of file diff --git a/src/sora.cpp b/src/sora.cpp index 77a7e83..13c0a4c 100644 --- a/src/sora.cpp +++ b/src/sora.cpp @@ -1012,4 +1012,60 @@ std::string Sora::GetConnectedSignalingURL() const { return signaling_->GetConnectedSignalingURL(); } +void Sora::GetTracks() const { + RTC_LOG(LS_INFO) << __func__ << " start"; + auto conn = signaling_->GetPeerConnection(); + RTC_LOG(LS_INFO) << __func__ << " hoge"; + + if (conn != nullptr) { + RTC_LOG(LS_INFO) << __func__ << " A"; + } else { + RTC_LOG(LS_INFO) << __func__ << " B"; + } + + auto conf = conn->GetConfiguration(); + if (conf.sdp_semantics == webrtc::SdpSemantics::kUnifiedPlan) { + RTC_LOG(LS_INFO) << __func__ << " sdp_semantics: kUnifiedPlan"; + } else { + RTC_LOG(LS_INFO) << __func__ << " sdp_semantics: kPlanB"; + } + + if (conf.sdp_semantics != webrtc::SdpSemantics::kUnifiedPlan) { + auto local_streams = conn->local_streams(); + for (int i = 0; i < local_streams->count(); i++) { + auto stream = local_streams->at(i); + RTC_LOG(LS_INFO) << __func__ << " local stream: " << stream->id(); + auto audio_tracks = stream->GetAudioTracks(); + for (auto track : audio_tracks) { + RTC_LOG(LS_INFO) << __func__ << " local audio track: " << track->id(); + } + + auto video_tracks = stream->GetAudioTracks(); + for (auto track : video_tracks) { + RTC_LOG(LS_INFO) << __func__ << " local video track: " << track->id(); + } + } + // auto remote_streams = conn.remote_streams(); + } else { + auto transceivers = conn->GetTransceivers(); + for (auto transceiver : transceivers) { + auto sender = transceiver->sender(); + auto sender_stream_ids = sender->stream_ids(); + if (sender_stream_ids.size() != 0) { + RTC_LOG(LS_INFO) << __func__ + << " sender_stream_id=" << sender_stream_ids[0] + << ", track_id=" << sender->track()->id(); + } + + auto receiver = transceiver->receiver(); + auto receiver_stream_ids = receiver->stream_ids(); + if (receiver_stream_ids.size() != 0) { + RTC_LOG(LS_INFO) << __func__ + << " receiver_stream_id=" << receiver_stream_ids[0] + << ", track_id=" << receiver->track()->id(); + } + } + } +} + } // namespace sora_unity_sdk diff --git a/src/sora.h b/src/sora.h index ebbbd33..b86dae6 100644 --- a/src/sora.h +++ b/src/sora.h @@ -76,6 +76,8 @@ class Sora : public std::enable_shared_from_this, std::string GetSelectedSignalingURL() const; std::string GetConnectedSignalingURL() const; + void GetTracks() const; + private: void* GetAndroidApplicationContext(void* env); static sora_conf::ErrorCode ToErrorCode(sora::SoraSignalingErrorCode ec); diff --git a/src/unity.cpp b/src/unity.cpp index 2695a4b..f7dc90f 100644 --- a/src/unity.cpp +++ b/src/unity.cpp @@ -8,6 +8,7 @@ #include "sora_conf.json.h" #include "sora_conf_internal.json.h" #include "unity_context.h" +#include "unity_renderer.h" #if defined(SORA_UNITY_SDK_WINDOWS) || defined(SORA_UNITY_SDK_UBUNTU) #include @@ -183,6 +184,8 @@ void sora_set_on_handle_audio(void* p, handle_audio_cb_t f, void* userdata) { void sora_get_stats(void* p, stats_cb_t f, void* userdata) { auto wsora = (SoraWrapper*)p; + + wsora->sora->GetTracks(); // DEBUG wsora->sora->GetStats( [f, userdata](std::string json) { f(json.c_str(), userdata); }); } @@ -309,6 +312,13 @@ void sora_audio_output_helper_set_handsfree(void* p, unity_bool_t enabled) { helper->SetHandsfree(enabled != 0); } +UNITY_INTERFACE_EXPORT const char* get_track_id(ptrid_t track_id) { + void* p = sora_unity_sdk::IdPointer::Instance().Lookup(track_id); + return p != nullptr + ? ((sora_unity_sdk::UnityRenderer::Sink*)p)->GetTrackId().c_str() + : nullptr; +} + // iOS の場合は static link で名前が被る可能性があるので、別の名前にしておく void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API #if defined(SORA_UNITY_SDK_IOS) diff --git a/src/unity.h b/src/unity.h index 336084c..4405d8e 100644 --- a/src/unity.h +++ b/src/unity.h @@ -126,6 +126,7 @@ sora_audio_output_helper_is_handsfree(void* p); UNITY_INTERFACE_EXPORT void sora_audio_output_helper_set_handsfree( void* p, unity_bool_t enabled); +UNITY_INTERFACE_EXPORT const char* get_track_id(ptrid_t track_id); #ifdef __cplusplus } diff --git a/src/unity_renderer.cpp b/src/unity_renderer.cpp index 8b837e6..936a620 100644 --- a/src/unity_renderer.cpp +++ b/src/unity_renderer.cpp @@ -1,5 +1,6 @@ #include "unity_renderer.h" +#include #include // libwebrtc @@ -9,7 +10,8 @@ namespace sora_unity_sdk { // UnityRenderer::Sink -UnityRenderer::Sink::Sink(webrtc::VideoTrackInterface* track) : track_(track) { +UnityRenderer::Sink::Sink(webrtc::VideoTrackInterface* track) + : track_(track), track_id_(track_->id()) { RTC_LOG(LS_INFO) << "[" << (void*)this << "] Sink::Sink"; deleting_ = false; updating_ = false; @@ -25,12 +27,17 @@ UnityRenderer::Sink::~Sink() { // RTC_LOG(LS_INFO) << "[" << (void*)this << "] Sink::~Sink waiting..."; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } + track_->RemoveSink(this); IdPointer::Instance().Unregister(ptrid_); } ptrid_t UnityRenderer::Sink::GetSinkID() const { return ptrid_; } +const std::string& UnityRenderer::Sink::GetTrackId() const { + return track_id_; +} + void UnityRenderer::Sink::SetTrack(webrtc::VideoTrackInterface* track) { track_->RemoveSink(this); track->AddOrUpdateSink(this, rtc::VideoSinkWants()); diff --git a/src/unity_renderer.h b/src/unity_renderer.h index c6b6812..f388397 100644 --- a/src/unity_renderer.h +++ b/src/unity_renderer.h @@ -19,6 +19,8 @@ class UnityRenderer { class Sink : public rtc::VideoSinkInterface { rtc::scoped_refptr track_; ptrid_t ptrid_; + std::string track_id_; + char* track_id_c_; std::mutex mutex_; rtc::scoped_refptr frame_buffer_; uint8_t* temp_buf_ = nullptr; @@ -29,6 +31,7 @@ class UnityRenderer { Sink(webrtc::VideoTrackInterface* track); ~Sink(); ptrid_t GetSinkID() const; + const std::string& GetTrackId() const; void SetTrack(webrtc::VideoTrackInterface* track); private: