Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085
不知不觉到第九篇了,感觉还有好多好多没有写,路漫漫其修远兮 ,吾将上下而求索,上篇主要介绍了Stagefright框架及AwesomePlayer的数据解析器,最后我们说道,涉及parse及decode部分,将在本篇中介绍,看下今天的Agenda:
- 两张图看数据走向
- AwesomePlayer中prepare过程
- AwesomePlayer初始化音视频解码器过程
- Stagefright的Decode过程
- Stagefright处理数据过程
- 数据由源到最终解码后的流程
两张图看数据走向
一切从MediaSource中来,一切又从MediaSource中去
Audio:
Video:
AwesomePlayer中prepare过程
首先我们开始看下AwesomePlayer的prepare的执行过程:
以上代码总结为:prepare过程调用了prepareAsync_l函数,在prepareAsync_l中执行new AwesomeEvent,并将AwesomePlayer调用onPrepareAsyncEvent的结果返回AwesomeEvent的构造作为参数。
接着分析AwesomeEvent的过程: 启动mQueue,作为event handler
上面new AwesomeEvent会执行onPrepareAsyncEvent函数,我们看下该函数的做了什么?
以上代码总结为:会将AV(音视频)进行分处理,于是有了AwesomePlayer::initVideoDecoder及AwesomePlayer::initAudioDecoder()函数。
本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085
初始化音视频解码器过程
我们先看下initVideoDecoder,即初始化视频解码器:
接着看下初始化音频解码器,看下几个变量的声明:
接着看代码如下:
对上面代码进行总结:
Stagefright调用AwesomePlayer的prepare后,AwesomePlayer调用自身的prepareAsync进行初始化化音视频解码器,这两个方法里面都会OMXCodec::Create,接下来看下这个过程。
Stagefright的Decode过程
经过“数据流的封装”得到的两个MediaSource,其实是两个OMXCodec。AwesomePlayer和mAudioPlayer都是从MediaSource中得到数据进行播放。AwesomePlayer得到的是最终需要渲染的原始视频数据,而mAudioPlayer读取的是最终需要播放的原始音频数据。也就是说,从OMXCodec中读到的数据已经是原始数据了。
OMXCodec是怎么把数据源经过parse、decode两步以后转化成原始数据的。从OMXCodec::Create这个构造方法开始,下面看它的代码:
以上代码总结为:对应参数分析:
- IOMX &omx指的是一个OMXNodeInstance对象的实例。
- MetaData &meta这个参数由MediaSource.getFormat获取得到。这个对象的主要成员就是一个KeyedVector(uint32_t, typed_data) mItems,里面存放了一些代表MediaSource格式信息的名值对。
- bool createEncoder指明这个OMXCodec是编码还是解码。
- MediaSource &source是一个MediaExtractor(数据解析器)。
- char *matchComponentName指定一种Codec用于生成这个OMXCodec。
先使用findMatchingCodecs寻找对应的Codec,找到以后为当前IOMX分配节点并注册事件监听器:omx->allocateNode(componentName, observer, &node)。最后,把IOMX封装进一个OMXCodec:
这样就得到了OMXCodec。
- AwesomePlayer中得到这个OMXCodec后,接着看initVideoDecoder/initAudioDecoder,这里看initAudioDecoder方法,是把 mAudioSource = mOmxSource,赋值,接着调用mAudioSource->start()进行初始化。 OMXCodec初始化主要是做两件事:
- 向OpenMAX发送开始命令。mOMX->sendCommand(mNode, OMX_CommandStateSet, OMX_StateIdle)
- 调用allocateBuffers()分配两个缓冲区,存放在Vector mPortBuffers[2]中,分别用于输入和输出。
- 然后在现个initxxxDecoder方法中会调用(mAudioSource->start()/mVideoSource->start())
触发MediaSource的子类VideoSource及AudioSource调用start()方法后,它的内部就会开始从数据源获取数据并解析,等到缓冲区满后便停止。在AwesomePlayer里就可以调用MediaSource的read方法读取解码后的数据。
- 对于mVideoSource来说,读取的数据:mVideoSource->read(&mVideoBuffer, &options)交给显示模块进行渲染,mVideoRenderer->render(mVideoBuffer);
对mAudioSource来说,用mAudioPlayer对mAudioSource进行封装,然后由mAudioPlayer负责读取数据和播放控制。
AwesomePlayer调用OMXCode读取ES数据,并且进行解码的处理
- OMXCodec调用MediaSource的read函数来获取音视频的数据
- OMXCodec调用Android的IOMX接口,其实就是Stagefrightdecode中的 OMX实现
本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085
这个过程就是prepare的过程,重点是解码把流放到Buffer中
接下来,当java层调用start方法时,通过mediaplayerservice,再传到StagefrightPlayer中,引用AwesomePlayer,这样就调到AwesomePlayer的play方法,看代码:
- 当AwesomePlayer调用play后,通过mVideoSource->read(&mVideoBuffer, &options)读取数据。mVideoSource->read(&mVideoBuffer, &options)具体是调用OMXCodec.read来读取数据。而OMXCodec.read主要分两步来实现数据的读取:
- (1) 通过调用drainInputBuffers()对mPortBuffers[kPortIndexInput]进行填充,这一步完成 parse。由OpenMAX从数据源把demux后的数据读取到输入缓冲区,作为OpenMAX的输入。
- (2) 通过fillOutputBuffers()对mPortBuffers[kPortIndexOutput]进行填充,这一步完成 decode。由OpenMAX对输入缓冲区中的数据进行解码,然后把解码后可以显示的视频数据输出到输出缓冲区。
AwesomePlayer通过mVideoRenderer->render(mVideoBuffer)对经过parse和decode 处理的数据进行渲染。一个mVideoRenderer其实就是一个包装了IOMXRenderer的AwesomeRemoteRenderer:
Stagefright处理数据过程
Audioplayer为AwesomePlayer的成员,audioplayer通过callback来驱动数据的获取,awesomeplayer则是通过 videoevent来驱动。二者有个共性,就是数据的获取都抽象成mSource->read()来完成,且read内部把parse和decode绑在一起。Stagefright AV同步部分,audio完全是callback驱动数据流,注意是video部分在onVideoEvent里会获取audio的时间戳,是传统的AV时间戳做同步。
AwesomePlayer的Video主要有以下几个成员:
- mVideoSource(解码视频)
- mVideoTrack(从多媒体文件中读取视频数据)
- mVideoRenderer(对解码好的视频进行格式转换,android使用的格式为RGB565)
- mISurface(重绘图层)
- mQueue(event事件队列)
stagefright运行时的Audio流程如下:
- 首先设置mUri的路径
- 启动mQueue,创建一个线程来运行 threadEntry(命名为TimedEventQueue,这个线程就是event调度器)
- 打开mUri所指定的文件的头部,则会根据类型选择不同的分离器(如MPEG4Extractor)
- 使用 MPEG4Extractor对MP4进行音视频轨道的分离,并返回MPEG4Source类型的视频轨道给mVideoTrack
- 根据 mVideoTrack中的编码类型来选择解码器,avc的编码类型会选择AVCDecoder,并返回给mVideoSource,并设置mVideoSource中的mSource为mVideoTrack
- 插入onVideoEvent到Queue中,开始解码播放
- 通过mVideoSource对象来读取解析好的视频buffer
如果解析好的buffer还没到AV时间戳同步的时刻,则推迟到下一轮操作
1、mVideoRenderer为空,则进行初始化(如果不使用 OMX会将mVideoRenderer设置为AwesomeLocalRenderer)
2、通过mVideoRenderer对象将解析好的视频buffer转换成RGB565格式,并发给display模块进行图像绘制
3、将onVideoEvent重新插入event调度器来循环
本文出自逆流的鱼:http://blog.csdn.net/hejjunlin/article/details/52532085
Stagefright数据由源到最终解码后的流程
可以对照《Android Multimedia框架总结(八)Stagefright框架之AwesomePlayer及数据解析器》中那个图,这里不贴了,
- 设置DataSource,数据源可以两种URI和FD。URI可以http://,rtsp://等。FD是一个本地文件描述符,能过FD,可以找到对应的文件。
- 由DataSource生成MediaExtractor。通过sp extractor = MediaExtractor::Create(dataSource);来实现。 MediaExtractor::Create(dataSource)会根据不同的数据内容创建不同的数据读取对象。
- 通过调用setVideoSource由MediaExtractor分解生成音频数据流(mAudioTrack)和视频数据流(mVideoTrack)。
- onPrepareAsyncEvent()如果DataSource是URL的话,根据地址获取数据,并开始缓冲,直到获取到mVideoTrack和mAudioTrack。mVideoTrack和mAudioTrack通过调用initVideoDecoder()和initAudioDecoder()来生成 mVideoSource和mAudioSource这两个音视频解码器。然后调用postBufferingEvent_l()提交事件开启缓冲。
- 数据缓冲的执行函数是onBufferingUpdate()。缓冲区有足够的数据可以播放时,调用play_l()开始播放。play_l()中关键是调用了postVideoEvent_l(),提交了 mVideoEvent。这个事件执行时会调用函数onVideoEvent()。这个函数通过调用 mVideoSource->read(&mVideoBuffer, &options)进行视频解码。音频解码通过mAudioPlayer实现。
- 视频解码器解码后通过mVideoSource->read读取一帧帧的数据,放到mVideoBuffer中,最后通过 mVideoRenderer->render(mVideoBuffer)把视频数据发送到显示模块。当需要暂停或停止时,调用cancelPlayerEvents来提交事件用来停止解码,还可以选择是否继续缓冲数据。
第一时间获得博客更新提醒,以及更多android干货,源码分析,欢迎关注我的微信公众号,扫一扫下方二维码或者长按识别二维码,即可关注。
如果你觉得好,随手点赞,也是对笔者的肯定,也可以分享此公众号给你更多的人,原创不易
Android Multimedia框架总结(九)Stagefright框架之数据处理及到OMXCodec过程相关推荐
- Android Multimedia Framework overview(多媒体框架概述)--base on jellybean(一)
不知为啥今晚突然脑海中闪现出一个念头:写博客!原因有二,其一就是记录下自己的学习所得,巩固自己的知识,温故而知新吧,以前都是光看光想,都没有记录,而且不写下来,领悟估计就差点了,好记忆不如烂笔头啊!其 ...
- android stagefright框架
http://blog.csdn.net/mirkerson/article/details/38520135 stagefright框架(一)Video Playback的流程 在Android上, ...
- android stagefright 框架
原文:[转]android stagefright 框架 链接:http://blog.chinaunix.net/uid-9838896-id-2976618.html 在Android上,预设的多 ...
- Android MultiMedia框架完全解析 - 概览
之前的工作中,一直在看Android MultiMedia的一些东西,关注我博客的同学也许知道我换工作了,以后将要从事Camera相关的工作,于是乎,将之前整理存放在有道云笔记里面的一些东西发出来,整 ...
- StageFright框架流程解读
1. StageFright介绍 Android froyo版本多媒体引擎做了变动,新添加了stagefright框架,并且默认情况android选择stagefright,并没有完全抛弃ope ...
- Android 快速开发框架:推荐10个框架
一. Afinal 官方介绍: Afinal是一个Android的ioc,orm框架,内置了四大模块功能:FinalAcitivity,FinalBitmap,FinalDb,FinalHttp.通 ...
- stagefright框架概述
多媒体框架stagefright是android2.3后替代opencore的.整个框架非常庞大,这里将它分为编码器.解码器.合成器.分离器.PCM数据和YUV数据输入.数据源(DataSource) ...
- android调频收音机代码,android 收音机 FM 驱动 hal层 框架层以及应用层代码
[实例简介] android 收音机 FM 驱动 hal层 框架层以及应用层代码 方法一 不需要framework部分 1.fm放到 \hardware\rk2x 2.FmRadio 放到 packa ...
- Android用户界面设计“.NET研究”:框架布局
框架布局是将控件组织在Android程序的用户界面中最简单的布局类型之一. 理解布局对于良好的Android程序设计来说是非常重要的.在这个教程里,你将学到所以关于框架布局的知识,它们主要用来在屏幕上 ...
- 理想的互联网服务后台框架的九个要点
理想的互联网服务后台框架的九个要点 对于互联网服务后台团队,开发框架的选择是非常关键的一个问题,多年的海量服务经验和教训使得我们团队深刻的认识到: 要尽早规范团队的开发服务框架,避免到了后期,各种开发 ...
最新文章
- 知乎热议:28岁郭宇期权过亿,彪悍从字节退休,旅居日本开温泉酒店
- 各种编程语言的深度学习库整理(中英版)
- Origin如何绘制泡泡图?
- 1079. 延迟的回文数 (20)
- C++set容器去重法
- 一个人成为废材的9大原因
- 解决python-kafka连接kafka时报错kafka.errors.NoBrokersAvailable: NoBrokersAvailable
- 力扣101. 对称二叉树(JavaScript)
- 二选一数据选择器2-1 MUX
- Flex builder3相关
- 用户体验测试的心得体会
- Android Webview下载Blob文件
- C语言基础知识复习(1)
- 【matlab图像处理笔记4】【图像变换】(三)图像的霍夫变换
- waterdrop1.x导入clickhouse分布式表-fitersql
- html的日历中添加行程,HTML/CSS元素定位(html日程表/日历)
- 最新android iso,android x86 7.0下载
- mysql zfs快照_ZFS for MySQL
- 石臻臻的2021总结和2022展望 | 文末彩蛋
- 【视频】国产女声电子摇滚/电子核| 真军乐队True Army - 放课后少女| 混音母带处理 By JeromeAlanChan(MZD Studios)
热门文章
- tensorflow中获取shape的方法比较
- opencv图像分析与处理(15)- 图像压缩中的编码方法:霍夫曼编码、Golomb编码、Rice编码、算术编码及其实现
- 编译原理的first、follow、select
- HDU-1548(BFS+剪枝)
- 血压预测常用数据集整理
- LDD3 第15章 内存映射和DMA
- Excel基本操作技巧荟萃(值得您深入探讨 他懂了)
- MVC 发布到 windows2003遇到 'System.Web.WebPages.Razor 错误提示
- 寻找二值图像的连通域算法分析
- asp.net mvc 2.0 TryValidateModel(Object)方法