setcapturefile 和 alloccapturefile 函数如下:
/*
* put up a dialog to allow the user to select a capture file.
*/
bool setcapturefile(hwnd hwnd)
{
if (openfiledialog(hwnd, gcap.szcapturefile, _max_path)) {
ofstruct os;
// we have a capture file name
/*
* if this is a new file, then invite the user to
* allocate some space
*/
if (openfile(gcap.szcapturefile, &os, of_exist) == hfile_error) {
// bring up dialog, and set new file size
bool f = alloccapturefile(hwnd);
if (!f)
return false;
}
} else {
return false;
}
setappcaption(); // need a new app caption
// tell the file writer to use the new file name
if (gcap.psink) {
wchar wach[_max_path];
multibytetowidechar(cp_acp, mb_precomposed, gcap.szcapturefile, -1,
wach, _max_path);
gcap.psink->setfilename(wach, null);
}
return true;
}
// preallocate the capture file
//
bool alloccapturefile(hwnd hwnd)
{
// we'll get into an infinite loop in the dlg proc setting a value
if (gcap.szcapturefile[0] == 0)
return false;
/*
* show the allocate file space dialog to encourage
* the user to pre-allocate space
*/
if (dodialog(hwnd, idd_alloccapfilespace, alloccapfileproc, 0)) {
// ensure repaint after dismissing dialog before
// possibly lengthy operation
updatewindow(ghwndapp);
// user has hit ok. alloc requested capture file space
bool f = makebuilder();
if (!f)
return false;
wchar wach[_max_path];
multibytetowidechar(cp_acp, mb_precomposed, gcap.szcapturefile, -1,
wach, _max_path);
if (gcap.pbuilder->alloccapfile(wach,
gcap.wcapfilesize * 1024l * 1024l) != noerror) {
messageboxa(ghwndapp, "error",
"failed to pre-allocate capture file space",
mb_ok | mb_iconexclamation);
return false;
}
return true;
} else {
return false;
}
}
建立graph builder对象
amcap的 makebuilder函数建立了一个capture graph builer对象,通过调用cocreateinstance获得了icapturegraphbuilder 接口指针。amcap把他存储到gcap结构的pbuilder中。
// make a graph builder object we can use for capture graph building
//
bool makebuilder()
{
// we have one already
if (gcap.pbuilder)
return true;
ulong cfetched;
imoniker *pm; // this will access the actual devices
gcap.pvcap = null;
while(hr = pem->next(1, &pm, &cfetched), hr==s_ok)
{
if ((int)uindex == gcap.ivideodevice) { // this is the one we want. instantiate it.
hr = pm->bindtoobject(0, 0, iid_ibasefilter, (void**)&gcap.pvcap);
pm->release(); // we don't need the moniker pointer anymore
break;
}
pm->release();
uindex++;
}
pem->release(); // we've got the device; don't need the
enumerator anymore
当有了设备后,通过接口指针去测量帧数,得到driver的名字,得到捕捉的尺寸(size)。在例子中,把每个指针都存储才gcap全局结构中了。
, and get the capture size. amcap stores each pointer in the gcap global structure.
// we use this interface to get the number of captured and dropped frames
gcap.pbuilder->findcaptureinterface(gcap.pvcap,
iid_iamdroppedframes, (void **)&gcap.pdf);
// we use this interface to get the name of the driver
gcap.pbuilder->findcaptureinterface(gcap.pvcap,
iid_iamvideocompression, (void **)&gcap.pvc);
// we use this interface to set the frame rate and get the capture size
gcap.pbuilder->findcaptureinterface(gcap.pvcap,
iid_iamvideostreamconfig, (void **)&gcap.pvsc);
然后得到媒体的类型和显示窗口的大小去匹配视频格式的尺寸。
am_media_type *pmt;
gcap.pvsc->getformat(&pmt); // current capture format
stdmethodimp cvfwcapture::load(lppropertybag ppropbag, lperrorlog perrorlog)
{
hresult hr;
cautolock cobjectlock(m_plock); // locks the object; automatically unlocks it in the destructor.
if (m_pstream) // if the filter already exists for this stream
return e_unexpected;
variant var; // variant from platform sdk
var.vt = vt_i4; // four-byte integer (long)
hr = ppropbag->read(l"vfwindex", &var, 0); // vfwindex is the private name used by the vidcap class manager to refer to the vfw capture filter
if(succeeded(hr)) // if it read the properties successfully
{
hr = s_ok; // defaults return value to s_ok
m_ivideoid = var.lval; // stores the specified hardware device number
createpins(&hr); // inits the pins, replacing the return value if necessary
}
return hr; // returns s_ok or an error value, if createpins failed
包括在directshow sdk中的接口,类,和例子提供了音/视频捕捉和回放的功能。因为文件源过滤器和filter graph manager处理了内在的工作,所有,添加捕捉功能到一个应用程序中,只需添加很少的代码。你可以通过列举系统硬件设备和得到设备列表完成特别的任务(例如:所有的视频捕捉卡的列表)。directshow自动为win32和video for windows 设备实例化过滤器。
ienummoniker *pem;
hr = pcreatedevenum->createclassenumerator(clsid_videoinputdevicecategory, &pem, 0);
pcreatedevenum->release(); // we don't need the device enumerator anymore
pem->reset(); // go to the start of the
enumerated list