Write C + + program to make DirectShow video capture _c language

Source: Internet
Author: User

The build of video capture graph
a graph graph that captures audio or video is called a capture graph. Capturing graphs is much more complex than normal file playback graphs, DShow provides a capture graph Builder COM component that makes capturing graph generation simpler. The Capture Graph Builder provides a ICAPTUREGRAPHBUILDER2 interface that provides methods for building and controlling capture Graph. The
first creates a capture Graph builder object and a graph Manger object, and then uses the filter Graph Manager as a parameter to invoke ICaptureGraphBuilder2:: Setfiltergraph to initialize capture Graph Builder. Look at the following code:

HRESULT Initcapturegraphbuilder (igraphbuilder **ppgraph,//receives pointer Icapturegraphbuilde 
  R2 **ppbuilder)//receives the pointer {if (!ppgraph | |!ppbuilder) {return e_pointer; 
  } igraphbuilder *pgraph = NULL; 
  ICaptureGraphBuilder2 *pbuild = NULL;  
                    Create the Capture Graph Builder HRESULT hr = CoCreateInstance (Clsid_capturegraphbuilder2, NULL, 
 
  Clsctx_inproc_server, Iid_icapturegraphbuilder2, (void**) &pgraph); if (secceeded (HR)) {//create the Filter Graph Manager hr = CoCreateInstance (clsid_filtergraph, 0, CLSCTX_INPR 
    Oc_server, Iid_igraphbuilder, (void**) &pgraph); 
      if (secceeded (HR)) {//initialize The Capture Graph Builder pbuild->setfiltergraph (pgraph); 
      Return both interface pointers to the caller *ppbuild = Pbuild;   *ppgraph = pgraph; The caller must release both interface 
      return S_OK; 
    else {pbuild->release ();     } return HR; 
 Failed}


Device for video capture
now many new video capture devices are used in WDM drive method, in the WDM mechanism, Microsoft provides a hardware-independent driver, called Class driver. Drivers that are supplied by the vendor are called Minidrivers. Minidrivers provides functions that deal directly with the hardware, in which class drivers are invoked.
In the DirectShow filter chart, any WDM capture device appears as a WDM video capture filter (filter). WDM video capture filters based on the characteristics of the driver to build their own filter

Type of filter pin for video capture in Direcshow

The capture filter typically has two or more output pins, and they output the same type of media, such as previewing the pin and capturing the pin, so the pins cannot be distinguished according to the media type. Each pin is differentiated according to the function of the pin, and each pin has a GUID, called the pin type.
If you want to get a closer look at the type of pin, see the related content working with pin Categories. For most applications, ICAPTUREGRAPHBUILDER2 provides a number of functions that can automatically determine the type of pin.
Preview pin and capture pin

Video Capture filter provides a preview and capture of the output pin, the preview pin is used to display the video stream on the screen, and the capture pin is used to write the video stream to the file.

Preview pin and output pin have the following differences:
1 in order to ensure the capture pin to the video frame flow, preview the pin when necessary to stop.
2 video frames that capture pins have timestamps, but the video stream that previews the pin does not have a timestamp.

The reason the video stream that previews the pin does not have a timestamp is because the filter chart manager has a small latency in the video stream, and if capturing time is considered to be render time, the video Renderfilter thinks the video stream has a small delay. If render filter attempts to play continuously at this time, it will drop the frame. Remove the time stamp to ensure that the video frame can be played, do not wait, also do not throw frames.

    • Type of preview pin GUID is Pin_category_preview
    • The type of the pin to catch is GUID pin_category_capture

Video Port Pin
The video port is a hardware device that is located between a visual device (TV) and a video card. With the video Port, videos can be sent directly to the image card, through the hardware coverage, video can be directly displayed on the screen. The video port is connected to two devices.
The biggest advantage of using the video port is that the stream is written directly into memory without any work on the CPU.
If the capture device uses the video port, capture filter replaces the preview pin with a video port pin.

The type GUID for the video port pin is Pin_category_videoport

A capture filter has at least one capture pin, in addition, it may have a preview pin and a video port pin, or neither, perhaps filter has a lot of capture pin, and preview pin, each pin represents a media type, So a filter can have a video capture pin, video preview pin, audio capture pin, audio preview pin.

Upstream WDM Filters
on top of the capture filter, the WDM device may require additional filters, and the following is the filter

    • TV Tuner Filter
    • TV Audio Filter.
    • Analog Video Crossbar Filter

