这段代码导致内存泄漏和应用程序崩溃:
var outputSamples = [Float]()
assetReader.startReading()
while assetReader.status == .reading {
let trackOutput = assetReader.outputs.first!
if let sampleBuffer = trackOutput.copyNextSampleBuffer(),
let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) {
let blockBufferLength = CMBlockBufferGetDataLength(blockBuffer)
let sampleLength = CMSampleBufferGetNumSamples(sampleBuffer) * channelCount(from: assetReader)
var data = Data(capacity: blockBufferLength)
data.withUnsafeMutableBytes { (blockSamples: UnsafeMutablePointer<Int16>) in
CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: blockBufferLength, destination: blockSamples)
CMSampleBufferInvalidate(sampleBuffer)
let processedSamples = process(blockSamples,
ofLength: sampleLength,
from: assetReader,
downsampledTo: targetSampleCount)
outputSamples += processedSamples
}
}
}
var paddedSamples = [Float](repeating: silenceDbThreshold, count: targetSampleCount)
paddedSamples.replaceSubrange(0..<min(targetSampleCount, outputSamples.count), with: outputSamples)这要归功于copyNextSampleBuffer()和创建规则。
反过来,我们不能在Swift中使用CFRelease()。链接到目标C唯一规则的原因是我所无法理解的。
有没有一种在Swift中手动发布CMSampleBuffer的方法?
发布于 2019-03-05 10:11:34
这并不是一个真正的解决方案,因为手动释放内存似乎是不可能的,并且在读取不安全的可变字节时,结合使用when循环和assetReader将不会释放内存。
这个问题通过一个解决办法得到了解决:在将音频文件公开给while循环之前,将其转换为CAF格式。
缺点:热秒时间越长,音频文件越长--时间越长。
优点:它只使用极少量的内存,这首先是问题所在。
灵感来自:https://stackoverflow.com/users/2907715/carpsen90 从音频文件中提取仪表电平的答案
发布于 2020-06-01 20:16:16
最近,我使用一个自动发布池解决了一个类似的问题。
尝试包装在自动释放池中使用sampleBuffer的区域。就像这样:
var outputSamples = [Float]()
assetReader.startReading()
while assetReader.status == .reading {
let trackOutput = assetReader.outputs.first!
autoreleasepool {
if let sampleBuffer = trackOutput.copyNextSampleBuffer(),
let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) {
let blockBufferLength = CMBlockBufferGetDataLength(blockBuffer)
let sampleLength = CMSampleBufferGetNumSamples(sampleBuffer) * channelCount(from: assetReader)
var data = Data(capacity: blockBufferLength)
data.withUnsafeMutableBytes { (blockSamples: UnsafeMutablePointer<Int16>) in
CMBlockBufferCopyDataBytes(blockBuffer, atOffset: 0, dataLength: blockBufferLength, destination: blockSamples)
CMSampleBufferInvalidate(sampleBuffer)
let processedSamples = process(blockSamples,
ofLength: sampleLength,
from: assetReader,
downsampledTo: targetSampleCount)
outputSamples += processedSamples
}
}
}
}
var paddedSamples = [Float](repeating: silenceDbThreshold, count: targetSampleCount)
paddedSamples.replaceSubrange(0..<min(targetSampleCount, outputSamples.count), with: outputSamples)如果我正确理解,一旦它超出了autoreleasepool的范围,sampleBuffer就会被释放。
https://stackoverflow.com/questions/54903278
复制相似问题