Поделиться через


Отображение точечных рисунков, предоставленных приложением, на составном изображении

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует, чтобы новый код использовал MediaPlayer, IMFMediaEngine и аудио- и видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, использующий устаревшие API, чтобы по возможности использовать новые API.]

Приложения могут использовать режим смешивания VMR для отображения логотипов канала альфа-смешивания, пользовательского интерфейса или рекламы частично или полностью в виде видео прямоугольника. Поскольку смешивание выполняется графическим процессором на оборудовании, это минимально влияет на производительность воспроизведения видеопотока, и нет обнаруживаемых мерцания или разрыва артефактов. Приложения могут изменять отображаемое изображение так часто, как они хотят. Следует отметить, что изменения отражаются на экране только в том случае, если граф фильтра DirectShow находится в состоянии выполнения.

VMR использует компонент микшера для наложения растрового изображения на составное изображение. При использовании VMR-7 приложение должно принудительно загрузить виртуальную машину для микшера, даже если есть только один видеопоток. Это необязательно для VMR-9, так как по умолчанию загружается миксер.

Чтобы смешать статическое растровое изображение с видеопотоком, приложение создает VMR и добавляет его в граф, а затем вызывает IVMRFilterConfig::SetNumberOfStreams. Значение, передаваемое этой функции, определяет количество входных контактов, которые должен создать VMR. Приложения могут указывать любое значение от 1 до MAX_MIXER_STREAMS; Указание значения 1 является допустимым, если приложение намерено отображать только один видеопоток. Несмотря на то, что VMR-7 по умолчанию имеет один входной контакт, этот метод необходимо вызвать для принудительной загрузки компонента микшера. (VMR-9 загружает свой микшер и настраивает четыре контакта по умолчанию.)

Чтобы задать растровое изображение, используйте интерфейс IVMRMixerBitmap в VMR-7 или интерфейс IVMRMixerBitmap9 на VMR-9.

Растровое изображение может быть задано дескриптором контекста устройства GDI (hDC) или интерфейсом DirectDraw Surface. Если приложение хочет, чтобы изображение содержало внедренную альфа-информацию (также известную как альфа-пиксель), оно должно поместить данные изображения в интерфейс DirectDraw Surface. Это связано с тем, что в настоящее время невозможно разместить альфа-данные для каждого пикселя в контексте устройства GDI. Поверхность DirectDraw должна быть либо RGB32, либо ARGB32, и предпочтительно должна быть поверхностью системной памяти. Не обязательно, чтобы размеры поверхности были мощностью 2.

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

HRESULT BlendApplicationImage( 
  HWND hwndApp,
  IVMRWindowlessControl* pWc,
  HBITMAP hbm
)
{
    LONG cx, cy;
    HRESULT hr;
    hr = pWc->GetNativeVideoSize(&cx, &cy, NULL, NULL);
    if (FAILED(hr))
        return hr;
    
    HDC hdc = GetDC(hwndApp);
    if (hdc == NULL)
    {
        return E_FAIL;
    }
    
    HDC hdcBmp = CreateCompatibleDC(hdc);
    ReleaseDC(hwndApp, hdc);
    
    if (hdcBmp == NULL)
    {
        return E_FAIL;
    }
    
    BITMAP bm;
    if (0 == GetObject(hbm, sizeof(bm), &bm))
    {
        DeleteDC(hdcBmp);
        return E_FAIL;
    }
    
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcBmp, hbm);
    if (hbmOld == 0)
    {
        DeleteDC(hdcBmp);
        return E_FAIL;
    }
    
    VMRALPHABITMAP bmpInfo;
    ZeroMemory(&bmpInfo, sizeof(bmpInfo) );
    bmpInfo.dwFlags = VMRBITMAP_HDC;
    bmpInfo.hdc = hdcBmp;
    
    // Show the entire bitmap in the top-left corner of the video image.
    SetRect(&bmpInfo.rSrc, 0, 0, bm.bmWidth, bm.bmHeight);
    bmpInfo.rDest.left = 0.f;
    bmpInfo.rDest.top = 0.f;
    bmpInfo.rDest.right = (float)bm.bmWidth / (float)cx;
    bmpInfo.rDest.bottom = (float)bm.bmHeight / (float)cy;
    
    // Set the transparency value (1.0 is opaque, 0.0 is transparent).
    bmpInfo.fAlpha = 0.2f;
    
    IVMRMixerBitmap* pBmp;
    hr = pWc->QueryInterface(IID_IVMRMixerBitmap, (LPVOID *)&pBmp);
    if (SUCCEEDED(hr)) 
    {
        pBmp->SetAlphaBitmap(&bmpInfo);
        pBmp->Release();
    }
    
    DeleteObject(SelectObject(hdcBmp, hbmOld));
    DeleteDC(hdcBmp);
    return hr;
}

Основные понятия, рассмотренные в этом разделе, демонстрируются в примере приложения VMRPlayer .

Создание простых анимаций с помощью растрового изображения

Чтобы создать простой анимированный точечный логотип, поместите все "кадры" растрового рисунка в одно изображение, как показано на следующем рисунке.

Полоса образа vmr

При первоначальном задании растрового изображения с помощью IVMRMixerBitmap::SetAlphaBitmap, если растровое изображение находится в HDC, задайте поле rSrc структуры VMRALPHABITMAP , чтобы указать размер всего растрового изображения в HDC. Верхний и левый элементы структуры имеют значение 0, а правый и нижний элементы — это ширина и высота растрового изображения. Если растровое изображение находится в поверхности DirectDraw, размер поверхности известен, поэтому указывать rSrc в этом методе не нужно.

При вызове IVMRMixerBitmap::UpdateAlphaBitmapParameters используйте член rSrc для растровых изображений HDC и DirectDraw, чтобы указать конкретный кадр или прямоугольник в изображении, которое требуется отобразить, и установить флаг VMRBITMAP_SRCRECT в элементе dwFlags .

Использование режима смешивания VMR