http://www.360doc.com/content/08/0705/23/29694_1401883.shtml 此網址有源碼
下面的程式碼示範了如何用VW卡採集MPG,AVI或ASF檔案。 本程式是基於DirectShow通過VW卡的DirectShow Source Filter及相關Filter實現檔案採集。 由於在這裡AVI,ASF格式檔案均為MPEG-4視頻,所以,為簡單起見,MPG檔案也為MPEG-4視頻,即前面文章所提高的MPEG-4 Embedded MPEG-2。
在程式運行後,首先建立一個Filter Graph,其中僅含有VW Source Filter並進行相應的設定,在本執行個體中設定的參數為: PAL複合視頻輸入,MPEG-4 Program編碼,視頻位速率為1M bps, 解析度為720 x 576 , 音頻位速率192K bps, 44.1K採樣頻率,MPEG-1 L2 音頻編碼(AVI檔案的音頻編碼為PCM)。然後,根據選擇不同的輸出檔案 格式,完成相應的Filte Graph。
1. 建立基本的Filter Graph
// We create a Filter graph including Source Filter only.
// For every usage, we add other usaful filter into the graph
// and remove useless filters.
HRESULT CCap4Dlg::CraeteBaseCaptureGraph ()
{
HRESULT hr;
IBaseFilter *pSrc = NULL;
if (m_pGraph)
{
SAFE_RELEASE (m_pGraph);
}
__try {
// 建立Filter Graph
CHECK_HR( hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,/
IID_IGraphBuilder, (void **)&m_pGraph));
// 建立Source Filter執行個體並加入到Filter Graph中.
CHECK_HR( hr = CoCreateInstance(CLSID_VWSource, NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pSrc));
CHECK_HR( hr = m_pGraph->AddFilter(pSrc, L"Source Filter"));
ISrcControl * p_ISrc;
CHECK_HR( hr = pSrc->QueryInterface (IID_ISrcControl, (void **)&p_ISrc));// 擷取介面指標
p_ISrc->SetAudioEncodeFormat (1);// MPEG-1 L2
p_ISrc->SetDeviceNumber (0);// 指定操作0號卡
p_ISrc->SetStreamType (3);// 指定MPEG-4 Program
p_ISrc->SetVideoSource (VW_COMPOSITE);// 複合輸入
p_ISrc->SetVideoStandard (VW_SRC_PAL);// PAL
p_ISrc->SetVideoResolution (VW_VIDEO_RESOLUTION_FULL_720);// 720 x 576
p_ISrc->SetVideoBitrate (1000000);// 1M bps視頻位速率
p_ISrc->SetAudioFrequency(VW_AUDIO_FREQ_44100);// 44.1KHz音頻採樣
p_ISrc->SetAudioBitrate(VW_AUDIO_BITRATE_192);// 192K 音頻位速率
p_ISrc->SetParameterActive ();
SAFE_RELEASE (p_ISrc);
}__finally {
SAFE_RELEASE(pSrc);
if (FAILED(hr)){
SAFE_RELEASE(m_pGraph);
}
}
#ifdef _DEBUG
if (SUCCEEDED(hr))
AddGraphToRot(m_pGraph, &m_dwGraphRegister);
#endif
return hr;
}
2. 建立MPG檔案採集的Filter Graph
建立用於採集MPG檔案的Filter Graph 比較簡單,只需要加入Dump Filter,把它串連到Source Filter就行了。
// Remove all filters except source filter, then add Dump filter
HRESULT CCap4Dlg::UpdateCaptureGraphForMpg (const char * filename)
{
HRESULT hr = E_FAIL;
IBaseFilter * pSrc = NULL;
IBaseFilter * pDump = NULL;
IFileSinkFilter *pSink = NULL;
WCHAR wFile[512];
IPin * pSrcPin;
IPin * pDstPin;
#ifdef _DEBUG
if (m_dwGraphRegister) {
RemoveGraphFromRot(m_dwGraphRegister);
m_dwGraphRegister = 0;
}
#endif
__try {
CHECK_HR (hr = m_pGraph->FindFilterByName (L"Source Filter", &pSrc));
TearDownGraph (pSrc);
// Create and add Dump Filter
CHECK_HR( hr = CoCreateInstance(CLSID_Dump,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pDump));
CHECK_HR( hr = m_pGraph->AddFilter(pDump, L"Dump"));
CHECK_HR( hr = pDump->QueryInterface (IID_IFileSinkFilter, (void **)&pSink));
MultiByteToWideChar(CP_ACP, 0, filename, -1, wFile, NUMELMS(wFile));
pSink->SetFileName (wFile, NULL);
// Connect Source to Dump
pSrcPin = GetOutPin (pSrc, 0);
pDstPin = GetInPin (pDump, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
}__finally {
SAFE_RELEASE(pSink);
SAFE_RELEASE(pDump);
SAFE_RELEASE(pSrc);
}
#ifdef _DEBUG
if (SUCCEEDED(hr))
AddGraphToRot(m_pGraph, &m_dwGraphRegister);
#endif
return hr;
}
用於採集mpg檔案的Filter Graph如
3. 建立AVI檔案採集的Filter Graph
建立AVI檔案採集的Filter Graph要稍微複雜一些,我們直接利用VW Source Video的Video和Audio輸出Pin,把他們串連到AVI Mux filter,由於是採用PCM音頻編碼,我們要串連一個MPEG Audio Decoder Filter在VW Source Filter Pin2到AVI Mux。VW Source Filter的Pin0,即輸出MPEG Multiplexing Stream 的Pin上實現的主線程,我們不能讓他空在這兒,所以就用一個NullRenderer Filter串連到這個Pin上。最後把AVI Mux串連到File Witer filter。
// Remove all filters except source filter, then add AVI Mux filter
HRESULT CCap4Dlg::UpdateCaptureGraphForAvi (const char * filename)
{
HRESULT hr = E_FAIL;
IBaseFilter * pSrc = NULL;
IBaseFilter * pFileWriter = NULL;
IBaseFilter * pMux = NULL;
IBaseFilter * pAudDec = NULL;
IBaseFilter * pNullRnd = NULL;
IFileSinkFilter *pSink = NULL;
WCHAR wFile[512];
IPin * pSrcPin;
IPin * pDstPin;
#ifdef _DEBUG
if (m_dwGraphRegister) {
RemoveGraphFromRot(m_dwGraphRegister);
m_dwGraphRegister = 0;
}
#endif
__try {
CHECK_HR (hr = m_pGraph->FindFilterByName (L"Source Filter", &pSrc));
TearDownGraph (pSrc);
CHECK_HR( hr = CoCreateInstance(CLSID_NullRenderer, NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pNullRnd));
CHECK_HR( hr = m_pGraph->AddFilter(pNullRnd, L"Null Render"));
pSrcPin = GetOutPin (pSrc, 0);
pDstPin = GetInPin (pNullRnd, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
CHECK_HR( hr = CoCreateInstance(CLSID_AviDest, NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pMux));
CHECK_HR( hr = m_pGraph->AddFilter(pMux, L"AVI Mux"));
CHECK_HR( hr = CoCreateInstance(CLSID_CMpegAudioCodec,NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pAudDec));
CHECK_HR( hr = m_pGraph->AddFilter(pAudDec, L"Audio Decoder"));
CHECK_HR( hr = CoCreateInstance(CLSID_FileWriter, NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pFileWriter));
CHECK_HR( hr = m_pGraph->AddFilter(pFileWriter, L"File Writer"));
CHECK_HR( hr = pFileWriter->QueryInterface (IID_IFileSinkFilter, (void **)&pSink));
MultiByteToWideChar(CP_ACP, 0,filename, -1, wFile, NUMELMS(wFile));
pSink->SetFileName (wFile, NULL);
pSrcPin = GetOutPin (pSrc, 1);
pDstPin = GetInPin (pMux, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
pSrcPin = GetOutPin (pSrc, 2);
pDstPin = GetInPin (pAudDec, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
pSrcPin = GetOutPin (pAudDec, 0);
pDstPin = GetInPin (pMux, 1);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
pSrcPin = GetOutPin (pMux, 0);
pDstPin = GetInPin (pFileWriter, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
}__finally {
SAFE_RELEASE(pMux);
SAFE_RELEASE(pNullRnd);
SAFE_RELEASE(pFileWriter);
SAFE_RELEASE(pSink);
SAFE_RELEASE(pAudDec);
SAFE_RELEASE(pSrc);
}
#ifdef _DEBUG
if (SUCCEEDED(hr))
AddGraphToRot(m_pGraph, &m_dwGraphRegister);
#endif
return hr;
}
建立後的Filter Graph如:
4. 建立ASF檔案採集的Filter Graph.
建立ASF檔案採的Filter Graph和前面的AVI檔案採集Filter Graph差不多,但ASF Writer中包含了檔案儲存體,所以不需要 File Writer或Dump這樣的檔案輸出Filter了.
// Remove all filters except source filter, then add ASF Mux filter
HRESULT CCap4Dlg::UpdateCaptureGraphForAsf (const char * filename)
{
HRESULT hr = E_FAIL;
IBaseFilter * pSrc = NULL;
IBaseFilter * pMux = NULL;
IBaseFilter * pNullRnd = NULL;
IFileSinkFilter *pSink = NULL;
WCHAR wFile[512];
IPin * pSrcPin;
IPin * pDstPin;
#ifdef _DEBUG
if (m_dwGraphRegister) {
RemoveGraphFromRot(m_dwGraphRegister);
m_dwGraphRegister = 0;
}
#endif
__try {
CHECK_HR (hr = m_pGraph->FindFilterByName (L"Source Filter", &pSrc));
TearDownGraph (pSrc);
CHECK_HR( hr = CoCreateInstance(CLSID_NullRenderer, NULL,CLSCTX_INPROC,IID_IBaseFilter, (void**)&pNullRnd));
CHECK_HR( hr = m_pGraph->AddFilter(pNullRnd, L"Null Render"));
pSrcPin = GetOutPin (pSrc, 0);
pDstPin = GetInPin (pNullRnd, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
CHECK_HR( hr = CoCreateInstance(CLSID_ASFWRITER, NULL,CLSCTX_INPROC,IID_IBaseFilter,(void**)&pMux));
CHECK_HR( hr = m_pGraph->AddFilter(pMux, L"ASF Mux"));
CHECK_HR( hr = pMux->QueryInterface (IID_IFileSinkFilter, (void **)&pSink));
MultiByteToWideChar(CP_ACP, 0,filename, -1, wFile, NUMELMS(wFile));
pSink->SetFileName (wFile, NULL);
pSrcPin = GetOutPin (pSrc, 1);
pDstPin = GetInPin (pMux, 0);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
pSrcPin = GetOutPin (pSrc, 2);
pDstPin = GetInPin (pMux, 1);
CHECK_HR( hr = m_pGraph->Connect (pSrcPin, pDstPin));
}__finally {
SAFE_RELEASE(pMux);
SAFE_RELEASE(pNullRnd);
SAFE_RELEASE(pSink);
SAFE_RELEASE(pSrc);
}
#ifdef _DEBUG
if (SUCCEEDED(hr))
AddGraphToRot(m_pGraph, &m_dwGraphRegister);
#endif
return hr;
}
建立後的Filter Graph如: