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

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

Прием большого потока данных по UDP


Страницы:   1 2

MBo ©   (2008-01-31 07:26:00) 

Задача следующая - некий спецдевайс передает по сети по протоколу UDP данные (видеопоток), порядка 11 мегабайт в секунду, пакет 770 байт - строка. Прием занимает очень значительную часть процессорного времени (применяется WSA-функции + RecvFrom, также пробовал использовать Indy и ICS), причем, если программа занимается еще чем-то, то пакеты, приходящие  в этот момент, теряются. Например, если после приема кадра отрисовывать его, то несколько первых строк следующего кадра не принимаются.

Можно ли предпринять какие-то меры к улучшению ситуации?
C сетями ранее не работал, так что могут помочь любые идеи.


Slym   (2008-02-04 05:13:00) [1]

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


ага   (2008-02-03 11:46:00) [2]

2 MBo ©

WSARecv c кучей буферов сразу под весь кадр не пробовал? Те буфер один, но разбит на несколько, по числу строк.

Синхронизацию сообщениями я бы выкинул. Как и многопоточность, скоре всего, использовал бы асинхронный режим. В любом случае, синхронизация здесь - лишние потери, имхо. Два буфера, один рисуется, второй принимается. Буферы переключает "приемник", а по WM_PAINT выводится "рисуемый", независимо от того, было ли обновление.

Как гипотеза - может вывод через DirectX побыстрее будет. Не знаю, не спец.


Slym   (2008-02-01 04:51:00) [3]

procedure x;
type
 TLineRec=packed record
   Info:word;
   Data:array[0..192*4-1] of char;
 end;
var
 Bitmap:TBitmap;
 Line:TLineRec;
 FromLen,LineNum,CadrNum,Wrd:integer;
 WSResult:integer;
 UD:TSocket;
 Addr:TSockAddr;
begin
 Bitmap:=TBitmap.Create;
 try
   Bitmap.PixelFormat:=pf32bit;
   Bitmap.Width:=192;
   Bitmap.Height:=192;
   while not Terminated do begin
     FromLen := SizeOf(TSockAddr);
     WSResult := RecvFrom(UD, Line, SizeOf(Line), 0, Addr, FromLen);
     if WSResult<>SizeOf(Line) then continue;
     Wrd := Swap(Line.Info);
     LineNum:= Wrd and $3FF;
     if (LineNum>-1) and (LineNum<Bitmap.Height) then
       Move(Line.Data,Bitmap.ScanLine[LineNum]^,SizeOf(Line.Data));

     if LineNum = Bitmap.Height-1 then
     begin
       Inc(FrameCount);
       FCanvas.Lock;
       try
         FCanvas.Draw(0,0,Bitmap);
       finally
         FCanvas.Unlock;
       end;
     end;
   end;
 finally
   Bitmap.Free;
 end;
end;


DVM   (2008-02-01 00:01:00) [4]


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

Нет, не должна. Вся нагрузка возникает, если в принимаемом потоке надо. что то искать, выцеплять, декодировать. Отрисовка это тоже мелочи.


DVM   (2008-01-31 23:58:00) [5]


> MBo ©

А что за девайс такой? IP камера? Просто знакомая мне тематика.


Anatoly Podgoretsky   (2008-01-31 20:05:00) [6]

> MBo  (31.01.2008 18:31:24)  [24]

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


MBo   (2008-01-31 18:31:00) [7]

>а в другом месте.
Вот и хочется понять, что это за место ;)


Anatoly Podgoretsky   (2008-01-31 16:28:00) [8]

> MBo  (31.01.2008 15:47:22)  [22]

100 мегабит это ничто для процессора, проблема не в количестве, а в другом месте.


MBo   (2008-01-31 15:47:00) [9]

>А если отрисовка медленней заполнения ?
тогда бы я ставил в очередь и отрисовывал бы только часть кадров.

В данном случае хватает двух буферов.
14400 пакетов в секунду, 0.07 мс один пакет
Отрисовка сначала у меня происходила более сложно, и занимала 3-4 мс, это по времени порядка 60 пакетов, около 40 КБ данных.
Визуально - если критерий отрисовки - приход нулевой строки, то в районе 20-50 строк было много выпавших.
Сейчас отрисовка быстрее, и артефактов на моей машине (Athlon 3500) практически нет, но на машинах вдвое медленнее - все-таки появляются.

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

