2010-12-30 10 views
8

Tengo una pequeña UIView que muestra una película repetida. Cuando el usuario toca un botón, se carga otra película y se muestra en la misma UIView.MPMoviePlayerController cambio de películas provoca flash blanco

El problema es que hay medio segundo "flash" entre la eliminación de la primera película y la visualización de la segunda. ¿Hay alguno para eliminar esto?

- (void) setUpMovie:(NSString*)title { 
NSString *url = [[NSBundle mainBundle] pathForResource:title ofType:@"mp4"]; 

MPMoviePlayerController *player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:url]]; 
[[player view] setFrame:self.movieView.bounds]; 
[self.movieView addSubview:player.view]; 
if ([title isEqualToString:@"Bo_idle_02"]) { 
    [player setRepeatMode:MPMovieRepeatModeOne]; 
} else { 
    [player setRepeatMode:MPMovieRepeatModeNone]; 
} 
[player setControlStyle:MPMovieControlStyleNone]; 
[player play]; 
} 

- (void) startDanceAnimation { [self setUpMovie:@"Bo_dance_02"]; return; } 

Respuesta

4

Logré que mis películas cambiaran sin el flash blanco con la AVFoundation, como se sugirió anteriormente. código sudo a continuación, espero que ayude a alguien :)

documentos de referencia manzanas se pueden encontrar aquí y los utilizó para obtener la mayor parte de mi información: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188-CH1-SW3

La primera cosa que hice fue agregar la siguiente clase, llamado PlayerView (no recuerdo dónde lo sentí) a mi proyecto. Es una subclase de UIView y es la vista en la que se mostrará la película. Una vez que la agregue a su proyecto, abra el Constructor de UI, agregue una nueva vista a un xib existente y cambie su clase a PlayerView. Conecte esto usando un IBOutlet. Recuerde de nuevo que esta es la vista que mostrará la película.

PlayerView.h


#import 
#import 
#import 

@interface PlayerView : UIView { 
    AVPlayer *player; 
} 

@property (nonatomic,retain) AVPlayer *player; 

@end 

PlayerView.m


#import "PlayerView.h" 


@implementation PlayerView 
@synthesize player; 

+ (Class)layerClass { 
    return [AVPlayerLayer class]; 
} 
- (AVPlayer*)player { 
    return [(AVPlayerLayer *)[self layer] player]; 
} 
- (void)setPlayer:(AVPlayer *)player { 
    [(AVPlayerLayer *)[self layer] setPlayer:player]; 
} 

- (void) dealloc { 
    [super dealloc]; 
    [player release]; 
} 

@end 

En el ViewContoller que muestra las películas que tienen las siguientes:

DisplayMovies.h


#import 
#import 
@class PlayerView; 

@interface DisplayMovies : UIViewController { 
IBOutlet AVPlayer *player; 
AVPlayerItem *movieOneItem; 
AVPlayerItem *movieTwoItem; 
} 
@property (nonatomic, retain) AVPlayer *player; 
@property (retain) AVPlayerItem *movieOneItem; 
@property (retain) AVPlayerItem *movieTwoItem; 

DisplayMovies.m


@implementation DisplayMovies 
@synthesize player, movieOneItem, movieTwoItem; 

- (void)viewDidLoad { 
// load the two movies 
NSURL *movieOneItemURL = [[NSBundle mainBundle] URLForResource:@"movieOne" withExtension:@"mp4"]; 
    AVURLAsset *movieOneItemAsset = [AVURLAsset URLAssetWithURL:movieOneItemURL options:nil]; 
    self.movieOneItem = [AVPlayerItem playerItemWithAsset:movieOneItemAsset]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(movieOneItemDidReachEnd:) 
               name:AVPlayerItemDidPlayToEndTimeNotification 
               object:self.movieOneItem]; 

NSURL *movieTwoItemURL = [[NSBundle mainBundle] URLForResource:@"movieTwo" withExtension:@"mp4"]; 
    AVURLAsset *movieTwoItemAsset = [AVURLAsset URLAssetWithURL:movieTwoItemURL options:nil]; 
    self.movieTwoItem = [AVPlayerItem playerItemWithAsset:movieTwoItemAsset]; 

    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(movieTwoItemDidReachEnd:) 
               name:AVPlayerItemDidPlayToEndTimeNotification 
               object:self.movieTwoItem]; 
    [self.player play]; 
} 


