diff --git a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt index 02151ab5..d1341a4e 100644 --- a/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt +++ b/webrtc-jni/src/main/cpp/dependencies/webrtc/CMakeLists.txt @@ -228,7 +228,15 @@ elseif(LINUX) target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_LINUX WEBRTC_POSIX WEBRTC_USE_H264 WEBRTC_USE_X11 WEBRTC_USE_PIPEWIRE WEBRTC_USE_GIO) target_link_libraries(${PROJECT_NAME} X11 Xext Xfixes Xdamage Xtst Xrandr Xcomposite dbus-1 ${GIO_LIBRARIES} ${GBM_LIBRARIES} ${DRM_LIBRARIES}) elseif(WIN32) - target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN WEBRTC_USE_H264 NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG) + # RTC_ENABLE_WIN_WGC must match the gn build: webrtc.lib is compiled with gn's + # default rtc_enable_win_wgc=true (webrtc.gni: "rtc_enable_win_wgc = is_win"), + # and DesktopCaptureOptions has members guarded by that define. Compiling the + # JNI wrapper without it changes the class layout and size (64 vs 80 bytes as + # of branch-heads/7977) — the out-of-line CreateDefault()/copy constructor in + # the lib then overflow the wrapper's smaller stack slot and every member + # after the guarded block is read at wrong offsets, silently breaking desktop + # capture (same ABI bug WEBRTC_USE_X11 fixed on Linux). + target_compile_definitions(${PROJECT_NAME} PUBLIC WEBRTC_WIN WEBRTC_USE_H264 NOMINMAX WIN32_LEAN_AND_MEAN NDEBUG RTC_ENABLE_WIN_WGC) target_link_libraries(${PROJECT_NAME} D3D11 DXGI user32 gdi32 iphlpapi dmoguids msdmo secur32 strmiids winmm wmcodecdspuuid ws2_32) endif() diff --git a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp b/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp index 2b93a3aa..75a35f02 100644 --- a/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp +++ b/webrtc-jni/src/main/cpp/src/media/video/VideoTrackDesktopSource.cpp @@ -194,7 +194,13 @@ namespace jni buffer->MutableDataU(), buffer->StrideU(), buffer->MutableDataV(), buffer->StrideV(), crop_x, crop_y, - frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, buffer->height(), crop_w, crop_h, + // (src_width, src_height) must describe the FULL source frame, not the cropped + // output. Passing buffer->height() (== crop_h) here made libyuv's internal + // bounds check (crop_y + crop_height <= src_height) fail with -1 whenever + // crop_y > 0 — i.e. for every maximized window, whose frame sits at + // top_left().y() == -border. Screen frames never hit this branch (exact stride, + // fullscreen == true), which is why only window capture appeared broken. + frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, height, crop_w, crop_h, libyuv::kRotate0, libyuv::FOURCC_ARGB); diff --git a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp index 46b8d6d2..ac29ddb5 100644 --- a/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp +++ b/webrtc-jni/src/main/cpp/src/media/video/desktop/DesktopCaptureCallback.cpp @@ -44,6 +44,11 @@ namespace jni JNIEnv * env = AttachCurrentThread(); if (result != webrtc::DesktopCapturer::Result::SUCCESS) { + // Propagate the failure to Java instead of silently dropping it — + // callers waiting for a frame otherwise have to rely on timeouts. + auto jerror = JavaEnums::toJava(env, result); + env->CallVoidMethod(callback, javaClass->onCaptureResult, jerror.get(), nullptr); + ExceptionCheck(env); return; } @@ -83,7 +88,13 @@ namespace jni i420Buffer->MutableDataU(), i420Buffer->StrideU(), i420Buffer->MutableDataV(), i420Buffer->StrideV(), crop_x, crop_y, - frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, i420Buffer->height(), crop_w, crop_h, + // (src_width, src_height) must describe the FULL source frame, not the cropped + // output. Passing i420Buffer->height() (== crop_h) here made libyuv's internal + // bounds check (crop_y + crop_height <= src_height) fail with -1 whenever + // crop_y > 0 — i.e. for every maximized window, whose frame sits at + // top_left().y() == -border. Screen frames never hit this branch (exact stride, + // fullscreen == true), which is why only window capture appeared broken. + frame->stride() / webrtc::DesktopFrame::kBytesPerPixel, height, crop_w, crop_h, libyuv::kRotate0, libyuv::FOURCC_ARGB);