使用 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 块中。似乎正在创建而不是释放图像缓冲区,这是内存峰值和随后崩溃的原因。
我正在尝试使用此问题中接受的答案中的方法读取视频帧:
然后我尝试在 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 块中。似乎正在创建而不是释放图像缓冲区,这是内存峰值和随后崩溃的原因。