Форум: "Компоненты";
Текущий архив: 2006.11.12;
Скачать: [xml.tar.bz2];
ВнизНужен совет по созданию компонента с потоком. Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.049 c