📄 capture.cpp
字号:
{
int cch = lstrlenW(varName.bstrVal) + 1;
CHAR* lpszFilterName = new char[cch * 2];
if (!lpszFilterName)
return E_OUTOFMEMORY;
WideCharToMultiByte(GetACP(), 0, varName.bstrVal, -1,
lpszFilterName, cch, NULL, NULL);
VariantClear(&varName);
if(strcmp(lpszFilterName, strName) == 0)
{
hr = pMoniker->BindToObject(NULL, NULL,
IID_IBaseFilter,
(VOID**)ppFilter);
delete [] lpszFilterName;
pPropBag->Release();
pMoniker->Release();
break;
}
delete [] lpszFilterName;
}
pPropBag->Release();
}
pMoniker->Release();
}
pClassEnum->Release();
pDevEnum->Release();
return S_OK;
}
// used to get audio capture device
HRESULT CCaptureGraph::GetAudioCaptureDevice()
{
HRESULT hr;
IMoniker *pMoniker =NULL;
ULONG cFetched;
// Create the system device enumerator
ICreateDevEnum* pDevEnum = NULL;
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC,
IID_ICreateDevEnum, (void **) &pDevEnum);
if (FAILED(hr))
{
TRACE1(TEXT("Couldn't create system enumerator! hr=0x%x"), hr);
return hr;
}
IEnumMoniker *pClassEnum = NULL;
hr = pDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pClassEnum, 0);
if (FAILED(hr))
{
pDevEnum->Release();
TRACE1(TEXT("Couldn't create class enumerator! hr=0x%x"), hr);
return hr;
}
if (pClassEnum == NULL)
{
pDevEnum->Release();
return S_OK;
}
pDevEnum->Release();
hr = pClassEnum->Reset();
if(S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched)))
{
hr = pMoniker->BindToObject(NULL, NULL,
IID_IBaseFilter,
(VOID**)&m_pAudioCapture);
if(FAILED(hr))
{
pMoniker->Release();
pClassEnum->Release();
TRACE("Cant find Audio Capture");
return hr;
}
}
pMoniker->Release();
pClassEnum->Release();
return hr;
}
// used for filling the m_arryOtherFilter, diff from our
// refrenced filters
BOOL CCaptureGraph::IsFilterInStdFilters(IBaseFilter *pFilter)
{
if(m_pVideoCapture == pFilter ||
m_pAudioCapture == pFilter ||
m_pVideoEncoder == pFilter ||
m_pAudioEncoder == pFilter ||
m_pTVStreamSink == pFilter ||
m_pVideoSmartTee == pFilter)
return TRUE;
else
return FALSE;
}
//得到媒体类型
bool CCaptureGraph::GetCurMediaType(AM_MEDIA_TYPE** aMTMediaType)
{
//Arthur:把当前的媒体类型交出去。重新拷一下,不能直接只拷指针。只拷指针不能访问
if(m_pCurAudioAMT)
{
if (!*aMTMediaType)
{
*aMTMediaType = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(),
HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY,
sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
if (!*aMTMediaType)
{
return false;
}
}
memcpy(*aMTMediaType, m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE));
(*aMTMediaType)->pbFormat = (LPBYTE)(*aMTMediaType+ 1);//指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
//赋给pbFormat
memcpy((*aMTMediaType)->pbFormat, m_pCurAudioAMT->pbFormat, m_pCurAudioAMT->cbFormat);
int ii = sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat;
return true;
}
return false;
}
//设置媒体类型
bool CCaptureGraph::SetCurMediaType(AM_MEDIA_TYPE *aMTMediaType)
{
//设置当前媒体类型的一个指针。
if(aMTMediaType)
{
//如果此时已经有媒体类型则将之释放掉
if (!m_pCurAudioAMT)
{
m_pCurAudioAMT = (AM_MEDIA_TYPE *)HeapAlloc(GetProcessHeap(),
HEAP_NO_SERIALIZE|HEAP_ZERO_MEMORY,
sizeof(AM_MEDIA_TYPE) + aMTMediaType->cbFormat);
if (!m_pCurAudioAMT)
{
return false;
}
}
ZeroMemory(m_pCurAudioAMT, sizeof(AM_MEDIA_TYPE) + m_pCurAudioAMT->cbFormat);
memcpy(m_pCurAudioAMT, aMTMediaType, sizeof(AM_MEDIA_TYPE));
BYTE* ii = (LPBYTE)(m_pCurAudioAMT+1);
int iii = sizeof(AM_MEDIA_TYPE);
m_pCurAudioAMT->pbFormat = (LPBYTE)(m_pCurAudioAMT+1);//arthur:指针加1。则相当于空出一个AM_MEDIA_TYPE。在这
//赋给pbFormat
if (m_pCurAudioAMT->pbFormat && aMTMediaType->pbFormat)
{
memcpy(m_pCurAudioAMT->pbFormat, aMTMediaType->pbFormat, aMTMediaType->cbFormat);
}
return true;
}
return false;
}
//=========================================
// Writed by zhuwei 2005-8-12
//Show Pin Setting
void CCaptureGraph::ShowPinSetting(HWND hParent)
{
if (NULL == m_pVideoCapture)
{
AfxMessageBox("视频采集设备未找到");
return;
}
/*
* SECOND: prompt user to configure output pin configuration
*/
HRESULT hr;
ISpecifyPropertyPages *pSpec;
WCHAR wstrCaption[256];
CAUUID cauuid;
// must be added in the graph this time
m_pGB->AddFilter(m_pVideoCapture, NULL);
IAMStreamConfig *pSC;
IPin *pOutPin = FindPinOnFilter(m_pVideoCapture, NULL);
hr = pOutPin->QueryInterface(IID_IAMStreamConfig, (void**)(&pSC));
pOutPin->Release();
if(FAILED(hr))
return;
hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void**)(&pSpec));
if(FAILED(hr))
{
pSC->Release();
return;
}
// Popup page
CString str = CString(_T("Video Capture Configuration 2")); // dlg caption
pSpec->GetPages(&cauuid);
if(cauuid.cElems >= 1)
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_USEGLYPHCHARS,
str.GetBuffer(str.GetLength()), -1,
wstrCaption, sizeof(wstrCaption) / sizeof(WCHAR));
hr = OleCreatePropertyFrame(hParent, 30, 30, wstrCaption, 1,
(IUnknown **)&pSC, cauuid.cElems,
(GUID *)cauuid.pElems, 0, 0, NULL);
if(FAILED(hr))
{
CoTaskMemFree(cauuid.pElems);
pSpec->Release();
pSC->Release();
return;
}
}
// Destructor
CoTaskMemFree(cauuid.pElems);
pSpec->Release();
pSC->Release();
return;
}
//Set AVI Filename
void CCaptureGraph::SetAVIFile( char* szFile )
{
if ( szFile[0] )
{
this->m_bSave = true;
strncpy( this->m_szAVIFile, szFile, MAX_PATH);
}
}
HRESULT CCaptureGraph::DVSplitter()
{
HRESULT hr;
if(!m_pVideoCapture)
{
AfxMessageBox("No Video Capture Device!");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pVideoCapture, NULL);
if(FAILED(hr))
{
TRACE("cant add video capture filter to graph");
return hr;
}
hr = AddFilter(CLSID_DVSplitter, &m_pftrDVSpliter);
//Add DV Splitter Filter
if(FAILED(hr))
{
AfxMessageBox("cant add DV Splitter Filter to graph");
return hr;
}
hr = ConnectAutoPins(m_pVideoCapture, "DV A/V Out", m_pftrDVSpliter, NULL);
if (FAILED(hr))
{
AfxMessageBox("cant ConnectDirect DV Splitter Filter to graph");
return hr;
}
return hr;
}
HRESULT CCaptureGraph::BuildDVAudio()
{
//DV加音频
HRESULT hr;
//Add Audio Encoder
if(!m_pAudioEncoder)
{
AfxMessageBox("No Aduio Compressor available!");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
if(FAILED(hr))
{
TRACE("cant add audio encoder filter to graph");
return hr;
}
//[DVSplitter] --> [AudioEncoder]
hr = ConnectAutoPins(m_pftrDVSpliter,"AudOut00", m_pAudioEncoder, NULL);
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择音频编码器。");
return hr;
}
//Add AudioSmartTee
hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
if(FAILED(hr))
{
TRACE("cant add smarttee filter to graph");
return hr;
}
//[AudioEncoder] --> [AudioSmartTee]
hr = ConnectPins(m_pAudioEncoder, __T("Output"), m_pAudioSmartTee, __T("Input"));
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择音频编码器。");
return E_FAIL;
}
//[AudioSmartTee] -> [TVSink]
hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择音频编码器。");
return hr;
}
return hr;
}
HRESULT CCaptureGraph::AddDVVideoOverlay()
{
HRESULT hr;
hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
if(FAILED(hr))
{
TRACE("cant add Video Overlay to graph");
return E_FAIL;
}
//[DVEncoder] --> [VideoOverlay]
hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoOverlay, NULL);
if(FAILED(hr))
{
AfxMessageBox("与字幕Filter连接失败");
return E_FAIL;
}
//将字幕Filter和视频编码filter相连
//Add Video Encoder
if(!m_pVideoEncoder)
{
AfxMessageBox("No Video Compressor available!");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
if(FAILED(hr))
{
TRACE("cant add video encoder filter to graph");
return E_FAIL;
}
//如果是DMO组件
if (IsDMOFilter())
{
hr = BuildVideoDMOEncoder();
if (FAILED(hr))
{
return hr;
}
}
else
{
//[VideoOverlay] --> [VideoEncoder]
hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择视频编码器。");
return hr;
}
}
return hr;
}
//DV视频预览
HRESULT CCaptureGraph::BuildDVVideoPrview()
{
//Get VideoSmartTee's Sencond Output Pin
IPin *pPreview;
if(FAILED(pPreview = FindPinOnFilter(m_pVideoSmartTee, __T("Output2"))))
{
TRACE("cant get preview outpin of smart tee!");
return E_FAIL;
}
//Render pin
HRESULT hr;
hr = m_pGB->Render(pPreview);
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择视频编码器。");
return hr;
}
pPreview->Release();
if ( NULL == m_pVW )
{
hr = m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW);
if (FAILED(hr))
{
TRACE0("ERROR - Could not Get IVideoWindow.");
return hr;
}
}
m_pVW->put_Owner((OAHWND)m_hWndOwner);
m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
CRect rc;
GetClientRect(m_hWndOwner, &rc);
m_pVW->put_Top(0);
m_pVW->put_Left(0);
m_pVW->put_Width(rc.Width());
m_pVW->put_Height(rc.Height());
m_pVW->put_Visible(-1);
m_pVW->put_AutoShow(-1);
return hr;
}
//构建DV视频链路
HRESULT CCaptureGraph::BuildDVVideo()
{
HRESULT hr;
hr = AddFilter(CLSID_DVVideoCodec, &m_pDVDecoder);
if (FAILED(hr))
{
TRACE("加载m_pDVDecoder失败");
return hr;
}
//为了解决CPU消耗过高,只减小输出画面
IIPDVDec* lpDVDec = NULL;
hr = m_pDVDecoder->QueryInterface(IID_IIPDVDec, (void**)&lpDVDec);
if (FAILED(hr))
{
TRACE("获取IIPDVDec接口失败");
return hr;
}
else
{
lpDVDec->put_IPDisplay(DVRESOLUTION_HALF);
lpDVDec->Release();
}
//[DVSpliter] --> [DVVideoCodec]
hr = ConnectPins(m_pftrDVSpliter, "DVVidOut0", m_pDVDecoder, NULL);
if(FAILED(hr))
{
AfxMessageBox("与m_pDVDecoderFilter连接失败");
return E_FAIL;
}
if (m_pVideoOverlay)//如果字幕filter有则需连字幕filter
{
hr = AddDVVideoOverlay();
}
else//不需要字幕的情况
{
//Add Video Encoder
if(!m_pVideoEncoder)
{
AfxMessageBox("No Video Compressor available!");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
if(FAILED(hr))
{
AfxMessageBox("cant add video encoder filter to graph");
return hr;
}
//如果是DMO组件
if (IsDMOFilter())
{
hr = BuildVideoDMOEncoder();
if (FAILED(hr))
{
return hr;
}
}
else
{
//[DV Splitter] --> [VideoEncoder]
hr = ConnectPins(m_pDVDecoder, NULL, m_pVideoEncoder, NULL);
if(FAILED(hr))
{
AfxMessageBox("不能进行自动连接在m_pftrDVSpliter和m_pVideoEncoder之间");
return E_FAIL;
}
}
}
//Add VideoSmartTee
hr = AddFilter(CLSID_InfTee, &m_pVideoSmartTee);
if(FAILED(hr))
{
TRACE("cant add smarttee filter to graph");
return hr;
}
//[VideoEncoder] --> [VideoSmartTee]
hr = ConnectPins(m_pVideoEncoder, NULL, m_pVideoSmartTee, __T("Input"));
if(FAILED(hr))
{
TRACE("cant connect video encoder and Smart Tee!");
return E_FAIL;
}
//[Video SmartTee] --> [TVSink]
hr = ConnectPins(m_pVideoSmartTee, __T("Output1"), m_pTVStreamSink, __T("Video"));
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择视频编码器。");
return hr;
}
//==================================================================================================
//预览
if(m_bIsPreview)
{
hr = BuildDVVideoPrview();
if (FAILED(hr))
{
return hr;
}
}
return hr;
}
//采集DV
HRESULT CCaptureGraph::DisplayDV()
{
HRESULT hr;
//分离DV的信号
hr = DVSplitter();
if (FAILED(hr))
{
return hr;
}
//构建DV音频
hr = BuildDVAudio();
if (FAILED(hr))
{
return hr;
}
if (FALSE == m_bIsOnlyAudio)
{
hr = BuildDVVideo();
if (FAILED(hr))
{
return hr;
}
}
if (m_bSave)
{
hr = BuildSaveGraph();
if (FAILED(hr))
{
return hr;
}
}
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -