DirectShow's Chinese data creates a capture program

zhaozj2021-02-11  208

DirectShow provides the ability to capture and preview / video from your application from your appropriate hardware. Data sources include: VCR, Camera, TV Tuner, MicroPhone, or other data sources. An application can immediately display capture data (preview), or save it to a file.

In this example, the ICapturegraphBuilder interface is the main interface for processing capture work. You can use the same method and interface in your own capture program. Here mainly discusses how ICAPTuregraphBuilder performs tone / video capture. We assume that you are familiar with the architecture of DirectShow's Filter Graph and the structure of the general Capture Filter Graph (you can refer to the DirectShow Infrastructure).

The ICAPTUREGRAPHBUILDER interface provides a Filter Graph Builder object that allows your application to handle many monotonous work when establishing Capture Filter Graph, and concentrate on capture. His offers meet the requirements of basic capture and preview features.

Method FindInterface, finds a detailed interface to capture in the Filter GRAPH. Make you access to a detailed interface, do not need you to list Pins and Filters in Filter Graph. Method Renderstream, connection source filters, and rendering filters, choose to add some intermediate filters. Method ControlStream, independent precise control of the start and end frame of Graph.

Since hardware capture, of course, you have to deal with hardware, then introduce the device to capture the interface. Enumeral to capture the device in the system via the IcreateDevenum :: CreateClassenumerator method. After that, instantiate a DirectShow's Filter to use this device. Then use ICapturegraphBuilder :: FindInterface to get the capture-related interface pointer IamdroppedFrames, IamvideoCompression, Iamstreamconfig, and IamvfwcaptureDialogs. Because the device enumeration and capture interfaces are relatively long, it will be chaos, and all special writes (reference device enumeration and capture interface).

Note: 1. This example is an example of DirectShow comes. You can see this example code (amcap.cpp) in DirectShow SDK directory Sample / DS / Caputre. Here is just some of his piece of fragment. It can be said that it is his Chinese module. 2. Amcap example, save all interface pointers and some member variables 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; when an interface pointer is not need to save GCAP is sure to Release these interface pointers, typically in the destructive function of the program, or in other equivalents. As follows: if (gcap.pbuilder) gcap.pbuilder-> release (); gcap.pbuilder = null; if (gcap.psink) gcap.psink-> release (); gcap.psink = null; if (gcap.pconfigavimux) gcap.pconfigavimux-> Release (); gcap.pconfigavimux = null; if (gcap.prender) gcap.prender-> release (); gcap.prender = null; if (gcap.pvw) gcap.pvw-> release () GCAP.PVW = NULL; if (gcap.pme) gcap.pme-> release (); gcap.pme = null; if (gcap.pfg) gcap.pfg-> release (); gcap.pfg = null;

Setting the file name Use normal OpenFile Dialog to get information about capture files. Assign space to the capture file by calling the AllocCaptureFile function. This is important because it is a huge space. This can improve the speed of the capture operation. ICAPTUREGRAPHBUILDER :: AlloccapFile Performs the actual file allocation, ifilesinkfilter :: setFileName indicates that the file name that File Writer Filter uses the user selected file name to save data. IcapturegraphBuilder :: setOutputFileName Add File Writer Filter to Filter Graph (later, he is IcapturegraphBuilderd self-generation). SetCaptureFile AllocCaptureFile and functions are as follows: / * * 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, the invite the user to * allocate some space * / if (OpenFile (gcap.szcape, os, of_exist) == hfile_error) {

// Bring Up Dialog, and set new file size bool f = allocapturefile (hwnd); if (! F) return false;}} else {returnaf 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 repaintARSILOG BEFORE / / POSSIBLY longthy operation updateWindow (GHWNDAPP);

// User has hit OK Alloc requested capture file space BOOL f = MakeBuilder ();. If return FALSE (f!); 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 Else {Return false;}} Create a Graph Builder object

The AMCAP's Makebuilder function has established a Capture Graph Builer object to get the ICAPTureGraphBuilder interface pointer by calling CocreateInstance. AMCAP stores him into the PBUilder of the GCAP structure. // Make a graph Builder Object We can use for capture graph building // Bool makebuilder () {// we have one already if (gcap.pbuilder) Return True;

HRESULT hr = CoCreateInstance ((REFCLSID) CLSID_CaptureGraphBuilder, NULL, CLSCTX_INPROC, (REFIID) IID_ICaptureGraphBuilder, (void **) & gcap.pBuilder); return (hr == NOERROR) TRUE:? FALSE;}

Establish a graph's rendering section and tell him to write the file (with the previously decided file)

This includes a Multiplexer Filter and File Writer. DirectShow provides an AVI MUX (Multiplexer) Filter. Here IcapturegraphBuilder :: setOutputFileName is a key way. He added Multiplexer and File Writer to Filter Graph, connect them, and set the name of the file. The first parameter mediaubtype_avi indicates that the Capture Graph Builder object will insert an AVI MULTIPLEXER FILTER, so the File Writer will record the captured data in the AVI file format. The second parameter (WACH) is the file name. The last two parameters indicate Multiplexer Filter (gcap.prender) and File Writer Filter (GCAP.PSINK), which is initialized by the SetOutputFileName function. AMCAP stores these pointers to the global structure GCAP. The Capture Graph Builder has a FILTER GRAPH object (IGRAPHBUILDER), adding these two filters to the Filter Graph. He tells File Writer to save data using the specified file. The following example demonstrates how to call SetOutputFileName. //// We need a rendering section that will write the capture file out in AVI // file format // WCHAR wach [_MAX_PATH]; MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, gcap.szCaptureFile, -1, wach, _MAX_PATH); GUID guid = MediaSubtype_avi; hr = gcap.pbuilder-> setoutputFileName (& gcap.psink); if (hr! = Noerror) {errmsg ("Error% x: cannot setput file", hr); goto Setupcapturefail;

Get current Filter Graph

Because in call setoutputFileName, the Capture Graph Builder object has established a Filter Graph, all you must add the required Filter to the same filter graph. Get newly created Filter Graph through IcapturegraphBuilder :: getFiltergraph. The returned pointer is the parameter GCAP.PFG. /////////////// '

HR = gcap.pbuilder-> getfiltergraph (& gcap.pfg); if (hr! = noerror) {errmsg ("Error% x: cannot get filtergraph", hr); goto setupcapturefail;}

Adding a sound / video filter to the current filter graph hr = gcap.pfg-> addfilter (gcap.pvcap, null); if (hr! = Noerror) {errmsg ("Error% x: cannot add vidap to filtergraph", HR ); Goto setuppreviewFail;} hr = gcap.pfg-> addfilter (gcap.pacap, null); if (hr! = Noerror) {errmsg ("ERROR% x: cannot add Audcap to filtergraph", HR); goto setupcapturefail; }

Rendering video capture Capture PIN and audio capture Capture PinicapturegraphBuilder :: Renderstream connection source filter PIN to rendering filter. The category of the PIN is optional, capture pin (pin_category_capture) or preview pin (pin_category_preview). The following example demonstrates the Capture PiN to the Video Capture Filter (GCAP.PVCAP) to render GCAP.Prender. /// RENDER THE Video Capture and Preview Pins - WE May Not Have Preview, SO // Don't Worry IF IT Doesn't Work //

HR = gcap.pbuilder-> renderstream (& pin_category_capture, null, gcap.pvcap, null, gcap.prender); // error Checking

Audio Capture Filter (GCAP.PACAP) is again connected to the Audio Renderer again. /// RENDER THE AUDIO CAPTURE PIN? //

