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

Вниз

Снимок экрана   Найти похожие ветки 

 
Nic2   (2004-09-22 17:41) [0]

Здравствуйте Мастера.
Пишу программу, которая передает снимки моего экрана на др. машину по сети и там их отображает (короче просмотр экрана удаленной машины). Делать это пытаюсь 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;
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Заранее спасибо.


 
WondeRu ©   (2004-09-23 13:02) [1]

а пробуй просто упаковывать! используй zlib (F1 in Delphi)


 
Multy   (2004-09-23 14:50) [2]

А почему не воспользоватся уже готовым совтом?


 
Анонимщик ©   (2004-09-23 15:24) [3]

А сколько кадров ты в состоянии сжать за секунду?


 
Mihey_temporary ©   (2004-09-23 15:26) [4]

Попробуй использовать глобальные переменные, например, для Jpg, т.е. не создавать и удалять каждый раз.


 
Nic2   (2004-09-24 14:40) [5]

<<А почему не воспользоватся уже готовым совтом?>>
Мне нужно делать просмотр в определенные моменты времени, которые определяет моя программа, но это не главное, в последствии я собираюсь организовать просмотр экранов 4-х машин (ну хотябы попробую...).

<<А сколько кадров ты в состоянии сжать за секунду?>>
Если Вы имеете в виду сколько я хотел бы видеть кадров в секунду, то 15-20 (ну в идеале естественно 24).

<<Попробуй использовать глобальные переменные, например, для Jpg, т.е. не создавать и удалять каждый раз.>>
Это я привел один из вариантов, а вообще я пробовал и глобальные переменные, и создавал все по загрузке проги (а убивал по завершению). Все бестолку-7-8кадров.

Спасибо всем кто отозвался.


 
Анонимщик ©   (2004-09-24 15:19) [6]

<<А сколько кадров ты в состоянии сжать за секунду?>>
Если Вы имеете в виду сколько я хотел бы видеть кадров в секунду, то 15-20 (ну в идеале естественно 24).


Я имею в виду, сколько кадров в секунду ты можешь сжать без передачи, а то есть подозрение, что больше 8-ми. Проверь.


 
Nic2   (2004-09-24 16:17) [7]

<<а то есть подозрение, что больше 8-ми. Проверь>>
Сама передача, в плане поедания системных ресурсов не стоит ничего. Если в коде поменять:
Socket.PostIt(ms);
на
//Socket.PostIt(ms);
не изменится ничего.
Все ресурсы "хавает" <jpg.SaveToStream(ms);>. (причем что интересно, что jpg.SaveToFile("c:\..."); работает ничуть не медленнее, хотя по логике ведь дисковые операции...).

Спасибо всем кто отозвался.


 
Анонимщик ©   (2004-09-24 16:41) [8]

Было где-то непроверенное мною утверждение, что в дельфи неэффективная реализация jpeg"а, это нужно бы проверить. Есть интелловская какая-то библиотека, не помню как называется. Хорошо бы, если бы ты проверил и рассказал.


 
Анонимщик ©   (2004-09-24 16:43) [9]

А какой процент времени занимает код

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];

и какой - все остальное? Смотрел профайлером?


 
WondeRu ©   (2004-09-24 16:53) [10]

у кого-то я видел замечательный способ сжимания картинок с экрана: "видеокарта с ТВ-выходом + карта видео захвата = гонишь всю захваченную картинку по сети пакетами, сжатыми по Mpeg4"


 
Nic2   (2004-09-24 17:01) [11]

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 с выводом.

Спасибо всем, кто отозвался.


 
Nic2   (2004-09-24 17:06) [12]

<<гонишь всю захваченную картинку по сети пакетами, сжатыми по Mpeg4>>
Честно говоря сомнительно, что упаковка в JPEG более ресурсоемкая, чем упаковка в mpeg4.
К тому же единственный найденный мой метод упаковки в jpeg (через модуль VFW,...и еще несколько названий не помню), у меня не заработал, справки я к нему не нашел, и нигде в нете не увидел ни примеров, ни хотя-бы людей, которые с ним работали. Короче с этим лажа...

Спасибо всем, кто отозвался.


 
Nic2   (2004-09-24 17:10) [13]

