AVCaptureSession でマイク入力を得る / AudioBufferList.allocate() 後のメモリリーク
https://github.com/daisuke-t-jp/AVCaptureAudioDataOutputSampleBufferTesting
iOS でマイク入力を取得してみたかったので試してみた。↑が、そのサンプルプロジェクト。
今回、いろいろなプロジェクトを参考にしてやってみたのだが、気になる点がひとつ。
AVCaptureAudioDataOutputSampleBufferDelegate
の captureOutput()
を下のような感じで実装するパターンが多いのだが
extension ViewController: AVCaptureAudioDataOutputSampleBufferDelegate { func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { var blockBuffer: CMBlockBuffer? let audioBufferList = AudioBufferList.allocate(maximumBuffers: 1) CMSampleBufferGetAudioBufferListWithRetainedBlockBuffer( sampleBuffer, bufferListSizeNeededOut: nil, bufferListOut: audioBufferList.unsafeMutablePointer, bufferListSize: MemoryLayout<AudioBufferList>.size, blockBufferAllocator: nil, blockBufferMemoryAllocator: nil, flags: UInt32(kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment), blockBufferOut: &blockBuffer ) } }
AudioBufferList.allocate()
は
ということで free()
を要することがコメントされている。
これを Xcode の Instruments で実際に試してみると
やはりこんな感じでメモリリークを確認できた。
なので先ほどの AudioBufferList.allocate
の周りのコードはこんな感じに修正するとメモリリークが消える。(defer
はこんな風なリソース解放の時に便利だ)
let audioBufferList = AudioBufferList.allocate(maximumBuffers: 1) defer { free(audioBufferList.unsafeMutablePointer) }
・・・というリークが AVCaptureSession
のコードで参考にした https://github.com/google/science-journal-ios のプロジェクトでも起きていたので、この修正をプルリクエストしてみたら、レビューが通ってマージされたので、なんか一件落着という感じで落ち着きましたよ。