Directshow中的视频捕捉[3]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 aoosang 的 blog

ienummoniker接口penum返回一个imoniker接口的列表,代表一系列的moniker,你可以显示所有的设备,然后让用户选择一个。
采用imoniker::bindtostorage方法,返回一个ipropertybag接口指针。然后调用ipropertybag::read读取moniker的属性。下面看看都包含什么属性
1 friendlyname 是设备的名字
2 description 属性仅仅适用于dv和d-vhs/mpeg摄象机,如果这个属性可用,这个属性更详细的描述了设备的资料
3devicepath 这个属性是不可读的,但是每个设备都有一个独一无二的。你可以用这个属性来区别同一个设备的不同实例
下面的代码演示了如何显示遍历设备的名称 ,接上面的代码

hwnd hlist; // handle to the list box.
imoniker *pmoniker = null;
while (penum->next(1, &pmoniker, null) == s_ok)
{
ipropertybag *ppropbag;
hr = pmoniker->bindtostorage(0, 0, iid_ipropertybag,
(void**)(&ppropbag));
if (failed(hr))
{
pmoniker->release();
continue; // skip this one, maybe the next one will work.
}
// find the description or friendly name.
variant varname;
variantinit(&varname);
hr = ppropbag->read(l"description", &varname, 0);
if (failed(hr))
{
hr = ppropbag->read(l"friendlyname", &varname, 0);
}
if (succeeded(hr))
{
// add it to the application's list box.
uses_conversion;
(long)sendmessage(hlist, lb_addstring, 0,
(lparam)ole2t(varname.bstrval));
variantclear(&varname);
}
ppropbag->release();
pmoniker->release();
}
如果用户选中了一个设备调用imoniker::bindtoobject为设备生成filter,然后将filter加入到graph中。
ibasefilter *pcap = null;
hr = pmoniker->bindtoobject(0, 0, iid_ibasefilter, (void**)&pcap);
if (succeeded(hr))
{
hr = m_pgraph->addfilter(pcap, l"capture filter");
}
3预览视频(previewing video)

为了创建可以预览视频的graph,可以调用下面的代码
icapturegraphbuilder2 *pbuild; // capture graph builder
// initialize pbuild (not shown).

ibasefilter *pcap; // video capture filter.
/* initialize pcap and add it to the filter graph (not shown). */

hr = pbuild->renderstream(&pin_category_preview, &mediatype_video, pcap, null, null);

4如何捕捉视频流并保存到文件(capture video to file)

1 将视频流保存到avi文件
下面的图表显示了graph图

图2
avi mux filter接收从capture pin过来的视频流,然后将其打包成avi流。音频流也可以连接到avi mux filter上,这样mux filter就将视频流和视频流合成avi流。file writer将avi流写入到文件中。
可以像下面这样构建graph图
ibasefilter *pmux;
hr = pbuild->setoutputfilename(
&mediasubtype_avi, // specifies avi for the target file.
l"c:\\example.avi", // file name.
&pmux, // receives a pointer to the mux.
null); // (optional) receives a pointer to the file sink.
第一个参数表明文件的类型,这里表明是avi,第二个参数是制定文件的名称。对于avi文件,setoutputfilename函数会创建一个avi mux filter 和一个 file writer filter ,并且将两个filter添加到graph图中,在这个函数中,通过file writer filter 请求ifilesinkfilter接口,然后调用ifilesinkfilter::setfilename方法,设置文件的名称。然后将两个filter连接起来。第三个参数返回一个指向 avi mux的指针,同时,它也通过第四个参数返回一个ifilesinkfilter参数,如果你不需要这个参数,你可以将这个参数设置成null。
然后,你应该调用下面的函数将capture filter 和avi mux连接起来。
hr = pbuild->renderstream(
&pin_category_capture, // pin category.
&mediatype_video, // media type.
pcap, // capture filter.
null, // intermediate filter (optional).
pmux); // mux or file sink filter.
// release the mux filter.
pmux->release();
第5个参数就是使用的上面函数返回的pmux指针。
当捕捉音频的时候,媒体类型要设置为mediatype_audio,如果你从两个不同的设备捕捉视频和音频,你最好将音频设置成主流,这样可以防止两个数据流间drift,因为avi mux filter为同步音频,会调整视频的播放速度的。为了设置master 流,调用iconfigavimux::setmasterstream方法,可以采用如下的代码:
iconfigavimux *pconfigmux = null;
hr = pmux->queryinterface(iid_iconfigavimux, (void**)&pconfigmux);
if (succeeded(hr))
{
pconfigmux->setmasterstream(1);
pconfigmux->release();
}
setmasterstream的参数指的是数据流的数目,这个是由调用renderstream的次序决定的。例如,如果你调用renderstream首先用于视频流,然后是音频,那么视频流就是0,音频流就是1。
添加编码filter
  ibasefilter *pencoder;
/* create the encoder filter (not shown). */
// add it to the filter graph.
pgraph->addfilter(pencoder, l"encoder);

/* call setoutputfilename as shown previously. */

// render the stream.
hr = pbuild->renderstream(&pin_category_capture, &mediatype_video,
pcap, pencoder, pmux);
pencoder->release();

本文关键:Directshow中的视频捕捉
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top