From 23fbfb5501dd3ccee64b95b92bc14b04cfa4d1cf Mon Sep 17 00:00:00 2001 From: melpon Date: Sat, 11 Jan 2025 16:16:47 +0900 Subject: [PATCH] =?UTF-8?q?sumomo=20=E3=81=AB=E3=83=93=E3=83=87=E3=82=AA?= =?UTF-8?q?=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9=E3=81=A8=E3=82=AA=E3=83=BC?= =?UTF-8?q?=E3=83=87=E3=82=A3=E3=82=AA=E3=83=87=E3=83=90=E3=82=A4=E3=82=B9?= =?UTF-8?q?=E3=82=92=E8=A8=AD=E5=AE=9A=E3=81=99=E3=82=8B=E3=82=AA=E3=83=97?= =?UTF-8?q?=E3=82=B7=E3=83=A7=E3=83=B3=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/c_cpp_properties.json | 71 +++++++++-------- CHANGES.md | 4 + examples/sumomo/src/sumomo.cpp | 24 +++++- include/sora/sora_client_context.h | 4 + src/sora_client_context.cpp | 123 ++++++++++++++++++++++++++++- 5 files changed, 187 insertions(+), 39 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index c48c0204..a7768ebb 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,40 +1,5 @@ { "configurations": [ - { - "name": "ubuntu-20.04_x86_64 Release", - "includePath": [ - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/boost/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/webrtc/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/webrtc/include/third_party/abseil-cpp", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/webrtc/include/third_party/boringssl/src/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/webrtc/include/third_party/libyuv/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/webrtc/include/third_party/zlib", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/llvm/libcxx/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/openh264/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/vpl/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/blend2d/include", - "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/catch2/include", - "${workspaceFolder}/_build/ubuntu-20.04_x86_64/release/sora", - "${workspaceFolder}/third_party/NvCodec/include", - "${workspaceFolder}/third_party/NvCodec/NvCodec", - "${workspaceFolder}/include", - "/usr/local/cuda/include" - ], - "defines": [ - "WEBRTC_POSIX", - "_LIBCPP_ABI_UNSTABLE", - "_LIBCPP_DISABLE_AVAILABILITY", - "OPENSSL_IS_BORINGSSL", - "SORA_CPP_SDK_UBUNTU_2004", - "USE_NVCODEC_ENCODER", - "RTC_ENABLE_H265" - ], - "compilerPath": "${workspaceFolder}/_install/ubuntu-20.04_x86_64/release/llvm/clang/bin/clang++", - "compilerArgs": ["-nostdinc++"], - "cStandard": "gnu17", - "cppStandard": "gnu++17", - "intelliSenseMode": "linux-clang-x64" - }, { "name": "ubuntu-20.04_armv8_jetson Release", "includePath": [ @@ -104,6 +69,42 @@ "cppStandard": "gnu++17", "intelliSenseMode": "linux-clang-x64" }, + { + "name": "ubuntu-24.04_x86_64 Release", + "includePath": [ + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/boost/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/webrtc/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/webrtc/include/third_party/abseil-cpp", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/webrtc/include/third_party/boringssl/src/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/webrtc/include/third_party/libyuv/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/webrtc/include/third_party/zlib", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/llvm/libcxx/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/openh264/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/vpl/include", + "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/blend2d/include", + "${workspaceFolder}/_build/ubuntu-24.04_x86_64/release/sora", + "${workspaceFolder}/third_party/NvCodec/include", + "${workspaceFolder}/third_party/NvCodec/NvCodec", + "${workspaceFolder}/include", + "/usr/local/cuda/include" + ], + "defines": [ + "WEBRTC_POSIX", + "_LIBCPP_ABI_UNSTABLE", + "_LIBCPP_DISABLE_AVAILABILITY", + "OPENSSL_IS_BORINGSSL", + "SORA_CPP_SDK_UBUNTU_2204", + "USE_NVCODEC_ENCODER", + "USE_VPL_ENCODER", + "RTC_ENABLE_H265" + ], + // "compilerPath": "${workspaceFolder}/_install/ubuntu-24.04_x86_64/release/llvm/clang/bin/clang++", + "compilerPath": "/usr/bin/clang++-18", + "compilerArgs": ["-nostdinc++"], + "cStandard": "gnu17", + "cppStandard": "gnu++17", + "intelliSenseMode": "linux-clang-x64" + }, { "name": "android Release", "includePath": [ diff --git a/CHANGES.md b/CHANGES.md index a096bc20..35847837 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -65,6 +65,10 @@ - @melpon - [ADD] scaleResolutionDownTo に対応する - @melpon +- [ADD] SoraClientContext にオーディオデバイスの設定するオプションを追加 + - @melpon +- [ADD] sumomo にビデオデバイスとオーディオデバイスを設定するオプションを追加 + - @melpon - [FIX] HTTP Proxy 利用時の Websocket 初期化で insecure_ メンバ変数が初期化されていなかったのを修正 - @melpon - [FIX] SoraSignalingConfig の client_cert と client_key に渡す必要がある値を、ファイルパスからファイルの内容に修正 diff --git a/examples/sumomo/src/sumomo.cpp b/examples/sumomo/src/sumomo.cpp index 213e3b56..69442dbe 100644 --- a/examples/sumomo/src/sumomo.cpp +++ b/examples/sumomo/src/sumomo.cpp @@ -27,6 +27,7 @@ struct SumomoConfig { std::string client_id; bool video = true; bool audio = true; + std::string video_device; std::string video_codec_type; std::string audio_codec_type; std::string resolution = "VGA"; @@ -108,6 +109,7 @@ class Sumomo : public std::enable_shared_from_this, cam_config.height = size.height; cam_config.fps = 30; cam_config.use_native = config_.hw_mjpeg_decoder; + cam_config.device_name = config_.video_device; auto video_source = sora::CreateCameraDeviceCapturer(cam_config); if (video_source == nullptr) { RTC_LOG(LS_ERROR) << "Failed to create video source."; @@ -381,6 +383,7 @@ int main(int argc, char* argv[]) { app.add_option("--client-id", config.client_id, "Client ID"); app.add_option("--video", config.video, "Send video to sora (default: true)"); app.add_option("--audio", config.audio, "Send audio to sora (default: true)"); + app.add_option("--video-device", config.video_device, "Video device name"); app.add_option("--video-codec-type", config.video_codec_type, "Video codec for send") ->check(CLI::IsMember({"", "VP8", "VP9", "AV1", "H264", "H265"})); @@ -436,11 +439,20 @@ int main(int argc, char* argv[]) { // 証明書に関するオプション app.add_flag("--insecure", config.insecure, "Allow insecure connection"); - app.add_option("--client-cert", config.client_cert, "Client certificate file")->check(CLI::ExistingFile); - app.add_option("--client-key", config.client_key, "Client key file")->check(CLI::ExistingFile); - app.add_option("--ca-cert", config.ca_cert, "CA certificate file")->check(CLI::ExistingFile); + app.add_option("--client-cert", config.client_cert, "Client certificate file") + ->check(CLI::ExistingFile); + app.add_option("--client-key", config.client_key, "Client key file") + ->check(CLI::ExistingFile); + app.add_option("--ca-cert", config.ca_cert, "CA certificate file") + ->check(CLI::ExistingFile); // SoraClientContextConfig に関するオプション + std::string audio_recording_device; + app.add_option("--audio-recording-device", audio_recording_device, + "Recording device name"); + std::string audio_playout_device; + app.add_option("--audio-playout-device", audio_playout_device, + "Playout device name"); std::optional use_hardware_encoder; add_optional_bool(app, "--use-hardware-encoder", use_hardware_encoder, "Use hardware encoder"); @@ -473,6 +485,12 @@ int main(int argc, char* argv[]) { } auto context_config = sora::SoraClientContextConfig(); + if (!audio_recording_device.empty()) { + context_config.audio_recording_device = audio_recording_device; + } + if (!audio_playout_device.empty()) { + context_config.audio_playout_device = audio_playout_device; + } if (use_hardware_encoder != std::nullopt) { context_config.use_hardware_encoder = *use_hardware_encoder; } diff --git a/include/sora/sora_client_context.h b/include/sora/sora_client_context.h index bfa2dc3e..d3181894 100644 --- a/include/sora/sora_client_context.h +++ b/include/sora/sora_client_context.h @@ -14,6 +14,10 @@ struct SoraClientContextConfig { // オーディオデバイスを利用するかどうか // false にすると一切オーディオデバイスを掴まなくなる bool use_audio_device = true; + // 録音デバイス名 + std::optional audio_recording_device; + // 再生デバイス名 + std::optional audio_playout_device; // ハードウェアエンコーダ/デコーダを利用するかどうか // false にするとソフトウェアエンコーダ/デコーダのみになる(H.264 は利用できない) bool use_hardware_encoder = true; diff --git a/src/sora_client_context.cpp b/src/sora_client_context.cpp index d91bfc82..64074aba 100644 --- a/src/sora_client_context.cpp +++ b/src/sora_client_context.cpp @@ -65,7 +65,7 @@ std::shared_ptr SoraClientContext::Create( void* env = sora::GetJNIEnv(); - dependencies.adm = c->worker_thread_->BlockingCall([&] { + auto adm = c->worker_thread_->BlockingCall([&] { sora::AudioDeviceModuleConfig config; if (!c->config_.use_audio_device) { config.audio_layer = webrtc::AudioDeviceModule::kDummyAudio; @@ -78,6 +78,7 @@ std::shared_ptr SoraClientContext::Create( } return sora::CreateAudioDeviceModule(config); }); + dependencies.adm = adm; dependencies.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory(); @@ -133,6 +134,126 @@ std::shared_ptr SoraClientContext::Create( factory_options.crypto_options.srtp.enable_gcm_crypto_suites = true; c->factory_->SetOptions(factory_options); + // オーディオデバイス名を列挙して名前を覚える + std::vector> recording_devices; + std::vector> playout_devices; + { + int recording_device_count = adm->RecordingDevices(); + recording_devices.resize(recording_device_count); + for (int i = 0; i < recording_device_count; i++) { + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; + if (adm->SetRecordingDevice(i) != 0) { + RTC_LOG(LS_WARNING) << "Failed to SetRecordingDevice: index=" << i; + continue; + } + bool available = false; + if (adm->RecordingIsAvailable(&available) != 0) { + RTC_LOG(LS_WARNING) << "Failed to RecordingIsAvailable: index=" << i; + continue; + } + + if (!available) { + continue; + } + if (adm->RecordingDeviceName(i, name, guid) != 0) { + RTC_LOG(LS_WARNING) << "Failed to RecordingDeviceName: index=" << i; + continue; + } + RTC_LOG(LS_INFO) << "RecordingDevice: index=" << i << " name=" << name + << " guid=" << guid; + std::get<0>(recording_devices[i]) = name; + std::get<1>(recording_devices[i]) = guid; + } + adm->SetRecordingDevice(0); + + int playout_device_count = adm->PlayoutDevices(); + playout_devices.resize(playout_device_count); + for (int i = 0; i < playout_device_count; i++) { + char name[webrtc::kAdmMaxDeviceNameSize]; + char guid[webrtc::kAdmMaxGuidSize]; + if (adm->SetPlayoutDevice(i) != 0) { + RTC_LOG(LS_WARNING) << "Failed to SetPlayoutDevice: index=" << i; + continue; + } + bool available = false; + if (adm->PlayoutIsAvailable(&available) != 0) { + RTC_LOG(LS_WARNING) << "Failed to PlayoutIsAvailable: index=" << i; + continue; + } + + if (!available) { + continue; + } + if (adm->PlayoutDeviceName(i, name, guid) != 0) { + RTC_LOG(LS_WARNING) << "Failed to PlayoutDeviceName: index=" << i; + continue; + } + RTC_LOG(LS_INFO) << "PlayoutDevice: index=" << i << " name=" << name + << " guid=" << guid; + std::get<0>(playout_devices[i]) = name; + std::get<1>(playout_devices[i]) = guid; + } + adm->SetPlayoutDevice(0); + } + + // オーディオデバイスを設定する + if (c->config_.audio_recording_device) { + int index = -1; + for (int i = 0; i < recording_devices.size(); i++) { + const auto& name = std::get<0>(recording_devices[i]); + const auto& guid = std::get<1>(recording_devices[i]); + if (*c->config_.audio_recording_device == name || + *c->config_.audio_recording_device == guid) { + index = i; + break; + } + } + if (index == -1) { + RTC_LOG(LS_ERROR) << "No recording device found: name=" + << *c->config_.audio_recording_device; + return nullptr; + } + + const auto& name = std::get<0>(recording_devices[index]); + const auto& guid = std::get<1>(recording_devices[index]); + if (adm->SetRecordingDevice(index) == 0) { + RTC_LOG(LS_INFO) << "Succeeded SetRecordingDevice: index=" << index + << " name=" << name << " name=" << guid; + } else { + RTC_LOG(LS_ERROR) << "Failed to SetRecordingDevice: index=" << index + << " name=" << name << " guid=" << guid; + } + } + + if (c->config_.audio_playout_device) { + int index = -1; + for (int i = 0; i < playout_devices.size(); i++) { + const auto& name = std::get<0>(playout_devices[i]); + const auto& guid = std::get<1>(playout_devices[i]); + if (*c->config_.audio_playout_device == name || + *c->config_.audio_playout_device == guid) { + index = i; + break; + } + } + if (index == -1) { + RTC_LOG(LS_ERROR) << "No playout device found: name=" + << *c->config_.audio_playout_device; + return nullptr; + } + + const auto& name = std::get<0>(playout_devices[index]); + const auto& guid = std::get<1>(playout_devices[index]); + if (adm->SetPlayoutDevice(index) == 0) { + RTC_LOG(LS_INFO) << "Succeeded SetPlayoutDevice: index=" << index + << " name=" << name << " guid=" << guid; + } else { + RTC_LOG(LS_ERROR) << "Failed to SetPlayoutDevice: index=" << index + << " name=" << name << " guid=" << guid; + } + } + return c; }