The header file for MTAudioProcessingTap says that its initialization and prepare callbacks will be balanced by unprepare and finalize callbacks. However, in Apple's example, these callbacks never get called (I added logging to them to so I could check). The header file says they will be called when the object is deallocated.
In Apple's example, the Tap is passed into a retain parameter in audioMixInputParameters, which are passed into the audio mix, where it is no longer publicly accessible:
MTAudioProcessingTapRef audioProcessingTap;
if (noErr == MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &audioProcessingTap))
{
audioMixInputParameters.audioTapProcessor = audioProcessingTap;
CFRelease(audioProcessingTap);
audioMix.inputParameters = @[audioMixInputParameters];
_audioMix = audioMix;
}
I would expect AudioMix therefore to be responsible for releasing it in its own dealloc method, and for AudioMix to be released when the associated PlayerItem is released.
Apple's example uses an AVPlayer that only ever plays one item, so maybe it has no need to deallocate anything directly. But in my case, I'm using an AVQueuePlayer so I keep passing it new AVPlayerItems. I think it's leaking the Taps that I'm creating for each player item (along with associated audio units), even though the player items get deallocated.
What's the proper way to deallocate the MTAudioProcessingTap and get its unprepare and finalize callbacks to fire when I'm done with its associated player item?
Update: I found that it actually is still accessible through the audio mix, but releasing it like this doesn't trigger the unprepare and finalize callbacks:
((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor = nil;
Neither does this:
MTAudioProcessingTapRef audioProcessingTap = ((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor;
CFRelease(audioProcessingTap);
I had the same problem. To make it work, I had to reset the player item's audioMix
, the tap processor (MYAudioTapProcessor
in Apple's sample project) and manually release the MTAudioProcessingTapRef
:
MTAudioProcessingTapRef tap = ((AVMutableAudioMixInputParameters *)_audioTapProcessor.audioMix.inputParameters[0]).audioTapProcessor;
_player.currentItem.audioMix = nil;
_audioTapProcessor = nil;
CFRelease(tap);
This causes the finalize
callback to be invoked.
Edit: Seems like the CFRelease
is not required, see comments.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With