feat: upgrade libwebrtc to m150. - #1284
Conversation
Changeset ✓This PR includes a changeset covering all affected packages:
|
The webrtc::I420ToARGB etc. symbols from api/video/yuv_helper.h were not present in the webrtc.lib for aarch64-pc-windows-msvc, causing 22 linker errors. Replace the webrtc:: namespace wrappers with direct libyuv:: calls using third_party/libyuv/include/libyuv.h, which is already in the include path and whose symbols are always compiled into webrtc.lib. Also removes the erroneous duplicate i420_to_nv12 overload that incorrectly called NV12ToI420 instead of I420ToNV12.
|
|
…nker errors The pre-built libwebrtc.a at webrtc-a970b87 was compiled with use_custom_libcxx=true (Chromium's libc++ with ABI namespace std::__Cr::), making it ABI-incompatible with GCC/libstdc++ (std::__cxx11:: / std::). Every linker error in CI was caused by this mismatch, e.g.: SdpVideoFormat(std::__Cr::basic_string const&) [in library] SdpVideoFormat(std::__cxx11::basic_string const&) [called by our code] Revert to use_custom_libcxx=false so the library links with the system libstdc++, matching the GCC compilation used by our SDK build. The library must be rebuilt at a new webrtc-* tag for this fix to take effect in CI. After the rebuild, update WEBRTC_TAG in build/src/lib.rs.
024a137 to
bf52ad6
Compare
e1df4fe to
309c4b3
Compare
Removed unnecessary patches and comments related to GCC toolchain and Abseil.
| + GetClass(env, "livekit/livekit/org/webrtc/HardwareVideoEncoderFactory"); | ||
| jmethodID factory_constructor = env->GetMethodID( | ||
| - factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V"); | ||
| + factory_class.obj(), "<init>", "(Llivekit/org/webrtc/EglBase$Context;ZZ)V"); | ||
| + factory_class.obj(), "<init>", "(Llivekit/livekit/org/webrtc/EglBase$Context;ZZ)V"); |
There was a problem hiding this comment.
🟡 Android helper looks up a Java class under a doubled package name
The hardware encoder factory class name is written with the vendor prefix twice ("livekit/livekit/org/webrtc/HardwareVideoEncoderFactory" at webrtc-sys/libwebrtc/patches/jni_prefix.patch:10-13) while every other renamed class uses the prefix once, so any code path that goes through it cannot find the class.
Impact: If that helper is ever built, creating the Android hardware encoder factory fails at runtime with a class-not-found error.
Inconsistent prefixing within the same patch
In the same patched file, the decoder counterpart is correctly rewritten to livekit/org/webrtc/HardwareVideoDecoderFactory and Llivekit/org/webrtc/EglBase$Context; (see the following hunk in webrtc-sys/libwebrtc/patches/jni_prefix.patch), and the runtime prefix configured in webrtc.gni is a single livekit. The affected file is modules/video_coding/codecs/test/android_codec_factory_helper.cc, which is excluded from the shipped build (rtc_include_tests=false in webrtc-sys/libwebrtc/build_android.sh:104), which is why it is only latent today.
| + GetClass(env, "livekit/livekit/org/webrtc/HardwareVideoEncoderFactory"); | |
| jmethodID factory_constructor = env->GetMethodID( | |
| - factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V"); | |
| + factory_class.obj(), "<init>", "(Llivekit/org/webrtc/EglBase$Context;ZZ)V"); | |
| + factory_class.obj(), "<init>", "(Llivekit/livekit/org/webrtc/EglBase$Context;ZZ)V"); | |
| + GetClass(env, "livekit/org/webrtc/HardwareVideoEncoderFactory"); | |
| jmethodID factory_constructor = env->GetMethodID( | |
| - factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V"); | |
| + factory_class.obj(), "<init>", "(Llivekit/org/webrtc/EglBase$Context;ZZ)V"); |
Was this helpful? React with 👍 or 👎 to provide feedback.
| { | ||
| "name": 'src', | ||
| "url": 'https://github.com/webrtc-sdk/webrtc.git@m144_release', | ||
| "url": 'https://github.com/webrtc-sdk/webrtc.git@duan/m150-patching', |
There was a problem hiding this comment.
🟡 Native library source is pinned to a personal working branch instead of a stable release
The upstream WebRTC checkout now points at a personal, moving development branch (duan/m150-patching at webrtc-sys/libwebrtc/.gclient:4) rather than a fixed release tag, so what gets built changes whenever that branch is updated or deleted.
Impact: Builds are no longer reproducible and can silently change or start failing without any change in this repository.
Comparison with previous pinning
The previous value was m144_release, a stable release branch of webrtc-sdk/webrtc. All the new patches in webrtc-sys/libwebrtc/patches/ are written against the m150 tree, so they can break the moment the personal branch is rebased. Consider pinning to an m150_release branch/tag or an explicit commit hash before merging.
Was this helpful? React with 👍 or 👎 to provide feedback.
| use_llvm_libatomic=false \ | ||
| use_custom_libcxx=false \ | ||
| use_custom_libcxx_for_host=false \ | ||
| is_clang=false \ |
There was a problem hiding this comment.
does this is_clang change from clang to gcc ?
I remember that it caused quite a lot of issues last time when we did the change
| @@ -389,8 +394,10 @@ void AudioSendStream::Stop() { | ||
| RTC_LOG(LS_INFO) << "AudioSendStream::Stop: " << config_.rtp.ssrc; | ||
| RemoveBitrateObserver(); | ||
| channel_send_->StopSend(); | ||
| sending_ = false; | ||
| - sending_ = false; | ||
| - audio_state()->RemoveSendingStream(this); | ||
| + // Only unregister if we registered (when not using external source). | ||
| + if (!config_.external_source) { |
There was a problem hiding this comment.
🔴 Audio publishing cannot be resumed after being stopped
The internal "currently sending" flag is no longer cleared when an audio stream is stopped (the sending_ = false; line removed from AudioSendStream::Stop() in webrtc-sys/libwebrtc/patches/external_audio_source.patch:41), so a later attempt to start the same audio stream is silently ignored.
Impact: After a publisher stops (e.g. mutes/unpublishes) an audio track, restarting it produces no audio.
How the regenerated m150 patch drops the state reset in AudioSendStream::Stop()
The m144 version of this patch kept sending_ = false; as a context line and only wrapped audio_state()->RemoveSendingStream(this) in the external_source check. In the regenerated m150 hunk the line is prefixed with -, so the resulting Stop() becomes:
RemoveBitrateObserver();
channel_send_->StopSend();
// Only unregister if we registered (when not using external source).
if (!config_.external_source) {
audio_state()->RemoveSendingStream(this);
}
Upstream AudioSendStream::Start() begins with an early return when sending_ is already true, and Stop() also early-returns when sending_ is false. With sending_ stuck at true, Start() never calls channel_send_->StartSend() again and AddSendingStream() is never re-registered. The hunk line counts (@@ -389,8 +394,10 @@) match the deletion, so git apply will succeed and the regression is silent.
(Refers to lines 37-46)
Was this helpful? React with 👍 or 👎 to provide feedback.
| __attribute__((weak)) size_t __hash_memory(void const* p, size_t n) noexcept { | ||
| auto const* ptr = static_cast<unsigned char const*>(p); | ||
| #if defined(__LP64__) | ||
| // 64-bit FNV-1a | ||
| size_t hash = 14695981039346656037ULL; | ||
| for (size_t i = 0; i < n; ++i) { | ||
| hash ^= static_cast<size_t>(ptr[i]); | ||
| hash *= 1099511628211ULL; | ||
| } | ||
| #else | ||
| // 32-bit FNV-1a | ||
| size_t hash = 2166136261U; | ||
| for (size_t i = 0; i < n; ++i) { | ||
| hash ^= static_cast<size_t>(ptr[i]); | ||
| hash *= 16777619U; | ||
| } | ||
| #endif | ||
| return hash; | ||
| } |
There was a problem hiding this comment.
🟡 Hash-value shim on Android can make lookups in shared hash tables fail
The fallback memory-hash routine added for Android (__hash_memory at webrtc-sys/src/ndk_compat.cpp:37-55) computes FNV-1a instead of the algorithm the C++ standard library actually uses, so identical keys can hash differently in different parts of the same program.
Impact: On Android, hash-table lookups for keys stored by one half of the library and looked up by the other can silently miss, causing lost or wrong data.
Algorithm mismatch between the weak stub and libc++'s real __hash_memory
libc++ implements std::__hash_memory(const void*, size_t) as __murmur2_or_cityhash<size_t>()(ptr, size) (see src/hash.cpp in LLVM libc++), not FNV-1a; the comment at webrtc-sys/src/ndk_compat.cpp:28-29 claiming FNV-1a is "the same ... algorithm that LLVM libc++ historically used" is incorrect.
The shim is only actually linked in the scenario the file describes: the newer NDK marks __hash_memory _LIBCPP_HIDE_FROM_ABI, so newly compiled webrtc-sys translation units inline the real murmur/cityhash implementation, while the prebuilt libwebrtc.a keeps its out-of-line call, which now resolves to this weak FNV-1a definition. Any std::unordered_map/unordered_set with string (or other memory-hashed) keys whose insertions and lookups are split across that boundary will compute two different hash values for the same key, producing spurious lookup failures rather than a link error.
A safe stub would delegate to a hash computed by the same header-inlined implementation (e.g. call std::hash<std::string_view>{}(...)) so both sides agree.
Prompt for agents
The weak fallback for std::__ndk1::__hash_memory in webrtc-sys/src/ndk_compat.cpp implements FNV-1a, but libc++'s real __hash_memory is __murmur2_or_cityhash. When this weak definition is actually used (prebuilt libwebrtc.a calling out-of-line while newly compiled code inlines the hidden-from-ABI version), the same key can hash to two different values in one process, breaking unordered container lookups that cross the boundary. Fix by making the stub delegate to the header-inlined libc++ hashing path so both sides agree (for example forwarding to std::hash<std::string_view> over the same bytes), and correct the misleading comment about FNV-1a.
Was this helpful? React with 👍 or 👎 to provide feedback.
| { | ||
| "name": 'src', | ||
| "url": 'https://github.com/webrtc-sdk/webrtc.git@m144_release', | ||
| "url": 'https://github.com/webrtc-sdk/webrtc.git@duan/m150-patching', |
There was a problem hiding this comment.
🟨 WebRTC source pulled from a mutable personal branch (supply-chain risk)
webrtc-sys/libwebrtc/.gclient:4 now syncs the WebRTC checkout from https://github.com/webrtc-sdk/webrtc.git@duan/m150-patching, a personal topic branch rather than an immutable release branch or pinned commit. Anyone able to push to that branch can alter the native code that gets compiled into every released binary, with no change visible in this repository.
Was this helpful? React with 👍 or 👎 to provide feedback.
No description provided.