Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.12;
Скачать: CL | DM;

Вниз

Нужен совет по созданию компонента с потоком.   Найти похожие ветки 

 
DVM ©   (2006-03-20 11:05) [0]

Пишу компонент. Невизуальный. Для простоты изложения положим, что у него должны присутствовать два события:
OnError и OnNewBitmap.
Компонент при старте создает дополнительный поток, который получает откуда-то (с вебсервера) изображения. Если поток получил новую картинку - должно возникать OnNewBitmap, если при получении произошла ошибка OnError.
И в том и в другом случае из потока надо передавать параметры (код ошибки или сам битмап), поэтому Synchronize тут не подходит.
Я решил сделать так:
1) Компонент создает скрытое окно и ждет получения сообщений от потока.
2) Поток при возникновении нужной ситуации посылает сообщение скрытому окну компонента.
3) Я планирую использовать WM_COPYDATA для передачи картинки из дополнительного потока в основной и далее в обработчик события.

Правильно ли я спланировал путь решения задачи? Или есть ли более простые пути и если да, то какие?


 
Reindeer Moss Eater ©   (2006-03-20 11:16) [1]

3) Я планирую использовать WM_COPYDATA

Зачем так серьёзно?
Все же происходит в рамках одного процесса.
Достаточно указателя на начало битмапа и его длину в wParam и lParam.


 
DVM ©   (2006-03-20 11:27) [2]


> Зачем так серьёзно?

А если пока я буду работать с битмапом в обработчике OnNewBitmap поток его (битмап) изменит? Не хотелось бы тормозить поток блокировкой битмапа.
А так просто я отправлю копию битмапа и все.
Правда опасаюсь, что с WM_COPYDATA может получиться медленно. Битмапов будет передаваться много.


 
Reindeer Moss Eater ©   (2006-03-20 11:29) [3]

А если пока я буду работать с битмапом в обработчике OnNewBitmap поток его (битмап) изменит?

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


 
DVM ©   (2006-03-20 11:33) [4]


> А после того как его выкачал, зачем потоку что-то делать
> с картинкой?

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


 
Reindeer Moss Eater ©   (2006-03-20 11:34) [5]

Он начинает качать следующую и класть ее на место старой.

На какое такое "место"?
В тот же файл-что ли? Или в тот же кусок памяти?
И нафига?


 
DVM ©   (2006-03-20 11:42) [6]


> На какое такое "место"?
> В тот же файл-что ли? Или в тот же кусок памяти?
> И нафига?

При старте потока он создает новый битмап FCamBitmap := TBitmap.Create;
Поток получает данные JPEG в специальный буфер, потом как накопится полный кадр, кадр декодируется в Bitmap с пом. Intel Jpeg Library и декодированные данные помещаются в этот битмап.

Поток получает видео в формате MotionJPEG.


function LoadBmpFromJpegInMemory   (bitmap: TBitmap;  Mem: Pointer; MemSize: integer;
                             const set_pixel_format: boolean;
                             const scale: TIJLScale = ijlFullSize): boolean;

var
 iWidth, iHeight, iNChannels: Integer;
 iDIBChannels: integer;
 iStatus: integer;
 jcprops: TJPEG_CORE_PROPERTIES;
 DIB: TDIBSection;
