您的位置:首页 > 其它

[DirectShow] 014 - Samples and Allocators

2009-07-29 21:17 302 查看
When a pin delivers media data to another pin, it does not pass a
direct pointer to the memory buffer. Instead, it delivers a pointer to a COM
object that manages the memory. This object, called a media sample
,
exposes the IMediaSample

interface. The receiving pin accesses the memory buffer by calling IMediaSample
methods, such as IMediaSample::GetPointer

,
IMediaSample::GetSize

,
and IMediaSample::GetActualDataLength

.


pin
传递媒体数据到另外一个
pin
,不是通过传递内存
buffer
的直接指针。而是传递一个管理内存的对象的一个指针。这个对象叫作
media sample
。暴露
IMediaSample
接口。接收
pin
通过调用
IMediaSample
的方法访问内存
buffer
。例如:
IMediaSample::GetPointer , IMediaSampleGetSize


IMediaSample::GetActualDataLength .

Samples always travel downstream, from output pin to input pin. In
the push model, the output pin delivers a sample by calling IMemInputPin::Receive

on the input pin. The input pin will either process the data synchronously
(that is, completely inside the Receive
method), or process it
asynchronously on a worker thread. The input pin is allowed to block within the
Receive
method, if it needs to wait for resources.

sample
总是从输出
pin
到输入
pin
流到下游。在
push
模式中,输出
pin
通过在输入
pin
上调用
IMemInputPin::Receive
来传递
sample
。输入
pin
在工作线程中既可以同步也可以异步处理。如果需要等待资源,输入
pin
运行阻塞在
Receive
中。

Another COM object, called an allocator
, is responsible for
creating and managing media samples. Allocators expose the IMemAllocator

interface. Whenever a filter needs a media sample with an empty buffer, it
calls the IMemAllocator::GetBuffer

method, which returns a pointer to the sample. Every pin connection shares one
allocator. When two pins connect, they decide which filter will provide the
allocator. The pins also set properties on the allocator, such as the number of
buffers and the size of each buffer. (For details, see How
Filters Connect
and Negotiating
Allocators
.)

另外一个
COM
对象叫作
allocator
,负责创建和管理媒体
sample

allocator
暴露
IMemAllocator
接口。每当一个
filter
需要一个包含空
buffer

media
sample
的时候,就调用
IMemAllocator::GetBuffer
方法,这个方法返回指向
sample
的指针。每一个
pin
连接共享一个
allocator
。当两个
pin
连接,他们决定哪一个
filter
提供
allocator

pin
也可以设置
allocator
的属性,例如
buffer
的个数以及每个
buffer
的大小。

An
allocator creates a finite pool of samples. At any time, some samples may be in
use, while others are available for GetBuffer
calls. The allocator uses
reference counting to keep track of the samples. The GetBuffer
method
returns a sample with a reference count of 1. If the reference count goes to
zero, the sample goes back into the allocator's pool, where it can be used in
the next GetBuffer
call. As long as the reference count remains above
zero, the sample is not available to GetBuffer
. If every sample
belonging to the allocator is in use, the GetBuffer
method blocks until
a sample becomes available.

allocator
创建一个有限的
sample
缓冲池。某一时刻,一些
sample
可能正在使用,一些则在
GetBuffer
调用的时候有效。
allocator
使用引用计数联系
sample

GetBuffer
方法返回引用计数为
1

sample
。如果引用计数为
0
,则
sample
回到
allocator
缓冲池中,此时这个
sample
可以被下一个
GetBuffer
呼叫使用。只要引用计数大于
0

sample
就不能被
GetBuffer
使用。如果属于
allocator

sample
都在使用,
GetBuffer
将被阻塞,直到有
sample
可用。

For example, suppose that an input pin receives a sample. If it
processes the sample synchronously, inside the Receive
method, it does
not increment the reference count. After Receive
returns, the output pin
releases the sample, the reference count goes to zero, and the sample returns
to the allocator's pool. On the other hand, if the input pin processes the
sample on a worker thread, it increments the reference count before leaving the
Receive
method. The reference count is now 2. When the output pin
releases the sample, the count goes to 1; the sample does not yet return to the
pool. After the worker thread is done with the sample, it calls Release
to free the sample. Now the sample returns to the pool.

例如:假如一个
input pin
接收一个
sample
,如果它在
Receive
内部同步处理这个
sample
,它不增加引用计数。
Receive
返回后,
output pin
释放
sample
,引用计数回到
0

sample
返回
allocator
缓冲池。另外一种处理方式中,如果
input pin
在工作线程处理
sample
,它就在离开
Receive
方法之前增加引用计数。现在引用计数编程
2
。当
output pin
释放
sample
,计数到
1

sample
仍然没有回到缓冲池。工作线程结束对
sample
的操作以后调用
Release
释放
sample
。现在
sample
回到了缓冲池。

When a pin receives a sample, it can copy the data to another
sample, or it can modify the original sample and deliver that one to the next
filter. Potentially, a sample can travel the entire length of the graph, each
filter calling AddRef
and Release
in turn. Therefore, the output
pin must never re-use a sample after it calls Receive
, because a
downstream filter may be using the sample. The output pin must always call GetBuffer
to get a new sample.


pin
接收一个
sample
,它可以拷贝数据到别的
sample
,或者修改原始
sample
并把它传递给下一个
filter
。一个
sample
能经过整个
graph
,每个
filter
依次调用
AddRef

Release
。因此,
output pin
在它调用
Receive
之后不能再次使用
sample
,因为下游
filter
也许正在使用这个
sample

filter
必须始终调用
GetBuffer
来获得新的
sample.

This mechanism reduces the amount of memory allocation, because
filters re-use the same buffers. It also prevents filters from accidentally
writing over data that has not been processed, because the allocator maintains
a list of available samples.

这个机制减少内存的分配数量
,
因为
filter
重复使用同一个
buffer
。也可以组织
filter
意外的改写没有处理过的数据,因为
allocator
维护一个有效
sample
的列表。

A filter can use separate allocators for input and output. It
might do this if it expands the input data (for example, by decompressing it).
If the output is no larger than the input, a filter might process the data in
place
, without copying it to a new sample. In that case, two or more pin
connections can share one allocator.

filter
可以在
input

output
上使用不同的
allocator
。如果它扩展输入数据它也许会这么做。如果输出没有输入大,
filter
将在一个地方处理数据,不拷贝数据到新的
sample
。如果是那样的话,两个或多个
pin
连接能共享同一个
allocator


When a filter first creates an allocator, the allocator has not
reserved any memory buffers. At this point, any calls to the GetBuffer
method will fail. When streaming starts, the output pin calls IMemAllocator::Commit

,
which commits
the allocator, causing it to allocate memory. Pins can now
call GetBuffer
.


filter
第一次创建一个
allocator

allocator
没有预留
memory buffer
。这个时候调用
GetBuffer
方法将失败。当流开始,
outpin pin
调用
IMemAllocator::Commit
约束
allocator
,分配内存。
pin
就可以调用
GetBuffer
了。

When streaming stops, the pin calls IMemAllocator::Decommit

,
which decommits
the allocator. All subsequent calls to GetBuffer
fail until the allocator is committed again. Also, if any calls to GetBuffer
are currently blocked waiting for a sample, they immediately return a failure
code. The Decommit
method may or may not free the memory, depending on
the implementation. For example, the CMemAllocator

class waits until its destructor method to free memory.

当流停止,
pin
调用
IMemAllocator::Decommit
解除约束。所有
GetBuffer
调用失败,知道
allocator
再次被约束。并且,如果一些调用
GetBuffer
的正在阻塞等待
sample
,他们将立即返回失败代码。
Decommit
方法也许会也许不会释放内存,依靠执行情况。例如,
CMemAllocator
累等待知道他的析构方法释放内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: