Pts dts что это
Перейти к содержимому

Pts dts что это

  • автор:

Расчет pts dts и duration FFmpeg и C++

есть вектор, который содержит кадры и временные метки, соответствующие кадру:

std::vector> rawData; 

Кадры это просто QImage . Временные метки получаются так:

const int64_t timestamp = QDateTime::currentMSecsSinceEpoch(); 

Настройка контекста:

pCodecCxt->time_base = AVRational; pCodecCxt->framerate = AVRational; 

как правильно вычислить с учетом временных меток кадра?:

pkt.pts = ?; pkt.dts = ?; pkt.duration = m_currentFrameTimestamp - m_previousFrameTimestamp; 

UPD: Итак, зная метки кадров, я могу вычислять продолжительность кадра и начало каждого кадра.

int64_t frameTime; int64_t frameDuration; int count = m_frameCounter++; frameDuration = m_currentFrameTimestamp - m_previousFrameTimestamp; frameTime = count * frameDuration; pkt.pts = frameTime; pkt.dts = pkt.pts; pkt.duration = frameDuration; 

Остался вопрос по поводу настройки контекста tame_base. Так как временные метки в миллисекундах, то видимо должно быть так:

pCodecCxt->time_base = AVRational; 

UPD: Это по прежнему не работает.

int64_t frameTime; int64_t frameDuration; int count = m_frameCounter; frameDuration = (m_currentFrameTimestamp - m_previousFrameTimestamp) / (1000 / 60); frameTime = count * frameDuration; pkt.pts = frameTime; pkt.dts = pkt.pts; pkt.duration = frameDuration; 

Ой, у меня задержка. Часть 2

В предыдущей статье мы говорили о сокращении задержки в трансляции видео. С отправкой разобрались, теперь поговорим о доставке.

У клиента есть места, где видео может накапливаться и отставать от реального времени:

  • входной сетевой буфер;
  • внутренний синхронизационный буфер транспорта;
  • протокольный буфер компенсации колебания скорости сети;
  • буфер плеера;
  • буфер декодера (видеокарты);
  • аппаратные задержки.

(ламповый буфер)

Входной сетевой буфер

Клиент получает данные через сетевой сокет. IP сокеты имеют буферы, которые могут заполняться при недостаточно быстром получении данных пользовательской программы.

Если буфер слишком мал, то видеотрансляция будет постоянно прерываться, а если слишком большим, то пользователь будет должен ждать наполнения буфера дольше необходимого времени, определяемого скоростью передачи данных. В худшем случае, если буфер будет под мегабайт, то в него может набиться до 4-8 секунд видео.

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

С точки зрения близости к риалтайму большой сетевой буфер — зло. С точки зрения плавности проигрывания телеканала — вполне себе разумная вещь, потому что ядро работает достаточно быстро и хорошо, чтобы успевать наполнять свои буферы.

Посмотреть на состояние буфера на клиенте сложно, потому что если бы там был Linux, можно было бы запустить утилиту ss. Но выяснить эту информацию на Android или Windows сложнее.

Внутренний синхронизационный буфер демуксера

В различных протоколах любят по разному растащить в сторону аудио и видео. Например, в MPEG-TS принято взять подряд по 3-5 аудиокадров и положить их в один пакет, чтобы сократить трафик. При этом поток кадров из «VAVAAVAVAA» превращается в «VVAAAAAVVAAAAVAAAVVVAAA».

Таймстемпы при этом перемешиваются и, если вам дальше хочется их иметь отсортированными (например, для отдачи в RTMP это критично), то надо заводить буфер, который будет притормаживать кадры. Особенно чудесное поведение у такого буфера возникает, когда аудио пропадает полностью или на одном канале из пяти.

Отличить полное пропадание от очень большой задержки в общем случае практически невозможно. Поэтому в процессе разработки приходится писать код, который должен «чувствовать», что же там произошло.

Буфер компенсации скорости сети

Здесь речь пойдет о том буфере, который мы имеем в HLS, или о том буфере, которым управляли в RTMP плеере.

