📄 grabberds.cpp
字号:
hr = m_DSI_GB->QueryInterface(IID_IMediaSeeking, (void**)&m_DSI_MS);
if(FAILED(hr))
goto L_ERR;
hr = S_OK;
goto L_EXIT;
L_ERR:
ReleaseDShow();
L_EXIT:
return hr;
}
//
virtual HRESULT __fastcall RenderVideoCaptureSource(LPCWSTR szName)
{
HRESULT hr;
IPin *Pin = NULL;
// Get the interface for DirectShow's GraphBuilder
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (VOID **)&m_DSI_GB);
if(FAILED(hr))
{
if(hr != CO_E_NOTINITIALIZED)
goto L_ERR;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
if(FAILED(hr))
goto L_ERR;
co_initialized = TRUE;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (VOID **)&m_DSI_GB);
if(FAILED(hr))
goto L_ERR;
}
hr = m_DSI_GB->QueryInterface(IID_IFilterGraph2, (void**)&m_DSI_FG);
if(FAILED(hr))
goto L_ERR;
hr = FindVideoCaptureSource(szName, &m_DSI_BF_source);
if(FAILED(hr))
goto L_ERR;
hr = m_DSI_GB->AddFilter(m_DSI_BF_source, L"Video Capture Source");
if(FAILED(hr))
goto L_ERR;
vR = (IBaseFilter*)this;
vR->AddRef();
hr = m_DSI_GB->AddFilter(vR, L"V-Renderer");
if(FAILED(hr))
goto L_ERR;
hr = FindPinByCategory(m_DSI_BF_source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
if(FAILED(hr))
goto L_EXIT;
if(capture_subtype != GUID_NULL)
{
IAMStreamConfig *cfg;
if(SUCCEEDED(Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg)))
{
AM_MEDIA_TYPE *pmt;
if(SUCCEEDED(cfg->GetFormat(&pmt)))
{
BITMAPINFOHEADER *pBih = NULL;
REFERENCE_TIME avg_time_per_frame = (__int64)(10000000.0f / (float)capture_fps + 0.5f);
if(pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmt->pbFormat);
pVih->AvgTimePerFrame = avg_time_per_frame;
pBih = &(pVih->bmiHeader);
pVih->dwBitRate = 0;
}
else
if(pmt->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmt->pbFormat);
pVih2->AvgTimePerFrame = avg_time_per_frame;
pVih2->dwBitRate = 0;
pVih2->dwInterlaceFlags = 0;
pVih2->dwPictAspectRatioX = capture_sz.cx;
pVih2->dwPictAspectRatioY = capture_sz.cy;
pVih2->dwControlFlags = 0;
pBih = &(pVih2->bmiHeader);
}
if(pBih)
{
ZeroMemory(pBih, sizeof(BITMAPINFOHEADER));
pBih->biSize = sizeof(BITMAPINFOHEADER);
pBih->biWidth = capture_sz.cx;
pBih->biHeight = capture_sz.cy;
if((capture_subtype == MEDIASUBTYPE_RGB32) ||
(capture_subtype == MEDIASUBTYPE_ARGB32))
pBih->biBitCount = 32;
else
if(capture_subtype == MEDIASUBTYPE_RGB24)
pBih->biBitCount = 24;
else
if((capture_subtype == MEDIASUBTYPE_RGB555) ||
(capture_subtype == MEDIASUBTYPE_RGB565))
pBih->biBitCount = 16;
else
if(capture_subtype == MEDIASUBTYPE_YUY2)
{
pBih->biCompression = MAKEFOURCC('Y', 'U', 'Y', '2');
pBih->biBitCount = 16;
}
else
if(capture_subtype == MEDIASUBTYPE_UYVY)
{
pBih->biCompression = MAKEFOURCC('U', 'Y', 'V', 'Y');
pBih->biBitCount = 16;
}
else
if(capture_subtype == MEDIASUBTYPE_YV12)
{
pBih->biCompression = MAKEFOURCC('Y', 'V', '1', '2');
pBih->biBitCount = 12;
}
else
if(capture_subtype == MEDIASUBTYPE_NV12)
{
pBih->biCompression = MAKEFOURCC('N', 'V', '1', '2');
pBih->biBitCount = 12;
}
pBih->biSizeImage = (pBih->biWidth * pBih->biHeight * pBih->biBitCount) >> 3;
pmt->subtype = capture_subtype;
cfg->SetFormat(pmt);
}
DeleteMediaType(pmt);
}
cfg->Release();
}
}
hr = m_DSI_FG->RenderEx(Pin, AM_RENDEREX_RENDERTOEXISTINGRENDERERS, NULL);
SAFE_RELEASE(Pin);
if(FAILED(hr))
goto L_ERR;
// QueryInterface for DirectShow
hr = m_DSI_GB->QueryInterface(IID_IMediaControl, (void**)&m_DSI_MC);
if(FAILED(hr))
goto L_ERR;
hr = m_DSI_GB->QueryInterface(IID_IMediaSeeking, (void**)&m_DSI_MS);
if(FAILED(hr))
goto L_ERR;
hr = S_OK;
goto L_EXIT;
L_ERR:
ReleaseDShow();
L_EXIT:
return hr;
}
//
virtual void __fastcall SetCallback(vg_callback callback)
{
CVRenderer::callback = callback;
}
//
virtual void __fastcall SetUserObject(void *obj)
{
user_obj = obj;
}
//
virtual void* __fastcall GetUserObject()
{
return user_obj;
}
//
virtual IUnknown* __fastcall GetMediaControl()
{
return m_DSI_MC;
}
//
virtual void __fastcall EnableLoop(BOOL bEnable)
{
if((bEnable) && (!m_hwnd))
{
WNDCLASS wnd;
ZeroMemory(&wnd, sizeof(wnd));
wnd.lpszClassName = "grabber_new";
wnd.lpfnWndProc = WindowProcedure;
RegisterClass(&wnd);
m_hwnd = CreateWindowEx(0, wnd.lpszClassName, "", WS_POPUP,
0, 0, 0, 0, NULL, NULL, NULL, NULL);
SetWindowLong(m_hwnd, GWL_USERDATA, (LONG)this);
}
b_loop_enabled = bEnable;
}
//
virtual void __fastcall SuggestVideoCaptureFormat(const GUID *subtype, SIZE sz, float fps)
{
capture_subtype = *subtype;
capture_sz = sz;
capture_fps = fps;
}
//
virtual HRESULT __fastcall GetVideoCaptureFormat(GUID *subtype, SIZE *sz, float *fps)
{
IPin *Pin = NULL;
IAMStreamConfig *cfg = NULL;
AM_MEDIA_TYPE *pmt = NULL;
HRESULT hr;
if(!m_DSI_BF_source)
{
hr = E_FAIL;
goto L_EXIT;
}
hr = FindPinByCategory(m_DSI_BF_source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
if(FAILED(hr))
goto L_EXIT;
hr = Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg);
if(FAILED(hr))
goto L_EXIT;
hr = cfg->GetFormat(&pmt);
if(FAILED(hr))
goto L_EXIT;
*subtype = pmt->subtype;
BITMAPINFOHEADER *pBih = NULL;
if(pmt->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmt->pbFormat);
*fps = 10000000.0f / (float)pVih->AvgTimePerFrame;
pBih = &(pVih->bmiHeader);
}
else
if(pmt->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmt->pbFormat);
*fps = 10000000.0f / (float)pVih2->AvgTimePerFrame;
pBih = &(pVih2->bmiHeader);
}
if(pBih)
{
sz->cx = pBih->biWidth;
sz->cy = pBih->biHeight;
}
hr = S_OK;
L_EXIT:
if(pmt)
DeleteMediaType(pmt);
SAFE_RELEASE(cfg);
SAFE_RELEASE(Pin);
return hr;
}
//
virtual BOOL __fastcall IsVideo()
{
return b_video;
}
//
virtual BOOL __fastcall IsAudio()
{
return b_audio;
}
// Overridables
public:
virtual CBasePin *GetPin(int n)
{
if(!m_pInputPin)
{
HRESULT hr;
m_pInputPin = new CVPin(this, &hr, L"In");
}
return m_pInputPin;
}
//
virtual HRESULT CheckMediaType(const CMediaType *pmt)
{
const GUID *type = pmt->Type();
if(*type != MEDIATYPE_Video)
return E_INVALIDARG;
const GUID *formattype = pmt->FormatType();
if((*formattype != FORMAT_VideoInfo) && (*formattype != FORMAT_VideoInfo2))
return E_INVALIDARG;
const GUID *subtype = pmt->Subtype();
DWORD i;
for(i = 0; i < N_SUBTYPES; i++)
if((subtypes_enabled[i]) && (*subtype == g_subtypes[i]))
break;
if(i >= N_SUBTYPES)
return E_INVALIDARG;
return S_OK;
}
virtual HRESULT DoRenderSample(IMediaSample *pMediaSample)
{
BYTE *pBits = NULL;
HRESULT hr = pMediaSample->GetPointer(&pBits);
if(FAILED(hr))
return hr;
if((!pBits) || (!callback))
return S_FALSE;
if(callback)
hr = (*callback)((IVideoGrabber*)(IVideoGrabberX*)this, pBits);
if(SUCCEEDED(hr))
{
end_of_stream = FALSE;
SetEvent(event);
}
return hr;
}
virtual HRESULT SetMediaType(const CMediaType *pmt)
{
const GUID *subtype = pmt->Subtype();
const GUID *formattype = pmt->FormatType();
if(*formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pVI = (VIDEOINFOHEADER*)pmt->Format();
aspect_x = pVI->bmiHeader.biWidth;
aspect_y = pVI->bmiHeader.biHeight;
memcpy(&bih, &pVI->bmiHeader, sizeof(BITMAPINFOHEADER));
}
else
if(*formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2 *pVI2 = (VIDEOINFOHEADER2*)pmt->Format();
if((aspect_x != pVI2->dwPictAspectRatioX) ||
(aspect_y != pVI2->dwPictAspectRatioY))
{
aspect_x = pVI2->dwPictAspectRatioX;
aspect_y = pVI2->dwPictAspectRatioY;
}
memcpy(&bih, &pVI2->bmiHeader, sizeof(BITMAPINFOHEADER));
}
else
return E_UNEXPECTED;
DWORD i;
for(i = 0; i < N_SUBTYPES; i++)
if(g_subtypes[i] == *subtype)
{
current_subtype = &g_subtypes[i];
break;
}
if(i >= N_SUBTYPES)
return E_UNEXPECTED;
return S_OK;
}
virtual void OnReceiveFirstSample(IMediaSample *pMediaSample)
{
DoRenderSample(pMediaSample);
}
virtual HRESULT EndOfStream()
{
if(b_loop_enabled)
PostMessage(m_hwnd, WM_USER, 0, 0);
end_of_stream = TRUE;
SetEvent(event);
return S_OK;
}
// Statis members
public:
static LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
CVRenderer *obj = (CVRenderer*)GetWindowLong(hwnd, GWL_USERDATA);
if(obj)
return obj->WindowProc(hwnd, message, wParam, lParam);
return DefWindowProc(hwnd, message, wParam, lParam);
}
};
//
//
extern "C"
HRESULT __fastcall VideoGrabberCreate(IVideoGrabber **grabber)
{
HRESULT hr = S_OK;
CVRenderer *obj = new CVRenderer(&hr);
if(!obj)
return E_OUTOFMEMORY;
if(FAILED(hr))
{
delete obj;
return hr;
}
obj->AddRef();
*grabber = (IVideoGrabber*)(IVideoGrabberX*)obj;
return S_OK;
}
//
//
extern "C"
HRESULT __fastcall EnumVideoCaptureSourcesStart(IUnknown **ppEnumMoniker)
{
ICreateDevEnum *pDevEnum;
IEnumMoniker *pEnum;
// Create the System Device Enumerator.
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pDevEnum);
if(FAILED(hr))
goto L_EXIT;
// Create an enumerator for the video capture category.
hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnum, 0);
pDevEnum->Release();
if(hr != S_OK)
goto L_EXIT;
*ppEnumMoniker = pEnum;
hr = S_OK;
L_EXIT:
return hr;
}
//
//
extern "C"
HRESULT __fastcall EnumVideoCaptureSourcesNext(IUnknown *pEnumMoniker, VARIANT *pName,
IUnknown **ppMoniker)
{
IEnumMoniker *pEnum = (IEnumMoniker*)pEnumMoniker;
IMoniker *pMoniker;
HRESULT hr;
while((hr = pEnum->Next(1, &pMoniker, NULL)) == S_OK)
{
IPropertyBag *pPropBag;
hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pPropBag);
if(FAILED(hr))
{
pMoniker->Release();
continue; // Skip this one, maybe the next one will work.
}
// Find the description or friendly name.
VariantInit(pName);
hr = pPropBag->Read(L"FriendlyName", pName, 0);
if((SUCCEEDED(hr)) && (pName->vt == VT_BSTR))
{
pPropBag->Release();
if(ppMoniker)
*ppMoniker = pMoniker;
else
pMoniker->Release();
hr = S_OK;
goto L_EXIT;
}
else
VariantClear(pName);
pPropBag->Release();
pMoniker->Release();
}
L_EXIT:
return hr;
}
//
//
extern "C"
void __fastcall EnumVideoCaptureSourcesEnd(IUnknown *pEnumMoniker)
{
pEnumMoniker->Release();
}
//
//
extern "C"
HRESULT __fastcall EnumVideoCaptureFormatsStart(LPWSTR szVideoCaptureSource,
IUnknown **ppAMStreamConfig,
DWORD *nFormats)
{
IBaseFilter *source = NULL;
IPin *Pin = NULL;
IAMStreamConfig *cfg = NULL;
HRESULT hr;
hr = FindVideoCaptureSource(szVideoCaptureSource, &source);
if(FAILED(hr))
goto L_EXIT;
hr = FindPinByCategory(source, PINDIR_OUTPUT, PIN_CATEGORY_CAPTURE, &Pin);
if(FAILED(hr))
goto L_EXIT;
hr = Pin->QueryInterface(IID_IAMStreamConfig, (void**)&cfg);
if(FAILED(hr))
goto L_EXIT;
int iCount = 0, iSize = 0;
hr = cfg->GetNumberOfCapabilities(&iCount, &iSize);
if(FAILED(hr))
goto L_EXIT;
if(iSize != sizeof(VIDEO_STREAM_CONFIG_CAPS))
{
hr = E_UNEXPECTED;
goto L_EXIT;
}
cfg->AddRef();
*ppAMStreamConfig = cfg;
*nFormats = iCount;
hr = S_OK;
L_EXIT:
SAFE_RELEASE(cfg);
SAFE_RELEASE(Pin);
SAFE_RELEASE(source);
return hr;
}
//
//
extern "C"
HRESULT __fastcall EnumVideoCaptureFormatsByIndex(IUnknown *pAMStreamConfig, DWORD iFormat,
GUID *subtype,
SIZE *szMin, SIZE *szMax, SIZE *szStep,
float *fpsMin, float *fpsMax,
SIZE *szDef, float *fpsDef)
{
VIDEO_STREAM_CONFIG_CAPS scc;
AM_MEDIA_TYPE *pmtConfig = NULL;
IAMStreamConfig *cfg = (IAMStreamConfig*)pAMStreamConfig;
HRESULT hr;
hr = cfg->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
if(FAILED(hr))
goto L_EXIT;
BITMAPINFOHEADER bih;
if(pmtConfig->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmtConfig->pbFormat);
bih = pVih->bmiHeader;
}
else
if(pmtConfig->formattype == FORMAT_VideoInfo2)
{
VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmtConfig->pbFormat);
bih = pVih2->bmiHeader;
}
else
{
hr = E_UNEXPECTED;
goto L_EXIT;
}
*subtype = pmtConfig->subtype;
*szMin = scc.MinOutputSize;
*szMax = scc.MaxOutputSize;
szStep->cx = scc.OutputGranularityX;
szStep->cy = scc.OutputGranularityY;
*fpsMin = 10000000.0f / (float)scc.MaxFrameInterval;
*fpsMax = 10000000.0f / (float)scc.MinFrameInterval;
DeleteMediaType(pmtConfig);
pmtConfig = NULL;
hr = cfg->GetFormat(&pmtConfig);
if((SUCCEEDED(hr)) && ((pmtConfig->formattype == FORMAT_VideoInfo) ||
(pmtConfig->formattype == FORMAT_VideoInfo2)))
{
if(pmtConfig->formattype == FORMAT_VideoInfo)
{
VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)(pmtConfig->pbFormat);
bih = pVih->bmiHeader;
*fpsDef = 10000000.0f / (float)pVih->AvgTimePerFrame;
}
else
{
VIDEOINFOHEADER2 *pVih2 = (VIDEOINFOHEADER2*)(pmtConfig->pbFormat);
bih = pVih2->bmiHeader;
*fpsDef = 10000000.0f / (float)pVih2->AvgTimePerFrame;
}
szDef->cx = bih.biWidth;
szDef->cy = bih.biHeight;
}
else
{
szDef->cx = 0;
szDef->cy = 0;
*fpsDef = 0.0f;
}
if(pmtConfig)
{
DeleteMediaType(pmtConfig);
pmtConfig = NULL;
}
hr = cfg->GetFormat(&pmtConfig);
if(SUCCEEDED(hr))
{
hr = (pmtConfig->subtype == *subtype) ? S_OK : S_FALSE;
}
else
hr = S_FALSE;
L_EXIT:
if(pmtConfig)
DeleteMediaType(pmtConfig);
return hr;
}
//
//
extern "C"
void __fastcall EnumVideoCaptureFormatsEnd(IUnknown *pAMStreamConfig)
{
pAMStreamConfig->Release();
}
//
// End
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -