¿Pueden los ffmpeg av libs devolver un PTS preciso?

Estoy trabajando con una secuencia de mpeg que usa una secuencia IBBP ... GOP. Los valores (DTS, PTS) devueltos para los primeros 4 AVPackets son los siguientes: I = (0,3) B = (1,1) B = (2,2) P = (3,6)

El PTS en el cuadro I parece legítimo, pero el PTS en los cuadros B no puede ser correcto, ya que los cuadros B no deberían mostrarse antes del cuadro I como lo indican sus valores PTS. También intenté decodificar los paquetes y usar el valor pts en el AVFrame resultante, puse que el PTS siempre se establece en cero.

¿Hay alguna forma de obtener un PTS exacto de ffmpeg? Si no, ¿cuál es la mejor manera de sincronizar el audio?

0
agregado
Puntos de vista: 1

2 Respuestas

Creo que finalmente descubrí lo que sucede a partir de un comentario hecho en http: //www.dranger. com/ffmpeg/tutorial05.html :

ffmpeg reordena los paquetes para que el DTS del paquete procesado por avcodec_decode_video() siempre sea el mismo que el PTS del marco que devuelve

Traducción: Si introduzco un paquete en avcodec_decode_video() que tiene un PTS de 12, avcodec_decode_video() no devolverá el marco decodificado contenido en ese paquete hasta que lo alimente con un paquete later que tenga un DTS de 12. Si el PTS del paquete es el mismo que su DTS, entonces el paquete dado es el mismo que el que se devuelve. Si el PTS del paquete es 2 fotogramas más tarde que su DTS, entonces avcodec_decode_video() retrasará el fotograma y no lo devolverá hasta que proporcione 2 paquetes más.

En función de este comportamiento, supongo que av_read_frame() tal vez reordene los paquetes de IPBB a IBBP, de modo que avcodec_decode_video() solo tenga que almacenar en búfer los cuadros P para 3 cuadros en lugar de 5. Por ejemplo, la diferencia entre la entrada y la salida del cuadro P con este orden es 3 (6 - 3):

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

frente a una diferencia de 5 con el orden estándar (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
agregado

Estoy bastante seguro de que está obteniendo valores precisos. Podría ser útil si piensas en una transmisión MPEG como, bueno, una transmisión. En ese caso, antes del IBBPBB que ves normalmente habría otro GOP. Tal vez algo así (usando la misma notación que la pregunta original):

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

Básicamente, los cuadros B después de los cuadros I se basan en el cuadro I y el último cuadro P del anterior GOP.

Si bien tiene sentido lógico que un video comience con esto:

Start GOP: IPBBPBBPBB...

Más tarde debe ser

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

Recuerde que decodificar cualquier cuadro B requiere un cuadro completo antes y después de él. Por lo tanto, cada par de fotogramas B debe mostrarse antes del fotograma I o P justo antes de este en el archivo.

FFMPEG puede haber olvidado el "caso especial" del primer GOP.

Como los primeros dos fotogramas B no tienen un fotograma previo para manipular, debe poder descartarlos con seguridad. Simplemente restaure sus marcas de tiempo del primer fotograma I y ajuste la transmisión de audio en la misma cantidad.

Si esto realmente resultará en una pérdida de cuadros dependerá de la implementación de FFMPEG, pero el peor escenario es que pierda 83 milisegundos (2 cuadros a 24 cuadros/seg).

0
agregado
Este tipo de pirateo (aceptar la pérdida de 2 fotogramas) es ... hacky :) La documentación de la vergüenza es tan aburrida que casi nadie molesta.
agregado el autor Roman Starkov, fuente