(С цифрового видеограббера без проблем принимаю, достаточно сложным образом обрабатываю и отрисовываю втрое-вчетверо больший поток)


Anatoly Podgoretsky   (2008-01-31 15:41:00) [10]

> MBo  (31.01.2008 14:32:19)  [19]

Для испытания временно отключи отрисовку.


Сергей М.   (2008-01-31 15:16:00) [11]


> один заполняется, предыдущий отрисовывается


А если отрисовка медленней заполнения ?
Подумай ...


MBo   (2008-01-31 14:32:00) [12]

>PostMessage… да ещё и SetDiBits
Отрисовку, временно забыв об опасностях обращения к основному окну из доп. потока, можно вести и прямо из потока, ничего принципиально это не меняет.
SetDiBitsToDevice  - оказался в данном случае наименее затратный способ из испытанных (альтернатива, например - формирование битмапа, происходит дольше)

насчет DirectX - еще не прорабатывал, побоялся затрат времени на преобразование цветов.


ketmar   (2008-01-31 14:11:00) [13]

у-у-у. PostMessage… да ещё и SetDiBits… есть (ничем не обоснованое, правда) мнение, что:
эту фигню надо тихонько совать в буфер моска сразу по получении. раз.
наладить frame skiping, если не успевает отрисоваться, а в буферг гадит.
рисовать директиксом на оверлеях (тут, возможно, вылезут тормоза с преобразованием цветовых пространств, искать карты, оверлеи на которых потянут rgb).

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


MBo   (2008-01-31 13:52:00) [14]


инициализация в конструкторе потока

 if WSAStartup($0202, WSAD) <> 0 then
   Exception.Create('WSAStartup Error');
 Ud := Socket(AF_INET, Sock_Dgram, 0);
 if INVALID_SOCKET  = Ud then
   Exception.Create('Socket Create Error');
 Addr.sin_family := PF_Inet;
 Addr.sin_addr.S_addr := Inet_Addr('0.0.0.0');
 Addr.sin_port := HtoNS(FPort);
 FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);
 if Bind(UD, Addr, SizeOf(Addr)) = Socket_Error then
   Exception.Create('Socket Bind Error');

поточная функция

 Len := 770;
 while not Terminated do begin
   FromLen := SizeOf(TSockAddr);
   WSResult := RecvFrom(UD, LineBuf, Len, 0, Addr, FromLen);
   Wrd := Swap(PWord(@LineBuf[0])^);
   LineNum := Wrd and $3FF;
   CadrNum := (Wrd shr 12) and 1;

   if LineNum = 0 then begin
     Inc(FrameCount);
     PostMessage(Form3.Handle, WM_USER, FrameCount and $F, CadrNum xor 1);
   end;

   Move(LineBuf[2], Buf[CadrNum, LineNum, 0], Wdt);
 end;

Buf - 2 массива, один заполняется, предыдущий отрисовывается

в обработчике WM_USER отрисовка
 SetDiBitsToDevice(Canvas.Handle, 0, 0, Wdt, Hgt, 0, 0, 0, Hgt,
   @Buf[M.LParam], PBitmapInfo(@Info)^, DIB_RGB_COLORS);


ketmar   (2008-01-31 11:23:00) [15]

>[15] Сергей М. ©(31.01.08 10:54)
я подозреваю, что ничего там такого нет. тупо сетка успевает впритык.

однако ж глянуть не помешает в любом случае, да.


Сергей М.   (2008-01-31 10:54:00) [16]


> MBo ©   (31.01.08 10:37) [14]


Ты бы код своего транспортного алгоритма показал ..


MBo   (2008-01-31 10:37:00) [17]

> лучше таки накапливай где-то на отдельном сервере и с него уже забирай. и на гигабитке, желательно

Увы, не получится - в реальности будут полевые условия, железка - кабель - ноутбук.


ketmar   (2008-01-31 10:19:00) [18]

>[12] MBo ©(31.01.08 10:11)
ну, ты учти, что поток не может быть особо приоритетней приложения. подними ещё приоритет самому приложению. другим потокам приоритет поспускай.

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


MBo   (2008-01-31 10:11:00) [19]

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


ketmar   (2008-01-31 09:58:00) [20]

>[10] Сергей М. ©(31.01.08 09:53)
так нечестно, я это уже посоветовал! %-)


Страницы:   1 2

Наверх

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