Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Сети";
Текущий архив: 2006.05.21;
Скачать: [xml.tar.bz2];

Вниз

Организация непрерывной передачи файлов по сети для видеочата   Найти похожие ветки 

 
Setor   (2005-10-26 01:42) [0]

Пишу нечто вроде видеочата. Т.к. по сети нельзя передать видеопоток (по крайней мере информации по данной теме я не нашёл), передаю сжатые картинки (jpeg). На данный момент ситуация такова, что по таймеру я делаю запрос к серверу, а он мне отправляет картинку. При кол-ве запросов > 10 в секунду, иногда приложение зависает. Хотелось бы, если можно, не слать каждый раз запрос на получение картинки, а высылать их потоком друг за дружкой или быть может есть вариант лучше?

Видеозахват реализован при помощи DSPack


 
Digitman ©   (2005-10-26 08:35) [1]


> по сети нельзя передать видеопоток


можно.

и видеопоток, и слышиопоток, и вообще любой поток любого рода информации


 
Setor   (2005-10-26 09:35) [2]

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


 
Digitman ©   (2005-10-26 10:03) [3]


> Setor   (26.10.05 09:35) [2]


> твой пост бессмысленный


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


 
DVM ©   (2005-10-26 10:24) [4]


> Т.к. по сети нельзя передать видеопоток (по крайней мере
> информации по данной теме я не нашёл)

Очень просто через HTTP. В MotionJPEG формате. jpeg - разделитель - jpeg - разделитель


 
Eraser ©   (2005-10-26 17:17) [5]


> Setor   (26.10.05 01:42)

Есть специальные потоковые видеоформаты.
Передавай через UDP или TCP.


 
Arazel/NikNet   (2005-10-26 19:00) [6]

Передовай с помощью TMemoryStreem и TSocket
и оптимально и поточно!


 
Setor   (2005-10-26 21:18) [7]

Описываю более подробно:

Имеется 2 приложения: Клиент и Сервер.

1) Сервер IdTCPServer
* При подключении клиента включается видеозахват (DSPack)

 FilterGraph.ClearGraph;
 FilterGraph.Active := false;
 Filter.BaseFilter.Moniker := SysDev.GetMoniker( DefaultVideoDevice ); // DefaultVideoDevice = номер выбранного девайса

 FilterGraph.Active := true;

 with FilterGraph as ICaptureGraphBuilder2 do
   RenderStream(@PIN_CATEGORY_CAPTURE, nil, Filter as IBaseFilter, nil, SampleGrabber as IBaseFilter );

 FilterGraph.Play;

* Сервер ждёт команд клиента
* При получении команды от клиента, сервер берёт 1 кадр (bmp) конвертирует его в jpg опред. качества и отправляет клиенту

procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
 stream: TStream;
 get : string; // команда клиента
 jpg: TJpegImage;
 bmp: TBitmap;
begin
 get:= AThread.Connection.Readln;

 if FilterGraph.Active = true then
   begin
     if get = "go" then
     begin
       stream:= TMemoryStream.Create;
       try
         stream.Position:= 0;

         jpg:= TJpegImage.Create;
         try
           jpg.ProgressiveEncoding:= False;
           jpg.CompressionQuality:= VideoQuality;

           bmp:= TBitmap.Create;
           try
             SampleGrabber.GetBitmap( bmp );
             jpg.Assign( bmp );
           finally
             bmp.Free;
           end;

           jpg.SaveToStream( stream );
           AThread.Connection.WriteStream( stream, true, true );
         finally
           jpg.Free;
         end;
       finally
         stream.Free;
       end;
     end;
   end
end;


2) Клиент IdTCPClient
* Подключается к серверу
* Активируем таймер, по которому происходит запрос и получение кадра

procedure TForm2.Timer1Timer(Sender: TObject);
var
 stream: TMemoryStream;
 jpg: TJpegImage;
begin
 if IdTCPClient1.Connected = false then
   begin
     ShowMessage( "Not Connected!" );
     Stop1.Click;
     exit;
   end;

 stream:= TMemoryStream.Create;
 try
   IdTCPClient1.WriteLn("go");
   IdTCPClient1.ReadStream(stream);
   stream.position:=0;

   jpg:=TJpegImage.Create;
   try
     jpg.LoadFromStream( stream );

     Image1.Canvas.Lock;
     try
       Image1.Picture.Bitmap.Assign(jpg);
     finally
       Image1.Canvas.Unlock;
     end;
     
   finally
     jpg.Free;
   end;

 finally
   stream.Free;
 end;
end;


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

В качестве дополнения:
1) можно указать скорость видеозахвата (не реализовано)
2) можно менять качество передаваемых jpg картинок (реализовано)
3) получать опр. количество кадров в секунду с сервера (изменить интервал таймера)

Загрузка процессора (Celeron 2GHz, RAM >= 512Mb):
Сервер:
* Видеозахват 320x240 (процесс System) кушает ~20%
* bmp->jpg (60% quality) 5-10 кадров/сек кушает ~15% CPU

Клиент:
* Отображение полученных jpeg изображений 5-10 кадров/сек кушает ~10% CPU

Возможно, что-то используется неоптимально, в дельфи я новичок.


 
Digitman ©   (2005-10-27 08:40) [8]

Для рамок ЛВС под управлением сетевого ПО от Майкрософт использовать TCP в кач-ве транспортного протокола для эффективного решения данной задачи, imho, неразумно. Гораздо лучших результатов (с т.з. производительности транспортной подсистемы) можно достичь с использованием именованых программных каналов (Namep Pipes). Если в ЛВС есть хосты под управлением иных ОС (не Windows), то в этом случае лучшим решением будет использование UDP в кач-ве транспортного протокола - он проще в реализации и потому ощутимо быстрей нежели ТСР.

К тому же я не вижу резона для организации ПИО в виде "клиент запрашивает кадр - сервер передает кадр". При подключении клиенту достаточно единожды сообщить серверу желаемые параметры видеопотока, такие, например, как FPS (число кадров , которые клиент способен принять и обработать в секунду), разрешение, глубина цветности, способ кодирования и т.п. После этого сервер начинает передавать видеопоток безо всяких подтверждений клиента о принятых им фрагментах. С этого момента уже клиент ответственен за максимально быструю обработку принимаемых фрагментов потока. Те фрагменты, которые клиент не успел обработать, попросту исключаются. Чтобы при этом не нарушалась синхронизация сервер должен включать в передаваемый поток метки времени и в зависимости от способа кодирования периодически передавать опорные кадры.


 
Slym ©   (2005-10-27 10:22) [9]

Причина зависа- фрагментация склейка пакетов...
как ты в потоке между собой JPGи отличаешь? никак! и получается один кадр ты перегрузил второй не догрузил...

Я бы сделал так:
1. раз сообщил FPS
2. на сервере отсылал картинку постоянно (без команды) и паузой для ФПС. (менше Sleep выше FPS больше загруз CPU)
3. Использовал ПРОТОКОЛ ПЕРЕДАЧИ, т.е. договоренность сторон об сигнатурах разделения картинок. Будь то boundary как в MotionJPG, или заголовок с указанным размером данных картинки.


 
Slym ©   (2005-10-27 10:30) [10]

4. Можно отсылать только изменения картинки
или на 1 этапе. флаг not changed для статичной картинки... фпс на статике выростет


 
Setor   (2005-10-27 11:23) [11]

Digitman
> лучшим решением будет использование UDP в кач-ве транспортного
> протокола - он проще в реализации и потому ощутимо быстрей
> нежели ТСР

Я подумаю над этим вопросом. Изначально я тоже склонялся в сторону UDP, но т.к. с TCP я знаком намного лучше, решил взять его за основу для передачи данных.

Slym
> Причина зависа- фрагментация склейка пакетов...

Да, я уже не раз сталкивался с данной проблемой. Где-то на форуме мелькало одно из решений данной проблемы.

Digitman
> я не вижу резона для организации ПИО в виде "клиент запрашивает
> кадр - сервер передает кадр".

Мне тоже чертовски не нравится данная схема, по этому я собственно, и задал вопрос на форуме.

Digitman
> сервер должен в зависимости от способа кодирования
> периодически передавать опорные кадры

