mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] improve the performance of ScreenCapturerSck
This commit is contained in:
@@ -72,13 +72,15 @@ class API_AVAILABLE(macos(14.0)) ScreenCapturerSckImpl : public ScreenCapturer {
|
|||||||
unsigned char *nv12_frame_ = nullptr;
|
unsigned char *nv12_frame_ = nullptr;
|
||||||
int width_ = 0;
|
int width_ = 0;
|
||||||
int height_ = 0;
|
int height_ = 0;
|
||||||
|
int fps_ = 30;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Called by SckHelper when shareable content is returned by ScreenCaptureKit. `content` will be
|
// Called by SckHelper when shareable content is returned by ScreenCaptureKit. `content` will be
|
||||||
// nil if an error occurred. May run on an arbitrary thread.
|
// 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);
|
||||||
|
void OnNewCVPixelBuffer(CVPixelBufferRef pixelBuffer, 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 from a
|
||||||
@@ -239,6 +241,7 @@ void ScreenCapturerSckImpl::OnShareableContentCreated(SCShareableContent *conten
|
|||||||
config.width = filter.contentRect.size.width * filter.pointPixelScale;
|
config.width = filter.contentRect.size.width * filter.pointPixelScale;
|
||||||
config.height = filter.contentRect.size.height * filter.pointPixelScale;
|
config.height = filter.contentRect.size.height * filter.pointPixelScale;
|
||||||
config.captureResolution = SCCaptureResolutionNominal;
|
config.captureResolution = SCCaptureResolutionNominal;
|
||||||
|
config.minimumFrameInterval = CMTimeMake(1, fps_);
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(lock_);
|
std::lock_guard<std::mutex> lock(lock_);
|
||||||
|
|
||||||
@@ -252,10 +255,12 @@ void ScreenCapturerSckImpl::OnShareableContentCreated(SCShareableContent *conten
|
|||||||
// TODO: crbug.com/327458809 - Choose an appropriate sampleHandlerQueue for
|
// TODO: crbug.com/327458809 - Choose an appropriate sampleHandlerQueue for
|
||||||
// best performance.
|
// best performance.
|
||||||
NSError *add_stream_output_error;
|
NSError *add_stream_output_error;
|
||||||
|
dispatch_queue_t queue = dispatch_queue_create("ScreenCaptureKit.Queue", DISPATCH_QUEUE_SERIAL);
|
||||||
bool add_stream_output_result = [stream_ addStreamOutput:helper_
|
bool add_stream_output_result = [stream_ addStreamOutput:helper_
|
||||||
type:SCStreamOutputTypeScreen
|
type:SCStreamOutputTypeScreen
|
||||||
sampleHandlerQueue:nil
|
sampleHandlerQueue:queue
|
||||||
error:&add_stream_output_error];
|
error:&add_stream_output_error];
|
||||||
|
|
||||||
if (!add_stream_output_result) {
|
if (!add_stream_output_result) {
|
||||||
stream_ = nil;
|
stream_ = nil;
|
||||||
LOG_ERROR("addStreamOutput failed");
|
LOG_ERROR("addStreamOutput failed");
|
||||||
@@ -279,12 +284,16 @@ void ScreenCapturerSckImpl::OnShareableContentCreated(SCShareableContent *conten
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenCapturerSckImpl::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionaryRef attachment) {
|
void ScreenCapturerSckImpl::OnNewCVPixelBuffer(CVPixelBufferRef pixelBuffer,
|
||||||
size_t width = IOSurfaceGetWidth(io_surface);
|
CFDictionaryRef attachment) {
|
||||||
size_t height = IOSurfaceGetHeight(io_surface);
|
size_t width = CVPixelBufferGetWidth(pixelBuffer);
|
||||||
|
size_t height = CVPixelBufferGetHeight(pixelBuffer);
|
||||||
|
|
||||||
uint32_t aseed;
|
CVReturn status = CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||||
IOSurfaceLock(io_surface, kIOSurfaceLockReadOnly, &aseed);
|
if (status != kCVReturnSuccess) {
|
||||||
|
LOG_ERROR("Failed to lock CVPixelBuffer base address: %d", status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
size_t required_size = width * height * 3 / 2;
|
size_t required_size = width * height * 3 / 2;
|
||||||
if (!nv12_frame_ || (width_ * height_ * 3 / 2 < required_size)) {
|
if (!nv12_frame_ || (width_ * height_ * 3 / 2 < required_size)) {
|
||||||
@@ -294,12 +303,26 @@ void ScreenCapturerSckImpl::OnNewIOSurface(IOSurfaceRef io_surface, CFDictionary
|
|||||||
height_ = height;
|
height_ = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(nv12_frame_, IOSurfaceGetBaseAddress(io_surface), width * height * 3 / 2);
|
void *base_y = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
|
||||||
|
size_t stride_y = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
|
||||||
|
|
||||||
|
void *base_uv = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
|
||||||
|
size_t stride_uv = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
|
||||||
|
|
||||||
|
unsigned char *dst_y = nv12_frame_;
|
||||||
|
for (size_t row = 0; row < height; ++row) {
|
||||||
|
memcpy(dst_y + row * width, static_cast<unsigned char *>(base_y) + row * stride_y, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *dst_uv = nv12_frame_ + width * height;
|
||||||
|
for (size_t row = 0; row < height / 2; ++row) {
|
||||||
|
memcpy(dst_uv + row * width, static_cast<unsigned char *>(base_uv) + row * stride_uv, width);
|
||||||
|
}
|
||||||
|
|
||||||
_on_data(nv12_frame_, width * height * 3 / 2, width, height,
|
_on_data(nv12_frame_, width * height * 3 / 2, width, height,
|
||||||
display_id_map_reverse_[current_display_]);
|
display_id_map_reverse_[current_display_]);
|
||||||
|
|
||||||
IOSurfaceUnlock(io_surface, kIOSurfaceLockReadOnly, &aseed);
|
CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
|
void ScreenCapturerSckImpl::StartOrReconfigureCapturer() {
|
||||||
@@ -349,15 +372,12 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
IOSurfaceRef ioSurface = CVPixelBufferGetIOSurface(pixelBuffer);
|
CFRetain(pixelBuffer);
|
||||||
if (!ioSurface) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFArrayRef attachmentsArray =
|
CFArrayRef attachmentsArray = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false);
|
||||||
CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, /*createIfNecessary=*/false);
|
if (!attachmentsArray || CFArrayGetCount(attachmentsArray) == 0) {
|
||||||
if (!attachmentsArray || CFArrayGetCount(attachmentsArray) <= 0) {
|
|
||||||
LOG_ERROR("Discarding frame with no attachments");
|
LOG_ERROR("Discarding frame with no attachments");
|
||||||
|
CFRelease(pixelBuffer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,8 +386,10 @@ std::unique_ptr<ScreenCapturer> ScreenCapturerSck::CreateScreenCapturerSck() {
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(_capturer_lock);
|
std::lock_guard<std::mutex> lock(_capturer_lock);
|
||||||
if (_capturer) {
|
if (_capturer) {
|
||||||
_capturer->OnNewIOSurface(ioSurface, attachment);
|
_capturer->OnNewCVPixelBuffer(pixelBuffer, attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFRelease(pixelBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)releaseCapturer {
|
- (void)releaseCapturer {
|
||||||
|
|||||||
Reference in New Issue
Block a user