IF (gcap.fcapaudio) {hr = gcap.pbuilder-> renderstream (& pin_category_capture, null, gcap.pacap, null, gcap.prender); // error Checking

Rendering Video Capture Filter's Preview PIN again calls IcapturegraphBuilder :: Renderstream, from the Preview Pin of Capture Filter to Video Renderer. The code is as follows: hr = gcap.pbuilder-> renderstream (& pin_category_preview, null, gcap.pvcap, null, null);

Get the interface pointer of the Video Preview Window, Video Preview Window is a separate window. If you want to change the default behavior, please call iCaptureGraphBuilder :: FindInterface to get the iVideoWindow interface. The second parameter is specified by gcap.pvcap, describing the Video Capture Filter, the third parameter is an iVideoWindow, and finally the return interface. When you get the iVideoWindow interface, you can call the iVideoWindow method like PUT_OWNER, PUT_WINDOWSTYLE, or setWindowPosition to get the VIDEO Preview Window's Handle, set the window properties, or put him in the desired location. // This will go through a possible decoder, find the video renderer it's // connected to, and get the IVideoWindow interface on it hr = gcap.pBuilder-> FindInterface (& PIN_CATEGORY_PREVIEW, gcap.pVCap, IID_IVideoWindow, (void **) & gcap .pvw); if (hr! = noerror) {Errmsg ("this graph cannot preview");} else {rect rc; gcap.pvw-> put_owner ((long) ghwndapp); // We own the window NOW GCAP. pVW-> put_WindowStyle (WS_CHILD); // you are now a child // give the preview window all our space but where the status bar is GetClientRect (ghwndApp, & rc); cyBorder = GetSystemMetrics (SM_CYBORDER); cy = statusGetHeight () Cyborder; rc.bottom - = cy; gcap.pvw-> setWindowPosition (0, 0, rc.right, rc.bottom); // be this Big gcap.pvw-> put_visible (oatrue);} Now you have established a complete Capture Filter Graph, you can preview audio, video, or capture data.

Control Capture Filter GRAPH

Because Capture Filter Graph constructed by the ICapturegraphBuilder interface is just a simple special purpose Filter Graph, all, control him like controlling other types of Filter Graph. You can use the IMEDIACONTROL Interface Run, Pause, and Stop, you can also use CBASEFILTER :: Pause. In addition, IcapturegraphBuilder provides the ControlStream method to control the start and end time of the streams of the Capture Filter Graph. ControlStream calls IamstreamControl :: Startat and IamstreamControl :: Stopat Control the start and preview of the Filter Graph's capture and preview. Note: Not all Capture Filter can, because every Capture Filter supports IamstreamControl.

The first parameter of the ICAPTUREGRAPHBUILDER :: ControlStream method is a GUID of an output PIN class. This variable is usually PIN_CATEGORY_CAPTURE or PIN_CATEGORY_PREVIEW. Specifies that NULL controls all Capture Filter. The second parameter pointed out that Filter control. NULL illustrates all Filter Graphs. If you just preview (prevent capture), you can call ICAPTUREGRAPHBUILDER :: ControlStream, parameter with Capture Pin type, max_time as the start time (third parameter, pstart). Call the method again, the parameter uses the Preview PIN type, and NULL starts to preview immediately as the start time. The fourth parameter indicates the end of the time (PSTOP), the meaning, and the third parameter (NULL means immediate). Max_time is defined in DirectShow as the largest reference time. Here, it means ignoring or canceling the specified operation. The last parameters, WstartCookie and Wstopcookie are cookies that start and end, respectively (I don't know how to translate, because I don't understand the meaning of this parameter). The following code settings begin to preview, but ignore the capture. // Let the preview section run, but not the capture section // (There might not be a capture section) REFERENCE_TIME start = MAX_TIME, stop = MAX_TIME;? // show us a preview first but do not capture quite yet .. . hr = gcap.pBuilder-> ControlStream (& PIN_CATEGORY_PREVIEW, NULL, gcap.fWantPreview NULL: & start, gcap.fWantPreview & stop:?? NULL, 0, 0); if (SUCCEEDED (hr)) hr = gcap.pBuilder-> ControlStream (& Pin_category_capture, null, & start, null, 0, 0); Similarly, if you only want to capture instead of preview, set the captured start time to null, set the capture end time to max_time. Set the start time of the preview to max_time, null is the end time. The following example tells Filter Graph Start Preview (the third parameter: start time is null). End Time Specifies to max_time means ignoring the stop time (let it go down). GCap.pbuilder-> ControlStream (& pin_category_preview, null, null, max_time, 0, 0);

IMediaControl :: Run Run call graph // Run the graph IMediaControl * pMC = NULL; HRESULT hr = gcap.pFg-> QueryInterface (IID_IMediaControl, (void **) & pMC); if (SUCCEEDED (hr)) {hr = pMC- > Run (); if (Failed (HR)) {// stop parts ();} PMC-> Release ();} if (Failed (HR)) {errmsg ("Error% x: Cannot Run Preview Graph ", HR); Return False; If Graph has run, start capture by calling ICApturegraphBuilder :: ControlStream immediately. For example, the following code controls the entire Filter Graph (the second parameter null), immediately begins (the third parameter is null), and never stopped (the fourth parameter is MAX_TIME). // Now! Gcap.pbuilder-> controlstream (& pin_category_capture, null, max_time, & stop, 0, 0); stop preview or capture operation, call iMediaControl :: stop, just call iMediaControl :: run. // stop the graph imediacontrol * pmc = null; hResult hr = gcap.pfg-> queryinterface (IID_IMEDIACONTROL, (void **) & pmc); if (successded (HR)) {hr = pmc-> stop (); PMC- > Release ();

Get capture information

Get it through the IamdroppedFrames interface. Test the number of lost frames (iamdroppedframes :: getnumdropped), captured quantity (iamdroppedframes :: getnumnotdropped). The IamdroppedFrames :: GetaveRageFramesize method provides average size of capture frames (unit: byte). Use this information to know that the total capture byte and the number of frames per second (rate).

save document

The originally allocated capture file is just a temporary saving data, all you can capture as fast as possible. When you want to save the captured data into your hard drive, call ICAPTUREGRAPHBUILDER :: CopyCaptureFile. This method outputs data from previous capture files to another file you selected. This new storage file is matched with actual captured data, not compatible with the previous file size. The first parameter of the ICAPTUREGRAPHBUILDER :: CopyCaptureFile method is a replication source, the second is the target file. The third parameter is set to TRUE indicates that the user is allowed to interrupt the replication operation with the ESC key. The last parameter is optional. Allows you to provide a process indicator. If you want, you can perform the IAMCopyCaptureFileProgress interface. The following example describes how to call CopyCaptureFile. HR = Pbuilder-> Copycapturefile (Wachsrcfile, Wachdstfile, True, NULL);

Get the new file name by ordinary open file dialog. Use the multibytetowideChar function to transfer the file name to Wide String, saving the captured data into the specified file using IcapturegraphBuilder :: CopyCaptureFile. / * * Put up a dialog to allow the user to save the contents of the capture file * elsewhere * / BOOL SaveCaptureFile (HWND hWnd) {HRESULT hr; char achDstFile [_MAX_PATH]; WCHAR wachDstFile [_MAX_PATH]; WCHAR wachSrcFile [_MAX_PATH] ; if (gcap.pbuilder == null) Return False;

IF (OpenFileDialog (hwnd, achdstfile, _max_path) {

// We have a capture file name MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, gcap.szCaptureFile, -1, wachSrcFile, _MAX_PATH); MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, achDstFile, -1, wachDstFile, _MAX_PATH); statusUpdateStatus (ghwndStatus, "Saving capture file - please wait ... ");

// We need our own graph builder because the main one might not exist ICaptureGraphBuilder * pBuilder; hr = CoCreateInstance ((REFCLSID) CLSID_CaptureGraphBuilder, NULL, CLSCTX_INPROC, (REFIID) IID_ICaptureGraphBuilder, (void **) & pBuilder); if (hr == {// allow the user to press esc to abort ... don't ask for progress HR = Pbuilder-> CopyCaptureFile (Wachsrcfile, Wachdstfile, true, null); pbuilder-> release ();} if (hr = = S_OK) statusUpdateStatus (ghwndStatus, "Capture file saved"); else if (hr == S_FALSE) statusUpdateStatus (ghwndStatus, "Capture file save aborted"); else statusUpdateStatus (ghwndStatus, "Capture file save ERROR"); return (hr == Noerror? True: false);

} else {return true; // they candeled or something}}

For details on capturing media files and get capture information, you can refer to AMCAP.cpp and Status.cpp.

转载请注明原文地址:https://www.9cbs.com/read-4318.html

New Post(0)