你可以调用iamstreamconfig::setformat设置新的媒体类型
hr = pconfig->setformat(pmtconfig);
如果pin没有连接,当连接的时候就试图用新的格式,如果pin已经在连接了,它就会用的新的媒体格式重新连接。在任何一种情况下,下游的filter都有可能拒绝新的媒体格式。
在setformat前你可以修改video_stream_config_caps结构来重新设置媒体类型。
例如:
如果getstreamcaps返回的是24-bit rgb format,桢的大小是320 x 240 像素,你可以通过检查媒体类型的major type,subtpye,和format等值
if ((pmtconfig.majortype == mediatype_video) &&video_stream_config_caps结构里包含了该媒体类型的视频长度和宽度的最大值和最小值,还有递增的幅度值,就是每次调整视频size的幅度,例如,设备可能返回如下的值
(pmtconfig.subtype == mediasubtype_rgb24) &&
(pmtconfig.formattype == format_videoinfo) &&
(pmtconfig.cbformat >= sizeof (videoinfoheader)) &&
(pmtconfig.pbformat != null))
{
videoinfoheader *pvih = (videoinfoheader*)pmtconfig.pbformat;
// pvih contains the detailed format information.
long lwidth = pvih->bmiheader.biwidth;
long lheight = pvih->bmiheader.biheight;
}
? minoutputsize: 160 x 120
? maxoutputsize: 320 x 240
? outputgranularityx: 8 pixels (horizontal step size)
? outputgranularityy: 8 pixels (vertical step size)
这样你可以在(160, 168, 176, ... 304, 312, 320) 范围内设置宽度,在 (120, 128, 136, ... 104, 112, 120).设置高度值,
学习笔记九_视频捕捉/6.jpg)
图6
如果想设置新的值,直接修改在getstreamcaps函数中返回的值即可,
pvih->bmiheader.biwidth = 160;然后将媒体类型传递给setformat函数,就可修改视频格式了。
pvih->bmiheader.biheight = 120;
pvih->bmiheader.bisizeimage = dibsize(pvih->bmiheader);
7将设备从系统中移走时的事件通知(device remove notify)
如果用户将一个graph正在使用的即插即用型的设备从系统中去掉,filter图表管理器就会发送一个ec_device_lost事件通知,如果该设备又可以使用了,filter图表管理器就发送另外的一个ec_device_lost通知,但是先前组建的捕捉filter graph图就没法用了,用户必须重新组建graph图。
当系统中有新的设备添加时,dshow是不会发送任何通知的,所以,应用程序如果想要知道系统中何时添加新的设备,应用程序可以监控wm_devicechange消息。
8从静止图像pin中捕捉图片
有些照相机,摄像头除了可以捕获视频流以外还可以捕获单张的,静止的图片。通常,静止的图片的质量要比流的质量要高。摄像头一般都一个按钮来触发,或者是支持软件触发。支持输出静态图片的摄像头一般都要提供一个静态图片pin,这个pin的种类是pin_category_still。
从设备中获取静态图片,我们一般推荐使用windows image acquisition (wia) apis。当然,你也可以用dshow来获取图片。
在graph运行的时候利用iamvideocontrol::setmode来触发静态的pin。代码如下
pcontrol->run(); // run the graph.首先向capture filter 请求iamvideocontol,如果支持该接口,就调用icapturegraphbuilder2::findpin请求指向静止pin 的指针,然后调用pin的put_mode方法。
iamvideocontrol *pamvidcontrol = null;
hr = pcap->queryinterface(iid_iamvideocontrol, (void**)&pamvidcontrol);
if (succeeded(hr))
{
// find the still pin.
ipin *ppin = 0;
hr = pbuild->findpin(pcap, pindir_output, &pin_category_still, 0,
false, 0, &ppin);
if (succeeded(hr))
{
hr = pamvidcontrol->setmode(ppin, videocontrolflag_trigger);
ppin->release();
}
pamvidcontrol->release();
}
根据不同的摄像头,你可能静态pin连接前要render 该pin。
捕捉静态图片常用的filter是sample grabber filter,sample grabber使用了一个用户定义的回调汗水来处理图片。关于这个filter的详细用法,参见using the sample grabber.。
下面的例子假设静态pin传递的是没有压缩的rgb图片。首先定义一个类,从isamplegrabbercb继承。
// class to hold the callback function for the sample grabber filter.然后将捕捉filter的静态pin连接到sample grabber,将sample grabber连接到null renderer filter。null renderer仅仅是将她接收到的sample丢弃掉。实际的工作都是在回调函数里进行,连接null renderer 仅仅是为了给sample grabber's 输出pin上连接点东西。具体见下面的代码
class samplegrabbercallback : public isamplegrabbercb
{
// implementation is described later.
}// global instance of the class.
samplegrabbercallback g_stillcapcb;
// add the sample grabber filter to the graph.
ibasefilter *psg_filter;
hr = cocreateinstance(clsid_samplegrabber, null, clsctx_inproc_server,
iid_ibasefilter, (void**)&psg_filter);
hr = pgraph->addfilter(psg_filter, l"samplegrab");// add the null renderer filter to the graph.
ibasefilter *pnull;
hr = cocreateinstance(clsid_nullrendere, null, clsctx_inproc_server,
iid_ibasefilter, (void**)&pnull);
hr = pgraph->addfilter(psg_filter, l"nullrender");