Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Чем разделить видеопоток? [D7, WinXP]


Страницы:   1 2 3

ABolnykh ©   (2009-10-06 15:25:00) 

Здравствуйте, уважаемые Мастера!
Кто-нибудь может подсказать направление решения следующей задачи?

Имеется сетевая видеокамера со встроенным web-сервером.
Когда к видеокамере подключается клиент, она начинает транслировать на его IP свой видеопоток.
Когда к камере подключается второй клиент, она начинает транслировать свой видеопоток (тот же самый) и на его IP тоже.
Когда к камере подключается десятый клиент, суммарное количество идентичных видеопотоков становится равно десяти.
А если таких камер в сети - десятка полтора... Затык сети очевиден.

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

Прочитав "Глубины Indy", я, по простоте душевной, в качестве искомого компонента выбрал TIdMappedPort, посчитав, что на каждое подключение он, по умолчанию, самостоятельно создаст отдельный поток (Thread), что и требуется.

Каково же было моё удивление, когда, написав пробный кусок программы и подключив через TIdMappedPort к камере трёх клиентов, а потом запросив лог видеокамеры, я обнаружил, что к камере подключены ТРИ клиента, а не один, как я ожидал. То есть, TIdMappedPort просто смаппировал обращённые к нему запросы к адресу камеры, а потоки же (Threads) если и создал для каждого подключения, то потоки обработки кода, а не видеопотоки. То есть, выбранный мною подход оказался неверным.

Полазав как следует по Интернету в поисках ответа на вопрос, как же всё-таки люди решают подобную проблему, ничего не нашёл. :-( А судя по тому, что "видеонаблюдательные" программы сейчас плодятся, как грибы, проблема должна иметь простое или несложное решение.

Может быть, кто-нибудь сталкивался с подобной задачей и может посоветовать если не готовый компонент, то хотя бы направление, в котором следует копать. Буду благодарен за любые наводящие мысли и советы.

Пишу на Delphi 7, Indy 9.


DVM   (2009-10-22 13:23:00) [1]

В коде выше /jpeg.cgi это виртуальный путь, по которому вебсервер должен понять что от него хотят картинку, а параметр channel - определяет с какой камеры картинку.


DVM   (2009-10-22 13:21:00) [2]


> ABolnykh ©

Ты научился получать отдельные кадры.
Теперь научи TIDHTTPServer отдавать эти отдельные кадры по запросу, не надо пока формировать MJPEG поток.
И все уже будет работоспособно более-менее. И смотреть тогда можно в браузере с пом например такого кода:



 
   JavaScript
   

   

     var ch=1;  
     errorimg = 0;

     function LoadImage() {
       uniq = Math.random();
       document.images.webcam1.src = " http://127.0.0.1:80/jpeg.cgi?channel=" + ch + "&uniq=" + uniq;
       document.images.webcam1.onload = DoIt;
     }

     function ErrorImage() {
       errorimg++;
       if (errorimg > 3) {
         document.images.webcam1.onload = "";
         document.images.webcam1.onerror = "";
         document.images.webcam1.src = " http://127.0.0.1:80/images/failure.gif";
       } else {
         uniq = Math.random();
       document.images.webcam1.src = " http://127.0.0.1:80/jpeg.cgi?channel=" + ch + "&uniq=" + uniq;
       }
     }
 
     function DoIt()
     {
       errorimg = 0;
       window.setTimeout("LoadImage();", 40);
     }
 
     

 
 
   
   Просмотр видео (JavaScript)
   
   
 




Получится подобие видео.


DVM   (2009-10-22 13:09:00) [3]


> ABolnykh ©   (22.10.09 11:36) [40]


> DVM, огромное Вам спасибо за полезные советы!

Не за что.


> Кстати, Вам приходилось иметь дело с компонентом TVideoGrabber

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


> Так чего делать-то, как жить дальше?

Если хочешь транслировать через UDP, да еще мультикастом, то тебе придется либо изобретать свой протокол, либо обратить свой взор на связку RTSP/RTP/RTCP.

А чтобы смотреть это дело через браузер, надо для браузера писать либо JavaApplet, либо FlashPlayer, либо QuickTime, либо ActiveX компонент (только для IE) или Silverlight компонент, который будет принимать поток в нужном формате. Сам браузер ясное дело не умеет.

Из браузеров только FireFox умеет принимать и показывать  MJPEG over HTTP без всяких дополнений.

Я тебе потому и советую безо всяких мультикастов и UDP для начала обойтись. Это проще в реализации как на сервере так и на клиенте.


Сергей М.   (2009-10-22 12:58:00) [4]

Для передачи потокового видео используются ряд сетевых протоколов, из которых важнейшими являются протокол RTSP и протокол IGMP.

RTSP (Real-Time Streaming Protocol) - это протокол, с возможностью контролируемой передачи видео-потока в интернете. Протокол обеспечивает пересылку информации в виде пакетов между сервером и клиентом. При этом получатель может одновременно воспроизводить первый пакет данных, декодировать второй и получать третий.

Протокол из этой же группы RTP (Real-time transport protocol) определяет и компенсирует потерянные пакеты, обеспечивает безопасность передачи контента и распознавание информации. Вместе с RTP работает протокол RTCP (Real-Time Control Protocol). Он отвечает за проверку идентичности отправленных и полученных пакетов, идентифицирует отправителя и контролирует загруженность сети.

Для присоединения к сети или выхода из группы рассылки используется стандартный протокол IGMP (Internet Group Membership Protocol).


Сергей М.   (2009-10-22 12:49:00) [5]

Для этого каст-сервер и каст-клиент должны взаимодействовать по единому известному обоим прикладному потоковому протоколу.
А что у тебя за протокол используется  - ты и сам поди не знаешь)


