2017-09-22 15 views
0

audioTap example from appleと同様のaudioTapProcessorを使用しています。iOS11でaudioTapProcessorを正しく停止して削除する方法

基本的には、audioTapProcessorが作成され、audioMixに追加されます。audioMixが作成されると

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

    CFRelease(audioProcessingTap); 

    audioMix.inputParameters = @[audioMixInputParameters]; 

    _audioMix = audioMix; 
} 

、それはavPlayerののCurrentItemに追加されます:私は

self.avPlayer.currentItem.audioMix = audioMix; 

audioTapProcessorで行われた場合、audioTapProcessorとaudioMixへの参照を削除します。

if (self.avPlayer.currentItem.audioMix){ 

    for (AVMutableAudioMixInputParameters *inputParameter in player.currentItem.audioMix.inputParameters) { 
     inputParameter.audioTapProcessor = nil; 

    } 

    player.currentItem.audioMix = nil; 
} 

これにより、tap_UnprepareCallbacktap_FinalizeCallback関数が起動され、audioTapProcessorオブジェクトgetの割り当てが解除されます。

これは数日前にiOS11が出てくるまで問題なく動作しました。

iOS11デバイスでは、ClientProcessingTapManagerスレッドでEXC_BAD_ACCESSエラーが発生することがあります。このエラーはAVFoundationのクラスの1つで発生するため、デバッグできません。エラーはClientProcessingTap :: PerformTapのどこかで発生します。

audioTapコールバックにログを追加しました。これは、ClientProcessingTapManagerスレッドでtap_ProcessCallBackだけが実行されたようです。

audioTapProcessorのtap_ProcessCallbackメソッドがこのスレッドでトリガーされることがありますが、実際のaudioTapProcessorはすでに別のスレッドで割り当て解除されていることがあります。

質問:私は正しくaudioTapProcessorを停止し、メモリから削除できますか?


これは、いくつかの例の出力ログです:私はavPlayersのプールをUSNGので、私は、これらのオブジェクトを再利用しています

:知って良い

2017-09-22 12:49:26:171 xx[1261:780894] cleaning up audioMix of AvPlayer 
2017-09-22 12:49:26:213 xx[1261:781173] into tap_ProcessCallback. thread: ClientProcessingTapManager 
2017-09-22 12:49:26:213 xx[1261:781173] end of tap_ProcessCallback 
2017-09-22 12:49:26:217 xx[1261:781127] into tap_UnprepareCallback. 
2017-09-22 12:49:26:218 xx[1261:781127] end of tap_UnprepareCallback 
2017-09-22 12:49:26:218 xx[1261:781127] into tap_FinalizeCallback. 
2017-09-22 12:49:26:218 Tunify[1261:781127] end of tap_FinalizeCallback 
2017-09-22 12:49:26:218 Tunify[1261:781127] into MYAudioTapProcessor dealloc. 
(lldb) 

。私のavPlayersのaudioMixを取り除かないと、私はこのエラーに遭遇しません。 audioMixオブジェクトのクリーンアップがなければ、audioTapProcessorsは、avPlayerを再利用して新しいaudioMixをavPlayerに割り当てるときにのみ割り当てが解除されます。


related questionが見つかりましたが、すでにクリーンアップ機能を起動しています。そこの解決策はiOS11デバイスで同じエラーを表示します

答えて

0

これはiOS 11のAVFoundationのバグです。Appleに報告する必要があります。 rdar://34977000

可能な回避策がprepareReleaseAudioMix呼び出すことです問題のレーダー:ちょうどAVPlayer/AVPlayerItem

+ (void)prepareReleaseAudioMix:(AVAudioMix*)audioMix { 
    if (@available(iOS 11.0, *)) { 
     // Starting with iOS 11, it is not required to manually nil audioTapProcessor, 
     // but we need to retain the audioMix for a bit to make sure the processing callback 
     // will not be called after we release (this is due to a bug in iOS 11 which calls the release 
     // callback but still calls the processing callback afterwards - it also releases internal data 
     // on release, so simply checking for release in the processing block is not enough) 
     // rdar://34977000 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
      [self _prepareReleaseAudioMixNow:audioMix]; 
     }); 
    } else { 
     // Prior to iOS 11 we need to manually nil the audioTapProcessor 
     [self _prepareReleaseAudioMixNow:audioMix]; 
    } 
} 

+ (void)_prepareReleaseAudioMixNow:(AVAudioMix*)audioMix { 
    for (AVMutableAudioMixInputParameters *parameters in audioMix.inputParameters) { 
     if (![parameters isKindOfClass:[AVMutableAudioMixInputParameters class]]) 
      continue; 
     parameters.audioTapProcessor = nil; 
    } 
} 
を解放する前に、
関連する問題