android stagefright框架
http://blog.csdn.net/mirkerson/article/details/38520135
[圖1] Stagefright在Android多媒體架構中的位置。
[圖2] Stagefright所涵蓋的模組 (註2)。
以下我們就先來看看Stagefright是如何播放一個影片檔。
Stagefright在Android中是以shared library的形式存在(libstagefright.so),其中的module -- AwesomePlayer可用來播放video/audio(註3)。AwesomePlayer提供許多API,可以讓上層的應用程式(Java/JNI)來呼叫,我們以一個簡單的程式來說明video playback的流程。
在Java中,若要播放一個影片檔,我們會這樣寫:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE); ...... (1)
mp.prepare(); ........................ (2)、(3)
mp.start(); .......................... (4)
在Stagefright中,則會看到相對應的處理;
(1)將檔案的絕對路徑指定給mUri
|
(2)啟動mQueue,作為event handler
|
(3) onPrepareAsyncEvent被觸發
|
(3.1)解析mUri所指定的檔案,並且根據其header來選擇對應的extractor
|
(3.2)使用extractor對檔案做A/V的分離 (mVideoTrack/mAudioTrack)
|
(3.3)根據mVideoTrack中的編碼類型來選擇video decoder (mVideoSource)
|
(4) 將mVideoEvent放入mQueue中,開始解碼播放,並交由mVideoRenderer來畫出
|
(註1) 從Android2.3 (Gingerbread) 開始,預設的多媒體框架為 Stagefright。
(註2) Stagefright的架構尚不斷在演進中,本系列文章並未含括所有的模組。
(註3) Audio的播放是交由 AudioPlayer 來處理,請參考《Stagefright (6) - Audio Playback的流程》。
stagefright框架(二)- 和OpenMAX的運作
Stagefright的編解碼功能是利用OpenMAX框架,而且用的還是OpenCORE之OMX的實作,我們來看一下Stagefright和OMX是如何運作的。
(1) OMX_Init
|
(2) OMX_SendCommand
|
(3) 其他作用在 OMX 元件的指令
其他作用在OMX元件的指令也和OMX_SendCommand的callpath一樣,請見下表:
OMXCodec |
OMX |
OMXNodeInstance |
useBuffer |
useBuffer (OMX_UseBuffer) |
|
getParameter |
getParameter (OMX_GetParameter) |
|
fillBuffer |
fillBuffer (OMX_FillThisBuffer) |
|
emptyBuffer |
emptyBuffer (OMX_EmptyThisBuffer) |
(4) Callback Functions
|
stagefright框架(三)-選擇Video Decoder
在《Stagefright (1) – Video Playback的流程》中,我們並沒有詳述Stagefright是如何根據影片檔的類型來選擇適合的video decoder,現在,就讓我們來看一看。
(1) Video decoder是在onPrepareAsyncEvent中的initVideoDecoder被決定的
OMXCodec::Create()會回傳video decoder給mVideoSource。
|
(2) 根據mVideoTrack的MIME從kDecoderInfo挑出合適的components
|
GetCodec會依據mime從kDecoderInfo挑出所有的component name,然後存到matchingCodecs中。
(3) 根據matchingCodecs中component的順序,我們會先去檢查其是否為software decoder
|
所有的software decoder都會被列在kFactoryInfo中,我們藉由傳進來的name來對應到適合的decoder。
(4) 如果該component不是software decoder,則試著去配置對應的OMX component
|
(5) 若該component為OMX deocder,則回傳;否則繼續檢查下一個component
stagefright框架(四)-Video Buffer傳輸流程
這篇文章將介紹Stagefright中是如何和OMX video decoder傳遞buffer。
(1) OMXCodec會在一開始的時候透過read函式來傳送未解碼的data給decoder,並且要求decoder將解碼後的data傳回來
|
(2) Decoder從input port讀取資料後,開始進行解碼,並且回傳EmptyBufferDone通知OMXCodec
|
OMXCodec收到EMPTY_BUFFER_DONE之後,繼續傳送下一個未解碼的資料給decoder。
(3) Decoder將解碼完的資料送到output port,並回傳FillBufferDone通知OMXCodec
|
OMXCodec收到FILL_BUFFER_DONE之後,將解碼後的資料放入mFilledBuffers,發出mBufferFilled信號,並且要求decoder繼續送出資料。
(4) read函式在後段等待mBufferFilled信號。當mFilledBuffers被填入資料後,read函式將其指定給buffer指標,並回傳給AwesomePlayer
|
stagefright框架(五)-Video Rendering
AwesomePlayer::onVideoEvent除了透過OMXCodec::read取得解碼後的資料外,還必須將這些資料(mVideoBuffer)傳給video renderer,以便畫到螢幕上去。
(1) 要將mVideoBuffer中的資料畫出來之前,必須先建立mVideoRenderer
|
(2) 如果video decoder是OMX component,則建立一個AwesomeRemoteRenderer作為mVideoRenderer
從上段的程式碼(1)來看,AwesomeRemoteRenderer的本質是由OMX::createRenderer所創建的。createRenderer會先建立一個hardware renderer --SharedVideoRenderer (libstagefrighthw.so);若失敗,則建立software renderer -- SoftwareRenderer (surface)。
|
(3) 如果video decoder是software component,則建立一個AwesomeLocalRenderer作為mVideoRenderer
AwesomeLocalRenderer的constructor會呼叫本身的init函式,其所做的事和OMX::createRenderer一模一樣。
|
(4) mVideoRenderer一經建立就可以開始將解碼後的資料傳給它
|
stagefright框架(六)-Audio Playback的流程
到目前為止,我們都只著重在video處理的部分,對於audio卻隻字未提。這篇文章將會開始audio處理的流程。
Stagefright中關於audio的部分是交由AudioPlayer來處理,它是在AwesomePlayer::play_l中被建立的。
(1) 當上層應用程式要求播放影音時,AudioPlayer同時被建立出來,並且被啟動
|
(2) AudioPlayer在啟動的過程中會先去讀取第一筆解碼後的資料,並且開啟audio output
|
從AudioPlayer::start的程式碼來看,AudioPlayer似乎並沒有將mFirstBuffer傳給audio output。
(3) 開啟audio output的同時,AudioPlayer會將callback函式設給它,之後每當callback函式被呼叫,AudioPlayer便去audio decoder讀取解碼後的資料
|
解碼後audio資料的讀取就是由callback函式所驅動,但是callback函式又是怎麼由audio output去驅動的,目前從程式碼上還看不出來。另外一方面,從上面的程式片段可以看出,fillBuffer將資料(mInputBuffer)複製到data之後,audio output應該會去取用data。
(5) 至於audio decoder的工作流程則和video decoder相同,可參閱《Stagefright (4)- Video Buffer傳輸流程》
stagefright框架(七)-Audio和Video的同步
講完了audio和video的處理流程,接下來要看的是audio和video同步化(synchronization)的問題。OpenCORE的做法是設置一個主clock,而audio和video就分別以此作為輸出的依據。而在Stagefright中,audio的輸出是透過callback函式來驅動,video則根據audio的timestamp來做同步。以下是詳細的說明:
(1) 當callback函式驅動AudioPlayer讀取解碼後的資料時,AudioPlayer會取得兩個時間戳 -- mPositionTimeMediaUs和mPositionTimeRealUs
|
mPositionTimeMediaUs是資料裡面所載明的時間戳(timestamp);mPositionTimeRealUs則是播放此資料的實際時間(依據framenumber及samplerate得出)。
(2) Stagefright中的video便依據從AudioPlayer得出來之兩個時間戳的差值,作為播放的依據
|
AwesomePlayer從AudioPlayer取得realTimeUs(即mPositionTimeRealUs)和mediaTimeUs(即mPositionTimeMediaUs),並算出其差值mTimeSourceDeltaUs。
(3) 最後我們將該video資料做排程
|
android stagefright框架相关推荐
- android stagefright 框架
原文:[转]android stagefright 框架 链接:http://blog.chinaunix.net/uid-9838896-id-2976618.html 在Android上,预设的多 ...
- android多媒体框架学习 详解
原址 一:多媒体框架概述 jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了! ...
- android多媒体框架学习 详解 最新版本
一:多媒体框架概述 jellybean 的多媒体跟以前的版本,通过对比没啥变化,最大的变化是google终于舍得给multimedia建个独立的git了(framework/av),等你好久了!也体现 ...
- StageFright框架流程解读
1. StageFright介绍 Android froyo版本多媒体引擎做了变动,新添加了stagefright框架,并且默认情况android选择stagefright,并没有完全抛弃ope ...
- Android View框架的measure机制
Android中View框架的工作机制中,主要有三个过程: 1.View树的测量(measure)Android View框架的measure机制 http://www.cnblogs.com/xyh ...
- 5个最佳的Android测试框架
2019独角兽企业重金招聘Python工程师标准>>> 谷歌的Android生态系统正在不断地迅速扩张.有证据表明,新的移动OEM正在攻陷世界的每一个角落,不同的屏幕尺寸.ROM / ...
- 开发自己的山寨Android注解框架
目录 开发自己的山寨Android注解框架 开发自己的山寨Android注解框架 参考 Github黄油刀 Overview 在上一章我们学习了Java的注解(Annotation),但是我想大家可能 ...
- android layout后还原位置,Android图片框架photoview如何记住所有状态并还原,包括缩放度,缩放后的移动的距离等等...
Android图片框架photoview如何记住状态并还原,包括缩放度,缩放后的移动的距离等等,尝试了好多方法都没有作用. private void generateImages() { for (i ...
- stagefright框架概述
多媒体框架stagefright是android2.3后替代opencore的.整个框架非常庞大,这里将它分为编码器.解码器.合成器.分离器.PCM数据和YUV数据输入.数据源(DataSource) ...
最新文章
- PHP executable not found. Install PHP 7 and add it to your PATH or set the php.executablePath settin
- win10下pycharm安装opencv tensorflow anaconda
- 死磕Java并发:J.U.C之读写锁:ReentrantReadWriteLock
- 【NGINX+PHP7.3+MYSQL】安装指南
- Python学习笔记:电子邮件,POP3收取邮件
- 提取图片纹理_Fundamentals Of Computer Graphics 第十一章 纹理映射(中)
- 【Trie】【费用流】管道监控(loj 3026)
- CIO大咖专访 | 从实战中提炼的企业数字化转型要点
- TensorFlow第八步 Nesterov's accelerated gradient descent+L2 regularization
- python中布尔变量的值为_python 布尔操作实现代码 python是如何定义并使用变量的...
- Java字符串中最长回文子字符串
- 梦幻之旅--深入大规模芯片设计全过程
- 《薄世宁医学通识讲义》笔记
- 如何删除360浏览器的桔梗导航
- 什么是工业物联网?与工业互联网有什么区别
- sudo: no valid sudoers sources found,quitting sudo sudoers改坏后无法使用sudo的解决办法
- UE5学习笔记(五)——地形及地表材质
- linux应用程序注册表,如何打开 Linux 中 Windows 程序的注册表编辑器
- [转载]机器人工程师的漫漫长路
- Linux - 如何生成configure文件
热门文章
- Typora+PicGo+GitHub图床的搭建和常见问题的个人解决方法
- 我让小屋更漂亮计算机教案,漂亮的房间教案
- win10 调整了文本大小后桌面图标间距变宽,改不回去
- 抖音游戏发行人项目,靠量去堆砌也能月入三千
- 精通 TensorFlow 2.x 计算机视觉:第一部分
- Vue-3D-Model:用简单的方式来展示三维模型
- 2021(SSL) 自监督学习最新力作:Barlow Twins: Self-Supervised Learning via Redundancy Reduction
- 30个视频号运用方法,你都知道哪些?(四)
- PowerPoint绘图笔不能用
- linux temp文件夹在哪_全方位剖析 Linux 操作系统,太全了