- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 IOSurface 支持的 CVPixelBuffer,它以 30fps 从外部源更新。我想在 NSView 中呈现图像数据的预览——对我来说最好的方法是什么?
我可以直接在 View 上设置 CALayer 的 .contents ,但这只会在我的 View 第一次更新时更新(或者说,如果我调整了 View 的大小)。我一直在仔细研究文档,但我无法弄清楚在图层或 View 上正确调用需求显示以让 View 基础结构知道刷新自身,尤其是当更新来自 View 外部时。
理想情况下,我只需将 IOSurface 绑定(bind)到我的层,我对其所做的任何更改都会被传播,但我不确定这是否可能。
class VideoPreviewController: NSViewController, VideoFeedConsumer {
let customLayer : CALayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
print("Loaded our video preview")
view.layer?.addSublayer(customLayer)
customLayer.frame = view.frame
// register our view with the browser service
VideoFeedBrowser.instance.registerConsumer(self)
}
override func viewWillDisappear() {
// deregister our view from the video feed
VideoFeedBrowser.instance.deregisterConsumer(self)
super.viewWillDisappear()
}
// This callback gets called at 30fps whenever the pixelbuffer is updated
@objc func updateFrame(pixelBuffer: CVPixelBuffer) {
guard let surface = CVPixelBufferGetIOSurface(pixelBuffer)?.takeUnretainedValue() else {
print("pixelbuffer isn't IOsurface backed! noooooo!")
return;
}
// Try and tell the view to redraw itself with new contents?
// These methods don't work
//self.view.setNeedsDisplay(self.view.visibleRect)
//self.customLayer.setNeedsDisplay()
self.customLayer.contents = surface
}
}
这是我对基于 NSView 而不是基于 NSViewController 的缩放版本的尝试,它也不能正确更新(或就此问题正确缩放):
class VideoPreviewThumbnail: NSView, VideoFeedConsumer {
required init?(coder decoder: NSCoder) {
super.init(coder: decoder)
self.wantsLayer = true
// register our view with the browser service
VideoFeedBrowser.instance.registerConsumer(self)
}
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.wantsLayer = true
// register our view with the browser service
VideoFeedBrowser.instance.registerConsumer(self)
}
deinit{
VideoFeedBrowser.instance.deregisterConsumer(self)
}
override func updateLayer() {
// Do I need to put something here?
print("update layer")
}
@objc
func updateFrame(pixelBuffer: CVPixelBuffer) {
guard let surface = CVPixelBufferGetIOSurface(pixelBuffer)?.takeUnretainedValue() else {
print("pixelbuffer isn't IOsurface backed! noooooo!")
return;
}
self.layer?.contents = surface
self.layer?.transform = CATransform3DMakeScale(
self.frame.width / CGFloat(CVPixelBufferGetWidth(pixelBuffer)),
self.frame.height / CGFloat(CVPixelBufferGetHeight(pixelBuffer)),
CGFloat(1))
}
}
我错过了什么?
最佳答案
也许我错了,但我认为你是在后台线程上更新你的 NSView 。 (我想 updateFrame
的回调在后台线程上)
如果我是对的,当你想更新 NSView 时,转换你的 pixelBuffer
到任何你想要的(NSImage?),然后在主线程上调度它。
伪代码(我不经常使用 CVPixelBuffer,所以我不确定这是转换为 NSImage 的正确方法)
let ciImage = CIImage(cvImageBuffer: pixelBuffer)
let context = CIContext(options: nil)
let width = CVPixelBufferGetWidth(pixelBuffer)
let height = CVPixelBufferGetHeight(pixelBuffer)
let cgImage = context.createCGImage(ciImage, from: CGRect(x: 0, y: 0, width: width, height: height))
let nsImage = NSImage(cgImage: cgImage, size: CGSize(width: width, height: height))
DispatchQueue.main.async {
// assign the NSImage to your NSView here
}
另一个捕获 : 我做了一些测试,似乎你不能将 IOSurface 直接分配给 CALayer 的内容。
let textureImageWidth = 1024
let textureImageHeight = 1024
let macPixelFormatString = "ARGB"
var macPixelFormat: UInt32 = 0
for c in macPixelFormatString.utf8.reversed() {
macPixelFormat *= 256
macPixelFormat += UInt32(c)
}
let ioSurface = IOSurfaceCreate([kIOSurfaceWidth: textureImageWidth,
kIOSurfaceHeight: textureImageHeight,
kIOSurfaceBytesPerElement: 4,
kIOSurfaceBytesPerRow: textureImageWidth * 4,
kIOSurfaceAllocSize: textureImageWidth * textureImageHeight * 4,
kIOSurfacePixelFormat: macPixelFormat] as CFDictionary)!
IOSurfaceLock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
let test = CIImage(ioSurface: ioSurface)
IOSurfaceUnlock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
v1?.layer?.contents = ioSurface
v1 是我的观点。没有效果
IOSurfaceLock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
let test = CIImage(ioSurface: ioSurface)
IOSurfaceUnlock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
v1?.layer?.contents = test
如果我创建一个 CGImage 它可以工作
IOSurfaceLock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
let test = CIImage(ioSurface: ioSurface)
IOSurfaceUnlock(ioSurface, IOSurfaceLockOptions.readOnly, nil)
let context = CIContext.init()
let img = context.createCGImage(test, from: test.extent)
v1?.layer?.contents = img
关于swift - 如何使用 CVPixelBuffer/IOSurface 更新 CALayer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64864430/
如何将一系列 IOSurfaces 绘制到另一个然后将其绘制到屏幕上?我在 MultiGPU 示例项目中尝试过一些来自苹果的源代码,但我设法做的最好的事情就是绘制一个白屏或获得大量的工件并使应用程序崩
这个问题是对: 的扩展链接-1:Creating an image out of the ios surface and saving it Link-2:Taking Screenshots fro
当我尝试编译我的调整时出现此错误。 'IOSurface/IOSurfaceAPI.h' file not found #include 我试过了 this answer ,但我在计算机上找不到 /
要使用快速屏幕截图,我需要执行一些 IOSurfaceRef 操作——使用 CARenderServerRenderDisplay(0, CFSTR("LCD"), iosurfaceref, 0,
如果我使用 IOSurface 框架为我的应用制作视频,苹果会拒绝我的应用吗 最佳答案 是的,如果您链接 IOSurface Apple 将拒绝您的应用程序。 商店中的一些项目正在使用它,但他们可
这是一个由两部分组成的问题。我有以下代码可以抓取当前显示表面并从表面创建视频(一切都在后台发生)。 for(int i=0;i<100;i++){ IOMobileFramebuf
对于我当前的项目,我正在读取 iPhone 的主摄像头输出。然后,我通过以下方法将像素缓冲区转换为缓存的 OpenGL 纹理:CVOpenGLESTextureCacheCreateTextureFr
写入IOSurface时需要使用哪些API,以及需要采取哪些预防措施在 XPC 进程中,该进程也被用作 MTLTexture 的后备存储。在主应用程序中? 在我的 XPC 服务中,我有以下内容: IO
我想使用 mipmapping 渲染 IOSurface 纹理。 我正在从 IOSurface 生成 OpenGL 纹理,如下所示: let error = CGLTexImageIOSurface2
我正在尝试修改 Apple MultiGPUIOSurface 示例(特别是文件 http://developer.apple.com/library/mac/#samplecode/MultiGPU
我正在尝试在 Swift 中创建一个 IOSurface,然后从中创建一个 CIImage。 IOSurfaceRef 看起来不错,但 CIImage 返回 nil: textureImage
我在 iOS 12 及更高版本的应用程序中遇到内存问题。 IOSurface 在 iOS 12.1.1 中同时逐渐增加,在 iOS 11 版本中运行良好。我在下面附上了问题截图, 为什么iOS 12版
我有一个 IOSurface 支持的 CVPixelBuffer,它以 30fps 从外部源更新。我想在 NSView 中呈现图像数据的预览——对我来说最好的方法是什么? 我可以直接在 View 上设
我正在尝试使用 CVPixelBufferCreateWithIOSurface 和从 IOSurfaceGetBaseAddressOfPlane 读取像素来捕获 IOSurface。 但是,在较新
我想从后台服务截屏。私有(private) API 很好,因为我不需要提交到应用商店。我已经尝试过 UIGetScreenImage,它在后台应用程序中不起作用。 我正在使用从 SO 获得的以下代码。
这个错误很奇怪。昨天一切都很好。我安装了Xcode 9 beta,然后我使用Xcode 8在iPhone 6p,iOS 9.3.2上运行我的应用程序(我昨天可以这样做,我可以仍然在模拟器上运行应用程序
当我运行我的项目时,你能帮我解决这个问题吗: Could not load IOSurface for time string. Rendering locally instead 我不知道我的编码是
在使用我的 ipad 应用程序时,我收到了一系列警告(Mar 18 11:18:06 kernel[0] : IOSurface warning: buffer allocation failed.
所以我从网络回调(voip 应用程序)中获取 3 个单独数组中的原始 YUV 数据。根据我的理解,您不能根据 here 使用 CVPixelBufferCreateWithPlanarBytes 创建
我收到 YUV 帧 (kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange),当从 CVPixelBufferRef 创建 CIImage 时,我得到: in
我是一名优秀的程序员,十分优秀!