Estoy trabajando en un reproductor de vídeo personalizado para iOS usando AVFoundation. La idea es ser capaz de cambiar a un video diferente con un gesto (tocar, deslizar el dedo, lo que sea). Ahora el jugador está funcionando a la perfección en el simulador, pero cuando lo pruebo en un dispositivo real, la vista se queda en blanco después de 3 o 4 pasadas. Incluso he creado los controles de reproducción para el reproductor, cuando la vista se queda en blanco, estos controles se carga correctamente pero no hacen nada. Alguna idea chicos?
Esta es la inicialización para el jugador

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

Este es el código que se reproduce el vídeo:

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


    }

El código para seleccionar el clip para ser jugados:

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

Y por último la acción de gesto:

    - (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: Probado con diferentes AVPlayerLayers para cada archivo de vídeo, misma situación, funciona en el simulador, no en el iPad.

EDIT 2: me encontré instrumentos para analizar el núcleo de rendimiento de la animación, y cuando se reproduce el video muestra a la tasa de fotogramas de 30 fps, cuando el jugador se queda en blanco se cae todo el camino hasta la 1 o 2 fps. Esto puede ser ovbious, pero aún así, si que ayuda a dar un poco más de luz…..

EDIT 3: Ok, por fin estoy de llegar a alguna parte, yo sé cuál es el problema, tengo un core animation pérdida de memoria, en el simulador «funciona» porque el equipo tiene MUCHA más memoria que el iPad, pero desde el iPad tiene muy limitada la memoria deja de funcionar muy rápidamente. Si alguien tiene algún consejo con respecto Core Animation fugas, será muy bien recibido.

OriginalEl autor Samssonart | 2011-06-06

2 Comentarios

  1. 4

    FINALMENTE RESUELTO. El diseño que había hecho fue muy pobre, tenía una muy mala gestión de la memoria y así sucesivamente. Yo lo que hice fue, en lugar de soltar todo lo que pude, incluyendo vistas, las capas, los jugadores, activos, etc, he creado un método para actualizar el reproductor de activos y punto, el reciclaje, el jugador, vistas, capas, etc.

        [player pause];
    contentURL = [[NSURL alloc] initFileURLWithPath:newPath];
    AVAsset *newAsset = [AVURLAsset URLAssetWithURL:contentURL options:nil];
    AVPlayerItem *newPlayerItem = [AVPlayerItem playerItemWithAsset:newAsset];
    [player replaceCurrentItemWithPlayerItem:newPlayerItem];
    [contentURL release];

    Y ahora funciona a las mil maravillas. Gracias a todos por su ayuda.

    OriginalEl autor Samssonart

  2. 1

    Hay 2 lugares en el código donde se ha contratado a un objeto, y no veo la versión correspondiente en cualquier lugar en el código que has publicado. Me gustaría empezar por asegurarse de que la referencia de memoria de recuento de incrementos y decrementos son todos adecuadamente equilibrada.

    La primera retener parece sospechoso para mí. Generalmente, usted debe primero grupo de liberación automática la variable que se asigna a y, a continuación, retener de la siguiente manera:

    [systemPath autorelease];
    systemPath = [aContentURL retain]

    En el código anterior es fácil ver que el retener/liberación de coincidencia es mantenido, y es mucho menos propenso a errores que otros esquemas. Tenga en cuenta que si systemPath == aContentURL el objeto no será publicada.

    Todos los retenidos los objetos se liberan en el ‘dealloc’ método. Sería eso suficiente? En realidad, yo solía tener el jugador sin el ‘retener’ palabra clave’, pero fue peor, que finalmente llevó a un choque, porque el objeto de ser lanzado en algún momento durante el tiempo de ejecución.
    No es seguro, sin ver el código exacto. Pero la primera retener no parecen seguir el patrón estándar.
    Gracias por la ayuda Himadri, yo he probado un par de memoria diferente/referece recuento de las soluciones, pero es alféizar de no trabajo. He intentado usar instrumentos y hubo un par de escapes, me hice cargo de ellos, y todavía nada. Voy a seguir intentando.

    OriginalEl autor Himadri Choudhury

Dejar respuesta

Please enter your comment!
Please enter your name here