0

I am using the AudioFileOpenWithCallbacks function in my app to provide MP3 data in chunks. I call the function as follows:

AudioFileOpenWithCallbacks((__bridge void *)(self), TTMAudioFile_ReadProc, NULL, TTMAudioFile_GetSizeProc, NULL, 0, &aqData.mAudioFile);

In this case, self is the containing Objective-C class.

My TTMAudioFile_ReadProc callback function is as follows:

OSStatus TTMAudioFile_ReadProc(void *inClientData, SInt64 inPosition, UInt32 requestCount, void *buffer, UInt32 *actualCount) {

    TTMAudioQueuePlayer *this = (__bridge TTMAudioQueuePlayer *)inClientData;
    NSData *data = [this.decryptor dataAtOffset:inPosition length:requestCount error:NULL];
    memcpy(buffer, data.bytes, data.length);

    NSUInteger length = data.length;
    *actualCount = (UInt32)length;

    return noErr;
}

This works, but the NSData isn't being released. Profiling Allocations in Instruments reveal many allocations that look like the following:

enter image description here

Apparently there are two extra retain calls in my callback function, but I don't see where I can be retaining them. Furthermore, I am using ARC, so I don't know why this is happening either.

1actobacillus
  • 408
  • 4
  • 12

1 Answers1

0

I needed an autorelease pool.

The C callback function TTMAudioFile_ReadProc is called on a separate thread from the main thread. In this case, an autorelease pool is not automatically created, unlike when working with dispatch queues.

OSStatus TTMAudioFile_ReadProc(void *inClientData, SInt64 inPosition, UInt32 requestCount, void *buffer, UInt32 *actualCount) {
    @autoreleasepool {
        TTMAudioQueuePlayer *this = (__bridge TTMAudioQueuePlayer *)inClientData;
        NSData *data = [this.decryptor dataAtOffset:inPosition length:requestCount error:NULL];

        memcpy(buffer, data.bytes, data.length);
        NSUInteger length = data.length;
        *actualCount = (UInt32)length;

        return noErr;
    }
}
1actobacillus
  • 408
  • 4
  • 12