Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

AVAssetWriterInput Crash on appendSampleBuffer Converting PCM

Overview

We are producing audio in real time from an editing application and are trying to put that on an HLS stream. We attempt to submit PCM samples through an audio writer but are getting a crash after a select number of samples have been appended.

Depending on the number of audio frames in the PCM buffer, we might get more iterations before the crash but it always has the same traceback (see below).

Code

The setup is rather simple. We took inspiration from a few sources around the web.

NSMutableDictionary *audio = [[NSMutableDictionary alloc] init];
[audio setObject:@(kAudioFormatMPEG4AAC) forKey:AVFormatIDKey];

[audio setObject:[NSNumber numberWithInt:config.audioSampleRate] // 48000
          forKey:AVSampleRateKey];
[audio setObject:[NSNumber numberWithInt:config.audioChannels] // 2
          forKey:AVNumberOfChannelsKey];

[audio setObject:@160000 forKey:AVEncoderBitRateKey];

m_audioConfig = [[NSDictionary alloc] initWithDictionary:audio];

m_audio = [[AVAssetWriterInput alloc] initWithMediaType:AVMediaTypeAudio
                                              outputSettings:m_audioConfig];

AVAudioFrameCount audioFrames = BUFFER_SAMPLES * bCount;
AVAudioPCMBuffer *pcmBuffer = [[AVAudioPCMBuffer alloc] initWithPCMFormat:m_full.pcmFormat
                                                            frameCapacity:audioFrames];
pcmBuffer.frameLength = pcmBuffer.frameCapacity;


AudioChannelLayout layout;
memset(&layout, 0, sizeof(layout));
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;

CMFormatDescriptionRef format;
OSStatus stats = CMAudioFormatDescriptionCreate(
    kCFAllocatorDefault,
    pcmBuffer.format.streamDescription,
    sizeof(layout),
    &layout,
    0,
    nil,
    nil,
    &format
);

for (int i = 0; i < bCount; i++)
{
    AudioPCM pcm;
    audioCallback->callback(pcm);
    memcpy(*(pcmBuffer.int16ChannelData) + (bufferSize * i), pcm.data, bufferSize);
}


size_t samplesConsumed = BUFFER_SAMPLES * bCount;

CMSampleBufferRef sampleBuffer;
CMSampleTimingInfo timing;
timing.duration = CMTimeMake(1, config.audioSampleRate);
timing.presentationTimeStamp = presentationTime;
timing.decodeTimeStamp = kCMTimeInvalid;

OSStatus ostatus = CMSampleBufferCreate(
    kCFAllocatorDefault,
    nil,
    false,
    nil,
    nil,
    format,
    (CMItemCount)pcmBuffer.frameLength,
    1,
    &timing,
    0,
    nil,
    &sampleBuffer
);

////

ostatus = CMSampleBufferSetDataBufferFromAudioBufferList(
    sampleBuffer,
    kCFAllocatorDefault,
    kCFAllocatorDefault,
    kCMSampleBufferFlag_AudioBufferList_Assure16ByteAlignment,
    pcmBuffer.audioBufferList
);
if (ostatus != noErr)
{
    NSLog(@"fill audio sample from buffer list failed: %s", logAudioError(ostatus));
    return;
}

ostatus = CMSampleBufferSetDataReady(sampleBuffer);
if (ostatus != noErr)
{
    NSLog(@"set sample buffer ready failed: %s", logAudioError(ostatus));
    return;
}

// Finally we can attach it, then shove the presentation time forward
[m_audio appendSampleBuffer:sampleBuffer];

The Crash

The crash points towards some level of deallocation when the conversion tooling is done or has enough samples to process an output packet? It's had to say.

