O ffmpeg av libs pode retornar um PTS preciso?

Eu estou trabalhando com um fluxo mpeg que usa uma seqüência IBBP ... GOP. Os valores (DTS, PTS) retornados para os primeiros 4 AVPackets são os seguintes: I = (0,3) B = (1,1) B = (2,2) P = (3,6)

O PTS no quadro I parece ser legítimo, mas o PTS nos quadros B não pode estar certo, já que os quadros B não devem ser exibidos antes do quadro I como seus valores PTS indicam. Eu também tentei decodificar os pacotes e usar o valor pts no AVFrame resultante, colocar que o PTS é sempre definido como zero.

Existe alguma maneira de obter um PTS preciso de ffmpeg? Se não, qual é a melhor maneira de sincronizar o áudio?

0
adicionado
Visualizações: 1

2 Respostas

Acho que finalmente descobri o que está acontecendo com base em um comentário feito em http: //www.dranger. com/ffmpeg/tutorial05.html :

O ffmpeg reordena os pacotes para que o DTS do pacote que está sendo processado pelo avcodec_decode_video() seja sempre o mesmo que o PTS do quadro que ele retorna

Tradução: Se eu alimentar um pacote em avcodec_decode_video() que tem um PTS de 12, avcodec_decode_video() não retornará o quadro decodificado contido naquele pacote até eu alimentá-lo com um pacote posterior que tenha um DTS de 12. Se o PTS do pacote é o mesmo que o seu DTS, então o pacote dado é o mesmo que o quadro retornado. Se o PTS do pacote for 2 quadros mais tarde que seu DTS, então avcodec_decode_video() atrasará o quadro e não o retornará até que eu forneça mais 2 pacotes.

Com base nesse comportamento, estou supondo que av_read_frame() talvez esteja reordenando os pacotes do IPBB para o IBBP, de modo que avcodec_decode_video() tenha que armazenar em buffer os quadros P para 3 quadros em vez de 5. Por exemplo, a diferença entre a entrada e a saída do quadro P com este pedido é 3 (6 - 3):

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

contra uma diferença de 5 com o pedido padrão (6 - 1):

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

but that is pure conjecture.

0
adicionado

Tenho quase certeza de que você está obtendo valores precisos. Pode ser útil se você pensar em um fluxo MPEG como, bem, um fluxo. Nesse caso, antes do IBBPBB, você verá que normalmente haveria outro GOP. Talvez algo assim (usando a mesma notação como pergunta original):

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

Basicamente, os quadros B após os quadros I baseiam-se no quadro I e no último quadro P do GOP anterior .

Enquanto faz sentido lógico para um vídeo começar com isso:

Start GOP: IPBBPBBPBB...

Mais tarde, deve ser

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

Lembre-se de que a decodificação de qualquer quadro B requer um quadro completo antes e depois dele. Portanto, cada par de quadros B deve ser exibido antes do quadro I ou P logo antes no arquivo.

O FFMPEG pode ter simplesmente renunciado ao "caso especial" do primeiro GOP.

Como os dois primeiros quadros B não têm um quadro anterior para manipular, você deve ser capaz de descartá-los com segurança. Basta rebase seus timestamps fora do primeiro quadro e ajustar o fluxo de áudio na mesma quantidade.

Se isso realmente resultará em uma perda de quadros dependerá da implementação do FFMPEG, mas o pior cenário é que você perderá 83 milissegundos (2 quadros a 24 quadros/segundo).

0
adicionado
Esses tipos de hacks (aceitando a perda de 2 frames) são ... hacky :) Vergonha escrever documentação é tão chata que quase ninguém incomoda.
adicionado o autor Roman Starkov, fonte