2012-08-23 102 views
8

我有用於顯示AVPlayer播放的PlayerView類。代碼從documentation如何獲取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 

設置我的AVPlayer(包含視頻與資產的大小爲320x240)在此PlayerView(與frame.size.width = 100,frame.size.height = 100)和我的視頻大小。如何在PlayerView中添加視頻後獲取視頻大小?

回答

18

的iOS 7.0增加了新的功能:

AVPlayerLayer擁有財產videoRect

+11

對我來說,videoRect只是返回CGRectZero,即使我可以在屏幕上看到視頻。我正在使用iOS 8 – tettoffensive

+0

等待currentItem.status爲== AVPlayerStatusReadyToPlay,然後您將獲得幀 – YoCoh

+0

這不起作用,即使我已添加KVO以等待狀態爲AVPlayerStatusReadyToPlay。 videoRect仍然返回所有的零 – codingrhythm

6

找到了解決辦法:

添加到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

它不適合我在Xcode4.5,iOS6 sdk,構建目標4.3。獲取大小(0,0)。它現在還在爲你工作嗎? – Mingming

+0

是的。 xcode 4.5.1,base sdk 6.0。 –

2

下面是爲我工作的解決方案,考慮了AVPlayer在視圖中的位置。我只是將其添加到PlayerView自定義類。我必須解決這個問題,因爲沒有出現videoRect在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

這裏是移植到iOS的Eric Badros' answer。我還添加了preferredTransform處理。這是假設_player是一個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

你有錯誤。兩者如果和其他如果有「>」「 – tettoffensive

+0

謝謝@tettoffensive –

0

這爲我工作。當你沒有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); 

}