0   caulk                         	       0x1a1e9532c caulk::alloc::tiered_allocator<caulk::alloc::size_range_tier<0ul, 1008ul, caulk::alloc::tree_allocator<caulk::alloc::chunk_allocator<caulk::alloc::page_allocator, caulk::alloc::bitmap_allocator, caulk::alloc::embed_block_memory, 16384ul, 16ul, 6ul>>>, caulk::alloc::size_range_tier<1009ul, 256000ul, caulk::alloc::guarded_edges_allocator<caulk::alloc::consolidating_free_map<caulk::alloc::page_allocator, 10485760ul>, 4ul>>, caulk::alloc::tracking_allocator<caulk::alloc::page_allocator>>::deallocate(caulk::alloc::block, unsigned long) + 636
1   AudioToolboxCore              	       0x1993fbfe4 ExtendedAudioBufferList_Destroy + 112
2   AudioToolboxCore              	       0x1993d5fe0 std::__1::__optional_destruct_base<ACCodecOutputBuffer, false>::~__optional_destruct_base[abi:ne180100]() + 68
3   AudioToolboxCore              	       0x1993d5f48 acv2::CodecConverter::~CodecConverter() + 196
4   AudioToolboxCore              	       0x1993d5e5c acv2::CodecConverter::~CodecConverter() + 16
5   AudioToolboxCore              	       0x1992574d8 std::__1::vector<std::__1::unique_ptr<acv2::AudioConverterBase, std::__1::default_delete<acv2::AudioConverterBase>>, std::__1::allocator<std::__1::unique_ptr<acv2::AudioConverterBase, std::__1::default_delete<acv2::AudioConverterBase>>>>::__clear[abi:ne180100]() + 84
6   AudioToolboxCore              	       0x199259acc acv2::AudioConverterChain::RebuildConverterChain(acv2::ChainBuildSettings const&) + 116
7   AudioToolboxCore              	       0x1992596ec acv2::AudioConverterChain::SetProperty(unsigned int, unsigned int, void const*) + 1808
8   AudioToolboxCore              	       0x199324acc acv2::AudioConverterV2::setProperty(unsigned int, unsigned int, void const*) + 84
9   AudioToolboxCore              	       0x199327f08 with_resolved(OpaqueAudioConverter*, caulk::function_ref<int (AudioConverterAPI*)>) + 60
10  AudioToolboxCore              	       0x1993281e4 AudioConverterSetProperty + 72
11  MediaToolbox                  	       0x1a7566c2c FigSampleBufferProcessorCreateWithAudioCompression + 2296
12  MediaToolbox                  	       0x1a754db08 0x1a70b5000 + 4819720
13  MediaToolbox                  	       0x1a754dab4 FigMediaProcessorCreateForAudioCompressionWithFormatWriter + 100
14  MediaToolbox                  	       0x1a77ebb98 0x1a70b5000 + 7564184
15  MediaToolbox                  	       0x1a7804158 0x1a70b5000 + 7663960
16  MediaToolbox                  	       0x1a7801da0 0x1a70b5000 + 7654816
17  AVFCore                       	       0x1ada530c4 -[AVFigAssetWriterTrack addSampleBuffer:error:] + 192
18  AVFCore                       	       0x1ada55164 -[AVFigAssetWriterAudioTrack _flushPendingSampleBuffersReturningError:] + 500
19  AVFCore                       	       0x1ada55354 -[AVFigAssetWriterAudioTrack addSampleBuffer:error:] + 472
20  AVFCore                       	       0x1ada4ebf0 -[AVAssetWriterInputWritingHelper appendSampleBuffer:error:] + 128
21  AVFCore                       	       0x1ada4c354 -[AVAssetWriterInput appendSampleBuffer:] + 168
22  lib_devapple_hls.dylib      	       0x115d2c7cc detail::AppleHLSImplementation::audioRuntime() + 1052
23  lib_devapple_hls.dylib      	       0x115d2d094 void* std::__1::__thread_proxy[abi:ne180100]<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct>>, void (detail::AppleHLSImplementation::*)(), detail::AppleHLSImplementation*>>(void*) + 72
24  libsystem_pthread.dylib       	       0x196e5b2e4 _pthread_start + 136

Any insight would be welcome!

@mmccartney,

Can you provide a focused sample project that reproduces the crash?

-- Greg

@mmccartney,

We suspect this may have been caused by an issue that was fixed in a recent software update. Could you please check to see if you can still reproduce the crash after updating?

Thanks!

-- rhymu

AVAssetWriterInput Crash on appendSampleBuffer Converting PCM
 
 
Q