在Windows 8 Media Foundation转换中在IMFMediaBuffer上绘制文本

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

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

Solutions Collecting From Web of "在Windows 8 Media Foundation转换中在IMFMediaBuffer上绘制文本"

我可以用Windows GDI调用完成这个任务。 我创建的MFT具有RGB32输入/输出类型,这使我可以复制到/从一个位图对象。 我将我想叠加文本框架的部分复制到我创建的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; } 

参考文献: