Подтвердить что ты не робот

Могу ли я использовать AVFoundation для потоковой передачи загруженных видеокадров в текстуру OpenGL ES?

Я смог использовать класс AVFoundation AVAssetReader для загрузки видеокадров в текстуру OpenGL ES. Он имеет оговорку, однако, что он не работает при использовании с AVURLAsset, который указывает на удаленный носитель. Этот провал не очень хорошо документирован, и мне интересно, есть ли какой-нибудь путь вокруг недостатка.

4b9b3361

Ответ 1

Там есть API, который был выпущен с iOS 6, который я смог использовать, чтобы сделать процесс легким. Он вообще не использует AVAssetReader и вместо этого полагается на класс под названием AVPlayerItemVideoOutput. Экземпляр этого класса может быть добавлен в любой экземпляр AVPlayerItem с помощью нового метода -addOutput:.

В отличие от AVAssetReader, этот класс отлично работает для AVPlayerItem, который поддерживается удаленным AVURLAsset, а также имеет преимущество для более сложного интерфейса воспроизведения, поддерживающего нелинейное воспроизведение через -copyPixelBufferForItemTime:itemTimeForDisplay: (вместо AVAssetReader строго ограничивающего метод -copyNextSampleBuffer.


КОД ОБРАЗЦА

// Initialize the AVFoundation state
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:someUrl options:nil];
[asset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler:^{

    NSError* error = nil;
    AVKeyValueStatus status = [asset statusOfValueForKey:@"tracks" error:&error];
    if (status == AVKeyValueStatusLoaded)
    {
        NSDictionary* settings = @{ (id)kCVPixelBufferPixelFormatTypeKey : [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] };
        AVPlayerItemVideoOutput* output = [[[AVPlayerItemVideoOutput alloc] initWithPixelBufferAttributes:settings] autorelease];
        AVPlayerItem* playerItem = [AVPlayerItem playerItemWithAsset:asset];
        [playerItem addOutput:[self playerItemOutput]];
        AVPlayer* player = [AVPlayer playerWithPlayerItem:playerItem];

        // Assume some instance variable exist here. You'll need them to control the
        // playback of the video (via the AVPlayer), and to copy sample buffers (via the AVPlayerItemVideoOutput).
        [self setPlayer:player];
        [self setPlayerItem:playerItem];
        [self setOutput:output];
    }
    else
    {
        NSLog(@"%@ Failed to load the tracks.", self);
    }
}];

// Now at any later point in time, you can get a pixel buffer
// that corresponds to the current AVPlayer state like this:
CVPixelBufferRef buffer = [[self output] copyPixelBufferForItemTime:[[self playerItem] currentTime] itemTimeForDisplay:nil];

Как только вы получите свой буфер, вы можете загрузить его в OpenGL, как хотите. Я рекомендую ужасно документированную функцию CVOpenGLESTextureCacheCreateTextureFromImage(), потому что вы получите аппаратное ускорение на всех более новых устройствах, что намного быстрее, чем glTexSubImage2D(). См. Примеры GLCameraRipple в Apple RosyWriter.