Например, HLS плеер устроен так:

  • плеер скачивает три сегмента;
  • скачав третий, плеер начинает проигрывать поток, начиная с первого;
  • один процесс независимо забирает самый старый сегмент, а другой подкачивает первый.

Буфер для компенсации колебания скорости сети заложен в любом плеере. Например, у RTMP этот буфер, теоретически, 0, у HLS он, теоретически, скажем 10 секунд, у RTSP плееров он как правило реально 0, а в SIP он точно 0.

Мы говорим «теоретически», потому что на граничных параметрах ничего не будет работать. Например, HLS плееры на 1-секундных фрагментах могут начать работать крайне нестабильно. Причем это может быть из-за банальных ошибок типа учета длительности сегмента в секундах, а не миллисекундах.

А RTMP флеш плеер на нулевом буфере себя ведет просто «восхитительно» — он начинает накапливать задержку по одной секунде за минуту и через пару часов может умереть в страшных мучениях.

Буфер плеера

Механизм проигрывания почти всегда отделен от механизма, скачивающего видео по какому-либо протоколу. Кадры распаковываются, отделяются от метаданных и передаются в плеер. Дальше начинается «странное»: Flash и MSE плеер могут потребовать больше одного кадра для старта проигрывания.

Если это происходит, то у вас опять начинается отставание и задержка. Здесь цифры бывают порядка 2–5 кадров, т.е. до 200 мс.

Буфер декодера

Хороший риалтайм декодер сразу будет декодировать полученный поток и отдавать его. Блоки доступа поступают в буфер непрерывно, причем скорость заполнения буфера пропорциональна скорости кодированного потока. Блоки доступа загружаются в буфер за разное время, поскольку кодированные изображения имеют разный объем данных. Выгружаются данные из буфера через одинаковые интервалы, равные частоте кадров воспроизводимого изображения, причем выгружаются целиком и моментально. Если, например, стартовая задержка нового потока значительно больше финишной задержки старого, то после того, как будет воспроизведено и выгружено из буфера последнее изображение старого потока, придется долго ждать декодирования и воспроизведения первого изображения нового потока. Это приведет, например, к замораживанию последнего изображения старого потока и заметной склейке. Если скорость нового потока значительно больше скорости старого, то склейка будет еще более заметной, поскольку при этом буфер переполняется и часть данных теряется.

Если же вы на кодировании риалтайм потока включили b-frames, что само по себе чудесная затея, то немедленно на выходе получаете задержку в размере N*T, где:

  • N — максимальное расстояние перестановки кадров, обычно около 4
  • T — длительность кадра. Для 25 fps — это 40 мс.

В реальности декодер может ещё притормозить кадр-другой или просто не иметь хорошего событийного API для своевременного оповещения о готовности кадра.

Аппаратные задержки на последнем метре доставки видео

Огромный декодированный кадр надо показать. Если вы декодировали не на видеокарте, а на процессоре, то его надо скопировать в видеопамять для показа, а это занимает время. Видеокарты также могут добавлять миллисекунды, но обычно здесь уже все не так страшно по сравнению с тысячами миллисекунд в предыдущих случаях.

Итого

Разобравшись со всеми видами задержки в доставке и получении видео, можно начать измерять ее. В следующей статье мы расскажем, как это можно сделать.

Как проверить корректность PTS в транспортном потоке?

PTS (временная метка воспроизведения) — это число, указывающее время, когда необходимо воспроизвести единицу элементарного потока (видеокадр, аудио, DVB субтитры). Это один из важнейших показателей, по которому можно судить, будет ли видео проигрываться корректно. Согласно стандарту ETSI TR 101 290 период повторения PTS не должен превышать 700 мс, иначе фиксируется ошибка второго приоритета — PTS Error.

Stream Analyzer позволяет легко проверить поток на соответствие данному стандарту. Наличие подобных ошибок можно увидеть на панели TR101-290.

Stream Analyzer

Дельты значений PTS представлены на панели Time Dynamics. В выпадающих списках необходимо выбрать PTS Only, интересующий PID и график PTS/DTS Dynamics.

Time Dynamics

Чтобы визуально оценить возрастание значений PTS, в Stream Analyzer можно построить график для любого целочисленного параметра. На панели Explorer поставьте флажок напротив желаемого PES, а затем на панели Property щелкните значение PES и выберите Add to graphic control. В окне Graphics появится график.

