设置AVSampleBufferDisplayLayer呈现样本缓冲区的速率

我正在使用AVSampleBufferDisplayLayer来显示通过h.264格式的networking连接来的CMSampleBuffers。 video播放是顺利和正常工作,但我似乎无法控制帧速率。 特别是,如果我在AVSampleBufferDisplayLayer中每秒排列60帧,即使video以30 FPSlogging,它也会显示这60帧。

创build样本缓冲区时,可以通过向CMSampleBufferCreate传递一个时间信息数组来设置表示时间戳(时间信息不在h.264stream中,但可以通过容器格式进行计算或传递)。 我设置的演示时间戳大约相隔0.033秒,持续时间为0.033,但显示层仍然每秒显示尽可能多的帧数。

有两种方法可以在AVSampleBufferDisplayLayer上排队缓冲区:通过在缓冲区就绪时调用[AVSampleBufferDisplayLayer enqueueSampleBuffer:],或通过调用[AVSampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue:usingBlock:]并使该块中的缓冲区排入队列,来“约束”缓冲区。 我已经尝试了两个,但即使第二个方法尽可能快地显示缓冲区 – 例如,如果我有300帧在接收端排队,那么上面的方法中的块第一次执行readyForMoreMediaData保持真实无论多less缓冲区会被排队,并且它们都会在很短的时间内显示出来。

如果在CMSampleBuffer上设置了kCMSampleAttachmentKey_DisplayImmediately附件,则此行为与预期的行为类似,但目前未设置(默认值为false)。

我试图设置图层controlTimeBase,但它似乎没有任何效果。 我在其他东西的损失尝试,无法find网上的例子。 有谁知道如何控制AVSampleBufferDisplayLayer显示帧的帧率?

时基需要设置为您打算解码的第一帧的显示时间戳(pts)。 我通过从所有后续的pts中减去初始pts并将timebase设置为0来将第一帧的pts索引到0。不pipe出于什么原因,这是行不通的。

你想要这样的东西( 调用解码之前调用):

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会议513中对此进行了非常简短的介绍。

打了同样的问题,设法播放一个又一个stream,没有滞后时间在CMSampleBufferCreate创build

 CMSampleTimingInfo timingdata ={ .presentationTimeStamp = CMTimeMakeWithSeconds(self.frame0time+(1/self.frameFPS)*self.frameActive, 1000), .duration = CMTimeMakeWithSeconds(1/self.frameFPS, 1000), .decodeTimeStamp = kCMTimeInvalid }; 

不需要使用kCMSampleAttachmentKey_Display立即使用这种方法,你只需要在每个iframe和BFrame上使用self.frameActive ++,并使self.frame0time = CACurrentMediaTime(); 在第一帧