2012-08-23 18 views
8

Mam klasy PlayerView do wyświetlania odtwarzania AVPlayer. Kod od documentation.Jak uzyskać klatkę wideo odtwarzacza AVP?

#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 

skonfigurować moje AVPlayer (zawiera materiał wideo o rozmiarze 320x240) w tym PlayerView (z frame.size.width = 100, frame.size.height = 100) i mój film jest zmieniany. Jak mogę uzyskać rozmiar wideo po dodaniu w PlayerView?

Odpowiedz

18

W iOS 7.0 dodaje nową funkcję:

AVPlayerLayer ma własność videoRect.

+11

Dla mnie videoRect po prostu zwraca CGRectZero, mimo że widzę wideo na ekranie. Używam iOS 8 – tettoffensive

+0

czekać na currentItem.status do == AVPlayerStatusReadyToPlay, a następnie otrzymasz ramkę – YoCoh

+0

To nie działa, nawet dodałem KVO czekać na status AVPlayerStatusReadyToPlay. VideoRect nadal zwraca wszystkie zera – codingrhythm

6

znalazł rozwiązanie:

Dodaj do klasy 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

Nie działa dla mnie w Xcode4.5, iOS6 sdk, kompilacji docelowej 4.3. uzyskać rozmiar (0,0). Czy nadal działa dla ciebie? – Mingming

+0

tak. xcode 4.5.1, base sdk 6.0. –

2

Oto rozwiązanie, które działa dla mnie, bierze pod uwagę pozycjonowanie AVPlayera w widoku. Właśnie dodałem to do niestandardowej klasy PlayerView. Musiałem rozwiązać ten problem, ponieważ nie wygląda na to, że videoRect działa w wersji 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

Oto Eric Badros' answer przeniesiony do iOS. Dodałem również preferowaną obsługę Transakcji. Zakłada _player jest 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

Wystąpił błąd. zarówno jeśli i jeszcze, jeśli ">" – tettoffensive

+0

Dzięki @tettoffensive –

0

ten pracował dla mnie. Kiedy nie masz 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); 

}