BitBlt - более быстрый аналог

269
25 июля 2017, 19:09

Реализую запись видео с экрана. Требуемый fps - не ниже 50. К сожалению, с использованием BitBlt такого результата не достичь (20 ms на все "телодвижения", у меня выполняется за 30-40 ms).

Я, конечно, понимаю, что эта функция годы проходила оптимизацию, выполняется практически самим драйвером устройства (ну, как я прочитал в одном из обсуждений подобного вопроса на другом ресурсе), но реально нужно что-то побыстрее. Желательно без сторонних библиотек конечно же.

BITMAP GetScreenshort()
{
    auto start = std::chrono::high_resolution_clock::now();
    HBITMAP hbtmScreen;
    BITMAP bmp;
    HDC hdcScreen = GetDC(NULL);
    HDC hdcCompatible = CreateCompatibleDC(hdcScreen);
    int height = GetDeviceCaps(hdcScreen, VERTRES);
    int width = GetDeviceCaps(hdcScreen, HORZRES);
    hbtmScreen = CreateCompatibleBitmap(hdcScreen, width, height);
    SelectObject(hdcCompatible, hbtmScreen);
    BitBlt(hdcCompatible, 0, 0, width, height, hdcScreen, 0, 0, SRCCOPY);
    CURSORINFO cinfo;
    ZeroMemory(&cinfo, sizeof(CURSORINFO));
    cinfo.cbSize = sizeof(CURSORINFO);
    GetCursorInfo(&cinfo);
    DrawIconEx(hdcCompatible, cinfo.ptScreenPos.x, cinfo.ptScreenPos.y, cinfo.hCursor, 0, 0, 0, NULL, DI_NORMAL);
    GetObject(hbtmScreen, sizeof BITMAP, &bmp);
    DeleteDC(hdcScreen);
    DeleteDC(hdcCompatible);
    auto finish = std::chrono::high_resolution_clock::now();
    std::cout << "Time: " << std::chrono::duration_cast<std::chrono::microseconds>(finish - start).count() << std::endl;
    return bmp;
}
Answer 1

Для более точной картины, Вам надо делать не единичный замер скорости, а усредненный замер на серии экспериментов.

Например, можно вынести код замеров в отдельный поток, в котором бесконечно вызывать BitBlt. Но, думаю, Вы будете замерять по сути скорость работы Ваших модулей RAM.

Скорость работы BitBlt будет зависеть от формата и разрешения картинки, которую Вы таким образом копируете. Вот к примеру у меня 1920x1080, 32bit, т.е. 8Мб на каждый растр. Учитывая пиковую скорость моей RAM (PC3-14200) копирование 8мб займет 563мкс, в идеальных условиях, конечно же.

Вот тут человек делал аналогичные замеры: How to make BitBlt faster (for copying screen)?. И у него выходило 4-20мс. Опять же, это зависит от многих факторов.

Т.е., когда Вы пишете: "Требуемый fps - не ниже 50", учитывайте еще разрешение, глубину цвета, скорость Вашей RAM. Вполне возможно, что Вас устроит какой-то компромисс между всеми этими зависимостями.

READ ALSO
Как &ldquo;правильнее&rdquo; работать с QMap C++

Как “правильнее” работать с QMap C++

Как лучше писать так:

199
class Point c++

class Point c++

Существует ли класс или структура Point (точка) в stl или её аналог?

252
Как написать InputIterator?

Как написать InputIterator?

Есть некоторый генератор, который выдает значенияЕго интерфейс описывается тремя функциями:

277
Как получит HWND окна при наведении на него курсора мыши?

Как получит HWND окна при наведении на него курсора мыши?

Как получить HWND окна при наведении на него курсора мыши С++ WinApi32 или Qt?

233