- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想用 AVSampleBufferDisplayLayer 显示一些 CMSampleBuffer,但它在显示第一个示例后卡住。
我从 AVCaptureVideoDataOutputSampleBuffer 委托(delegate)中获取样本缓冲区:
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
CFRetain(sampleBuffer);
[self imageToBuffer:sampleBuffer];
CFRelease(sampleBuffer);
}
将它们放入向量中
-(void) imageToBuffer: (CMSampleBufferRef )source{
//buffers is defined as: std::vector<CMSampleBufferRef> buffers;
CMSampleBufferRef newRef;
CMSampleBufferCreateCopy(kCFAllocatorDefault, source, &newRef);
buffers.push_back(newRef);
}
然后尝试通过 AVSampleBufferDisplayLayer(在另一个 ViewController 中)显示它们
AVSampleBufferDisplayLayer * displayLayer = [[AVSampleBufferDisplayLayer alloc] init];
displayLayer.bounds = self.view.bounds;
displayLayer.position = CGPointMake(CGRectGetMidX(self.displayOnMe.bounds), CGRectGetMidY(self.displayOnMe.bounds));
displayLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
displayLayer.backgroundColor = [[UIColor greenColor] CGColor];
[self.view.layer addSublayer:displayLayer];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
dispatch_queue_t queue = dispatch_queue_create("My queue", DISPATCH_QUEUE_SERIAL);
[displayLayer setNeedsDisplay];
[displayLayer requestMediaDataWhenReadyOnQueue:queue
usingBlock:^{
while ([displayLayer isReadyForMoreMediaData]) {
if (samplesKey < buffers.size()) {
CMSampleBufferRef buf = buffers[samplesKey];
[displayLayer enqueueSampleBuffer:buffers[samplesKey]];
samplesKey++;
}else
{
[displayLayer stopRequestingMediaData];
break;
}
}
}];
但它显示第一个样本然后卡住,什么也不做。
而我的视频数据输出设置如下:
//set up our output
self.videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
dispatch_queue_t queue = dispatch_queue_create("VideoQueue", DISPATCH_QUEUE_SERIAL);
[_videoDataOutput setSampleBufferDelegate:self queue:queue];
[_videoDataOutput setVideoSettings:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],(id)kCVPixelBufferPixelFormatTypeKey,
nil]];
最佳答案
我在相同的上下文中遇到过这个问题,试图从 AVCaptureVideoDataOutput 获取输出并将其显示在 AVSampleDisplay 层中。
如果您的帧按显示顺序显示,则修复非常简单,只需在 CMSampleBufferRef 上设置立即显示标志即可。
获取委托(delegate)返回的样本缓冲区,然后...
CFArrayRef attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, YES);
CFMutableDictionaryRef dict = (CFMutableDictionaryRef)CFArrayGetValueAtIndex(attachments, 0);
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
如果您的帧按编码器顺序(而非显示顺序)输出,则 CMSampleBuffer 上的时间戳需要零偏差并重新标记,以便第一帧时间戳等于时间 0。
double pts = CMTimeGetSeconds(CMSampleBufferGetPresentationTimeStamp(sampleBuffer));
// ptsStart is equal to the first frames presentationTimeStamp so playback starts from time 0.
CMTime presentationTimeStamp = CMTimeMake((pts-ptsStart)*1000000,1000000);
CMSampleBufferSetOutputPresentationTimeStamp(sampleBuffer, presentationTimeStamp);
更新:
当我使用零偏差方法时,我遇到了一些视频仍然播放不流畅的情况,我进一步调查了。正确答案似乎是使用您打算播放的第一帧的 PTS。
我的答案在这里,但我也会在这里发布。
Set rate at which AVSampleBufferDisplayLayer renders sample buffers
Timebase 需要设置为您要解码的第一帧的呈现时间戳 (pts)。我通过从所有后续点中减去初始点并将时基设置为 0 将第一帧的点索引为 0。无论出于何种原因,这不适用于某些视频。
你想要这样的东西(在解码调用之前调用):
CMTimebaseRef controlTimebase;
CMTimebaseCreateWithMasterClock( CFAllocatorGetDefault(), CMClockGetHostTimeClock(), &controlTimebase );
displayLayer.controlTimebase = controlTimebase;
// Set the timebase to the initial pts here
CMTimebaseSetTime(displayLayer.controlTimebase, CMTimeMake(ptsInitial, 1));
CMTimebaseSetRate(displayLayer.controlTimebase, 1.0);
为 CMSampleBuffer 设置 PTS...
CMSampleBufferSetOutputPresentationTimeStamp(sampleBuffer, presentationTimeStamp);
也许确保没有设置立即显示....
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanFalse);
这在 WWDC 2014 session 513 中有非常简短的介绍。
关于ios - 为什么 AVSampleBufferDisplayLayer 停止显示从 AVCaptureVideoDataOutput 的委托(delegate)中获取的 CMSampleBuffers?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28700206/
我在 iOS 上遇到 AVSampleBufferDisplayLayer 问题。我想使用这一层显示 CVPixelBuffer,但我无法在实际的 iOS 设备上运行它。在我的示例应用程序中,我尝试使
我有一些视频显示在 AVsampleBufferDisplayLayer 上,我想捕获此图像并将其保存到相册中。由于 AVSampleBufferDisplayLayer 继承自 CALayer,我认
我正在使用 AVSampleBufferDisplayLayer 来显示通过网络连接以 h.264 格式传输的 CMSampleBuffer。视频播放流畅且工作正常,但我似乎无法控制帧速率。具体来说,
在我的项目中,我使用了 AVSampleBufferDisplayLayer 和 AVPlayerLayer。它们的 Bot 具有相似的界面和 videoGravity 属性。当我更改 AVPlaye
我有这个委托(delegate)方法 -(void)airPlayServer:(id)server sampleBufferReceived:(CMSampleBufferRef)sampleBuf
我一直在与 AVSampleBufferDisplayLayer 作斗争,因为它真的很不稳定,有很多 Action 。当我的直播中有运动时,它会变成像素化和半卡住状态,同时显示多个帧。但是,一旦我添加
我正在尝试在 AVSampleBufferDisplayLayer 上循环播放视频。我可以毫无问题地播放一次。但是,当我尝试循环播放时,它并没有继续播放。 根据对 AVFoundation to re
我想知道是否有人知道为什么 AVSampleBufferDisplayLayer 被标记为“__TVOS_PROHIBITED”? 我不想在这里写些讽刺的话,但禁止在电视设备上呈现视频这一事实有点有趣
我正在尝试在基于 Swift 的项目中设置视频流查看器。 我查看了以下非常有帮助的内容( objective-c ):How AVSampleBufferDisplayLayer displays H
我想分享我这几天积累的知识。没有太多关于它的信息。 我还在为声音嘶嘶作响。欢迎提出意见和提示。 ;-) 最佳答案 这是我的代码片段。声明一下 @property (nonatomic, retain)
我正在使用 AVSampleBufferDisplayLayer 来解码和显示从服务器流式传输的 H.264 视频。当我的应用程序进入后台然后返回前台时,解码过程被搞砸并且 AVSampleBuffe
我一直在探索 iOS 上的选项来实现原始 H.264 流的硬件加速解码,到目前为止我只发现唯一的选择是将 H.264 流写入 MP4 文件,然后将文件传递给AVAssetReader 的一个实例。尽管
在详细回顾了 WWDC2014,Session513 之后,我尝试在 IOS8.0 上编写我的应用程序来解码和显示一个实时 H.264 流。首先,我成功构建了一个H264参数集。当我得到一个带有 4
我想用 AVSampleBufferDisplayLayer 显示一些 CMSampleBuffer,但它在显示第一个示例后卡住。 我从 AVCaptureVideoDataOutputSampleB
在得知 iOS 8 中的程序员可以使用 HW-H264-Decoder 后,我想立即使用它。 WWDC 2014 对“直接访问视频编码和解码”有一个很好的介绍。你可以看看here . 基于那里的案例
我是一名优秀的程序员,十分优秀!