【问题标题】:Swift: Message from debugger: Terminated due to memory issueSwift:来自调试器的消息:由于内存问题而终止
【发布时间】:2018-09-28 20:34:58
【问题描述】:

这个问题与Ios Xcode Message from debugger: Terminated due to memory issue 不同。我正在使用不同的设备,并且我的应用程序在前台被终止,此外我无法使用 Instruments 查看分配。

我正在尝试将许多 AVAsset 的短时间间隔合并到一个视频文件中。我需要对它们应用额外的过滤器和转换。

我实现了类,它可以使用一项资产并完全按照我的意愿制作所有内容,但是现在,当我尝试对许多(cca 7 aaset 仍然可以)更短的资产做同样的事情时(完整的持续时间可能会更短然后使用一项资产),应用程序崩溃,我只收到“来自调试器的消息:由于内存问题而终止”日志。

我无法使用大多数 Instruments 工具,因为应用程序会立即崩溃。我尝试了很多方法来解决它,但我没有成功,我非常感谢一些帮助。

谢谢

相关代码sn-ps在这里:

创作构图:

func export(toURL url: URL, callback: @escaping (_ url: URL?) -> Void){
    var lastTime = kCMTimeZero
    var instructions : [VideoFilterCompositionInstruction] = []
    let composition = AVMutableComposition()
    composition.naturalSize = CGSize(width: 1080, height: 1920)

    for (index, assetURL) in assets.enumerated() {
        let asset : AVURLAsset? = AVURLAsset(url: assetURL)
        guard let track: AVAssetTrack = asset!.tracks(withMediaType: AVMediaType.video).first else{callback(nil); return}

        let range = CMTimeRange(start: CMTime(seconds: ranges[index].lowerBound, preferredTimescale: 1000),
                                end: CMTime(seconds: ranges[index].upperBound, preferredTimescale: 1000))

        let videoTrack = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)!
        let audioTrack = composition.addMutableTrack(withMediaType: AVMediaType.audio, preferredTrackID: kCMPersistentTrackID_Invalid)!

        do{try videoTrack.insertTimeRange(range, of: track, at: lastTime)}
        catch _{callback(nil); return}

        if let audio = asset!.tracks(withMediaType: AVMediaType.audio).first{
            do{try audioTrack.insertTimeRange(range, of: audio, at: lastTime)}
            catch _{callback(nil); return}
        }

        let layerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
        layerInstruction.trackID = videoTrack.trackID

        let instruction = VideoFilterCompositionInstruction(trackID: videoTrack.trackID,
                                                            filters: self.filters,
                                                            context: self.context,
                                                            preferredTransform: track.preferredTransform,
                                                            rotate : false)
        instruction.timeRange = CMTimeRange(start: lastTime, duration: range.duration)
        instruction.layerInstructions = [layerInstruction]

        instructions.append(instruction)

        lastTime = lastTime + range.duration
    }

    let videoComposition = AVMutableVideoComposition()
    videoComposition.customVideoCompositorClass = VideoFilterCompositor.self
    videoComposition.frameDuration = CMTimeMake(1, 30)
    videoComposition.renderSize = CGSize(width: 1080, height: 1920)
    videoComposition.instructions = instructions

    let session: AVAssetExportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)!
    session.videoComposition = videoComposition
    session.outputURL = url
    session.outputFileType = AVFileType.mp4

    session.exportAsynchronously(){
        DispatchQueue.main.async{
            callback(url)
        }
    }

和 AVVideoCompositing 类的一部分:

func startRequest(_ request: AVAsynchronousVideoCompositionRequest){
    autoreleasepool() {
        self.getDispatchQueue().sync{
            guard let instruction = request.videoCompositionInstruction as? VideoFilterCompositionInstruction else{
                request.finish(with: NSError(domain: "jojodmo.com", code: 760, userInfo: nil))
                return
            }
            guard let pixels = request.sourceFrame(byTrackID: instruction.trackID) else{
                request.finish(with: NSError(domain: "jojodmo.com", code: 761, userInfo: nil))
                return
            }

            var image : CIImage? = CIImage(cvPixelBuffer: pixels)

            for filter in instruction.filters{
                filter.setValue(image, forKey: kCIInputImageKey)
                image = filter.outputImage ?? image
            }

            let newBuffer: CVPixelBuffer? = self.renderContext.newPixelBuffer()

            if let buffer = newBuffer{
                instruction.context.render(image!, to: buffer)
                request.finish(withComposedVideoFrame: buffer)
            }
            else{
                request.finish(withComposedVideoFrame: pixels)
            }
        }
    }

【问题讨论】:

  • 这些问题似乎无关。我只是收到相同的一般消息“由于内存问题而终止”。相信我,我已经在这里看到了所有可能相关的问题,并且我尝试了许多解决方案,但都没有奏效。 Instruments 中的内存使用率很低(大约 17 MB),我仍然可以在这里看到内存不足警报,但在应用程序中,didReceiveMemoryWarning 在崩溃前没有被触发,即使它是,我也不知道如何释放在这种情况下记忆。
  • 您是否有机会通过自定义 AVVideoCompositing 类解决旋转问题?它不尊重资产转换,请求中的所有 CIFilter 始终处于横向......我们坚持了一个多星期啊

标签: ios swift cifilter avasset avvideocomposition


【解决方案1】:

App返回内存警告时有一些规避措施。这是因为当我们试图处理大量数据时。

为了避免这种内存警告,我们必须养成使用[unowned self] 成绩单的习惯。

如果我们没有在闭包中使用这个[unowned self],那么我们会收到内存泄漏警告,并且在某个阶段,应用程序会崩溃。

您可以通过以下链接在[unowned self] 上找到更多信息: Shall we always use [unowned self] inside closure in Swift

添加[unowned self] 后,在您的类中添加deinit(){ } 函数并释放或消除不需要的数据。

【讨论】:

  • 不幸的是,即使使用 [unowned self]deinit() ,我仍然会收到内存不足警告和崩溃 :( 。这是 Instruments 的输出:!Instruments
  • 嘿Pratik,我已经发布了关于这个主题的问题。你有没有机会看看,也许可以帮助我和我的团队?我们被一个小问题困扰了好几天啊:stackoverflow.com/questions/51114201/…
猜你喜欢
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2018-07-21
  • 1970-01-01
  • 2021-01-04
  • 2018-03-12
  • 1970-01-01
  • 2016-08-18
相关资源
最近更新 更多