Explorer

К заголовку, отображаемому в главном окне, вы можете добавить любой параметр (например, значение PTS). Это позволит в дальнейшем легко находить необходимые PES.
Для этого на панели Property щелкните желаемый параметр и выберите Show in header title.

Property

Stream Analyzer — приложение для анализа синтаксиса медиапотока: проверка структуры, а также выявление и анализ ошибок в составе контейнера и транспортных потоков (transport stream).

Монотонный DTS

Не могу разобраться с monotonous DTS в h264. Ffmpeg ругается, что DTS увеличивается не монотонно. Также сыпятся сообщения из libx264: non-strictly-monotonic.

ffmpeg -y -loglevel repeat+info -i bad_7s.mp4 -vsync 0 out.mp4 Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'bad_7s.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.12.100 Duration: 00:01:04.33, start: 0.000000, bitrate: 1656 kb/s Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 480x270, 1654 kb/s, 24.42 fps, 16k tbr, 16k tbn, 32k tbc (default) Metadata: handler_name : VideoHandler Stream mapping: Stream #0:0 -> #0:0 (h264 (native) -> h264 (libx264)) Press [q] to stop, [?] for help [libx264 @ 0x6473e80] using cpu capabilities: MMX2 SSE2Fast LZCNT SSSE3 SSE4.2 AVX [libx264 @ 0x6473e80] profile High, level 2.1 [libx264 @ 0x6473e80] 264 - core 155 r2901 7d0ff22 - H.264/MPEG-4 AVC codec - Copyleft 2003-2018 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=1 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=24 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00 Output #0, mp4, to 'out.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.12.100 Stream #0:0(und): Video: h264 (libx264) (avc1 / 0x31637661), yuv420p, 480x270, q=-1--1, 24.42 fps, 1571k tbn, 24.42 tbc (default) Metadata: handler_name : VideoHandler encoder : Lavc58.18.100 libx264 Side data: cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1 [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 0, current: 0; changing to 1. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 192993, current: 192993; changing to 192994. This may result in incorrect timestamps in the output file. [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 321655, current: 321655; changing to 321656. This may result in incorrect timestamps in the output file. [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 771972, current: 771972; changing to 771973. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 900634, current: 900634; changing to 900635. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 1029296, current: 1029296; changing to 1029297. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 1157958, current: 1157958; changing to 1157959. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 1415282, current: 1415282; changing to 1415283. This may result in incorrect timestamps in the output file. [libx264 @ 0x6473e80] non-strictly-monotonic PTS [libx264 @ 0x6473e80] non-strictly-monotonic PTS [mp4 @ 0x6475540] Non-monotonous DTS in output stream 0:0; previous: 1801268, current: 1801268; changing to 1801269. This may result in incorrect timestamps in the output file. 
 if( h->param.b_vfr_input && fenc->i_pts frames.i_largest_pts ) x264_log( h, X264_LOG_WARNING, "non-strictly-monotonic PTS\n" ); 

из чего следует(по моей логике), что если текущий PTS меньше или равен предыдущему (точнее самому большому значению всех предыдущих PTS?), то выводится предупреждение

Распарсил свой видеоролик

ffprobe -show_frames -select_streams v:0 bad_7s.mp4 

И не увидел там плохих DTS\PTS(они всегда равны в моем случае). Я даже написал простой скрипт, который бы находил эти «плохие» DTS

Выгрузил в json информацию о всех фреймах

 ffprobe -show_frames -select_streams v:0 -print_format json bad_7s.mp4 > frames.json 
const fs = require("fs"); var data = JSON.parse(fs.readFileSync("frames.json").toString()); var largest_dst; for(var item of data.frames) < var dts = item.pkt_dts; var pts = item.pkt_pts; if(dts !== pts) < console.error("error", item); process.exit(); >if(largest_dst && dts if(!largest_dst || dts > largest_dst) < largest_dst = dts; >> 

. и скрипт не нашел ничего, вывод пустой. Все DTS увеличиваются!

Что я делаю\понимаю не так?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *