2010-12-30 20 views
8

Ho un piccolo UIView che mostra un film ripetuto. Quando l'utente tocca un pulsante, un altro film viene caricato e visualizzato nello stesso UIView.MPMoviePlayerController commuta filmati causa flash bianco

Il problema è che c'è un "flash" di mezzo secondo tra la rimozione del primo film e la visualizzazione del secondo. C'è qualcuno da rimuovere?

- (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; } 

risposta

4

Sono riuscito a cambiare i miei filmati senza il flash bianco utilizzando AVFoundation come suggerito in precedenza. Codice sudo seguito, spero che aiuta qualcuno :)

docs Le mele di riferimento possono essere trovati qui e li ha usati per ottenere la maggior parte delle mie informazioni: http://developer.apple.com/library/ios/#documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/00_Introduction.html#//apple_ref/doc/uid/TP40010188-CH1-SW3

La prima cosa che ho fatto è stato quello di aggiungere la seguente classe, chiamato PlayerView (non ricordo dove mi sono dispiaciuto) per il mio progetto. È una sottoclasse di UIView e la sua visione è che il film verrà visualizzato. Una volta aggiunto al progetto, UI Builder, aggiungi una nuova vista a uno xib esistente e cambia la sua classe in PlayerView. Collegalo usando un IBOutlet. Ricorda ancora che questa è la vista che mostrerà il film.

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 

Nel ViewContoller che visualizza i film che ho il seguente:

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

Ciao @SoundBlaster Non sono d'accordo. Come ho detto sopra, è sudo-code ma funziona, sia nei miei progetti che in altri popoli. Se spieghi cosa sta succedendo/non sta succedendo nel tuo progetto, allora forse possiamo aiutarti. – bennythemink

1

Devo ancora tornare a questo progetto ma ho ricevuto ulteriori consigli. Tornerò a lavorare su questo progetto speriamo in due settimane, quindi ti farò sapere quale soluzione ha funzionato (dita incrociate) per me. Nel frattempo, ecco le mie opzioni:

1. Non sarà possibile utilizzare MPMoviePlayerController per passare il film senza flash.

In alternativa, è possibile utilizzare AV Foundation. L'AVPlayer -replaceCurrentItemWithPlayerItem: il metodo passerà senza problemi dal vecchio elemento giocatore a quello nuovo senza flash.

Per ulteriori informazioni sulla programmazione con AV Foundation, consultare la "Guida AV Foundation di programmazione", che potete trovare qui:

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

2. è possibile unire tutti i tuoi film in un unico (grande), quindi utilizzare le proprietà MPMediaPlayback currentPlaybackTime/endPlaybackTime per "selezionare" e riprodurre il film desiderato (all'interno del filmato di grandi dimensioni). Se usi questa tecnica dovrai anche assicurarti che ci sia un fotogramma chiave nel momento in cui inizia il nuovo film.

3. In alternativa, creare un singolo oggetto MPMoviePlayerController, utilizzare -setContentURL: per impostare il nuovo URL del film e sfruttare la proprietà backgroundView per effettuare una transizione più semplice. BackgroundView viene automaticamente ridimensionato con la proprietà view, ma sarà nascosto prima che il film sia precaricato. Puoi mettere una vista nera dietro a entrambe le visuali del film e quindi rendere lo sfondo backgroundColor = nero, che dovrebbe renderlo più trasparente.

Spero che questo aiuti.

+1

Sto usando 'replaceCurrentItemWithPlayerItem' e vedo ancora i flash bianchi, sebbene solo sul dispositivo. Il simulatore funziona senza flash. (iOS 9) – shim

2

La soluzione postato sopra didn' lavoro per me. Stavo ancora ricevendo brevi flash tra le tracce. Sono stato in grado di risolvere il problema creando due viste ciascuna con il proprio AVPlayer. Li ho messi entrambi in riproduzione e poi li ho passati nascondendo la vista dall'alto. Questo ha eliminato il flash e sono stato in grado di animare una transizione tra le due tracce nascondendo la vista superiore impostando il suo alpha su 0.0 invece di usare setHidden. Qui è il mio codice:

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]; 

Poi animare tra i video che ho usato:

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; 
} 

Per modificare i video, è sufficiente impostare la vista nascosta per iniziare a giocare quello che vuoi e poi fare l'interruttore dopo il flash.

Problemi correlati