I am trying to create Directshow virtaul camera to capture desktop.
For creating virtual camera I used existing https://github.com/roman380/tmhare.mvps.org-vcam
For adding desktop capturing instead of random data I took help from Microsofts Push Source Filters Sample
Exact source code for Desktop capturing Push source Filter is at
https://github.com/roman380/Windows-classic-samples/blob/master/Samples/Win7Samples/multimedia/directshow/filters/pushsource/PushSourceDesktop.cpp
My output pin constructor which is initializing Media Type is
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);
is
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;
}
I tried this virtual camera on google meet and its working fine, its showing my desktop but video quality is very poor
What is reason of this blur video and How can I fix this?