Получите размеры видео программно в объективе c - PullRequest
9 голосов
/ 14 февраля 2012

Я новичок в разработке iOS.Я разрабатываю приложение, в котором мне требуется размер видео, которое воспроизводится в MPMoviePlayerController.

Я использую свойство naturalSize MPMoviePlayerController, чтобы получить размеры воспроизводимого видео.

@property(nonatomic, readonly) CGSize naturalSize;

Но проблема в том, что я могу получить естественный размер только тогда, когда видео воспроизводится в MPMoviePlayerController.

Есть ли способ, которым я могу получить размеры видео до его воспроизведения в MPMoviePlayerController.

- РЕДАКТИРОВАТЬ -

Есть ли какой-нибудь другой обходной путь, к которому я могу обратиться, чтобы решить эту проблему?Пожалуйста помоги.

Ответы [ 4 ]

34 голосов
/ 24 января 2013

Вы можете прочитать размеры видео, используя AVURLAsset и AVAssetTrack, например:

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;

Преимущество получения метаданных видео таким образом заключается в том, что вы можете получить к нему доступ сразу, без необходимости проигрывать видео или ждать его загрузки.

7 голосов
/ 14 февраля 2012

MPMoviePlayerController требуется время для загрузки метаданных видео, поэтому вы должны добавить прослушиватель и дождаться загрузки NaturalSize.Примерно так:

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

А в movieNaturalSizeAvailable:, myVideoPlayer.naturalSize дает желаемое значение, и после этого вы можете воспроизводить видео.

2 голосов
/ 23 мая 2016

Просто подумал, что поделюсь своим опытом для тех, кто находит эту страницу.

Естественный размер - это не кодированное разрешение, а разрешение экрана. это может отличаться от кодированного разрешения, например, если соотношение сторон пикселя! = 1 или (более распространенное) в кодированном видео есть информация о метаданных чистой апертуры.

Чтобы получить закодированное разрешение, я нашел единственный способ - декодировать первый кадр, например, с помощью AVASsetReaderTrackOutput, а затем проверить полученный пиксельный буфер с помощью CVPixelBufferGetWidth (или GetHeight), чтобы получить разрешение данных. если вы используете imageGenerator, вы получите разрешение экрана (и растровое изображение rgb разрешения экрана)

0 голосов
/ 18 апреля 2019

Это старый вопрос, но это первый хит в результатах поиска 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;
}
...