The Sample Grabber filter is a filter that can be inserted, it has its own buffer, stored samples.
If you want to have a simple rush from a video file, then I suggest you use the Media Detector object. Sample Grabber provides more complex and more flexible controls. We use the Sample Grabber filter by the following steps:
1. Specify the type of media you want to rush
You must configure it before the Sample Grabber filter is connected to another filter. First you have to call CocreateInstance to create Sample Grabber, then call the iFiltergraph :: AddFilter to load it into the filter graphics. Then query the ISAMPLEGRABBER interface. We use the isamplegrabber :: setMediaType method to set the media type. This method specifies the media type that the Sample Grabber filter will be connected. You can specify only the primary media type; or the primary type, subtype, and type format.
For example, if you want to get an uncompressed video, this video is compatible with the current display mode, you can set the primary type for MediaTyPE_Video and then set the child type based on the current display bit. The following example may explain the problem:
// Create Sample Grabber.
IBasefilter * pf = null;
ISAMPLEGRABBER * PGRABBER = NULL;
HR = COCREATEINSTANCE (CLSID_SAMPLEGRABBER, NULL, CLSCTX_INPROC_SERVER,
IID_IBASEFILTER, ReinterPret_cast
HR = Pf-> QueryInterface (IID_ISAMPLEGRABBER,
Reinterpret_cast
HR = pgraph-> addfilter (pf, l "samplegrabber);
/ / Find the current color
HDC HDC = Getdc (NULL);
INT ibitDepth = getDeviceCaps (HDC, Bitspixel);
ReleaseDC (NULL, HDC);
// Set the media type
AM_MEDIA_TYPE MT;
ZeromeMory (& MT, SIZEOF (AM_MEDIA_TYPE));
Mt.majortype = mediatype_video;
Switch (ibitDepth)
{
Case 8:
Mt.subtype = MediaSubType_RGB8;
Break;
Case 16:
Mt.subtype = MediaSubtype_RGB555;
Break;
Case 24:
Mt.subtype = MediaSubtype_RGB24;
Break;
Case 32:
Mt.subtype = MediaSubType_RGB32;
Break;
DEFAULT:
Return E_FAIL;
}
HR = pgrabber-> setmediatype (& MT);
2. Create an included Sample Grabber filtering graphic
After you specify the media type, you can build a filter graphic containing Sample Grabber. Sample Grabber will only connect to the specified type, and allow you to use the smart connection mechanism when you create a filter graph.
For example, the previous code specifies the uncompressed video. After you are ready, you can call the iGraphBuilder :: AddSourceFilter method to add capture filters from the video file source stream. In order to insert this filter into the filtration graphics, we also need to call the IGRAPHBUILDER :: Connect method to connect the source filter and Sample Grabber. Filtering Graphics Manager will automatically add a desired decoding filter. The following code is doing this. It uses two helper functions to enumerate pin. The getPin function found the first pin, input or output pin in the filter. The ConnectFilters function finds the first output pin in the filter and then connects this pin to the first input pin of another filter.
HRESULT GETPIN (IBasefilter *, pin_direction, ipin **);
HRESULT ConnectFilters (iGraphbuilder *, IBaseFilter *, IBaseFilter *);
Ibasefilter * psrc;
HR = pgraph-> addsourcefilter (WSZFileName, L "Source", & PSRC);
HR = ConnectTWOFILTERS (PGRAPH, PSRC, PF);
// Helper Functions:
HRESULT GETPIN (IBasefilter * Pfilter, pin_direction pindir, ipin ** pppin)
{
Ienumpins * penum;
Ipin * ppin;
Pfilter-> Enumpins (& Penum);
While (Penum-> Next (1, & PPIN, 0) == S_OK)
{
PIN_DIRECTION PINDIRTHIS;
PPIN-> Querydirection (& Pindirthis);
IF (Pindir == PindIRTHIS)
{
Penum-> Release ();
* PPPIN = PPIN;
Return S_OK;
}
PPIN-> Release ();
}
Penum-> Release ();
Return E_FAIL;
}
HRESULT ConnectFilters (iGraphbuilder * PGRAPH, IBASEFILTER * PFIRST, IBASEFILTER * PSECOND)
{
IPIN * Pout = NULL, * PIN = NULL;
HRESULT HR = Getpin (Pfirst, Pindir_output, & Pout);
IF (Failed (HR)) Return HR;
HR = getpin (psecond, pindir_input, & pin);
IF (Failed (HR))
{
Pout-> Release ();
Return E_FAIL;
}
HR = PGRAPH-> Connect (Pout, PIN);
PIN-> Release ();
Pout-> Release ();
Return HR;
}
The application must connect to the output pin of the Sample Grabber. If you want to discard the sample, you can connect the Null Renderer filter. This filter will discard every 桢 it receives.
Ibasefilter * pnull = null;
HR = CocreateInstance (CLSID_NULLRENDERER, NULL, CLSCTX_INPROC_SERVER,
IID_IBASEFILTER, Reinterpret_cast
HR = pgraph-> addfilter (pnull, l "nullrenderer"); HR = ConnectTWofilters (PGRAPH, PF, PNULL);
3, run filter graphics
Sample Grabber works with two modes:
A. Generate a copy of each sample before transferring the sample down, and then put it in its buffer.
B, process data in a callback mode, and callback is defined by the application.
Here we only discuss the buffer mode. But everyone should pay attention to the callback mode will affect our work efficiency, even dead locks. The callback function settings We use the isamplegrabber :: setCallback method.
In order to activate the buffer mode, we call the isamplegrabberr :: setBuffersample method, and the parameter populates TRUE. You can also use the isamplegrabber :: setOnShot method, which will cause the filtration pattern to stop each capture. This feature is very beneficial to us if you only want to capture a need in the stream. We can search for the run filter graphics where you want to capture, intercept. But the accuracy of is determined by the nature of the data source.
The following example is achieved:
// Set snapshots and buffer mode.
HR = pgrabber-> setOnShot (TRUE);
HR = pgrabber-> setBuffersamples (true);
IMEDIAFILTER * PMEDIAFILTER = NULL;
IMediaControl * pControl = null;
IMediaeventex * pevent = null;
Pmediafilter-> setsyncsource (null); // Turn off the reference clock
PControl-> run (); // Run filter graphics.
PEVENT-> WAITFORCOMPLETION (Infinite, & Evcode); // Waiting until the end
4. Get buffer samples from Sample Grabber, or achieve the callback function to obtain data.
In the buffer mode, the Sample Grabber filter stores the copy of each sample it receives. We have to get buffer data to call the isamplegrabber :: getCurrentBuffer method. This method fills a caller to assign a good matrix. In order to get the size of the buffer, the buffer pointer must be filled with the buffer pointer.
Long cbbuffer = 0;
HR = pgrabber-> getCurrentBuffer (& CBBuffer, NULL);
Char * pBuffer = new char [cbuffer];
IF (! pbuffer)
{
Return E_OUTOFMEMORY;
}
HR = pgrabber-> getCurrentBuffer (& CBBuffer,
Reinterpret_cast
Use the isamplegrabber :: getConnectedMediatype method to get the buffer format. For example, if buffering is an uncompressed video, its format is the VideoInfoHeader structure format. Note that Sample Grabber does not support the VideoFoHeader2 structure.
AM_MEDIA_TYPE MT;
HR = pgrabber-> getConnectedMediatype (MT);
VideoInfoHeader * PVIH;
IF (mt.formattype == Format_VideoInfo)
PVIH = Reinterpret_cast
Elsereturn VFW_E_INVALIDMEDITYPE; // Something Went Wrong
// pvih-> Bmiheader This parameter is the BitmapInfoHeader structure, which is the graphical information of each.
// Release format block
FreeMediaType (MT);