webrtc性能优化:MacOS下的快速截屏录屏方式
截屏和录屏现在已经变成了各个系统中最最基础的功能了,特别是直播的兴起和疫情促进的会议系统,诸如远程办公,都会使用到系统录屏的功能,录屏的快慢又决定了我们直播和会议的流畅程度。
最近各个大厂商也推出了很多屏幕截屏的优化方案。
对于远程录屏系统,在使用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下的快速截屏录屏方式相关推荐
- DXGI快速截屏录屏技术
DXGI快速截屏录屏技术 概述 很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...
- DXGI快速截屏录屏技术,高帧率直播桌面
DXGI快速截屏录屏技术 概述 很多地方都需要用到截屏/录屏技术,比如桌面直播,桌面录制等等.在微软Windows平台,有很多截屏的接口,不过大多数性能并不理想,Windows8以后微软引入了一套 ...
- iphone屏幕镜像如何全屏_苹果系统截屏录屏+标记剪辑功能详解( iPhone/iPad/Mac)
苹果系统中的截屏和录屏.标记和剪辑功能一如它的其他产品设计,做得非常细致.在我们日常的工作中,不免会遇到这些功能,今天小编就给大家详细讲解下苹果系统截屏录屏.标记剪辑功能,希望对大家有所帮助! 001 ...
- 苹果xr截屏怎么截_苹果系统截屏录屏+标记剪辑功能详解( iPhone/iPad/Mac)
苹果系统中的截屏和录屏.标记和剪辑功能一如它的其他产品设计,做得非常细致.在我们日常的工作中,不免会遇到这些功能,今天小编就给大家详细讲解下苹果系统截屏录屏.标记剪辑功能,希望对大家有所帮助! 001 ...
- Win10怎么截屏录屏?Win10截图方法大全 超强大的工具!
转载自奇它博客,原文链接:[http://qitablog.com/tips/win10怎么截屏录屏?win10截图方法大全-超强大的工具!.html ] [infobox title=" ...
- 巧用别名和 sh 脚本,adb 快速截图和录屏,提高你的效率
本文首发我的微信公众号程序员徐公,回复 徐公 666 可以获得我精心整理的简历模板,带你走近大厂 前言 在平时开发过程中,我们经常需要截图和录制视频,尤其是客户端开发和测试. 可能有一些人的姿势是这样 ...
- 【Ubuntu20.04】好用的快捷键\截屏录屏
unbuntu20.04好用的快捷键 快捷键很大程度上决定了一个产品的使用体验,作为一个刚刚接触linux的小白根据自身需求学习了一下在编码过程中ubuntu20.04可能会用到的一些,在这里和大家分 ...
- python+adb实现截屏/录屏功能
当测试一些物联网产品使用安卓系统,但系统界面没有像手机那么方便操作时,可以考虑使用adb命令实现对测试产品的截屏/录屏,adb shell screenrecord可以实现对安卓系统的录屏功能,截屏则 ...
- android 禁止截屏录屏功能,android 应用禁止截屏录屏
更新记录 1.0.0(2021-02-01) Android 应用禁止截屏录屏 平台兼容性 Android iOS 适用版本区间:4.4 - 11.0 × 原生插件通用使用流程: 购买插件,选择该插件 ...
最新文章
- 如果MySQL引起CPU消耗过大,你会怎么优化?
- Git 技术篇 - Github在项目分支里下载某个文件方法,Github项目里的单个js文件下载实例演示
- 05 前端HTTP协议(图解HTTP) 之 HTTP首部
- 文献记录(part12)--Biclustering of human cancer microarray data using co-similarity based co-clustering
- .NET RulesEngine(规则引擎)
- Mac OS 在远程主机(Linux 系统)上使用命令执行 sql 脚本文件(使用的是 MySQL 数据库)
- CSS 背景图片 设置居中
- 【BZOJ1095】捉迷藏,动态点分治
- web网页打印设计的CSS样式
- OC6_代理的基本概念
- Node.js学习9~Egg.js框架学习和部署实战
- angular报错:Maximum call stack size exceeded
- c语言 程序设计 题库答案 p,《C语言程序设计》复习题库答案.doc
- 论文笔记:CVPR2021 Bottom-Up Shift and Reasoning for Referring Image Segmentation
- 微型计算机3月2017,2017年3月计算机一级基础及MSOffice强化习题
- ESP32S蓝牙05
- 肉牛养殖前景好,他尝到甜头带富了贫困户
- Windows:直接使用命令运行一个程序
- 2021年中考计算机考试,2021年中考这样改革,初一初二考生需提前了解!
- 陈林接替张一鸣任今日头条CEO 字节跳动学谷歌进行架构升级
热门文章
- 实证研究的步骤_【财务实证研究方法】SAS05反腐败复制流程介绍
- Origin软件中Correlation function(关联/相关函数)原理剖析
- mac os如何批量删除xmind标记
- poj1985 / poj2631(树的直径)
- K近邻算法的Python实现
- 智能盘点,Yolo用于钢筋检测计数
- centOS7+Samba服务器配置
- 《伤寒论》——辨太阳病脉证并治(中)97条
- 处理warning:Each child in a list should have a unique “key” prop.
- 浪潮bcp oracle,浪潮BCP2.0集群管理软件维护手册.docx