title: Getting PCM data of HLS from AVPlayer
body: <p>This question seems to be asked few times over last few years but none has answer for that. I am trying to process PCM data from HLS and I have to use AVPlayer. </p>
  
  <p>this post taps the local files
  <a href="https://chritto.wordpress.com/2013/01/07/processing-avplayers-audio-with-mtaudioprocessingtap/">https://chritto.wordpress.com/2013/01/07/processing-avplayers-audio-with-mtaudioprocessingtap/</a></p>
  
  <p>and this tap work with remote files but not with .m3u8 hls files. 
  <a href="http://venodesigns.net/2014/01/08/recording-live-audio-streams-on-ios/">http://venodesigns.net/2014/01/08/recording-live-audio-streams-on-ios/</a></p>
  
  <p>I can play first two tracks in the playlist but it doesn't start the needed callbacks to get the pcm, when the file is local or remote(not stream) I can still get the pcm but it is the hls is not working and I need HLS working</p>
  
  <p>here is my code</p>
  
  <pre><code>//avplayer tap try
  - (void)viewDidLoad {
      [super viewDidLoad];
  
      NSURL*testUrl= [NSURL URLWithString:@"http://playlists.ihrhls.com/c5/1469/playlist.m3u8"];
  
      AVPlayerItem *item = [AVPlayerItem playerItemWithURL:testUrl];
      self.player = [AVPlayer playerWithPlayerItem:item];
  
      // Watch the status property - when this is good to go, we can access the
      // underlying AVAssetTrack we need.
      [item addObserver:self forKeyPath:@"status" options:0 context:nil];
  
  }
  
  -(void)observeValueForKeyPath:(NSString *)keyPath
  ofObject:(id)object
  change:(NSDictionary *)change
  context:(void *)context
  {
      if(![keyPath isEqualToString:@"status"])
          return;
  
      AVPlayerItem *item = (AVPlayerItem *)object;
      if(item.status != AVPlayerItemStatusReadyToPlay)
          return;
  
      NSArray *tracks = [self.player.currentItem tracks];
      for(AVPlayerItemTrack *track in tracks) {
          if([track.assetTrack.mediaType isEqualToString:AVMediaTypeAudio]) {
              NSLog(@"GOT DAT FUCKER");
              [self beginRecordingAudioFromTrack:track.assetTrack];
              [self.player play];
          }
      }
  }
  
  - (void)beginRecordingAudioFromTrack:(AVAssetTrack *)audioTrack
  {
      // Configure an MTAudioProcessingTap to handle things.
      MTAudioProcessingTapRef tap;
      MTAudioProcessingTapCallbacks callbacks;
      callbacks.version = kMTAudioProcessingTapCallbacksVersion_0;
      callbacks.clientInfo = (__bridge void *)(self);
      callbacks.init = init;
      callbacks.prepare = prepare;
      callbacks.process = process;
      callbacks.unprepare = unprepare;
      callbacks.finalize = finalize;
  
      OSStatus err = MTAudioProcessingTapCreate(
                                                kCFAllocatorDefault,
                                                &amp;callbacks,
                                                kMTAudioProcessingTapCreationFlag_PostEffects,
                                                &amp;tap
                                                );
  
      if(err) {
          NSLog(@"Unable to create the Audio Processing Tap %d", (int)err);
          return;
      }
  
      // Create an AudioMix and assign it to our currently playing "item", which
      // is just the stream itself.
      AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
      AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters
                                                       audioMixInputParametersWithTrack:audioTrack];
  
      inputParams.audioTapProcessor = tap;
      audioMix.inputParameters = @[inputParams];
      self.player.currentItem.audioMix = audioMix;
  }
  
  void process(MTAudioProcessingTapRef tap, CMItemCount numberFrames,
               MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut,
               CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut)
  {
      OSStatus err = MTAudioProcessingTapGetSourceAudio(tap, numberFrames, bufferListInOut,
                                                        flagsOut, NULL, numberFramesOut);
      if (err) NSLog(@"Error from GetSourceAudio: %d", (int)err);
  
      NSLog(@"Process");
  
  }
  
  void init(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut)
  {
      NSLog(@"Initialising the Audio Tap Processor");
      *tapStorageOut = clientInfo;
  }
  
  void finalize(MTAudioProcessingTapRef tap)
  {
      NSLog(@"Finalizing the Audio Tap Processor");
  }
  
  void prepare(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat)
  {
      NSLog(@"Preparing the Audio Tap Processor");
  }
  
  void unprepare(MTAudioProcessingTapRef tap)
  {
      NSLog(@"Unpreparing the Audio Tap Processor");
  }
  </code></pre>
  
  <p><code>void init</code> is called <code>void prepare</code> and <code>process</code> has to be called as well. </p>
  
  <p>how can I do this? </p>