我正在尝试将帧从ARSession实时流传输到Firebase Storage,在帧被发送到Firebase之前,会对帧进行一些预处理,app的流程如下。
变量frameCount
用于命名数据库中的图像文件。我希望图像按照捕获时的顺序命名。文件上传成功,问题是:
1.它不是实时的,因为upload()异步运行并需要一些时间
1.图片没有按顺序上传。我希望它们按捕获时的顺序上传。异步部分做了一些与count
变量无关的事情。经过几个小时的调试,我发现count
的同一个值被多次用于不同的帧。上传到处都是。frameCount
达到100,但上传滞后5 - 10,然后,当我停止会话时,上传部分继续,但顺序随机,例如,它将上传文件98.jpg,下一个将是5.jpg
var frameCount = 0
func session(_ session: ARSession, didUpdate frame: ARFrame) {
frameCount += 1
DispatchQueue.async{
process(frame: frame, count: frameCount)
}
}
func process(frame: ARFrame, count: Int){
// all the processing happens here to get jpg data of the image
var imgData = ...
var fileURL = writeToFile(imageData: imgData, count: count)
upload(fileURL: fileURL, count: count)
}
func writeToFile(imageData: Data, count: Int)-> URL{
jpgFileURL = try getDirectory().appendingPathComponent("\(count).jpg")
try jpgData.write(to: jpgFileURL!)
return jpgFileURL
}
func upload(fileURL: URL, count: Int){
let imageFileRef = storageRef.child("\(count).jpg")
imageFileRef.putFile(from: fileURL) // this part runs asynchronously
}
我已经尝试了多种DispatchQueues、await/async关键字、TaskGroups等的变体,但似乎都不起作用。在核心,我只想递增frameCount
,将数据写入文件,并以顺序方式上传。下一帧的管道应该堆叠在前一帧的执行之上,并等待它成功上传。
1条答案
按热度按时间m3eecexj1#
如果没有别的,你需要确保在你的闭包中没有引用一个正在变化的属性。所以,举个例子,你需要引用
frameCount
的一个拷贝。要复制这个拷贝,使用一个“捕获列表”。所以......而是使用...
这仍然不会按顺序上载它们,但它将确保它们至少具有当前的、唯一的
frameCount
值,并因此得到正确的命名。现在,我不知道你要处理多少帧,但是这很容易遭受“线程爆炸”,而且一旦你有超过64帧的积压,它可能会表现得很奇怪。你可能想把它限制在一个合理的数字。你可以用
OperationQueue
:或Swift并发:
也有一些方法可以使这个任务按顺序运行(按顺序,一次一个),但是这会使它运行得更慢。我敢打赌,您已经跟不上您的“实时”目标了,而使这个异步任务按顺序运行可能只会使情况变得更糟。