使用 AVAssetReader 读取视频文件时,应用程序因内存利用率高而崩溃

App crashes due to high memory utilization when reading video file with AVAssetReader

我正在尝试使用此问题中接受的答案中的方法读取视频帧:

然后我尝试在 MetalKit MKTView 上按顺序显示这些帧(我尝试了常规 UIImage 视图,但视频根本不呈现)。问题是这只能工作几秒钟(大约 400 帧视频),之后应用程序崩溃并且视频停止播放。

这是视图控制器中的代码:

class MetalRenderViewController: UIViewController {
    var metalView: MetalRenderView!
    
    var videoFileReader: VideoFileReader?
    var videoUrl: URL!
    override func viewDidLoad() {
        super.viewDidLoad()
        metalView = MetalRenderView(frame: view.bounds, device: MTLCreateSystemDefaultDevice())
        view.addSubview(metalView)
        videoFileReader = VideoFileReader(videoUrl: videoUrl) { (image) in
            guard let image = image else {return}
            self.metalView.image = image

        }
        videoFileReader?.beginReadingAsset()
    }
    
}

下面是 videoFileReader 中的相关代码:

guard let track = asset.tracks(withMediaType: .video).first else {return}
let reader = try! AVAssetReader(asset: asset)
let output = AVAssetReaderTrackOutput(track: track, outputSettings: settings)
reader.add(output)
reader.startReading()

while let sampleBuffer = output.copyNextSampleBuffer() {
            guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
            DispatchQueue.main.async {
                let image = CIImage(cvImageBuffer: imageBuffer)
                self.callback(image)
                
            }
        }

我怀疑这个问题可能与高内存使用率有关,因为在调试器中内存使用率飙升至大约 1.5 GB,然后在崩溃后下降,尽管我没有看到任何内存警告。

这是错误日志:

2021-06-28 16:13:22.491431-0400 WorkoutApp[10844:2837856] [xpc] XPC error talking to pkd: Connection interrupted
2021-06-28 16:13:22.773817-0400 WorkoutApp[10844:2837835] [ServicesDaemonManager] interruptionHandler is called. -[FontServicesDaemonManager connection]_block_invoke
2021-06-28 16:13:28.057141-0400 WorkoutApp[10844:2837857] [lifecycle] [u 5485F2DA-5C8A-40DD-91A5-F248E652AA58:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin interrupted while in use.
2021-06-28 16:13:28.075489-0400 WorkoutApp[10844:2838140] [lifecycle] [u 5485F2DA-5C8A-40DD-91A5-F248E652AA58:m (null)] [com.apple.mobileslideshow.photo-picker(1.0)] Connection to plugin invalidated while in use.

如果有人可以帮助我降低内存使用率,或者建议一个更好的方法来完全做到这一点,我们将不胜感激。

编辑

更新标题以更具体地说明错误,删除金属渲染 类,这是一个红色鲱鱼。

通过确认删除 ViewController 和金属渲染 class 后问题仍然存在,我能够将此问题隔离到 VideoFileReader class 中的 while 循环。通过计算崩溃前读取的帧数并与调试器中的内存使用增长进行比较,我还能够确认崩溃确实是由于高内存使用率造成的。

最终解决问题的方法是将 while 循环体包装在 autoreleasepool 块中。似乎正在创建而不是释放图像缓冲区,这是内存峰值和随后崩溃的原因。