Although these are independent filter, they may represent the same hardware device, each filter controls the different functions of the device, which are connected by a pin, but there is no data flow in the PIN. Therefore, the connection to these pins is independent of the media type. They use a GUID value to define the minidriver of a given device, for example: TV tuner Filter and video capture filter all support the same medium.

In practical applications, if you use ICaptureGraphBuilder2 to create your capture graphs, these filters will automatically be added to your graph. For more detailed information, you can refer to the WDM Class Driver Filters.

Select a video capture device (select Capture device)

How to select a video capture device, you can use the system device enumeration, details see Using the Systems Device Enumerator. Enumerator can return the monikers of a device based on the type of filter. Moniker is a COM object, and you can see the SDK for IMoniker.

For capture devices, the following two kinds are relevant.

    • Clsid_audioinputdevicecategory Audio Device
    • Clsid_videoinputdevicecategory Video Equipment

The following code shows how to enumerate a video capture device

Icreatedevenum *pdevenum = NULL; 
IEnumMoniker *penum = NULL; 
 
Create the System device Enumerator 
HRESULT hr = CoCreateInstance (Clsid_systemdeviceenum, NULL, 
               Clsct_inproc _server, Iid_icreatedevenum,  
               reinterpret_cast<void**> (&pdevenum)); 
 
if (SUCCEEDED (HR)) 
{ 
  //Create an enumerator, enumerate video device 
  hr = Pdevenum->createclassenumerator (clsid_ Videoinputdevicecategory,  
                    &penum, 0); 
} 


The IEnumMoniker interface Penum returns a list of IMoniker interfaces, representing a range of moniker, where you can display all the devices and then let the user select one.
Using the Imoniker::bindtostorage method, returns a IPropertyBag interface pointer. The ipropertybag::read is then invoked to read the moniker properties. Here's a look at what attributes are included:

1 FriendlyName is the name of the device
The 2 Description property applies only to DV and d-vhs/mpeg cameras, and if this property is available, this property describes the device's data in more detail.
3DevicePath This property is unreadable, but each device has a unique one. You can use this attribute to distinguish different instances of the same device

The following code shows how to display the name of the traversing device, followed by the code

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 would work 
  } 
  VARIANT varName; 
  hr = Ppropbag->read (L "Description", &varname, 0); 
  if (FAILED (HR)) 
  { 
    hr = Ppropbag->read (L "FriendlyName", &varname, 0); 
  } 
  if (secceeded (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 (); 
} 


If the user selects a device call IMoniker::BindToObject generates filter for the device and then adds filter to graph.

Ibasefilter *pcap = NULL; 
hr = pmoniker->bindtoobject (0, 0, Iid_ibasefilter, (void**) &pcap); 
if (secceeded (HR)) 
{ 
  hr = M_pgraph->addfilter (Pcap, L "Capture Filter"); 


To create graph that can preview the video, you can call the following code:

ICaptureGraphBuilder2 *pbuild;   Capture Graph Builder 
//initialize pbuild (not shown) 
... 
Ibasefilter *pcap;                 Video Capture filter 
hr = Pbuild->renderstream (&pin_category_preview, &mediatype_video, 
                        pcap , NULL, NULL); 
 

How to capture a video stream and save it to a file (Capture)

1 Save video stream to AVI file

Avi Mux Filter receives a video stream from the capture pin and then packs it into an AVI stream. The audio stream can also be connected to AVI Mux Filter so that Mux filter synthesizes the video stream and the video stream into an AVI stream. File writer writes an AVI stream to a file.
You can build graphs like this

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 



The first parameter indicates the type of file, which indicates AVI, and the second parameter is the name of the file being developed. For AVI files, the Setoutputfilename function creates an AVI MUX filter and a file writer filter, and adds two filter to the graph, in this function, through the file writer The Filter requests the Ifilesinkfilter interface, and then calls the Ifilesinkfilter::setfilename method to set the name of the file. Then connect the two filter. The third argument returns a pointer to the AVI MUX, and it also returns a ifilesinkfilter parameter through the fourth argument, which you can set to NULL if you do not need this parameter.
Then, you should call the following function to connect capture filter and 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 

The 5th parameter is the Pmux pointer that is returned using the function above.
When capturing audio, the media type should be set to Mediatype_audio, if you capture video and audio from two different devices, you'd better set the audio to mainstream so that you can prevent two data streams from drift because AVI MUX filter is sync audio, Adjusts the playback speed of the video. To set up the master stream, invoke the Iconfigavimux::setmasterstream method, which can take the following code:

Iconfigavimux *pconfigmux = NULL; 
hr = Pmux->queryinterface (Iid_iconfigavimux, (void**) &pconfigmux); 
if (SUCCEEDED (HR)) 
{ 
  pconfigmux->setmasterstream (1); 
  Pconfigmux->release (); 
} 

The Setmasterstream parameter refers to the number of data streams, which are determined by the order in which the Renderstream is invoked. For example, if you call Renderstream first for the video stream, then the audio, then the video stream is 0, and the audio stream is 1.
Add Encoding Filter

Ibasefilter *pencoder; 
Add it to the filter graph 
pgraph->addfilter (Pencoder, L "Encode"); 
Render the stream 
hr = Pbuild->renderstream (&pin_category_capture, &mediatype_video,  
             Pcap, Pencoder, Pmux); 
Pencoder->release (); 

2 Save the video stream to a file in WMV format

To save the video stream to a file that is encoded in Windows Media Store (WMV) format, connect the capture pin to the WM ASF Writer filter.

The easiest way to build a graph graph is to specify MEDIASUBTYPE_ASF filter in the Icapturegraphbuilder2::setoutputfilename method. As follows

Ibasefilter *pasfwriter = 0; 
hr = Pbuild->setoutputfilename (&mediasubtype_asf,    //create a Windows Media file 
                L "C:\\vidcap.wmv",        //file name 
                &pasfwriter,       //receives A pointer to the filter 
                NULL);        Receives an Ifilesinkfilter interface pointer (optional)

Parameter mediasubtype_asf tells graph Builder to use the WM ASF writer as a file sink, Pbuild creates the filter, adds it to the graph, and then invokes Ifilesinkfilter: Setfilename to set the name of the output file. The third parameter is used to return an ASF writer pointer, and the fourth parameter is used to return a pointer to the file.

Before connecting any PIN to the WM ASF writer, be sure to set up the WM ASF writer, which you can set with the Iconfigasfwriter interface pointer of the WM ASF writer.

Iconfigasfwriter *pconfig = 0; 
hr = Pasfwriter->queryinterface (Iid_iconfigasfwriter, (void**) &pconfig); 
if (SUCCEEDED (HR)) 
{ 
  //configure the ASF Writer filter 
  pconfig->release (); 
} 
Then call Icapturegraphbuilder2::renderstream to connect capture Filter and ASF Writer:
hr = Pbuild->renderstream (&pin_category_capture,     //capture PIN 
             &mediatype_video,       //Video . Use Mediatype_audio for Audio 
             pcap,     //pointer to the capture filter 
             0,  
             pasfwriter);   Pointer to the sink filter (ASF filter) 


3 saved as a custom file format
if you want to save your files in your own format, you must have your own file writer. Look at the following code:

Ibasefilter *pmux = 0; 
Ifilesinkfilter *psink = 0; 
hr = Pbuild->setoutputfilename (&clsid_mycustommuxfilter,   //Develop own filter 
                L "C:\\vidcap.avi", & Pmux, &psink); 
 

4 How to save a video stream into multiple files
When you save a video stream into a file, if you want to start saving the second file, you should first stop graph and then change the file name by Ifilesinkfilter::setfilename. Note that you can return the Ifilesinkfilter pointer by using the fourth argument at Setoutputfilename.
Look at the code that holds multiple files:

Ibasefilter *pmux = 0; 
Ifilesinkfilter *psink = 0; 
hr = Pbuild->setoutputfilename (&mediasubtype_avi,  
                L "C:\\yourfilename.avi", &pmux, &pSink); 
if (SUCCEEDED (HR)) 
{ 
  hr = Pbuild->renderstream (&pin_category_capture, &mediatype_video, 
                        Pcap, NULL, Pmux); 
  if (SUCCEEDED (HR)) 
  { 
    pcontrol->run (); 
    Pcontrol->stop (); 
    Change the file name and run the graph again 
    psink->setfilename (L "Yourfilename02.avi", 0); 
    Pcontrol->run (); 
  } 
 
  Pmux->release (); 
  Psink->release (); 
} 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.