Desktop Video Capturing
Модераторы: Duncon, Hawk, Romeo, Eugie
Здравствуйте!
Пытаюсь создать некоторый аналог RAdmin, но никак не могу найти способ быстрого захвата текущей картинки рабочего стола. Все известные мне методы требуют слишком много времени на один кадр.
На данный момент мне известны 3 способа захвата картинки с рабочего стола:
1) Классика: GetDC(0); CreateCompatibleBitmap(); BitBlt(). Не годится, т.к. нужно минимум 100ms на захват одного кадра.
2) DirectX: g_pd3dDevice->GetFrontBufferData(); не годится по той же причине... (MSDN: very slow by design...)
3) слегка извращенный метод, но быстрый, хотя и глючный: ставится Hmelov Screen Capture Driver, который эмулирует веб-камеру, в видеопотоке которой и идут кадры рабочего стола. Достаточно подключиться к этому потоку и хватать кадры. Работает невероятно быстро, но грузит проц на 50-100%, т.к. требует окна для Preview, т.е. постоянно идет ненужный рендеринг, на некоторых компах очень криво работает, и не переваривает 16-битный цвет.
При этом существует много программ, которые быстро и безглючно берут кадры со стола: vuCamera, RAdmin,...,...,...
как?
Буду очень признателен за любую помощь, идею, совет. Всем спасибо!
Пытаюсь создать некоторый аналог RAdmin, но никак не могу найти способ быстрого захвата текущей картинки рабочего стола. Все известные мне методы требуют слишком много времени на один кадр.
На данный момент мне известны 3 способа захвата картинки с рабочего стола:
1) Классика: GetDC(0); CreateCompatibleBitmap(); BitBlt(). Не годится, т.к. нужно минимум 100ms на захват одного кадра.
2) DirectX: g_pd3dDevice->GetFrontBufferData(); не годится по той же причине... (MSDN: very slow by design...)
3) слегка извращенный метод, но быстрый, хотя и глючный: ставится Hmelov Screen Capture Driver, который эмулирует веб-камеру, в видеопотоке которой и идут кадры рабочего стола. Достаточно подключиться к этому потоку и хватать кадры. Работает невероятно быстро, но грузит проц на 50-100%, т.к. требует окна для Preview, т.е. постоянно идет ненужный рендеринг, на некоторых компах очень криво работает, и не переваривает 16-битный цвет.
При этом существует много программ, которые быстро и безглючно берут кадры со стола: vuCamera, RAdmin,...,...,...
как?
Буду очень признателен за любую помощь, идею, совет. Всем спасибо!
Radmin использует свой драйвер на основе технологии Video Hook Driver (mirror drivers), т.е. перехватывает отрисовку на уровне ядра OC. Это гораздо экономичнее, т.к. пересылаются только реальные изменения на экране: для не-media приложений картинка практически статична. Наверняка еще и сжатие при передаче видеопотока применяют.
См. также
http://msdn2.microsoft.com/en-us/library/ms797878.aspx
http://msdn2.microsoft.com/en-us/library/ms791672.aspx (src\video Sample display drivers and a mirroring driver)
http://www.demoforge.com/dfmirage.htm (здесь можно скачать бесплатный VHD)
http://serotek.com/mirror-driver-paper.html (другой подход)
См. также
http://msdn2.microsoft.com/en-us/library/ms797878.aspx
http://msdn2.microsoft.com/en-us/library/ms791672.aspx (src\video Sample display drivers and a mirroring driver)
http://www.demoforge.com/dfmirage.htm (здесь можно скачать бесплатный VHD)
http://serotek.com/mirror-driver-paper.html (другой подход)
Огромное спасибо! Ответ исчерпывающий. осталось разобраться, как это работает ) Но это уже не проблема. Спасибо!!
А чем DirectDraw не устраивает. Я вот щас для интереса решил замерить... Код очень простой, разрешение экрана 1024х768х32, захват кадра за 45-50М тактов, что составляет примерно 18-20 мс.
It's a long way to the top if you wanna rock'n'roll
somewhere, а как это сделать через DirectDraw? подскажите, пожалуйста. Попытался захватывать через Mirror Drivers - выяснилось, что не работает захват DirectX&OpenGL, а именно это и нужно...
Так тебе на каком языке?
С DirectDraw (далее ДД) много ньюансов - скорость передачи зависит в основном от возможностей адаптера и драйверов. На той машине, на которой разрабатывалась демка стоит Radeon X1950XT - соответственно имеет аппаратные преобразования BitBlT и передачу посредством DMA. Скорость захвата скриншотов на нем достигала 50-60 кадров/сек. На работе старушка NVidia Vanta 8M - доступ к видеопамяти (первичной поверхности ДД) очень медленный. Без использования Blt захват всего экрана за 150-200 мс. Примерно такой же результат дает RAdmin подключенный к самому себе на этой тачке, хотя немного быстрее. Если переносить вручную через move из указателя lpSurface быстрее никак все-равно не получается - т.е. здесь скорость ограничивается на аппаратном уровне. Если покопаешься с ДД наверняка найдешь способ передачи только изменившигося куска памяти посредством масок AND или XOR через BitBlT опции. Не говорю что демка оптимальна по быстродействию но всеже работает неплохо. Удивительно то, что запись напрямую в видеопамять почти на всех тестированых тачках быстрее раз в 10. Если что не понятно, спрашивай.
Да, и еще - скачай оснастку для DirectDraw для того языка, на котором пишешь. Демку отправлю по почте, так как здесь не влезает.
С DirectDraw (далее ДД) много ньюансов - скорость передачи зависит в основном от возможностей адаптера и драйверов. На той машине, на которой разрабатывалась демка стоит Radeon X1950XT - соответственно имеет аппаратные преобразования BitBlT и передачу посредством DMA. Скорость захвата скриншотов на нем достигала 50-60 кадров/сек. На работе старушка NVidia Vanta 8M - доступ к видеопамяти (первичной поверхности ДД) очень медленный. Без использования Blt захват всего экрана за 150-200 мс. Примерно такой же результат дает RAdmin подключенный к самому себе на этой тачке, хотя немного быстрее. Если переносить вручную через move из указателя lpSurface быстрее никак все-равно не получается - т.е. здесь скорость ограничивается на аппаратном уровне. Если покопаешься с ДД наверняка найдешь способ передачи только изменившигося куска памяти посредством масок AND или XOR через BitBlT опции. Не говорю что демка оптимальна по быстродействию но всеже работает неплохо. Удивительно то, что запись напрямую в видеопамять почти на всех тестированых тачках быстрее раз в 10. Если что не понятно, спрашивай.
Да, и еще - скачай оснастку для DirectDraw для того языка, на котором пишешь. Демку отправлю по почте, так как здесь не влезает.
It's a long way to the top if you wanna rock'n'roll
Спасибо за пример! и за разъяснения. Язык не принципиален, разобраться можно в любом.
Я подозревал, что это зависит от железа.. но не на чем было попробовать в тот момент. Но вышеупомянутый Hmelyoff SC driver захватывает экран на скорости 30+ FPS, при этом bitblt работает 100-120 ms. Еще заметил, что bitblt c экрана на контекст любого окна работает очень быстро, раз в 5 быстрее, чем bitblt в битмап (CreateCompatibleBitmap()), видимо там идет операция копирования напрямую из видеопамяти в видеопамять без передачи в оперативку. Попробую DDraw, - может быть будет немного быстрее, и попробую как-то искать фрагменты изменившейся памяти.... Спасибо за подсказку!
Я подозревал, что это зависит от железа.. но не на чем было попробовать в тот момент. Но вышеупомянутый Hmelyoff SC driver захватывает экран на скорости 30+ FPS, при этом bitblt работает 100-120 ms. Еще заметил, что bitblt c экрана на контекст любого окна работает очень быстро, раз в 5 быстрее, чем bitblt в битмап (CreateCompatibleBitmap()), видимо там идет операция копирования напрямую из видеопамяти в видеопамять без передачи в оперативку. Попробую DDraw, - может быть будет немного быстрее, и попробую как-то искать фрагменты изменившейся памяти.... Спасибо за подсказку!

