2013-10-05 10 views
5

Plik nagłówka dla MTAudioProcessingTap mówi, że jego inicjalizacja i przygotowanie wywołań zwrotnych zostanie zrównoważone przez nieprzygotowanie i sfinalizowanie wywołań zwrotnych. Jednak w Apple's example te wywołania zwrotne nigdy nie są wywoływane (dodałem do nich logowanie, aby sprawdzić). Plik nagłówkowy mówi, że zostaną wywołane, gdy obiekt zostanie zwolniony.Jak zwolnić MTAudioProcessingTap?

W przykładzie Apple, kranik jest przekazywana w parametrze utrzymać w audioMixInputParameters, które są przekazywane w mix audio, gdzie nie jest już publicznie dostępny:

MTAudioProcessingTapRef audioProcessingTap; 
if (noErr == MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PreEffects, &audioProcessingTap)) 
{ 
    audioMixInputParameters.audioTapProcessor = audioProcessingTap; 

    CFRelease(audioProcessingTap); 

    audioMix.inputParameters = @[audioMixInputParameters]; 

    _audioMix = audioMix; 
} 

spodziewałbym AudioMix zatem być odpowiedzialny do zwalniania go we własnej metodzie dealloc i do zwolnienia AudioMix po zwolnieniu powiązanego PlayerItem.

Przykład firmy Apple używa odtwarzacza AVP, który odtwarza tylko jeden element, więc może nie ma potrzeby deallocowania czegokolwiek bezpośrednio. Ale w moim przypadku używam AVQueuePlayer, więc ciągle przekazuję nowe AVPlayerItems. Myślę, że to wyciek z Tapsów, które tworzę dla każdego elementu gracza (wraz z powiązanymi z nim jednostkami dźwiękowymi), mimo że przedmioty gracza są zwalniane.

Jaki jest właściwy sposób na zwolnienie MTAudioProcessingTap i uzyskanie jego nieprzygotowania oraz sfinalizowanie wywołań zwrotnych w celu odpalenia, gdy skończę z powiązanym elementem gracza?

Aktualizacja: Okazało się, że to rzeczywiście jest wciąż dostępny za pośrednictwem Audio Mix, ale uwalniając go tak nie pociąga za sobą unprepare i sfinalizować zwrotnych:

((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor = nil; 

Ani robi to:

MTAudioProcessingTapRef audioProcessingTap = ((AVMutableAudioMixInputParameters *)audioMix.inputParameters[0]).audioTapProcessor; 
CFRelease(audioProcessingTap); 

Odpowiedz

7

Miałem ten sam problem. Aby to działało, musiałem zresetować element graczom audioMix, procesor z kranu (MYAudioTapProcessor w projekcie próbki Apple) i ręcznie zwolnić MTAudioProcessingTapRef:

MTAudioProcessingTapRef tap = ((AVMutableAudioMixInputParameters *)_audioTapProcessor.audioMix.inputParameters[0]).audioTapProcessor; 
_player.currentItem.audioMix = nil; 
_audioTapProcessor = nil; 
CFRelease(tap); 

Powoduje to finalize zwrotna powoływać.

Edit: Wygląda na CFRelease jest nie wymagane zobaczyć komentarze.

+1

Dziękujemy! Dodam, że powoduje to wywołanie callback bez przygotowania (przed sfinalizowaniem). Co więcej, mój playerItem był czasami zwalniany zbyt wcześnie (przed sfinalizowaniem oddzwaniania), więc dodałem silne odniesienie do playerItem w MYAudioTapProcessor i zamiast tego używam tego odnośnika. Więc zastąpiłem '_player.currentItem.audioMix = nil;' z '_audioTapProcessor.playerItem.audioMix = nil;'. – Tenfour04

+0

Dodam też, że nie powinieneś dzwonić do CFRelease'a, jeśli zamierzasz kontynuować korzystanie z AVPlayera, ponieważ kran jest wówczas zbyt długi. Gdy będziesz kontynuować odtwarzanie dźwięku za pomocą nowego dotknięcia, uruchomione zostaną nieprzygotowane i sfinalizowane oddzwanianie. – Tenfour04

+0

Masz rację, zredagowałem moją odpowiedź. – chris

Powiązane problemy