📄 capture.cpp
字号:
if(FAILED(pIPinOutput->Disconnect()))
{
ASSERT(FALSE);
return E_FAIL;
}
if(FAILED(pIPinInput->Disconnect()))
{
ASSERT(FALSE);
return E_FAIL;
}
// Now just connect the two pins
hr = m_pGB->ConnectDirect(pIPinOutput, pIPinInput, pmt);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
TRACE("Could not connect pins!");
// Release the two pins and return the result
pIPinOutput->Release();
pIPinInput->Release();
return hr;
}
//自动连接Filter
STDMETHODIMP CCaptureGraph::ConnectAutoPins(IBaseFilter* pIFilterOutput,
LPCTSTR pstrPinNameOutput,
IBaseFilter* pIFilterInput,
LPCTSTR pstrPinNameInput)
{
HRESULT hr;
ASSERT(m_pGB);
// Parameters...
if((!pIFilterOutput) || (!pIFilterInput))
{
ASSERT(pIFilterOutput && pIFilterInput);
TRACE("ConnectPins called with NULL parameter\n");
return E_INVALIDARG;
}
// Find the first pin
IPin* pIPinOutput = FindPinOnFilter(pIFilterOutput,
pstrPinNameOutput,
PINDIR_OUTPUT);
if(!pIPinOutput)
{
ASSERT(pIPinOutput);
return E_FAIL;
}
// Find the second pin
IPin* pIPinInput = FindPinOnFilter(pIFilterInput,
pstrPinNameInput,
PINDIR_INPUT);
if(!pIPinInput)
{
ASSERT(pIPinInput);
// release the other pin
pIPinOutput->Release();
return E_FAIL;
}
if(FAILED(pIPinOutput->Disconnect()))
{
ASSERT(FALSE);
return E_FAIL;
}
if(FAILED(pIPinInput->Disconnect()))
{
ASSERT(FALSE);
return E_FAIL;
}
// Now just connect the two pins
hr = m_pGB->Connect(pIPinOutput, pIPinInput);
ASSERT(SUCCEEDED(hr));
if(FAILED(hr))
TRACE("Could not connect pins!");
// Release the two pins and return the result
pIPinOutput->Release();
pIPinInput->Release();
return hr;
}
STDMETHODIMP_(BOOL) CCaptureGraph::IsConnected(IBaseFilter *pFilter,
LPCTSTR pstrPinName,
PIN_DIRECTION pd)
{
ASSERT(m_pGB);
// Parameters...
if((!pFilter))
{
ASSERT(pFilter);
TRACE("ConnectPins called with NULL parameter\n");
return FALSE;
}
// Find the pin
IPin* pIPin = FindPinOnFilter(pFilter,
pstrPinName,
pd);
if(!pIPin)
{
ASSERT(pIPin);
return FALSE;
}
IPin *pNextPin = NULL;
pIPin->ConnectedTo(&pNextPin);
if(!pNextPin)
{
return FALSE;
}
pIPin->Release();
pNextPin->Release();
//That's it...
return TRUE;
}
STDMETHODIMP CCaptureGraph::DisconnectPin(IBaseFilter *pIFilter,
LPCTSTR pstrPinName,
PIN_DIRECTION dir)
{
HRESULT hr;
ASSERT(m_pGB);
// Parameters...
if(!pIFilter)
// DON'T fail on this, it is expected
return NOERROR;
// Find the pin
IPin* pIPin = FindPinOnFilter(pIFilter, pstrPinName, dir);
if(!pIPin)
{
TRACE("Could not find specified filter pin\n");
return E_FAIL;
}
// Find the pin it's connected to
IPin* pIPinConnected;
hr = pIPin->ConnectedTo(&pIPinConnected);
if((FAILED(hr)) || (!pIPinConnected))
{
// Function call failed, pin not connected, nothing to do!
pIPin->Release();
return NOERROR;
}
// Try to disconnect the input pin first
if (dir == PINDIR_INPUT)
{
// ok now disconnect both of them
hr = m_pGB->Disconnect(pIPin);
if(FAILED(hr))
{
// just forget everything
ASSERT(SUCCEEDED(hr));
pIPin->Release();
pIPinConnected->Release();
TRACE("Disconnect failed on input pin\n");
return hr;
}
hr = m_pGB->Disconnect(pIPinConnected);
if(FAILED(hr))
{
ASSERT(SUCCEEDED(hr));
TRACE("Disconnect failed on output pin\n");
}
}
else
{
// ok now disconnect both of them
hr = m_pGB->Disconnect(pIPinConnected);
if(FAILED(hr))
{
ASSERT(SUCCEEDED(hr));
// just forget everything
pIPin->Release();
pIPinConnected->Release();
TRACE("Disconnect failed on input pin\n");
return hr;
}
hr = m_pGB->Disconnect(pIPin);
if(FAILED(hr))
{
ASSERT(SUCCEEDED(hr));
TRACE("Disconnect failed on output pin\n");
}
}
// Just release the two pins and return last result
pIPin->Release();
pIPinConnected->Release();
return hr;
}
STDMETHODIMP_(IPin*) CCaptureGraph::FindPinOnFilter(IBaseFilter* pIFilter,
LPCTSTR pstrPinName,
PIN_DIRECTION dir)
{
HRESULT hr;
IEnumPins* pIEnumPins;
IPin* pIPin;
PIN_INFO pi;
ASSERT(m_pGB);
// Parameters...
if(!pIFilter)
return NULL;
// Enumerate pins on the filter
hr = pIFilter->EnumPins(&pIEnumPins);
if(FAILED(hr))
// pin was not found!
return NULL;
// Loop till we find no more pins
IPin* pIPinFound = NULL;
while( (!pIPinFound) && (pIEnumPins->Next(1, &pIPin, NULL)==S_OK) )
{
// Is this the pin?
hr = pIPin->QueryPinInfo(&pi);
if(!FAILED(hr))
{
// check if it is the right direction
if(pi.dir == dir)
{
// Let the graph builder find the right filter
TCHAR strFoundPinName[256];
#ifndef _UNICODE
// not unicode, we need to de-unicodify the returned pin name
WideCharToMultiByte(CP_ACP, NULL,
pi.achName, -1,
strFoundPinName, sizeof(strFoundPinName),
NULL, NULL);
#else
// just make a copy of the string
lstrcpyn(strFoundPinName, pi.achName, sizeof(strFoundPinName));
#endif
// check if there is a pin name specified
if(!pstrPinName)
{
// no name specified, take the first pin found
pIPinFound = pIPin;
pIPinFound->AddRef();
}
// check if we have the right pin name
else if(lstrcmp(strFoundPinName, pstrPinName)==0)
{
// yes we have!
pIPinFound = pIPin;
pIPinFound->AddRef();
}
}
// release the PIN_INFO data
pi.pFilter->Release();
}
// release the IPin pointer
pIPin->Release();
}
// Finished with the enumerator, let it go (be free)
pIEnumPins->Release();
// Return whatever we have found
return pIPinFound;
}
STDMETHODIMP CCaptureGraph::BuildGraph()
{
HRESULT hr;
//添加TV Sink Filter
hr = AddFilter(CLSID_TVStreamSink, &m_pTVStreamSink);
if (FAILED(hr))
{
return hr;
}
hr = m_pTVStreamSink->Release();
//添加IID_ITVSouceConfig接口
hr = m_pTVStreamSink->QueryInterface(IID_ITVSouceConfig, (VOID**)&m_pTVConfig);
if(FAILED(hr))
{
TRACE("cant Get the ITVConfig interface!!");
return hr;
}
//判断是否为DV设备将判断结果置为mbISDV的值若是DV则走DV的流程
JudgeDV();
//若为只有音频设备,则调TV Sink接口
if(m_bIsOnlyAudio)
{
m_pTVConfig->SetAudioOrVideoOnly(m_bIsOnlyAudio);
}
m_pTVConfig->Release();
//若为DV则调用DV的Graph
if (TRUE == mbIsDV)
{
hr = DisplayDV();//DisplayDV();
if (SUCCEEDED(hr))
{
m_bGraphBuiled = TRUE;
return hr;
}
return hr;
}
//若不是DV则调用一般的Graph
hr = BuildGeneralGraph();
if (SUCCEEDED(hr))
{
m_bGraphBuiled = TRUE;
return hr;
}
return hr;
// that's ok, we can run it!
//m_bGraphBuiled = TRUE;
//return S_OK;
}
STDMETHODIMP CCaptureGraph::DisassembleGraph()
{
HRESULT hr;
/*
// first must stop
if(m_hWndOwner != NULL)
{
CWnd wd;
wd.Attach(m_hWndOwner);
//((CGVCaptureDlg*)wd.GetParent())->OnNotifyStop();
wd.Detach();
}
*/
RemoveFilter(m_pVideoCapture);
RemoveFilter(m_pVideoEncoder);
RemoveFilter(m_pAudioCapture);
RemoveFilter(m_pAudioEncoder);
RemoveFilter(m_pTVStreamSink);
RemoveFilter(m_pVideoSmartTee);
RemoveFilter(m_pftrDVSpliter);
RemoveFilter(m_pDVDecoder);
for(int i = 0; i < m_arrayOtherFilter.GetSize(); i++)
{
IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
RemoveFilter(pFilter);
}
// added by zk for saving 2004-04-16
if(m_pVideoSmartTee)
RemoveFilter(m_pVideoSmartTee);
if(m_pAudioSmartTee)
RemoveFilter(m_pAudioSmartTee);
if(m_pAVIMuxer)
RemoveFilter(m_pAVIMuxer);
if(m_pFileWriter)
RemoveFilter(m_pFileWriter);
// release All filter in the graph except for
// videocapture and videoencoder.these two filters will be
// deleted in create CreateCapDeviceFilterByName and
// CreateEncoderFilterByNamer
SAFE_RELEASE(m_pAudioCapture);
// SAFE_RELEASE(m_pTVStreamSink);
SAFE_RELEASE(m_pVideoSmartTee);
SAFE_RELEASE(m_pAudioSmartTee);
// SAFE_RELEASE(m_pTVConfig);
SAFE_RELEASE(m_pftrDVSpliter);
SAFE_RELEASE(m_pDVDecoder);
for(i=0; i<m_arrayOtherFilter.GetSize(); i++)
{
IBaseFilter *pFilter = (IBaseFilter*)(m_arrayOtherFilter.GetAt(i));
SAFE_RELEASE(pFilter);
}
m_arrayOtherFilter.RemoveAll();
m_bGraphBuiled = FALSE;
CComPtr <IVideoWindow> lpVideoWindow;
hr = m_pGB->QueryInterface(IID_IVideoWindow, (void**)&lpVideoWindow);
if (FAILED(hr))
{
return hr;
}
hr = lpVideoWindow->put_Visible(OAFALSE);
return S_OK;
}
// [10/6/2005] xiezhouwei
void CCaptureGraph::JudgeDV()
{
HRESULT hr;
CComPtr<ICaptureGraphBuilder2> lpgraphBuilder2;
//获得graphBuilder2_
hr = lpgraphBuilder2.CoCreateInstance(CLSID_CaptureGraphBuilder2);
if (FAILED(hr))
{
return ;
}
hr = lpgraphBuilder2->SetFiltergraph(m_pGB);
if (FAILED(hr))
{
return ;
}
//判断是否为DV设备,如果不是就照正常的进行采集,否则链路将要变。
IAMStreamConfig *pSC;
mbIsDV =FALSE; //首先假设不是DV设备
hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Interleaved, m_pVideoCapture,
IID_IAMStreamConfig, (void **)&pSC);
if(hr != NOERROR)
hr = lpgraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE,
&MEDIATYPE_Video, m_pVideoCapture,
IID_IAMStreamConfig, (void **)&pSC);
if (!FAILED(hr))
{
AM_MEDIA_TYPE *pmt;
if(pSC && pSC->GetFormat(&pmt) == S_OK)
{
if(pmt->formattype == FORMAT_DvInfo)
{
mbIsDV = TRUE;
}
}
pSC->Release();
}
}
HRESULT CCaptureGraph::BuildGeneralAudio()
{
HRESULT hr;
hr = GetAudioCaptureDevice();
if (FAILED(hr))
{
return hr;
}
hr = m_pGB->AddFilter(m_pAudioCapture, NULL);
if (FAILED(hr))
{
return hr;
}
if (NULL == m_pAudioEncoder)
{
AfxMessageBox("请选择正确的音频解码器");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pAudioEncoder, NULL);
if (FAILED(hr))
{
return hr;
}
hr = ConnectPins(m_pAudioCapture, NULL, m_pAudioEncoder, NULL);
if (FAILED(hr))
{
AfxMessageBox("请选择正确的音频解码器");
return hr;
}
hr = AddFilter(CLSID_InfTee, &m_pAudioSmartTee);
if (FAILED(hr))
{
return hr;
}
hr = ConnectPins(m_pAudioEncoder, NULL, m_pAudioSmartTee,NULL);
if (FAILED(hr))
{
AfxMessageBox("音频部分构建出错");
return hr;
}
//[AudioSmartTee] -> [TVSink]
hr = ConnectPins(m_pAudioSmartTee, __T("Output1"), m_pTVStreamSink, __T("Audio"), m_pCurAudioAMT);
if(FAILED(hr))
{
AfxMessageBox("不能进行播放,请重新选择音频编码器。");
return hr;
}
return hr;
}
//在VideoGraph中加入字幕Filter
HRESULT CCaptureGraph::AddVideoOverlayFilter()
{
HRESULT hr;
hr = m_pGB->AddFilter(m_pVideoOverlay, NULL);
if (FAILED(hr))
{
return hr;
}
hr = ConnectPins(m_pVideoCapture, NULL, m_pVideoOverlay, NULL);
if (FAILED(hr))
{
AfxMessageBox("连接字幕Filter出错");
return hr;
}
if (NULL == m_pVideoEncoder)
{
AfxMessageBox("视频编码器出错");
return E_FAIL;
}
hr = m_pGB->AddFilter(m_pVideoEncoder, NULL);
if (FAILED(hr))
{
return hr;
}
//如果是DMO组件
if (IsDMOFilter())
{
hr = BuildVideoDMOEncoder();
if (FAILED(hr))
{
return hr;
}
}
else
{
hr = ConnectPins(m_pVideoOverlay, NULL, m_pVideoEncoder, NULL);
if (FAILED(hr))
{
AfxMessageBox("视频编码器出错。请重新选择视频编码器");
return hr;
}
}
return hr;
}
//视频部分预览
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -