【问题标题】:AVAssetWriter memory allocation skyrockets after movie creation电影创作后 AVAssetWriter 内存分配猛增
【发布时间】:2020-04-30 21:25:10
【问题描述】:

我的应用程序中有一个例程,它通过 AVAssetWriter 将 MTLTextures 捕获到电影中。当我在设备上运行应用程序时,内存管理似乎保持稳定,电影被创建并写入磁盘。但是,当我在 App Store 上发布该应用程序(并下载它)时,无论电影大小如何,该应用程序都会在电影创建后不久崩溃。通过仪器运行应用程序显示在从 MTLTextures 提取 PixelBuffer 的例程中发生了巨大的内存分配。这就是崩溃发生的地方。有问题的例程在我要记录的每个 MTLTexture 的循环中运行:

func AVAssetWriterEncodeFrame(forTexture texture: MTLTexture) {

    while !assetWriterVideoInput!.isReadyForMoreMediaData  {
    } // hang out here until isReadyForMoreMediaData == true

    autoreleasepool(invoking: { () -> () in

      let fps: Int32 = Int32(Constants.movieFPS)

      guard let pixelBufferPool = assetWriterPixelBufferInput!.pixelBufferPool else {
        print("[MovieMakerVC]: Pixel buffer asset writer input did not have a pixel buffer pool available; cannot retrieve frame")
        return
      }

      var maybePixelBuffer: CVPixelBuffer? = nil
      let status  = CVPixelBufferPoolCreatePixelBuffer(nil, pixelBufferPool, &maybePixelBuffer)
      if status != kCVReturnSuccess {
        print("[MovieMakerVC]: Could not get pixel buffer from asset writer input; dropping frame...")
        return
      }
      guard let pixelBuffer = maybePixelBuffer else { return }
      CVPixelBufferLockBaseAddress(pixelBuffer, [])
      let pixelBufferBytes = CVPixelBufferGetBaseAddress(pixelBuffer)!

      // Use the bytes per row value from the pixel buffer since its stride may be rounded up to be 16-byte aligned
      let bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer)
      let region = MTLRegionMake2D(0, 0, texture.width, texture.height)

      texture.getBytes(pixelBufferBytes, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)

      let presentationTime = CMTimeMake(value: Int64(frameIndexForPresentationTime), timescale: fps)

      assetWriterPixelBufferInput!.append(pixelBuffer, withPresentationTime: presentationTime)

      CVPixelBufferUnlockBaseAddress(pixelBuffer, [])

      frameIndexForPresentationTime += frameHoldLength  // set up for next frame

    }) // end of autoreleasepool

  } // end of func AVAssetWriterEncodeFrame(forTexture texture: MTLTexture)

在影片被写入磁盘后,图中看到的峰值无法控制地增长。分配列表显示了数以千计的条目,如下所示:

@autoreleasepool 内容。 ... 4 KiB AVFoundation。 -[AVAssetWriter 输入助手]。 (如上图所示)

有人能指出我做错了什么并希望如何解决它吗?

【问题讨论】:

  • 你能告诉我们分配列表,指出正在消耗内存的活动对象的类型,以及它们的分配位置吗?
  • 谢谢@warrenm。我添加了更多细节,希望能对问题有所了解。尽管我已经注意进行适当的内存管理,但我不确定为什么/在哪里没有释放或释放对象

标签: swift instruments allocation metal avassetwriter


【解决方案1】:

罪魁祸首竟然是这段代码:

而 !assetWriterVideoInput!.isReadyForMoreMediaData { } // 在这里闲逛直到 isReadyForMoreMediaData == true

事实证明,在 AVAssetWriterInputPixelBufferAdaptor 对象中测试这种情况的虚假性是一个非常糟糕的想法。

相反,将整个逻辑块包装如下:

var frameIsCaptured: Bool = false

while (assetWriterVideoInput!.isReadyForMoreMediaData && frameIsCaptured == false) {     
    ... // insert all the texture processing logic
    texture.getBytes(pixelBufferBytes, bytesPerRow: bytesPerRow, from: region, mipmapLevel: 0)
    ... // insert pixelBuffer ingestion logic
    frameIsCaptured = true. // needed so we only process this texture once
}

我之前所做的实现了同样的事情,即例程将无限循环,直到isReadyForMoreMediaData 变为真(此时我将完成将像素缓冲区附加到正在进行的电影所需的所有纹理工作),但该空循环所产生的荒谬开销似乎并不是要解决的设计缺陷。当然,Instruments 指出这个循环中存在问题,但我花了一段时间才看到结果。

【讨论】:

    猜你喜欢
    • 2022-06-22
    • 1970-01-01
    • 2023-03-30
    • 2018-12-14
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 2012-08-06
    • 2014-11-13
    相关资源
    最近更新 更多