begin
 Result := False;
 if not Assigned (bitmap) then Exit;
 if Mem = nil then Exit;

 case bitmap.PixelFormat of
   pf8Bit: iDIBchannels := 1;
   pf24Bit: iDIBchannels := 3;
 else
   iDIBchannels := 0;
 end;
 if (iDIBChannels = 0) and (not set_pixel_format) then Exit;

 // Initialise the JPEG library
 FillChar (jcprops, SizeOf (jcprops), 0);  // Just to be sure...
 iStatus := ijlInit (@jcprops);
 if iStatus = IJL_OK then
 try

   jcprops.JPGBytes := Mem;
   jcprops.JPGSizeBytes := MemSize;
   iStatus := ijlRead (@jcprops, IJL_JBUFF_READPARAMS);
   if iStatus = IJL_OK then
     begin
     iWidth := jcprops.JPGWidth;
     iHeight := jcprops.JPGHeight;
     case scale of
       ijlHalf: begin
                iWidth := (iWidth + 1) div 2;
                iHeight := (iHeight + 1) div 2;
                end;
       ijlQuarter: begin
                iWidth := (iWidth + 3) div 4;
                iHeight := (iHeight + 3) div 4;
                end;
       ijlEighth: begin
                iWidth := (iWidth + 7) div 8;
                iHeight := (iHeight + 7) div 8;
                end;
     end;
     iNChannels := jcprops.JPGChannels;
     if (iNChannels = 1) or (iNChannels = 3) then
       begin
       bitmap.Height := 0;
       bitmap.Width := 0;
       if set_pixel_format then
         begin
         iDIBChannels := iNChannels;
         if iDIBChannels = 1
           then bitmap.PixelFormat := pf8Bit
           else bitmap.PixelFormat := pf24Bit;
         end;
       bitmap.Width := iWidth;
       bitmap.Height := iHeight;
       FillChar (DIB, SizeOf (DIB), 0);
       iStatus := GetObject (bitmap.Handle, SizeOf (DIB), @DIB);
       if iStatus <> 0 then
         begin
         jcprops.DIBWidth := iWidth;
         jcprops.DIBHeight := -iHeight;
         jcprops.DIBChannels := iDIBChannels;
         if iDIBchannels = 3
           then jcprops.DIBColor := IJL_BGR
           else jcprops.DIBColor := IJL_G;
         jcprops.DIBPadBytes := ((((iWidth*iDIBChannels)+3) div 4)*4)-(iWidth*iDIBChannels);
         jcprops.DIBBytes := PByte (DIB.dsBm.bmBits);

         case scale of
           ijlHalf: iStatus := ijlRead (@jcprops, IJL_JBUFF_READONEHALF);
           ijlQuarter: iStatus := ijlRead (@jcprops, IJL_JBUFF_READONEQUARTER);
           ijlEighth: iStatus := ijlRead (@jcprops, IJL_JBUFF_READONEEIGHTH);
         else
           iStatus := ijlRead (@jcprops, IJL_JBUFF_READWHOLEIMAGE);
         end;

         if iStatus >= 0 then
           begin
           //bitmap.Modified := True;
           Result := True;
           end;
         end;
       end;
     end;
 finally
   ijlFree (@jcprops);
 end;

end;


 
Reindeer Moss Eater ©   (2006-03-20 11:47) [7]

Ну и в чем такая острая необходимость качать данные в один и тот же битмап?


 
DVM ©   (2006-03-20 11:53) [8]


> Ну и в чем такая острая необходимость качать данные в один
> и тот же битмап?

А как по другому? При получении нового кадра создавать каждый раз в потоке новый битмап и отсылать указатель на него с сообщением, а в обработчике после всех необходимых манипуляций освобождать? Я правильно понял?


 
Reindeer Moss Eater ©   (2006-03-20 12:07) [9]

Зачем тебе вообще битмап в потоке?
Он качает данные с веб сервера.
В итоге либо файл на диске, либо кусок байтов в памяти.
Закачав очередной кадр, оповести свой компонент о файле или блоек памяти и качай другой кадр в другой файл или в другой буфер.
Вот и все.


 
DVM ©   (2006-03-20 12:13) [10]


> Зачем тебе вообще битмап в потоке?

Ну потому как декодирование тоже в доп потоке происходит, хотя это можно оттуда и вынести в основной поток. И даже лучше вынести.

А вообще спасибо большое. Заклинило меня что-то на этом одном битмапе и отсюда все сложности.

Спасибо еще раз за советы.



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

Текущий архив: 2006.11.12;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.031 c
1-1159707242
RASkov
2006-10-01 16:54
2006.11.12
RectToObject и наоборот


15-1161493938
pkm
2006-10-22 09:12
2006.11.12
Восстановление инфы.


3-1158322229
Shaman_
2006-09-15 16:10
2006.11.12
Добавить поля в DataSet после выборки данных


15-1161677647
daser
2006-10-24 12:14
2006.11.12
Как узнать размер кластера на NTFS ( Win2003)?


3-1153997115
ALex123
2006-07-27 14:45
2006.11.12
MySQL и dbExpress: unable to load libmysql.dll.