将位图设置为IMediaSample

时间:2017-03-22 09:18:45

标签: c++ directshow

例如,IMediaSample由随机数据填充以测试DirectShow视频源过滤器:

HRESULT CVCamStream::FillBuffer(IMediaSample *pms)
{
    REFERENCE_TIME rtNow;
    REFERENCE_TIME avgFrameTime = ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame;

    rtNow = m_rtLastTime;
    m_rtLastTime += avgFrameTime;
    pms->SetTime(&rtNow, &m_rtLastTime);
    pms->SetSyncPoint(TRUE);

    BYTE *pData;
    long lDataLen;
    pms->GetPointer(&pData);
    lDataLen = pms->GetSize();
    for(int i = 0; i < lDataLen; ++i) pData[i] = rand();
}

相反,我想用从文件系统加载的位图填充缓冲区,这就是我正在尝试做的事情:

AM_MEDIA_TYPE *mt;
HRESULT hr;
hr = pms->GetMediaType(&mt);
if (FAILED(hr)) return hr;

VIDEOINFOHEADER *pVih;
if ((mt->formattype == FORMAT_VideoInfo) &&
    (mt->cbFormat >= sizeof(VIDEOINFOHEADER)) &&
    (mt->pbFormat != NULL))
{
    pVih = (VIDEOINFOHEADER*)mt->pbFormat;
}
else
{
    FreeMediaType(*mt);
    return VFW_E_INVALIDMEDIATYPE;
}

DWORD dwBmpSize = ((640 * 3 + 31) / 32) * 4 * 480; // 640x480x24bit
HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
char *lpbitmap = (char *)GlobalLock(hDIB);
HBITMAP hBMP = (HBITMAP)LoadImage(NULL, "path/to/my/image.png", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HDC hdc = GetDC(NULL);
GetDIBits(hdc, hBMP, 0, 480, lpbitmap, (BITMAPINFO*)&pVih->bmiHeader, DIB_RGB_COLORS);

SetDIBitsToDevice(
    hdc, 0, 0,
    pVih->bmiHeader.biWidth,
    pVih->bmiHeader.biHeight,
    0, 0,
    0,
    pVih->bmiHeader.biHeight,
    lpbitmap,
    (BITMAPINFO*)&pVih->bmiHeader,
    DIB_RGB_COLORS
);

但是当我用Skype尝试它时只是崩溃...... 关于上面代码的任何提示,我应该如何调试这样的过滤器?

1 个答案:

答案 0 :(得分:1)

这里是使用位图填充IMediaSample的工作代码:

HRESULT CVCamStream::FillBuffer(IMediaSample *pms)
{
    REFERENCE_TIME rtNow;
    REFERENCE_TIME avgFrameTime = ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame;

    rtNow = m_rtLastTime;
    m_rtLastTime += avgFrameTime;
    pms->SetTime(&rtNow, &m_rtLastTime);
    pms->SetSyncPoint(TRUE);

    BYTE *pData;
    long lDataLen;
    pms->GetPointer(&pData);
    lDataLen = pms->GetSize();

    HDC hdc = GetDC(NULL);
    HBITMAP hBmp = (HBITMAP)LoadImage(NULL, "path/to/image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    BITMAP bmp;
    GetObject(hBmp, sizeof(BITMAP), &bmp);

    BITMAPINFOHEADER bi;

    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = bmp.bmWidth;
    bi.biHeight = bmp.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = 24;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrUsed = 0;
    bi.biClrImportant = 0;

    DWORD dwBmpSize = ((bmp.bmWidth * bi.biBitCount + 31) / 32) * 4 * bmp.bmHeight;
    HANDLE hDIB = GlobalAlloc(GHND, dwBmpSize);
    char *lpbitmap = (char *)GlobalLock(hDIB);

    GetDIBits(hdc, hBmp, 0, (UINT)bmp.bmHeight, lpbitmap, (BITMAPINFO *)&bi, DIB_RGB_COLORS);
    memcpy(pData, lpbitmap, lDataLen);

    return NOERROR;
} // FillBuffer