Data stream flow in Filter Graph (from AOOSANG's Blog)

xiaoxiao2021-03-05  23

Summary:

1 DirectShow data flow overview

Data always exists in memory blocks, each buffer is encapsulated in a COM component called Media Sample, which leads out the iMediasample interface. This sample typically has a COM object called Memory Distributor to create, this object has an IMEMALLOCATOR interface. The connection between each PIN must specify an allocator, sometimes there are several connects to use an allocator.

Every Allocator must create a Media Sample pool and assign each Sample a memory buffer. Whenever a Filter requires a buffer to populate the data, it gets a Sample through allocator's functions IMallocator :: getBuffer. If the dispenser Allocator is just free Sample, getBuffer immediately returns a pointer to the Sample. If there is no idle Sample, the method is blocking until there is a SAMPLE available. When the function returns a SAMPLE, Filter fills the data into the buffer, sets the logo, and then passs Sample to the next Filter.

When a renderfilter receives a SAMPLE, it checks the Sample timestamp until the FLITER GRAPH reference clock indicates that the data can be played, and the filter begins to play the data. When the data is played, the Filter releases Sample until all Filter releases a reference to the Sample. When the Sample reference count is 0, this SAMPLE returns to the Sample pool.

Sometimes the upstream of the data stream is fast to Buffer faster than playing. Even so, render Filter also plays data according to timestamp, so that the number in the Sample pool is small, so that the speed is slowed down.

The following describes the scene in the stream, in fact, there are several allocator in each data stream, and when a Sample is released, maybe there are several allocator waiting for this Sample. This has a new problem, and maybe some alloctor will never be assigned Sample, which is inserted. The following picture shows this situation, Decoder has data needs to be compressed, so it is waiting for renderer to release Sample, but Parser is also requesting Sample, which is waiting for Decoder to release Sample.

Participate in HELP

2 Transports

In order to transmit media data in the filter chart, the DirectShow filter needs to support some protocols called Transport. The connected filter must support the same transport protocol, otherwise the media data cannot be exchanged.

Most DirectShow filters save media data in the main memory and submitted data to other filters through the pin, which is called local memory transmission (Local Memory Transport). Although local memory is used most commonly used in DirectShow, not all filters use it. For example, some filters deliver media data through hardware, and the pins are only used to submit control information, such as the IOverlay interface.

DirectShow defines two mechanisms for local memory transmission: Push Model and Pull Model. In push mode, the source filter generates data and submits it to the next filter. The next level filter is passively received data, and then transfer it to the next level filter after completing the processing. In the pull mode, the source filter is connected to one analysis filter. After analyzing the filter requests data to the source filter, the source filter transmits the data to respond to request. Push mode uses the IMEMINPUTPIN interface, pull mode uses an IASYNCREADER interface, and push the mode than the multi-draw mode. 3 Samples and Allocators

When a PIN passes data to another, it does not pass a PIN of the memory block directly, in fact, it will pass a pointer to the COM object that manages memory to the next PIN. This COM object is called Media Sample. ImediaMple interface exposed. Receive the PIN to operate the memory by calling iMediaSample, such as method iMediaSample :: getSize, iMediasample :: getActualDatalength and

IMediaSample :: getPointer.

SAMPLE is generally starting from the source filter, passing the PIN to the next Filter to enter the PIN, all the way to the render filter. In the pull mode, the output PIN passes the mode, entering the PIN or processes data by calling the IMEMINPUTPIN:: Receive method on the input PIN, or processing data synchronously in the Receive function, or otherwise using a working thread asynchronously. If you need a resource in the Recive method, you can also block.

Another COM object called allocator to create and manage Sample. IMEMALLOCATOR interface exposed. When a Filter requires an empty buffer, you can call IMEMALLOCATOR :: GetBuffer, which returns a pointer to the Sample. Each PIN connection shares an allocator, when two PIN connections, they will decide which filter to provide allocator, which can also set up allocator properties, such as the number of buffers, and size.

The chart below shows the relationship between allocator, sample, and filter.

Media Sample reference count

Allocator creates an Sample pool. Therefore, when a Filter calls the getBuffer function, some SAMPLE is used, and the other idle SAMPLE can respond. Allocator tracks Samples by reference counting. Filter calls GetBuffer returns a reference count of the SAMPLE is 1. When the Sample of the Sample is 0, SAMPLE returns the memory pool, becomes an idle SAMPLE, which can respond again to getBuffer calls. If all SAMPLE is busy, getBuffer will block until there is an Sample Idle.

For example, suppose one input PIN is connected to a SAMPLE, if it synchronizes this SAMPLE in the Receive method, does not add the Sample reference count, wait until the Receive returns, then the output is released, the reference count is 0, SAMPLE Return to the memory pool. If the thread is entered, the SAMPLE is also handled, the reference count increases 1, becomes 2, the output PIN returns, release, counts 1.

When an input PIN receives a SAMPLE, it can copy the data to another, or pass this SAMPLE to the next filter. A SAMPLE can flow throughout the Filter Graph. However, the reference count should be maintained greater than 0. When an output PIN calls Release, it should not be used again, because there may be Filter under the downstream, which is using this SAMPLE. Output PIN must call GetBuffer to get a new Sample. This mechanism reduces memory allocation because buffer can be reused. It also prevents the data that the data is not processed is rewritten.

When a Filter creates an allocator, Allocator has not retained any memory, if someone getBuffer at this time, it will fail. Only when the data stream begins, the output PIN calls IMEMALLOCATOR :: Commit, submits allocator, and now you can allocate memory.

When the data stream is stopped, PIN calls Imemallocator :: Decommit to destroy allocator. All calling getBuffer methods fails before allocator Commmitt again. Of course, if there is a getBuffer block call to wait for Sample, you will return an error code immediately.

4 Filter status

Filter has three states, stop, pause, and run.

Filter Chart Manager controls the conversion of all states of the Filter. When the application calls iMediaControl :: Run, iMediaControl :: Pause, or iMediaControl :: STOP, the Filter Chart Manager calls the Filter's corresponding IMEDIAFILTER method. Stopping, the switching of the running status is always paused, so when an application calls the Run command to a stopped Graph, the filter chart manager first paused before RUN.

For most Filter, Running and PaUSED status are the same. Look at the graph below

Source> Transform> Renderer

When a FILTER stops, it refuses to send any Samples, source Filter closes their Stream thread, and other Filter also closes the other threads they created, and Pin Decommit their memory distributor.

The filter chart manager switches the state of the Filter in accordance with the direction of the countercurrent, from the renderer filter to the source filter, which can prevent deadlocks. The most critical state switch is paused and stopped.

From the stop to the pause, when the Filter is paused, it is ready to receive SAMPLE, and the source filter is the last switch to pause. It starts to create a streaming thread, send SAMPLE, because the state of the downstream file has been switched to pause, so all filters can receive SAMPLE. Only when all FLTER receives Sample, the filter chart manager is completed to complete the switch.

From the pause to stop. When a FILTER is stopped, it is to release all of the Samples it owns. When the Chart Manager tries to stop a Filter upstream, this filter does not block in the GetBuffer and Receive method, which will respond to the stop command immediately. The upstream Filter may also speak a small amount of Sample to pass on the STOP command, but the downstream file will refuse because they have stopped.

5 pull PULL mode

In the IMEMINPUTPIN interface, the upstream FLTER determines what kind of data sent, and then pushes the data to the downstream file. However, in additional occasions, the pull mode is more suitable. The downstream Filter requests data to the upstream file, and the data is still from upstream to downstream, from output PIN to input PIN, but downstream Filter leads the flow of data. This type of connection is played in the playback of the typical application of the IASYNCReader interface puller mode, for example in the playback of an AVI file, async file source

Filter is responsible for reading data from the file, then sending data to the following Filter.

About the author: Li Qiang, currently temporarily served in Shan Dawun Information Technology Co., Ltd., engaged in the development of network video conferencing software, the current direction of interest, the development of multimedia on mobile equipment. Aooang@hotmail.com Welcome to reprint this document, I hope to keep the author profile to show the respect of the author's labor.

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

New Post(0)