как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 13.12.22 04:15
Оценка:
я сделал код который прнимает несколько потоков и делает из них multi view
в данном случаи показана часть лога для 4 потоков с камер в разных частях здания (потоки можно отличить по цифрам [505])

2022-12-13 02:43:27.986  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:28.768  info   [505] ---  : Channel 0 is receiving video at 59.149395ffps.
2022-12-13 02:43:31.415  info   [457] ---  : Channel 0 is receiving video at 33.086918ffps.
2022-12-13 02:43:32.014  info   [452] ---  : Channel 0 is receiving video at 30.078526ffps.
2022-12-13 02:43:32.120  info   [505] ---  : Channel 0 is receiving video at 59.667934ffps.
2022-12-13 02:43:32.990  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:33.056  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:35.471  info   [505] ---  : Channel 0 is receiving video at 59.68681ffps.
2022-12-13 02:43:37.534  info   [457] ---  : Channel 0 is receiving video at 32.685978ffps.
2022-12-13 02:43:38.187  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:38.249  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:38.714  info   [452] ---  : Channel 0 is receiving video at 29.849714ffps.
2022-12-13 02:43:38.826  info   [505] ---  : Channel 0 is receiving video at 59.61486ffps.
2022-12-13 02:43:42.185  info   [505] ---  : Channel 0 is receiving video at 59.53062ffps.
2022-12-13 02:43:43.186  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:43.458  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:43.694  info   [457] ---  : Channel 0 is receiving video at 32.466408ffps.
2022-12-13 02:43:45.414  info   [452] ---  : Channel 0 is receiving video at 29.8547ffps.
2022-12-13 02:43:45.533  info   [505] ---  : Channel 0 is receiving video at 59.7366ffps.
2022-12-13 02:43:48.386  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:48.454  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:48.940  info   [505] ---  : Channel 0 is receiving video at 58.70607ffps.
2022-12-13 02:43:49.597  info   [457] ---  : Channel 0 is receiving video at 33.882202ffps.
2022-12-13 02:43:52.125  info   [452] ---  : Channel 0 is receiving video at 29.79798ffps.
2022-12-13 02:43:52.239  info   [505] ---  : Channel 0 is receiving video at 60.625294ffps.
2022-12-13 02:43:53.448  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:53.583  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:55.455  info   [457] ---  : Channel 0 is receiving video at 34.141876ffps.
2022-12-13 02:43:55.593  info   [505] ---  : Channel 0 is receiving video at 59.634636ffps.
2022-12-13 02:43:58.454  info   [466] ---  : Receiver connection status changed.
2022-12-13 02:43:58.786  info   [505] ---  : Receiver connection status changed.
2022-12-13 02:43:58.813  info   [452] ---  : Channel 0 is receiving video at 29.904644ffps.
2022-12-13 02:43:58.951  info   [505] ---  : Channel 0 is receiving video at 59.55274ffps.



из за разной загруженности сети, разного разрешения камер и загруженности CPU fps меняеться
подскажите пожалуйста как можно синхронизировать вывод потоков в multiview

моя начальная идея была запомнить time stamp первого принятого кадра с каждой камеры, использовать его как base time и синхронизировать по ним кадры выводимы на экран
с другой стороны разница небольшая в среднем 0.2 и возможно ее можно проигнорировать
Re: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 13.12.22 10:25
Оценка: 15 (1) +3
Здравствуйте, sergey2b, Вы писали:

S>из за разной загруженности сети, разного разрешения камер и загруженности CPU fps меняеться

S>подскажите пожалуйста как можно синхронизировать вывод потоков в multiview

В общем случае нет никакого FPS. Кадры могут пропадать, FPS меняться и т.д. Это очень ненадёжная характеристика в сети. Опираться нужно на времена семплов и только на них. У каждого канала должен быть таймер (Clock). Принимаешь и декодируешь каждый канал по отдельности и рендеришь кадры по таймеру в multiview back buffer. Back buffer уже по своему таймеру (например 50 Hz) должен выводит все слепленные кадры, независимо ни от чего, на экран.
Или я не понял проблему
Re[2]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 18.12.22 18:48
Оценка: -1
Здравствуйте, Videoman, Вы писали:

V>В общем случае нет никакого FPS. Кадры могут пропадать, FPS меняться и т.д. Это очень ненадёжная характеристика в сети. Опираться нужно на времена семплов и только на них. У каждого канала должен быть таймер (Clock). Принимаешь и декодируешь каждый канал по отдельности и рендеришь кадры по таймеру в multiview back buffer. Back buffer уже по своему таймеру (например 50 Hz) должен выводит все слепленные кадры, независимо ни от чего, на экран.

V>Или я не понял проблему


скажите пожалуйста где можно об этом можно почитать, тк
у меня часть потоков 60 fps часть 30 fps

я попробовал у потоков с 60fps использовать только каждый второй кадр в результате движения с этих потков рванные и звук не нормальный
Re[3]: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 18.12.22 19:20
Оценка: 12 (1) +2
Здравствуйте, sergey2b, Вы писали:

S>скажите пожалуйста где можно об этом можно почитать, тк

S>у меня часть потоков 60 fps часть 30 fps

Вот где можно почитать я к сожалению не знаю.

S>я попробовал у потоков с 60fps использовать только каждый второй кадр в результате движения с этих потков рванные и звук не нормальный


Давай поэтапно: сделай плеер который проигрывает ровно один сетевой поток, плавно, на экран. Не нужно ни в коем случае ничего выкидывать. Есть таймер, есть время кадра. Как только время >= времени кадра, показываем его. Важно!: считывание, декодирование кадра, его подготовка, должны происходит строго до времени показа. Время показа — только swap кадра на экран. Плавный рендеринг очень сильно зависит от таймингов, так что нужно стараться выдерживать строгую синхронизацию. После того как у тебя получится плеер, который плавно рендерит один стрим, можно переходить к следующей стадии.

Как только будет котов плеер единственного стрима, делаешь несколько плееров, которые работают параллельно, но не на экран, а в back buffer.
Re[4]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 18.12.22 19:30
Оценка:
Спасибо за ответ

Плеер работает хорошо,
версия которая сохраняет в back buffer несколько потоков, каждый потоков в свой буфер
работает нормально

Те первый шаг выполнен
Отредактировано 18.12.2022 19:31 sergey2b . Предыдущая версия .
Re[5]: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 18.12.22 19:41
Оценка: 9 (1)
Здравствуйте, sergey2b, Вы писали:

S>Те первый шаг выполнен


Теперь каждый плеер должен рендерить свои поток в один backbuffer, каждый со своей частотой. Backbuffer должен независимо, рендерить на экран со своей частотой (например 60Hz), независимо. Т.е. multiview, пусть представляет из себя отдельный плеер. Если всё правильно сделать, то рывков никаких не будет. У меня была точно такая же задача, правда на Qt, но в данном контексте это не важно.
Re[6]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 18.12.22 20:33
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Теперь каждый плеер должен рендерить свои поток в один backbuffer, каждый со своей частотой. Backbuffer должен независимо, рендерить на экран со своей частотой (например 60Hz), независимо. Т.е. multiview, пусть представляет из себя отдельный плеер. Если всё правильно сделать, то рывков никаких не будет. У меня была точно такая же задача, правда на Qt, но в данном контексте это не важно.


как я понял у меня будет функция которая будет вызываться 60 раз в секунду
считывать очередной фрейм из backbuffer
по его номеру определять в какую позицию экрана его выводить


но если у меня два потока 30 fps и 60fps то в буфере каждую секунду будет 90 фреймов
как мне определить сколько входящих фремов должно участовать в генерации выходящего фрейма 1 или 2

так же возможна ситуация когда в backbuffer будет подряд несколько фреймов из одного входящего потока
Re[4]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 19.12.22 01:17
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Вот где можно почитать я к сожалению не знаю.


я нашел вот такое описание https://habr.com/ru/company/edison/blog/500402/#threads
оригинал на английском гуглиться
Re[7]: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 19.12.22 09:31
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>как я понял у меня будет функция которая будет вызываться 60 раз в секунду

S>считывать очередной фрейм из backbuffer
S>по его номеру определять в какую позицию экрана его выводить

Я запутался и мне казалось, что мы говорим про multiview. Чего-то не договариваешь. Опиши задачу полнее. Я думал что каждый плеер будет рисовать себя в нужную ему область backbuffer-а, а он, в свою очередь, будет рисоваться целиком на весь экран.

S>но если у меня два потока 30 fps и 60fps то в буфере каждую секунду будет 90 фреймов

S>как мне определить сколько входящих фремов должно участовать в генерации выходящего фрейма 1 или 2

S>так же возможна ситуация когда в backbuffer будет подряд несколько фреймов из одного входящего потока


Второй вариант, если тебе не нужен единый backbuffer сразу для всех плееров, и не нужно его никуда пересылать, тогда пусть каждый отдельный плеер рисует себя сразу в свой control, widget и т.д.
Re: как синхронизировать несколько видеостримов
От: paradok  
Дата: 19.12.22 12:06
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>я сделал код который прнимает несколько потоков и делает из них multi view


1) либо сделай все окна мульти-вью незаввисимыми процессами и пусть операционка сама все делает и от тебя не требуется ничего синхрить

2) либо тебе придется научиться интерполировать и экстраполировать изображения потоков
умея это ты просто делаешь общий процесс который выводит в некоторые моменты времени все нужные кадры
и в случае если они еще не поступили или поступили до момента вывода или дропнулись
делается интерполяция или экстраполяция по всем потокам до нужного общего момента вывода.
если дисер пишешь — то тут можно нейронки заюзать и получить зачетный дисер.
Re[2]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 19.12.22 12:40
Оценка:
У меня сделан вариант 2
И вариант 1 мне не подходит тк конечная цель отпаслась полученный образ multiview по сети
Re[3]: как синхронизировать несколько видеостримов
От: paradok  
Дата: 19.12.22 12:45
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>У меня сделан вариант 2

S>И вариант 1 мне не подходит тк конечная цель отпаслась полученный образ multiview по сети

если задача только отсылать то в теории можно 1) захватывать область экрана с потоками... ну это как бы студенчески вариант,
трушныйй — экстраполяция — интерполяция
Re[8]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 21.12.22 01:02
Оценка:
Здравствуйте, Videoman, Вы писали:

на камере стоит настройка 30fps
я сделал тестовое приложение

получаю видофреймы из сети, используя NDI API проверяю стрим 30fps
сохраняю каждый фрейм в очередь

функция вызываемая каждые несколько миллисекунд long interval = trunc((double)1000/fps);
выводит фрейм на экран

бефер видеофреймов быстро переполняеться



я добавил код который считывает frame_rate у видеопотока

// What is the frame rate of this frame.
// For instance NTSC is 30000,1001 = 30000/1001 = 29.97 fps.
int frame_rate_N, frame_rate_D;

и пересчитываю интервал, это не помогло, очередь медленней но переполняеться


если интервал между вызовами сделать короче long interval = trunc((double)1000/fps-4);
очередь сохраняет неусточивое равновесие, но все равно в течении 1-2 часа используюет всю доступную память



как вы считаете, что правильно делать если камера посылает чуть больше кадров чем должно быть
Re[9]: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 21.12.22 11:27
Оценка: 3 (1)
Здравствуйте, sergey2b, Вы писали:

S>функция вызываемая каждые несколько миллисекунд long interval = trunc((double)1000/fps);


Вот тут по ходу собака порылась. Нельзя надеяться на то, что функция будет точно вызываться синхронно с частотой потока. У камеры свои часы CamClock и эти часы никогда не будут совпадать с твоими PClock.
Соотношение грубо будет таким: CamClock = PClock * k, где k обычно чуть меньше или чуть больше единицы. Попробуй статистически считать k и подводить свои часы, что бы корректировать ошибку.
По остальному описанию все вроде так, как и должно быть. У меня бывало что часы источника отставали, и у меня начинался голод по кадрам. У каждого сетевого источника свои часы и это логично.
Re[10]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 21.12.22 13:36
Оценка:
Скажите пожалуйста где вы про это узнали
Может есть какие то книги или форумы
Re[11]: как синхронизировать несколько видеостримов
От: paradok  
Дата: 21.12.22 14:32
Оценка: 9 (1)
Здравствуйте, sergey2b, Вы писали:

S>Скажите пожалуйста где вы про это узнали

S>Может есть какие то книги или форумы

эта задача была хорошо изучена в аналогово-цифровых модемах лет 20 назад.
одно из решений — для каждого потока создается свои виртуальные часы идущие снхронно с часами потока
и динамически через цифровую ФАПЧ подстраивающие свою виртуальную скорость хода под скорость потока.

Тогда все буферы примерно постояненны по объему. И в них всегда будут данные.
Глвные часы управлют забором данных из всех буферов и их объединением.

При сильной разнице в скорости потоков — в объединенной картинке будет видно, что где-то изображение идет быстрее а где-то замедленно
но это не мешает объединению в единю картинку.
Отредактировано 21.12.2022 14:37 paradok . Предыдущая версия . Еще …
Отредактировано 21.12.2022 14:35 paradok . Предыдущая версия .
Re[12]: как синхронизировать несколько видеостримов
От: sergey2b ЮАР  
Дата: 21.12.22 14:53
Оценка:
Здравствуйте, paradok, Вы писали:

P>При сильной разнице в скорости потоков — в объединенной картинке будет видно, что где-то изображение идет быстрее а где-то замедленно

P>но это не мешает объединению в единю картинку.

большое спасибо я сейчас погуглю


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

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

// Using a frame-sync we can always get data which is the magic and it will adapt
// to the frame-rate that it is being called with.
NDIlib_video_frame_v2_t video_frame;
NDIlib_framesync_capture_video(pNDI_framesync, &video_frame);

// Display video here. The reason that the frame-sync does not return a frame until it has
// received the frame (e.g. it could return a black 1920x1080 image p) is that you are likely to
// want to default to some video standard (NTSC or PAL) and there would be no way to know what
// your default image should be from an API level.
if (video_frame.p_data) {
// You display the video frame.
}





скажите пожалуйста, а есть ли книги которые стоит почтить по кодекам и обработки видео
Re[11]: как синхронизировать несколько видеостримов
От: Videoman Россия https://hts.tv/
Дата: 21.12.22 17:28
Оценка: 8 (2)
Здравствуйте, sergey2b, Вы писали:

S>Скажите пожалуйста где вы про это узнали

Просто уже 20 лет в мультимедиа как-никак. Частичная подсказка вам есть в DirectShow. У фильтров рендереров и источников есть персональные таймеры — именно по этому. Также, по умолчанию, часы есть у самого графа. До начала работы, граф запрашивает мастер часы, по которым будет работать. Если их нет, то использует свои. У аудио-рендерера всегда есть часы, так как у аудио-платы всегда свой генератор. Если поставите два произвольных компьютера и начнёте играть фильм синхронно, то закончится он играть с разницей несколько секунд на одном и другом. Это именно по тому, что у каждого компьютера часы идут немного по разному.
Какой-нибудь сетевой "Push Demultiplexer" фильтр, тоже всегда имеет часы, именно по этому. Он подсчитывает скорость приходящего потока и подводит часы как на источнике. Граф автоматически использует его часы для рендеринга. Получается что на источнике и приёмнике время часов течёт строго синхронно.

В случае с сетью, источник выдает кадры строго синхронно по своим часам, но относительно ваших часов на приёмнике время будет идти чуть быстрее или чуть медленнее. Ошибка, на самом деле большая, что бы ею можно было пренебречь. Мы как-то считали и получалось уже в 4-м знаке после запятой. Если источник асинхронный (мы можем регулировать его скорость, например файл), то проблемы не возникает, так как мы гарантировано заполняем буфер быстрее хода часов. На синхронном источнике (Live, Сеть) на приёме всегда будет либо перебор, либо недобор.

S>Может есть какие то книги или форумы

Вот к сожалению что-то по книгам подсказать не могу.
Отредактировано 21.12.2022 17:38 Videoman . Предыдущая версия . Еще …
Отредактировано 21.12.2022 17:37 Videoman . Предыдущая версия .
Re[13]: как синхронизировать несколько видеостримов
От: paradok  
Дата: 22.12.22 09:24
Оценка: 9 (1)
Здравствуйте, sergey2b, Вы писали:


S>скажите пожалуйста, а есть ли книги которые стоит почтить по кодекам и обработки видео


вроде в оф. стандарте мпег расписано про устройство кодеков типа мпег — это нехилая наука
про другие типы надо искать журналах типа IEEE

но обычно такие глубины рядовому прогеру не нужны
Re[12]: как синхронизировать несколько видеостримов
От: paradok  
Дата: 22.12.22 09:30
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Здравствуйте, sergey2b, Вы писали:


>> синхронном источнике (Live, Сеть) на приёме всегда будет либо перебор, либо недобор.


вроде вот так не будет...
пусть eсть буфера длинной N1..NK
при поступлении очередного кадра из NX потока он добавляется в нужный буфер, а самый кадр старый удаляется из буфера...
а главный объединитель по своим тактам просматривает все буфера и обирает картинку в главный буфер.
Отредактировано 22.12.2022 9:33 paradok . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.