首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何手动发布CMSampleBuffer

如何手动发布CMSampleBuffer
EN

Stack Overflow用户
提问于 2019-02-27 10:27:19
回答 2查看 1.4K关注 0票数 3

这段代码导致内存泄漏和应用程序崩溃:

代码语言:javascript
复制
    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的方法?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-03-05 10:11:34

这并不是一个真正的解决方案,因为手动释放内存似乎是不可能的,并且在读取不安全的可变字节时,结合使用when循环和assetReader将不会释放内存。

这个问题通过一个解决办法得到了解决:在将音频文件公开给while循环之前,将其转换为CAF格式。

缺点:热秒时间越长,音频文件越长--时间越长。

优点:它只使用极少量的内存,这首先是问题所在。

灵感来自:https://stackoverflow.com/users/2907715/carpsen90 从音频文件中提取仪表电平的答案

票数 1
EN

Stack Overflow用户

发布于 2020-06-01 20:16:16

最近,我使用一个自动发布池解决了一个类似的问题。

尝试包装在自动释放池中使用sampleBuffer的区域。就像这样:

代码语言:javascript
复制
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就会被释放。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54903278

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档