2012-08-23 11 views
8

Tengo una clase PlayerView para mostrar la reproducción de AVPlayer. Código desde documentation.¿Cómo obtener el marco de video del AVPlayer?

#import <UIKit/UIKit.h> 
#import <AVFoundation/AVFoundation.h> 

@interface PlayerView : UIView 
@property (nonatomic) AVPlayer *player; 
@end 

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

puedo configurar mi AVPlayer (contiene contenido de vídeo con un tamaño de 320x240) en este PlayerView (con frame.size.width = 100, frame.size.height = 100) y mi vídeo cambia de tamaño. ¿Cómo puedo obtener el tamaño del video después de agregar PlayerView?

Respuesta

18

En iOS 7.0 añade nueva característica:

AVPlayerLayer tiene la propiedad videoRect.

+11

Para mí, videoRect solo devuelve CGRectZero aunque puedo ver el video en la pantalla. Estoy usando iOS 8 – tettoffensive

+0

espere el currentItem.status a == AVPlayerStatusReadyToPlay, y luego obtendrá el marco – YoCoh

+0

Esto no funciona, incluso he agregado KVO para esperar que el estado sea AVPlayerStatusReadyToPlay. El videoRect todavía devuelve todos los ceros – codingrhythm

6

encontrado una solución:

Añadir a la clase PlayerView:

- (CGRect)videoContentFrame { 
    AVPlayerLayer *avLayer = (AVPlayerLayer *)[self layer]; 
    // AVPlayerLayerContentLayer 
    CALayer *layer = (CALayer *)[[avLayer sublayers] objectAtIndex:0]; 
    CGRect transformedBounds = CGRectApplyAffineTransform(layer.bounds, CATransform3DGetAffineTransform(layer.sublayerTransform)); 
    return transformedBounds; 
} 
+1

No funciona para mí en Xcode4.5, iOS6 sdk, build target 4.3. obtener tamaño (0,0). ¿Todavía está trabajando para ti ahora? – Mingming

+0

sí. xcode 4.5.1, base sdk 6.0. –

2

Esta es la solución que me funciona, tiene en cuenta el posicionamiento del AVPlayer dentro de la vista. Acabo de agregar esto a la clase personalizada PlayerView. Tuve que resolver esto porque no parece que videoRect esté funcionando en 10.7.

- (NSRect) videoRect { 
    NSRect theVideoRect = NSMakeRect(0,0,0,0); 
    NSRect theLayerRect = self.playerLayer.frame; 

    NSSize theNaturalSize = NSSizeFromCGSize([[[self.movie asset] tracksWithMediaType:AVMediaTypeVideo][0] naturalSize]); 
    float movieAspectRatio = theNaturalSize.width/theNaturalSize.height; 
    float viewAspectRatio = theLayerRect.size.width/theLayerRect.size.height; 
    if (viewAspectRatio < movieAspectRatio) { 
     theVideoRect.size.width = theLayerRect.size.width; 
     theVideoRect.size.height = theLayerRect.size.width/movieAspectRatio; 
     theVideoRect.origin.x = 0; 
     theVideoRect.origin.y = (theLayerRect.size.height/2) - (theVideoRect.size.height/2); 
} 
    else if (viewAspectRatio > movieAspectRatio) { 

     theVideoRect.size.width = movieAspectRatio * theLayerRect.size.height; 
     theVideoRect.size.height = theLayerRect.size.height; 
     theVideoRect.origin.x = (theLayerRect.size.width/2) - (theVideoRect.size.width/2); 
     theVideoRect.origin.y = 0; 
    } 
    return theVideoRect; 
} 
1

Aquí está Eric Badros' answer portado a iOS. También agregué el manejo preferido de Transform. Esto supone _player es un AVPlayer

- (CGRect) videoRect { 
    CGRect theVideoRect = CGRectZero; 

    // Replace this with whatever frame your AVPlayer is playing inside of: 
    CGRect theLayerRect = self.playerLayer.frame; 

    AVAssetTrack *track = [_player.currentItem.asset tracksWithMediaType:AVMediaTypeVideo][0]; 
    CGSize theNaturalSize = [track naturalSize]; 
    theNaturalSize = CGSizeApplyAffineTransform(theNaturalSize, track.preferredTransform); 
    theNaturalSize.width = fabs(theNaturalSize.width); 
    theNaturalSize.height = fabs(theNaturalSize.height); 

    CGFloat movieAspectRatio = theNaturalSize.width/theNaturalSize.height; 
    CGFloat viewAspectRatio = theLayerRect.size.width/theLayerRect.size.height; 

    // Note change this *greater than* to a *less than* if your video will play in aspect fit mode (as opposed to aspect fill mode) 
    if (viewAspectRatio > movieAspectRatio) { 
     theVideoRect.size.width = theLayerRect.size.width; 
     theVideoRect.size.height = theLayerRect.size.width/movieAspectRatio; 
     theVideoRect.origin.x = 0; 
     theVideoRect.origin.y = (theLayerRect.size.height - theVideoRect.size.height)/2; 
    } else if (viewAspectRatio < movieAspectRatio) { 
     theVideoRect.size.width = movieAspectRatio * theLayerRect.size.height; 
     theVideoRect.size.height = theLayerRect.size.height; 
     theVideoRect.origin.x = (theLayerRect.size.width - theVideoRect.size.width)/2; 
     theVideoRect.origin.y = 0; 
    } 
    return theVideoRect; 
} 
+0

tiene un error. tanto si y si tiene ">" – tettoffensive

+0

Gracias @tettoffensive –

0

Esto funcionó para mí. Cuando no tienes el AVPLayerLayer.

- (CGRect)videoRect { 
    // @see http://stackoverflow.com/a/6565988/1545158 

    AVAssetTrack *track = [[self.player.currentItem.asset tracksWithMediaType:AVMediaTypeVideo] firstObject]; 
    if (!track) { 
     return CGRectZero; 
    } 

    CGSize trackSize = [track naturalSize]; 
    CGSize videoViewSize = self.videoView.bounds.size; 

    CGFloat trackRatio = trackSize.width/trackSize.height; 
    CGFloat videoViewRatio = videoViewSize.width/videoViewSize.height; 

    CGSize newSize; 

    if (videoViewRatio > trackRatio) { 
     newSize = CGSizeMake(trackSize.width * videoViewSize.height/trackSize.height, videoViewSize.height); 
    } else { 
     newSize = CGSizeMake(videoViewSize.width, trackSize.height * videoViewSize.width/trackSize.width); 
    } 

    CGFloat newX = (videoViewSize.width - newSize.width)/2; 
    CGFloat newY = (videoViewSize.height - newSize.height)/2; 

    return CGRectMake(newX, newY, newSize.width, newSize.height); 

} 
Cuestiones relacionadas