2012-08-23 8 views
8

Ho una classe PlayerView per visualizzare la riproduzione di AVPlayer. Codice da documentation.Come ottenere il frame video di 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 

Ho impostato il mio AVPlayer (contiene asset video con la dimensione 320x240) in questo PlayerView (con frame.size.width = 100, frame.size.height = 100) e il mio video viene ridimensionato. Come posso ottenere la dimensione del video dopo l'aggiunta in PlayerView?

risposta

18

In iOS 7.0 aggiunto nuova funzionalità:

AVPlayerLayer ha proprietà videoRect.

+11

Per me, videoRect restituisce CGRectZero anche se riesco a vedere il video sullo schermo. Sto usando iOS 8 – tettoffensive

+0

in attesa di currentItem.status su == AVPlayerStatusReadyToPlay, e quindi riceverai il frame – YoCoh

+0

Questo non funziona, anche io ho aggiunto KVO per aspettare che lo stato sia AVPlayerStatusReadyToPlay. Il videoRect restituisce ancora tutti gli zeri – codingrhythm

6

trovato una soluzione:

Aggiungi alla classe 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

Non funziona per me in Xcode4.5, iOS6 sdk, build target 4.3. ottenere la dimensione (0,0). Funziona ancora per te adesso? – Mingming

+0

sì. xcode 4.5.1, base sdk 6.0. –

2

Ecco la soluzione che funziona per me, tiene conto del posizionamento di AVPlayer all'interno della visualizzazione. Ho appena aggiunto questo alla classe personalizzata PlayerView. Ho dovuto risolvere questo problema perché non sembra che VideoRect funzioni in 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

Qui è il Eric Badros' answer portato su iOS. Ho anche aggiunto la gestione preferita di Transform. Ciò presuppone _player è 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

hai un errore. sia if che else se hanno ">" – tettoffensive

+0

Grazie a @tettoffensive –

0

Questo ha funzionato per me. Quando non si dispone di 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); 

}