- (void) movieOneItemDidReachEnd:(NSNotification*)notification { 
// play movie two once movie one finishes 
    [self.player seekToTime:kCMTimeZero]; 
    [self.player replaceCurrentItemWithPlayerItem:self.movieTwoItem]; 
    [self.player play]; 
} 

- (void) movieTwoItemDidReachEnd:(NSNotification*)notification { 
// play movie one once movie two finishes 
    [self.player seekToTime:kCMTimeZero]; 
    [self.player replaceCurrentItemWithPlayerItem:self.movieOneItem]; 
    [self.player play]; 
} 

+0

Hola @SoundBlaster No estoy de acuerdo. Como indiqué, lo anterior es un código de sudo, pero funciona, tanto en mis proyectos como en otros pueblos. Si explica lo que está sucediendo/no sucede en su proyecto, entonces tal vez podamos ayudarlo. – bennythemink

1

Todavía tengo que volver a este proyecto, pero he recibido más consejos. Volveré a trabajar en este proyecto con suerte en dos semanas, así que les dejaré saber qué solución funcionó (con los dedos cruzados) para mí. Mientras tanto, aquí están mis opciones:

1. No podrá usar MPMoviePlayerController para cambiar la película sin flash.

Como alternativa, puede usar AV Foundation. El método AVPlayer -replaceCurrentItemWithPlayerItem: hará una transición sin inconvenientes desde el elemento antiguo jugador al nuevo sin flashes.

Para obtener más información acerca de la programación con la Fundación de virus, consulte la "Guía de Programación AV Foundation", que se puede encontrar aquí:

http://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/

2. puede combinar todas sus películas en una sola (grande) película, luego use las propiedades MPMediaPlayback actualPlaybackTime/endPlaybackTime para "seleccionar" y reproducir la película deseada (dentro de la película grande). Si usa esta técnica, también deberá asegurarse de que haya un fotograma clave en el momento en que se inicia la nueva película.

3. Alternativamente, cree un solo objeto MPMoviePlayerController, use -setContentURL: para establecer la nueva URL de película y aproveche la propiedad backgroundView para realizar una transición más fluida. La vista de fondo se dimensiona automáticamente con la propiedad de vista, pero se ocultará antes de que la película esté precargada. Puede colocar una vista negra detrás de ambas vistas de película y, a continuación, hacer que backgroundColor = black, lo que debería hacer que parezca más uniforme.

Espero que esto ayude.

+1

Estoy usando 'replaceCurrentItemWithPlayerItem' y sigo viendo los flashes blancos, aunque solo en el dispositivo. El simulador funciona sin flashes. (iOS 9) – shim

2

La solución publicada anteriormente didn' t trabajo para mi Todavía estaba recibiendo breves flashes entre pistas. Pude resolver el problema creando dos vistas, cada una con su propio AVPlayer. Los puse a los dos jugando y luego los cambio ocultando la vista superior. Esto eliminó el flash, y pude animar una transición entre las dos pistas al ocultar la vista superior al establecer su alfa en 0.0 en lugar de usar setHidden. Aquí está mi código:

AVPlayerItem *theAsset = [self generatePlaylistAssetWithVideoOne]; //In my app this returns an AVPlayer Item 

    layerView1 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)]; //VideoLayerView is a subclass of UIView with the video layer stuff added in. 

    [layerView1 setPlayer:thePlayer]; 

    [thePlayer play]; 

    [self.view addSubview:layerView1]; 



    AVPlayerItem *theAsset2 = [self generatePlaylistAssetWithVideoTwo]; 

    [thePlayer2 setActionAtItemEnd:AVPlayerActionAtItemEndNone]; 

    layerView2 = [[VideoLayerView alloc] initWithFrame:CGRectMake(-50, 0, 580, 320)]; 

    [layerView2 setPlayer:thePlayer2]; 

    [thePlayer2 play]; 

    [self.view addSubview:layerView2]; 

Luego de animar entre los vídeos que he utilizado:

if (water) //Water is a BOOL set up earlier in the file 
{ 



    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.5]; 

    ///DO STUFF 
    [layerView2 setAlpha:0]; 


    [UIView commitAnimations]; 


    water = NO; 
} 
else 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationDuration:0.5]; 

    ///DO STUFF 
    [layerView2 setAlpha:1.0]; 

    [UIView commitAnimations]; 

    water = YES; 
} 

Para cambiar los videos, sólo tiene que establecer la vista oculto para empezar a jugar lo que quiere y luego hacer el interruptor después del flash.

Cuestiones relacionadas