我已经能够使用 AVFoundation 的AVAssetReader
类将视频帧上传到 OpenGL ES 纹理中。但是,它有一个警告,因为它在与AVURLAsset
指向远程媒体的 an 一起使用时会失败。这个失败没有很好的记录,我想知道是否有任何方法可以解决这个缺点。
问问题
9355 次
1 回答
31
iOS 6 中发布了一些 API,我可以使用这些 API 使该过程变得轻而易举。它根本不使用AVAssetReader
,而是依赖于一个名为AVPlayerItemVideoOutput
. AVPlayerItem
可以通过新-addOutput:
方法将此类的实例添加到任何实例。
与 不同的是AVAssetReader
,此类对于AVPlayerItem
由远程支持的 s可以正常工作,并且还具有允许通过(而不是严格限制方法)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()
. 有关示例,请参阅 Apple 的GLCameraRipple和RosyWriter演示。
于 2012-09-19T18:06:31.680 回答