12/08/2018, 13:31

Giới thiệu về ExoPlayer trong Android

Hướng dẫn Play video và audio là một hoạt động phổ biến trên các thiết bị Android. Android framwork cung cấp MediaPlayer như một giải pháp nhanh chóng đơn giản và tiện ích nhất để thức hiện việc trên. Nó cũng cung cấp các media API cấp thấp như MediaCodec, AudioTrack và MediaDrm, cái mà có thể ...

Hướng dẫn

Play video và audio là một hoạt động phổ biến trên các thiết bị Android. Android framwork cung cấp MediaPlayer như một giải pháp nhanh chóng đơn giản và tiện ích nhất để thức hiện việc trên. Nó cũng cung cấp các media API cấp thấp như MediaCodec, AudioTrack và MediaDrm, cái mà có thể được sử dụng để xây dựng media tuỳ chỉnh theo mục đích người chơi.

ExoPlayer là một thư viện mã nguồn mở, nằm ở tầng ứng dụng, được xây dựng phía trên của các media APIs cấp thấp của android.

Thư viện ExoPlayer - https://github.com/google/ExoPlayer/tree/master/library

Ứng dụng Demo - Phần này của dự án cho biết cách sử dụng thư viện ExoPlayer https://github.com/google/ExoPlayer/tree/master/demo

Hướng dẫn này mô tả các thư viện ExoPlayer và việc sử dụng nó. Nó liên quan đến code trong app demo được đưa ra ở trên. Hướng dẫn để biết được những ưu và khuyết điểm của việc sử dụng ExoPlayer. Nó chỉ ra làm thế nào để sử dụng ExoPlayer play DASH, SmoothStreaming và HLS adaptive streams, cũng như các định dạng như FMP4, MP4, M4A, MKV, WebM, MP3, AAC, MPEG-TS, MPEG-PS, OGG, FLV và WAV. Nó cũng bàn về ExoPlayer Events, messages, tùy biến và hỗ trợ DRM.

Ưu điểm

Hỗ trợ Dynamic Adaptive Streaming over HTTP (DASH) và SmoothStreaming, cái mà không được hỗ trợ trong MediaPlayer (nó cũng hỗ trợ HTTP Live Streaming (HLS), FMP4, MP4, M4A, MKV, WebM, MP3, AAC, MPEG-TS, MPEG-PS, OGG, FLV và WAV).

Hỗ trợ các tính năng nâng cấp của HLS, như là xử lý đúng của thẻ #EXT-X-DISCONTINUITY.

Khả năng tùy chỉnh và mở rộng cao. ExoPlayer được thiết kế đặc biệt, cho phép nhiều thành phần được thay thế và tuỳ chỉnh khi thực thi.

Dễ dàng cập nhật.

Các issue liên quan đến device là ít hơn.

Nhược điểm

ExoPlayer được xây dựng dựa trên các component MediaCodec API của Android chuẩn về audio và video, cái mà được phát hành trong Android 4.1 (API level 16). Do đó nó không làm việc trên các version thấp hơn 4.1 của Android.

Tổng quan về thư viện

Phần core của thư viện ExoPlayer là class ExoPlayer. Class này duy trì, cung cấp toàn bộ trạng thái của player, nhưng có một vài giả định về tính chất của các media đang được play, chẳng hạn như làm thế nào để media lấy được data, làm thế nào để buffered hay định dạng của nó. Bạn làm chức năng này thông qua method prepare của ExoPlayer dựa vào đối tượng TrackRenderer.

ExoPlayer cung cấp renderer mặc định audio và video, cái mà sử dụng các class MediaCodec và AudioTrack trong Android framework. Cả hai yêu cầu đưa vào một đối tượng SampleSource, từ đó có được media sample cho playback.

Injection của các component là một theme cho cả thư viện ExoPlayer. Hình bên dưới chỉ ra các đối tượng model cấp cao cho một ExoPlayer được cấu hình để play MP4 streams. Renderer mặc định audio và video được đưa vào ExoPlayer. Một instance của một class được gọi là ExtractorSampleSource được đưa vào trong renderer để cung cấp cho media sample. Trường hợp DataSource và Extractor được đưa vào ExtractorSampleSource và đẩy vào trong renderer để cung cấp cho media sample. Trong trường hợp này DefaultUriDataSource và Mp4Extractor được sử dụng để play MP4 streams tải từ URI. Ba thành phần quan trọng nhất trong model này là: TrackRenderer, SampleSource và DataSource.standard-model.png

TrackRenderer

Một TrackRenderer play mỗi loại riêng biệt của media, chẳng hạn như video, audio hoặc text. Class ExoPlayer gọi phương thức trên TrackRenderer của nó từ một thread độc lập. Thư viện ExoPlayer cung cấp MediaCodecVideoTrackRenderer là cái mặc định rendering video và MediaCodecAudioTrackRenderer cho audio. Cả hai triển khai việc sử dụng các lớp MediaCodec của Android để giải mã các media sample. Chúng có thể xử lý tất cả các định dạng audio và video được hỗ trợ trên thiết bị Android. Thư viện ExoPlayer cũng cung cấp việc triển khai rendering văn bản, gọi là TextTrackRenderer.

Đoạn câu lệnh trong ảnh bên dưới là một ví dụ về các bước chính cần thiết cho ExoPlayer để play video và audio bằng cách sử dụng trình thực thi chuẩn TrackRenderer. Screenshot from 2016-05-30 16:12:44.png

SampleSource

Việc triển khai TrackRenderer chuẩn được cung cấp bởi thư viện yêu cầu SampleSource instances được đưa vào các constructor của chúng. Một đối tượng SampleSource cung cấp thông tin định dạng và media sample để được renderer. Thư viện ExoPlayer cung cấp một số cách triển khai SampleSource cụ thể đối với trường hợp sử dụng khác nhau:

ExtractorSampleSource - Đối với các định dạng như FMP4, MP4, M4A, MKV, WebM, MP3, AAC, MPEG-TS, MPEG-PS, OGG, FLV và WAV.

ChunkSampleSource - Đối với DASH và phát lại SmoothStreaming.

HlsSampleSource - Đối với HLS playbacks.

DataSource

Việc triển khai SampleSource chuẩn được cung cấp bởi thư viện sử dụng DataSource instances cho việc tải media data. Việc triển khai này có thể được tìm thấy trong các gói upstream. Cái phổ biến nhất được sử dụng để triển khai là:

  • DefaultUriDataSource - Play media local hoặc thông qua internet.

  • AssetDataSource - Play media được lưu trữ trong thư mục assets của ứng dụng.

Media playbacks truyền thống

Thư viện ExoPlayer cung cấp ExtractorSampleSource để chơi các định dạng media truyền thống, bao gồm cả FMP4, MP4, M4A, MKV, WebM, MP3, AAC, MPEG-TS, MPEG-PS, OGG, FLV và WAV. Các mã sau đây chỉ ra cách TrackRenderer instances được khởi tạo: Xem hình bên dưới: Screenshot from 2016-05-30 16:20:46.png

ExtractorSampleSource sẽ tự động tải đúng Extractor cho media đã được play. Nếu không có Extractor cho media mà bạn muốn play, nó có thể thực hiện và chèn vào cái của riêng bạn.

ExoPlayer demo app cung cấp đầy đủ cách triển khai các mã này trong ExtractorRendererBuilder .Class PlayerActivity sử dụng nó để play một số video có sẵn trong ứng dụng demo.

Adaptive media playbacks

ExoPlayer hỗ trợ adaptive streaming, cho phép chất lượng của media data phải được điều chỉnh trong quá trình playback dựa trên các điều kiện mạng. DASH, SmoothStreaming và HLS là những ví dụ của công nghệ adaptive streaming. Trong cả ba, media được tải trong khối nhỏ (thường là trong thời hạn 2-10 giây). Mỗi lần một đoạn của media được yêu cầu, client lựa chọn từ một số định dạng có thể. Ví dụ, một client có thể chọn một định dạng chất lượng cao, nếu điều kiện mạng tốt, hoặc định dạng chất lượng thấp, nếu điều kiện mạng là xấu. Trong cả hai kỹ thuật, video và âm thanh được truyền riêng.

DASH và SmoothStreaming

ExoPlayer hỗ trợ DASH và SmoothStreaming playbacks tương thích thông qua sử dụng các ChunkSampleSource, cái mà tải media data mà từ đó các sample riêng biệt có thể lấy được. Mỗi ChunkSampleSource yêu cầu đưa vào một đối tượng ChunkSource thông qua constructor của nó, nhiệm vụ của nó là cung cấp khối media data từ đó có thể load và đọc samples. Class DashChunkSource cung cấp DASH playbacks bằng cách sử dụng định dạng chứa FMP4 và WebM. Class SmoothStreamingChunkSource cung cấp SmoothStreaming playbacks bằng cách sử dụng định dạng container FMP4. dash-model.png

Cả hai tiêu chuẩn ChunkSource hiện thực đòi hỏi một FormatEvaluator và một DataSource được đưa qua các hàm khởi tạo. Các FormatEvaluator đối tượng chọn từ các định dạng có sẵn trước mỗi đoạn được tải, và DataSource cung cấp các method để thực hiện việc tải dữ liệu. Cuối cùng, ChunkSampleSource yêu cầu một đối tượng LoadControl để điều khiển quyền buffer các section.

Mô hình object model cho một ExoPlayer được cấu hình cho DASH adaptive playbacks được thể hiện trong hình bên dưới. Chất lượng video được thay đổi trong thời gian chạy bằng cách sử dụng adaptive của FormatEvaluator, trong khi âm thanh được play ở một mức độ chất lượng cố định

Đoạn câu lệnh hình dưới cho biết làm thế nào để video và audio renderer được khởi tạo. Screenshot from 2016-05-30 16:27:51.png

Trong mã này, manifestFetcher là một đối tượng phụ trách việc tải các DASH manifest như là định nghĩa media. Các videoAdaptationSetIndex và audioAdaptationSetIndex chỉ số biến thành phần ban đầu được đưa vào với video và audio tương ứng.

App demo ExoPlayer đưa ra việc triển khai đầy đủ các mã này trong DashRendererBuilder. Class PlayerActivity sử dụng builder này để khởi tạo renderer cho việc play DASH các video mẫu trong demo app. Một ví dụ SmoothStreaming tương đương, xem class SmoothStreamingRendererBuilder trong ứng dụng demo.

HLS

ExoPlayer hỗ trợ HLS adaptive playback thông qua việc sử dụng các HlsSampleSource, cái mà tải khối dữ liệu media mà từ đó mà samples có thể trích xuất được. Một HlsSampleSource yêu cầu một HlsChunkSource được đưa vào qua các constructor của nó, phụ trách cung cấp đoạn media để tải và đọc samples. Một HlsChunkSource yêu cầu một DataSource được đưa vào qua constructor của nó, thông qua cái mà media data có thể được load.

hls-model.png

Một model object thông thường ExoPlayer được cấu hình cho HLS adaptive playback được chỉ ra trong hình bên dưới. Chất lượng video được thay đổi trong thời gian chạy bằng cách sử dụng adaptive của 'FormatEvaluator', trong khi audio được mở ở một mức độ chất lượng nhất định.

Ví dụ hình dưới cho biết làm thế nào để video và audio renderers được khởi tạo

Screenshot from 2016-05-30 16:34:57.png

App demo ExoPlayer cung cấp việc triển khai đầy đủ các mã này trong HlsRendererBuilder . Class PlayerActivity sử dụng builder này để khởi tạo các renderer cho play HLS các video mẫu trong demo app.

Player events

Trong suốt quá trình playback, ứng dụng của bạn có thể lắng nghe sự kiện được tạo bởi ExoPlayer đồng thời chỉ ra các trạng thái chung của player. Những sự kiện này có ích giúp cho việc cập nhật vào giao diện người dùng của ứng dụng như điều khiển playback. Nhiều thành phần ExoPlayer cũng report dựa vào các component riêng của chúng với các event level thấp, nó khá hữu ích cho việc theo dõi performance trên màn hình.

  • Events cấp cao

    • ExoPlayer cho phép các trường hợp của ExoPlayer.Listener được thêm vào và lấy ra sử dụng bằng method addListener() và removeListener(). Một listener được đăng ký được thông báo về những thay đổi về trạng thái playback, cũng như khi có lỗi xảy ra mà playback là nguyên nhân dẫn đến lỗi. Để biết thêm thông tin về các trạng thái playback hợp lệ và quá trình chuyển đổi có thể giữa chúng, xem mã nguồn ExoPlayer.
    • Các nhà phát triển những người mà thực hiện việc điều khiển tùy chỉnh playback nên đăng ký một listener và sử dụng nó để cập nhật các điều khiển của họ như thay đổi trạng thái của player. Một ứng dụng cũng nên hiển thị ra lỗi tương ứng cho người dùng nếu playback fails.
  • Events cấp thấp

    • Bên cạnh High level listeners, rất nhiều các thành phần riêng biệt được cung cấp bởi thư viện ExoPlayer cho phép lắng nghe sự kiện riêng của chúng. Ví dụ, MediaCodecVideoTrackRenderer có các hàm khởi tạo mà có một là MediaCodecVideoTrackRenderer.EventListener . Trong app demo ExoPlayer, DemoPlayer đóng vai trò là bộ lắng nghe nhiều thành phần riêng biệt, chuyển tiếp các sự kiện để PlayerActivity . Cách tiếp cận này cho phép PlayerActivity để điều chỉnh kích thước của surface để có chiều cao chính xác và tỷ lệ chiều rộng cho các video đang được phát (Xem câu lệnh hình bên dưới)
    • Class RendererBuilder trong ứng dụng demo ExoPlayer thì mỗi DemoPlayer như một listener mỗi component.

    Screenshot from 2016-05-30 16:39:04.png

Gửi tin nhắn đến các component

Một số thành phần ExoPlayer phép thay đổi trong cấu hình trong khi play. Theo quy ước, bạn thực hiện những thay đổi này bằng cách thông qua các messages không đồng bộ từ các thành phần của ExoPlayer.

Việc sử dụng phổ biến nhất của message thông qua surface đến MediaCodecVideoTrackRenderer:

  • player.sendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE , surface);

Lưu ý rằng để surface được xóa thì cần phải gọi SurfaceHolder.Callback.surfaceDestroyed(), sau đó bạn phải gửi thông điệp này bằng cách sử dụng biến thể ngăn chặn các sendMessage():

  • player.blockingSendMessage(videoRenderer, MediaCodecVideoTrackRenderer.MSG_SET_SURFACE, null);

Bạn phải sử dụng một thư chặn vì hợp đồng của surfaceDestroyed() yêu cầu các ứng dụng không cố gắng để truy cập vào surface khi đã được return.

Tùy biến

Một trong những lợi ích chính của ExoPlayer trên Android của MediaPlayer là khả năng tùy biến và mở rộng các player để phù hợp hơn với các trường hợp sử dụng của nhà phát triển. Thư viện ExoPlayer được thiết kế đặc biệt, xác định một số class abtract và interface mà cho phép các nhà phát triển ứng dụng dễ dàng thay thế cài đặt các mặc định được cung cấp bởi thư viện. Dưới đây là một số trường hợp sử dụng để xây dựng các thành phần tùy chỉnh:

  • TrackRenderer: Bạn có thể muốn thực hiện một tùy chỉnh TrackRenderer để xử lý các loại media khác kiểu audio và video thông thường. Các class TextTrackRenderer trong thư viện ExoPlayer là một ví dụ về làm thế nào để thực hiện một tùy chỉnh renderer.

  • Extractor: Nếu bạn cần hỗ trợ một định dạng hiện không được hỗ trợ bởi thư viện ExoPlayer, xem xét thực hiện một tùy chỉnh class Extractor, mà sau đó có thể được sử dụng cùng với ExtractorSampleSource play media của loại đó.

  • SampleSource: Thực hiện một tùy chỉnh class SampleSource thích hợp nếu bạn muốn media samples renderer một cách khác.

  • FormatEvaluator: Đối với DASH và SmoothStreaming playback, thư viện ExoPlayer cung cấp FormatEvaluator.AdaptiveEvaluator giống như một tài liệu tham khảo cho việc thực hiện một ví dụ đơn giản mà bạn chuyển đổi giữa các định dạng chất lượng khác nhau dựa trên băng thông có sẵn. Phát triển ứng dụng được khuyến khích để phát triển tương thích với việc thực hiện FormatEvaluator phù hợp với nhu cầu cụ thể.

  • DataSource: Gói upstream của ExoPlayer đã có chứa một số DataSource để triển khai với các trường hợp sử dụng khác nhau. Bạn có thể muốn thực hiện lớp DataSource của bạn để tải dữ liệu theo cách khác, chẳng hạn như tùy chỉnh giao thức, dùng để tùy chỉnh một ngăn sắp HTTP, ...

Hướng dẫn tuỳ biến

Nếu một thành phần tùy chỉnh cần thông báo sự kiện trở lại ứng dụng, chúng tôi khuyên bạn nên sử dụng các model có sẵn trong các thành phần của ExoPlayer.

Chúng khuyến nghị tùy chỉnh các thành phần sử dụng các model tương tự như các thành phần có sẵn trong ExoPlayer để cho phép cấu hình lại ứng dụng trong suốt quá trình playback, như mô tả trong Sending messages to components. Để làm điều này, bạn nên thực hiện một ExoPlayerComponent và nhận được những thay đổi cấu hình trong method handleMessage(). Ứng dụng của bạn nên thay đổi cấu hình thông qua việc gọi method sendMessage() và blockingSendMessage() của ExoPlayer.

Quản lý bản quyền kỹ thuật số

Trên Android 4.3 (API ở level 18) và cao hơn, hỗ trợ ExoPlayer Digital Rights Managment (DRM) playback. Để play được nội dung DRM với ExoPlayer, ứng dụng của bạn phải đưa một DrmSessionManager vào hàm khởi tạo MediaCodecVideoTrackRenderer và MediaCodecAudioTrackRenderer. Một đối tượng DrmSessionManager phụ trách cung cấp các đối tượng MediaCrypto cần thiết để giải mã, cũng như đảm bảo rằng các khóa giải mã khả dụng cho các mô-đun DRM được sử dụng.

Thư viện ExoPlayer cung cấp một thực hiện mặc định của DrmSessionManager, gọi StreamingDrmSessionManager, trong đó sử dụng MediaDrm. Session manager hỗ trợ bất kỳ chương trình DRM cái mà một DRM modular thành phần có sẵn trên thiết bị. Tất cả các thiết bị Android được yêu cầu để hỗ trợ Widevine modular DRM (với L3 security, mặc dù nhiều thiết bị cũng hỗ trợ L1). Một số thiết bị có thể hỗ trợ các chương trình bổ sung như PlayReady.

Class StreamingDrmSessionManager yêu cầu một MediaDrmCallback được đưa vào constructor của nó, cái mà phụ trách thực hiện việc cung cấp và yêu cầu quan trọng. Bạn nên implement interface này để thực hiện các yêu cầu mạng đến máy chủ cấp phép của bạn và có được các khóa cần thiết. class WidevineTestMediaDrmCallback trong ExoPlayer demo app gửi yêu cầu đến một Widevine kiểm tra server.

     Nguồn tham khảo: http://google.github.io/ExoPlayer/guide.html
0