Синхронизация декодированного видео с помощью Ffmpeg

Я использую Ffmpeg для декодирования и воспроизведения видеофайлов. В настоящее время у меня воспроизводится видео и звук так быстро, как процессор может их декодировать и отображать. Проблема в том, что я хочу воспроизводить видео и звук синхронно, используя системные часы.

Я искал помощь, но не нашел ничего существенного, кроме урока 05, но Я не очень понимаю, что он делает, потому что моя программа написана не так, как его.

Я использую файлы mjpeg, поэтому кажется, что pts извлекаются каждый раз, когда кадр декодируется, я умножил pts на time_base, как это делает dranger, чтобы получить значение в секундах, но разрешение кажется всего лишь секундами, и поэтому я получаю значение «6» 25 раз, а затем «7» 25 раз, поскольку видео воспроизводится со скоростью 25 кадров в секунду.

Нет ли более точного значения? Или способ получить более точное значение, и если да, то как мне выполнить синхронизацию с этим значением? Я использую SDL для отображения значения, поэтому могу ли я просто использовать SDL_Delay() полученного значения?

Спасибо за ваше время,

Инфинитифизз


person Infiniti Fizz    schedule 18.07.2011    source источник
comment
Убедитесь, что вы используете правильный тип, возможно, вы выполняете вычисление pts * time_base как int вместо float.   -  person Nathan Whitehead    schedule 19.07.2011
comment
Что ж, значение PTS, похоже, находится в int64t, а не в float или double.   -  person Infiniti Fizz    schedule 19.07.2011
comment
Глядя на учебник dranger, он в основном использует точки первого пакета, из которого состоит кадр, в качестве точек кадра или, если он не существует, значение dts пакета. Затем это значение умножается на видео time_base (как двойное), но все еще является uint64_t, поэтому я просто получаю вывод, например: 0,0,0,0,0,0,1,1,1,1,1,1 ,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4 и т. д., а не что-то в миллисекундах или что-то более точное, чем секунды.   -  person Infiniti Fizz    schedule 19.07.2011


Ответы (1)


Чтобы преобразовать pts или dts в секунды с плавающей запятой, используйте av_q2d() с правильным time_base:

// You got the context from open_input:
AVFormatContext *pFormatCtx;
avformat_open_input(&pFormatCtx, inputfilename, NULL, &format_opts);

// Get a stream from the context
AVStream pStream= pFormatCtx->streams[i];

// Convert packet time (here, dts) to seconds with:  
double seconds= (dts - pStream->start_time) * av_q2d(pStream->time_base);

// Or convert frame number to seconds with the codec context
AVCodecContext *pCodecCtx= pStream->pVideoStream->codec;
double seconds= framenumber * av_q2d(pCodecCtx->time_base);

Это возвращает время, с которого начинается видео, в секундах.

person hexatron    schedule 17.03.2012
comment
Что такое кадр и откуда вы получаете dts? - person Ian Medeiros; 28.06.2012
comment
Вы, вероятно, решили свои проблемы, но для будущих искателей: framenumber получается из pCodecCtx, а dts происходит из AVPacket, которое вы получаете после вызова функции декодирования. - person Sam; 07.09.2015