【发布时间】:2012-03-29 11:51:21
【问题描述】:
我有一个 AVPlayerLayer(CALayer 的子类),我需要进入一个可以传递给 QCRenderer 的图像类型(QCRenderer 接受 NSImages 和 CIImages。)我可以将 CALayer 转换为 CGImageRef,并将其转换为NSImage,但内容总是清晰的。
我已将其缩小为以下两个原因之一:
- 我没有正确创建 NSImage。
- AVPlayer 未渲染到 AVPlayerLayer。
我没有收到任何错误,并且找到了一些关于转换 CALayers 的文档。另外,我将 AVPlayerLayer 添加到 NSView 中,它仍然是空的,所以我相信 2 是问题所在。
我正在使用 Apple 的 AVPlayerDemo 的 AVPlayerDemoPlaybackViewController 的修改版本。我把它变成了一个 NSObject,因为我把所有的接口代码都去掉了。
当我创建 AVPlayer 时,我在 (void)prepareToPlayAsset:withKeys: 方法中创建了 AVPlayerLayer:(我只是将图层添加到 NSView 以测试它是否正常工作。)
if (![self player])
{
/* Get a new AVPlayer initialized to play the specified player item. */
[self setPlayer:[AVPlayer playerWithPlayerItem:self.mPlayerItem]];
/* Observe the AVPlayer "currentItem" property to find out when any
AVPlayer replaceCurrentItemWithPlayerItem: replacement will/did
occur.*/
[self.player addObserver:self
forKeyPath:kCurrentItemKey
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:AVPlayerDemoPlaybackViewControllerCurrentItemObservationContext];
mPlaybackView = [AVPlayerLayer playerLayerWithPlayer:self.player];
[self.theView setWantsLayer:YES];
[mPlaybackView setFrame:self.theView.layer.bounds];
[self.theView.layer addSublayer:mPlaybackView];
}
然后我创建一个 NSRunLoop 以每秒 30 次抓取 AVPlayerLayer 的帧:
framegrabTimer = [NSTimer timerWithTimeInterval:(1/30) target:self selector:@selector(grabFrameFromMovie) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:framegrabTimer forMode:NSDefaultRunLoopMode];
这是我用来抓取帧并将其传递给处理 QCRenderer 的类的代码:
-(void)grabFrameFromMovie {
CGColorSpaceRef colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGContextRef theContext = CGBitmapContextCreate(NULL, mPlaybackView.frame.size.width, mPlaybackView.frame.size.height, 8, 4*mPlaybackView.frame.size.width, colorSpace, kCGImageAlphaPremultipliedLast);
[mPlaybackView renderInContext:theContext];
CGImageRef CGImage = CGBitmapContextCreateImage(theContext);
NSImage *image = [[NSImage alloc] initWithCGImage:CGImage size:NSMakeSize(mPlaybackView.frame.size.width, mPlaybackView.frame.size.height)];
[[NSNotificationCenter defaultCenter] postNotificationName:@"AVPlayerLoadedNewFrame" object:[image copy]];
CGContextRelease(theContext);
CGColorSpaceRelease(colorSpace);
CGImageRelease(CGImage); }
我不明白为什么我只是变得清楚。非常感谢您对此提供任何帮助,因为没有足够的 OS X AVFoundation 文档。
【问题讨论】:
-
你好。你有这个问题的运气吗?以某种方式解决?我也想从 AVPlayerLayer 截屏,但到目前为止 renderInContext 对我不起作用。
-
我不确定它与您的问题有何关系,但
timerWithTimeInterval:(1/30)并没有按照您的想法行事。1/30的计算结果为 0,因为两个操作数都是整数,您应该使用1./30.来获得 0.0333333 的双精度值。
标签: macos avfoundation calayer avplayer