|
上一篇:从MPEG文件中解析出视频流和音频流
采集MPG, AVI或ASF文件
下面的程序代码示范了如何用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
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就行了。
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。
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了.
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如下图:
下载可执行文件
下载源代码
|
|