Directshow 虚拟相机中的模糊桌面捕获输出

问题描述

我正在尝试创建 Directshow 虚拟相机来捕获桌面。
为了创建虚拟相机,我使用了现有的 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

我正在初始化 output pinMedia Type 构造函数是

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);

    // 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 上试过这个虚拟摄像头,它工作正常,显示我的桌面但视频质量很差

enter image description here

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

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...