1. 程式人生 > >快速整合一個視訊直播功能

快速整合一個視訊直播功能

前言

前段時間的工作安排,需要做一個視訊監控的功能,其實就是採用 m3u8 做一個直播。

確定需求後進行了一堆調研,最後在B站的 ijkplayer 與 Google 的 ExoPlayer 中做出了選擇,對於為啥選擇了 ExoPlayer ,後面會做具體分析,目前先留點懸念,目前根據選擇 ExoPlayer,從最初調研到整合成功打算做一個專題,分別從眾多框架中為何選擇了 ExoPlayer、硬解碼與軟解碼的區別和對比、自定義 ExoPlayer、整合中所遇到的坑、原始碼分析,作為開頭第一篇,目前只是一篇短暫的整合,並附上大量的註釋,具體不做太多分析。

專案相關地址

ExoPlayer 原始碼地址:

https://github.com/google/ExoPlayer

ExoPlayer api地址:http://google.github.io/ExoPlayer/doc/reference/

ExoPlayer 開發者指南:https://google.github.io/ExoPlayer/guide.html

優點和缺點

相比 Android 內建的 MediaPlayer,ExoPlayer 具有許多優於優勢:

  • 支援 Dynamic Adaptive Streaming over HTTP (DASH) 和SmoothStreaming進行動態自適應流,這兩種都不受 MediaPlayer 支援,還支援許多其它格式。有關詳細資訊,請參考開發者指南。
  • 支援高階 HLS 功能,如正確處理 #EXT-X-DISCONTINUITY的標籤。
  • 能夠無縫融合,連線和迴圈媒體資源。
  • 自定義和擴充套件播放器以適應您的用例的能力。 ExoPlayer專門設計了這一點,並允許許多元件被替換為自定義實現。
  • 輕鬆更新播放器與您的應用程式。 因為 ExoPlayer 是您的應用程式apk中包含的庫,所以您可以控制使用哪個版本,你可以輕鬆地將其更新為常規應用程式更新的一部分。
  • 裝置通用性更強。
  • 支援在Android 4.4(API級別19)以上的Widevine通用加密。

需要注意的是,也有一些缺點,這一點很重要:

  • ExoPlayer的標準音頻和視訊部件依賴於Android的 MediaCodecAPI,MediaCodecAPI 在搭載Android 4.1(API級別16)釋出。因此,他們不會在較早版本的 Android 的工作。Widevine 的通用加密可以在 Android 4.4(API級別19)和更高。

附上原文

Pros and cons

ExoPlayer has a number of advantages over Android’s built in MediaPlayer:
  • Support for Dynamic Adaptive Streaming over HTTP (DASH) and SmoothStreaming, neither of which are supported by MediaPlayer. Many other formats are also supported. See the Supported formats page for details.
  • Support for advanced HLS features, such as correct handling of#EXT-X-DISCONTINUITY tags.
  • The ability to seamlessly merge, concatenate and loop media.
  • The ability to update the player along with your application. Because ExoPlayer is a library that you include in your application apk, you have control over which version you use and you can easily update to a newer version as part of a regular application update.
  • Fewer device specific issues and less variation in behavior across different devices and versions of Android.
  • Support for Widevine common encryption on Android 4.4 (API level 19) and higher.
  • The ability to customize and extend the player to suit your use case. ExoPlayer is designed specifically with this in mind, and allows many components to be replaced with custom implementations.
  • The ability to quickly integrate with a number of additional libraries using official extensions. For example the IMA extension makes it easy to monetize your content using the Interactive Media Ads SDK.

It’s important to note that there are also some disadvantages:

  • ExoPlayer’s standard audio and video components rely on Android’sMediaCodec API, which was released in Android 4.1 (API level 16). Hence they do not work on earlier versions of Android. Widevine common encryption is available on Android 4.4 (API level 19) and higher.

**

支援的格式

**

ExoPlayer支援播放DASH,SmoothStreaming和HLS自適應流,以及如MP4,M4A,FMP4,WebM,MKV,MP3,Ogg,WAV,MPEG-TS,MPEG-PS,FLV和ADTS (AAC)。

整合

先上程式碼在做分析,首先匯入ExoPlayer需要的包:

compile 'com.google.android.exoplayer:exoplayer:r2.4.1'

xml檔案如下:

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/player_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true" />

是的,就這麼短,Google考慮得很全面,提供了exoplayer2-ui的包,給開發者省去了很多事情。

核心程式碼如下:

/**
 * 播放器頁面
 *
 * Created by Zero on 2017/9/16.
 */
public class ExoPlayerActivity extends AppCompatActivity {


    @BindView(R.id.player_view)
    SimpleExoPlayerView playerView;
    private SimpleExoPlayer player;

    /**
     * 網上找的一個m3u8地址
     */
    private static  final String url = "http://devimages.apple.com/iphone/samples/bipbop/gear1/prog_index.m3u8";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_exo_player);
        ButterKnife.bind(this);
        initPlayer();
    }
    private void initPlayer(){
        /**
         * Provides estimates of the currently available bandwidth.
         */
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        /**
         * TrackSelector用來選擇磁軌,由MediaSource所提供,並會被任意的可用的Renderers所使用,當播放器被建立時,TrackSelector會被注入.
         */
        TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);

        /**
         * SimpleExoPlayer單例
         */
        player = ExoPlayerFactory.newSimpleInstance(this, trackSelector);
        /**
         * 設定使用者控制,其實就是螢幕上的功能按鈕,預設顯示,false則不顯示,設定false後可自定義
         *
         * 原始碼中:Sets whether the playback controls can be shown. If set to {@code false} the playback controls
         * are never visible and are disconnected from the player.
         *
         * @param useController Whether the playback controls can be shown.
         */
        playerView.setUseController(true);
        playerView.requestFocus();

        /**
         * 將播放器新增到檢視
         */
        playerView.setPlayer(player);

        Uri uri =Uri.parse(url);
        /**
         * Estimates bandwidth by listening to data transfers
         */
        DefaultBandwidthMeter bandwidthMeterA = new DefaultBandwidthMeter();
        /**
         * PS:
         * DefaultUriDataSource - 用於播放本地和網路媒體;
         * AssetDataSource - 用於播放應用中assets資料夾下的媒體。
         */
        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "ExoPlayerDemo"), bandwidthMeterA);
        /**
         * ExoPlayer每幀是通過MediaSource展示的,播放的每一幀必須先建立對應的MediaSource
         *
         * MediaSource 定義了載入、播放媒體,並且可以讀取已經載入的媒體,使用ExoPlayer.prepare 可在播放開始傳入MediaSource
         */
        MediaSource videoSource = new HlsMediaSource(uri, dataSourceFactory, 1, null, null);
        /**
         * 無縫迴圈播放視訊
         */
        LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);

        player.prepare(loopingSource);
        /**
         * 開始播放
         */
        player.setPlayWhenReady(true);
    }
}

就這麼簡單?是的,現在一個播放器就這麼搞定了,親測可以,來張圖證明下:
這裡寫圖片描述

好了,就這麼搞定一個 m3u8 格式的視訊直播,上述也說了,支援的格式很多,可根據不同的格式做出相應的處理,主要是對MediaSource(DashMediaSource),SmoothStreaming(SsMediaSource),HLS(HlsMediaSource)和常規的媒體檔案(ExtractorMediaSource)做出相應的處理,在此不做多餘的贅述,敬請期待,^_^。

友情推薦:

這裡寫圖片描述