截屏和录屏现在已经变成了各个系统中最最基础的功能了,特别是直播的兴起和疫情促进的会议系统,诸如远程办公,都会使用到系统录屏的功能,录屏的快慢又决定了我们直播和会议的流畅程度。

最近各个大厂商也推出了很多屏幕截屏的优化方案。

对于远程录屏系统,在使用webrtc中,碰到了一些问题,比较明显的一点是,在macos系统中,进行远程投屏的时候,帧数上不去,只能维持在20帧左右,甚至有的时候更低。在排查问题的时候,看了下底层的源代码。

macos中如果系统自带的截屏方式的话,那么用的是如下的代码:

// static
std::unique_ptr<DesktopFrameCGImage> DesktopFrameCGImage::CreateForDisplay(CGDirectDisplayID display_id) {// Create an image containing a snapshot of the display.rtc::ScopedCFTypeRef<CGImageRef> cg_image(CGDisplayCreateImage(display_id));if (!cg_image) {return nullptr;}return DesktopFrameCGImage::CreateFromCGImage(cg_image);
}

webrtc 使用的是CGDisplayCreateImage 系统api 进行截屏,但是发现在macos下还有其他的截屏录屏方式,我们依次的进行对比。

CGDisplayCreateImage

CGDisplayCreateImage 可以排除特定窗口,直接截取当前屏幕的图像,使用的方法如下:

- (void)CGDisplayCreateImageDesktop {uint32_t displayID = [self getDirectDisplayID];[self displayInfo:displayID];dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{while ( !self.isCancel ) {CGImageRef image = CGDisplayCreateImage(displayID);CGDataProviderRef provider = CGImageGetDataProvider(image);CGDataProviderCopyData(provider);CFRelease(image);[self calculateFps];}});
}

测试了下,在Catalina下,可以达到60帧左右的,CGDisplayCreateImage 不能控制具体的帧数,占用的cpu比较高,录屏中的鼠标无法去除。

AVCaptureScreenInput

如果之前有做过摄像头采集的话,那么使用AVCaptureScreenInput进行录屏,你会觉得熟悉很多。用AVCaptureSession 来调用屏幕截屏,屏幕截屏的数据就会在回调中。使用的方式如下:

- (void)captureDesktopWithCaptureScreenInput {_captureSession = [[AVCaptureSession alloc] init];AVCaptureVideoDataOutput* captureOutput = [[AVCaptureVideoDataOutput alloc] init];NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;NSNumber* val = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:val forKey:key];captureOutput.videoSettings = videoSettings;if ([_captureSession canAddOutput:captureOutput]) {[_captureSession addOutput:captureOutput];}[captureOutput setSampleBufferDelegate:selfqueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];NSArray* currentInputs = [_captureSession inputs];// remove current inputif ([currentInputs count] > 0) {AVCaptureInput* currentInput = (AVCaptureInput*)[currentInputs objectAtIndex:0];[_captureSession removeInput:currentInput];}// now create capture session input out of AVCaptureDeviceuint32_t count = 0;CGDirectDisplayID displayIDs[3] = {0};CGGetOnlineDisplayList(3, displayIDs, &count);AVCaptureScreenInput* newCaptureInput = [[AVCaptureScreenInput alloc] initWithDisplayID:displayIDs[0]];newCaptureInput.minFrameDuration = CMTimeMake(1, 120);// try to add our new capture device to the capture session[_captureSession beginConfiguration];BOOL addedCaptureInput = NO;if ([_captureSession canAddInput:newCaptureInput]) {[_captureSession addInput:newCaptureInput];addedCaptureInput = YES;} else {addedCaptureInput = NO;}[_captureSession commitConfiguration];
}- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {const int kFlags = 0;CVImageBufferRef videoFrame = CMSampleBufferGetImageBuffer(sampleBuffer);if (CVPixelBufferLockBaseAddress(videoFrame, kFlags) != kCVReturnSuccess) {return;}CVPixelBufferUnlockBaseAddress(videoFrame, kFlags);count_pic++;if (count_pic > 1000) {count_pic = 0;}[self calculateFps];
}

newCaptureInput.minFrameDuration = CMTimeMake(1, 120); 中,把帧率设置为120 ,当然实际的可能达不到这么大,在这台Catalina下,基本可以达到100帧左右,他同时也可以控制鼠标是否出现,占用的cpu并不高。
在回调captureOutput 中,给出了CVImageBufferRef 格式的数据,方便我们的调用。

但是在webrtc中,并没有AVCaptureScreenInput,改怎么添加进去呢?

其实也比较简单,如果你熟悉了webrtc中,macos下的摄像头推流方式,同样的你也可以在 captureOutput 中进行推流。

var peerConnectionFactory: RTCPeerConnectionFactory?var localVideoSource: RTCVideoSource?var videoCapturer: RTCVideoCapturer?func setupVideoCapturer(){// localVideoSource and videoCapturer will use localVideoSource = self.peerConnectionFactory!.videoSource() videoCapturer = RTCVideoCapturer()//      localVideoSource.capturer(videoCapturer, didCapture: videoFrame!)let videoTrack : RTCVideoTrack =   self.peerConnectionFactory!.videoTrack(with: localVideoSource, trackId: "100")let mediaStream: RTCMediaStream = (self.peerConnectionFactory?.mediaStream(withStreamId: "1"))!mediaStream.addVideoTrack(videoTrack)self.newPeerConnection!.add(mediaStream)}override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) {switch sampleBufferType {case RPSampleBufferType.video:// create the CVPixelBufferlet pixelBuffer:CVPixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!;// create the RTCVideoFramevar videoFrame:RTCVideoFrame?;let timestamp = NSDate().timeIntervalSince1970 * 1000videoFrame = RTCVideoFrame(pixelBuffer: pixelBuffer, rotation: RTCVideoRotation._0, timeStampNs: Int64(timestamp))// connect the video frames to the WebRTClocalVideoSource.capturer(videoCapturer, didCapture: videoFrame!)break}}

webrtc性能优化:MacOS下的快速截屏录屏方式相关推荐

  1. DXGI快速截屏录屏技术

    DXGI快速截屏录屏技术 概述   很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...

  2. DXGI快速截屏录屏技术,高帧率直播桌面

    DXGI快速截屏录屏技术 概述   很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...

  3. iphone屏幕镜像如何全屏_苹果系统截屏录屏+标记剪辑功能详解( iPhone/iPad/Mac)

    苹果系统中的截屏和录屏.标记和剪辑功能一如它的其他产品设计,做得非常细致.在我们日常的工作中,不免会遇到这些功能,今天小编就给大家详细讲解下苹果系统截屏录屏.标记剪辑功能,希望对大家有所帮助! 001 ...

  4. 苹果xr截屏怎么截_苹果系统截屏录屏+标记剪辑功能详解( iPhone/iPad/Mac)

    苹果系统中的截屏和录屏.标记和剪辑功能一如它的其他产品设计,做得非常细致.在我们日常的工作中,不免会遇到这些功能,今天小编就给大家详细讲解下苹果系统截屏录屏.标记剪辑功能,希望对大家有所帮助! 001 ...

  5. Win10怎么截屏录屏?Win10截图方法大全 超强大的工具!

    转载自奇它博客,原文链接:[http://qitablog.com/tips/win10怎么截屏录屏?win10截图方法大全-超强大的工具!.html ‎] [infobox title=" ...

  6. 巧用别名和 sh 脚本,adb 快速截图和录屏,提高你的效率

    本文首发我的微信公众号程序员徐公,回复 徐公 666 可以获得我精心整理的简历模板,带你走近大厂 前言 在平时开发过程中,我们经常需要截图和录制视频,尤其是客户端开发和测试. 可能有一些人的姿势是这样 ...

  7. 【Ubuntu20.04】好用的快捷键\截屏录屏

    unbuntu20.04好用的快捷键 快捷键很大程度上决定了一个产品的使用体验,作为一个刚刚接触linux的小白根据自身需求学习了一下在编码过程中ubuntu20.04可能会用到的一些,在这里和大家分 ...

  8. python+adb实现截屏/录屏功能

    当测试一些物联网产品使用安卓系统,但系统界面没有像手机那么方便操作时,可以考虑使用adb命令实现对测试产品的截屏/录屏,adb shell screenrecord可以实现对安卓系统的录屏功能,截屏则 ...

  9. android 禁止截屏录屏功能,android 应用禁止截屏录屏

    更新记录 1.0.0(2021-02-01) Android 应用禁止截屏录屏 平台兼容性 Android iOS 适用版本区间:4.4 - 11.0 × 原生插件通用使用流程: 购买插件,选择该插件 ...

最新文章

  1. 如果MySQL引起CPU消耗过大,你会怎么优化?
  2. Git 技术篇 - Github在项目分支里下载某个文件方法,Github项目里的单个js文件下载实例演示
  3. 05 前端HTTP协议(图解HTTP) 之 HTTP首部
  4. 文献记录(part12)--Biclustering of human cancer microarray data using co-similarity based co-clustering
  5. .NET RulesEngine(规则引擎)
  6. Mac OS 在远程主机(Linux 系统)上使用命令执行 sql 脚本文件(使用的是 MySQL 数据库)
  7. CSS 背景图片 设置居中
  8. 【BZOJ1095】捉迷藏,动态点分治
  9. web网页打印设计的CSS样式
  10. OC6_代理的基本概念
  11. Node.js学习9~Egg.js框架学习和部署实战
  12. angular报错:Maximum call stack size exceeded
  13. c语言 程序设计 题库答案 p,《C语言程序设计》复习题库答案.doc
  14. 论文笔记:CVPR2021 Bottom-Up Shift and Reasoning for Referring Image Segmentation
  15. 微型计算机3月2017,2017年3月计算机一级基础及MSOffice强化习题
  16. ESP32S蓝牙05
  17. 肉牛养殖前景好,他尝到甜头带富了贫困户
  18. Windows:直接使用命令运行一个程序
  19. 2021年中考计算机考试,2021年中考这样改革,初一初二考生需提前了解!
  20. 陈林接替张一鸣任今日头条CEO 字节跳动学谷歌进行架构升级

热门文章

  1. 实证研究的步骤_【财务实证研究方法】SAS05反腐败复制流程介绍
  2. Origin软件中Correlation function(关联/相关函数)原理剖析
  3. mac os如何批量删除xmind标记
  4. poj1985 / poj2631(树的直径)
  5. K近邻算法的Python实现
  6. 智能盘点,Yolo用于钢筋检测计数
  7. centOS7+Samba服务器配置
  8. 《伤寒论》——辨太阳病脉证并治(中)97条
  9. 处理warning:Each child in a list should have a unique “key” prop.
  10. 浪潮bcp oracle,浪潮BCP2.0集群管理软件维护手册.docx