Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,18 @@ set_target_properties(libc++abi PROPERTIES IMPORTED_OBJECTS_DEBUG "${libc++abi_o
# M114: branch-heads/5735
set(WEBRTC_REVISION branch-heads/5735)

file(STRINGS nix.gni NIX_GN_GEN_ARGS)
# nix.gni is generated by the Nix shell hook (shell.nix) with platform-specific
# GN args like clang_base_path and mac_sdk_path. For non-Nix builds, create an
# empty file or one with: is_clang=true\nuse_lld=false\nclang_use_chrome_plugins=false
if(EXISTS "${CMAKE_SOURCE_DIR}/nix.gni")
file(STRINGS nix.gni NIX_GN_GEN_ARGS)
else()
set(NIX_GN_GEN_ARGS
"is_clang=true"
"use_lld=false"
"clang_use_chrome_plugins=false"
)
endif()
list(APPEND GN_GEN_ARGS
rtc_build_examples=false
rtc_use_x11=false
Expand Down Expand Up @@ -261,6 +272,7 @@ else()
${libwebrtc_binary_dir}/obj/api/video_codecs/libbuiltin_video_encoder_factory.a
${libwebrtc_binary_dir}/obj/api/video_codecs/libbuiltin_video_decoder_factory.a
${libwebrtc_binary_dir}/obj/media/librtc_internal_video_codecs.a
${libwebrtc_binary_dir}/obj/media/librtc_simulcast_encoder_adapter.a
)
endif()

Expand All @@ -277,6 +289,7 @@ ExternalProject_Add(
BUILD_BYPRODUCTS ${byproducts}

DOWNLOAD_COMMAND ${CMAKE_COMMAND} -E env DEPOT_TOOLS=${depot_tools_install_dir} PLATFORM=${PLATFORM} WEBRTC_REVISION=${WEBRTC_REVISION} ${CMAKE_SOURCE_DIR}/scripts/download-webrtc.${suffix}
PATCH_COMMAND ${CMAKE_SOURCE_DIR}/scripts/patch-webrtc.sh <SOURCE_DIR> ${CMAKE_SOURCE_DIR}/patches
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not crazy about having to patch, but there are some other patches I've had to apply on Windows, so overall this functionality is OK, so long as it stays minimal.

CONFIGURE_COMMAND ${CMAKE_COMMAND} -E env BINARY_DIR=<BINARY_DIR> DEPOT_TOOLS=${depot_tools_install_dir} GN_GEN_ARGS=${GN_GEN_ARGS} SOURCE_DIR=<SOURCE_DIR> ${CMAKE_SOURCE_DIR}/scripts/configure-webrtc.${suffix}
BUILD_COMMAND ${CMAKE_COMMAND} -E env CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} DEPOT_TOOLS=${depot_tools_install_dir} ${CMAKE_SOURCE_DIR}/scripts/build-webrtc.${suffix}
INSTALL_COMMAND ""
Expand Down Expand Up @@ -321,6 +334,10 @@ add_library(librtc_internal_video_codecs STATIC IMPORTED)
add_dependencies(librtc_internal_video_codecs project_libwebrtc)
set_property(TARGET librtc_internal_video_codecs PROPERTY IMPORTED_LOCATION "${libwebrtc_binary_dir}/obj/media/librtc_internal_video_codecs.a")

add_library(librtc_simulcast_encoder_adapter STATIC IMPORTED)
add_dependencies(librtc_simulcast_encoder_adapter project_libwebrtc)
set_property(TARGET librtc_simulcast_encoder_adapter PROPERTY IMPORTED_LOCATION "${libwebrtc_binary_dir}/obj/media/librtc_simulcast_encoder_adapter.a")

set(libc++_include_dir
"${libwebrtc_source_dir}/src/buildtools/third_party/libc++/trunk/include"
"${libwebrtc_source_dir}/src/buildtools/third_party/libc++"
Expand Down Expand Up @@ -403,6 +420,7 @@ target_link_libraries(${MODULE} PRIVATE
libbuiltin_video_encoder_factory
libbuiltin_video_decoder_factory
librtc_internal_video_codecs
librtc_simulcast_encoder_adapter
${CMAKE_JS_LIB}
)

Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
"patch-package": "^8.0.0",
"prettier": "^3.4.2",
"recursive-copy": "^2.0.14",
"simple-peer": "~9.7.0",
"tape": "^5.6.1",
"temp": "^0.9.4"
},
Expand Down
14 changes: 14 additions & 0 deletions patches/webrtc-macos26-sdk.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--- a/modules/desktop_capture/mac/screen_capturer_mac.mm
+++ b/modules/desktop_capture/mac/screen_capturer_mac.mm
@@ -24,6 +24,11 @@
// These have the correct annotation. See https://crbug.com/1431897.
// TODO(thakis): Remove this once FB12109479 is fixed and we updated to an SDK
// with the fix.
+// NOTE: CG_AVAILABLE_BUT_DEPRECATED was removed in macOS 26 SDK.
+#ifndef CG_AVAILABLE_BUT_DEPRECATED
+#define CG_AVAILABLE_BUT_DEPRECATED(from, to, ...) \
+ API_DEPRECATED(__VA_ARGS__, macos(from, to))
+#endif

static CGDisplayStreamRef __nullable
wrapCGDisplayStreamCreate(CGDirectDisplayID display,
2 changes: 1 addition & 1 deletion scripts/build-webrtc.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ set -v
# We want to use system ninja, _NOT_ depot_tools ninja, actually
export PATH="${DEPOT_TOOLS}/python-bin:${PATH}:${DEPOT_TOOLS}"

export TARGETS="webrtc libjingle_peerconnection libc++ libc++abi builtin_video_encoder_factory builtin_video_decoder_factory rtc_internal_video_codecs"
export TARGETS="webrtc libjingle_peerconnection libc++ libc++abi builtin_video_encoder_factory builtin_video_decoder_factory rtc_internal_video_codecs rtc_simulcast_encoder_adapter"

ninja $TARGETS
17 changes: 17 additions & 0 deletions scripts/patch-webrtc.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
# Apply patches to the downloaded WebRTC source.
# Skips patches that have already been applied (idempotent).
set -e

SOURCE_DIR="$1"
PATCHES_DIR="$2"

for patch in "$PATCHES_DIR"/webrtc-*.patch; do
[ -f "$patch" ] || continue
if git -C "$SOURCE_DIR" apply --check "$patch" 2>/dev/null; then
echo "Applying patch: $(basename "$patch")"
git -C "$SOURCE_DIR" apply "$patch"
else
echo "Skipping already-applied patch: $(basename "$patch")"
fi
done
19 changes: 17 additions & 2 deletions src/interfaces/rtc_data_channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ DataChannelObserver::DataChannelObserver(
PeerConnectionFactory *factory,
rtc::scoped_refptr<webrtc::DataChannelInterface> jingleDataChannel)
: _factory(factory), _jingleDataChannel(std::move(jingleDataChannel)) {
_jingleDataChannel->RegisterObserver(this);
// Don't register here. Registration happens in RTCDataChannel's constructor,
// which avoids a double RegisterObserver that causes message loss through
// M114's ObserverAdapter signaling thread relay.
}

void DataChannelObserver::OnStateChange() {
Expand Down Expand Up @@ -72,9 +74,20 @@ RTCDataChannel::RTCDataChannel(const Napi::CallbackInfo &info)
_jingleDataChannel = observer->_jingleDataChannel;
_jingleDataChannel->RegisterObserver(this);

// Re-queue cached observer events
// Re-queue any cached observer events (from the window between
// OnDataChannel and this constructor).
requeue(*observer, *this);

// If the channel already transitioned to open before we registered,
// dispatch the open event so JS onopen handlers fire.
auto state = _jingleDataChannel->state();
if (state == webrtc::DataChannelInterface::kOpen) {
Dispatch(
Callback1<RTCDataChannel>::Create([state](RTCDataChannel &channel) {
RTCDataChannel::HandleStateChange(channel, state);
}));
}

delete observer;

// NOTE(mroberts): These doesn't actually matter yet.
Expand Down Expand Up @@ -106,6 +119,8 @@ void RTCDataChannel::CleanupInternals() {

void RTCDataChannel::OnPeerConnectionClosed() {
if (_jingleDataChannel != nullptr) {
CleanupInternals();
HandleStateChange(*this, webrtc::DataChannelInterface::kClosed);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-added Stop(), seems important 😄

Stop();
}
}
Expand Down
18 changes: 11 additions & 7 deletions src/interfaces/rtc_peer_connection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -777,10 +777,16 @@ Napi::Value RTCPeerConnection::Close(const Napi::CallbackInfo &info) {
if (_jinglePeerConnection) {
_cached_configuration = ExtendedRTCConfiguration(
_jinglePeerConnection->GetConfiguration(), _port_range);
_jinglePeerConnection->Close();
// NOTE(mroberts): Perhaps another way to do this is to just register all
// remote MediaStreamTracks against this RTCPeerConnection, not unlike what
// we do with RTCDataChannels.

// Fire all JS close events proactively, matching Chrome/Blink's approach.
// Blink dispatches events synchronously during RTCPeerConnection.close()
// rather than relying on the C++ observer callback path. This is necessary
// because PeerConnection::Close() calls PrepareForShutdown() which
// deactivates the SafeTask safety flag, silently cancelling any pending
// async callbacks from the network thread.
for (auto channel : _channels) {
channel->OnPeerConnectionClosed();
}
if (_jinglePeerConnection->GetConfiguration().sdp_semantics ==
webrtc::SdpSemantics::kUnifiedPlan) {
for (const auto &transceiver : _jinglePeerConnection->GetTransceivers()) {
Expand All @@ -789,9 +795,7 @@ Napi::Value RTCPeerConnection::Close(const Napi::CallbackInfo &info) {
track->OnPeerConnectionClosed();
}
}
for (auto channel : _channels) {
channel->OnPeerConnectionClosed();
}
_jinglePeerConnection->Close();
}

// Clear the wrap caches before releasing the WebRTC peer connection.
Expand Down
24 changes: 19 additions & 5 deletions src/interfaces/rtc_peer_connection/peer_connection_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,22 @@ PeerConnectionFactory::PeerConnectionFactory(const Napi::CallbackInfo &info)
// TODO(mroberts): Read `audioLayer` from some PeerConnectionFactoryOptions?
auto audioLayer = MakeNothing<webrtc::AudioDeviceModule::AudioLayer>();

_workerThread = rtc::Thread::CreateWithSocketServer();
assert(_workerThread);
_networkThread = rtc::Thread::CreateWithSocketServer();
assert(_networkThread);

bool result =
_networkThread->SetName("PeerConnectionFactory:networkThread", nullptr);
assert(result);
(void)result;

result = _networkThread->Start();
assert(result);
(void)result;

_workerThread = rtc::Thread::Create();
assert(_workerThread);

result =
_workerThread->SetName("PeerConnectionFactory:workerThread", nullptr);
assert(result);
(void)result;
Expand Down Expand Up @@ -93,7 +105,7 @@ PeerConnectionFactory::PeerConnectionFactory(const Napi::CallbackInfo &info)
(void)result;

_factory = webrtc::CreatePeerConnectionFactory(
_workerThread.get(), _workerThread.get(), _signalingThread.get(),
_networkThread.get(), _workerThread.get(), _signalingThread.get(),
_audioDeviceModule, webrtc::CreateBuiltinAudioEncoderFactory(),
webrtc::CreateBuiltinAudioDecoderFactory(),
webrtc::CreateBuiltinVideoEncoderFactory(),
Expand All @@ -105,11 +117,11 @@ PeerConnectionFactory::PeerConnectionFactory(const Napi::CallbackInfo &info)
_factory->SetOptions(options);

_networkManager = std::unique_ptr<rtc::NetworkManager>(
new rtc::BasicNetworkManager(_workerThread->socketserver()));
new rtc::BasicNetworkManager(_networkThread->socketserver()));
assert(_networkManager != nullptr);

_socketFactory = std::unique_ptr<rtc::PacketSocketFactory>(
new rtc::BasicPacketSocketFactory(_workerThread->socketserver()));
new rtc::BasicPacketSocketFactory(_networkThread->socketserver()));
assert(_socketFactory != nullptr);
}

Expand All @@ -118,9 +130,11 @@ PeerConnectionFactory::~PeerConnectionFactory() {

_workerThread->BlockingCall([this]() { this->_audioDeviceModule = nullptr; });

_networkThread->Stop();
_workerThread->Stop();
_signalingThread->Stop();

_networkThread = nullptr;
_workerThread = nullptr;
_signalingThread = nullptr;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ public:
static void Dispose();

private:
std::unique_ptr<rtc::Thread> _networkThread;
std::unique_ptr<rtc::Thread> _signalingThread;
std::unique_ptr<rtc::Thread> _workerThread;

Expand Down
2 changes: 2 additions & 0 deletions src/node/error_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ node_webrtc::ErrorFactory::DOMExceptionNameToString(DOMExceptionName name) {
return "NetworkError";
case kOperationError:
return "OperationError";
default:
return "UnknownError";
}
}

Expand Down
Loading