我去年买了一台3D 4K投影仪,它使用了DLP-Link技术,它需要一个120 for左右交替的视频流来进行立体透视。
我正在使用核心视频在Swift中编写一个播放器,一个函数要求我向它传递一个UnsafeMutableRawPointer? (void * in Obj-C),并且我使用self关键字将视图实例传递给它。
这是我的密码:
//
// MovieView.swift
// Studio Media Player
//
// Created by DannyNiu on 2022-07-03.
//
import Foundation
import Cocoa
import AVFoundation
import CoreVideo
class MovieView : NSView
{
var asset: AVAsset?
var player: AVPlayer?
var item: AVPlayerItem?
var vout: AVPlayerItemVideoOutput?
var cvpb: CVPixelBuffer?
var cii: CIImage?
var cgi: CGImage?
var irect: CGRect?
var vlink: CVDisplayLink?
func setup_displaylink() -> Bool
{
var cvret: CVReturn
cvret = CVDisplayLinkCreateWithActiveCGDisplays(&vlink)
if( vlink == nil ) { return false }
var me: MovieView = self
cvret = CVDisplayLinkSetOutputCallback(
vlink!, vlink_callback, &me)
if( cvret == kCVReturnSuccess ) {
return true
} else { return false }
}
func assign_asset(_ asset: AVAsset)
{
self.asset = asset
item = .init(asset: asset)
player = .init(playerItem: item)
vout = .init()
cvpb = nil
cii = nil
}
func video_render(_ d: CVTimeStamp)
{
let t: CMTime = player!.currentTime()
let cgc: CGContext = (NSGraphicsContext.current?.cgContext)!
let cic: CIContext = (NSGraphicsContext.current?.ciContext)!
if( vout?.hasNewPixelBuffer(forItemTime: t) ?? false )
{
cvpb = vout?.copyPixelBuffer(
forItemTime: t, itemTimeForDisplay: nil)
cii = .init(cvPixelBuffer: cvpb!)
irect = cii!.extent
cgi = cic.createCGImage(cii!, from: irect!)
}
if( irect == nil ) { return }
let orect: CGRect = NSRectToCGRect(bounds)
var vrect: CGRect =
CGRect(origin: orect.origin,
size: CGSize(width: orect.width * 2,
height: irect!.height *
orect.width /
irect!.width))
cgc.setFillColor(gray:0, alpha:1)
cgc.fill(orect)
if( d.videoTime % 2 == 1 )
{
vrect = vrect.offsetBy(dx: -orect.width, dy: 0)
}
cgc.draw(cgi!, in: vrect)
}
}
func vlink_callback(
displayLink: CVDisplayLink,
inNow: UnsafePointer<CVTimeStamp>,
inOutputTime: UnsafePointer<CVTimeStamp>,
flagsIn: CVOptionFlags,
flagsOut: UnsafeMutablePointer<CVOptionFlags>,
arg_mvview: UnsafeMutableRawPointer?
) -> CVReturn
{
let mvview: MovieView = arg_mvview!.load(as: MovieView.self)
mvview.video_render(inNow.pointee)
return kCVReturnSuccess
}当我调试程序时,mvview.video_render(inNow.pointee)行使用code = 1导致了一个EXC_BAD_ACCESS陷阱。我认为这是由于我没有正确地将self传递给显示链接回调造成的。那我该怎么解决呢?
发布于 2022-07-04 05:33:45
使用Unmanaged类。
在setup_displaylink()中
func setup_displaylink() -> Bool
{
var cvret: CVReturn
cvret = CVDisplayLinkCreateWithActiveCGDisplays(&vlink)
if( vlink == nil ) { return false }
var me: UnsafeMutableRawPointer =
Unmanaged.passUnretained(self).toOpaque()
cvret = CVDisplayLinkSetOutputCallback(
vlink!, vlink_callback, &me)
if( cvret == kCVReturnSuccess ) {
return true
} else { return false }
}在vlink_callback中
func vlink_callback(
displayLink: CVDisplayLink,
inNow: UnsafePointer<CVTimeStamp>,
inOutputTime: UnsafePointer<CVTimeStamp>,
flagsIn: CVOptionFlags,
flagsOut: UnsafeMutablePointer<CVOptionFlags>,
arg_mvview: UnsafeMutableRawPointer?
) -> CVReturn
{
let mvview: MovieView =
Unmanaged.fromOpaque(arg_mvview!).takeUnretainedValue()
mvview.video_render(inNow.pointee)
return kCVReturnSuccess
}注意,我使用了“未保留”函数,因为没有必要添加到电影视图的引用计数中,因为self是在内部传递的。在适当的情况下使用“保留”函数。
https://stackoverflow.com/questions/72851478
复制相似问题