我正在尝试创建 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 上试过这个虚拟相机,它工作正常,它显示我的桌面,但视频质量很差
这个模糊视频的原因是什么,我该如何解决这个问题?