2012-09-29 7 views
5

Me encuentro con una situación extraña con mi reproductor de video, cuyo código principal no ha cambiado mucho de lo que funcionó en una aplicación anterior que hice. Aquí está el problema: estoy insertando un "_loadingLayer" (un CATextLayer que dice que el video se está cargando), y luego observando la propiedad de estado del actualItem del AVPlayer para averiguar cuándo eliminar el "_loadingLayer" y reemplazarlo con mi "_playerLayer" real. . Aquí está mi código de MVA para ello:AV Foundation: diferencia entre currentItem listo para jugar, y - propiedad [AVPlayer readyForDisplay]?

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 

if ((object == _playerLayer) && (_playerLayer.player.currentItem.status == AVPlayerItemStatusReadyToPlay)) { 

    [CATransaction setAnimationDuration:1.8]; 

    _loadingLayer.opaque = NO; 

    if (_playerLayer.readyForDisplay) { 

     NSLog(@"Should be ready now."); 

    } 

    [self addPlayerLayerToLayerTree]; 

} 

} 

Mi problema es que el vídeo está empezando, pero sólo se reproduce el audio - la capa permanece en negro. Cuando inserté la declaración NSLog anterior, descubrí por qué: Aparentemente, aunque el estado del actualItem es "AVPlayerItemStatusReadyToPlay", la capa del reproductor no está realmente preparada para la visualización. Esto no tiene sentido para mí, parece contradictorio. ¿Puede alguien darme alguna orientación sobre esto?

Pude verificar que _playerLayer se está agregando al árbol de capas estableciendo el color de fondo en rojo.

Otra cosa extraña que creo que podría estar relacionado .... He estado viendo estos mensajes en la consola depurador:

PSsetwindowlevel, Error de configuración de nivel de la ventana (1000) CGSSetIgnoresCycle: error de selección 1000 o ventana de compensación etiquetas

Gracias de antemano. Este es un cruce de los foros de Apple Dev.

Respuesta

3

Tuvimos un problema similar y lo remontamos a lo que creo que es un error en iOS 5.1 (y tal vez en versiones anteriores). Está arreglado en iOS 6.0. Como no pude encontrar una solución para esto en ningún lado, estoy escribiendo un largo informe para las personas que tienen este problema en el futuro.

Si AVPlayerItem informa de un estado de AVPlayerStatusReadyToPlay antes de que se haya obtenido AVPlayerLayer, el AVPlayer nunca informará que está listo para la exhibición.

Así que cuando usted hacer:

self.player = [AVPlayer playerWithPlayerItem:self.playerItem]; 

asegúrese de que es seguido con:

self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; 

y que no tienen mucho si cualquier código de entre los dos.

Creé una plataforma de prueba para que funcione el 100% del tiempo o falle el 100% del tiempo. Tenga en cuenta que puede ser difícil ver lo que sucede en su aplicación real, ya que tendrá diferentes tiempos de carga en el video y eso afectará la rapidez con la que playerItem informe AVPlayerStatusReadyToPlay.

Si desea probar en su aplicación, ponga esto en una vista simple. Lo siguiente no funcionará (es decir, escuchará audio pero no verá el video) en iOS 5.1. Si cambia loadPlayerLayer para que se invoque en su lugar al final de loadPlayer, siempre funcionará.

Un seguimiento para futuros lectores: un par de eventos de jugadores pueden cambiar este orden y hacerle pensar que está funcionando. Sin embargo, son pistas falsas porque invierten inadvertidamente el orden de carga de modo que playerLayer se agarra antes de AVStatusReadyToPlay. Los eventos son: buscar el video, ir a la pantalla de inicio y luego reactivar la aplicación; el reproductor cambia a una pista de video/audio diferente dentro de un video de HLS. Estas acciones desencadenan AVStatusReadyToPlay nuevamente y, por lo tanto, hacen que playerLayer suceda antes de AVStatusReadyToPlay.

Aquí está el arnés de prueba que utiliza el vídeo HLS prueba de Apple:

-(void)loadPlayer 
{ 
    NSLog(@"loadPlayer invoked"); 

    NSURL *url = [NSURL URLWithString:@"https://devimages.apple.com.edgekey.net/resources/http-streaming/examples/bipbop_4x3/bipbop_4x3_variant.m3u8"]; 
    self.playerItem = [AVPlayerItem playerItemWithURL:url]; 
    [self.playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:&kPlayerContext]; 
    self.player = [AVPlayer playerWithPlayerItem:self.playerItem]; 

} 

-(void)loadPlayerLayer 
{ 
    NSLog(@"starting player layer"); 
    self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; 
    [self.playerLayer addObserver:self forKeyPath:@"readyForDisplay" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:&kPlayerLayerContext]; 
    [self.playerLayer setFrame:[[self view] bounds]]; 
    [[[self view] layer] addSublayer:self.playerLayer]; 
} 

-(void)observeValueForKeyPath:(NSString*)path ofObject:(id)object change:(NSDictionary*)change context:(void*) context 
{ 
    if(context == &kPlayerContext){ 
    if([self.player status] == AVPlayerStatusReadyToPlay){ 
     NSLog(@"Player is ready to play"); 
     //Robert: Never works if after AVPlayerItem reports AVPlayerStatusReadyToPlay 
     if(!self.startedPlayerLayer){ 
     self.startedPlayerLayer = YES; 
     [self loadPlayerLayer]; 
     } 
    } 
    } 

    if(context == &kPlayerLayerContext){ 
    if([self.playerLayer isReadyForDisplay] == YES){ 
     NSLog(@"PlayerLayer says it's ready to display now"); 
     [self playTheVideoIfReady]; 
    } 
    } 
} 
Cuestiones relacionadas