分享

TechThink - 北京东方金谷

 WWWo福oCOM 2008-07-05

使用VideoWave采集不同格式的视音频文件 (3)
采集MPG,AVI和ASF的程序代码


     
 

上一篇:从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

// 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如下图

Filter graph for mpg file capture 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如下图:

Filter graph for avi file capture


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如下图:

Filter graph for asf file capture

下载可执行文件
下载源代码

 
     

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多