0

我正在尝试创建 Directshow virtaul 相机来捕获桌面。
为了创建虚拟相机,我使用了现有的https://github.com/roman380/tmhare.mvps.org-vcam
为了添加桌面捕获而不是随机数据,我从Microsofts Push Source Filters Sample获得了帮助

桌面捕获推送源过滤器的确切源代码位于
https://github.com/roman380/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/directshow/filters/pushsource/PushSourceDesktop.cpp

我正在初始化媒体类型的输出引脚构造函数是

CVCamStream::CVCamStream(HRESULT *phr, CVCam *pParent, LPCWSTR pPinName) :
    CSourceStream(NAME("Virtual Cam"),phr, pParent, pPinName),
    m_pParent(pParent),
    m_iFrameNumber(0),
    m_rtFrameLength(FPS_5), // Capture and display desktop 5 times per second
    m_nCurrentBitDepth(32)
{
    // Set the default media type to higest quality
    GetMediaType(0, &m_mt);

    // Get the device context of the main display
    HDC hDC;
    hDC = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL);

    // Get the dimensions of the main desktop window
    m_rScreen.left = m_rScreen.top = 0;
    m_rScreen.right = GetDeviceCaps(hDC, HORZRES);
    m_rScreen.bottom = GetDeviceCaps(hDC, VERTRES);

    // Save dimensions for later use in FillBuffer()
    m_iImageWidth = m_rScreen.right - m_rScreen.left;
    m_iImageHeight = m_rScreen.bottom - m_rScreen.top;

    // Release the device context
    DeleteDC(hDC);
}

HRESULT GetMediaType(int iPosition, CMediaType *pmt);

HRESULT CVCamStream::GetMediaType(int iPosition, CMediaType *pmt)
{
    CheckPointer(pmt, E_POINTER);
    CAutoLock cAutoLock(m_pFilter->pStateLock());

    if (iPosition < 0)
        return E_INVALIDARG;

    // Have we run off the end of types?
    if (iPosition > 4)
        return VFW_S_NO_MORE_ITEMS;

    VIDEOINFO* pvi = (VIDEOINFO*)pmt->AllocFormatBuffer(sizeof(VIDEOINFO));
    if (NULL == pvi)
        return(E_OUTOFMEMORY);

    // Initialize the VideoInfo structure before configuring its members
    ZeroMemory(pvi, sizeof(VIDEOINFO));

    switch (iPosition)
    {
    case 0:
    {
        // Return our highest quality 32bit format

        // Since we use RGB888 (the default for 32 bit), there is
        // no reason to use BI_BITFIELDS to specify the RGB
        // masks. Also, not everything supports BI_BITFIELDS
        pvi->bmiHeader.biCompression = BI_RGB;
        pvi->bmiHeader.biBitCount = 32;
        break;
    }

    case 1:
    {   // Return our 24bit format
        pvi->bmiHeader.biCompression = BI_RGB;
        pvi->bmiHeader.biBitCount = 24;
        break;
    }

    case 2:
    {
        // 16 bit per pixel RGB565

        // Place the RGB masks as the first 3 doublewords in the palette area
        for (int i = 0; i < 3; i++)
            pvi->TrueColorInfo.dwBitMasks[i] = bits565[i];

        pvi->bmiHeader.biCompression = BI_BITFIELDS;
        pvi->bmiHeader.biBitCount = 16;
        break;
    }

    case 3:
    {   // 16 bits per pixel RGB555

        // Place the RGB masks as the first 3 doublewords in the palette area
        for (int i = 0; i < 3; i++)
            pvi->TrueColorInfo.dwBitMasks[i] = bits555[i];

        pvi->bmiHeader.biCompression = BI_BITFIELDS;
        pvi->bmiHeader.biBitCount = 16;
        break;
    }

    case 4:
    {   // 8 bit palettised

        pvi->bmiHeader.biCompression = BI_RGB;
        pvi->bmiHeader.biBitCount = 8;
        pvi->bmiHeader.biClrUsed = iPALETTE_COLORS;
        break;
    }
    }

    // Adjust the parameters common to all formats
    pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    pvi->bmiHeader.biWidth = m_iImageWidth;
    pvi->bmiHeader.biHeight = m_iImageHeight;
    pvi->bmiHeader.biPlanes = 1;
    pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
    pvi->bmiHeader.biClrImportant = 0;

    SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
    SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle

    pmt->SetType(&MEDIATYPE_Video);
    pmt->SetFormatType(&FORMAT_VideoInfo);
    pmt->SetTemporalCompression(FALSE);

    // Work out the GUID for the subtype from the header info.
    const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
    pmt->SetSubtype(&SubTypeGUID);
    pmt->SetSampleSize(pvi->bmiHeader.biSizeImage);

    return NOERROR;
}

我在 google meet 上试过这个虚拟相机,它工作正常,它显示我的桌面,但视频质量很差

在此处输入图像描述

这个模糊视频的原因是什么,我该如何解决这个问题?

4

0 回答 0