opencore内部调度

opencore内部调度

1 引言

多媒体框架是非常重要而又令人关心的模块,尤其在 android 的系统上,多媒体播放效果如何,对其框架了解是非常必要的。

多媒体中的调度问题,是个背后的故事,但却对性能影响至关重要,本文并非全面分析多媒体框架,旨在探讨媒体框架调度方面与传统的多线程应用间的差异。  

2 基本知识

1.        多媒体框架:

宏观上看多媒体框架一般包含: engine parser codec output engine 为控制部分, parser 为文件解析及读取部分, codec 就是音视频编解码, output 包含音视频输出。针对不同文件类型及编解码器,会有多种 parser codec

2.        Linux 线程:

       一般来讲 linux 都会定义最大线程为 1024 ,不过还没有看到哪个系统运行起来有如此之多的线程存在,也有网评说创建到 382 个线程时返回失败。最大线程数目会受到系统资源的影响。

       多线程在管理调度上也会影响系统性能,影响的是 kernel 部分。

       多线程应用设计中,数据共享是个问题,线程 A 和线程 B 间共享数据,为确保数据访问有效,会引入锁,比如信号量。多个线程中,信号量等待是很重要的,有时线程 A 的数据准备 OK 了,但线程 B 没有用完,那么接下来线程 A 只能死等或是空转。

       多线程中,还要避免线程死锁。  

3 调度对比

在此我们拿传统 while 循环、多线程模式、 opencore 调度模式作对比,如下图示。

 

模式一:

      顺序执行,有新模块加入就挨着添加。

模式二:

      不论有限与否, ABCD 四个模块都在独立运行,即使浪费也要空转。

模式三:

      由统一调度器调度,优先者优先调度, ABCD 四个模块都注册到调度器上,通过状态机切换触发下一次调度,谁着急被再次调用谁就去触发调度器执行,相对公平。 Opencore 采用该模式, PlayerDriver 创建后进入 OSCL 线程来处理消息, engine 创建完各个 node 节点并将其连接起来,剩下的就是 node 间的通讯问题,各 node 状态变化会触发 oscl 对其下一次调度,参与到oscl调度中的模块都必须提供一个Run函数,oscl会去call这个函数。

 

4     opencore 为何不用多线程

因为有人曾疑问,为什么opencore不去创建大量线程来调度,那样不是更快,事实上opencore是采用上述模式三来解决调度问题的。附上一张oscl调度相关的类图。

 

opencore 中为何不大量去创建线程来完成各个模块,暂时没有看到 opencore 的官方设计文档来讲述其设计思路,只能通过代码去分析,下述也仅一家之言供参考。

1.        从模块化去看, opencore 有很多模块,包含 engine player author parser omx codec output audio video 等,并且 opencore 抽象出来个概念叫 node parser/codec/omx 都被封装成 node engine 负责把各个 node 节点创建并连接起来后,剩下的就是各个 node 节点之间的通讯,它们由统一调度器来调度。试想,如果每个 node (或者说模块)都去创建一个线程去执行,如何管理是个问题,也有悖软件工程的模块化思想。

2.        从模块化再看,假如把多媒体缩减到 engine parser decoder 三个模块,如果多线程去做,会有三个线程,这是其一,其二,文件类型识别及解码器识别需要事先完成,必然由 engine 去完成,从而决定用哪个 parser decoder Opencore 里分的很清楚,各个模块干各自的事情,一个线程统一调度完成。

3.        CS 模型去看, android 中多媒体采用服务器客户端架构来实现,客户端是 jiava 程序,仅用于一些 API 的封装、控制指令的下放等;核心的媒体播放控制都在服务器端实现,它们之间通过 binder 调用衔接。当有客户端发起媒体请求时,服务器就创建一个 client 去对应它,如果有第二个媒体请求,就会创建第二个 client 来对应。如此一来,服务器端可能会存在多个 client ,每个 client 都是一个媒体引擎的实例,假如 opencore 采用了多线程模式,又假如引擎总共涉及 6 个线程,倘若有五个客户端发起请求,系统就会增加 30 个线程,如此一来显然增加 kernel 的调度时间,影响系统性能。而采用 opencore 的统一调度,五个客户端也就呼起五个线程,这是可以接受的。

4.        从多媒体的应用场景来看,视频播放、短信铃声、彩信铃声、电话铃声、闹钟铃声是会同时出现的,这样就触发了上述多种客户端的情况。

5.        从可移植看, opencore 采用的统一调度器叫 oscl ,它是一个抽象封装,基于 oscl 之上可以看做纯软件模块,如此一来 opencore 可以很容易的移植到各个平台,且保持一致性。

6.        从扩展性看, opencore 现有框架添加一个模块很容易,比如添加 rmvb 的支持,只要添加一个 rmvb parser-node 即可,对系统框架没有任何影响。如果采用多线程, rmvb parser 肯定要实现, engine 中要添加 rmvb 识别部分,也会添加创建 rmvb-parser 线程部分。

7.        多线程肯定是最快的,但复杂系统考虑自身架构设计及可扩展性,势必在多线程的应用上采取谨慎态度。关键的问题,应该还是落在系统性能上,拿 200M 主频和 1G 主频作对比,在 200M 主频处理器上再怎么优化,也赶不上 1G 处理器,换句话说, 1G 处理器上即使框架再烂,系统运行的也不会太差。

8.        DirectX 中也有一个 filter 的概念(类似 opencore 中的 node 节点),应用 directx 开发中,只要把各个 filter 连接起来即可,剩下的是 filter 间的事情。  

5 附录

附录两张图,均来自网络。

一张 opencore 的框架图。

 

 

下面是代码片段



原文: http://blog.chinaunix.net/u2/61880/showart_2330325.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值