DirectShow Filter

xiaoxiao2021-03-06  39

1. FILTER Overview Filter is a COM component, consisting of one or more PINs. PIN is also a COM component. The extension of the FILTER file is .aX, but can also be .dll. Filter can be roughly divided into three categories depending on the case (or in the FILTER GRAPH): Source Filter (only Output Pin), Transform Filter (with Input PIN and OUTPUT PIN) and RENDERER FILTER (INPUT PIN).

In general, create a Filter using a normal Win32 DLL project. Moreover, general Filter projects do not use MFC. At this time, the application passes the COCREATEINSTANCE function Filter instance; Filter and the application collaborate in binary levels. Another method can also create a Filter in the MFC's application project. In this case, Filter does not need to register as a COM component, and the collaboration between Filter and the application is the source code level; create a Filter instance, no use of the CocreateInstance function, but directly new Filter object, as follows: m_pfilterObject = New cfilterclass (); // make the initial refplace 1 to match Creationm_pfilterObject -> addref (); Because the Filter's base class implements the reference count of the object, even in the second case, the Filter object after the creation is Operation can also follow the COM standard. Filter is a separate functional module, it is best not to depends on other third-party DLLs. Because Filter has the position transparency characteristics of COM, the Filter file can be placed on any position of the hard disk, and will be re-registered as long as the location is moved. But at this time, if Filter rely on other DLLs, the Filter will have problems with the DLL position.

Filter cannot be separated from Filter Graph alone. So, if you want to bypass the Filter Graph directly using the Filter implementation module function, transplanted your Filter into DMO (DirectX Media Object).

2. Filter's registration FILTER is a COM component, so you must register before use. Filter's registration program is regsvr32.exe. If the command line parameter / u is collected, it is denoted; if the belt is / s, it means that any registration / logout success or not, the prompt dialog is not popped up. If you want to register automatically in the Build Filter project, please set up on the Custom Build page of the VC's Project Settings: Description: Register FilterCommands: Regsvr32 / S / C $ (TargetPath) Echo Regsvr32 EXE.TIME> $ (targetdir) / (Targetdir) / $ (targetname) .trg / $( TargetDir) .TRG

Filter's registration information includes two parts: basic COM information and Filter information. The registration information is stored in the registry. The position of the former is: hkey_classes_root / clsid / filter CLSID /, the latter location is: hkey_classes_root / clsid / category / instance / filter CLSID /. The COM information indicates that Filter is a standard that can be created by the COCREATEINSTANCE function, and the Filter information indicates the information of our filter as seen through Graphedit. If you don't want Graphedit to see (or let Filter enumerator find) you write Filter, you can do not register Filter information. And don't worry, you don't affect the Filter's functionality at all. The method of masking the registration of Filter information is also very simple. Because CBaseFilter implements two functions of the IAMOVIESETUP interface: Register and Unregister. We only need to overload these two functions and directly returnes S_OK. (Note: IAMOVIESETUP is an interface to register for the Filter information section, but it has been discarded, which is only used in AmoviedllRegisterServer and AmoviedllunregisterServer. The new Filter registration function is usually used, this function does not use the IAMOVIESETUP interface. If you want not Register Filter information, it is best to implement two export functions of Filter: DllRegisterServer and DllunregisterServer, where only the REGISTERALLSERVERS function is registered with OLTER.) Filter's MERIT value. This value is used by Microsoft's "smart connection" function. In Graphedit, when we join a Source Filter, execute "Render" on its PIN, it will automatically connect some Filter. Merit reference to the following values: MERIT_PREFERRED = 0x800000, MERIT_NORMAL = 0x600000, MERIT_UNLIKELY = 0x400000, MERIT_DO_NOT_USE = 0x200000, MERIT_SW_COMPRESSOR = 0x100000, MERIT_HW_COMPRESSOR = 0x100050Merit only when the value is likely to be greater than MERIT_DO_NOT_USE of "intelligent connection" used; the larger the value of Merit The greater the chance of this Filter.

3. The connection process of the PIN between FILTER will only work only after adding to the Filter Graph and connects to the other Filter to a complete link. The connection between the FILTER (that is, the connection between the PIN) is actually a negotiation process for connecting the two parties. The direction of the connection always points from Output PIN to the Input Pin. The approach process of the connection is: If a complete Media Type is specified when the connection function is called, then use this Media Type to connect to the connection process; if the Media Type is not specified or not fully specified, enter the following Enumeration process. Enumerates all Media Type on Input PIN, connects to Output PIN one by one (if the connection function provides incomplete Media Type, you must first match it with it. Check) If the Output Pin also accepts this Media Type, the connection between the PIN is successful; if all INPUT PINs enumerated Media Type, Output Pin does not support all Media Type on Output PIN, And use these Media Type to connect with the Input Pin one by one. If the Input Pin accepts one of the Media Type, the connection between the PIN is also successful; if all Media Type on the Output PIN does not support, the connection process between the two PINs declares failed. . Each PIN can enable the getMediaType function to provide all Preferred Media Types supported on this PIN (but generally only on the Output PIN, the Input Pin mainly implements Checkmediatype to see if the currently available Media Type). During the connection, all Media Types obtained on the PIN are provided here.

There is a protected member variable m_btrymytypesfirst in the CBasepin class, the default value is false. Change the value of this variable in our custom Filter's Output PIN, you can customize our own connection process (first enumerate the Media Type on Output Pin).

When the connection between the PIN is successful, the completeConnect function is called on the respective PINs. We can get some information on some connected Media Type here, and some calculations. In the CompleteConnect implementation of Output Pin, there is an important task that the memory configuration used by the Sample Transport after the negotiation Filter GRAPH runs. This is also a interaction process: first to ask the configuration requirements on the Input PIN, if the Input Pin provides a memory manager (Allocator), give priority to the memory manager on the Input PIN; otherwise, using the Output PiN you generated by the memory management . We generally implement DecideBuffersize to decide to store Sample's memory size. Note: After this process is completed, the actual memory does not assign, and wait until the Active function call on the Output PIN.

4. FILTER Media Type Overview Media Type can generally have two representations: am_media_type and cmediatype. The former is a structure, the latter is from this Struct inherited the class. Each Media Type has three components: Major Type, Subtype, and Format Type. These three parts use the GUID to uniquely indicate. Major Type primarily describes a Media Type, such as specifying this is a video, or audio or stream, etc.; Subtype further refines Media Type, if VIDEO can be further specified is UYVY or YUY2 or RGB24 or RGB32, etc. Struct is further refined MEDIA TYPE. If the three parts of Media Type are specified a specific GUID value, this Media Type is fully specified; if there is any value in the three parts of Media Type, it is guid_null, but this Media Type is not Fully specified. GUID_NULL has a function of wildcard. Commonly used Major type: MEDIATYPE_Video; MEDIATYPE_Audio; MEDIATYPE_AnalogVideo; // Analog captureMEDIATYPE_AnalogAudio; MEDIATYPE_Text; MEDIATYPE_Midi; MEDIATYPE_Stream; MEDIATYPE_Interleaved; // DV camcorderMEDIATYPE_MPEG1SystemStream; MEDIATYPE_MPEG2_PACK; MEDIATYPE_MPEG2_PES; MEDIATYPE_DVD_ENCRYPTED_PACK; MEDIATYPE_DVD_NAVIGATION;

Commonly used Subtype: MEDIASUBTYPE_YUY2; MEDIASUBTYPE_YVYU; MEDIASUBTYPE_YUYV; MEDIASUBTYPE_UYVY; MEDIASUBTYPE_YVU9; MEDIASUBTYPE_Y411; MEDIASUBTYPE_RGB4; MEDIASUBTYPE_RGB8; MEDIASUBTYPE_RGB565; MEDIASUBTYPE_RGB555; MEDIASUBTYPE_RGB24; MEDIASUBTYPE_RGB32; MEDIASUBTYPE_ARGB32; // Contains alpha valueMEDIASUBTYPE_Overlay; MEDIASUBTYPE_MPEG1Packet; MEDIASUBTYPE_MPEG1Payload; // Video payload MEDIASUBTYPE_MPEG1AudioPayload; // Audio payloadMEDIASUBTYPE_MPEG1System ; // A / V payloadMEDIASUBTYPE_MPEG1VideoCD; MEDIASUBTYPE_MPEG1Video; MEDIASUBTYPE_MPEG1Audio; MEDIASUBTYPE_Avi; MEDIASUBTYPE_Asf; MEDIASUBTYPE_QTMovie; MEDIASUBTYPE_PCM; MEDIASUBTYPE_WAVE; MEDIASUBTYPE_dvsd; // DVMEDIASUBTYPE_dvhd; MEDIASUBTYPE_dvsl; MEDIASUBTYPE_MPEG2_PROGRAM;; MEDIASUBTYPE_MPEG2_VIDEO MEDIASUBTYPE_MPEG2_TRANSPORT; MEDIASUBTYPE_MPEG2_AUDIO; MEDIASUBTYPE_DOLBY_AC3; MEDIASUBTYPE_DVD_SUBPICTURE; MEDIASUBTYPE_DVD_LPCM_AUDIO; MEDIASUBTYPE_DVD_NAVIGATION_PCI; MEDIASUBTYPE_DVD_NAVIGATION_DSI; MEDIASUBTYPE_DVD_NAVIGATION_PROVIDER; Common format type: Format_noneFormat_D VINFO DVINFOFORMAT_MPEGVIDEO MPEG1VIDEOINFOFORMAT_MPEG2VIDEO MPEG2VIDEOINFOFORMAT_VIDEOINFO VideoInfoHeaderformat_VideoInfo2 VideoInfoHeader2Format_WaveFormatex Waveformatex

5. The data between the data transfer between the FILTER is transmitted by SAMPLE. Sample is a COM component that has its own data buffer. SAMPLE is managed by Allocator. As shown below:

There are two ways of data transfer between Filter: PUSH mode and PULL mode.

The so-called PUSH mode, the Source Filter can generate data, and generally in its Output PIN has a separate sub-thread to send data to the Live Source filter of the capture of the WDM model, such as the WDM model; and the so-called PULL mode, That is, Source Filter does not have the ability to send your own data. In this case, the general Source Filter is tightened with a Parser Filter or Splitter filter, which is generally a separate sub-thread in the Input PIN, responsible Continuously request data from the Source Filter, and then transfer the data after processing, common situations such as File Source. In Push mode, Source Filter is active; in Pull mode, Source Filter is passive. And in fact, if the Source Filter and Splitter filter in the above-picture PULL mode are regarded as another virtual Source Filter, the data transfer between the following filters is identical to the PUSH mode. So how did the data are transmitted by connecting PIN? First, look at the Push mode. On the INPUT PIN of the Source Filter, a IMEMINPUTPIN interface must be implemented, and the data is transmitted by calling the remote method of this interface by the previous FILTER. It is worth noting that data from Output Pin is transferred to the Input PIN via the Receive method, and does not perform memory copies, it is just a "notification" equivalent to data arrival. Take a look at the PULL mode. On the Output PIN of the Source Filter in Pull mode, an IASYNCReader interface is implemented; the Splitter filter behind is the request to obtain data by calling the request method or the SYNCREAD method of this interface. Splitter Filter then calls the IMEMINPUTPIN interface Receive method to implement the data down transfer in the IMEMINPUTPIN interface Receive method on the next level of Filter.

A DirectShow application, at least two threads: main threads and FILTERs for data transfer sub-threads. Since it is multi-thread, it is inevitable that thread synchronization problems will occur. Filter's status change is completed in the main thread, and Filter's data-related operations are called in the data thread. Some of the main thread of each function call reference as follows: Streaming thread (s): IMemInputPin :: Receive, IMemInputPin :: ReceiveMultiple, IPin :: EndOfStream, IMemAllocator :: GetBuffer Application thread:. IMediaFilter :: Pause, IMediaFilter :: Run, IMediaFilter: : Stop, iMediaseeking :: setPositions, ipin :: beginflush, ipin :: endflush. Either: ipin :: newsegment. These functions should not be mixed, otherwise the deadlock of the thread will cause the thread. It is also worth noting that Beginflush and Endflush belong to the main thread call, not a data thread call.

6. The difference between Transform Filter and Trans-IN-Place Filter First, these two filters are common, because the Trans-in-Place Filter itself is inherited from Transform Filter. Second, we have to understand that Trans-IN-Place Filter "Try" makes your INPUT PIN and OUTPUT PIN use the same allocator to avoid MemcPy of Sample data. We say "do our best", that is, Trans-in-Place Filter may not be able to achieve its original intention. (If the allocator used by Trans-IN-Place Filter is Readonly, the Trans-Place Filter wants to modify the Sample data, and the Trans-PIN and OUTPUT PIN will have to use different allocator. Trans-in-place filter has a Protected member variable m_bmodifiesdata, the default value is true. If you are confident that custom Trans-PLACE FILTER does not need to modify Sample data, the m_bmodifiesdata assigns FALSE, which ensures that INPUT PIN and OUTPUT PIN use the same allocator. The implementation of Trans-IN-Place Filter is mainly reflected in the following three functions: CTransinplaceFilter :: CompleteConnect, CTransinplaceInputpin :: getAllocator and CTransinplaceInputpin :: NotifyAllocator. The necessary reconnect is performed in CompleteConnect, ensuring that Trans-PIN and OUTPUT PIN use the same Media Type. GetAllocator can get allocator on the INPUT PIN of Trans-in-Place Filter's next level. NotifyAllocator "Try" makes Trans-in-place filters of Input Pin and Output PIN use the same allocator.

7. iMediaseEKing's implementation IMEDIASEEKING implemented on the Filter, but the application should get this interface from the Filter Graph Manager. At Filter Level, Filter Graph Manager first begins with renderer filter to ask if the Output PIN of the last level Filter supports iMediaseEKing interface. If support, return to this interface; if you don't support it, continue to query the previous Filter until Source Filter. The iMediaseEKing interface is typically implemented on the Output PIN of Source Filter. (If File Source, this interface is generally implemented in Parser Filter or Splitter Filter.) For Filter developers, if we write Source Filter, you must implement an iMediaseEKing interface on Filter's Output PIN; if you write Transform Filter, just pass the user's interface request to the previous Filter's Output PIN; if written is rendere file, you need to pass the user's interface request to the previous FILTER on the FILTER. Output Pin. Note: In order to ensure the STREAM synchronization after the Seek operation, if the FILTER of the IMEDIASEEKING interface is actually implemented, there are multiple Output PINs, and only one PIN supports the SEEK operation. For your custom TRANSFORM FILTER, if there are multiple Input Pins, you need to decide which path to choose which path when the Output Pin receives the IMEDIASEEKING interface request. The application can perform the SEEK operation at any time (running, paused or stopped) for Filter GRAPH. However, when Filter Graph is running, Filter Graph Manager will live in PAUSE. After performing the Seek operation, re-Run.

IMediaSeeking time format can have the following categories Seek:. TIME_FORMAT_FRAME Video frames.TIME_FORMAT_SAMPLE Samples in the stream.TIME_FORMAT_FIELD Interlaced video fields.TIME_FORMAT_BYTE Byte offset within the stream.TIME_FORMAT_MEDIA_TIME Reference time (100-nanosecond units) but the implementation of this interface may not Filter Support all of these formats. General FILTER supports time_format_media_ time, when using other formats, it is best to call iMediaseEKing :: isFormatSupported to confirm.

For Filter, it is not approved to use an IMEDIAPSITION interface. IMediaPosition is used to support Automation (such as DirectShow inside VB), iMediaseEKing does not support Automation.

8. Filter's status conversion filter has three states: stopped, paused, running. PaUSED is an intermediate state, and the Stopped status to the Running state must pass through the PAUSED state. Paused can be understood as a data ready state, designed to quickly switch to Running state. In the PAUSED state, the data thread is started, but is blocked by the Renderer Filter. Paused and running state transitions, for Source Filter and Transform Filter, it is slightly different for RENDERER FILTER (especially video renderer / audio renderer). Render first handles the SAMPLE of the HOLD in the PAUSED state, and when the new SAMPLE is received, the timestamp on the SAMPLE is determined. If the time is not arriving, rendere will hold this SAMPLE to wait.

Filter Graph Manager converts Filter to the Filter from the downward order, ie, from renderer filter to the Source Filter. This order can effectively avoid the loss of SAMPLE and the deadlock of Filter Graph. Stopped to paused: The transition of the PAUSED state is first started from renderer. At this time, Filter calls all the PIN's Active function to initialize (generally PIN for SAMPLE memory allocation, if the Source Filter will start the data thread), so that the Filter is in a ready state. Source Filter is the last Filter that completes the ready state. Then, Source Filter launches the data thread and sends SAMPLE to the next. When the rendere receives the first SAMPLE, it blocks it. Filter Graph Manager considers status conversion when all Renderer implements state conversion. Paused to stopped: When the Filter enters the Stopped status, call all the PIN of the PIN inactive function (General PIN is released in inactive, if the Source Filter will also terminate the data thread). Release all HOLD SAMPLE to cause the last level of Filter's getBuffer to block; terminate all the waits in Receive to return the last level Filter's Receive function call. Filter refuses to accept any Sample in a Stopped state. This is removed from the rendere filter to the top level level. When the Source Filter is reached, it ensures that the data thread is terminated.

9. Endofstream Problem When all data of the Source Filter has been sent, the next level of Filter's IPIN :: Endofstream on the IPIN :: Endofstream until renderer filter. When all INPUT PINs of this Renderer Filter are called EndOfStream, send an EC_COMPLETE event to the Filter Graph Manager. Filter Graph Manager is sent to the application only when all streams in Filter Graph have sent an EC_COMPLETE event.

In our custom Filter, if the endofstream passing over the previous FILTER is received, the above data has been completed, and the Receive method does not have to receive data. If we buffer the data, you should confirm that all the data in the buffer is processed and sent down, and then call the endofstream. PULL mode, generally splitter filter or Parser Filter sends endofstream, and the direction is down, and this notification will not be received on the Source Filter. 10. Beginflush, endflush, NewSegment problem typical case, after MEDIASEEKING, Beginflush, Endflush. These two functions are generally implemented on the Input PIN. For Filter developers, Filter needs to do the following when called Beginflush: • Call the next level of Filter's Beginflush so that it no longer receives new Sample; • Refused to receive the previous Filter data, including Receive calls and Endofstream call; · If the last level Filter is blocking the waiting Sample, it needs to be detached from the blocking (by destructure allocator); • Make sure the data stream thread is detached from the blocking state. Filter needs to do the following: • Make sure all Samples waiting cache are discarded; • Make sure that the data that has cached on the Filter is discarded; • Clear the EC_COMPLETE event that is not sent (if this is a rendered input pin); · Call the next level of Filter's Endflush. Another point: If you have to play Time Stamp for each Sample in custom Filter, then remember the time stamp of the sample after MediaseEKing, should start from 0 to start.

Segment is a group of SAMPLEs with the same Playback Rate for a while, which is called in the NewSegment function to indicate the beginning of this segment. NewSegment is generally when the new stream is started, or after the user performs MediAseeking, the Source Filter is initiated by Source Filter or PARSER / SPLITTER Filter (PULL mode), and the lower layer is called until renderefter. In our custom Filter, you can use NewSegment to pass the information, especially for Decoder. For Audio Renderer, it is also a typical example, which generates output from the actual sampling frequency of Playback Rate and Audio.

11. Quality Control problem FILTER data transfer, sometimes too fast, sometimes too slow. DirectShow uses Quality Control to solve this problem, that is, two functions of the iQualityControl interface (Setsink and Notify). Generally, Renderer Filter implements this interface on the Filter, while other Filter implements this interface on the Output PIN. The above figure shows the general Quality Control process. The iQualityControl interface capable of adjusting the transmission speed is generally implemented on the Source Filter (Pull mode for PARSER / SPLITTER FILTER), and the Transform Filter just passes the Quality Message to the first level Filter. Applications can implement their Quality Control Manager, and then set to Filter by calling the setsink method. The above process changes, and Quality Message sends directly to custom Manager. 12. Support for MEDIA TYPE changes in the run, we can see from CBaseinputpin :: Receive, INPUT PIN is generally checkstream each time you receive SAMPLE, if the current Filter is already stop or is Flush or RuntimeError Then refuse to receive the SAMPLE, then save the current Sample property to the M_SampleProps member variable of protected. Describe the structure of the SAMPLE attribute is a structure of an am_sample2_properties, which has a tag to indicate whether the current SAMPLE's Media Type has changed. If Media Type changed, checking checkmedaitype, see if our Filter still supports it. If you do not support, a RuntimeError is sent and Endofstream is sent. A sound film should be able to handle changes to the runtime MEDIA TYPE. In our Receive method implementation, we can determine if the MEIDA TYPE has changed via if (pprops-> dwsamplechanged); if it is changed, we need to initialize the necessary initialization according to the new Media Type.

A typical case: Audio's Media Type may change when Camcorder input. For example, when the Filter connection, Media Type used MediaType_pcm, and it was changed to MediaTyPE_Wave; or the sample frequency of AUDIO was 44.1k when the connection was connected, but it turned 48K during operation; or the Camcorder's band was saved. Mixed 44.1k and 48k Audio.

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

New Post(0)