将 12 个 ARFrame 添加到数组后 ARSCNView 冻结(iOS/Swift)

崔振宇*_*崔振宇 3 iphone ios scenekit swift arkit

我有一个ARSCNViewViewController.swift我想将它保存ARFrames到一个预先分配的数组中

func session(_ session: ARSession, didUpdate frame: ARFrame)
Run Code Online (Sandbox Code Playgroud)

但是,在处理大约 11-13 后ARFrames,整个ARSCNView将通过使用冻结

self.ARFrames.append(frame)
Run Code Online (Sandbox Code Playgroud)

奇怪的是,func session(_ session: ARSession, didFailWithError error: Error)在此过程中没有调用,也没有报告任何其他错误,应用程序没有崩溃,所有其他用户控件都可以正常工作,只有ARSCNView冻结和didpUdate 事件不会被调用。类似于ARSCNView 在添加具有强引用的 14 个 ARAnchor 子类对象时冻结,但那里的页面没有解决方案。同时也是应用后转到后台并返回,sessionWasInterrupted(:)sessionInterruptionEnded(:)被称为,即使现场查看被冻结之前。这是iOS 11的错误吗?

这是我在我的应用程序中使用的完整代码。

import UIKit

class ViewController: UIViewController,ARSCNViewDelegate,ARSessionDelegate {
    @IBOutlet var sceneView: ARSCNView!
    let configuration = ARFaceTrackingConfiguration()
    var ARFrames = [ARFrame]()
    var imgCount = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        ARFrames.reserveCapacity(300)
        sceneView.delegate = self
        sceneView.session.delegate = self
        sceneView.session.run(configuration, options: [.resetTracking, .removeExistingAnchors])
    }

    func session(_ session: ARSession, didUpdate frame: ARFrame) {
        if (frame.capturedDepthData == nil || self.imgCount >= 300){
            return
        }
        DispatchQueue.global().async {
            self.ARFrames.append(frame)
            self.imgCount += 1
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

ric*_*ter 5

每个都ARFrame包含直接来自相机捕获系统的视频帧(在其capturedImage属性中)。

捕获系统提供的每个帧都来自一个固定大小的内存池,捕获系统会在会话继续时重用这些内存池。如捕获文档中所述

如果多个样本缓冲区引用此类内存池的时间过长,则输入将不再能够将新样本复制到内存中,并且这些样本将被删除。

如果您的应用程序通过将提供的 CMSampleBuffer 对象保留太久而导致样本被丢弃,但它需要长时间访问样本数据,请考虑将数据复制到新缓冲区,然后释放样本缓冲区(如果它以前被保留了),以便它引用的内存可以被重用。

通过将ARFrame你得到的所有s添加到一个数组中,你声称拥有(即保留)它们的像素缓冲区,并最终使内存捕获系统饿死以写入新帧。 ARKit 需要连续的视频流,所以你的 AR会话放弃。

解决方案?不要抓住所有这些框架。仅将您需要的任何信息从每个帧复制到您自己的数据结构中。