![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Снимок экрана [D6, Win2k, WinXP]
Nic2 © (2004-09-22 17:41:00)Здравствуйте Мастера.
Пишу программу, которая передает снимки моего экрана на др. машину по сети и там их отображает (короче просмотр экрана удаленной машины). Делать это пытаюсь 24 кадра в сек., пакуя снимки в JPEG Проблема такая: упаковка в JPEG длится долго, а по сему получается максимум 8 кадров в секунду. Можно ли как-то увеличить кол-во кадров в секунду.
Код:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
procedure TFORM1.CopyScrMy();
var
ScrBitmap: TBitmap;
jpg: TJPEGImage;
begin
DC := GetDC(0);
BInfo.bmiHeader.biSize := sizeof(tagBITMAPINFOHEADER);
BInfo.bmiHeader.biWidth := 1024;
BInfo.bmiHeader.biHeight := 768;
BInfo.bmiHeader.biPlanes := 1;
BInfo.bmiHeader.biBitCount := 24;
BInfo.bmiHeader.biCompression := BI_RGB;
binfo.bmiHeader.biSizeImage:=0;
ScrBitmap := TBitmap.Create();
ScrBitmap.Handle := CreateDIBSection(Canvas.Handle, BInfo, DIB_RGB_COLORS, Scr, 0, 0);
bitblt(ScrBitmap.Canvas.Handle,0,0,1024,768,DC,0,0,srccopy);
ScrBitmap.ScanLine[1];
try
if not ScrBitmap.Empty then
begin
ms:=TMemoryStream.Create;
jpg := TJPEGImage.Create;
jpg.Performance:=jpBestspeed;
jpg.PixelFormat:=jf8Bit;
jpg.Scale:=jsHalf;
jpg.CompressionQuality:=50;
jpg.Compress;
jpg.Assign(ScrBitmap);
ScrBitmap.Assign(jpg);
jpg.SaveToStream(ms);
ms.Position:=0;
try
Socket.PostIt(ms);
except
end;
end;
finally
ms.Clear;
b.Free;
jpg.Free;
DeleteDC(DC);
SCRBitmap.Free;
end;
end;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Заранее спасибо.
DeadMeat (2004-09-26 13:43:00) [21]Как дополнение к [20] можно попробовать усложнить.
Орагнизовать перехват EndPaint (или как она там зовется). При ее вызове отсылать данные из полученного от нее DC... Тогда и не надо BitBlt вообще вызывать...
ЗЫЖ. Это только идея. Не проверенно....
DeadMeat (2004-09-26 13:36:00) [22]В любом случае сжатие добавляет нагрузку... Ведь все равно надо еще и bitblt делать. Так что ИМХО, вариант [20] оптимальнее...
_silver (2004-09-26 12:07:00) [23]2PGM_X
bitblt работает довольно быстро, а сжатие в jpeg довольно долгая процедура. Если не веришь проверь
PGM_X (2004-09-25 23:04:00) [24]Для информации: чтение из видеопамяти операция на порядки медленне чем запись (на многи картах меряется в 5-6 Мб/с, только GeForce может похвастать приличной скоростью. Так что на тех же ATI лимитирует не сжатие в JPEG, а банальная низкая скорость чтения из памяти. Как раз BitBlt с экрана и будет все тормозить.
_silver (2004-09-25 14:38:00) [25]Я делал подобное.
jpeg там не нужен.
В общих чертах:
1. хук на все сообщения связаные с перерисовкой экрана
2. определить координаты перерисованного участка
3. bitblt с него и отправляешь это куда надо
Скорость не хуже чем у RAdmin( кстати он также сделан)
Sapersky (2004-09-25 01:48:00) [26]Может, попробовать чего попроще, например, перевод в grayscale (цветом можно пожертвовать) и RLE (взять хотя бы этот форум, большая часть экрана - один цвет, так что RLE должен хорошо сработать).
Или передавать различия между соседними кадрами - AVI/MPEG вроде это и делают?
Или ещё есть такая мысль - относительно сжатия текстур, которое есть в современных картах... они только разжимают аппаратно, или сжимать тоже могут? В DX SDK написано:
use IDirectDrawSurface7::Blt or IDirectDrawSurface7::BltFast to blit from the uncompressed surface to the compressed surface. DirectDraw does the compression for you.
но как он её does, аппаратно или программно - не уточняется. Надо пробовать...
Nic2 (2004-09-24 19:16:00) [27]См. ответ №11 пункт 2.
Из хелпа:
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
TJPEGImage.JPEGNeeded
Creates a new TJPEGData object if the jpeg image only has a bitmap and a jpeg is needed.
procedure JPEGNeeded;
Description
Call JPEGNeeded to create a new jpeg data source when the jpeg image has thrown away the jpeg data and only has an internal bitmap. JPEGNeeded creates a new jpeg data source. The SaveToStream method uses JPEGNeeded .
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Анонимщик (2004-09-24 19:07:00) [28]А из чего ты вывел, что именно сохранение в поток жрет ресурсы? Ведь если ты его отключишь, то я за оптимизатор не ручаюсь, даже если он отключен.
Анонимщик (2004-09-24 18:34:00) [29]Нет, глупости это. Видимо, проблема в больших размерах (1024 на 768) и 24-ых битах. Конечно, можно уменьшить битность до 256 цветов, будет быстрее. Для начала нужно выяснить, какая у людей максимальная скорость сжатия jpeg'ом для таких картинок.
Что же касается C, то у интела можно взять уже откомпилированную библиотеку, сам язык знать необязательно.
Попробуй задать вопрос на http://www.compression.ru/forum/, а результаты доложи.
Nic2 (2004-09-24 17:43:00) [30]А еще лучше-все компы к себе на стол перетянуть. Все видно, частота смены кадров 100Гц! Так еще и управлять ими можно!!!!!!!!!!!!!!! Красота....
WondeRu (2004-09-24 17:19:00) [31]в Mpeg4 сжимать будет DirectShow... короче забудь способ с платой захвата видео - ерунда полная!
Новая бредовая идея: ставишь мультиплексор себе с монитором, а на ведомые компы видеокарты с ТВ-выходом, протягиваешь РК кабель от каждого компа! и наслаждаешься 25 кадрами в секунду! ;)
Nic2 (2004-09-24 17:10:00) [32]To:WondeRu
Сижу на Делфе6, zlib в нем нет. Ща поставлю 7 Делфу. О результатах напишу.
Nic2 (2004-09-24 17:06:00) [33]<<гонишь всю захваченную картинку по сети пакетами, сжатыми по Mpeg4>>
Честно говоря сомнительно, что упаковка в JPEG более ресурсоемкая, чем упаковка в mpeg4.
К тому же единственный найденный мой метод упаковки в jpeg (через модуль VFW,...и еще несколько названий не помню), у меня не заработал, справки я к нему не нашел, и нигде в нете не увидел ни примеров, ни хотя-бы людей, которые с ним работали. Короче с этим лажа...
Спасибо всем, кто отозвался.
Nic2 (2004-09-24 17:01:00) [34]1). Уже и тут покопался: называется библиотека Intel JPEG Library входит в состав чего-то типа пакета для разработчиков Intel IPP (Intel® Integrated Performance Primitive) но она написана на С (а я если честно с С не дружу);
2). А какой смысл в проценте времени этого кода, если я опытным методом установил, что ресурсы пожирает jpg.SaveToStream(ms);, который в свою очередь использует DIBNeeded. Я пытался писать все как есть в коде, только вместо
jpg.SaveToStream(ms);
писал
jpg.DIBNeeded;
Эффект тот же - 8 кадров.
А если закомментировать jpg.SaveToStream(ms);/jpg.DIBNeeded; то получается 33 кадра в секунду, бе вывода на экран и 30 с выводом.
Спасибо всем, кто отозвался.
WondeRu (2004-09-24 16:53:00) [35]у кого-то я видел замечательный способ сжимания картинок с экрана: "видеокарта с ТВ-выходом + карта видео захвата = гонишь всю захваченную картинку по сети пакетами, сжатыми по Mpeg4"
Анонимщик (2004-09-24 16:43:00) [36]А какой процент времени занимает код
DC := GetDC(0);
BInfo.bmiHeader.biSize := sizeof(tagBITMAPINFOHEADER);
BInfo.bmiHeader.biWidth := 1024;
BInfo.bmiHeader.biHeight := 768;
BInfo.bmiHeader.biPlanes := 1;
BInfo.bmiHeader.biBitCount := 24;
BInfo.bmiHeader.biCompression := BI_RGB;
binfo.bmiHeader.biSizeImage:=0;
ScrBitmap := TBitmap.Create();
ScrBitmap.Handle := CreateDIBSection(Canvas.Handle, BInfo, DIB_RGB_COLORS, Scr, 0, 0);
bitblt(ScrBitmap.Canvas.Handle,0,0,1024,768,DC,0,0,srccopy);
ScrBitmap.ScanLine[1];
и какой - все остальное? Смотрел профайлером?
Анонимщик (2004-09-24 16:41:00) [37]Было где-то непроверенное мною утверждение, что в дельфи неэффективная реализация jpeg'а, это нужно бы проверить. Есть интелловская какая-то библиотека, не помню как называется. Хорошо бы, если бы ты проверил и рассказал.
Nic2 (2004-09-24 16:17:00) [38]<<а то есть подозрение, что больше 8-ми. Проверь>>
Сама передача, в плане поедания системных ресурсов не стоит ничего. Если в коде поменять:
Socket.PostIt(ms);
на
//Socket.PostIt(ms);
не изменится ничего.
Все ресурсы "хавает" <jpg.SaveToStream(ms);>. (причем что интересно, что jpg.SaveToFile('c:\...'); работает ничуть не медленнее, хотя по логике ведь дисковые операции...).
Спасибо всем кто отозвался.
Анонимщик (2004-09-24 15:19:00) [39]<<А сколько кадров ты в состоянии сжать за секунду?>>
Если Вы имеете в виду сколько я хотел бы видеть кадров в секунду, то 15-20 (ну в идеале естественно 24).
Я имею в виду, сколько кадров в секунду ты можешь сжать без передачи, а то есть подозрение, что больше 8-ми. Проверь.
Nic2 (2004-09-24 14:40:00) [40]<<А почему не воспользоватся уже готовым совтом?>>
Мне нужно делать просмотр в определенные моменты времени, которые определяет моя программа, но это не главное, в последствии я собираюсь организовать просмотр экранов 4-х машин (ну хотябы попробую...).
<<А сколько кадров ты в состоянии сжать за секунду?>>
Если Вы имеете в виду сколько я хотел бы видеть кадров в секунду, то 15-20 (ну в идеале естественно 24).
<<Попробуй использовать глобальные переменные, например, для Jpg, т.е. не создавать и удалять каждый раз.>>
Это я привел один из вариантов, а вообще я пробовал и глобальные переменные, и создавал все по загрузке проги (а убивал по завершению). Все бестолку-7-8кадров.
Спасибо всем кто отозвался.