This explanation and examples how to initialize and access the system's hardware devices through the interface of DirectShow. Representative, DirectShow applications use the hardware of the following types.
Tone / Video Capture Card Audio or Video Card Audio or Video Compression or Decompression Card (like MPEG Decoder) will be referred to by AV device.
How to enumerate equipment
Includes interfaces, classes, and examples of DirectShow SDK provide sound / video capture and playback. Because the file source filter and Filter Graph Manager processes internal work, all, add a capture function to an application, just add a few code. You can use the system hardware device and get a special task (for example: a list of all video capture cards). DirectShow automatically instantizes the filter for Win32 and Video for Windows devices.
To work to be AV, first, you must detect the device existing in the current system. The ICreateDevenum interface establishes a list of specified types. Provide you need to detect and set hardware features. Accessing a specified device has three steps, detailed instructions and code as follows:
Establish a list of system hardware devices First, declare a list pointer and build it via CoCreateInstance. CLSID_SYSTEMDEVICEENUM is the type we want to build an object, and IID_ICREATEDEVENUM is the GUID of the interface.
IcreateDevenum * pcreatedEvenum; CoCreateInstance (CLSID_SYSTEMDEVICEENUM, NULL, CLSCTX_INPROC_SERVER, IID_ICREATEDEVENUM, (Void **) & pcreateDevenum);
Second, establish a special type of hardware device list (such as video capture card), declare a Ienummoniker interface, pass him to the IcreateDevenum :: CreateClassenumerator method. You can use his access to the new list.
Ienummoniker * penummon; pcreatedevenum-> createClassenumerator ([Specify Device Guid Here] & Penummon, 0);
Finally, list the list until you get the device you want. If the previous CreateClassenumerator call is successful, you can get the device with Ienummoniker :: next. Call iMoniker :: bindtoObject to create a combined FILTER in which you select Device, and load the Filter's property (CLSID, FriendlyName, and DevicePath). No need to confuse the IF statement, before testing legitimacy, Penummon-> Next (1, & pmon, & cfetched) method sets his number to return to an object (if successful is 1).
Ulong cfetched = 0; iMoniker * PMON;
IF (S_OK == (Penummon-> Next (1, & PMON, & CFETCHED)) && (1 == CFETCHED)) {PMON-> BindToObject (0, 0, IID_IBASEFILTER, (Void **) & [Desired Interface Here]) ;
Ok, now you have an IMONIKER pointer, you can add the device's Filter to Filter Graph. Once you have added Filter, you don't need the IMONIKER pointer, a list of devices, or a list of system devices.
PGRAPH-> AddFilter ([Desired Interface Here], L "[Filter Name Here]"); PMON-> Release (); // Release Moniker} Penummon-> Release (); // Release The class enumerator} PcreatedEvenum-> Release (); instance: device list code in AMCAP
In the AMCAP example, all interface pointers and some member variables are saved in a global structure GCAP. Is defined as follows: struct _capstuff {char szCaptureFile [_MAX_PATH]; WORD wCapFileSize; // size in Meg ICaptureGraphBuilder * pBuilder; IVideoWindow * pVW; IMediaEventEx * pME; IAMDroppedFrames * pDF; IAMVideoCompression * pVC; IAMVfwCaptureDialogs * pDlg; IAMStreamConfig * pASC; // for audio cap IAMStreamConfig * pVSC; // for video cap IBaseFilter * pRender; IBaseFilter * pVCap, * pACap; IGraphBuilder * pFg; IFileSinkFilter * pSink; IConfigAviMux * pConfigAviMux; int iMasterStream; BOOL fCaptureGraphBuilt; BOOL fPreviewGraphBuilt; BOOL fCapturing; BOOL fPreviewing; BOOL fCapAudio; int iVideoDevice; int iAudioDevice; double FrameRate; BOOL fWantPreview; long lCapStartTime; long lCapStopTime; char achFriendlyName [120]; BOOL fUseTimeLimit; DWORD dwTimeLimit;} gcap;
Examples list the hardware devices of the system with the UINDEX variable cycle. Bool INITCAPFILTERS () {HRESULT HR; BOOL F; uint uINDex = 0;
The Makebuilder function creates a Filter Graph Builder (refer to the creation of a capture program).
f = makebuilder ();
Establish a list of devices to get the IcreatedEvenum interface
IcreateDevenum * pcreatedEvenum; hr = cocreateInstance (CLSID_SYSTEMDEVICEENUM, NULL, CLSCTX_INPROC_SERVER, IID_ICREATEDEVENUM, (VOID **) & PCREATEDEVENUM);
Establish a list of special types of hardware devices, the ID of the class is CLSID_VideoInputDeviceCategory. Now there is a Ienummoniker pointer that can access the list of capture devices.
IEnumMoniker * pEm; hr = pCreateDevEnum-> CreateClassEnumerator (CLSID_VideoInputDeviceCategory, & pEm, 0); pCreateDevEnum-> Release (); // We do not need the device enumerator anymore pEm-> Reset (); // Go to the start of The Enumerated List now needs the actual device, call IEnummoniker :: next, then use the get pointer PM call iMoniker :: BindToObject, bind the filter to the device. If you don't want to build a union filter, use iMoniker :: BindtoOBject.
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.ivideodeodevice) {// this is the one we want. instantiate it. hr = pm-> bindtoobject (0, 0, IID_IBASEFILTER, (void **) & gcap.pvcap); PM-> Release (); // We don't need name break;} pm-> release (); uINDEX ;} PEM-> release (); // we've got the device; don't need the enumerator Anymore
When there is a device, the number of frames is measured by the interface pointer to get the name of the Driver, and the size of the capture is obtained. In the example, each pointer is stored in the GCAP global structure. 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); then the resulting size and type of media display window to Match the size of the video format.
Am_media_type * pmt; gcap.pvsc-> getformat (& pmt); // Current Capture Format
ResizeWindow (header (pmt-> pbformat) -> BiWidth, Header (PMT-> PBFORMAT) -> Biheight); deletemediatype (PMT);
Now, there is already a video device and his related information, repeat this process, get the audio and his information and store it in a global agency. Note that this time is used to call iCreatedEvenum :: CreateClassenumeUmerator with parameters CLSID_AUDIOINPUTDEVICECATEGORY.
hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **) & pCreateDevEnum); uIndex = 0; hr = pCreateDevEnum-> CreateClassEnumerator (CLSID_AudioInputDeviceCategory, & pEm, 0); pCreateDevEnum-> Release ();
PEM-> reset (); gcap.pacap = null; while (hr = pem-> next (1, & pm, & cfetched), hr == s_ok) {if ((int) uINDEX == gcap.iaudiodevice) {//// This is the one we want hr = pm-> bindtoobject (0, 0, IID_IBASEFILTER, (Void **) & gcap.pacap); PM-> Release (); break;} Pm-> Release (); uINDEX ;} PEM -> Release ();
Amcap Also Repeats The Process of Retrieving The Format Interface, this Time for the Audio Device.
HR = gcap.pbuilder-> FindcaptureInterface (gcap.pacap, IID_iamaudiostreamconfig, (void **) & gcap.pasc);
How to keep DirectShow Filter (Properties) props
The iPropertyBag and IPersistPropertyBag interface stores and returns the "Bags" group of Properties. Properties stored by these interfaces can be kept. The same object is between different instances, they are consistent. Filter can store their Properties (CLSID, FriendlyName, And DevicePath). When a FILTER stores his Properties, DirectShow will automatically get them when an instance is file. Add a function to your Filter, perform the IPersistPropertyBag interface and his method. You can load the filter profterties to the Win32 Variant variable with the iPropertybag :: Read method, then initialize the input and output PIN. The following code demonstrates how DirectShow's VFWCapture Filter performs IPersistPropertyBag :: LOAD method. Remember: During the execution, your Filter must provide a valid iPropertyBag pointer.
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 platage sdk var.vt = vt_i4; // four-byte integer (long) hr = ppropbag-> read (l "vfwindex", & var, 0); // vfwindex is the private name buy 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 Faled