Если я правильно понял, речь идёт о сжатии видеопотока и передаче этого потока по сети? Я ещё не обладаю достаточными знаниями для реализации подобного алгоритма.

Slym
> Я бы сделал так:
> 3. Использовал ПРОТОКОЛ ПЕРЕДАЧИ, т.е. договоренность сторон
> об сигнатурах разделения картинок. Будь то boundary как
> в MotionJPG, или заголовок с указанным размером данных картинки.

Искал я в интернете информацию по поводу MotionJPEG... Её оказалось не так уж и много. Посмотрел кодек Morgan"а, а он денег стоит...

По поводу boundary - идея неплохая, лишь бы в коде картинок не встретилось комбинации символов, используемой для разделения картинок (boundary), иначе всё поломается...

Единственная проблема заключается в том, что я просто не у мею создавать кадры, класть них заголовки и тело, не знаю как потом разделить и пропарсить эти полученные кадры. У меня были в голове аналогичные идеи, но в связи с тем, что с Delphi я мало знаком, делал так, как умею. Моя основная специализация - WEB программист (PHP), а в создании приложений для Windows - я как рыба на суше.

Подведу итоги, то что хотелось бы изменить:
1) В качестве транспортного протокола использовать UDP
2) Клиент единожды сообщает серверу параметры захвата видео (размеры, глубина цвета и fps)
3) Сервер начинает передачу видеопотока
4) Клиент обрабатывает принятый поток

По 3му и 4му пункту - я не знаю как создать и обработать видеопоток. Я знаю лишь то, что это должно быть потоковое видео. Это был бы идеальный вариант. Пока что для меня самое простое - использовать текущую схему разбиения на картинки. Но как их разделить... Вот в чём вопрос!


 
Digitman ©   (2005-10-27 12:06) [12]


> речь идёт о сжатии видеопотока и передаче этого потока по
> сети?


да.


> не обладаю достаточными знаниями для реализации подобного
> алгоритма


в таком случае есть резон воспользоваться готовыми алгоритмами, реализованными в различных инсталлированных и доступных в системе кодеках

открой в панели управления "Звук и мультимедиа", в закладке "Оборудование" выбери "Видеокодеки", найди в Сети и изучи материалы, касаемые характеристик того или иного интересующего тебя кодека ... если устраивает, найди в Сети материалы, касаемые программного доступа к интерфесам видеокодеков - базовые интерфейсы как правило стандартные для любого кодека


 
Slym ©   (2005-10-27 14:53) [13]

Незаметил- Фактически перед каждой картинкой посылаешь размер данных:
отправка
AThread.Connection.WriteStream(stream, true, true );
(первый 4х байтник размер данных)
прием
IdTCPClient1.ReadStream(stream);
прием первых 4х байт потом прием N данных


 
Eraser ©   (2005-10-27 18:48) [14]


> Digitman ©   (27.10.05 08:40) [8]


> Гораздо лучших результатов (с т.з. производительности транспортной
> подсистемы) можно достичь с использованием именованых программных
> каналов (Namep Pipes).

А разве это не обёртка над TCP/IP, при использовании в сети, а не на локальном компьютере?


 
Setor   (2005-10-28 02:51) [15]

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

Видеопоток получаю SampleGrabber"ом для проигрывания, хотелось бы, тоже воспользываться DirectShow (DSPack). Буду копать дальше...

P.S. В сети я нашёл лишь 1 исходник видеочата, написанного на Delphi, но он какой-то глючный и слишком сложный для меня...


 
Digitman ©   (2005-10-28 08:35) [16]


> Eraser ©   (27.10.05 18:48) [14]


> разве это не обёртка над TCP/IP


нет , это не обертка.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/optimsql/odp_tun_1a_7fcj.asp


> Setor   (28.10.05 02:51) [15]



> Пытался передать видеопоток через UDP, но возникла проблема
> - слишком большие кадры


максимальный размер дейтаграмм, передаваемых под управлением UDP, можно изменить (см. SetSockOpt)


 
Verg ©   (2005-10-28 09:27) [17]

http://book.itep.ru/4/44/rtp_4492.htm


 
Idx ©   (2005-10-28 09:36) [18]

Да дайте ему хороши пример и все!!!

