awsomeplayer结构认识
把这个搞明白,算是顿悟的一个真实例子。怎么也搞不懂的架构,突然就想明白了。不过这其实是一个思维的过程。
当然如果你想明白这些东西,至少要非常清楚一个概念:接口。
我只是一个半路出家的开发者,我真正明白什么接口时,我已经写了一年多代码了。书面的解释实在拗口,我记不住。
我的理解就是:接口,在C语言里面,就是函数接口,在C++里面就是纯虚函数,在java里面就是interface。用接口,而不是实现来编程一个最大的好处就是:隔离变化。其实这些东西,都是我在李先静老师《系统程序员成长计划》里面领悟到的。
好吧说完了接口的体会,少说废话,步入正题。
我们要思考一个问题,对于一个播放器,解决的主要问题有哪些?当然是播放音视频。如何播放?播放的过程有哪几步?
想到这一点,剩下的东西,就很简单了。
播放器的四大基本组件:access/demux/decode/render。(这些知识,我已经在之前的文章写过了)
下面来看android awesomeplayer是如何抽象这四大组件的。时刻记住,我们是面向接口编程,一定要找准接口。
1.access
有些问题我们之前说过,获取stream的方式是多样的,本地文件,rtsp,http都有可能。我们要足够抽象才行。其实我不知道如何抽象一个好的接口,这也不是这个文章的要点,我们的要点是:印证自己的想法,理解别人的设计理念。
android抽象了一个叫DataSource的接口类,来隔离获stream方式的变化。
virtual status_t initCheck() const = 0;
virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0;
这个类,规定了两个接口。我们剩下的任务就是找出谁继承了这个类,就知道android能支持的stream种类了。
class FileSource : public DataSource
struct HTTPBase : public DataSource
struct ChromiumHTTPDataSource : public HTTPBase
struct NuCachedSource2 : public DataSource
这里http方式的流,没有直接继承datasource,而是又加了一层包装,另外这个http协议的实现是直接使用的webkit的库。
最后一种stream,我也没搞明白是什么。。。。。
这三种流,分别实现了上述的两个接口,完全了第一步抽象。
2.demux
同理,不同的container,也是需要隔离变化的,avi,mkv,mp4,需要不同的实现。我们不多说其他的,找出基类,看看谁继承了他。
原来他叫MediaExtractor ,再来看看他抽象了什么接口:
virtual size_t countTracks() = 0;
virtual sp<MediaSource> getTrack(size_t index) = 0;
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags = 0) = 0;
ok,原来是这三个接口需要实现。
再来看看谁实现了他。
class AacAdtsExtractor : public MediaExtractor
class AACExtractor : public MediaExtractor
struct ARTSPController : public MediaExtractor
struct AVIExtractor : public MediaExtractor
class DRMExtractor : public MediaExtractor
class FLACExtractor : public MediaExtractor
struct MatroskaExtractor : public MediaExtractor
class MP3Extractor : public MediaExtractor
struct MPEG2TSExtractor : public MediaExtractor
class MPEG4Extractor : public MediaExtractor
struct OggExtractor : public MediaExtractor
class WAVExtractor : public MediaExtractor
这就是android默认支持的demux文件各类了,如果我们要支持新的文件格式,比如flv,就可以新加个类
比如:class FlvExtractor:pulic MediaExtractor这样的,然后实现上述三个接口,就可以支持flv文件格式了。
3.encodec/decodec
这块代码主要是omx在实现,比较复杂,但还是符合我们上述所说的接口抽象,隔离变化的原则的
主要的抽象类是:
MediaSource
virtual status_t start(MetaData *params = NULL) = 0;
virtual status_t stop() = 0;
virtual sp<MetaData> getFormat() = 0;
virtual status_t read(MediaBuffer **buffer, const ReadOptions *options = NULL) = 0;
MediaBufferObserver
virtual void signalBufferReturned(MediaBuffer *buffer) = 0;
这里使用了观察者模式,我不知道为什么要这么设计才好,理解不了这样的设计,但是隐隐知道是有道理的。
实现这两个类的是:
struct OMXCodec : public MediaSource,public MediaBufferObserver
当然是OMXCodec,这个类,隔离了所有的codec的种类,软解,硬解,h264,mpeg4,mp3。。。。。
这是awesomeplayer中最复杂的类,隔离了最复杂的东西,屏避了最大的变化。
从代码分析,原生代码里面omxcodec只支持软解,但是对实际的soc来说,都加入了硬解支持。
下篇文章会分析,omx的组件如何构成以及如何在omxcodec里面加入硬解支持。
4.render。
对于这一步来说,android似乎是最轻松的,因为不用考虑太多变化的问题。因为对android的render来说,实际上没有任何变化。音频直接给audioflinger,图像直接给surfaceflinger。
这里只需要简单包装一下即可。
因为我只对视频有兴趣,我们就看看视频是如何抽象的。这一步甚至已经简单到不用单独起一个文件的地步了。其实整个stragefright目录,除掉上面写的那些类(每个类基本都是一个文件)和一些基本工具类(比如handler,timeevent,string。。类),就没有太多额外的东西了。整体架构比较简洁,比起vlc/directshow这种重型的多媒体框架/应用来说,相当简单。
这个类,只有一个接口。两种实现
struct AwesomeRenderer
virtual void render(MediaBuffer *buffer) = 0;
struct AwesomeLocalRenderer : public AwesomeRenderer
struct AwesomeNativeWindowRenderer : public AwesomeRenderer
local/native不同codec出来的数据
这里有几行注释,
// Hardware decoders avoid the CPU color conversion by decoding
// directly to ANativeBuffers, so we must use a renderer that
// just pushes those buffers to the ANativeWindow.
可以解释这个问题。
localrenderer,额外做了colorspace转化的工作,当然一般都是yv12/nv12(i420p)到rgb565这种,大众的,呵呵,如果你要支持特殊硬件,就要自己手写了。
好了。主要内容就是这些,理一下框架
datasource-->MediaExtractor-->MediaSource--->AwesomeRenderer
四大步,四种抽象接口。与其他的多媒体框架相比,抽象方法是一样的,只是接口略有区别。over..
awsomeplayer结构认识的更多相关文章
- 【.net 深呼吸】细说CodeDom(1):结构大观
CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧.DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了.如果你从来没接触过 CodeDom,你大概 ...
- 读书笔记:《HTML5开发手册》--HTML5新的结构元素
读书笔记:<HTML5开发手册> (HTML5 Developer's CookBook) 虽然从事前端开发已有很长一段时间,对HTML5标签也有使用,但在语义化上面理解还不够清晰.之前在 ...
- Python学习--04条件控制与循环结构
Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...
- HTML5 语义元素(一)页面结构
本篇主要介绍HTML5增加的语义元素中关于页面结构方面的,包含: <article>.<aside>.<figure>.<figcaption>.< ...
- React在开发中的常用结构以及功能详解
一.React什么算法,什么虚拟DOM,什么核心内容网上一大堆,请自行google. 但是能把算法说清楚,虚拟DOM说清楚的聊聊无几.对开发又没卵用,还不如来点干货看看咋用. 二.结构如下: impo ...
- ElasticSearch 5学习(10)——结构化查询(包括新特性)
之前我们所有的查询都属于命令行查询,但是不利于复杂的查询,而且一般在项目开发中不使用命令行查询方式,只有在调试测试时使用简单命令行查询,但是,如果想要善用搜索,我们必须使用请求体查询(request ...
- ASP.NET Core应用针对静态文件请求的处理[4]: DirectoryBrowserMiddleware中间件如何呈现目录结构
和StaticFileMiddleware中间件一样,DirectoryBrowserMiddleware中间本质上还是定义了一个请求地址与某个物理目录之间的映射关系,而目标目录体现为一个FilePr ...
- Go结构体实现类似成员函数机制
Go语言结构体成员能否是函数,从而实现类似类的成员函数的机制呢?答案是肯定的. package main import "fmt" type stru struct { testf ...
- CRL快速开发框架系列教程十(导出对象结构)
本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...
随机推荐
- string应用
今天在网上搜了一些资料. C# string类应用 判断是否包含子串 想要判断一个字符串中是否包含某个子串,可以用Contains方法来实现: ? public bool Contains (stri ...
- Force removing ActivityRecord,app died, no saved state报错的理解
为什么说理解呢?出现这个问题,我的情景是,在activity里面直接起了一个Thread,线程里面进行了一个繁重的任务,当线程执行完后,这个activity也销毁了,界面显示的任务栈下面的一个活动.百 ...
- Android中log4j的运用
网上一查关于android上面运用Log4j的运用,各种说需要添加多样的包的,照着log4j的官网教程看了下,给了个简单的输出到console上面的代码,似乎没什么用.看网上关于Log4j更多是在ja ...
- iOS开发——视频播放 待更新……
本文主要实现调用系统自带的播放器,自带的播放器已经做好了屏幕的适配,集成播放,暂停,快进等功能.能够满足基本的视频播放功能及iOS的视频播放的开发. 最后将其简单的封装成一个iOS视频播放工具类. 一 ...
- 关于layoutSubviews以及drawRect方法
首先两个方法都是异步执行.layoutSubviews方便数据计算,drawRect方便视图重绘. layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubvi ...
- 浅谈break 、continue、return,goto四种语句的区别。
浅谈break .continue.return三种语句的区别: break,continue,return这三个具有跳转功能的语句在c语言中经常被用到,近期身边有些小伙伴总是把它们的用法搞乱,在这里 ...
- html-----009
</head> <!-- 通过使用框架,你可以在同一个浏览器窗口中显示不止一个页面. <p> 垂直框架</p> 本例演示:如何使用三份不同的文档制作一个垂直框 ...
- tp_shop解读1
由于想弄一个商城,因此研究了一下tp_shop,这个据说能完成几乎所有的功能. 考虑到原有的例子过于复杂,因此把所有相关的数据都删除了,结果上来就出错了,查了两天,大致弄清楚了状况. 关于错误的原因 ...
- 一个供新手把玩的jQueryUI在线文档
最近整理了一份jQueryUI文档,方便以后学习和运用. 把玩地址
- 默认时,销毁会话,session_unset, session_destory
<?php /** 一般我们登录时,开启了会话,就会自动生成 session 有关的文件, 保存有相关的用户登录信息,所以正常情况下得退出登录, 同时也要清空 session 有关的文件和相关的 ...