我的其他文章
0.拼音查詞開源庫
1.ExoPlayer源碼淺析
2.Android實現LED燈顯示效果
3.Picasso源碼淺析
4.一行代碼實現RecyclerView的多選批量操作
5.Android 圖片網格布局控件
6.PaperView:像紙一樣折疊
7.TabViewPager 很好用
8.RecyclerView 學習筆記
9.發布Library到JCenter可以這么簡單
Developer guide
在Android設備中,播放視頻和音樂是非常普遍的。Android框架提供了一個對于媒體的操作的最省代碼的解決方案:MediaPlayer。它提供了低等級的媒體API,例如:MediaCodec,AudioTrack,MediaDrm,可以用于建立自定義媒體播放的解決方案。
ExpPlayer是一個開源的,App等級的媒體API,它的開源項目包含了library和示例:
- ExoPlayer library - 這部分是核心的庫
- Demo app - 這部分是演示怎么使用ExoPlayer的Demo
Pros and cons
ExoPlayer相較于MediaPlayer有很多很多的優點:
- 支持動態的自適應流HTTP(DASH) 和 平滑流,任何目前MediaPlayer支持的視頻格式(同時它還支持HTTP直播了(HLS),MP4,MP3,WebM,M4A,MPEG-TS 和 AAC).
- 支持高級的HLS特性,例如正確處理
EXT-X-DISCONTINUITY
標簽; - 支持自定義和擴治你的使用場景。ExoPlayer專門為此設計;
- 便于隨著App的升級而升級。因為ExoPlayer是一個包含在你的應用中的庫,對于你使用哪個版本有完全的控制權,并且你可以簡單的跟隨應用的升級而升級;
- 更少的適配性問題。
值得注意的時,ExoPlayer同時有些缺點:
- ExoPlayer的音頻和視頻組件依賴Android的
MediaCodec
接口,該接口發布于Android4.1(API 等級16)。因此它不能工作于之前的Android版本。 - ExoPlayer目前還不支持自動檢查需要播放的媒體格式。應用需要知道他想要播放的媒體格式去構建一個ExoPlayer去播放媒體。這個問題已經在Issue #438解決。
Library overview
在ExoPlayer的庫中最重要的類是ExoPlayer
,這個類維護著播放器的全局狀態,和正在播放的媒體特質,例如怎么獲取到的媒體數據,它使怎么緩存或者它的格式。你可以以TrackRenderer
類的方式通過ExoPlayer的prepare
方法注入。
ExoPlayer提供默認的音頻和視頻渲染器,利用了Android框架中的MediaCodec
和AudioTrach
類。這兩個都需要一個SampleSource
對象中注入,用來實現媒體示例的播放。
組件的注入在當前ExoPlayer庫中是普遍存在的。圖1展示了使用一個ExoPlayer來配置和播放MP4媒體流的高級對象模型。默認的音頻和視頻渲染器已經被注解到ExoPlayer
中。一個叫ExtractorSampleSource
類的實現被注解到渲染器中用于提供簡單的媒體播放功能。DataSource
和Extractor
示例被注解到ExtractorSampleSource
來支持加載媒體流和在被加載的數據中提取樣板。在這個示例中DefaultUriDataSource
和Mp4Extractor
被用于播放從URIs中導入的MP4流。
總的來說,ExoPlayer實例被用來注解支持開發者需求的組件,這個模型使定制播放器變得非常簡單,并支持自定義組件。以下部分介紹了在這個模型圖種三個最最重要的部分:
TrackRender
,SampleSource
和DataSource
。
TrackRenderer
一個TrackRenderer
播放特定類型的媒體,例如視頻,音頻和文字。ExoPlayer類在它的TrackRenderer
上執行方法,使用單獨的線程,因此,導致每種類型的媒體被渲染全局的播放位置,ExoPlayer庫提供MediaCodecVideoTrackRenderer
作為默認的實現用于渲染視頻,MediaCodecAudioTrackRender
渲染音頻。兩種實現都是利用Android的 MediaCodec 去解碼每個媒體樣本。他們可以處理所有Android設備支持的音頻和視頻格式(詳細信息請看支持媒體類型)。ExoPlayer庫也提供了一個渲染文本的渲染器TextTrackRenderer
。
以下代碼示例使用標準的TrackRenderer
實現視頻,音頻播放需要的步驟:
//1.初始化播放器
player = ExoPlayer.Factory.newInstance(RENDERER_COUNT);
//2.構建渲染器
MediaCodecVideoTrackRender videoRender = ...
MediaCodecAudioTrackRender audioRender = ...
//3.通過prepare注入渲染器
player.prepare(videoRender,audioRender);
//4.將surface傳遞到渲染器
player.sendMessage(videoRender,MediaCodecVideoTrackRenderer.MSG_SET_SURFACE,surface);
//5.開始播放
player.setPlayWhenReady(true);
....
player.release(); //當播放完成,別忘了釋放!
想看完整的例子,請在ExoPlayer demo app中查看PlayerActivity和
DemoPlayer。其中詳細的示范如何使用ExoPlayer實例,以及
Activity和
Surface`的生命周期。
SampleSource
庫中提供標準的TrackRenderer
實現需要SampleSource
實例被注入到他們的構造方法中。一個SampleSource
對象提供了格式信息,和被渲染的媒體樣本。ExoPlayer庫提供了一些不同類型的SampleSource
實例:
-
ExtractorSampleSource
- 用于MP3,M4A,WebM,MPEG-TS和AAC; -
ChunkSampleSource
- 用于DASH和平滑流的播放; -
HlsSampleSource
- 用于HLS 播放;
后面的部分會詳細介紹這些實例的使用。
DataSource
ExoPlayer庫提供的標準的SampleSource
實例是利用了DataSource
來加載媒體數據的。各種類型的實現都放在upstream
包種。最最多用到的實現是:
-
DefaultUriDataSource
- 用于播放本地和網絡媒體; -
AssetDataSource
- 用于播放應用中assets
文件夾下的媒體。
Traditional media playbacks
Explayer庫提供了ExtractorSampleSource
用于播放傳統格式的媒體,包括MP3,M4A,MP4,WebM,MPEG-TS和AAC,圖1中展示了ExoPlayer播放MP4流的對象模型,以下代碼展示了如何構造和實例化TrackRenderer
。
DataSource dataSource = new DefaultUriDataSource(userAgent, null);
Mp4Extractor extractor = new Mp4Extractor();
ExtractorSampleSource sampleSource = new ExtractorSampleSource(
uri, dataSource, extractor, 2, BUFFER_SIZE);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(
sampleSource, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT);
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource);
每種類型的媒體格式都需要一個對應的解析器(Extractor
)。在ExoPlayer庫的extractor
包種包含了不同類型的解析器,你可以實現你自己的解析器,如果庫中不包含你需要的類型的話。
ExoPlayer的示例代碼中提供了一個完整的ExtractorRendererBuilder
的示例。PlayerActivity
使用它播放一些可用的視頻。
Adaptive media playbacks
ExoPlayer 支持自適應流,即在播放的時候,根據網絡狀況自動調節視頻質量。DASH,SmoothStreaming和HLS展示了自適應流技術。以上三種,媒體都是通過小塊的方式加載(通常2到10秒的長度)。每當一塊媒體被請求,客戶端將會選擇一種可能的規格。例如:如果網絡情況比較好,客戶端將選擇高質量的規格,如果網絡比較差則會低質量的。在兩種技術中,視頻和音頻都需要被分割。
DASH android SmoothStreaming
ExoPlayer庫通過ChunkSampleSource
支持DASH和SmoothStreaming動態播放,即通過讀取獨立的媒體塊。每個ChunkSampleSOurce
需要一個ChunkSource
通過構造方法注入進來。ChunkSource
主要負責加載和讀取樣本來提供媒體塊。DashChunkSource
類使用FMP4和WebM容器格式來提供DASH播放。SmoothStreamingChunkSource
類使用FMP4容器格式。
兩種類型的ChunkSource
實例需要一個解析器FormatEvaluator
和一個數據源DataSource
通過構造的方式注入。FormatEvaluator
在每個塊被加載之前選擇一種可用的格式,DataSource
提供數據源。最終,ChunkSampleSource
需要一個LoadControl
對象去控制緩沖塊。
圖2演示了DASH動態播放通常的配置。通過FormatEvaluator
實現視頻質量的動態變化,但是音頻的質量是固定的。
這部分動態視頻流暫時用不著,以后有機會翻譯...
Player events
在播放階段,你的App可以收到所有ExoPlayer產生的時間,這些事件對于提升用戶體驗有很大的幫助,如對播放的控制。一些ExoPlayer組件還提供了他們自己底層的事件,可以監聽性能。
High level events
ExoPlayer允許通過addListener()
和removeListener()
的方式添加ExoPlayer.Listener
實例,被注冊的監聽器將會得到播放狀態的回調,還要錯誤導致的播放失敗,如果需要知道更多的播放狀態和可能的狀態直接的相互轉換,請查閱ExoPlayer源碼。
Low level events
除了高級事件,個別的組件還允許監聽他們自己的時間,例如,MediaCodecVideoTrackRenderer
的構造方法提供了MediaCodecVideoTrackRenderer.EventListener
。在ExoPlayer的demo中,這給PlayerAcitivity
調整目標surface的尺寸到合適的高度和寬度的途徑。
@Override
public void onVideoSizeChanged(int width, int height, float pixelWidthAspectRatio) {
surfaceView.setVideoWidthHeightRatio(
height == 0 ? 1 : (width * pixelWidthAspectRatio) / height);
}
Customization
懶得翻譯了...