video ffmpeg video-streaming pts avcodec

Comprender PTS y DTS en marcos de video



ffmpeg video-streaming (1)

Tuve problemas de fps al transcodificar de avi a mp4 (x264). Finalmente, el problema estaba en los valores PTS y DTS, por lo que las líneas 12-15 se agregaron antes de la función av_interleaved_write_frame:

1. AVFormatContext* outContainer = NULL; 2. avformat_alloc_output_context2(&outContainer, NULL, "mp4", "c://test.mp4"; 3. AVCodec *encoder = avcodec_find_encoder(AV_CODEC_ID_H264); 4. AVStream *outStream = avformat_new_stream(outContainer, encoder); 5. // outStream->codec initiation 6. // ... 7. avformat_write_header(outContainer, NULL); 8. // reading and decoding packet 9. // ... 10. avcodec_encode_video2(outStream->codec, &encodedPacket, decodedFrame, &got_frame) 11. 12. if (encodedPacket.pts != AV_NOPTS_VALUE) 13. encodedPacket.pts = av_rescale_q(encodedPacket.pts, outStream->codec->time_base, outStream->time_base); 14. if (encodedPacket.dts != AV_NOPTS_VALUE) 15. encodedPacket.dts = av_rescale_q(encodedPacket.dts, outStream->codec->time_base, outStream->time_base); 16. 17. av_interleaved_write_frame(outContainer, &encodedPacket)

Después de leer muchos mensajes, todavía no entiendo:

  1. outStream->codec->time_base = 1/25 y outStream->time_base = 1/12800. El primero fue establecido por mí, pero no puedo entender por qué y quién configuró 12800. Me di cuenta de que antes de la línea (7) outStream->time_base = 1/90000 y justo después cambia a 1/12800, ¿por qué? Cuando transcoblo de avi a avi, lo que significa cambiar la línea (2) a avformat_alloc_output_context2(&outContainer, NULL, "avi", "c://test.avi"; por lo que antes y después de la línea (7) outStream->time_base permanece siempre 1/25 y no como en el caso mp4, ¿por qué?
  2. ¿Cuál es la diferencia entre time_base de outStream->codec y outStream ?
  3. Para av_rescale_q los pts av_rescale_q hace: toma 2 time_base, multiplica sus fracciones en cross y luego calcula los pts. ¿Por qué hace esto de esta manera? Como encodedPacket.pts , el encodedPacket.pts tiene un valor incremental en 1, entonces, ¿por qué cambiarlo si tiene valor?
  4. Al principio, el valor de dts es -2 y después de cada cambio de escala todavía tiene un número negativo, pero a pesar de esto el video se reprodujo correctamente. ¿No debería ser positivo?

  1. La base de tiempo es solo una unidad de medida. Se pueden usar diferentes unidades para representar los mismos tiempos (aproximadamente, si no son múltiplos exactos). En algunos casos, un formato de contenedor requiere una cierta base de tiempo y será configurado por el muxer. En otros casos, el contenedor no requiere una base de tiempo, pero tiene un valor predeterminado que es posible que tenga que anular. No estoy seguro acerca de 1/12800 específicamente, sé que 1/600 es un valor especial en la especificación mp4.

  2. Las dos bases de tiempo son las unidades de medida de tiempo para el códec y para el contenedor. Si se usan fps constantes, la unidad de códec de cómputo comúnmente se establece en el intervalo entre cada cuadro y el siguiente (la duración que se muestra cada cuadro), de modo que los tiempos de cuadro son enteros sucesivos. Sin embargo, no tiene que establecerse en 1 / fps, siempre que los tiempos pts sean correctos en cualquier unidad que se use.

  3. Lo que describes es simplemente lo que uno debería hacer para convertir de una unidad a otra. (es decir: multiplicar por unidad antigua, dividir por nueva). Un tiempo t en unidades de a/b se puede convertir en unidades c/d como t*(a*d)/(b*c) .

  4. La secuencia dts puede comenzar desde cualquier valor, no hay un significado especial para dts 0. Al inicio de la reproducción, se calcula la diferencia entre el reloj de pared y los dts iniciales, y todos los futuros dts se convierten en reloj de pared usando eso. Una transmisión de video con dts = -10, -9, -8, ... está perfectamente bien. La diferencia entre sucesivos dts es lo que se usa, los valores absolutos no importan.