Jouant beaucoup de différentes vidéos de l'iphone à l'aide de AVPlayer
Je suis en train de travailler sur un lecteur vidéo personnalisé pour iOS à l'aide de AVFoundation. L'idée est d'être en mesure de passer à une autre vidéo avec un geste (tap, glisser, peu importe). Dès maintenant le lecteur fonctionne parfaitement sur simulateur, mais quand je l'ai tester sur un périphérique réel, l'affichage s'éteint au bout de 3 ou 4 passages de doigts. J'ai même créé des commandes de lecture pour mon lecteur, lorsque la vue se vide, ces contrôles se charger correctement, mais ne rien faire. Toutes les idées, les gars?
C'est l'initialisation pour le joueur
- (id)initWithContentURL:(NSString *)aContentURL delegate:(id)aDelegate {
self = [super initWithNibName:@"NoCashMoviePlayer" bundle:nil];
if (self == nil)
return nil;
delegate = aDelegate;
systemPath = [aContentURL retain];
contentURL = [[NSURL alloc]initFileURLWithPath:systemPath];
asset = [AVURLAsset URLAssetWithURL:contentURL options:nil];
playerItem = [AVPlayerItem playerItemWithAsset:asset];
isPaused = false;
controlsHidden = false;
self.player = [[AVPlayer playerWithPlayerItem:playerItem] retain];
duration = self.player.currentItem.asset.duration;
return self;
}
C'est le code qui lit la vidéo:
-(void)playMovie{
UITapGestureRecognizer *tapRecon = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(toggleControls:)];
[tapRecon setNumberOfTapsRequired:2];
[self.movieContainer addGestureRecognizer:tapRecon];
[tapRecon release];
NSLog(@"Playing item: %@",contentURL);
playerLayer = [AVPlayerLayer playerLayerWithPlayer:player];
[movieContainer.layer addSublayer:playerLayer];
playerLayer.frame = movieContainer.layer.bounds;
playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
self.seeker.alpha = 1.0;
[self.view addSubview:movieContainer];
[self.movieContainer addSubview:controls];
[self setSlider];
[player play];
player.actionAtItemEnd = AVPlayerActionAtItemEndNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(playerItemDidReachEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:[player currentItem]];
}
Le code pour sélectionner le clip à écouter:
-(void)viewSelect: (double) curTime{
self.myView.backgroundColor = [UIColor blackColor];
UISwipeGestureRecognizer *swipeRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFrom:)];
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self.myView addGestureRecognizer:swipeRecognizer];
[swipeRecognizer release];
UISwipeGestureRecognizer *leftRecognizer = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(handleSwipeFromLeft:)];
swipeRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
[self.myView addGestureRecognizer:leftRecognizer];
[leftRecognizer release];
if(isMain){
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationTransitionFlipFromLeft animations:^{
self.myView.alpha = 1.0;
moviePlayer = [[NoCashMoviePlayer alloc]initWithContentURL:[self movieURL:vidIndex] delegate:self];
self.moviePlayer.view.frame = self.myView.bounds;
self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
[self.myView addSubview:moviePlayer.view];
}completion:^(BOOL finished) {
[self.moviePlayer.player seekToTime:CMTimeMake(curTime, 1)];
[self.moviePlayer playMovie];
}];
}else{
[UIView animateWithDuration:0.5 delay:0.0 options:UIViewAnimationTransitionFlipFromLeft animations:^{
self.otherView.alpha = 1.0;
moviePlayer = [[NoCashMoviePlayer alloc]initWithContentURL:[self movieURL:vidIndex] delegate:self];
self.moviePlayer.view.frame = self.otherView.bounds;
self.moviePlayer.view.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
[self.otherView addSubview:moviePlayer.view];
}completion:^(BOOL finished) {
[self.moviePlayer.player seekToTime:CMTimeMake(curTime, 1)];
[self.moviePlayer playMovie];
}];
}
}
Et, enfin, le geste de l'action:
- (void)handleSwipeFromLeft:(UISwipeGestureRecognizer *)recognizer {
double elapsedTime = 0.0;
if(vidIndex==0){
vidIndex = 3;
}else vidIndex = vidIndex --;
elapsedTime = [self.moviePlayer currentTimeInSeconds];
[self.moviePlayer stopMovie];
isMain = !isMain;
[self viewSelect: elapsedTime];
}
EDIT: je l'ai Essayé à l'aide de différents AVPlayerLayers pour chaque fichier vidéo, même situation, travaille dans le simulateur, pas sur l'iPad.
EDIT 2: j'ai couru des instruments pour analyser core animation de la performance, et lors de la lecture de la vidéo elle montre un framerate de 30 fps, lorsque le joueur se vide, il tombe tout le chemin jusqu'à 1 ou 2 fps. Cela peut être ovbious, mais encore, si cela permet de donner un peu plus de lumière.....
EDIT 3: Ok, je suis enfin arriver quelque part, je sais ce qu'est le problème, j'ai un core animation de fuite de mémoire, dans le simulateur, il "fonctionne", parce que l'ordinateur a BEAUCOUP plus de mémoire que l'iPad, mais depuis l'iPad a très peu de mémoire il s'arrête de fonctionner très rapidement. Si quelqu'un a des conseils sur Core Animation des fuites, il sera très bien reçu.
OriginalL'auteur Samssonart | 2011-06-06
Vous devez vous connecter pour publier un commentaire.
J'AI ENFIN RÉSOLU. La conception que j'avais était en effet très pauvre, Il a eu une très mauvaise gestion de la mémoire et ainsi de suite. Ce que j'ai fait, au lieu de libérer tout ce que je pouvais, y compris les vues, les couches, les joueurs, actifs, etc, je viens de créer une méthode pour mettre à jour le lecteur de l'actif et du point, le recyclage, le joueur, des vues, des couches, etc.
Et maintenant il fonctionne des merveilles. Merci à vous tous pour votre aide.
OriginalL'auteur Samssonart
Il y a 2 endroits dans le code où vous avez retenu les services d'un objet, et je ne vois pas la version correspondante n'importe où dans le code que vous avez posté. Je voudrais commencer par faire en sorte que la mémoire de comptage de référence incrémente et décrémente sont tous bien équilibré.
Le premier conserver l'air suspect pour moi. Généralement, vous devez d'abord autorelease la variable de l'affectation et puis conserver comme suit:
Dans le code ci-dessus est facile de voir que le conserver/release correspondant est maintenu, et est beaucoup moins sujette aux erreurs que les autres régimes. Notez que si
systemPath
==aContentURL
l'objet ne sera pas publié.Pas sûr sans voir le code exact. Mais le premier conserver ne semblent pas suivre le modèle standard.
Merci pour l'aide Himadri, j'ai essayé un peu différent de la mémoire/referece comte de solutions, mais ce seuil ne fonctionne pas. J'ai essayé à l'aide d'instruments et il y avait quelques fuites, j'ai pris soin d'eux, et toujours rien. Je vais continuer d'essayer.
OriginalL'auteur Himadri Choudhury