Chinaunix首页 | 论坛 | 博客
  • 博客访问: 831838
  • 博文数量: 125
  • 博客积分: 4066
  • 博客等级: 上校
  • 技术积分: 1401
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-03 18:58
文章分类

全部博文(125)

文章存档

2014年(1)

2013年(1)

2012年(2)

2011年(29)

2010年(92)

我的朋友

分类: LINUX

2011-01-06 11:09:37




引言

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

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

基本知识

1.        多媒体框架:

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

2.        Linux线程:

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

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

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

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

调度对比

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

 

模式一:

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

模式二:

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

模式三:

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

 

为何不用多线程

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

 

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

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

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

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

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

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

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

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

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

附录

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

一张opencore的框架图。

 

下面是代码片段

阅读(1145) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~