AVSampleBufferDisplayLayer如何显示H.264视频

11

我想分享我在最近几天里学到的关于IT技术的知识。这方面的资料并不多。

我仍然在琢磨声音的问题。欢迎大家提出评论和建议。;-)


嘿,Karsten!我和我的团队最近几天一直在研究使用AVSampleBufferDisplayLayer + AVAssetReader这个相当基础的东西。我们已经取得了很好的进展,但现在卡在了一些问题上。如果可能的话,我们希望能够得到帮助(付费也可以)。有没有可能我可以以某种方式联系到你呢? - Roi Mulia
2个回答

14

这是我的代码片段。声明它

@property (nonatomic, retain) AVSampleBufferDisplayLayer *videoLayer;

首先设置视频层

self.videoLayer = [[AVSampleBufferDisplayLayer alloc] init];
self.videoLayer.bounds = self.bounds;
self.videoLayer.position = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
self.videoLayer.videoGravity = AVLayerVideoGravityResizeAspect;
self.videoLayer.backgroundColor = [[UIColor greenColor] CGColor];

//set Timebase
CMTimebaseRef controlTimebase;
CMTimebaseCreateWithMasterClock( CFAllocatorGetDefault(), CMClockGetHostTimeClock(), &controlTimebase );

self.videoLayer.controlTimebase = controlTimebase;
CMTimebaseSetTime(self.videoLayer.controlTimebase, CMTimeMake(5, 1));
CMTimebaseSetRate(self.videoLayer.controlTimebase, 1.0);

// connecting the videolayer with the view

[[self layer] addSublayer:_videoLayer];

将视频数据提供给该层

__block AVAssetReaderTrackOutput *outVideo = [AVAssetReaderTrackOutput assetReaderTrackOutputWithTrack:video outputSettings:dic];

if( [assetReaderVideo startReading] )
{
    [_videoLayer requestMediaDataWhenReadyOnQueue: assetQueue usingBlock: ^{
        while( [_videoLayer isReadyForMoreMediaData] )
        {
            CMSampleBufferRef *sampleVideo = [outVideo copyNextSampleBuffer];

            [_videoLayer enqueueSampleBuffer:sampleVideo.data];
        }
    }];
}

更多细节请参考:WWDC 2014中的Session 513非常富有信息量。


这个答案缺少所需的一大段代码,正如下一个回答所指示的那样。目前这个答案对任何人来说都行不通。 - James Bush
代码不仅缺失,而且是错误的。CMSampleBuffer没有数据属性,因此sampleBuffer.data毫无意义。 - James Bush
数据是通过读取视频的outVideo在第二个片段中提供的。您应该先观看WWDC会议513/2014... - Karsten
你需要一个AVAssetReader来获取轨道(或AVPlayerItem),以及一个AVAssetReader来读取视频[AVAssetReader startReading]。我可以看出他完全没有这样做,并且他的代码无法运行,因为他对资产阅读器使用了两个不同的变量:video和assetReaderVideo。任何情况下都不会起作用。 - James Bush

2

我正在尝试这个,但发现AVSampleBufferDisplay图层上没有图像。

我从原始字节流创建NAL单元,并使用以下方式传递IDR和非IDR切片:

if ([avLayer isReadyForMoreMediaData]) {
         [avLayer enqueueSampleBuffer:sampleBuffer];
}

从EnqueueSampleBuffer中没有返回错误状态,因此很难找出问题所在。


你最好查看一下2014年WWDC的Session 513,以获取详细信息。问题在于提供CMSampleBufferRef与预期不符。 - Karsten
流中的帧可能与呈现顺序不同? - Lukasz Czerwinski
多层次的播放只会在单核处理器设备上出现抖动,或者当您使用AVAssetReader来加载资产时(它不适用于实时播放)。如果您使用PHImageManager将资产作为AVPlayerItem或AVAsset加载到AVPlayer中,然后通过AVPlayerItemVideoDataOutput重定向播放器输出,您可以轻松地将像素缓冲区转换为样本缓冲区。将执行这些任务的方法运行在与主线程分离的线程上,您将拥有高达16个图层的实时播放性能。我有可用的工作示例代码,只需询问即可。 - James Bush
没有错误意味着您没有验证样本缓冲区(CMSampleBufferValidate)。顺便说一句,您的样本缓冲区的来源并不重要;除非创建样本缓冲区是问题所在,否则请省略这些细节。它只会不必要地使问题复杂化,听起来像是您正在寻求对NALUnit或其他什么东西的支持。那是一个单独的问题。有50亿种方法来处理样本缓冲区;有时,您需要使用它们全部。 - James Bush
默认情况下,错误消息不会在块内生成;请使用try-catch语句捕获任何异常。 - James Bush
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接