【问题标题】:Media Foundation capture reversed image [duplicate]媒体基金会捕获反转图像[重复]
【发布时间】:2019-08-02 07:29:27
【问题描述】:

这有点奇怪,我正在使用 SourceReader 从我的相机中捕获样本。我最终得到了一个倒置的 HBITMAP。

这里是捕获代码:

for (;;)
{
    DWORD streamIndex = 0, flags = 0;
    LONGLONG llTimeStamp = 0;
    CComPtr<IMFSample> pSample;

    hr = sr->ReadSample(MF_SOURCE_READER_FIRST_VIDEO_STREAM,0,&streamIndex,&flags,&llTimeStamp,&pSample);
...
}

我得到了一个 IMFSample,我正在尝试绘制(目前不是使用 Direct3D,而是使用 Direct2D)。捕获的格式是 MFVideoFormat_NV12,我想将其转换为 MFVideoFormat_RGB32,以便可以从中创建 HBITMAP。因此,我创建了一个 IMFTransform,其源类型设置为从捕获返回的媒体类型,并以 RGB 类型为目标:

if (prvtrs)
{
    DWORD is = 0, os = 0;
    hr = prvtrs->GetStreamCount(&is, &os);
    if (is > 0 && os > 0)
    {
        hr = prvtrs->SetInputType(iids[0], fmt, 0);
        if (SUCCEEDED(hr))
        {
            PROPVARIANT pv;
            InitPropVariantFromCLSID(MFVideoFormat_RGB32, &pv);
            hr = prmt->SetItem(MF_MT_SUBTYPE, pv);
            if (SUCCEEDED(hr))
            {
                hr = prvtrs->SetOutputType(oods[0], prmt, 0);
                if (SUCCEEDED(hr))
                {
// OK
                }
            }
        }
    }
}

捕获后,我转换 IMFSample:

CComPtr<IMFSample> pSample2;
MFCreateSample(&pSample2);

if (si.cbSize == 0)
    prvtrs->GetOutputStreamInfo(oods[0], &si);

CComPtr<IMFMediaBuffer> bb;
MFCreateMemoryBuffer(si.cbSize, &bb);
pSample2->AddBuffer(bb);


hr = prvtrs->ProcessInput(iids[0], pSample, 0);
MFT_OUTPUT_DATA_BUFFER db = { 0 };
db.dwStreamID = oods[0];
db.pSample = pSample2;
DWORD st;
hr = prvtrs->ProcessOutput(0, 1, &db, &st);
if (db.pEvents)
    db.pEvents->Release();
if (SUCCEEDED(hr))
{
    // Show it
    CComPtr<IMFMediaBuffer> b4;
    pSample2->ConvertToContiguousBuffer(&b4);
    if (b4)
    {
        vector<char> o;
        auto bi = SaveSample(b4, wi, he);
....

这是我的 SaveSample:

HBITMAP SaveSample(CComPtr<IMFMediaBuffer> mediaBuffer, int width32, int height32)
{
    HRESULT hr = 0;
    BYTE *pData = NULL;
    DWORD le = 0;
    mediaBuffer->GetCurrentLength(&le);
    hr = mediaBuffer->Lock(&pData, NULL, NULL);
    if (!pData)
        return 0;
    unsigned char*  pixels = pData;
    // at this point we have some input

    BITMAPINFOHEADER bmih;
    bmih.biSize = sizeof(BITMAPINFOHEADER);
    bmih.biWidth = width32;
    bmih.biHeight = height32;
    bmih.biPlanes = 1;
    bmih.biBitCount = 32;
    bmih.biCompression = BI_RGB;
    bmih.biSizeImage = 0;
    bmih.biXPelsPerMeter = 0;
    bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;

    BITMAPINFO dbmi = { 0 };
    dbmi.bmiHeader = bmih;
    dbmi.bmiColors->rgbBlue = 0;
    dbmi.bmiColors->rgbGreen = 0;
    dbmi.bmiColors->rgbRed = 0;
    dbmi.bmiColors->rgbReserved = 0;

    HDC hdc = ::GetDC(NULL);
    HBITMAP hbmp = CreateDIBitmap(hdc, &bmih, CBM_INIT, pixels, &dbmi, DIB_RGB_COLORS);
    ::ReleaseDC(NULL, hdc);

    mediaBuffer->Unlock();
    return hbmp;
}

我得到的是一个颠倒的位图。我做错了什么?

【问题讨论】:

    标签: winapi ms-media-foundation gdi


    【解决方案1】:

    你错过了specification of BMP files 的关键部分:

    像素数组是一个 32 位 DWORD 块,逐个像素地描述图像。 通常像素是“自下而上”存储的,从左下角开始,从左到右,然后逐行从图像的底部到顶部。[4] 除非 BITMAPCOREHEADER使用时,未压缩的 Windows 位图也可以从上到下存储,当 Image Height 值为负时。

    考虑到这一点,您可以轻松修复错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多