Кстати посмотри компонент TMNN на toory


 
Eraser ©   (2005-10-28 14:58) [19]


> Digitman ©   (28.10.05 08:35) [16]

И правда... Спасибо за ссылку, а то я сам по этой теме не нашёл ничего.


 
Анонимщики ©   (2005-10-28 16:54) [20]

Не так-то просто найти хороший пример на эту тему, поскольку затрагивается множество подтем: захват видео, обработка (в частности, с использованием кодеков), передача по сети (вопрос, использовать ли UDP (можно и широковещательно) или TCP/IP - не так уж и прост; в коммерческих программах, обычно, реализованы оба варианта), прием с другой стороны, протокол обмена(в частности, подтверждать-не подтверждать прием кадра (для TCP, естественно), в случае TCP - как производить взаимодействие с каждым из подключенных клиентов - тоже можно по-разному сделать). Если еще и звук добавить - количество проблем вырастет.

Совет Digitman"а, в принципе, годится, да только он недоукомплектован.

Я бы посоветовал следующий путь:
1. Изучаем DirectShow. Можно достаточно поверхностно, можно и поглубже, включая написание собственных фильтров.
2. Если поверхностно, берем готовые фильтры - то ли из майкрософтовского примера - NetSend, кажется, он называется (он не идет с DSPack"ом), то ли, скажем, элекардовский MPEG-2 сетевой фильтр. Если глубже, пытаемся написать свой фильтр (фильтры), который бы покрывал множество наших задач: широковещательная передача и точка-точка (с разными, возможно, вариантами взаимодействия с подключенными клиентами).
3. Что касается использования кодеков, то их следует использовать при построениии графа фильтров на сервере и  клиентах.
4. Можно пойти дальше, и разобраться еще и с Windows Media. После этого разбора будет понятно, каким образом использовать на стороне клиента Windows Media Player, а на стороне сервера - Windows Media Encoder. Сетевыми протоколами в таких случаях могут быть уже RTP/RTSP или, скажем, MMS. При очень большом желании можно и с ними разобираться. Впрочем, я не видел (правда, не искал особо) готовой библиотеки для работы через MMS. А вот для RTP/RTSP - есть свободная (вот забыл как называется и где можно взять).

Ну, и не советую использовать этот самый DSPack - только голову заморочит, особенно поначалу


 
Setor   (2005-10-28 20:11) [21]

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

По поводу DSPack - он только облегчает работу с DirectShow, так зачем искать геммор на свою задницу? Сегодня я сделаю, а завтра забуду. Пусть лучше будет просто и красиво.


 
PAVIA ©   (2005-10-28 21:05) [22]

Лично я использовал vfw для воспроизведения видео MPEG-4.   Я пробовал UDP, TCP. Показывать надо начинать от ключевого кадра. Обязательно нужна проверка на то, что кадр дошел. Так как, если не ключевой кадр теряеться то программа падает. А теряються они как на UDP так и на TCP. Для того чтобы программа показывала 25 кадров в секунду, а не 5-10 надо передовать потоком. То есть иными словами в одном пакете нужно передовать сразу несколько кадров, забить под завяску. И наче будет работать медлено, причина органезация сети. Но нужно помнить об ограничение пакета. Еще лучше сделать буферизацию запасом в 1 секунду.


 
rrr8888   (2005-11-24 17:45) [23]

А чем вам протоколы SIP и H.323 не подходят - специально же для передачи потокового аудио/видео созданы..


 
zd ©   (2006-01-26 16:33) [24]

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



Страницы: 1 вся ветка

Форум: "Сети";
Текущий архив: 2006.05.21;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.014 c
4-1141037259
Руслан
2006-02-27 13:47
2006.05.21
Как перехватить сообщения, посылаемые другому процессу?


15-1145732092
DBwewq
2006-04-22 22:54
2006.05.21
Помогите пожалуйста! В чем ошибка! timer:longint absolute $40:$6c


2-1146220976
фил
2006-04-28 14:42
2006.05.21
delphi


2-1146643356
Alex_C
2006-05-03 12:02
2006.05.21
Как получить CharSet шрифта


4-1141220323
ionn
2006-03-01 16:38
2006.05.21
Как отследить момент закрытия внешнего приложения?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский