2013-07-15 36 views
10

Ho realizzato un lettore video che analizza le tracce audio e video in tempo reale dal video attualmente in riproduzione. I video sono archiviati sul dispositivo iOS (nella directory Documenti di app).iOS: tocca Audio e video da Airplay

Tutto funziona correttamente. Uso MTAudioProcessingTap per ottenere tutti i campioni audio e fare alcuni FFT, e sto analizzando il video semplicemente copiando i pixel buffer dal CMTime attualmente riprodotto (la proprietà currenttime di AVPlayer). Come ho detto, questo funziona bene.

Ma ora voglio supportare Airplay. Solo l'airplay non è difficile, ma i miei tocchi cessano di funzionare non appena Airplay viene attivato e il video viene riprodotto sull'ATV. In qualche modo, MTAudioProcessingTap non verrà elaborato e i pixelbuffer sono tutti vuoti ... Non riesco ad accedere ai dati.

C'è un modo per ottenere questi dati?

Per ottenere i pixel buffer, faccio semplicemente un evento ogni pochi millisecondi e recuperando il tempo corrente del lettore. Poi:

CVPixelBufferRef imageBuffer = [videoOutput copyPixelBufferForItemTime:time itemTimeForDisplay:nil]; 
CVPixelBufferLockBaseAddress(imageBuffer,0); 

uint8_t *tempAddress = (uint8_t *) CVPixelBufferGetBaseAddress(imageBuffer); 

size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
size_t height = CVPixelBufferGetHeight(imageBuffer); 

CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

Dove è la mia tempAddress pixelbuffer, e videoOutput è un'istanza di AVPlayerItemVideoOutput.

Per l'audio, io uso:

AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioTrack]; 

// Create a processing tap for the input parameters 
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; 

MTAudioProcessingTapRef tap; 
OSStatus err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, 
              kMTAudioProcessingTapCreationFlag_PostEffects, &tap); 
if (err || !tap) { 
    NSLog(@"Unable to create the Audio Processing Tap"); 
    return; 
} 

inputParams.audioTapProcessor = tap; 

// Create a new AVAudioMix and assign it to our AVPlayerItem 
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; 
audioMix.inputParameters = @[inputParams]; 
playerItem.audioMix = audioMix; 

saluti, Niek

+0

La prego di aggiungere il codice in cui si sta accedendo i buffer di pixel? –

+0

Anche il codice per riprodurre il video potrebbe aiutare :) –

+0

Fatto. qualche idea ? –

risposta

-2

Ecco la soluzione:

questo è di implementare AirPlay, io uso questo codice solo per l'audio sul mio applicazioni Mi non so se puoi migliorare per il video ma puoi provare;)

On AppDelegate.m:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    [RADStyle applyStyle]; 
    [radiosound superclass]; 
    [self downloadZip]; 

    NSError *sessionError = nil; 
    [[AVAudioSession sharedInstance] setDelegate:self]; 
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:&sessionError]; 
    [[AVAudioSession sharedInstance] setActive:YES error:nil]; 

    UInt32 sessionCategory = kAudioSessionCategory_MediaPlayback; 
    AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory); 

    UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker; 
    AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute,sizeof (audioRouteOverride),&audioRouteOverride); 

    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
} 

Se si utilizza l'airplay per implementare il controllo LockScreen, ArtWork, Stop/riproduci, Titolo ecc.

Nel DetailViewController di voi uso lettore di questo codice:

- (BOOL)canBecomeFirstResponder { 

    return YES; 
} 
- (void)viewDidAppear:(BOOL)animated { 

    [super viewDidAppear:animated]; 
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
    [self becomeFirstResponder]; 

    NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString: (self.saved)[@"image"]]]; 

    if (imageData == nil){ 

    MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter]; 
    MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageNamed:@"lockScreen.png"]]; 

    infoCenter.nowPlayingInfo = @{MPMediaItemPropertyTitle: saved[@"web"],MPMediaItemPropertyArtist: saved[@"title"], MPMediaItemPropertyArtwork:albumArt}; 

    } else { 

     MPNowPlayingInfoCenter *infoCenter = [MPNowPlayingInfoCenter defaultCenter]; 
     MPMediaItemArtwork *albumArt = [[MPMediaItemArtwork alloc] initWithImage:[UIImage imageWithData:imageData]]; 

     infoCenter.nowPlayingInfo = @{MPMediaItemPropertyTitle: saved[@"link"],MPMediaItemPropertyArtist: saved[@"title"], MPMediaItemPropertyArtwork:albumArt}; 

    } 

} 

Spero che questo codice può aiutare;)

+0

L'utilizzo di airplay non è un problema, ma l'analisi dei dati audio e video in tempo reale lo è. –