流式显示、转换它并在 window 中显示它?
Stream a display, transform it, and display it in a window?
我需要一个应用程序,作为一个体面的(我认为)Swift 开发者,我想我会尝试一下。
要点很简单:我想
- 捕获显示(CGDisplayStream?)
- 垂直翻转图像
- 在 window.
中显示翻转的流
我只是不确定从哪里开始?也许是 CGDisplayStream 或者 AVFoundation?有没有人有如何完成捕获显示流并将其显示在 window 中的示例代码?或者甚至是“使用这些classes/interfaces/apis”的指南来做到这一点?我已经 github 搜索了 CGDisplayStream.init 并没有真正想出任何例子:(
我不要求任何人为我写它,但我可以使用:从这里开始,使用这个,注意...
这是我目前正在试验的代码。我 认为? 我有步骤 1 和 2 的工作,但如果没有 #3 就很难说...
struct ContentView: View {
@State var displayStream: CGDisplayStream?
let backgroundQueue = DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
var body: some View {
VStack{
MetalView()
Text("Hello")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear{
self.displayStream = CGDisplayStream(dispatchQueueDisplay: 0, outputWidth: 100, outputHeight: 100,pixelFormat: Int32(k32BGRAPixelFormat), properties: nil, queue: backgroundQueue) { (status, code, iosurface, update) in
switch(status){
case .frameBlank:
print("FrameBlank")
break;
case .frameIdle:
print("FrameIdle")
break;
case .frameComplete:
print("FrameComplete")
var image = CIImage(ioSurface: iosurface!)
image = image.transformed(by: CGAffineTransform(scaleX: -1, y: 1))
break;
case .stopped:
print("Stopped")
break;
@unknown default:
print("Unknown Error")
}
}
displayStream?.start()
}
.onDisappear{
displayStream?.stop()
displayStream = nil
}
}
}
}
我创建了一个 mtkview NSViewRepresentable,如下所示:
import MetalKit
import SwiftUI
struct MetalView: NSViewRepresentable {
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: NSViewRepresentableContext<MetalView>) -> MTKView {
let mtkView = MTKView()
mtkView.delegate = context.coordinator
mtkView.preferredFramesPerSecond = 60
mtkView.enableSetNeedsDisplay = true
if let metalDevice = MTLCreateSystemDefaultDevice() {
mtkView.device = metalDevice
}
mtkView.framebufferOnly = false
mtkView.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
mtkView.drawableSize = mtkView.frame.size
mtkView.enableSetNeedsDisplay = true
return mtkView
}
func updateNSView(_ nsView: MTKView, context: NSViewRepresentableContext<MetalView>) {
}
class Coordinator : NSObject, MTKViewDelegate {
var parent: MetalView
var metalDevice: MTLDevice!
var metalCommandQueue: MTLCommandQueue!
init(_ parent: MetalView) {
self.parent = parent
if let metalDevice = MTLCreateSystemDefaultDevice() {
self.metalDevice = metalDevice
}
self.metalCommandQueue = metalDevice.makeCommandQueue()!
super.init()
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
guard let drawable = view.currentDrawable else {
return
}
let commandBuffer = metalCommandQueue.makeCommandBuffer()
let rpd = view.currentRenderPassDescriptor
rpd?.colorAttachments[0].clearColor = MTLClearColorMake(0, 1, 0, 1)
rpd?.colorAttachments[0].loadAction = .clear
rpd?.colorAttachments[0].storeAction = .store
let re = commandBuffer?.makeRenderCommandEncoder(descriptor: rpd!)
re?.endEncoding()
commandBuffer?.present(drawable)
commandBuffer?.commit()
}
}
}
这是我第一次用 metal 或 core image 做任何事情,我感觉自己摇摇欲坠 - 理解明智 -
看来您可以使用 Core Image 完成大部分工作:
CGDisplayStream
的处理程序给你一个 IOSurface
。您可以将其包装在 CIImage
和 CIImage(ioSurface:)
. 中
- 使用
image.transformed(by:)
. 将任何(或多个)CGAffineTransform
应用于 CIImage
- 使用
CIContext
将生成的图像渲染为 MTKView
。也许你可以从我的例子中得到一些启发 here.
注意:我不是 100% 确定 Core Image 是否会在您将其包装在 CIImage
中时为您正确保留 IOSurface
。如果您仍然需要执行 handler documentation 中描述的任何操作,您应该 double-check。
我需要一个应用程序,作为一个体面的(我认为)Swift 开发者,我想我会尝试一下。
要点很简单:我想
- 捕获显示(CGDisplayStream?)
- 垂直翻转图像
- 在 window. 中显示翻转的流
我只是不确定从哪里开始?也许是 CGDisplayStream 或者 AVFoundation?有没有人有如何完成捕获显示流并将其显示在 window 中的示例代码?或者甚至是“使用这些classes/interfaces/apis”的指南来做到这一点?我已经 github 搜索了 CGDisplayStream.init 并没有真正想出任何例子:(
我不要求任何人为我写它,但我可以使用:从这里开始,使用这个,注意...
这是我目前正在试验的代码。我 认为? 我有步骤 1 和 2 的工作,但如果没有 #3 就很难说...
struct ContentView: View {
@State var displayStream: CGDisplayStream?
let backgroundQueue = DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
var body: some View {
VStack{
MetalView()
Text("Hello")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.onAppear{
self.displayStream = CGDisplayStream(dispatchQueueDisplay: 0, outputWidth: 100, outputHeight: 100,pixelFormat: Int32(k32BGRAPixelFormat), properties: nil, queue: backgroundQueue) { (status, code, iosurface, update) in
switch(status){
case .frameBlank:
print("FrameBlank")
break;
case .frameIdle:
print("FrameIdle")
break;
case .frameComplete:
print("FrameComplete")
var image = CIImage(ioSurface: iosurface!)
image = image.transformed(by: CGAffineTransform(scaleX: -1, y: 1))
break;
case .stopped:
print("Stopped")
break;
@unknown default:
print("Unknown Error")
}
}
displayStream?.start()
}
.onDisappear{
displayStream?.stop()
displayStream = nil
}
}
}
}
我创建了一个 mtkview NSViewRepresentable,如下所示:
import MetalKit
import SwiftUI
struct MetalView: NSViewRepresentable {
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeNSView(context: NSViewRepresentableContext<MetalView>) -> MTKView {
let mtkView = MTKView()
mtkView.delegate = context.coordinator
mtkView.preferredFramesPerSecond = 60
mtkView.enableSetNeedsDisplay = true
if let metalDevice = MTLCreateSystemDefaultDevice() {
mtkView.device = metalDevice
}
mtkView.framebufferOnly = false
mtkView.clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0)
mtkView.drawableSize = mtkView.frame.size
mtkView.enableSetNeedsDisplay = true
return mtkView
}
func updateNSView(_ nsView: MTKView, context: NSViewRepresentableContext<MetalView>) {
}
class Coordinator : NSObject, MTKViewDelegate {
var parent: MetalView
var metalDevice: MTLDevice!
var metalCommandQueue: MTLCommandQueue!
init(_ parent: MetalView) {
self.parent = parent
if let metalDevice = MTLCreateSystemDefaultDevice() {
self.metalDevice = metalDevice
}
self.metalCommandQueue = metalDevice.makeCommandQueue()!
super.init()
}
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {
}
func draw(in view: MTKView) {
guard let drawable = view.currentDrawable else {
return
}
let commandBuffer = metalCommandQueue.makeCommandBuffer()
let rpd = view.currentRenderPassDescriptor
rpd?.colorAttachments[0].clearColor = MTLClearColorMake(0, 1, 0, 1)
rpd?.colorAttachments[0].loadAction = .clear
rpd?.colorAttachments[0].storeAction = .store
let re = commandBuffer?.makeRenderCommandEncoder(descriptor: rpd!)
re?.endEncoding()
commandBuffer?.present(drawable)
commandBuffer?.commit()
}
}
}
这是我第一次用 metal 或 core image 做任何事情,我感觉自己摇摇欲坠 - 理解明智 -
看来您可以使用 Core Image 完成大部分工作:
CGDisplayStream
的处理程序给你一个IOSurface
。您可以将其包装在CIImage
和CIImage(ioSurface:)
. 中
- 使用
image.transformed(by:)
. 将任何(或多个) - 使用
CIContext
将生成的图像渲染为MTKView
。也许你可以从我的例子中得到一些启发 here.
CGAffineTransform
应用于 CIImage
注意:我不是 100% 确定 Core Image 是否会在您将其包装在 CIImage
中时为您正确保留 IOSurface
。如果您仍然需要执行 handler documentation 中描述的任何操作,您应该 double-check。