objective-c - textura - texture mapping opengl
¿Puedo usar AVFoundation para transmitir los cuadros de video descargados en una textura OpenGL ES? (1)
Hay algunas API que se lanzaron con iOS 6 que he podido usar para facilitar el proceso. No utiliza AVAssetReader
en absoluto, y en su lugar se basa en una clase llamada AVPlayerItemVideoOutput
. Se puede agregar una instancia de esta clase a cualquier instancia de AVPlayerItem
través de un nuevo método -addOutput:
.
A diferencia del AVAssetReader
, esta clase funcionará bien para AVPlayerItem
s que están respaldados por un AVURLAsset
remoto, y también tiene la ventaja de permitir una interfaz de reproducción más sofisticada que admite la reproducción no lineal mediante -copyPixelBufferForItemTime:itemTimeForDisplay:
(en lugar de AVAssetReader
-copyNextSampleBuffer
severamente el método -copyNextSampleBuffer
.
CÓDIGO DE MUESTRA
// 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];
Una vez que tengas tu búfer, puedes subirlo a OpenGL como quieras. Recomiendo la función CVOpenGLESTextureCacheCreateTextureFromImage()
horriblemente documentada, porque obtendrás la aceleración de hardware en todos los dispositivos más nuevos, que es mucho más rápido que glTexSubImage2D()
. Vea las GLCameraRipple de Apple GLCameraRipple y RosyWriter para ver ejemplos.
He podido usar la clase AVAssetReader de AVAssetReader
para cargar marcos de video en una textura OpenGL ES. Sin embargo, tiene una caveat , ya que falla cuando se usa con un AVURLAsset
que apunta a medios remotos. Este fracaso no está bien documentado, y me pregunto si hay alguna manera de solucionar el problema.