ios - OpenTok iOS SDK 2.18.1 屏幕共享质量问题
问题描述
我们正在使用 ReplayKit 获取 CMSSampleBuffers 并将它们转发给 OTVideoCaptureConsumer,在将 ReplayKit 缓冲区大小调整为 1280x720 或 1024x768 缓冲区后,我们会获得屏幕共享提要,但它总是变得模糊。
在确保我们控制发送到 videoCaptureConsumer 的 FPS 以限制带宽之后,我们仍然无法从订阅设备上的媒体路由器接收到高质量的图像。
我们验证了发送到 OpenTok OTVideoCaptureConsumer 的图像是清晰的图像,但生成的流在订阅者端总是很快变得模糊
问题:任何人都想出一种方法来使用 OpenTok iOS SDK 获得干净的 OTPublisher 屏幕共享提要,而不管设备的屏幕尺寸如何?
尝试:
- 发送帧的不同方式:
我尝试使用 CVPixelBuffer 和 OTVideoFrame 发送图像。OpenTok 支持建议的示例对摄像机图像使用 CVPixelBuffer 方法,对黑色图像使用 OTVideoFrame 方法,当没有从摄像机接收到帧时。但无论哪种方式,结果流都会变得模糊
- 不同的格式和尺寸:
我没有找到任何提及 iOS SDK 预期图像规格的文档。有什么东西可以帮助我们了解支持的图像格式、数据大小限制和支持的分辨率吗?
我尝试将 ReplayKit 缓冲区按原样从我们的应用程序发送到 videoCaptureConsumer,例如:9.7 Pro iPad,本机屏幕分辨率为 1920x1440,这似乎被 iOS SDK 接受(返回成功),但只会在订户端。
我只是没有其他想法
- ReplayKit 停止发送帧时重传最后一帧:
我在 Twilio ReplayKit 示例中看到了这种行为,但是当 ReplayKit 不发送任何帧时,我们是否应该重新发送最后一帧?如果没问题,或者如果我们这样做,媒体路由器是否会正常运行,我没有看到任何文档
PS:我发现了一些参考资料,以防它可能对其他人有所帮助
我在OpenTok 的支持建议示例中看到的是:
iOS AVCaptureSession 支持的预设,然后转发到 OTVideoCapturer (Custom-Video-Driver/Lets-Build-OTPublisher/Single-Cam-Capturer/TBExampleVideoCapture.m#L255)
黑帧的硬编码大小(Custom-Video-Driver/Lets-Build-OTPublisher/Single-Cam-Capturer/TBExampleVideoCapture.m#L552)
未处理的 CMSampleBuffer 直接转发给 videoCaptureConsumer (Custom-Video-Driver/Lets-Build-OTPublisher/Single-Cam-Capturer/TBExampleVideoCapture.m#L711)
来自 OpenTok 的文档和论坛帖子:
OTPublisherKit文档提到 FPS 应为 5 FPS 或更低,并且代码本身
我还发现了一些其他有助于理解可能是什么问题的帖子:
可悲的是不是一个很好的...谁提到图像需要是“16的倍数”
解决方案
我最终使用 OTVideoFrame 发送图像并使用 DispatchWorkItem 实现重新发送最后一帧逻辑
// We just received a frame, cancel any retransmit
self.resetRetransmitTimer()
let resized = cgImage
self.checkPixelBufferSize(forImage: resized)
let ref = self.fillPixelBuffer(withCGImage: resized)
CVPixelBufferLockBaseAddress(ref, CVPixelBufferLockFlags.readOnly)
self.videoFrame?.format?.pixelFormat = .ARGB
self.videoFrame?.timestamp = timestamp
self.videoFrame?.format?.estimatedCaptureDelay = 10
self.videoFrame?.format?.estimatedFramesPerSecond = self.config.desiredFrameRate
self.videoFrame?.orientation = .up
self.videoFrame?.clearPlanes()
self.videoFrame?.planes?.addPointer(CVPixelBufferGetBaseAddress(ref))
self.videoCaptureConsumer?.consumeFrame(self.videoFrame!)
self.lastReplayKitImage = cgImage
self.lastReplayKitImageTimeStamp = timestamp
CVPixelBufferUnlockBaseAddress(ref, CVPixelBufferLockFlags.readOnly)
self.scheduleRetransmitTimer()
推荐阅读
- python - 如何用字符串解决python while语句错误?
- python - 根据与字典值的匹配,用字典中的键替换子列表中的元素
- android - 通过依赖注入添加 Fragment
- logstash - 如何在 logstash.conf 文件中添加 2 个字段
- python - 用 2captcha python selenium 解决 Hcaptcha
- python - 带有 Python 和 Google Colab 的 MS Word 文档
- sql - 在选择查询中根据年龄提取不同的行
- visual-studio-2019 - 如何摆脱 Visual Studio“未映射到任何依赖关系验证图”警告?
- servicestack - 根据传入的请求控制servicestack中的cookiedomain
- swift - 应用程序试图以模态方式呈现视图控制器
已经由 迅速