2

Я использую AVSampleBufferDisplayLayer для отображения CMSampleBuffers, которые поступают через сетевое соединение в формате h.264. Воспроизведение видео является плавным и работает правильно, однако я не могу контролировать частоту кадров. В частности, если я вставляю 60 кадров в секунду в AVSampleBufferDisplayLayer, он отображает эти 60 кадров, даже если видео записывается при 30 FPS.Установите скорость, с которой AVSampleBufferDisplayLayer отображает буферы с образцами

При создании буферов выборки можно установить метку времени представления, передав массив данных синхронизации в CMSampleBufferCreate (информация о синхронизации отсутствует в потоке h.264, но может быть рассчитана или передана в виде контейнера) , Временные метки представления, которые я установил, составляют около 0,033 секунды, а продолжительность составляет 0,033, но уровень отображения по-прежнему отображает столько кадров в секунду, сколько может.

Есть два способа Епдиеих буферов на AVSampleBufferDisplayLayer: «стесненный» по телефону - [AVSampleBufferDisplayLayer enqueueSampleBuffer:] всякий раз, когда буфер готов, или «непринужденный» по телефону - [AVSampleBufferDisplayLayer requestMediaDataWhenReadyOnQueue: usingBlock:] и enqueuing буферов в это блок. Я пробовал оба, но даже второй метод отображает буферы так быстро, как это возможно - например, если у меня есть 300 кадров, стоящих в очереди на принимающей стороне, то при первом запуске блока в вышеописанном методе readyForMoreMediaData остается верным независимо от того, сколько буферы получают в очереди, и все они отображаются за очень короткое время.

Такое поведение похоже на то, что можно было бы ожидать, если в CMSampleBuffer было установлено вложение kCMSampleAttachmentKey_DisplayImmediately, однако в настоящее время оно НЕ установлено (и значение по умолчанию - false).

Я попытался установить слой controlTimeBase, но он, похоже, не имел никакого эффекта. Я испытываю недостаток в других вещах, чтобы попытаться найти примеры в Интернете. Кто-нибудь знает, как можно управлять частотой кадров, при которой AVSampleBufferDisplayLayer отображает фреймы?

+0

Вы когда-нибудь находили решение для этого? – Kaleb

+0

Прошу прощения, что я не –

ответ

1

Для временной шкалы необходимо установить метку времени представления (pts) первого кадра, который вы собираетесь декодировать. Я индексировал pts первого кадра в 0, вычитая начальные pts из всех последующих pts и установив Timebase в 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); 

Установите PTS для CMSampleBuffer ...

CMSampleBufferSetOutputPresentationTimeStamp(sampleBuffer, presentationTimeStamp); 

А может быть, убедитесь, что дисплей сразу ISN 't set ....

CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanFalse); 

Это покрытие очень кратко WWDC 2014 Сессия 513.

0

Хит с той же проблемой, удалось сыграть несколько потоков один за другим без задержек с последующей синхронизации в создании CMSampleBufferCreate

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

Нет необходимости использовать kCMSampleAttachmentKey_DisplayImmediately с этим подходом, вам просто нужно self.frameActive ++ на каждом Iframe и BFrame и сделать self.frame0time = CACurrentMediaTime(); на первом кадре

Смежные вопросы