【问题标题】:How AVSampleBufferDisplayLayer displays H.264AVSampleBufferDisplayLayer 如何显示 H.264
【发布时间】:2016-12-13 18:32:39
【问题描述】:

我想分享我在这几天积累的知识。没有太多可以找到的。

我仍然对声音感到沮丧。欢迎评论和提示。 ;-)

【问题讨论】:

  • 嘿卡斯滕!在过去的几天里,我和我的团队正在开发一个非常基本的 AVSampleBufferDisplayLayer + AVAssetReader。我们取得了很大进展,但在一些问题上遇到了困难。如果可能的话,我们很乐意提供帮助(如果需要,我们会付费)。有机会我可以通过什么方式与您联系吗?

标签: ios video-streaming h.264


【解决方案1】:

这里是我的代码 sn-ps。声明它

@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 提供了非常丰富的信息。

【讨论】:

  • 此答案缺少所需的大量代码,如下一个答案所示。事实上,这对任何人都不起作用。
  • 不仅代码丢失,而且是错误的。 CMSampleBuffer 没有 data 属性,所以 sampleBuffer.data 没有意义。
  • 数据通过正在读取视频的 outVideo 在第二个 sn-p 中提供。您应该先观看 WWDC 会议 513/2014...
  • 您需要一个 AVAssetReader 来获取曲目(或 AVPlayerItem);并且,一个 AVAssetReader 来读取视频 [AVAssetReader startReading]。我可以看出他根本没有这样做,而且他的代码不起作用,因为他为资产阅读器使用了两个不同的变量:video 和assetReaderVideo。这在任何情况下都行不通。
【解决方案2】:

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

我从原始字节流创建 NALUnit,并使用以下方法传递 IDR 和 Non-IDR 切片:

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

EnqueueSampleBuffer 没有返回错误状态,因此很难找出哪里出错了。

【讨论】:

  • 您最好查看 WWDC 2014 的 Session 513 以了解详细信息。问题在于按预期提供 CMSampleBufferRef。
  • 你可以看看我提供的源代码。 Take a look
  • 我在 AVSampleBufferDisplayLayer 方面取得了一些成功,有没有人在播放时遇到过任何抖动(通常是在 iFrame 到达时)?我已经尝试过缓冲以实现流畅播放,但没有取得太大的成功。我还尝试在 SampleBuffer 中使用 TimingInfo 让它与 PresentationTimeStamp 在同一点播放,同时将“ShouldDisplayImmediately”设置为 false。
  • 也许流中的帧顺序与显示顺序不同?
  • 抖动播放仅发生在单核处理器设备上的多个图层上,或者当您使用 AVAssetReader 加载资产时(它不适合实时播放)。如果您使用 PHImageManager 将资产作为 AVPlayerItem 或 AVAsset 加载到 AVPlayer 中,然后通过 AVPlayerItemVideoDataOutput 重定向播放器输出,则可以轻松地将像素缓冲区转换为样本缓冲区。在与主线程不同的线程上运行执行这些任务的方法,您将获得多达 16 层的实时回放性能。我有为此工作的示例代码;问一下。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多