android 使用 IJKPlayer 播放視頻流的實(shí)現(xiàn)代碼
最近在做音視頻相關(guān)的內(nèi)容,這就無法避開視屏采集和播放的問題了,然后播放器使用的是 ijkplayer,這個(gè)東西使用 url 播放倒是沒啥問題,只是我們的方案是接收 flv 的視頻流進(jìn)行播放,這需要借助 IAndroidIO 這個(gè)接口,也可以用于播放本地文件。
實(shí)現(xiàn) IAndroidIO 接口
播放類的實(shí)現(xiàn)
class ReadByteIO private constructor(): IAndroidIO { companion object { private var instance: ReadByteIO? = null var URL_SUFFIX = "recv_data_online" @Synchronized fun getInstance(): ReadByteIO { // 單例 instance?.let { return it } instance = ReadByteIO() return instance!! } } private var TAG = ReadByteIO::class.java.simpleName private var flvData = LinkedBlockingDeque<Byte>() // 內(nèi)存隊(duì)列,用于緩存獲取到的流數(shù)據(jù),要實(shí)現(xiàn)追幀效果,只需要根據(jù)策略丟棄本地緩存的內(nèi)容即可 private fun takeFirstWithLen(len : Int): ByteArray { // 取 byte 數(shù)據(jù)用于界面渲染 var byteList = ByteArray(len) for (i in 0 until len) { byteList[i] = flvData.take() } return byteList } @Synchronized fun addLast(bytes: ByteArray): Boolean { var tmpList:List<Byte> = bytes.toList() Log.e(TAG, "tmpList size " + tmpList.size) return flvData.addAll(tmpList) } // 如果是播放本地文件,可在此處打開文件流,后續(xù)讀取文件流即可 override fun open(url: String?): Int { if (url == URL_SUFFIX) { return 1 // 打開播放流成功 } return -1 // 打開播放流失敗 } override fun read(buffer: ByteArray?, size: Int): Int { var tmpBytes = takeFirstWithLen(size) // 阻塞式讀取,沒有數(shù)據(jù)不渲染畫面 System.arraycopy(tmpBytes, 0, buffer, 0, size) return size } override fun seek(offset: Long, whence: Int): Long { return 0 } override fun close(): Int { return 0 } }
調(diào)用播放類
接下來,就看看如何調(diào)用播放實(shí)例了。注意:我們還是需要傳入一個(gè) url,只是這個(gè) url 是我們自定義的
public class RecordVideoActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { private String TAG = RecordVideoActivity.class.getSimpleName(); private IjkMediaPlayer player; private Surface surface; private TextureView playView; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_record_video); playView = findViewById(R.id.v_play); playView.setSurfaceTextureListener(this); } @Override protected void onDestroy() { super.onDestroy(); if (player != null) { player.stop(); } } @Override public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { if (surface != null) { this.surface = new Surface(surface); play(); // 存在 surface 實(shí)例再做播放 } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { } private void play() { player = new IjkMediaPlayer(); player.reset(); player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzemaxduration", 100); player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 25 * 1024); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1); player.setOption(IjkMediaPlayer.OPT_CATEGORY_CODEC, "threads", 1); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "sync-av-start", 0); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec",1); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1); player.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 1); player.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "ijkio,crypto,file,http,https,tcp,tls,udp"); // 屬性設(shè)置支持,轉(zhuǎn)入我們自定義的播放類 player.setSurface(this.surface); player.setAndroidIOCallback(ReadByteIO.Companion.getInstance()); Uri uri = Uri.parse("ijkio:androidio:" + ReadByteIO.Companion.getURL_SUFFIX()); // 設(shè)定我們自定義的 url try { player.setDataSource(uri.toString()); } catch (IOException e) { e.printStackTrace(); } player.prepareAsync(); player.start(); } }
到此這篇關(guān)于android 使用 IJKPlayer 播放視頻流的文章就介紹到這了,更多相關(guān)android 播放視頻流內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android實(shí)現(xiàn)學(xué)生管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)學(xué)生管理系統(tǒng)的相關(guān)代碼,供大家學(xué)習(xí)借鑒,感興趣的小伙伴們可以參考一下2016-03-03Android Scroll實(shí)現(xiàn)彈性滑動(dòng)_列表下拉彈性滑動(dòng)的示例代碼
下面小編就為大家分享一篇Android Scroll實(shí)現(xiàn)彈性滑動(dòng)_列表下拉彈性滑動(dòng)的示例代碼,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Android手機(jī)號(hào)碼輸入框(滿11位自動(dòng)跳到下個(gè)輸入框)實(shí)例代碼
這篇文章主要介紹了Android手機(jī)號(hào)碼輸入框(滿11位自動(dòng)跳到下個(gè)輸入框)實(shí)例代碼,需要的朋友可以參考下2017-10-10Android實(shí)現(xiàn)LED發(fā)光字效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)LED發(fā)光字效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03Android開發(fā)中WebView的簡單使用小結(jié)
WebView(網(wǎng)絡(luò)視圖)能加載顯示網(wǎng)頁,可以將其視為一個(gè)瀏覽器。它使用了WebKit渲染引擎加載顯示網(wǎng)頁。下面這篇文章給大家總結(jié)了Android中WebView的簡單使用,有需要的可以參考借鑒。2016-09-09Android實(shí)現(xiàn)CoverFlow效果控件的實(shí)例代碼
這篇文章主要介紹了Android實(shí)現(xiàn)CoverFlow效果控件的實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-05-05Android 8.0 讀取內(nèi)部和外部存儲(chǔ)以及外置SDcard的方法
今天小編就為大家分享一篇Android 8.0 讀取內(nèi)部和外部存儲(chǔ)以及外置SDcard的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-08-08Android使用FontMetrics對象計(jì)算位置坐標(biāo)
這篇文章主要為大家詳細(xì)介紹了Android使用FontMetrics對象計(jì)算位置坐標(biāo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12