在目标c中以编程方式获取视频的尺寸

时间:2012-02-14 09:02:57

标签: iphone objective-c ios cocoa-touch mpmovieplayercontroller

我是iOS开发的初学者。我正在开发一个应用程序,我需要在MPMoviePlayerController中播放视频的大小。

我正在使用MPMoviePlayerController的属性naturalSize来获取播放视频的尺寸。

@property(nonatomic, readonly) CGSize naturalSize;

但问题是,只有当视频在MPMoviePlayerController中播放时,我才能获得自然大小。

在MPMoviePlayerController播放视频之前,我是否可以获取视频的尺寸。

- 编辑 -

我可以采取任何其他解决方法来解决此问题吗?请帮忙。

4 个答案:

答案 0 :(得分:34)

您可以使用AVURLAssetAVAssetTrack阅读视频的尺寸,如下所示:

NSURL *mediaURL; // Your video's URL
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:mediaURL options:nil];
NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
AVAssetTrack *track = [tracks objectAtIndex:0];

然后使用AVAssetTrack的naturalSize属性:

CGSize mediaSize = track.naturalSize;

以这种方式获取视频元数据的好处是您可以立即访问它,而无需播放视频或等待加载视频。

答案 1 :(得分:7)

MPMoviePlayerController加载视频元数据需要一些时间,因此您应该添加一个侦听器并等待加载naturalSize。像这样:

[[NSNotificationCenter defaultCenter] addObserver:self
                selector:@selector(movieNaturalSizeAvailable:)
                name:MPMovieNaturalSizeAvailableNotification
                object:myMoviePlayer];

movieNaturalSizeAvailable:中,myVideoPlayer.naturalSize会为您提供所需的值,然后您可以播放该视频。

答案 2 :(得分:2)

我想我会分享那些找到这个页面的人的经历。

自然尺寸实际上不是编码分辨率,而是显示分辨率。这可能与编码分辨率不同,例如,如果像素宽高比!= 1或(更常见),编码视频中有干净的光圈元数据信息。

要获得编码分辨率,我发现的唯一方法是使用例如AVASsetReaderTrackOutput解码第一帧,然后使用CVPixelBufferGetWidth(或GetHeight)检查生成的像素缓冲区以获得数据分辨率。如果您使用imageGenerator,您将获得显示分辨率(以及显示分辨率的rgb位图)

答案 3 :(得分:0)

这是一个古老的问题,但这是google搜索结果中的第一命。

“ naturalSize”属性似乎不是分辨率;在我的测试中,它看起来更像是长宽比。例如,我通常会看到naturalSize.height = 9和naturalSize.width = 16

这里有一些代码可以获取像素尺寸(可能是您想要的)以及其他一些东西。

// in a header file, perhaps
typedef struct VideoInfo {
    size_t width;
    size_t height;
    CGFloat durationInSeconds;
    CGFloat framesPerSecond;
} VideoInfo;


+ (VideoInfo) getVideoInfoFromUrl:(NSURL*)fileUrl
{
    VideoInfo vidInfo;
    vidInfo.width = vidInfo.height = 0;
    vidInfo.durationInSeconds = vidInfo.framesPerSecond = 0;

    @try {
        // get duration and fps
        AVURLAsset *asset = [AVURLAsset URLAssetWithURL:fileUrl options:nil];
        vidInfo.durationInSeconds = CMTimeGetSeconds(asset.duration);
        vidInfo.framesPerSecond = track.nominalFrameRate;

        // get width and height in pixels
        // you have to extract a frame from the video and get the dimensions from the frame
        AVAsset *avasset = [AVAsset assetWithURL:fileUrl];
        AVAssetReader *assetReader = [[AVAssetReader alloc] initWithAsset:avasset error:&error];
        if (assetReader) {
                NSArray<AVAssetTrack*> *tracks = [avasset tracksWithMediaType:AVMediaTypeVideo];
                if (tracks && tracks.count > 0) {
                    AVAssetTrack* track = [tracks objectAtIndex:0];

                    NSDictionary *settings = @{(__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_420YpCbCr8BiPlanarFullRange)};
                    trackOutput = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:track outputSettings:settings];

                    [assetReader addOutput:trackOutput];
                    [assetReader startReading];

                    CMSampleBufferRef sampleBuffer = [trackOutput copyNextSampleBuffer];
                    if (sampleBuffer) {
                        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

                        if (imageBuffer && (CFGetTypeID(imageBuffer) == CVPixelBufferGetTypeID())) {
                            // note on iOS, CVImageBufferRef and CVPixelBufferRef are synonyms via:
                            // typedef CVImageBufferRef CVPixelBufferRef;
                            CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly); 
                            vidInfo.height = CVPixelBufferGetHeight(imageBuffer);
                            vidInfo.width = CVPixelBufferGetWidth(imageBuffer);
                            CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);
                            CFRelease(imageBuffer);
                        }
                    }

                }
            }
        }
    }
    @catch (NSException *exception) {

    }

    return vidInfo;
}