首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Swift中将“自我”传递给接受“不安全突变的function”的函数?

如何在Swift中将“自我”传递给接受“不安全突变的function”的函数?
EN

Stack Overflow用户
提问于 2022-07-04 03:26:39
回答 1查看 50关注 0票数 0

我去年买了一台3D 4K投影仪,它使用了DLP-Link技术,它需要一个120 for左右交替的视频流来进行立体透视。

我正在使用核心视频在Swift中编写一个播放器,一个函数要求我向它传递一个UnsafeMutableRawPointer? (void * in Obj-C),并且我使用self关键字将视图实例传递给它。

这是我的密码:

代码语言:javascript
复制
//
//  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传递给显示链接回调造成的。那我该怎么解决呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-04 05:33:45

使用Unmanaged类。

setup_displaylink()

代码语言:javascript
复制
    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

代码语言:javascript
复制
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是在内部传递的。在适当的情况下使用“保留”函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72851478

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档