在Windows 8 Media Foundation Transform中绘制IMFMediaBuffer上的文本

时间:2012-08-05 03:49:15

标签: windows visual-c++ graphics directx ms-media-foundation

您如何在IMFMediaBuffer对象上绘制文本,并将其写入另一个IMFMediaBuffer对象?

上下文是我正在构建一个MFT,最初我尝试使用Direct2D和Direct3D11来实现这一目标,但无济于事。

1 个答案:

答案 0 :(得分:2)

我能够通过Windows GDI调用完成此操作。我创建的MFT具有RGB32输入/输出类型,允许我复制到Bitmap对象/从Bitmap对象复制。我将要覆盖文本的框架的一部分复制到我创建的Windows位图中,绘制文本,然后复制回IMFMediaBuffer。这是我的代码:

#define BREAK_ON_FAIL(val) { if ( FAILED(hr = (val)) ) { break; } }

HRESULT AddOverlay(IMFSample* pSample)
{
    HRESULT hr = S_OK;
    IMFMediaBuffer * pBuffer;
    HDC hDC, hMemDC;
    HBITMAP hBitmap, hOldBitmap;

    do
    {
        BYTE * pBufferData;
        UINT32 nWidth, nHeight;
        BITMAPV5HEADER bi;
        BYTE * pBitmapData;
        UINT32 nXOffset, nYOffset;
        RECT OverlayRect;
        OverlayRect.left = 0;
        OverlayRect.top = 0;
        OverlayRect.right = 400;
        OverlayRect.bottom = 32;
        DWORD nOverlayWidth = OverlayRect.right - OverlayRect.left;
        DWORD nOverlayHeight = OverlayRect.bottom - OverlayRect.top;
        LONG lFrameStride;

        // Get the frame dimensions and stride
        MFGetAttributeSize(m_pInputType, MF_MT_FRAME_SIZE, &nWidth, &nHeight);
        m_pInputType->GetUINT32(MF_MT_DEFAULT_STRIDE, (UINT32*)&lFrameStride))

        // Setup offset for the overlay area into the video frame
        nXOffset = (nWidth - nOverlayWidth) / 2;
        nYOffset = nOverlayHeight-1;

        // Set up the bitmap header
        ZeroMemory(&bi, sizeof(BITMAPV5HEADER));
        bi.bV5Size          = sizeof(BITMAPV5HEADER);
        bi.bV5Width         = nOverlayWidth;
        // If the stride is negative, the bitmap is bottom-up, which is designated by a negative height
        bi.bV5Height        = (lFrameStride > 0) ? nOverlayHeight : -(LONG)nOverlayHeight;
        bi.bV5Planes        = 1;
        bi.bV5BitCount      = 32;
        bi.bV5Compression   = BI_RGB;
        // The following mask specification specifies a supported 32 BPP
        // alpha format for Windows XP.
        bi.bV5RedMask       = 0x00FF0000;
        bi.bV5GreenMask     = 0x0000FF00;
        bi.bV5BlueMask      = 0x000000FF;
        bi.bV5AlphaMask     = 0xFF000000;

        // Create a DIB section with an alpha channel, along with
        // a memory device context
        hDC = GetDC(NULL);
        hBitmap = CreateDIBSection(hDC, (BITMAPINFO*)&bi, DIB_RGB_COLORS, (void**)&pBitmapData, NULL, 0);
        hMemDC = CreateCompatibleDC(hDC);
        ReleaseDC(NULL, hDC);

        // Lock the media buffer for our use
        BREAK_ON_FAIL( pSample->GetBufferByIndex(0, &pBuffer) );
        BREAK_ON_FAIL( pBuffer->Lock(&pBufferData, NULL, NULL) );

        // Copy the video frame to the bitmap (to support transparency)
        MFCopyImage(pBitmapData, nOverlayWidth*sizeof(RGBQUAD),
            pBufferData + nYOffset*abs(lFrameStride) + nXOffset*sizeof(RGBQUAD), lFrameStride,
            nOverlayWidth*sizeof(RGBQUAD), nOverlayHeight);

        // Draw on the bitmap
        hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
        //FillRect(hMemDC, &OverlayRect, WHITE_BRUSH);
        SetTextColor(hMemDC, RGB(255,0,0));
        SetBkMode(hMemDC, TRANSPARENT);
        DrawText(hMemDC, _T("Hello World!"), 12, &OverlayRect, DT_CENTER);
        SelectObject(hMemDC, hOldBitmap);

        // Copy the bitmap to the buffer
        MFCopyImage(pBufferData + nYOffset*abs(lFrameStride) + nXOffset*sizeof(RGBQUAD), lFrameStride,
            pBitmapData, nOverlayWidth*sizeof(RGBQUAD),
            nOverlayWidth*sizeof(RGBQUAD), nOverlayHeight);

        BREAK_ON_FAIL( pBuffer->Unlock() );

    } while(false);

    DeleteDC(hMemDC);
    DeleteObject(hBitmap);
    SafeRelease(&pBuffer);

    return hr;
}

参考文献: