Informazioni su PTS e DTS nei frame video



ffmpeg video-streaming (1)

  1. Time_base è solo un'unità di misura. Unità diverse possono essere utilizzate per rappresentare gli stessi orari (approssimativamente, se non sono multipli esatti). In alcuni casi un formato contenitore richiede una certa base di tempo e sarà impostato dal muxer. In altri casi il contenitore non richiede una base di tempo ma ha un valore predefinito che potrebbe essere necessario sovrascrivere. Non sono sicuro di 1/12800 in particolare, so che 1/600 è un valore speciale nelle specifiche MP4.

  2. Le due basi temporali sono le unità di misura del tempo per il codec e per il contenitore. Se si utilizza il fps costante, l'unità di misura del codec viene comunemente impostata sull'intervallo tra ciascun fotogramma e il successivo (la durata di visualizzazione di ciascun fotogramma), in modo che i tempi di fotogramma siano interi successivi. Tuttavia, non deve essere impostato su 1 / fps, a patto che i tempi dei pts siano corretti in qualsiasi unità venga utilizzata.

  3. Quello che descrivi è semplicemente ciò che si dovrebbe fare per convertire da un'unità all'altra. (es: moltiplicare per unità vecchia, dividere per nuova). Un tempo t in unità di a/b può essere convertito in unità c/d come t*(a*d)/(b*c) .

  4. La sequenza dts può iniziare da qualsiasi valore, non c'è alcun significato speciale per i valori 0. All'inizio della riproduzione, viene calcolata la differenza tra l'ora del muro e il dts iniziale, e tutti i futuri dts vengono convertiti in orologio a muro usando quello. Un flusso video con dts = -10, -9, -8, ... è perfettamente a posto. La differenza tra i dts successivi è quella che viene usata, i valori assoluti non contano.

Ho avuto problemi di fps durante la transcodifica da avi a mp4 (x264). Alla fine il problema era nei valori PTS e DTS, quindi le righe 12-15 dove sono state aggiunte prima della funzione 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)

Dopo aver letto molti post, ancora non capisco:

  1. outStream->codec->time_base = 1/25 e outStream->time_base = 1/12800. Il primo è stato impostato da me ma non riesco a capire perché e chi ha impostato 12800? Ho notato che prima della riga (7) outStream->time_base = 1/90000 e subito dopo esso cambia in 1/12800, perché? Quando transcodifico da avi a avi, ovvero cambiando la riga (2) in avformat_alloc_output_context2(&outContainer, NULL, "avi", "c:\\test.avi"; così prima e dopo la riga (7) outStream->time_base rimane sempre 1/25 e non come nel caso mp4, perché?
  2. Qual è la differenza tra time_base di outStream->codec e outStream ?
  3. Per av_rescale_q i pts av_rescale_q fa: richiede 2 time_base, moltiplica le loro frazioni in cross e quindi calcola i pts. Perché lo fa in questo modo? Come ho eseguito il debug, il file encodedPacket.pts ha un valore incrementale di 1, quindi perché cambiarlo se ha valore?
  4. All'inizio il valore di dts è -2 e dopo ogni riscalation ha ancora un numero negativo, ma nonostante questo il video è stato riprodotto correttamente! Non dovrebbe essere positivo?




avcodec