Если экран будет постоянно изменятся (полноэкранное видео без оверлеев) я не думаю что будет достигнута такая скорость, т.к. есть подозрения что передаются только изменения экрана, т.к. выше железа не прыгнешь :-)" писал(а):Но вышеупомянутый Hmelyoff SC driver захватывает экран на скорости 30+ FPS
Не в 5, а гораздо больше. Из видеопамять в видеопамять BltFast копирует весь экран за 2-3 мс." писал(а):Еще заметил, что bitblt c экрана на контекст любого окна работает очень быстро, раз в 5 быстрее, чем bitblt в битмап
Мне тут пришла в голову одна идея, как примерно передавать не весь экран а только изменившуюся часть. Примерно по той схеме, по которой я реализовывал сравнение двух картинок. Идея такая:
Первоначально считаем что мы уже захватили один кадр.
1. Условно экран разбивается на блоки 8х8 (можно выбрать любой другой размер, главное чтобы их умещалось ровное число, т.е. ширина и высота кратны сторонам блока) - т.е. при 1024х768 получим 128х96 блоков.
2. Выполняем StretchBitBlt (а лучше и быстрее IDirectDraw7.Blt) основной поверхности в дополнительную поверхность видеопамяти с размерами 128х96. Операция займет очень мало времени. Т.с. создание миниатюры.
3. Переносим из этой поверхности в системную память. Т.к. переносим в 64 раза меньше, операция выполняется в 64 раза быстрее. У нас уже есть миниатюра от предыдущего кадра, выполняем сравнение блоков(пикселей) - если отличаются, то данный блок необходимо захватить.
4. Переносим отмеченные блоки из основной поверхности в предыдущий битмап - получаем таким образом новый скриншот.
Переносить блоки 8х8 можно операцией BltBatch - по возможности видеокарты они перенесутся быстрее.
В теории изменение цвета хотя бы одного пикселя в блоке 8х8 повлияет на пиксель в миниатюре.
Попробую реализовать сегодня, если что о результатах сообщу.
It's a long way to the top if you wanna rock'n'roll
отличная идея, я тоже попробую
только у меня задача проще - мне и нужен мини-экран, где-то 192х144. Можно даже обойтись без сравнения и захвата основных блоков. Спасибо!

Что же ты раньше молчал? - тогда совсем проблем не будет. Нужно всего-то сделать
1. DirectDraw7.Blt (Stretch) до нужных размеров из основной поверхности в дополнительную, главное чтобы она была в видеопамяти.
2. BitBlt с контекста дополнительной в контекст битмапа. И все!!!
Настоятельно рекомендую делать именно так, потому что если видеокарта на аппаратном уровне не умеет делать Stretch из VM в SM - то будет оччччень медленно.
В понедельник могу показать как, щас под рукой ничего нет.
1. DirectDraw7.Blt (Stretch) до нужных размеров из основной поверхности в дополнительную, главное чтобы она была в видеопамяти.
2. BitBlt с контекста дополнительной в контекст битмапа. И все!!!
Настоятельно рекомендую делать именно так, потому что если видеокарта на аппаратном уровне не умеет делать Stretch из VM в SM - то будет оччччень медленно.
В понедельник могу показать как, щас под рукой ничего нет.
It's a long way to the top if you wanna rock'n'roll