使用VLC-Android寫一個簡單的電視直播demo
近兩年每天各種新的“干貨”出來,可以說真的是百花齊放百家爭鳴,每天也有各種各樣不同的文章在簡書和各大平台上嶄露頭角。而我就比較吃虧了,寫文章容易詞窮,文字功底一般,對於技術性的文字,也就記錄記錄流水賬,再加上我本來就沒有什么技術功底和學術功底,寫不出什么干貨文來,所以距離上一次寫博客文章已經過去很久很久以前的事情了。
前一陣子我買了一個電視盒子,所以我想寫個電視應用,沒事可以在盒子上安裝自己可控的電視應用,自己維護電視頻道,所以我開始着手做這件事情。
所以本文就是我就隨手記錄一下開發的思考過程,本文是最簡單的入門文,大牛們可以繞開此文。
准備工作
首先其一,要想一下如何做一個簡單的直播播放器的demo.
我們考慮一下,做一個電視直播應用需要哪些需求。
1、有好多台
2、能看直播頻道
3、能裝到盒子上
詳細一點的需求
再詳細一點說就是:
1、能維護一個電視頻道列表
2、能夠播放直播的流媒體視頻,並且能夠兼容多種流媒體視頻協議和視頻封裝和編碼格式
3、能安裝到多種硬件平台的Android盒子上
技術要求和實現
我們可以看到,這玩意兒的業務邏輯實在是再簡單不過了,只是個demo嘛。
首先看第一個,一個列表,相當簡單,維護一個ListView,並且用一個數據表來緩存這個列表,就OK了,毫無干貨。
先跳過第二個,看第三個,因為第二個看起來好麻煩的樣子。
第三個,我感覺這些便宜的盒子大多數是armv7a的硬件平台,最低系統版本是4.4,所以我們的應用只要考慮在這上面能夠播放視頻流就可以了。
回過頭來看最主要的要求,首先,我們要支持的是視頻格式。現在大多數硬件平台應該是可以輕松支持H.264,1080P,30fps的視頻解碼,包括硬件解碼和軟件解碼,而現在的流媒體視頻大多數是這種方式編碼傳輸,當然,不排除使用MPEG2格式的視頻。不管是硬件解碼還是軟件解碼,只要能解碼,就是好碼。嗯。
前面說啰嗦了,簡言之,只要是流媒體視頻,我們只要考慮能夠支持以下編碼即可:
H.264, MPEG2, ,稍微好點的可以支持H.265。
支持的分辨率大小,我想現在沒有不支持1080P的吧,那么1080P以下應該是沒有問題的。
幀率要達到30fps就不用說了。
另外,上面說的只是視頻編碼格式。還沒有提到流傳輸協議。我們最常見的有三種:
rtsp, hls, rtmp. Android系統的多媒體框架本身已經對除了rtmp以外的流媒體協議和視頻格式都已經有所支持,但是問題在於支持的程度根據硬件平台不同行為可能有些許不同。所以在繼續下去之前,我希望能夠保證這三種協議都能夠被我的demo所支持,因為rtmp協議的視頻流並不在少數。所以,我並不計划使用系統本身的媒體框架來做。我選用ijkplayer或者vlc來使用。
對比ijkplayer和vlc,兩個都是在ffmpeg基礎上進行開發的媒體框架,各自有各自的長處。我在測試時更加推薦ijkplayer,因為它的性能表現和軟硬解碼的切換的靈活性十分好,並且支持SurfaceView, TextureView可更換渲染視頻,並且可以選擇使用OpenGLES渲染視頻。ijkplayer解析和使用已有很多文章說明,其本質是SDL配合FFMPEG渲染解碼。但是昨天發生了一件以外情況,對於我想要快速原型的願望有所顧慮。ijkplayer在樂視2手機上報了一個(-10000,0)錯誤,官方issue中也有很多相同問題的人,但是並沒有解決這個問題。因此只好更換了VLC-android來構建這個demo。
老實說,我在Ubuntu下移植構建ffmpeg和vlc都遇到過很多麻煩,走過很多彎路。但是我希望能夠快速實現我的目的,所以我還是找到了別人提前編譯好的依賴包來使用,我只拿api來使用。當然我在使用vlc-android期間也走了一點彎路,被所謂的MediaPlayer-like API思維禁錮的我各種報錯運行不成功,結果我不撞南牆不回頭,索性繞開這個坑,找了使用范例來寫。
首先我建了一個android項目,並且在build.gradle文件當中加入已經編譯好的依賴。這個依賴來自於:
https://github.com/mrmaffen/vlc-android-sdk,根據上面的說明,加入
dependencies {
compile "de.mrmaffen:vlc-android-sdk:2.0.6"
}
readme當中依然提到了如果想自己構建,如何做如何做。自己構建?有空再說。
我們可以直接開始使用VLC庫的API了。
以下代碼我只寫出關鍵代碼,其余的多余代碼為了不干擾實現,不貼出來。
首先,我們要有一個SurfaceView表面來顯示渲染內容:
android:layout_width="match_parent"
android:layout_height="210dp" />
然后需要兩個按鈕
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="QTV1" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="QTV2"
android:visibility="visible" />
作為兩個頻道切換
實在不能再簡單了,然后上我們的Java代碼,在Activity中,我們需要這么使用:
//需要導入的包,不要用錯包的MediaPlayer類
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;
//在Activity中可以為按鈕增加事件
SurfaceView srfc;
LibVLC libVLC = null;
ArrayList options = new ArrayList<>();
libVLC = new LibVLC(getApplication(), options);
try {
if (mediaPlayer != null && mediaPlayer.isPlaying()) {
mediaPlayer.stop();
mediaPlayer.release();
mediaPlayer = null;
}
mediaPlayer = new MediaPlayer(libVLC);
String url = getString(R.string.http_video11_qtv_com_cn_qtv1_sd_manifest_m3u8);
//
mediaPlayer.getVLCVout().setVideoSurface(srfc.getHolder().getSurface(), srfc.getHolder());
//播放前還要調用這個方法
mediaPlayer.getVLCVout().attachViews();
Media media = new Media(libVLC, Uri.parse(url));
mediaPlayer.setMedia(media);
mediaPlayer.play();
} catch (Exception e) {
e.printStackTrace();
}
並且
@Override
protected void onPause() {
super.onPause();
if (mediaPlayer != null) {
mediaPlayer.pause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mediaPlayer != null) {
mediaPlayer.play();
}
}
然后就可以使用了