ABolnykh   (2009-10-22 12:44:00) [6]


> Сергей М. ©   (22.10.09 11:52) [41]
>
> Браузер понятия не имеет что делать с поступающими оттуда данными, ибо udp не является протоколом прикладногго уровня.

Похоже, что так. :-(

Так чего делать-то, как жить дальше? Есть какой-нибудь способ отобразить смультикасченные данные?


Сергей М.   (2009-10-22 11:52:00) [7]


> ввожу
> udp://224.0.0.1:10500
> получаю "The page cannot be displayed".


Браузер понятия не имеет что делать с поступающими оттуда данными, ибо udp не является протоколом прикладногго уровня.

VideoGrabber тоже понятия не имеет, но пытается интерпретировать их в соответствии известнымиему прикладными потоковыми протоколами. Соответствия не обнаруживает, потому и не рисует картинку.


ABolnykh   (2009-10-22 11:36:00) [8]

DVM, огромное Вам спасибо за полезные советы!
Специалист ТАКОГО уровня в тяжкую и голодную годину без персонального бутерброда с красной икрой уж точно не останется!

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

Поэтому, прикинув мышь к носу, я для начала решил избрать следующую последовательность действий:
1. Запрашиваю от камеры 1 кадр видеопотока по HTTP;
2. Копирую его в буфер.
3. Мультикастю буфер процедурой SendBuffer MCast-сервера на групповой адрес 224.0.0.1, порт 10500.
4. Даю задержку на 100 мс.
5. Перехожу на шаг 1.

Какой-то поток от меня начинает исходить, я вижу его трафик в окошке DUMeter-а.

Теперь очередной идиотский вопрос: как мне этот поток принять и отобразить? Если в строке адреса Internet Explorer-а я ввожу
udp://224.0.0.1:10500
то неизменно получаю "The page cannot be displayed".
Если пытаюсь поймать поток ВидеоГраббером, устанавливая его свойство
IpCameraUrl на тот же групповой адрес и порт, то тоже не получаю никакой картинки.  :-(

Кстати, Вам приходилось иметь дело с компонентом TVideoGrabber (www.datastead.com)? Можете сказать про него что-нибудь хорошего или плохого?


DVM   (2009-10-21 13:12:00) [9]


> > И потом: где задавать частоту обновления? В команде
> > http:///axis-cgi/mjpg/video.cgi?nbrofframes=1&fps=7
> >   ???
>
> fps и есть частота обновления. Частоту обновления лучше
> всего задавать в пути.

Только в данном случае (nbrofframes=1) задание fps=7 бессмысленно, т.к. кадр один. Если бы nbrofframes=10, тогда при fps=5 мы получили бы все кадры за 2 секунды, а так бессмсленно. Задание в пути fps имеет смысл только для потоков видео, а не для одиночных кадров. Для одиночных надо фпс задавать на принимающей стороне, т.е. выполнять запросы к камере через нужные промежутки времени.


DVM   (2009-10-21 12:57:00) [10]


> ABolnykh ©   (21.10.09 11:05) [37]


> http:///axis-cgi/mjpg/video.cgi?nbrofframes=_____?
>
> А если каждый раз запрашивать по одному кадру (nbrofframes=1),
>  то, опять же, непонятно, зачем искать границу кадра?

Когда я все писал, параметра nbrofframes несуществовало и я им не пользуюсь.

Если брать по одному кадру то проще будет вообще так:

http:///axis-cgi/jpg/image.cgi
Камера пришлет один единственный JPEG кадр. И никакаих --myboundary !!!

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


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

Это JPEG данные. Начинаются и заканчиваются маркерами FFD8 и FFD9 соответственно.


> И потом: где задавать частоту обновления? В команде
> http:///axis-cgi/mjpg/video.cgi?nbrofframes=1&fps=7
>   ???

fps и есть частота обновления. Частоту обновления лучше всего задавать в пути.


> И опять же: если мы запрашиваем у камеры "в лоб" 7 кадров
> в секунду, получаем каждый раз по 1 кадру и тут же их мультикастим
> - зачем нам самим формировать Sleep?

Потому что возможности клиентов/сети камеры часто расходятся с желаниями/потребностями. В идеальных условиях локальной сети может и можно так как ты описал, но в условиях Интернет вряд ли.
Начнутся затыки, расхождения, в результате все начнет отставать и т.д.


> DVM, какой населённый пункт нашей необъятной планеты

(с) рядом с моим ником нажми.


ABolnykh   (2009-10-21 11:05:00) [11]

Несколько проясню подробности нашего текущего техзадания.

Пока мы не волшебники, а только учимся, и потому решили сами несколько упростить себе ситуацию. А именно:
- камеры используем ТОЛЬКО Axis 207, потому возможная чехарда с несовпадением возможностей различных камер отпадает сама собой;
- все операторы смотрят картинку в одинаковом разрешении;
- аналогично - никакого волюнтаризма со стороны клиентов в вопросе самостоятельного выбора частоты кадров изображения (что тебе дали - то и смотри; чай, не у себя дома сидишь :-)  );
- никаких дополнительных функций на ретранслятор, в целях упрощения задачи, не возлагаем;
- никакого прямого обращения операторов к видеокамерам не допускается. Если диспетчер (человек) захочет зачем-то напрямую обратиться к видеокамере (посмотреть лог, установить часы, прописать юзера etc.), для этих целей предусматриваем прямой доступ к камерам через TIdMappedPortTCP. Через них же будем посылать камере и все дополнительные команды, не связанные с трансляцией видеопотока.

Клиентскую часть (программу для операторов) тоже пишем самостоятельно, и поскольку тоже не волшебники, все основные приёмно-отображательные функции решили возложить на лицензионно-покупной компонент TVideoGrabber. (Кстати, вопрос ретрансляции потока мы тоже попробовали возложить на него. Как ни странно, но работает (!), правда ОБАЛДЕННО грузит процессор: ретрансляция подключения ОДНОГО клиента (127.0.0.1) к ОДНОЙ видеокамере, подключенной к своей же сетевой карте, занимает примерно 65-70% процессорного времени моего P4 Celeron 2400 MHz. Плюс ко всему - огромная, секунд в 15-20, задержка отображения происходящего.)

DVM,ещё раз: ОГРОМНОЕ ВАМ СПАСИБО ЗА ЦЕННЫЕ СОВЕТЫ И КОНСУЛЬТАЦИИ!!!

И очередная порция идиотских вопросов.
Как я понял, частоту обновления (frames per second) Вы рекомендуете выбирать = 7 - исходя из условия достаточности этого значения для наблюдения за происходящим. Я-то спрашивал, какой размер потока лучше задавать при подключении в команде
http:///axis-cgi/mjpg/video.cgi?nbrofframes=_____?
А если каждый раз запрашивать по одному кадру (nbrofframes=1), то, опять же, непонятно, зачем искать границу кадра? Камера и так прислала один кадр, , начинающейся с "--myboundary, Content-Type" и заканчивающегося какими-то хитрыми двоичными данными, - копируй его в буфер и мультикасть! И потом: где задавать частоту обновления? В команде
http:///axis-cgi/mjpg/video.cgi?nbrofframes=1&fps=7  ???

И опять же: если мы запрашиваем у камеры "в лоб" 7 кадров в секунду, получаем каждый раз по 1 кадру и тут же их мультикастим - зачем нам самим формировать Sleep? Сам TVideoGrabber разве не способен правильно (во времени) отобразить полученное?

Кстати, DVM, какой населённый пункт нашей необъятной планеты Вы осчастливили, избрав местом своего проживания и творения? Если ответ на этот вопрос каким-то образом нарушает правила этого форума, можно ответить мне в личном сообщении.


DVM   (2009-10-20 16:04:00) [12]

Кстати, раз уж речь зашла о функциях ретранслятора. Ретранслятор должен уметь работать в обе стороны. Т.е. не только передавать видеопоток от камер клиентам, но и передавать команды клиентов камерам (например PTZ команды ил управление выходами DIO и т.д.)


Fr0sT   (2009-10-20 15:57:00) [13]

> [32] Сергей М. ©   (20.10.09 15:42)
Ок, точку зрения понял

> [34] DVM ©   (20.10.09 15:49)
Ага, вот оно что, на ретранслятор уже накладываются дополнительные функции! Тогда действительно, придётся разбирать.


DVM   (2009-10-20 15:49:00) [14]


> Fr0sT   (20.10.09 15:10) [29]

Дело в том что скорость на участке камера - ретранслятор может быть выше чем скорость на участке ретранслятор - клиент и куда девать тогда лишние кадры. Их из потока не выкинешь просто так. А если пытаться в таких условиях отдать все что прислала камера то получится отставание изображения которое все более будет нарастать и занимать память (куда кадры то девать).

Кроме этого отдельные клиенты могут захотеть принимать с меньшей частотой кадров изображение или другого размера и т.д. тут вариантов масса поэтому лучше ретранслировать собирая поток самому.

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


DVM   (2009-10-20 15:44:00) [15]


> ABolnykh ©   (19.10.09 14:06) [28]


> Какое количество кадров можно считать оптимальным при приёме
> потока

Я считаю оптимальной 7 кадров в секунду. Это же все таки наблюдение за ситуацией а не кинофильм. Есть конечно маньяки которые с пеной у рта доказывают что надо 25, но сами не могут отличить 15 от 25 когда им показываешь.


> а с другой стороны - не слишком раздувать буфер потока

А у меня лично буфер всего на один кадр. Один буфер в один кадр на одну камеру. Камера обновляет буфер, клиенты получают обновления буфера.


> и чем (как) формировать задержку между отправкой кадров?

Формировать то ее можно банальным Sleep() но с расчетом ее мне пришлось повозиться.


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

Еще раз повторю, не надо копить кадры. Достаточно всегда иметь один кадр последний, его и шлем клиентам.


> и потом - куда воткнуть процедуру нахождения "--myboundary"
> в
> try http.get (url, stream);

С пом TIdHTTP можно получить только отдельный кадр (камеры аксис кстати могут отдавать и покадрово а не потоком). Отдельными кадрами тоже выход, правда несколько более грузит ПК и камеру. Для принятия потока лучше брать TidTCPClient (или как он там называется). Я вообще на чистых сокетах делал без обертки (пример разбора потока есть в коде ZoneMinder в файле remote_camera.c ).


Сергей М.   (2009-10-20 15:42:00) [16]

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


Fr0sT   (2009-10-20 15:36:00) [17]

Почему?


Сергей М.   (2009-10-20 15:28:00) [18]


> разве нельзя просто его ретранслировать всем подключившимся
> клиентам?
>


Ретрансляция по TCP может быть неприемлемой


Fr0sT   (2009-10-20 15:10:00) [19]

Очень интересная тема, особенно в предчувствии того, что мне тоже предстоит делать нечто подобное. Возник вопрос: зачем влезать внутрь потока, разве нельзя просто его ретранслировать всем подключившимся клиентам?


ABolnykh   (2009-10-19 14:06:00) [20]


> DVM ©   (08.10.09 17:03) [16]
>
> Задача не так проста, как кажется. Просто тупо ретранслировать поток не выйдет, поток нужно принять, выделить кадры, затем собрать аналог потока. который транслировать клиенту.
>
> Работа ретранслятора грубо говоря выглядит следующим образом.
>
> 1) Ретранслятор подключается к камере по HTTP и начинает принимать видеопоток.
> 2) Выделяет очередной кадр (как разделены кадры в потоке см на сайте аксис HTTP API)
> 3) После того как кадр выделен, мы его откладываем в некий буфер, затирая предыдущий.
> 4) Продолжаем принимать входящий поток, обновляя наш буфер.
> 5) Тут к ретранслятору подключается очередной клиент.
> 6) Выдаем клиенту заголовок в соответствии с Axis HTTP API
> 7) Начинаем высылать клиенту кадры, отделяя их друг от друга разделителями. Кадры берем из буфера. Между кадрами делаем паузы чтобы поддерживать нужную частоту кадров, которую например клиент может передать нам в запросе. Кадровый буфер причем должен быть потокобезопасный.
> 8) Аналогично для второго третьего нн-ого клиентов.
> 9) Кроме этого следует наверное отключаться от камеры если клиентов нет.
>
> В двух словах не расскажешь, т.к. каждый шаг здесь отдельная длинная история.

[b]DVM[/b], ОГРОМНОЕ СПАСИБО ЗА ТАКОЙ ДЕТАЛЬНО ПРОРАБОТАННЫЙ "БИЗНЕС-ПЛАН"!

И ещё парочка вопросов.
Какое количество кадров можно считать оптимальным при приёме потока (чтобы, с одной стороны, не было эффекта "дёрганья" от частого переподключения к камере, а с другой стороны - не слишком раздувать буфер потока), и чем (как) формировать задержку между отправкой кадров?

В идеале, конечно, было бы задать количество кадров = 0 (unlimited), тогда бы и все вопросы отпали. Как только получил и выделил очередной кадр - сразу смультикастил его во вторичную сеть, и не надо формировать никаких задержек. Но сразу встаёт вопрос переполнения потока при круглосуточном видеонаблюдении, и потом - куда воткнуть процедуру нахождения "--myboundary" в
try http.get (url, stream);
finally http.free;
end;


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо