Подтвердить что ты не робот

Понимание PTS и DTS в видеокадрах

У меня возникла проблема с fps при перекодировании с avi на mp4 (x264). В конце концов проблема была в значениях PTS и DTS, поэтому строки 12-15, добавленные до функции 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)

Прочитав много сообщений, я до сих пор не понимаю:

  • outStream->codec->time_base= 1/25 и outStream->time_base= 1/12800. Первый был установлен мной, но я не могу понять, почему и кто установил 12800? Я заметил, что перед строкой (7) outStream->time_base= 1/90000 и сразу после нее она изменяется до 1/12800, почему? Когда я перекодирую из avi в avi, то есть меняя строку (2) на avformat_alloc_output_context2(&outContainer, NULL, "avi", "c:\\test.avi";, поэтому до и после строки (7) outStream->time_base остается всегда 1/25 и не нравится в случае mp4, почему?
  • В чем разница между time_base outStream->codec и outStream?
  • Для вычисления pts av_rescale_q делает: принимает 2 time_base, умножает их фракции на крест и затем вычисляет pts. Почему это делается так? Когда я отлаживался, encodedPacket.pts имеет значение incremental на 1, поэтому зачем его менять, если оно имеет значение?
  • В начале значение dts равно -2, и после каждого масштабирования он все еще имеет отрицательное число, но, несмотря на это, видео воспроизводится правильно! Не должно быть положительным?
4b9b3361

Ответ 1

  • Time_base - это всего лишь единица измерения. Различные единицы могут использоваться для представления одинакового времени (приблизительно, если они не являются точными кратными). В некоторых случаях для формата контейнера требуется определенная база времени, и она будет установлена ​​на мультиплексор. В других случаях для контейнера не требуется база времени, но по умолчанию она может быть переопределена. Я не уверен в 1/12800, я знаю, что 1/600 - это особое значение в спецификации mp4.

  • Две базы времени - это единицы измерения времени для кодека и для контейнера. Если используется постоянный fps, единица измерения кодека обычно устанавливается на интервал между каждым кадром и следующим (продолжительность отображения каждого кадра), так что времена кадра являются целыми целыми числами. Однако он не должен быть установлен в 1/fps, если время pts правильное в любых единицах.

  • То, что вы описываете, - это просто то, что нужно было бы сделать для преобразования из одной единицы в другую. (т.е. умножить на старый блок, делить на новый). Время t в единицах a/b может быть преобразовано в единицы c/d как t*(a*d)/(b*c).

  • Последовательность dts может начинаться с любого значения, нет особого значения для dts 0. При начале воспроизведения вычисляется разница между временем настенных часов и начальными dts, а все будущие dts преобразуются в стену часы используя это. Видеопоток с dts = -10, -9, -8,... отлично работает. Разница между последовательными dts - это то, что используется, абсолютные значения не имеют значения.