Merge pull request #1214 from shogo4405/feature/fix-crash-audio-samplebuffer
Fix Rare crash of makeSampleBuffer
This commit is contained in:
commit
442077e218
|
@ -415,6 +415,10 @@
|
|||
BC83A4732403D83B006BDE06 /* VTCompressionSession+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC83A4722403D83B006BDE06 /* VTCompressionSession+Extension.swift */; };
|
||||
BC83A4742403D83B006BDE06 /* VTCompressionSession+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC83A4722403D83B006BDE06 /* VTCompressionSession+Extension.swift */; };
|
||||
BC83A4752403D83B006BDE06 /* VTCompressionSession+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC83A4722403D83B006BDE06 /* VTCompressionSession+Extension.swift */; };
|
||||
BC8446052A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8446042A30BE1600609FFD /* CMAudioSampleBufferUtil.swift */; };
|
||||
BC8446062A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8446042A30BE1600609FFD /* CMAudioSampleBufferUtil.swift */; };
|
||||
BC8446072A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8446042A30BE1600609FFD /* CMAudioSampleBufferUtil.swift */; };
|
||||
BC8446092A30BFC800609FFD /* CMAudioSampleBufferUtilTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC8446082A30BFC800609FFD /* CMAudioSampleBufferUtilTests.swift */; };
|
||||
BC959EEF296EE4190067BA97 /* ImageTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC959EEE296EE4190067BA97 /* ImageTransform.swift */; };
|
||||
BC959EF0296EE4190067BA97 /* ImageTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC959EEE296EE4190067BA97 /* ImageTransform.swift */; };
|
||||
BC959EF1296EE4190067BA97 /* ImageTransform.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC959EEE296EE4190067BA97 /* ImageTransform.swift */; };
|
||||
|
@ -777,6 +781,8 @@
|
|||
BC7C56CC29A786AE00C41A9B /* ADTS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADTS.swift; sourceTree = "<group>"; };
|
||||
BC7C56D029A78D4F00C41A9B /* ADTSHeaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ADTSHeaderTests.swift; sourceTree = "<group>"; };
|
||||
BC83A4722403D83B006BDE06 /* VTCompressionSession+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VTCompressionSession+Extension.swift"; sourceTree = "<group>"; };
|
||||
BC8446042A30BE1600609FFD /* CMAudioSampleBufferUtil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CMAudioSampleBufferUtil.swift; sourceTree = "<group>"; };
|
||||
BC8446082A30BFC800609FFD /* CMAudioSampleBufferUtilTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CMAudioSampleBufferUtilTests.swift; sourceTree = "<group>"; };
|
||||
BC959EEE296EE4190067BA97 /* ImageTransform.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTransform.swift; sourceTree = "<group>"; };
|
||||
BC959F0D29705B1B0067BA97 /* SCStreamPublishViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SCStreamPublishViewController.swift; sourceTree = "<group>"; };
|
||||
BC959F1129717EDB0067BA97 /* PreferenceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferenceViewController.swift; sourceTree = "<group>"; };
|
||||
|
@ -918,6 +924,7 @@
|
|||
298BCF321DD4C44A007FF86A /* AnyUtil.swift */,
|
||||
29DC17B221D0CC0600E26CED /* Atomic.swift */,
|
||||
29B876B81CD70B3900FC07DA /* ByteArray.swift */,
|
||||
BC8446042A30BE1600609FFD /* CMAudioSampleBufferUtil.swift */,
|
||||
29B876631CD70AB300FC07DA /* Constants.swift */,
|
||||
BC0D236C26331BAB001DDA0C /* DataBuffer.swift */,
|
||||
29B876671CD70AB300FC07DA /* DataConvertible.swift */,
|
||||
|
@ -964,6 +971,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
290EA8A41DFB61E700053022 /* ByteArrayTests.swift */,
|
||||
BC8446082A30BFC800609FFD /* CMAudioSampleBufferUtilTests.swift */,
|
||||
290EA8A51DFB61E700053022 /* CRC32Tests.swift */,
|
||||
BCC9E9082636FF7400948774 /* DataBufferTests.swift */,
|
||||
290EA8A61DFB61E700053022 /* EventDispatcherTests.swift */,
|
||||
|
@ -1912,6 +1920,7 @@
|
|||
BC44A1A923D31E92002D4297 /* AudioCodecRingBuffer.swift in Sources */,
|
||||
BC20DF38250377A3007BC608 /* IOUIScreenCaptureUnit.swift in Sources */,
|
||||
29B876AF1CD70B2800FC07DA /* RTMPChunk.swift in Sources */,
|
||||
BC8446052A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */,
|
||||
29B876841CD70AE800FC07DA /* AVCDecoderConfigurationRecord.swift in Sources */,
|
||||
296242621D8DB86500C451A3 /* TSWriter.swift in Sources */,
|
||||
BC9CFA9323BDE8B700917EEF /* NetStreamDrawable.swift in Sources */,
|
||||
|
@ -2017,6 +2026,7 @@
|
|||
295018201FFA1BD700358E10 /* AudioCodecTests.swift in Sources */,
|
||||
290EA8AC1DFB61E700053022 /* MD5Tests.swift in Sources */,
|
||||
290EA8A01DFB61B100053022 /* AMFFoundationTests.swift in Sources */,
|
||||
BC8446092A30BFC800609FFD /* CMAudioSampleBufferUtilTests.swift in Sources */,
|
||||
BC7C56892995082700C41A9B /* NetStreamTests.swift in Sources */,
|
||||
2917CB662104CA2800F6823A /* AudioSpecificConfigTests.swift in Sources */,
|
||||
290EA8AB1DFB61E700053022 /* EventDispatcherTests.swift in Sources */,
|
||||
|
@ -2112,6 +2122,7 @@
|
|||
29EA87EE1E79A3E30043A5F8 /* CVPixelBuffer+Extension.swift in Sources */,
|
||||
29B8770C1CD70D5A00FC07DA /* NetService.swift in Sources */,
|
||||
BC1DC5152A05428800E928ED /* HEVCNALUnit.swift in Sources */,
|
||||
BC8446062A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */,
|
||||
2958911B1EEB8E3F00CE51E1 /* FLVAudioCodec.swift in Sources */,
|
||||
BC4914A328DDD33D009E2DF6 /* VTSessionConvertible.swift in Sources */,
|
||||
293B42EA2340B4840086F973 /* RTMPObjectEncoding.swift in Sources */,
|
||||
|
@ -2236,6 +2247,7 @@
|
|||
BC83A4752403D83B006BDE06 /* VTCompressionSession+Extension.swift in Sources */,
|
||||
BC9CFA9523BDE8B700917EEF /* NetStreamDrawable.swift in Sources */,
|
||||
29EB3E031ED0585D001CAE8B /* AudioSpecificConfig.swift in Sources */,
|
||||
BC8446072A30BE1600609FFD /* CMAudioSampleBufferUtil.swift in Sources */,
|
||||
29EB3E141ED05889001CAE8B /* IOVideoUnit.swift in Sources */,
|
||||
29EB3E221ED059FD001CAE8B /* RTMPMessage.swift in Sources */,
|
||||
29EB3E001ED05854001CAE8B /* HTTPService.swift in Sources */,
|
||||
|
|
|
@ -86,47 +86,7 @@ final class IOAudioUnit: NSObject, IOUnit {
|
|||
guard 0 < numSamples else {
|
||||
return nil
|
||||
}
|
||||
var status: OSStatus = noErr
|
||||
var sampleBuffer: CMSampleBuffer?
|
||||
var timing = CMSampleTimingInfo(
|
||||
duration: CMTime(value: 1, timescale: presentationTimeStamp.timescale),
|
||||
presentationTimeStamp: presentationTimeStamp,
|
||||
decodeTimeStamp: .invalid
|
||||
)
|
||||
status = CMSampleBufferCreate(
|
||||
allocator: kCFAllocatorDefault,
|
||||
dataBuffer: nil,
|
||||
dataReady: true,
|
||||
makeDataReadyCallback: nil,
|
||||
refcon: nil,
|
||||
formatDescription: buffer.formatDescription,
|
||||
sampleCount: numSamples,
|
||||
sampleTimingEntryCount: 1,
|
||||
sampleTimingArray: &timing,
|
||||
sampleSizeEntryCount: 0,
|
||||
sampleSizeArray: nil,
|
||||
sampleBufferOut: &sampleBuffer
|
||||
)
|
||||
guard
|
||||
let sampleBuffer = sampleBuffer,
|
||||
let formatDescription = sampleBuffer.formatDescription, status == noErr else {
|
||||
return nil
|
||||
}
|
||||
guard let buffer = AVAudioPCMBuffer(pcmFormat: AVAudioFormat(cmAudioFormatDescription: formatDescription), frameCapacity: AVAudioFrameCount(numSamples)) else {
|
||||
return nil
|
||||
}
|
||||
buffer.frameLength = buffer.frameCapacity
|
||||
status = CMSampleBufferSetDataBufferFromAudioBufferList(
|
||||
sampleBuffer,
|
||||
blockBufferAllocator: kCFAllocatorDefault,
|
||||
blockBufferMemoryAllocator: kCFAllocatorDefault,
|
||||
flags: 0,
|
||||
bufferList: buffer.audioBufferList
|
||||
)
|
||||
guard status == noErr else {
|
||||
return nil
|
||||
}
|
||||
return sampleBuffer
|
||||
return CMAudioSampleBufferUtil.makeSampleBuffer(buffer, numSamples: numSamples, presentationTimeStamp: presentationTimeStamp)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
import CoreMedia
|
||||
import Foundation
|
||||
|
||||
enum CMAudioSampleBufferUtil {
|
||||
static func makeSampleBuffer(_ buffer: CMSampleBuffer, numSamples: Int, presentationTimeStamp: CMTime) -> CMSampleBuffer? {
|
||||
guard 0 < numSamples, let formatDescription = buffer.formatDescription, let streamBasicDescription = formatDescription.streamBasicDescription else {
|
||||
return nil
|
||||
}
|
||||
var status: OSStatus = noErr
|
||||
var blockBuffer: CMBlockBuffer?
|
||||
let blockSize = numSamples * Int(streamBasicDescription.pointee.mBytesPerPacket)
|
||||
status = CMBlockBufferCreateWithMemoryBlock(
|
||||
allocator: nil,
|
||||
memoryBlock: nil,
|
||||
blockLength: blockSize,
|
||||
blockAllocator: nil,
|
||||
customBlockSource: nil,
|
||||
offsetToData: 0,
|
||||
dataLength: blockSize,
|
||||
flags: 0,
|
||||
blockBufferOut: &blockBuffer
|
||||
)
|
||||
guard let blockBuffer, status == noErr else {
|
||||
return nil
|
||||
}
|
||||
status = CMBlockBufferFillDataBytes(
|
||||
with: 0,
|
||||
blockBuffer: blockBuffer,
|
||||
offsetIntoDestination: 0,
|
||||
dataLength: blockSize
|
||||
)
|
||||
guard status == noErr else {
|
||||
return nil
|
||||
}
|
||||
var sampleBuffer: CMSampleBuffer?
|
||||
status = CMAudioSampleBufferCreateWithPacketDescriptions(
|
||||
allocator: nil,
|
||||
dataBuffer: blockBuffer,
|
||||
dataReady: true,
|
||||
makeDataReadyCallback: nil,
|
||||
refcon: nil,
|
||||
formatDescription: formatDescription,
|
||||
sampleCount: numSamples,
|
||||
presentationTimeStamp: presentationTimeStamp,
|
||||
packetDescriptions: nil,
|
||||
sampleBufferOut: &sampleBuffer
|
||||
)
|
||||
guard let sampleBuffer, status == noErr else {
|
||||
return nil
|
||||
}
|
||||
return sampleBuffer
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
import Foundation
|
||||
import XCTest
|
||||
import CoreMedia
|
||||
|
||||
@testable import HaishinKit
|
||||
|
||||
final class CMAudioSampleBufferUtilTests: XCTestCase {
|
||||
func test48000_2chTest() {
|
||||
let streamBasicDescription = AudioStreamBasicDescription(
|
||||
mSampleRate: 48000.0,
|
||||
mFormatID: kAudioFormatLinearPCM,
|
||||
mFormatFlags: 0xc,
|
||||
mBytesPerPacket: 4,
|
||||
mFramesPerPacket: 1,
|
||||
mBytesPerFrame: 4,
|
||||
mChannelsPerFrame: 2,
|
||||
mBitsPerChannel: 16,
|
||||
mReserved: 0
|
||||
)
|
||||
if let buffer = makeSampleBuffer(streamBasicDescription) {
|
||||
XCTAssertNotNil(CMAudioSampleBufferUtil.makeSampleBuffer(buffer, numSamples: 1024, presentationTimeStamp: .zero))
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func test48000_4chTest() {
|
||||
let streamBasicDescription = AudioStreamBasicDescription(
|
||||
mSampleRate: 48000.0,
|
||||
mFormatID: kAudioFormatLinearPCM,
|
||||
mFormatFlags: 0xc,
|
||||
mBytesPerPacket: 8,
|
||||
mFramesPerPacket: 1,
|
||||
mBytesPerFrame: 8,
|
||||
mChannelsPerFrame: 4,
|
||||
mBitsPerChannel: 16,
|
||||
mReserved: 0
|
||||
)
|
||||
if let buffer = makeSampleBuffer(streamBasicDescription) {
|
||||
XCTAssertNotNil(CMAudioSampleBufferUtil.makeSampleBuffer(buffer, numSamples: 1024, presentationTimeStamp: .zero))
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func test48000_3chTest() {
|
||||
let streamBasicDescription = AudioStreamBasicDescription(
|
||||
mSampleRate: 48000.0,
|
||||
mFormatID: kAudioFormatLinearPCM,
|
||||
mFormatFlags: 0xc,
|
||||
mBytesPerPacket: 6,
|
||||
mFramesPerPacket: 1,
|
||||
mBytesPerFrame: 6,
|
||||
mChannelsPerFrame: 3,
|
||||
mBitsPerChannel: 16,
|
||||
mReserved: 0
|
||||
)
|
||||
if let buffer = makeSampleBuffer(streamBasicDescription) {
|
||||
XCTAssertNotNil(CMAudioSampleBufferUtil.makeSampleBuffer(buffer, numSamples: 1024, presentationTimeStamp: .zero))
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
func test48000_2chTest_mac() {
|
||||
let streamBasicDescription = AudioStreamBasicDescription(
|
||||
mSampleRate: 48000.0,
|
||||
mFormatID: kAudioFormatLinearPCM,
|
||||
mFormatFlags: 0x29,
|
||||
mBytesPerPacket: 4,
|
||||
mFramesPerPacket: 1,
|
||||
mBytesPerFrame: 4,
|
||||
mChannelsPerFrame: 1,
|
||||
mBitsPerChannel: 32,
|
||||
mReserved: 0
|
||||
)
|
||||
if let buffer = makeSampleBuffer(streamBasicDescription) {
|
||||
XCTAssertNotNil(CMAudioSampleBufferUtil.makeSampleBuffer(buffer, numSamples: 1024, presentationTimeStamp: .zero))
|
||||
} else {
|
||||
XCTFail()
|
||||
}
|
||||
}
|
||||
|
||||
private func makeSampleBuffer(_ streamBasicDescription: AudioStreamBasicDescription) -> CMSampleBuffer? {
|
||||
guard let formatDescription = try? CMAudioFormatDescription(audioStreamBasicDescription: streamBasicDescription) else {
|
||||
return nil
|
||||
}
|
||||
var status: OSStatus = noErr
|
||||
var blockBuffer: CMBlockBuffer?
|
||||
let blockSize = 1024 * Int(streamBasicDescription.mBytesPerPacket)
|
||||
status = CMBlockBufferCreateWithMemoryBlock(
|
||||
allocator: nil,
|
||||
memoryBlock: nil,
|
||||
blockLength: blockSize,
|
||||
blockAllocator: nil,
|
||||
customBlockSource: nil,
|
||||
offsetToData: 0,
|
||||
dataLength: blockSize,
|
||||
flags: 0,
|
||||
blockBufferOut: &blockBuffer
|
||||
)
|
||||
guard let blockBuffer, status == noErr else {
|
||||
return nil
|
||||
}
|
||||
status = CMBlockBufferFillDataBytes(with: 0, blockBuffer: blockBuffer, offsetIntoDestination: 0, dataLength: blockSize)
|
||||
guard status == noErr else {
|
||||
return nil
|
||||
}
|
||||
var sampleBuffer: CMSampleBuffer?
|
||||
status = CMAudioSampleBufferCreateWithPacketDescriptions(
|
||||
allocator: nil,
|
||||
dataBuffer: blockBuffer,
|
||||
dataReady: true,
|
||||
makeDataReadyCallback: nil,
|
||||
refcon: nil,
|
||||
formatDescription: formatDescription,
|
||||
sampleCount: 1024,
|
||||
presentationTimeStamp: CMTimeMake(value: 1024, timescale: Int32(streamBasicDescription.mSampleRate)),
|
||||
packetDescriptions: nil,
|
||||
sampleBufferOut: &sampleBuffer
|
||||
)
|
||||
guard let sampleBuffer, status == noErr else {
|
||||
return nil
|
||||
}
|
||||
return sampleBuffer
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue