标签:des style blog http color 使用
译者注:这是原文地址。另外,关键的单词我保留原文】
作者:Hasselt University - Expertise Centre for Digital Media
这个是 EMIPLIB 的说明手册,EMIPLIB 即 EDM Media over IP libray。这个库开发于 Hasselt 大学 (http://www.uhasselt.be) 的 Expertise Centre for Digital Media (http://www.edm.uhasselt.be)研究所。正如这个库的名称所示、这个库的目标是让各种媒体更好地在网络传输,包括但不限于音视频。
【译者注:此处略】
这个库的主页地址可以在这里找。EMIPLIB有个邮件列表。你可以发送邮件到 emiplib-subscribe@edm.uhasselt.be 来订阅它。
为了提供灵活的框架,这个库旨在提供大量的小 component。这些 component 各自负责特定任务,比如,音频采样、把音频写到声音文件或传输音频包。这些 component 可以分布在一个,允许不同 component 交换 message 的 chain 上。这样,在不同 component 之间创建 link,我们可以创建更多的复杂应用。
除了上述的核心库,EMIPLIB也着力提供一系列用于组合 component 的 wrapper类。这样方便了 EMIPLIB 用户:除了把不同 component 手动 link 在一起,我们还可以简单地创建一个VoIP的 session 对象。如果需要更灵活的用法,用户完全可以非常简单地手动组合不同 component。
在这章节我们详述库的核心内容。我们由浅入深阐述:
如“设计哲学”这一节所述、核心库包含3部分:
MIPComponent 的子类即为 component,并且可以嵌入在 component chain(即 MIPComponentChain)。当 chain 被激活时,message 通过 component chain 的 link 而传递。这样的 message 继承自 MIPMessage 类。
假设我们有两个 component ,一个声卡输入 component ‘sndin‘ 和一个声卡输出 component ‘sndout‘。 我们把这些组件放在一个叫做‘loopchain‘的 chain 中并启动之:
loopchain.setChainStart(&sndin); loopchain.addConnection(&sndin,&sndout); loopchain.start();
这样就可以告知 chain,第一个 component 是 ‘sndin‘, 然后放置在一条 ‘sndin‘ 到 ‘sndout‘ 的link。chain 启动时,一个后台线程就会开始执行下面的事情:
所以,chain 的第一个 component 是 timer(定时器)。在这个案例中,是由声卡输入 component 自身的来完成的。
首先我们描述一下这个 chain 是如何建立的,之后叙述 message 是如何传递的。最后叙述反馈机制。
Component 的连接可以由 MIPComponentChain::addConnection 方法来指定。这样可以简单地在连接列表中添加特定连接,并存储在chain内部。我们可以使用 MIPComponentChain::setChainStart 方法来设定起始组件。这个组件将会接受第一个消息:MIPSYSTEMMESSAGE_TYPE_WAITTIME 子类型的 MIPSystemMessage。
当调用一个 MIPComponentChain::start 函数的时候,之前建立的连接列表会根据正确的message分布队列来重排序。下图是一个以 timing component 为起始的 chain。假设link是按照以下数字的顺序建立的:
把 component 放置在不同层是算法重拍连接的结果。第一层是 MIPComponentChain::setChainStart 方法的结果。算法迭代所有连接,寻找以 计时器 component 为起始的连接。对于每个连接都会从旧连接列表中移除,并加入到新的重排序的连接列表中。连接的末端被加入到下一层。当第一层被处理后,算法就会迭代地处理下一层的 component。最后处理的结果如上图,重排后的连接顺序是:4, 2, 1, 6, 3, 5.
如果没有指定起始component或算法找到一些连接不可为,就会返回错误了。
如果 chain 可以开始的话,后台进程就会大量产生,在不同的 component 之间分发 message。Chain 自身创建一个 MIPSYSTEMMESSAGE_TYPE_WAITTIME 子类型的 MIPSystemMessage 实例,然后发送自身到 chain 的第一个 component,使用 MIPComponent::push 方法。Chain 在调用期间会用 MIPComponent::lock 和 MIPComponent::unlock 方法 lock 住 component。
这个 message 告诉第一个 component 进入等待状态,直到其他的 message 可以被分发。当这个 component 的 push 方法返回时,后台线程开始迭代已排序的连接列表。对于列表的每个连接,头和尾 component 都被锁住了。通过 MIPComponent::pull 接口,Message 从连接的头 component 提取出来,并且通过 MIPComponent::push 接口输入连接的尾 component。关于 push 和 pull 方法的更多信息可参见 MIPComponent 文档。
如果 push 或 pull 方法返回 false,线程会调用 MIPComponentChain::onThreadExit 成员方法然后退出。产生错误的 component 的名称和错误描述会传递给这个函数的参数。
Message 分发系统只支持单向地传递。对于许多原因,我们可能希望逆向传递信息。这可以通过使用 MIPComponentChain::addConnection 成员函数的第三个参数来指定是否反馈。
在开始后台进程前,反馈 chain 就已经基于连接列表的信息建立起来了。例如,假设上图中,连接1和连接3被标记为反馈连接,反馈 chain 就将由 RTP component, RTP 音频编码器, 声卡输入组成。
当后台线程运行时,分发 message 后,反馈 message 也会被分发。对于每个反馈chain,一个 MIPFeedback message 会被创建,并且通过 MIPComponent::processFeedback 成员函数在 chain 的每个反馈 component 来传递。通过实现这个函数,一个 component 可以获取或修改反馈信息。
注意,许多反馈 chain 可以同时存在,它们甚至可以在 chain 的末端拥有同样的 component。然而,一个 component 不能同时处理两个 chain 的反馈信息。
“建立 chain” 一节的例子已经展示了从指定的 component(比如定时器),你可以创建连接到许多不同的component(比如 message dumper 和声卡输入 component),这甚至可以让 subchain 合并一起。在下列例子中,用上了两个不同的音频文件 component,读取每个音频文件的数据:
每个文件的数据将重采样,并统一采样率。一个混音器把两个文件的音频合并成一个输出流,然后经过核实的编码方式输出至声卡。
现在我们假设,其中一个声音文件已经具有合适的采样率。这样把它的数据传递给重采样器就不必要了,你可能会认为下图才是好通路:
于是,连接顺序将会是这样的:
Timer -> Soundfile input 2 Timer -> Soundfile input 1 Soundfile input 2 -> Mixer Soundfile input 1 -> Sampling rate converter Mixer -> Sample encoder Sampling rate converter -> Mixer Sample encoder -> Soundcard output
这种情况下,当一路音轨还从重采样器到混音器路上,另一路从混音器到采样编码器了。好的情况下,在两路音轨到混音器会有时差;差的情况下较后的音轨可能会被丢弃掉。
所以一般情况下,当使用分支与合并,你可能更愿意为不同的分支分配相同层数的 component 来避免这个问题——你可以使用 MIPComponentAlias 类来辅助解决。
【译者注:几乎都是代码,就不翻译了】
查看 component 的最简单的方法是看看目录结构
警告:
原则上,一个指定的 component 实例可以被用于多个 chain 上,每个 chain 在开始使用的过程中会被锁住。然而,事实上只有少数几个 component 可以被多个链条使用。大部分的 component 会引发同步问题。
目前有两个 wrapper 可被使用:
【译文】EMIPLIB 1.1.1 Doxygen,布布扣,bubuko.com
标签:des style blog http color 使用
原文地址:http://www.cnblogs.com/CatUpp/p/3811347.html