To:WondeRu
Сижу на Делфе6, zlib в нем нет. Ща поставлю 7 Делфу. О результатах напишу.


 
WondeRu ©   (2004-09-24 17:19) [14]

в Mpeg4 сжимать будет DirectShow... короче забудь способ с платой захвата видео - ерунда полная!

Новая бредовая идея: ставишь мультиплексор себе с монитором, а на ведомые компы видеокарты с ТВ-выходом, протягиваешь РК кабель от каждого компа! и наслаждаешься 25 кадрами в секунду! ;)


 
Nic2   (2004-09-24 17:43) [15]

А еще лучше-все компы к себе на стол перетянуть. Все видно, частота смены кадров 100Гц! Так еще и управлять ими можно!!!!!!!!!!!!!!! Красота....


 
Анонимщик ©   (2004-09-24 18:34) [16]

Нет, глупости это. Видимо, проблема в больших размерах (1024 на 768) и 24-ых битах. Конечно, можно уменьшить битность до 256 цветов, будет быстрее. Для начала нужно выяснить, какая у людей максимальная скорость сжатия jpeg"ом для таких картинок.

Что же касается C, то у интела можно взять уже откомпилированную библиотеку, сам язык знать необязательно.

Попробуй задать вопрос на http://www.compression.ru/forum/, а результаты доложи.


 
Анонимщик ©   (2004-09-24 19:07) [17]

А из чего ты вывел, что именно сохранение в поток жрет ресурсы? Ведь если ты его отключишь, то я за оптимизатор не ручаюсь, даже если он отключен.


 
Nic2   (2004-09-24 19:16) [18]

См. ответ №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.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


 
Sapersky   (2004-09-25 01:48) [19]

Может, попробовать чего попроще, например, перевод в 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, аппаратно или программно - не уточняется. Надо пробовать...


 
_silver ©   (2004-09-25 14:38) [20]

Я делал подобное.
jpeg там не нужен.
В общих чертах:
1. хук на все сообщения связаные с перерисовкой экрана
2. определить координаты перерисованного участка
3. bitblt с него и отправляешь это куда надо
Скорость не хуже чем у RAdmin( кстати он также сделан)


 
PGM_X   (2004-09-25 23:04) [21]

Для информации: чтение из видеопамяти операция на порядки медленне чем запись (на многи картах меряется в 5-6 Мб/с, только GeForce может похвастать приличной скоростью. Так что на тех же ATI лимитирует не сжатие в JPEG, а банальная низкая скорость чтения из памяти. Как раз BitBlt с экрана и будет все тормозить.


 
_silver ©   (2004-09-26 12:07) [22]

2PGM_X
bitblt работает довольно быстро, а сжатие в jpeg довольно долгая процедура. Если не веришь проверь


 
DeadMeat ©   (2004-09-26 13:36) [23]

В любом случае сжатие добавляет нагрузку... Ведь все равно надо еще и bitblt делать. Так что ИМХО, вариант [20] оптимальнее...


 
DeadMeat ©   (2004-09-26 13:43) [24]

Как дополнение к [20] можно попробовать усложнить.
Орагнизовать перехват EndPaint (или как она там зовется). При ее вызове отсылать данные из полученного от нее DC... Тогда и не надо BitBlt вообще вызывать...

ЗЫЖ. Это только идея. Не проверенно....


 
PGM_X   (2004-09-27 00:16) [25]

2 _silver: bitblt работает довольно быстро, а сжатие в jpeg довольно долгая процедура. Если не веришь проверь

Любая видеоплата не GeForce и 1280 на 1024 на 32 бита из видеопамяти (!) в обычную и фраза "довольно быстро" не будет казаться правильной. Была конкретная задача и тормоз было именно чтение из памяти при помощи BitBlt. А кодирование в JPEG решается хорошим процессором и чем дальше тем легче :-).


 
Анонимщик ©   (2004-09-27 11:45) [26]

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


 
_silver ©   (2004-09-27 12:37) [27]


> _silver ©   (25.09.04 14:38) [20]

Оптимальнее этого варианта не будет.


 
Nic2   (2004-09-27 15:19) [28]

<<Для информации: чтение из видеопамяти операция на порядки медленне чем запись (на многи картах меряется в 5-6 Мб/с, только GeForce может похвастать приличной скоростью. Так что на тех же ATI лимитирует не сжатие в JPEG, а банальная низкая скорость чтения из памяти. Как раз BitBlt с экрана и будет все тормозить.>>

Заинтересовало меня это, проверил:
У меня машина с Radeon 9000(не про)128М
Проверил у коллеги у нее GeForce FX5200(не ультра)128М

Процы - чистые Pentium(не Celeron-ы): у меня-2,4. У нее - 2,6.
Оперативки по 512.

У меня мать 845, у нее - 848

Результат:
у меня - (как уже писал-7-8 кадров)
у нее - 2-3

По скорости Радик похоже все же круче.
ЗЫ: Это все уже становится интересным...(аж похоже на тесты видях!!!!)


 
PGM_X   (2004-09-27 16:49) [29]

За все GeForce я вероятно поспешил, radeon тоже старый какой-то был. Конкретно у меня: GeForce MX400, Athlon 800, 1024х768х16 = 56 FPS.


 
PGM_X   (2004-09-27 16:50) [30]

Удалено модератором


 
PGM_X   (2004-09-27 16:50) [31]

Удалено модератором


 
PGM_X   (2004-09-27 16:52) [32]

И чего это его утроило?


 
Nic2   (2004-09-27 17:34) [33]

_silver ©   (25.09.04 14:38) [20]

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

Заранее спасибо.


 
_silver ©   (2004-09-27 19:08) [34]

Nic2   (27.09.04 17:34) [33]
Копай исходники WinVNC.
Если не знаешь С могу привести пример на delphi.


 
_silver ©   (2004-09-27 19:19) [35]

1. хук(обязательно в dll) на
WH_CALLWNDPROC
WH_GETMESSAGE
WH_SYSMSGFILTER
далее определяешь какое сообщение пришло
Самое сложное с WM_PAINT
Если WM_PAINT - определяешь координаты с помощью GetRegionData() (не забывая о том что для одного WM_PAINT может изменяться несколько регионов)
далее bitblt
для остальных сообщений - GetWindowRect.
2. ну это совсем уж
Что тебе мешает передать сначала координаты, а потом сам изменившийся кусок?
А потом тотже bitblt.


 
Nic2   (2004-09-27 19:48) [36]

Ну со вторым ступил, согласен....
Спасибо, попробую.


 
Nic2   (2004-10-04 20:06) [37]

Сделал упаковку через ZLibEx. Передаваемые кадры получаются обрезанными сверху  процентов на 20-25 (ну не обрезанные, а вместо полезного изображения черный фон). Может кто сталкивался, в чем прикол?

Заранее спасибо.


 
_silver ©   (2004-10-14 17:41) [38]

Nic2   (04.10.04 20:06) [37]
Так чем тебе

> _silver ©   (27.09.04 19:19) [35][Ответить]

не подходит?


 
GROL   (2004-10-17 01:33) [39]


> _silver ©   (25.09.04 14:38) [20]
> Я делал подобное.

Ловилась всякиая Windows-анимация, ну, тип выезжающее или плавно появляющееся меню, или только конечный результат?


 
_silver ©   (2004-10-18 12:23) [40]

GROL   (17.10.04 1:33) [39]
Зависит от того какие сообщения перехватывать.
Я делал перехват всех сообщений связаных с перерисовкой экрана, в том числе и те которые связаны с перерисовкой выпадающих меню.
Могу привести полный список сообщений которые надо перехватывать.



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

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

Наверх




Память: 0.58 MB
Время: 0.04 c
1-1106220131
BVV
2005-01-20 14:22
2005.02.06
Атрибуты


1-1106650009
гость
2005-01-25 13:46
2005.02.06
ProgressBar в поиске файлов


3-1104926804
Marat
2005-01-05 15:06
2005.02.06
Блокировка сервера


6-1100945155
Sicilla
2004-11-20 13:05
2005.02.06
Несовместимость типов


9-1099585410
MMN
2004-11-04 19:23
2005.02.06
Звуковые и графические файлы