Путаница с PTS в видеофайлах и медиапотоках

Возможно ли, что PTS конкретного кадра в файле отличается от PTS одного и того же кадра в одном и том же файле во время потоковой передачи?

Когда я читаю кадр с помощью av_read_frame, я сохраняю видеопоток в AVStream. После того, как я декодирую кадр с помощью avcodec_decode_video2, я сохраняю отметку времени этого кадра в int64_t, используя av_frame_get_best_effort_timestamp. Теперь, если программа получает входные данные из файла, я получаю другую временную метку от того, когда я передаю входные данные (из того же файла) в программу.

Чтобы изменить тип ввода, я просто изменяю аргумент argv с «/path/to/file.mp4» на что-то вроде «udp: // localhost: 1234», затем я передаю файл с помощью ffmpeg в командной строке: «ffmpeg -re -i /path/to/file.mp4 -f mpegts udp: // localhost: 1234 «. Может ли это быть из-за того, что аргументы «-f mpegts» меняют некоторые характеристики носителя?

Ниже мой код (упрощенно). Прочитав архивы списка рассылки ffmpeg, я понял, что база времени, которую я ищу, находится в AVStream, а не в AVCodecContext. Вместо использования av_frame_get_best_effort_timestamp я также попытался использовать package.pts, но результаты не изменились.
Мне нужны метки времени, чтобы иметь представление о номере кадра в принимаемом потоковом видео.
Я был бы очень признателен за любую помощь.

//..
//argv[1]="/file.mp4";
argv[1]="udp://localhost:7777";
// define AVFormatContext, AVFrame, etc.
// register av, avcodec, avformat_network_init(), etc.
avformat_open_input(&pFormatCtx, argv, NULL, NULL);
avformat_find_stream_info(pFormatCtx, NULL);
// find the video stream...
// pointer to the codec context...
// open codec...
pFrame=av_frame_alloc();
while(av_read_frame(pFormatCtx, &packet)>=0) {
AVStream *strem = pFormatCtx->streams[videoStream];
if(packet.stream_index==videoStream) {
avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if(frameFinished) {
int64_t perts = av_frame_get_best_effort_timestamp(pFrame);
if (isMyFrame(pFrame)){
cout << perts*av_q2d(strem->time_base) << "\n";
}
}
}
//free allocated space
}
//..

1

Решение

Метки времени хранятся на уровне контейнера, поэтому изменение контейнера может изменить метки времени. Кроме того, TS хранит временную метку для каждого кадра (на основе тактовой частоты 90 кГц). MP4 сохраняет только длительности кадра с предполагаемым временем начала 0 (это усложняется с bframes, поскольку первый PTS равен нулю, а первый DTS равен < 0). Таким образом, чтобы получить метку времени, добавляются все длительности кадра. Mp4 также позволяет установить тактовую частоту. Это часто 1001/3000 тиков в секунду для 29,97FPS, но оно может быть установлено на что угодно. поэтому av_frame_get_best_effort_timestamp возвращает вам тики в единицах codec-> stream_base. Для кодека TS-> stream_base всегда 1/90000

3

Другие решения


По вопросам рекламы [email protected]