Может ли ffmpeg av libs вернуть точный PTS? - PullRequest
7 голосов
/ 18 сентября 2008

Я работаю с потоком MPEG, который использует последовательность IBBP ... GOP. (DTS,PTS) значения, возвращаемые для первых 4 AVPackets, следующие: I=(0,3) B=(1,1) B=(2,2) P=(3,6)

PTS в I-кадре выглядит так, как будто он действительный, но тогда PTS в B-кадрах не может быть правильным, поскольку B-кадры не должны отображаться перед I-кадром, как показывают их значения PTS. Я также попытался декодировать пакеты и, используя значение pts в результирующем AVFrame, установить, что PTS всегда установлен в ноль.

Есть ли способ получить точный PTS из ffmpeg? Если нет, то как лучше синхронизировать звук?

Ответы [ 3 ]

10 голосов
/ 19 сентября 2008

Мне кажется, я наконец понял, что происходит, основываясь на комментарии, сделанном в http://www.dranger.com/ffmpeg/tutorial05.html:

ffmpeg переупорядочивает пакеты так, что DTS пакета, обрабатываемого avcodec_decode_video (), будет всегда такой же , что и PTS кадра, который он возвращает

Перевод: если я передам пакет в avcodec_decode_video (), у которого PTS равен 12, avcodec_decode_video () не вернет декодированный кадр, содержащийся в этом пакете, пока я не передам ему позже пакет, который имеет DTS из 12. Если PTS пакета совпадает с его DTS, то данный пакет совпадает с возвращаемым кадром. Если PTS пакета на 2 кадра позже, чем его DTS, то avcodec_decode_video () задержит кадр и не вернет его, пока я не предоставлю еще 2 пакета.

Исходя из этого поведения, я предполагаю, что av_read_frame (), возможно, переупорядочивает пакеты от IPBB к IBBP, так что avcodec_decode_video () должен только буферизовать P-кадры для 3 кадров вместо 5. Например, разница между вход и выход P-кадра с этим порядком равен 3 (6 - 3):

|                  I B B P B B P
|             DTS: 0 1 2 3 4 5 6
| decode() result:       I B B P

против. разница 5 со стандартным порядком (6 - 1):

|                  I P B B P B B
|             DTS: 0 1 2 3 4 5 6
| decode() result:       I B B P

<пожимает плечами /> но это чистое предположение.

1 голос
/ 19 сентября 2008

Хорошо, поцарапайте мой предыдущий запутанный ответ.

Для фильма IBBPBBI можно ожидать, что PTS будут выглядеть так (в порядке декодирования)

0, 3, 1, 2, 6, 4, 5, ...

соответствует кадрам

I, P, B, B, I, B, B, ...

Таким образом, вы, кажется, пропускаете I в начале вашей последовательности, но в противном случае временные метки выглядят правильно.

0 голосов
/ 20 сентября 2008

Я вполне уверен, что вы получаете точные значения. Это может помочь, если вы считаете поток MPEG потоком. В этом случае перед IBBPBB, который вы видите, обычно будет другая GOP. Может быть, что-то вроде этого (используя ту же запись, что и в оригинальном вопросе):

P(-3,-2)  B(-2,-1)  B(-1,0)

В основном B-кадры после I-кадров основаны на I-кадре и последнем P-кадре из предыдущего GOP.

Хотя логично начинать видео с этого:

Start GOP: IPBBPBBPBB...

Позже это должно быть

Start GOP: IBBPBBPBBPBB
Start GOP: IBBPBBPBBPBB
Start GOP: IBB... 

Помните, что для декодирования любого B-кадра требуется полный кадр до и после него. Таким образом, каждая пара кадров B должна отображаться перед кадром I или P непосредственно перед ним в файле.

FFMPEG мог просто отказаться от «особого случая» первой GOP.

Поскольку первые два B-кадра не имеют предшествующего кадра для манипулирования, вы должны быть в состоянии безопасно отбросить их. Просто сдвиньте временные метки с первого I-кадра и настройте аудиопоток на ту же величину.

Будет ли это фактически приводить к потере кадров, будет зависеть от реализации FFMPEG, но в худшем случае вы теряете 83 миллисекунды (2 кадра при 24 кадрах в секунду).

...