Format /modules folder

Formatting done via:

git ls-files | grep -E '^modules\/.*\.(h|cc|mm)' | xargs clang-format -i

No-Iwyu: Includes didn't change and it isn't related to formatting
Bug: webrtc:42225392
Change-Id: I5154c8e290591a6a0599b53802eaf152038c5f47
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/373703
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43677}
This commit is contained in:
Boris Tsirkin 2025-01-07 23:39:20 -08:00 committed by WebRTC LUCI CQ
parent 2becf23acc
commit dadb9f4643
40 changed files with 350 additions and 274 deletions

View File

@ -145,7 +145,7 @@ std::unique_ptr<Packet> AcmSendTestOldApi::CreatePacket() {
packet_memory[0] = 0x80; packet_memory[0] = 0x80;
packet_memory[1] = static_cast<uint8_t>(payload_type_); packet_memory[1] = static_cast<uint8_t>(payload_type_);
packet_memory[2] = (sequence_number_ >> 8) & 0xFF; packet_memory[2] = (sequence_number_ >> 8) & 0xFF;
packet_memory[3] = (sequence_number_)&0xFF; packet_memory[3] = (sequence_number_) & 0xFF;
packet_memory[4] = (timestamp_ >> 24) & 0xFF; packet_memory[4] = (timestamp_ >> 24) & 0xFF;
packet_memory[5] = (timestamp_ >> 16) & 0xFF; packet_memory[5] = (timestamp_ >> 16) & 0xFF;
packet_memory[6] = (timestamp_ >> 8) & 0xFF; packet_memory[6] = (timestamp_ >> 8) & 0xFF;

View File

@ -146,8 +146,7 @@ TEST(BuiltinAudioEncoderFactoryTest, SupportsTheExpectedFormats) {
#endif #endif
{"G722", 8000, 1}, {"G722", 8000, 1},
{"pcmu", 8000, 1}, {"pcmu", 8000, 1},
{"pcma", 8000, 1} {"pcma", 8000, 1}};
};
ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats)); ASSERT_THAT(supported_formats, ElementsAreArray(expected_formats));
} }
@ -164,11 +163,7 @@ TEST(BuiltinAudioEncoderFactoryTest, MaxNrOfChannels) {
#if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX) #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
"isac", "isac",
#endif #endif
"pcmu", "pcmu", "pcma", "l16", "G722", "G711",
"pcma",
"l16",
"G722",
"G711",
}; };
for (auto codec : codecs) { for (auto codec : codecs) {

View File

@ -703,9 +703,9 @@ bool AudioEncoderOpusImpl::RecreateEncoderInstance(
void AudioEncoderOpusImpl::SetFrameLength(int frame_length_ms) { void AudioEncoderOpusImpl::SetFrameLength(int frame_length_ms) {
if (next_frame_length_ms_ != frame_length_ms) { if (next_frame_length_ms_ != frame_length_ms) {
RTC_LOG(LS_VERBOSE) << "Update Opus frame length " RTC_LOG(LS_VERBOSE) << "Update Opus frame length " << "from "
<< "from " << next_frame_length_ms_ << " ms " << next_frame_length_ms_ << " ms " << "to "
<< "to " << frame_length_ms << " ms."; << frame_length_ms << " ms.";
} }
next_frame_length_ms_ = frame_length_ms; next_frame_length_ms_ = frame_length_ms;
} }

View File

@ -35,7 +35,7 @@ void BufferLevelFilter::Update(size_t buffer_size_samples,
// `level_factor_` and `filtered_current_level_` are in Q8. // `level_factor_` and `filtered_current_level_` are in Q8.
// `buffer_size_samples` is in Q0. // `buffer_size_samples` is in Q0.
const int64_t filtered_current_level = const int64_t filtered_current_level =
(level_factor_* int64_t{filtered_current_level_} >> 8) + (level_factor_ * int64_t{filtered_current_level_} >> 8) +
(256 - level_factor_) * rtc::dchecked_cast<int64_t>(buffer_size_samples); (256 - level_factor_) * rtc::dchecked_cast<int64_t>(buffer_size_samples);
// Account for time-scale operations (accelerate and pre-emptive expand) and // Account for time-scale operations (accelerate and pre-emptive expand) and

View File

@ -101,5 +101,4 @@ int DelayManager::TargetDelayMs() const {
return target_level_ms_; return target_level_ms_;
} }
} // namespace webrtc } // namespace webrtc

View File

@ -196,7 +196,6 @@ TEST(PacketBuffer, OverfillBuffer) {
EXPECT_CALL(decoder_database, Die()); // Called when object is deleted. EXPECT_CALL(decoder_database, Die()); // Called when object is deleted.
} }
TEST(PacketBuffer, ExtractOrderRedundancy) { TEST(PacketBuffer, ExtractOrderRedundancy) {
TickTimer tick_timer; TickTimer tick_timer;
StrictMock<MockStatisticsCalculator> mock_stats(&tick_timer); StrictMock<MockStatisticsCalculator> mock_stats(&tick_timer);

View File

@ -28,7 +28,7 @@ void MakeRtpHeader(int payload_type,
rtp_data[0] = 0x80; rtp_data[0] = 0x80;
rtp_data[1] = static_cast<uint8_t>(payload_type); rtp_data[1] = static_cast<uint8_t>(payload_type);
rtp_data[2] = (seq_number >> 8) & 0xFF; rtp_data[2] = (seq_number >> 8) & 0xFF;
rtp_data[3] = (seq_number)&0xFF; rtp_data[3] = (seq_number) & 0xFF;
rtp_data[4] = timestamp >> 24; rtp_data[4] = timestamp >> 24;
rtp_data[5] = (timestamp >> 16) & 0xFF; rtp_data[5] = (timestamp >> 16) & 0xFF;
rtp_data[6] = (timestamp >> 8) & 0xFF; rtp_data[6] = (timestamp >> 8) & 0xFF;

View File

@ -26,6 +26,7 @@
#endif #endif
#elif defined(WEBRTC_ANDROID) #elif defined(WEBRTC_ANDROID)
#include <stdlib.h> #include <stdlib.h>
#include "sdk/android/native_api/audio_device_module/audio_device_android.h" #include "sdk/android/native_api/audio_device_module/audio_device_android.h"
#elif defined(WEBRTC_LINUX) #elif defined(WEBRTC_LINUX)
#if defined(WEBRTC_ENABLE_LINUX_ALSA) #if defined(WEBRTC_ENABLE_LINUX_ALSA)
@ -82,7 +83,8 @@ rtc::scoped_refptr<AudioDeviceModuleForTest> AudioDeviceModule::CreateForTest(
return nullptr; return nullptr;
} else if (audio_layer == AudioDeviceModule::kAndroidJavaAudio || } else if (audio_layer == AudioDeviceModule::kAndroidJavaAudio ||
audio_layer == AudioDeviceModule::kAndroidOpenSLESAudio || audio_layer == AudioDeviceModule::kAndroidOpenSLESAudio ||
audio_layer == AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio || audio_layer ==
AudioDeviceModule::kAndroidJavaInputAndOpenSLESOutputAudio ||
audio_layer == kAndroidAAudioAudio || audio_layer == kAndroidAAudioAudio ||
audio_layer == kAndroidJavaInputAndAAudioOutputAudio) { audio_layer == kAndroidJavaInputAndAAudioOutputAudio) {
RTC_LOG(LS_ERROR) << "Use the CreateAndroidAudioDeviceModule() " RTC_LOG(LS_ERROR) << "Use the CreateAndroidAudioDeviceModule() "

View File

@ -57,8 +57,7 @@ void UpdateAccumulatedError(
} }
} }
size_t ComputePreEchoLag( size_t ComputePreEchoLag(const rtc::ArrayView<const float> accumulated_error,
const rtc::ArrayView<const float> accumulated_error,
size_t lag, size_t lag,
size_t alignment_shift_winner) { size_t alignment_shift_winner) {
static constexpr float kPreEchoThreshold = 0.5f; static constexpr float kPreEchoThreshold = 0.5f;

View File

@ -28,8 +28,7 @@ void Aec3ConfigFromJsonString(absl::string_view json_string,
// Encodes an Aec3 config in JSON format. Fields corresponds to substruct names, // Encodes an Aec3 config in JSON format. Fields corresponds to substruct names,
// with the addition that the top-level node is named "aec3". // with the addition that the top-level node is named "aec3".
std::string Aec3ConfigToJsonString( std::string Aec3ConfigToJsonString(const EchoCanceller3Config& config);
const EchoCanceller3Config& config);
} // namespace webrtc } // namespace webrtc

View File

@ -40,7 +40,7 @@ TEST(EchoCanceller3JsonHelpers, ToStringAndParseJson) {
std::string json_string = Aec3ConfigToJsonString(cfg); std::string json_string = Aec3ConfigToJsonString(cfg);
EchoCanceller3Config cfg_transformed; EchoCanceller3Config cfg_transformed;
bool parsing_successful; bool parsing_successful;
Aec3ConfigFromJsonString(json_string, &cfg_transformed, & parsing_successful); Aec3ConfigFromJsonString(json_string, &cfg_transformed, &parsing_successful);
ASSERT_TRUE(parsing_successful); ASSERT_TRUE(parsing_successful);
// Expect unchanged values to remain default. // Expect unchanged values to remain default.

View File

@ -50,7 +50,9 @@ bool IsValid(Timestamp timestamp) {
return timestamp.IsFinite(); return timestamp.IsFinite();
} }
double ToKiloBytes(DataSize datasize) { return datasize.bytes() / 1000.0; } double ToKiloBytes(DataSize datasize) {
return datasize.bytes() / 1000.0;
}
double GetLossProbability(double inherent_loss, double GetLossProbability(double inherent_loss,
DataRate loss_limited_bandwidth, DataRate loss_limited_bandwidth,
@ -347,8 +349,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
bounded_bandwidth_estimate < max_bitrate_) { bounded_bandwidth_estimate < max_bitrate_) {
if (loss_based_result_.state != LossBasedState::kDecreasing && if (loss_based_result_.state != LossBasedState::kDecreasing &&
config_->hold_duration_factor > 0) { config_->hold_duration_factor > 0) {
RTC_LOG(LS_INFO) << this << " " RTC_LOG(LS_INFO) << this << " " << "Switch to HOLD. Bounded BWE: "
<< "Switch to HOLD. Bounded BWE: "
<< bounded_bandwidth_estimate.kbps() << bounded_bandwidth_estimate.kbps()
<< ", duration: " << last_hold_info_.duration.ms(); << ", duration: " << last_hold_info_.duration.ms();
last_hold_info_ = { last_hold_info_ = {
@ -385,7 +386,8 @@ void LossBasedBweV2::UpdateBandwidthEstimate(
} }
bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited(
DataRate old_estimate, DataRate new_estimate) { DataRate old_estimate,
DataRate new_estimate) {
return (old_estimate < new_estimate || return (old_estimate < new_estimate ||
(old_estimate == new_estimate && (old_estimate == new_estimate &&
(loss_based_result_.state == LossBasedState::kIncreasing || (loss_based_result_.state == LossBasedState::kIncreasing ||

View File

@ -147,7 +147,8 @@ class LossBasedBweV2Test : public ::testing::TestWithParam<bool> {
} }
std::vector<PacketResult> CreatePacketResultsWith100pLossRate( std::vector<PacketResult> CreatePacketResultsWith100pLossRate(
Timestamp first_packet_timestamp, unsigned num_packets = 2) { Timestamp first_packet_timestamp,
unsigned num_packets = 2) {
std::vector<PacketResult> enough_feedback(num_packets); std::vector<PacketResult> enough_feedback(num_packets);
for (unsigned i = 0; i < num_packets - 1; ++i) { for (unsigned i = 0; i < num_packets - 1; ++i) {
enough_feedback[i].sent_packet.sequence_number = enough_feedback[i].sent_packet.sequence_number =

View File

@ -192,7 +192,8 @@ TimeDelta RttBasedBackoff::CorrectedRtt() const {
RttBasedBackoff::~RttBasedBackoff() = default; RttBasedBackoff::~RttBasedBackoff() = default;
SendSideBandwidthEstimation::SendSideBandwidthEstimation( SendSideBandwidthEstimation::SendSideBandwidthEstimation(
const FieldTrialsView* key_value_config, RtcEventLog* event_log) const FieldTrialsView* key_value_config,
RtcEventLog* event_log)
: key_value_config_(key_value_config), : key_value_config_(key_value_config),
rtt_backoff_(key_value_config), rtt_backoff_(key_value_config),
lost_packets_since_last_loss_update_(0), lost_packets_since_last_loss_update_(0),

View File

@ -234,7 +234,6 @@ TEST(DesktopFrameTest, CopyIntersectingPixelsFullyContainedRectsScaled) {
RunTests(tests, arraysize(tests)); RunTests(tests, arraysize(tests));
} }
TEST(DesktopFrameTest, CopyIntersectingPixelsPartiallyContainedRects) { TEST(DesktopFrameTest, CopyIntersectingPixelsPartiallyContainedRects) {
// clang-format off // clang-format off
const TestData tests[] = { const TestData tests[] = {
@ -299,7 +298,6 @@ TEST(DesktopFrameTest, CopyIntersectingPixelsPartiallyContainedRectsScaled) {
RunTests(tests, arraysize(tests)); RunTests(tests, arraysize(tests));
} }
TEST(DesktopFrameTest, CopyIntersectingPixelsUncontainedRects) { TEST(DesktopFrameTest, CopyIntersectingPixelsUncontainedRects) {
// clang-format off // clang-format off
const TestData tests[] = { const TestData tests[] = {

View File

@ -10,9 +10,9 @@
#include "modules/desktop_capture/mac/desktop_configuration.h" #include "modules/desktop_capture/mac/desktop_configuration.h"
#include <Cocoa/Cocoa.h>
#include <math.h> #include <math.h>
#include <algorithm> #include <algorithm>
#include <Cocoa/Cocoa.h>
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
@ -30,12 +30,12 @@ DesktopRect NSRectToDesktopRect(const NSRect& ns_rect) {
// Inverts the position of `rect` from bottom-up coordinates to top-down, // Inverts the position of `rect` from bottom-up coordinates to top-down,
// relative to `bounds`. // relative to `bounds`.
void InvertRectYOrigin(const DesktopRect& bounds, void InvertRectYOrigin(const DesktopRect& bounds, DesktopRect* rect) {
DesktopRect* rect) {
RTC_DCHECK_EQ(bounds.top(), 0); RTC_DCHECK_EQ(bounds.top(), 0);
*rect = DesktopRect::MakeXYWH( *rect = DesktopRect::MakeXYWH(rect->left(),
rect->left(), bounds.bottom() - rect->bottom(), bounds.bottom() - rect->bottom(),
rect->width(), rect->height()); rect->width(),
rect->height());
} }
MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) {
@ -97,7 +97,7 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) {
// DPI match that of the primary monitor. // DPI match that of the primary monitor.
for (NSUInteger i = 0; i < [screens count]; ++i) { for (NSUInteger i = 0; i < [screens count]; ++i) {
MacDisplayConfiguration display_config = MacDisplayConfiguration display_config =
GetConfigurationForScreen([screens objectAtIndex: i]); GetConfigurationForScreen([screens objectAtIndex:i]);
if (i == 0) if (i == 0)
desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale; desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale;
@ -139,8 +139,7 @@ MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) {
// MacDesktopConfiguration::Equals. // MacDesktopConfiguration::Equals.
bool operator==(const MacDisplayConfiguration& left, bool operator==(const MacDisplayConfiguration& left,
const MacDisplayConfiguration& right) { const MacDisplayConfiguration& right) {
return left.id == right.id && return left.id == right.id && left.bounds.equals(right.bounds) &&
left.bounds.equals(right.bounds) &&
left.pixel_bounds.equals(right.pixel_bounds) && left.pixel_bounds.equals(right.pixel_bounds) &&
left.dip_to_pixel_scale == right.dip_to_pixel_scale; left.dip_to_pixel_scale == right.dip_to_pixel_scale;
} }
@ -153,18 +152,20 @@ bool MacDesktopConfiguration::Equals(const MacDesktopConfiguration& other) {
} }
const MacDisplayConfiguration* const MacDisplayConfiguration*
MacDesktopConfiguration::FindDisplayConfigurationById( MacDesktopConfiguration::FindDisplayConfigurationById(
CGDirectDisplayID id) { CGDirectDisplayID id) {
bool is_builtin = CGDisplayIsBuiltin(id); bool is_builtin = CGDisplayIsBuiltin(id);
for (MacDisplayConfigurations::const_iterator it = displays.begin(); for (MacDisplayConfigurations::const_iterator it = displays.begin();
it != displays.end(); ++it) { it != displays.end();
++it) {
// The MBP having both discrete and integrated graphic cards will do // The MBP having both discrete and integrated graphic cards will do
// automate graphics switching by default. When it switches from discrete to // automate graphics switching by default. When it switches from discrete to
// integrated one, the current display ID of the built-in display will // integrated one, the current display ID of the built-in display will
// change and this will cause screen capture stops. // change and this will cause screen capture stops.
// So make screen capture of built-in display continuing even if its display // So make screen capture of built-in display continuing even if its display
// ID is changed. // ID is changed.
if ((is_builtin && it->is_builtin) || (!is_builtin && it->id == id)) return &(*it); if ((is_builtin && it->is_builtin) || (!is_builtin && it->id == id))
return &(*it);
} }
return NULL; return NULL;
} }

View File

@ -30,7 +30,8 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForDisplay(
} }
// static // static
std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForWindow(CGWindowID window_id) { std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForWindow(
CGWindowID window_id) {
rtc::ScopedCFTypeRef<CGImageRef> cg_image( rtc::ScopedCFTypeRef<CGImageRef> cg_image(
CGWindowListCreateImage(CGRectNull, CGWindowListCreateImage(CGRectNull,
kCGWindowListOptionIncludingWindow, kCGWindowListOptionIncludingWindow,
@ -49,7 +50,8 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
// Verify that the image has 32-bit depth. // Verify that the image has 32-bit depth.
int bits_per_pixel = CGImageGetBitsPerPixel(cg_image.get()); int bits_per_pixel = CGImageGetBitsPerPixel(cg_image.get());
if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) { if (bits_per_pixel / 8 != DesktopFrame::kBytesPerPixel) {
RTC_LOG(LS_ERROR) << "CGDisplayCreateImage() returned imaged with " << bits_per_pixel RTC_LOG(LS_ERROR) << "CGDisplayCreateImage() returned imaged with "
<< bits_per_pixel
<< " bits per pixel. Only 32-bit depth is supported."; << " bits per pixel. Only 32-bit depth is supported.";
return nullptr; return nullptr;
} }
@ -58,16 +60,18 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
CGDataProviderRef cg_provider = CGImageGetDataProvider(cg_image.get()); CGDataProviderRef cg_provider = CGImageGetDataProvider(cg_image.get());
RTC_DCHECK(cg_provider); RTC_DCHECK(cg_provider);
// CGDataProviderCopyData returns a new data object containing a copy of the providers // CGDataProviderCopyData returns a new data object containing a copy of the
// data. // providers data.
rtc::ScopedCFTypeRef<CFDataRef> cg_data(CGDataProviderCopyData(cg_provider)); rtc::ScopedCFTypeRef<CFDataRef> cg_data(CGDataProviderCopyData(cg_provider));
RTC_DCHECK(cg_data); RTC_DCHECK(cg_data);
// CFDataGetBytePtr returns a read-only pointer to the bytes of a CFData object. // CFDataGetBytePtr returns a read-only pointer to the bytes of a CFData
// object.
uint8_t* data = const_cast<uint8_t*>(CFDataGetBytePtr(cg_data.get())); uint8_t* data = const_cast<uint8_t*>(CFDataGetBytePtr(cg_data.get()));
RTC_DCHECK(data); RTC_DCHECK(data);
DesktopSize size(CGImageGetWidth(cg_image.get()), CGImageGetHeight(cg_image.get())); DesktopSize size(CGImageGetWidth(cg_image.get()),
CGImageGetHeight(cg_image.get()));
int stride = CGImageGetBytesPerRow(cg_image.get()); int stride = CGImageGetBytesPerRow(cg_image.get());
std::unique_ptr<DesktopFrameCGImage> frame( std::unique_ptr<DesktopFrameCGImage> frame(
@ -75,17 +79,21 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
CGColorSpaceRef cg_color_space = CGImageGetColorSpace(cg_image.get()); CGColorSpaceRef cg_color_space = CGImageGetColorSpace(cg_image.get());
if (cg_color_space) { if (cg_color_space) {
#if !defined(MAC_OS_X_VERSION_10_13) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_13 #if !defined(MAC_OS_X_VERSION_10_13) || \
rtc::ScopedCFTypeRef<CFDataRef> cf_icc_profile(CGColorSpaceCopyICCProfile(cg_color_space)); MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_13
rtc::ScopedCFTypeRef<CFDataRef> cf_icc_profile(
CGColorSpaceCopyICCProfile(cg_color_space));
#else #else
rtc::ScopedCFTypeRef<CFDataRef> cf_icc_profile(CGColorSpaceCopyICCData(cg_color_space)); rtc::ScopedCFTypeRef<CFDataRef> cf_icc_profile(
CGColorSpaceCopyICCData(cg_color_space));
#endif #endif
if (cf_icc_profile) { if (cf_icc_profile) {
const uint8_t* data_as_byte = const uint8_t* data_as_byte = reinterpret_cast<const uint8_t*>(
reinterpret_cast<const uint8_t*>(CFDataGetBytePtr(cf_icc_profile.get())); CFDataGetBytePtr(cf_icc_profile.get()));
const size_t data_size = CFDataGetLength(cf_icc_profile.get()); const size_t data_size = CFDataGetLength(cf_icc_profile.get());
if (data_as_byte && data_size > 0) { if (data_as_byte && data_size > 0) {
frame->set_icc_profile(std::vector<uint8_t>(data_as_byte, data_as_byte + data_size)); frame->set_icc_profile(
std::vector<uint8_t>(data_as_byte, data_as_byte + data_size));
} }
} }
} }
@ -93,12 +101,15 @@ std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateFromCGImage(
return frame; return frame;
} }
DesktopFrameCGImage::DesktopFrameCGImage(DesktopSize size, DesktopFrameCGImage::DesktopFrameCGImage(
DesktopSize size,
int stride, int stride,
uint8_t* data, uint8_t* data,
rtc::ScopedCFTypeRef<CGImageRef> cg_image, rtc::ScopedCFTypeRef<CGImageRef> cg_image,
rtc::ScopedCFTypeRef<CFDataRef> cg_data) rtc::ScopedCFTypeRef<CFDataRef> cg_data)
: DesktopFrame(size, stride, data, nullptr), cg_image_(cg_image), cg_data_(cg_data) { : DesktopFrame(size, stride, data, nullptr),
cg_image_(cg_image),
cg_data_(cg_data) {
RTC_DCHECK(cg_image_); RTC_DCHECK(cg_image_);
RTC_DCHECK(cg_data_); RTC_DCHECK(cg_data_);
} }

View File

@ -23,7 +23,8 @@ std::unique_ptr<DesktopFrameIOSurface> DesktopFrameIOSurface::Wrap(
} }
IOSurfaceIncrementUseCount(io_surface.get()); IOSurfaceIncrementUseCount(io_surface.get());
IOReturn status = IOSurfaceLock(io_surface.get(), kIOSurfaceLockReadOnly, nullptr); IOReturn status =
IOSurfaceLock(io_surface.get(), kIOSurfaceLockReadOnly, nullptr);
if (status != kIOReturnSuccess) { if (status != kIOReturnSuccess) {
RTC_LOG(LS_ERROR) << "Failed to lock the IOSurface with status " << status; RTC_LOG(LS_ERROR) << "Failed to lock the IOSurface with status " << status;
IOSurfaceDecrementUseCount(io_surface.get()); IOSurfaceDecrementUseCount(io_surface.get());
@ -33,19 +34,23 @@ std::unique_ptr<DesktopFrameIOSurface> DesktopFrameIOSurface::Wrap(
// Verify that the image has 32-bit depth. // Verify that the image has 32-bit depth.
int bytes_per_pixel = IOSurfaceGetBytesPerElement(io_surface.get()); int bytes_per_pixel = IOSurfaceGetBytesPerElement(io_surface.get());
if (bytes_per_pixel != DesktopFrame::kBytesPerPixel) { if (bytes_per_pixel != DesktopFrame::kBytesPerPixel) {
RTC_LOG(LS_ERROR) << "CGDisplayStream handler returned IOSurface with " << (8 * bytes_per_pixel) RTC_LOG(LS_ERROR) << "CGDisplayStream handler returned IOSurface with "
<< (8 * bytes_per_pixel)
<< " bits per pixel. Only 32-bit depth is supported."; << " bits per pixel. Only 32-bit depth is supported.";
IOSurfaceUnlock(io_surface.get(), kIOSurfaceLockReadOnly, nullptr); IOSurfaceUnlock(io_surface.get(), kIOSurfaceLockReadOnly, nullptr);
IOSurfaceDecrementUseCount(io_surface.get()); IOSurfaceDecrementUseCount(io_surface.get());
return nullptr; return nullptr;
} }
return std::unique_ptr<DesktopFrameIOSurface>(new DesktopFrameIOSurface(io_surface)); return std::unique_ptr<DesktopFrameIOSurface>(
new DesktopFrameIOSurface(io_surface));
} }
DesktopFrameIOSurface::DesktopFrameIOSurface(rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface) DesktopFrameIOSurface::DesktopFrameIOSurface(
rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface)
: DesktopFrame( : DesktopFrame(
DesktopSize(IOSurfaceGetWidth(io_surface.get()), IOSurfaceGetHeight(io_surface.get())), DesktopSize(IOSurfaceGetWidth(io_surface.get()),
IOSurfaceGetHeight(io_surface.get())),
IOSurfaceGetBytesPerRow(io_surface.get()), IOSurfaceGetBytesPerRow(io_surface.get()),
static_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface.get())), static_cast<uint8_t*>(IOSurfaceGetBaseAddress(io_surface.get())),
nullptr), nullptr),

View File

@ -41,7 +41,8 @@ std::unique_ptr<DesktopFrame> DesktopFrameProvider::TakeLatestFrameForDisplay(
return io_surfaces_[display_id]->Share(); return io_surfaces_[display_id]->Share();
} }
void DesktopFrameProvider::InvalidateIOSurface(CGDirectDisplayID display_id, void DesktopFrameProvider::InvalidateIOSurface(
CGDirectDisplayID display_id,
rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface) { rtc::ScopedCFTypeRef<IOSurfaceRef> io_surface) {
RTC_DCHECK(thread_checker_.IsCurrent()); RTC_DCHECK(thread_checker_.IsCurrent());

View File

@ -36,7 +36,8 @@ class DisplayStreamManager;
// A class to perform video frame capturing for mac. // A class to perform video frame capturing for mac.
class ScreenCapturerMac final : public DesktopCapturer { class ScreenCapturerMac final : public DesktopCapturer {
public: public:
ScreenCapturerMac(rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor, ScreenCapturerMac(
rtc::scoped_refptr<DesktopConfigurationMonitor> desktop_config_monitor,
bool detect_updated_region, bool detect_updated_region,
bool allow_iosurface); bool allow_iosurface);
~ScreenCapturerMac() override; ~ScreenCapturerMac() override;

View File

@ -26,7 +26,8 @@ namespace {
// Scales all coordinates of a rect by a specified factor. // Scales all coordinates of a rect by a specified factor.
DesktopRect ScaleAndRoundCGRect(const CGRect& rect, float scale) { DesktopRect ScaleAndRoundCGRect(const CGRect& rect, float scale) {
return DesktopRect::MakeLTRB(static_cast<int>(floor(rect.origin.x * scale)), return DesktopRect::MakeLTRB(
static_cast<int>(floor(rect.origin.x * scale)),
static_cast<int>(floor(rect.origin.y * scale)), static_cast<int>(floor(rect.origin.y * scale)),
static_cast<int>(ceil((rect.origin.x + rect.size.width) * scale)), static_cast<int>(ceil((rect.origin.x + rect.size.width) * scale)),
static_cast<int>(ceil((rect.origin.y + rect.size.height) * scale))); static_cast<int>(ceil((rect.origin.y + rect.size.height) * scale)));
@ -63,8 +64,8 @@ void CopyRect(const uint8_t* src_plane,
CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) { CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) {
if (!window_to_exclude) return nullptr; if (!window_to_exclude) return nullptr;
CFArrayRef all_windows = CFArrayRef all_windows = CGWindowListCopyWindowInfo(
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
if (!all_windows) return nullptr; if (!all_windows) return nullptr;
CFMutableArrayRef returned_array = CFMutableArrayRef returned_array =
@ -72,8 +73,8 @@ CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) {
bool found = false; bool found = false;
for (CFIndex i = 0; i < CFArrayGetCount(all_windows); ++i) { for (CFIndex i = 0; i < CFArrayGetCount(all_windows); ++i) {
CFDictionaryRef window = CFDictionaryRef window = reinterpret_cast<CFDictionaryRef>(
reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(all_windows, i)); CFArrayGetValueAtIndex(all_windows, i));
CGWindowID id = GetWindowId(window); CGWindowID id = GetWindowId(window);
if (id == window_to_exclude) { if (id == window_to_exclude) {
@ -93,7 +94,8 @@ CFArrayRef CreateWindowListWithExclusion(CGWindowID window_to_exclude) {
// Returns the bounds of `window` in physical pixels, enlarged by a small amount // Returns the bounds of `window` in physical pixels, enlarged by a small amount
// on four edges to take account of the border/shadow effects. // on four edges to take account of the border/shadow effects.
DesktopRect GetExcludedWindowPixelBounds(CGWindowID window, float dip_to_pixel_scale) { DesktopRect GetExcludedWindowPixelBounds(CGWindowID window,
float dip_to_pixel_scale) {
// The amount of pixels to add to the actual window bounds to take into // The amount of pixels to add to the actual window bounds to take into
// account of the border/shadow effects. // account of the border/shadow effects.
static const int kBorderEffectSize = 20; static const int kBorderEffectSize = 20;
@ -103,13 +105,14 @@ DesktopRect GetExcludedWindowPixelBounds(CGWindowID window, float dip_to_pixel_s
CFArrayRef window_id_array = CFArrayRef window_id_array =
CFArrayCreate(nullptr, reinterpret_cast<const void**>(&ids), 1, nullptr); CFArrayCreate(nullptr, reinterpret_cast<const void**>(&ids), 1, nullptr);
CFArrayRef window_array = CGWindowListCreateDescriptionFromArray(window_id_array); CFArrayRef window_array =
CGWindowListCreateDescriptionFromArray(window_id_array);
if (CFArrayGetCount(window_array) > 0) { if (CFArrayGetCount(window_array) > 0) {
CFDictionaryRef win = CFDictionaryRef win = reinterpret_cast<CFDictionaryRef>(
reinterpret_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(window_array, 0)); CFArrayGetValueAtIndex(window_array, 0));
CFDictionaryRef bounds_ref = CFDictionaryRef bounds_ref = reinterpret_cast<CFDictionaryRef>(
reinterpret_cast<CFDictionaryRef>(CFDictionaryGetValue(win, kCGWindowBounds)); CFDictionaryGetValue(win, kCGWindowBounds));
CGRectMakeWithDictionaryRepresentation(bounds_ref, &rect); CGRectMakeWithDictionaryRepresentation(bounds_ref, &rect);
} }
@ -127,7 +130,8 @@ DesktopRect GetExcludedWindowPixelBounds(CGWindowID window, float dip_to_pixel_s
// Create an image of the given region using the given `window_list`. // Create an image of the given region using the given `window_list`.
// `pixel_bounds` should be in the primary display's coordinate in physical // `pixel_bounds` should be in the primary display's coordinate in physical
// pixels. // pixels.
rtc::ScopedCFTypeRef<CGImageRef> CreateExcludedWindowRegionImage(const DesktopRect& pixel_bounds, rtc::ScopedCFTypeRef<CGImageRef> CreateExcludedWindowRegionImage(
const DesktopRect& pixel_bounds,
float dip_to_pixel_scale, float dip_to_pixel_scale,
CFArrayRef window_list) { CFArrayRef window_list) {
CGRect window_bounds; CGRect window_bounds;
@ -138,8 +142,8 @@ rtc::ScopedCFTypeRef<CGImageRef> CreateExcludedWindowRegionImage(const DesktopRe
window_bounds.size.width = pixel_bounds.width(); window_bounds.size.width = pixel_bounds.width();
window_bounds.size.height = pixel_bounds.height(); window_bounds.size.height = pixel_bounds.height();
return rtc::ScopedCFTypeRef<CGImageRef>( return rtc::ScopedCFTypeRef<CGImageRef>(CGWindowListCreateImageFromArray(
CGWindowListCreateImageFromArray(window_bounds, window_list, kCGWindowImageDefault)); window_bounds, window_list, kCGWindowImageDefault));
} }
} // namespace } // namespace
@ -204,7 +208,8 @@ void ScreenCapturerMac::CaptureFrame() {
RTC_DLOG(LS_WARNING) << "Overwriting frame that is still shared."; RTC_DLOG(LS_WARNING) << "Overwriting frame that is still shared.";
} }
MacDesktopConfiguration new_config = desktop_config_monitor_->desktop_configuration(); MacDesktopConfiguration new_config =
desktop_config_monitor_->desktop_configuration();
if (!desktop_config_.Equals(new_config)) { if (!desktop_config_.Equals(new_config)) {
desktop_config_ = new_config; desktop_config_ = new_config;
// If the display configuraiton has changed then refresh capturer data // If the display configuraiton has changed then refresh capturer data
@ -236,7 +241,8 @@ void ScreenCapturerMac::CaptureFrame() {
// If the current buffer is from an older generation then allocate a new one. // If the current buffer is from an older generation then allocate a new one.
// Note that we can't reallocate other buffers at this point, since the caller // Note that we can't reallocate other buffers at this point, since the caller
// may still be reading from them. // may still be reading from them.
if (!queue_.current_frame()) queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(CreateFrame())); if (!queue_.current_frame())
queue_.ReplaceCurrentFrame(SharedDesktopFrame::Wrap(CreateFrame()));
DesktopFrame* current_frame = queue_.current_frame(); DesktopFrame* current_frame = queue_.current_frame();
@ -248,15 +254,16 @@ void ScreenCapturerMac::CaptureFrame() {
if (detect_updated_region_) { if (detect_updated_region_) {
*new_frame->mutable_updated_region() = region; *new_frame->mutable_updated_region() = region;
} else { } else {
new_frame->mutable_updated_region()->AddRect(DesktopRect::MakeSize(new_frame->size())); new_frame->mutable_updated_region()->AddRect(
DesktopRect::MakeSize(new_frame->size()));
} }
if (current_display_) { if (current_display_) {
const MacDisplayConfiguration* config = const MacDisplayConfiguration* config =
desktop_config_.FindDisplayConfigurationById(current_display_); desktop_config_.FindDisplayConfigurationById(current_display_);
if (config) { if (config) {
new_frame->set_top_left( new_frame->set_top_left(config->bounds.top_left().subtract(
config->bounds.top_left().subtract(desktop_config_.bounds.top_left())); desktop_config_.bounds.top_left()));
} }
} }
@ -287,7 +294,8 @@ bool ScreenCapturerMac::SelectSource(SourceId id) {
current_display_ = 0; current_display_ = 0;
} else { } else {
const MacDisplayConfiguration* config = const MacDisplayConfiguration* config =
desktop_config_.FindDisplayConfigurationById(static_cast<CGDirectDisplayID>(id)); desktop_config_.FindDisplayConfigurationById(
static_cast<CGDirectDisplayID>(id));
if (!config) return false; if (!config) return false;
current_display_ = config->id; current_display_ = config->id;
} }
@ -296,11 +304,15 @@ bool ScreenCapturerMac::SelectSource(SourceId id) {
return true; return true;
} }
bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& region) { bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame,
// If not all screen region is dirty, copy the entire contents of the previous capture buffer, const DesktopRegion& region) {
// to capture over. // If not all screen region is dirty, copy the entire contents of the previous
if (queue_.previous_frame() && !region.Equals(DesktopRegion(screen_pixel_bounds_))) { // capture buffer, to capture over.
memcpy(frame.data(), queue_.previous_frame()->data(), frame.stride() * frame.size().height()); if (queue_.previous_frame() &&
!region.Equals(DesktopRegion(screen_pixel_bounds_))) {
memcpy(frame.data(),
queue_.previous_frame()->data(),
frame.stride() * frame.size().height());
} }
MacDisplayConfigurations displays_to_capture; MacDisplayConfigurations displays_to_capture;
@ -329,12 +341,15 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
// Capturing mixed-DPI on one surface is hard, so we only return displays // Capturing mixed-DPI on one surface is hard, so we only return displays
// that match the "primary" display's DPI. The primary display is always // that match the "primary" display's DPI. The primary display is always
// the first in the list. // the first in the list.
if (i > 0 && display_config.dip_to_pixel_scale != displays_to_capture[0].dip_to_pixel_scale) { if (i > 0 &&
display_config.dip_to_pixel_scale !=
displays_to_capture[0].dip_to_pixel_scale) {
continue; continue;
} }
// Determine the display's position relative to the desktop, in pixels. // Determine the display's position relative to the desktop, in pixels.
DesktopRect display_bounds = display_config.pixel_bounds; DesktopRect display_bounds = display_config.pixel_bounds;
display_bounds.Translate(-screen_pixel_bounds_.left(), -screen_pixel_bounds_.top()); display_bounds.Translate(-screen_pixel_bounds_.left(),
-screen_pixel_bounds_.top());
// Determine which parts of the blit region, if any, lay within the monitor. // Determine which parts of the blit region, if any, lay within the monitor.
DesktopRegion copy_region = region; DesktopRegion copy_region = region;
@ -348,15 +363,17 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
rtc::ScopedCFTypeRef<CGImageRef> excluded_image; rtc::ScopedCFTypeRef<CGImageRef> excluded_image;
if (excluded_window_ && window_list) { if (excluded_window_ && window_list) {
// Get the region of the excluded window relative the primary display. // Get the region of the excluded window relative the primary display.
excluded_window_bounds = excluded_window_bounds = GetExcludedWindowPixelBounds(
GetExcludedWindowPixelBounds(excluded_window_, display_config.dip_to_pixel_scale); excluded_window_, display_config.dip_to_pixel_scale);
excluded_window_bounds.IntersectWith(display_config.pixel_bounds); excluded_window_bounds.IntersectWith(display_config.pixel_bounds);
// Create the image under the excluded window first, because it's faster // Create the image under the excluded window first, because it's faster
// than captuing the whole display. // than captuing the whole display.
if (!excluded_window_bounds.is_empty()) { if (!excluded_window_bounds.is_empty()) {
excluded_image = CreateExcludedWindowRegionImage( excluded_image =
excluded_window_bounds, display_config.dip_to_pixel_scale, window_list); CreateExcludedWindowRegionImage(excluded_window_bounds,
display_config.dip_to_pixel_scale,
window_list);
} }
} }
@ -370,8 +387,8 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
int src_bytes_per_row = frame_source->stride(); int src_bytes_per_row = frame_source->stride();
RTC_DCHECK(display_base_address); RTC_DCHECK(display_base_address);
// `frame_source` size may be different from display_bounds in case the screen was // `frame_source` size may be different from display_bounds in case the
// resized recently. // screen was resized recently.
copy_region.IntersectWith(frame_source->rect()); copy_region.IntersectWith(frame_source->rect());
// Copy the dirty region from the display buffer into our desktop buffer. // Copy the dirty region from the display buffer into our desktop buffer.
@ -387,7 +404,8 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
if (excluded_image) { if (excluded_image) {
CGDataProviderRef provider = CGImageGetDataProvider(excluded_image.get()); CGDataProviderRef provider = CGImageGetDataProvider(excluded_image.get());
rtc::ScopedCFTypeRef<CFDataRef> excluded_image_data(CGDataProviderCopyData(provider)); rtc::ScopedCFTypeRef<CFDataRef> excluded_image_data(
CGDataProviderCopyData(provider));
RTC_DCHECK(excluded_image_data); RTC_DCHECK(excluded_image_data);
display_base_address = CFDataGetBytePtr(excluded_image_data.get()); display_base_address = CFDataGetBytePtr(excluded_image_data.get());
src_bytes_per_row = CGImageGetBytesPerRow(excluded_image.get()); src_bytes_per_row = CGImageGetBytesPerRow(excluded_image.get());
@ -398,14 +416,18 @@ bool ScreenCapturerMac::CgBlit(const DesktopFrame& frame, const DesktopRegion& r
window_bounds_relative_to_desktop.Translate(-screen_pixel_bounds_.left(), window_bounds_relative_to_desktop.Translate(-screen_pixel_bounds_.left(),
-screen_pixel_bounds_.top()); -screen_pixel_bounds_.top());
DesktopRect rect_to_copy = DesktopRect::MakeSize(excluded_window_bounds.size()); DesktopRect rect_to_copy =
rect_to_copy.IntersectWith(DesktopRect::MakeWH(CGImageGetWidth(excluded_image.get()), DesktopRect::MakeSize(excluded_window_bounds.size());
rect_to_copy.IntersectWith(
DesktopRect::MakeWH(CGImageGetWidth(excluded_image.get()),
CGImageGetHeight(excluded_image.get()))); CGImageGetHeight(excluded_image.get())));
if (CGImageGetBitsPerPixel(excluded_image.get()) / 8 == DesktopFrame::kBytesPerPixel) { if (CGImageGetBitsPerPixel(excluded_image.get()) / 8 ==
DesktopFrame::kBytesPerPixel) {
CopyRect(display_base_address, CopyRect(display_base_address,
src_bytes_per_row, src_bytes_per_row,
frame.GetFrameDataAtPos(window_bounds_relative_to_desktop.top_left()), frame.GetFrameDataAtPos(
window_bounds_relative_to_desktop.top_left()),
frame.stride(), frame.stride(),
DesktopFrame::kBytesPerPixel, DesktopFrame::kBytesPerPixel,
rect_to_copy); rect_to_copy);
@ -454,7 +476,8 @@ bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
CGDirectDisplayID display_id = config.id; CGDirectDisplayID display_id = config.id;
DesktopVector display_origin = config.pixel_bounds.top_left(); DesktopVector display_origin = config.pixel_bounds.top_left();
CGDisplayStreamFrameAvailableHandler handler = ^(CGDisplayStreamFrameStatus status, CGDisplayStreamFrameAvailableHandler handler = ^(
CGDisplayStreamFrameStatus status,
uint64_t /* display_time */, uint64_t /* display_time */,
IOSurfaceRef frame_surface, IOSurfaceRef frame_surface,
CGDisplayStreamUpdateRef updateRef) { CGDisplayStreamUpdateRef updateRef) {
@ -465,8 +488,8 @@ bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
if (status != kCGDisplayStreamFrameStatusFrameComplete) return; if (status != kCGDisplayStreamFrameStatusFrameComplete) return;
size_t count = 0; size_t count = 0;
const CGRect* rects = const CGRect* rects = CGDisplayStreamUpdateGetRects(
CGDisplayStreamUpdateGetRects(updateRef, kCGDisplayStreamUpdateDirtyRects, &count); updateRef, kCGDisplayStreamUpdateDirtyRects, &count);
if (count != 0) { if (count != 0) {
// According to CGDisplayStream.h, it's safe to call // According to CGDisplayStream.h, it's safe to call
// CGDisplayStreamStop() from within the callback. // CGDisplayStreamStop() from within the callback.
@ -482,14 +505,20 @@ bool ScreenCapturerMac::RegisterRefreshAndMoveHandlers() {
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks)); &kCFTypeDictionaryValueCallBacks));
CGDisplayStreamRef display_stream = CGDisplayStreamCreate( CGDisplayStreamRef display_stream =
display_id, pixel_width, pixel_height, 'BGRA', properties_dict.get(), handler); CGDisplayStreamCreate(display_id,
pixel_width,
pixel_height,
'BGRA',
properties_dict.get(),
handler);
if (display_stream) { if (display_stream) {
CGError error = CGDisplayStreamStart(display_stream); CGError error = CGDisplayStreamStart(display_stream);
if (error != kCGErrorSuccess) return false; if (error != kCGErrorSuccess) return false;
CFRunLoopSourceRef source = CGDisplayStreamGetRunLoopSource(display_stream); CFRunLoopSourceRef source =
CGDisplayStreamGetRunLoopSource(display_stream);
CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes); CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes);
display_streams_.push_back(display_stream); display_streams_.push_back(display_stream);
} }
@ -542,14 +571,17 @@ void ScreenCapturerMac::ScreenRefresh(CGDirectDisplayID display_id,
// Always having the latest iosurface before invalidating a region. // Always having the latest iosurface before invalidating a region.
// See https://bugs.chromium.org/p/webrtc/issues/detail?id=8652 for details. // See https://bugs.chromium.org/p/webrtc/issues/detail?id=8652 for details.
desktop_frame_provider_.InvalidateIOSurface( desktop_frame_provider_.InvalidateIOSurface(
display_id, rtc::ScopedCFTypeRef<IOSurfaceRef>(io_surface, rtc::RetainPolicy::RETAIN)); display_id,
rtc::ScopedCFTypeRef<IOSurfaceRef>(io_surface,
rtc::RetainPolicy::RETAIN));
helper_.InvalidateRegion(region); helper_.InvalidateRegion(region);
} }
std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() { std::unique_ptr<DesktopFrame> ScreenCapturerMac::CreateFrame() {
std::unique_ptr<DesktopFrame> frame(new BasicDesktopFrame(screen_pixel_bounds_.size())); std::unique_ptr<DesktopFrame> frame(
frame->set_dpi( new BasicDesktopFrame(screen_pixel_bounds_.size()));
DesktopVector(kStandardDPI * dip_to_pixel_scale_, kStandardDPI * dip_to_pixel_scale_)); frame->set_dpi(DesktopVector(kStandardDPI * dip_to_pixel_scale_,
kStandardDPI * dip_to_pixel_scale_));
return frame; return frame;
} }

View File

@ -28,10 +28,10 @@ namespace webrtc {
class ScreenCapturerSck; class ScreenCapturerSck;
} // namespace webrtc } // namespace webrtc
// The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture was reported to be // The ScreenCaptureKit API was available in macOS 12.3, but full-screen capture
// broken before macOS 13 - see http://crbug.com/40234870. // was reported to be broken before macOS 13 - see http://crbug.com/40234870.
// Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were introduced in // Also, the `SCContentFilter` fields `contentRect` and `pointPixelScale` were
// macOS 14. // introduced in macOS 14.
API_AVAILABLE(macos(14.0)) API_AVAILABLE(macos(14.0))
@interface SckHelper : NSObject <SCStreamDelegate, SCStreamOutput> @interface SckHelper : NSObject <SCStreamDelegate, SCStreamOutput>
@ -39,16 +39,18 @@ API_AVAILABLE(macos(14.0))
- (void)onShareableContentCreated:(SCShareableContent*)content; - (void)onShareableContentCreated:(SCShareableContent*)content;
// Called just before the capturer is destroyed. This avoids a dangling pointer, and prevents any // Called just before the capturer is destroyed. This avoids a dangling pointer,
// new calls into a deleted capturer. If any method-call on the capturer is currently running on a // and prevents any new calls into a deleted capturer. If any method-call on the
// different thread, this blocks until it completes. // capturer is currently running on a different thread, this blocks until it
// completes.
- (void)releaseCapturer; - (void)releaseCapturer;
@end @end
namespace webrtc { namespace webrtc {
class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final : public DesktopCapturer { class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final
: public DesktopCapturer {
public: public:
explicit ScreenCapturerSck(const DesktopCaptureOptions& options); explicit ScreenCapturerSck(const DesktopCaptureOptions& options);
@ -63,35 +65,38 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final : public DesktopCapture
void CaptureFrame() override; void CaptureFrame() override;
bool SelectSource(SourceId id) override; bool SelectSource(SourceId id) override;
// Called by SckHelper when shareable content is returned by ScreenCaptureKit. `content` will be // Called by SckHelper when shareable content is returned by ScreenCaptureKit.
// nil if an error occurred. May run on an arbitrary thread. // `content` will be nil if an error occurred. May run on an arbitrary thread.
void OnShareableContentCreated(SCShareableContent* content); void OnShareableContentCreated(SCShareableContent* content);
// Called by SckHelper to notify of a newly captured frame. May run on an arbitrary thread. // Called by SckHelper to notify of a newly captured frame. May run on an
// arbitrary thread.
void OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef attachment); void OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef attachment);
private: private:
// Called when starting the capturer or the configuration has changed (either from a // Called when starting the capturer or the configuration has changed (either
// SelectSource() call, or the screen-resolution has changed). This tells SCK to fetch new // from a SelectSource() call, or the screen-resolution has changed). This
// shareable content, and the completion-handler will either start a new stream, or reconfigure // tells SCK to fetch new shareable content, and the completion-handler will
// the existing stream. Runs on the caller's thread. // either start a new stream, or reconfigure the existing stream. Runs on the
// caller's thread.
void StartOrReconfigureCapturer(); void StartOrReconfigureCapturer();
// Helper object to receive Objective-C callbacks from ScreenCaptureKit and call into this C++ // Helper object to receive Objective-C callbacks from ScreenCaptureKit and
// object. The helper may outlive this C++ instance, if a completion-handler is passed to // call into this C++ object. The helper may outlive this C++ instance, if a
// ScreenCaptureKit APIs and the C++ object is deleted before the handler executes. // completion-handler is passed to ScreenCaptureKit APIs and the C++ object is
// deleted before the handler executes.
SckHelper* __strong helper_; SckHelper* __strong helper_;
// Callback for returning captured frames, or errors, to the caller. Only used on the caller's // Callback for returning captured frames, or errors, to the caller. Only used
// thread. // on the caller's thread.
Callback* callback_ = nullptr; Callback* callback_ = nullptr;
// Options passed to the constructor. May be accessed on any thread, but the options are // Options passed to the constructor. May be accessed on any thread, but the
// unchanged during the capturer's lifetime. // options are unchanged during the capturer's lifetime.
DesktopCaptureOptions capture_options_; DesktopCaptureOptions capture_options_;
// Signals that a permanent error occurred. This may be set on any thread, and is read by // Signals that a permanent error occurred. This may be set on any thread, and
// CaptureFrame() which runs on the caller's thread. // is read by CaptureFrame() which runs on the caller's thread.
std::atomic<bool> permanent_error_ = false; std::atomic<bool> permanent_error_ = false;
// Guards some variables that may be accessed on different threads. // Guards some variables that may be accessed on different threads.
@ -100,25 +105,28 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSck final : public DesktopCapture
// Provides captured desktop frames. // Provides captured desktop frames.
SCStream* __strong stream_ RTC_GUARDED_BY(lock_); SCStream* __strong stream_ RTC_GUARDED_BY(lock_);
// Currently selected display, or 0 if the full desktop is selected. This capturer does not // Currently selected display, or 0 if the full desktop is selected. This
// support full-desktop capture, and will fall back to the first display. // capturer does not support full-desktop capture, and will fall back to the
// first display.
CGDirectDisplayID current_display_ RTC_GUARDED_BY(lock_) = 0; CGDirectDisplayID current_display_ RTC_GUARDED_BY(lock_) = 0;
// Used by CaptureFrame() to detect if the screen configuration has changed. Only used on the // Used by CaptureFrame() to detect if the screen configuration has changed.
// caller's thread. // Only used on the caller's thread.
MacDesktopConfiguration desktop_config_; MacDesktopConfiguration desktop_config_;
Mutex latest_frame_lock_; Mutex latest_frame_lock_;
std::unique_ptr<SharedDesktopFrame> latest_frame_ RTC_GUARDED_BY(latest_frame_lock_); std::unique_ptr<SharedDesktopFrame> latest_frame_
RTC_GUARDED_BY(latest_frame_lock_);
int32_t latest_frame_dpi_ RTC_GUARDED_BY(latest_frame_lock_) = kStandardDPI; int32_t latest_frame_dpi_ RTC_GUARDED_BY(latest_frame_lock_) = kStandardDPI;
// Tracks whether the latest frame contains new data since it was returned to the caller. This is // Tracks whether the latest frame contains new data since it was returned to
// used to set the DesktopFrame's `updated_region` property. The flag is cleared after the frame // the caller. This is used to set the DesktopFrame's `updated_region`
// is sent to OnCaptureResult(), and is set when SCK reports a new frame with non-empty "dirty" // property. The flag is cleared after the frame is sent to OnCaptureResult(),
// rectangles. // and is set when SCK reports a new frame with non-empty "dirty" rectangles.
// TODO: crbug.com/327458809 - Replace this flag with ScreenCapturerHelper to more accurately // TODO: crbug.com/327458809 - Replace this flag with ScreenCapturerHelper to
// track the dirty rectangles from the SCStreamFrameInfoDirtyRects attachment. // more accurately track the dirty rectangles from the
// SCStreamFrameInfoDirtyRects attachment.
bool frame_is_dirty_ RTC_GUARDED_BY(latest_frame_lock_) = true; bool frame_is_dirty_ RTC_GUARDED_BY(latest_frame_lock_) = true;
}; };
@ -134,7 +142,8 @@ ScreenCapturerSck::~ScreenCapturerSck() {
void ScreenCapturerSck::Start(DesktopCapturer::Callback* callback) { void ScreenCapturerSck::Start(DesktopCapturer::Callback* callback) {
callback_ = callback; callback_ = callback;
desktop_config_ = capture_options_.configuration_monitor()->desktop_configuration(); desktop_config_ =
capture_options_.configuration_monitor()->desktop_configuration();
StartOrReconfigureCapturer(); StartOrReconfigureCapturer();
} }
@ -164,7 +173,8 @@ void ScreenCapturerSck::CaptureFrame() {
frame = latest_frame_->Share(); frame = latest_frame_->Share();
frame->set_dpi(DesktopVector(latest_frame_dpi_, latest_frame_dpi_)); frame->set_dpi(DesktopVector(latest_frame_dpi_, latest_frame_dpi_));
if (frame_is_dirty_) { if (frame_is_dirty_) {
frame->mutable_updated_region()->AddRect(DesktopRect::MakeSize(frame->size())); frame->mutable_updated_region()->AddRect(
DesktopRect::MakeSize(frame->size()));
frame_is_dirty_ = false; frame_is_dirty_ = false;
} }
} }
@ -189,7 +199,8 @@ bool ScreenCapturerSck::SelectSource(SourceId id) {
} }
} }
// If the capturer was already started, reconfigure it. Otherwise, wait until Start() gets called. // If the capturer was already started, reconfigure it. Otherwise, wait until
// Start() gets called.
if (stream_started) { if (stream_started) {
StartOrReconfigureCapturer(); StartOrReconfigureCapturer();
} }
@ -220,9 +231,10 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
} }
} }
if (!captured_display) { if (!captured_display) {
if (current_display_ == static_cast<CGDirectDisplayID>(kFullDesktopScreenId)) { if (current_display_ ==
RTC_LOG(LS_WARNING) static_cast<CGDirectDisplayID>(kFullDesktopScreenId)) {
<< "Full screen capture is not supported, falling back to first display."; RTC_LOG(LS_WARNING) << "Full screen capture is not supported, falling "
"back to first display.";
} else { } else {
RTC_LOG(LS_WARNING) << "Display " << current_display_ RTC_LOG(LS_WARNING) << "Display " << current_display_
<< " not found, falling back to first display."; << " not found, falling back to first display.";
@ -231,7 +243,8 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
} }
} }
SCContentFilter* filter = [[SCContentFilter alloc] initWithDisplay:captured_display SCContentFilter* filter =
[[SCContentFilter alloc] initWithDisplay:captured_display
excludingWindows:@[]]; excludingWindows:@[]];
SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init]; SCStreamConfiguration* config = [[SCStreamConfiguration alloc] init];
config.pixelFormat = kCVPixelFormatType_32BGRA; config.pixelFormat = kCVPixelFormatType_32BGRA;
@ -252,11 +265,15 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
[stream_ updateContentFilter:filter completionHandler:nil]; [stream_ updateContentFilter:filter completionHandler:nil];
[stream_ updateConfiguration:config completionHandler:nil]; [stream_ updateConfiguration:config completionHandler:nil];
} else { } else {
stream_ = [[SCStream alloc] initWithFilter:filter configuration:config delegate:helper_]; stream_ = [[SCStream alloc] initWithFilter:filter
configuration:config
delegate:helper_];
// TODO: crbug.com/327458809 - Choose an appropriate sampleHandlerQueue for best performance. // TODO: crbug.com/327458809 - Choose an appropriate sampleHandlerQueue for
// best performance.
NSError* add_stream_output_error; NSError* add_stream_output_error;
bool add_stream_output_result = [stream_ addStreamOutput:helper_ bool add_stream_output_result =
[stream_ addStreamOutput:helper_
type:SCStreamOutputTypeScreen type:SCStreamOutputTypeScreen
sampleHandlerQueue:nil sampleHandlerQueue:nil
error:&add_stream_output_error]; error:&add_stream_output_error];
@ -269,8 +286,9 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
auto handler = ^(NSError* error) { auto handler = ^(NSError* error) {
if (error) { if (error) {
// It should be safe to access `this` here, because the C++ destructor calls // It should be safe to access `this` here, because the C++ destructor
// stopCaptureWithCompletionHandler on the stream, which cancels this handler. // calls stopCaptureWithCompletionHandler on the stream, which cancels
// this handler.
permanent_error_ = true; permanent_error_ = true;
RTC_LOG(LS_ERROR) << "startCaptureWithCompletionHandler failed."; RTC_LOG(LS_ERROR) << "startCaptureWithCompletionHandler failed.";
} else { } else {
@ -282,8 +300,10 @@ void ScreenCapturerSck::OnShareableContentCreated(SCShareableContent* content) {
} }
} }
void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef attachment) { void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface,
rtc::ScopedCFTypeRef<IOSurfaceRef> scoped_io_surface(io_surface, rtc::RetainPolicy::RETAIN); CFDictionaryRef attachment) {
rtc::ScopedCFTypeRef<IOSurfaceRef> scoped_io_surface(
io_surface, rtc::RetainPolicy::RETAIN);
std::unique_ptr<DesktopFrameIOSurface> desktop_frame_io_surface = std::unique_ptr<DesktopFrameIOSurface> desktop_frame_io_surface =
DesktopFrameIOSurface::Wrap(scoped_io_surface); DesktopFrameIOSurface::Wrap(scoped_io_surface);
if (!desktop_frame_io_surface) { if (!desktop_frame_io_surface) {
@ -297,18 +317,19 @@ void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef
bool dirty; bool dirty;
{ {
MutexLock lock(&latest_frame_lock_); MutexLock lock(&latest_frame_lock_);
// Mark the frame as dirty if it has a different size, and ignore any DirtyRects attachment in // Mark the frame as dirty if it has a different size, and ignore any
// this case. This is because SCK does not apply a correct attachment to the frame in the case // DirtyRects attachment in this case. This is because SCK does not apply a
// where the stream was reconfigured. // correct attachment to the frame in the case where the stream was
// reconfigured.
dirty = !latest_frame_ || !latest_frame_->size().equals(frame->size()); dirty = !latest_frame_ || !latest_frame_->size().equals(frame->size());
} }
if (!dirty) { if (!dirty) {
const void* dirty_rects_ptr = const void* dirty_rects_ptr = CFDictionaryGetValue(
CFDictionaryGetValue(attachment, (__bridge CFStringRef)SCStreamFrameInfoDirtyRects); attachment, (__bridge CFStringRef)SCStreamFrameInfoDirtyRects);
if (!dirty_rects_ptr) { if (!dirty_rects_ptr) {
// This is never expected to happen - SCK attaches a non-empty dirty-rects list to every // This is never expected to happen - SCK attaches a non-empty dirty-rects
// frame, even when nothing has changed. // list to every frame, even when nothing has changed.
return; return;
} }
if (CFGetTypeID(dirty_rects_ptr) != CFArrayGetTypeID()) { if (CFGetTypeID(dirty_rects_ptr) != CFArrayGetTypeID()) {
@ -320,12 +341,13 @@ void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
const void* rect_ptr = CFArrayGetValueAtIndex(dirty_rects_array, i); const void* rect_ptr = CFArrayGetValueAtIndex(dirty_rects_array, i);
if (CFGetTypeID(rect_ptr) != CFDictionaryGetTypeID()) { if (CFGetTypeID(rect_ptr) != CFDictionaryGetTypeID()) {
// This is never expected to happen - the dirty-rects attachment should always be an array // This is never expected to happen - the dirty-rects attachment should
// of dictionaries. // always be an array of dictionaries.
return; return;
} }
CGRect rect{}; CGRect rect{};
CGRectMakeWithDictionaryRepresentation(static_cast<CFDictionaryRef>(rect_ptr), &rect); CGRectMakeWithDictionaryRepresentation(
static_cast<CFDictionaryRef>(rect_ptr), &rect);
if (!CGRectIsEmpty(rect)) { if (!CGRectIsEmpty(rect)) {
dirty = true; dirty = true;
break; break;
@ -341,9 +363,9 @@ void ScreenCapturerSck::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef
} }
void ScreenCapturerSck::StartOrReconfigureCapturer() { void ScreenCapturerSck::StartOrReconfigureCapturer() {
// The copy is needed to avoid capturing `this` in the Objective-C block. Accessing `helper_` // The copy is needed to avoid capturing `this` in the Objective-C block.
// inside the block is equivalent to `this->helper_` and would crash (UAF) if `this` is // Accessing `helper_` inside the block is equivalent to `this->helper_` and
// deleted before the block is executed. // would crash (UAF) if `this` is deleted before the block is executed.
SckHelper* local_helper = helper_; SckHelper* local_helper = helper_;
auto handler = ^(SCShareableContent* content, NSError* /* error */) { auto handler = ^(SCShareableContent* content, NSError* /* error */) {
[local_helper onShareableContentCreated:content]; [local_helper onShareableContentCreated:content];
@ -352,7 +374,8 @@ void ScreenCapturerSck::StartOrReconfigureCapturer() {
[SCShareableContent getShareableContentWithCompletionHandler:handler]; [SCShareableContent getShareableContentWithCompletionHandler:handler];
} }
std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(const DesktopCaptureOptions& options) { std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(
const DesktopCaptureOptions& options) {
if (@available(macOS 14.0, *)) { if (@available(macOS 14.0, *)) {
return std::make_unique<ScreenCapturerSck>(options); return std::make_unique<ScreenCapturerSck>(options);
} else { } else {
@ -363,8 +386,8 @@ std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(const DesktopCaptureOpt
} // namespace webrtc } // namespace webrtc
@implementation SckHelper { @implementation SckHelper {
// This lock is to prevent the capturer being destroyed while an instance method is still running // This lock is to prevent the capturer being destroyed while an instance
// on another thread. // method is still running on another thread.
webrtc::Mutex _capturer_lock; webrtc::Mutex _capturer_lock;
webrtc::ScreenCapturerSck* _capturer; webrtc::ScreenCapturerSck* _capturer;
} }
@ -397,8 +420,8 @@ std::unique_ptr<DesktopCapturer> CreateScreenCapturerSck(const DesktopCaptureOpt
return; return;
} }
CFArrayRef attachmentsArray = CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(
CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, /*createIfNecessary=*/false); sampleBuffer, /*createIfNecessary=*/false);
if (!attachmentsArray || CFArrayGetCount(attachmentsArray) <= 0) { if (!attachmentsArray || CFArrayGetCount(attachmentsArray) <= 0) {
RTC_LOG(LS_ERROR) << "Discarding frame with no attachments."; RTC_LOG(LS_ERROR) << "Discarding frame with no attachments.";
return; return;

View File

@ -10,7 +10,6 @@
#include "modules/desktop_capture/mouse_cursor_monitor.h" #include "modules/desktop_capture/mouse_cursor_monitor.h"
#include <memory> #include <memory>
#include <ApplicationServices/ApplicationServices.h> #include <ApplicationServices/ApplicationServices.h>
@ -33,7 +32,8 @@ namespace {
CGImageRef CreateScaledCGImage(CGImageRef image, int width, int height) { CGImageRef CreateScaledCGImage(CGImageRef image, int width, int height) {
// Create context, keeping original image properties. // Create context, keeping original image properties.
CGColorSpaceRef colorspace = CGImageGetColorSpace(image); CGColorSpaceRef colorspace = CGImageGetColorSpace(image);
CGContextRef context = CGBitmapContextCreate(nullptr, CGContextRef context =
CGBitmapContextCreate(nullptr,
width, width,
height, height,
CGImageGetBitsPerComponent(image), CGImageGetBitsPerComponent(image),
@ -66,7 +66,7 @@ class MouseCursorMonitorMac : public MouseCursorMonitor {
private: private:
static void DisplaysReconfiguredCallback(CGDirectDisplayID display, static void DisplaysReconfiguredCallback(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags, CGDisplayChangeSummaryFlags flags,
void *user_parameter); void* user_parameter);
void DisplaysReconfigured(CGDirectDisplayID display, void DisplaysReconfigured(CGDirectDisplayID display,
CGDisplayChangeSummaryFlags flags); CGDisplayChangeSummaryFlags flags);
@ -80,7 +80,8 @@ class MouseCursorMonitorMac : public MouseCursorMonitor {
__strong NSImage* last_cursor_ = NULL; __strong NSImage* last_cursor_ = NULL;
}; };
MouseCursorMonitorMac::MouseCursorMonitorMac(const DesktopCaptureOptions& options, MouseCursorMonitorMac::MouseCursorMonitorMac(
const DesktopCaptureOptions& options,
CGWindowID window_id, CGWindowID window_id,
ScreenId screen_id) ScreenId screen_id)
: configuration_monitor_(options.configuration_monitor()), : configuration_monitor_(options.configuration_monitor()),
@ -115,8 +116,7 @@ void MouseCursorMonitorMac::Capture() {
CaptureImage(scale); CaptureImage(scale);
if (mode_ != SHAPE_AND_POSITION) if (mode_ != SHAPE_AND_POSITION) return;
return;
// Always report cursor position in DIP pixel. // Always report cursor position in DIP pixel.
callback_->OnMouseCursorPosition( callback_->OnMouseCursorPosition(
@ -133,7 +133,8 @@ void MouseCursorMonitorMac::CaptureImage(float scale) {
NSSize nssize = [nsimage size]; // DIP size NSSize nssize = [nsimage size]; // DIP size
// No need to caputre cursor image if it's unchanged since last capture. // No need to caputre cursor image if it's unchanged since last capture.
if ([[nsimage TIFFRepresentation] isEqual:[last_cursor_ TIFFRepresentation]]) return; if ([[nsimage TIFFRepresentation] isEqual:[last_cursor_ TIFFRepresentation]])
return;
last_cursor_ = nsimage; last_cursor_ = nsimage;
DesktopSize size(round(nssize.width * scale), DesktopSize size(round(nssize.width * scale),
@ -144,17 +145,18 @@ void MouseCursorMonitorMac::CaptureImage(float scale) {
std::min(size.width(), static_cast<int>(nshotspot.x * scale))), std::min(size.width(), static_cast<int>(nshotspot.x * scale))),
std::max(0, std::max(0,
std::min(size.height(), static_cast<int>(nshotspot.y * scale)))); std::min(size.height(), static_cast<int>(nshotspot.y * scale))));
CGImageRef cg_image = CGImageRef cg_image = [nsimage CGImageForProposedRect:NULL
[nsimage CGImageForProposedRect:NULL context:nil hints:nil]; context:nil
if (!cg_image) hints:nil];
return; if (!cg_image) return;
// Before 10.12, OSX may report 1X cursor on Retina screen. (See // Before 10.12, OSX may report 1X cursor on Retina screen. (See
// crbug.com/632995.) After 10.12, OSX may report 2X cursor on non-Retina // crbug.com/632995.) After 10.12, OSX may report 2X cursor on non-Retina
// screen. (See crbug.com/671436.) So scaling the cursor if needed. // screen. (See crbug.com/671436.) So scaling the cursor if needed.
CGImageRef scaled_cg_image = nil; CGImageRef scaled_cg_image = nil;
if (CGImageGetWidth(cg_image) != static_cast<size_t>(size.width())) { if (CGImageGetWidth(cg_image) != static_cast<size_t>(size.width())) {
scaled_cg_image = CreateScaledCGImage(cg_image, size.width(), size.height()); scaled_cg_image =
CreateScaledCGImage(cg_image, size.width(), size.height());
if (scaled_cg_image != nil) { if (scaled_cg_image != nil) {
cg_image = scaled_cg_image; cg_image = scaled_cg_image;
} }
@ -199,8 +201,7 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForWindow(
} }
MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( MouseCursorMonitor* MouseCursorMonitor::CreateForScreen(
const DesktopCaptureOptions& options, const DesktopCaptureOptions& options, ScreenId screen) {
ScreenId screen) {
return new MouseCursorMonitorMac(options, kCGNullWindowID, screen); return new MouseCursorMonitorMac(options, kCGNullWindowID, screen);
} }

View File

@ -24,14 +24,17 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer(
if (options.allow_sck_capturer()) { if (options.allow_sck_capturer()) {
// This will return nullptr on systems that don't support ScreenCaptureKit. // This will return nullptr on systems that don't support ScreenCaptureKit.
std::unique_ptr<DesktopCapturer> sck_capturer = CreateScreenCapturerSck(options); std::unique_ptr<DesktopCapturer> sck_capturer =
CreateScreenCapturerSck(options);
if (sck_capturer) { if (sck_capturer) {
return sck_capturer; return sck_capturer;
} }
} }
auto capturer = std::make_unique<ScreenCapturerMac>( auto capturer =
options.configuration_monitor(), options.detect_updated_region(), options.allow_iosurface()); std::make_unique<ScreenCapturerMac>(options.configuration_monitor(),
options.detect_updated_region(),
options.allow_iosurface());
if (!capturer->Init()) { if (!capturer->Init()) {
return nullptr; return nullptr;
} }

View File

@ -218,7 +218,8 @@ void ScreenCapturerFuchsia::SetupBuffers() {
status = component_context_->svc()->Connect(sysmem_allocator_.NewRequest()); status = component_context_->svc()->Connect(sysmem_allocator_.NewRequest());
if (status != ZX_OK) { if (status != ZX_OK) {
fatal_error_ = true; fatal_error_ = true;
RTC_LOG(LS_ERROR) << "Failed to connect to fuchsia.sysmem2.Allocator: " << status; RTC_LOG(LS_ERROR) << "Failed to connect to fuchsia.sysmem2.Allocator: "
<< status;
return; return;
} }
@ -263,7 +264,8 @@ void ScreenCapturerFuchsia::SetupBuffers() {
if (status != ZX_OK) { if (status != ZX_OK) {
fatal_error_ = true; fatal_error_ = true;
RTC_LOG(LS_ERROR) RTC_LOG(LS_ERROR)
<< "fuchsia.sysmem2.Allocator.BindSharedCollection() failed: " << status; << "fuchsia.sysmem2.Allocator.BindSharedCollection() failed: "
<< status;
return; return;
} }

View File

@ -28,13 +28,13 @@ namespace {
#define RGBA(r, g, b, a) \ #define RGBA(r, g, b, a) \
((((a) << 24) & 0xff000000) | (((b) << 16) & 0xff0000) | \ ((((a) << 24) & 0xff000000) | (((b) << 16) & 0xff0000) | \
(((g) << 8) & 0xff00) | ((r)&0xff)) (((g) << 8) & 0xff00) | ((r) & 0xff))
#else // !defined(WEBRTC_ARCH_LITTLE_ENDIAN) #else // !defined(WEBRTC_ARCH_LITTLE_ENDIAN)
#define RGBA(r, g, b, a) \ #define RGBA(r, g, b, a) \
((((r) << 24) & 0xff000000) | (((g) << 16) & 0xff0000) | \ ((((r) << 24) & 0xff000000) | (((g) << 16) & 0xff0000) | \
(((b) << 8) & 0xff00) | ((a)&0xff)) (((b) << 8) & 0xff00) | ((a) & 0xff))
#endif // !defined(WEBRTC_ARCH_LITTLE_ENDIAN) #endif // !defined(WEBRTC_ARCH_LITTLE_ENDIAN)

View File

@ -92,15 +92,13 @@ bool WindowCapturerMac::GetSourceList(SourceList* sources) {
} }
bool WindowCapturerMac::SelectSource(SourceId id) { bool WindowCapturerMac::SelectSource(SourceId id) {
if (!IsWindowValid(id)) if (!IsWindowValid(id)) return false;
return false;
window_id_ = id; window_id_ = id;
return true; return true;
} }
bool WindowCapturerMac::FocusOnSelectedSource() { bool WindowCapturerMac::FocusOnSelectedSource() {
if (!window_id_) if (!window_id_) return false;
return false;
CGWindowID ids[1]; CGWindowID ids[1];
ids[0] = window_id_; ids[0] = window_id_;
@ -126,8 +124,8 @@ bool WindowCapturerMac::FocusOnSelectedSource() {
// TODO(jiayl): this will bring the process main window to the front. We // TODO(jiayl): this will bring the process main window to the front. We
// should find a way to bring only the window to the front. // should find a way to bring only the window to the front.
bool result = bool result = [[NSRunningApplication
[[NSRunningApplication runningApplicationWithProcessIdentifier:pid] activateWithOptions:0]; runningApplicationWithProcessIdentifier:pid] activateWithOptions:0];
CFRelease(window_id_array); CFRelease(window_id_array);
CFRelease(window_array); CFRelease(window_array);
@ -170,7 +168,8 @@ void WindowCapturerMac::CaptureFrame() {
[sources](CFDictionaryRef window) { [sources](CFDictionaryRef window) {
WindowId window_id = GetWindowId(window); WindowId window_id = GetWindowId(window);
if (window_id != kNullWindowId) { if (window_id != kNullWindowId) {
sources->push_back(DesktopCapturer::Source{window_id, GetWindowTitle(window)}); sources->push_back(DesktopCapturer::Source{
window_id, GetWindowTitle(window)});
} }
return true; return true;
}, },
@ -178,10 +177,12 @@ void WindowCapturerMac::CaptureFrame() {
false); false);
}); });
CGWindowID full_screen_window = full_screen_window_detector_->FindFullScreenWindow(window_id_); CGWindowID full_screen_window =
full_screen_window_detector_->FindFullScreenWindow(window_id_);
if (full_screen_window != kCGNullWindowID) { if (full_screen_window != kCGNullWindowID) {
// If this is the first time this happens, report to UMA that the feature is active. // If this is the first time this happens, report to UMA that the feature
// is active.
if (!fullscreen_usage_logged_) { if (!fullscreen_usage_logged_) {
LogDesktopCapturerFullscreenDetectorUsage(); LogDesktopCapturerFullscreenDetectorUsage();
fullscreen_usage_logged_ = true; fullscreen_usage_logged_ = true;
@ -190,7 +191,8 @@ void WindowCapturerMac::CaptureFrame() {
} }
} }
std::unique_ptr<DesktopFrame> frame = DesktopFrameCGImage::CreateForWindow(on_screen_window); std::unique_ptr<DesktopFrame> frame =
DesktopFrameCGImage::CreateForWindow(on_screen_window);
if (!frame) { if (!frame) {
RTC_LOG(LS_WARNING) << "Temporarily failed to capture window."; RTC_LOG(LS_WARNING) << "Temporarily failed to capture window.";
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
@ -202,7 +204,8 @@ void WindowCapturerMac::CaptureFrame() {
frame->set_top_left(GetWindowBounds(on_screen_window).top_left()); frame->set_top_left(GetWindowBounds(on_screen_window).top_left());
float scale_factor = GetWindowScaleFactor(window_id_, frame->size()); float scale_factor = GetWindowScaleFactor(window_id_, frame->size());
frame->set_dpi(DesktopVector(kStandardDPI * scale_factor, kStandardDPI * scale_factor)); frame->set_dpi(
DesktopVector(kStandardDPI * scale_factor, kStandardDPI * scale_factor));
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
} }

View File

@ -11,7 +11,6 @@
#ifndef MODULES_PACING_RTP_PACKET_PACER_H_ #ifndef MODULES_PACING_RTP_PACKET_PACER_H_
#define MODULES_PACING_RTP_PACKET_PACER_H_ #define MODULES_PACING_RTP_PACKET_PACER_H_
#include <optional> #include <optional>
#include <vector> #include <vector>

View File

@ -83,7 +83,9 @@ class MockRtpRtcpInterface : public RtpRtcpInterface {
OnSendingRtpFrame, OnSendingRtpFrame,
(uint32_t, int64_t, int, bool), (uint32_t, int64_t, int, bool),
(override)); (override));
MOCK_METHOD(bool, CanSendPacket, (const RtpPacketToSend& packet), MOCK_METHOD(bool,
CanSendPacket,
(const RtpPacketToSend& packet),
(const, override)); (const, override));
MOCK_METHOD(void, MOCK_METHOD(void,
AssignSequenceNumber, AssignSequenceNumber,

View File

@ -68,7 +68,7 @@ class AbsoluteSendTime {
static constexpr Timestamp ToTimestamp(uint32_t time_24bits) { static constexpr Timestamp ToTimestamp(uint32_t time_24bits) {
RTC_DCHECK_LT(time_24bits, (1 << 24)); RTC_DCHECK_LT(time_24bits, (1 << 24));
return Timestamp::Micros((time_24bits* int64_t{1'000'000}) >> 18); return Timestamp::Micros((time_24bits * int64_t{1'000'000}) >> 18);
} }
}; };

View File

@ -8,14 +8,14 @@
* be found in the AUTHORS file in the root of the source tree. * be found in the AUTHORS file in the root of the source tree.
*/ */
#include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h"
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <initializer_list> #include <initializer_list>
#include <vector> #include <vector>
#include "modules/rtp_rtcp/source/rtp_packetizer_av1_test_helper.h"
namespace webrtc { namespace webrtc {
Av1Obu::Av1Obu(uint8_t obu_type) : header_(obu_type | kAv1ObuSizePresentBit) {} Av1Obu::Av1Obu(uint8_t obu_type) : header_(obu_type | kAv1ObuSizePresentBit) {}

View File

@ -94,9 +94,8 @@ TEST(VideoRtpDepacketizerH264Test, SingleNaluSpsWithResolution) {
} }
TEST(VideoRtpDepacketizerH264Test, StapAKey) { TEST(VideoRtpDepacketizerH264Test, StapAKey) {
const NaluInfo kExpectedNalus[] = { {H264::kSps, 0, -1}, const NaluInfo kExpectedNalus[] = {
{H264::kPps, 1, 2}, {H264::kSps, 0, -1}, {H264::kPps, 1, 2}, {H264::kIdr, -1, 0}};
{H264::kIdr, -1, 0} };
// clang-format off: split example data on NAL unit boundaries. // clang-format off: split example data on NAL unit boundaries.
const uint8_t kPayload[] = { const uint8_t kPayload[] = {
H264::kStapA, // F=0, NRI=0, Type=24. H264::kStapA, // F=0, NRI=0, Type=24.

View File

@ -26,8 +26,7 @@ JVM* g_jvm;
struct { struct {
const char* name; const char* name;
jclass clazz; jclass clazz;
} loaded_classes[] = { } loaded_classes[] = {};
};
// Android's FindClass() is trickier than usual because the app-specific // Android's FindClass() is trickier than usual because the app-specific
// ClassLoader is not consulted when there is no app-specific frame on the // ClassLoader is not consulted when there is no app-specific frame on the

View File

@ -19,11 +19,13 @@ namespace webrtc {
namespace test { namespace test {
std::unique_ptr<VideoEncoderFactory> CreateObjCEncoderFactory() { std::unique_ptr<VideoEncoderFactory> CreateObjCEncoderFactory() {
return ObjCToNativeVideoEncoderFactory([[RTC_OBJC_TYPE(RTCVideoEncoderFactoryH264) alloc] init]); return ObjCToNativeVideoEncoderFactory(
[[RTC_OBJC_TYPE(RTCVideoEncoderFactoryH264) alloc] init]);
} }
std::unique_ptr<VideoDecoderFactory> CreateObjCDecoderFactory() { std::unique_ptr<VideoDecoderFactory> CreateObjCDecoderFactory() {
return ObjCToNativeVideoDecoderFactory([[RTC_OBJC_TYPE(RTCVideoDecoderFactoryH264) alloc] init]); return ObjCToNativeVideoDecoderFactory(
[[RTC_OBJC_TYPE(RTCVideoDecoderFactoryH264) alloc] init]);
} }
} // namespace test } // namespace test

View File

@ -25,8 +25,7 @@ VCMPacket::VCMPacket()
timesNacked(-1), timesNacked(-1),
completeNALU(kNaluUnset), completeNALU(kNaluUnset),
insertStartCode(false), insertStartCode(false),
video_header() { video_header() {}
}
VCMPacket::VCMPacket(const uint8_t* ptr, VCMPacket::VCMPacket(const uint8_t* ptr,
size_t size, size_t size,

View File

@ -148,8 +148,7 @@ int NackRequester::OnReceivedPacket(uint16_t seq_num) {
return OnReceivedPacket(seq_num, false); return OnReceivedPacket(seq_num, false);
} }
int NackRequester::OnReceivedPacket(uint16_t seq_num, int NackRequester::OnReceivedPacket(uint16_t seq_num, bool is_recovered) {
bool is_recovered) {
RTC_DCHECK_RUN_ON(worker_thread_); RTC_DCHECK_RUN_ON(worker_thread_);
// TODO(philipel): When the packet includes information whether it is // TODO(philipel): When the packet includes information whether it is
// retransmitted or not, use that value instead. For // retransmitted or not, use that value instead. For

View File

@ -254,8 +254,7 @@ std::string Vp9UncompressedHeader::ToString() const {
char buf[1024]; char buf[1024];
rtc::SimpleStringBuilder oss(buf); rtc::SimpleStringBuilder oss(buf);
oss << "Vp9UncompressedHeader { " oss << "Vp9UncompressedHeader { " << "profile = " << profile;
<< "profile = " << profile;
if (show_existing_frame) { if (show_existing_frame) {
oss << ", show_existing_frame = " << *show_existing_frame << " }"; oss << ", show_existing_frame = " << *show_existing_frame << " }";