ExoPlayer媒体资源相关类

之前介绍过 ExoPlayer 的缓存控制类LoadControl,它决定了ExoPlayer的缓存策略,该缓存多长时间的视频,缓存过程中什么时间该播放等。这篇文章介绍ExoPlayer 媒体资源相关的其它类,比如音视频资源从网络上下载后以什么样的格式存储的,存在哪里等。为什么要了解这些呢?当自定义ExoPlayer缓存时最好对音视频资源的表示形式,播放单元等有系统和全面的了解,这样才能在ExoPlayer默认设置的基础上更改起来得心应手。

为了防止自己对原文理解不准确,本文保留了源码中的英文注释,在此基础上添加自己的理解。

TimeLine

A flexible representation of the structure of media. A timeline is able to represent the structure of a wide variety of media, from simple cases like a single media file through to complex compositions of media such as playlists and streams with inserted ads. Instances are immutable. For cases where media is changing dynamically (e.g. live streams), a timeline provides a snapshot of the current state.

时间线(TimeLine)是媒体结构的灵活表示,从简单的案例如单个媒体文件到复杂的如媒体文件的组合和插入广告的流,时间线的实例是不可变的,对于媒体文件动态变化的情况,例如直播流,时间线提供当前状态的快照。

A timeline consists of related Periods and Windows.

时间线(TimeLine)由相关的句点(Period)和窗口(Window)组成。

A period defines a single logical piece of media, for example a media file. It may also define groups of ads inserted into the media, along with information about whether those ads have been loaded and played.

句点定义单个媒体片段的逻辑,例如一个媒体文件。它还可以定义插入媒体文件的一组广告,以及有关这些广告是否已加载和播放的信息。(如下图所示)
period

A window spans one or more periods, defining the region within those periods that’s currently available for playback along with additional information such as whether seeking is supported within the window. Each window defines a default position, which is the position from which playback will start when the player starts playing the window.

一个窗口跨越一个或多个句点,定义当前时段内的用于播放的句点和其它相关信息,例如在窗口内是否支持搜索。每个窗口定义一个默认位置作为播放的起始位置。(如下图所示)

window

The following examples illustrate timelines for various use cases:

以下列举几种不同情况下的时间线:

Single media file or on-demand stream(单个媒体文件或者点播流)

A timeline for a single media file or on-demand stream consists of a single period and window. The window spans the whole period, indicating that all parts of the media are available for playback. The window’s default position is typically at the start of the period (indicated by the black dot in the figure above).

单个媒体文件或者按需流的时间线由单一的句点和窗口组成,窗口跨越整个句点,表示媒体的所有部分都可以播放。 窗口的默认位置通常在句点的开头(由下图中的黑点表示)

timeline-single-file

Playlist of media files or on-demand streams(媒体文件或点播流的播放列表)

A timeline for a playlist of media files or on-demand streams consists of multiple periods, each with its own window. Each window spans the whole of the corresponding period, and typically has a default position at the start of the period. The properties of the periods and windows (e.g. their durations and whether the window is seekable) will often only become known when the player starts buffering the corresponding file or stream.

媒体文件或点播流的播放列表的时间线由多个句点组成,每个句点都有自己的窗口。 每个窗口跨越整个相应的句点,并且通常在句点的开始处有默认位置。 句点和窗口的属性(例如,它们的持续时间以及窗口是否可搜索)通常仅在播放器开始缓冲相应的文件或流时才知道。(如下图所示)

timeline-playlist

Live stream with limited availability(有限可用的直播流)

A timeline for a live stream consists of a period whose duration is unknown, since it’s continually extending as more content is broadcast. If content only remains available for a limited period of time then the window may start at a non-zero position, defining the region of content that can still be played. The window will have {@link Window#isDynamic} set to true if the stream is still live. Its default position is typically near to the live edge (indicated by the black dot in the figure above).

实时流的时间线由持续时间未知的句点组成,因为随着更多内容的广播,它会不断扩展。 如果内容仅在有限的时间段内保持可用,则窗口可以从非零位置开始,定义可以播放的内容区域。 如果流仍处于活动状态,则窗口将Window.isDynamic设置为true。 其默认位置通常靠近实时流的边缘(由下图中的黑点表示)。

timeline-live-limited

Live stream with indefinite availability(无限期可用的直播流)

A timeline for a live stream with indefinite availability is similar to the Live stream with limited availability case, except that the window starts at the beginning of the period to indicate that all of the previously broadcast content can still be played.

无限可用性的直播流的时间线类似于有限可用性的直播流情况,除了窗口在该句点的起始处开始以表明所有先前广播的内容仍然可以播放。(下图所示)

timeline-live-indefinite

Live stream with multiple periods(多个句点的直播流)

This case arises when a live stream is explicitly divided into separate periods, for example at content boundaries. This case is similar to the Live stream with limited availability case, except that the window may span more than one period. Multiple periods are also possible in the indefinite availability case.

这种情况出现在当直播流被明确划分为单独的句点时,例如在内容边界处。它类似于有限可用性的直播流情况,但窗口可能跨越多个句点。 无限期可用的直播流也可以有多个句点。

timeline-live-multi-period

On-demand stream followed by live stream(点播流然后是直播流)

This case is the concatenation of the Single media file or on-demand stream and Live stream with multiple periods cases. When playback of the on-demand stream ends, playback of the live stream will start from its default position near the live edge.

这种情况是’单个媒体文件或者点播流’ 与 ‘多个句点的直播流的拼接,当点播流结束时,直播流会从其有效边缘附近的默认位置开始播放。

timeline-advanced

On-demand stream with mid-roll ads(带有插播广告的点播流)

This case includes mid-roll ad groups, which are defined as part of the timeline’s single period. The period can be queried for information about the ad groups and the ads they contain.

这种情况包含插播广告组,这些广告组被定义为时间线上单个句点的一部分。通过该句点可以查询到广告组及其包含的广告信息。

timeline-single-file-midrolls

MediaPeriod

Loads media corresponding to a Timeline.Period, and allows that media to be read. All methods are called on the player’s internal playback thread, as described in the ExoPlayer Javadoc.

加载与时间线中一个片段对应的媒体,并允许读取该媒体。 所有方法在播放器的内部播放线程上调用。
ExoPlayer库提供了一些不同流媒体协议对应的MediaPeriod实现类,如HlsMediaPeriod加载hls数据流,DashMediaPeriod加载Dash数据流。

MediaPeriodQueue

Holds a queue of media periods, from the currently playing media period at the front to the loading media period at the end of the queue, with methods for controlling loading and updating the queue. Also has a reference to the media period currently being read.

MediaPeriodQueue是持有媒体片段的队列,包括队列前段的当前正在播放的媒体片段和队列后端的正在加载的媒体片段,MediaPeriodQueue包含了控制加载和更新队列的方法。并且有当前正在读的媒体片段的引用。

MediaSource

Defines and provides media to be played by an ExoPlayer. A MediaSource has two main responsibilities:

To provide the player with a Timeline defining the structure of its media, and to provide a new timeline whenever the structure of the media changes. The MediaSource provides these timelines by calling SourceInfoRefreshListener.onSourceInfoRefreshed() on the SourceInfoRefreshListeners passed to prepareSource(ExoPlayer,boolean, SourceInfoRefreshListener, TransferListener)

To provide MediaPeriod instances for the periods in its timeline. MediaPeriods are obtained by calling createPeriod(MediaPeriodId, Allocator, long), and provide a way for the player to load and read the media.

All methods are called on the player’s internal playback thread, as described in the ExoPlayer Javadoc. They should not be called directly from application code.

Instances can be re-used, but only for one ExoPlayer instance simultaneously.

MediaSource定义和提供了播放器需要的媒体资源。一个MediaSource主要有两个职责:

给播放器提供定义媒体结构的时间线,并且当媒体资源变化时提供新的时间线,MediaSource通过调用SourceInfoRefreshListener.onSourceInfoRefreshed() 提供这些时间线,SourceInfoRefreshListener作为参数传递给函数prepareSource(ExoPlayer,boolean, SourceInfoRefreshListener, TransferListener) 。

提供时间线中的MediaPeriod实例,MediaPeriod通过调用函数createPeriod(MediaPeriodId, Allocator, long)获得,并为播放器提供加载和读取媒体资源的方式。

所有的方法都在播放器内部线程中调用,不应该直接在应用程序代码中调用他们。

MediaSource的实例可以重用,但是仅限于同一个ExoPlayer实例。

MediaSource定义要播放的媒体,加载媒体,以及从中读取加载的媒体。 MediaSource开始播放时通过prepare(MediaSource)注入播放器。 ExoPlayer库提供了一些MediaSource的实现类,包括常规媒体文件ExtractorMediaSource,以及DASH(DashMediaSource),SmoothStreaming(SsMediaSource)和HLS(HlsMediaSource)的默认实现,它们用于加载单个媒体资源,SingleSampleMediaSource最常用于加载字幕文件。
除此之外还提供了利用单个媒体资源构建更加复杂媒体资源的类的如MergingMediaSource,ConcatenatingMediaSource,LoopingMediaSource和ClippingMediaSource。

MediaChunk

MediaChunk is an abstract base class for Chunks that contain media samples.

Chunk is an abstract base class for Loadable implementations that load chunks of data required for the playback of streams.

Chunk是实现了借口Loadable的抽象基类,加载播放流所需的数据块。

MediaChunk是包含媒体样本的Chunks的抽象基类。

ExoPlayer库提供的有MediaChunk的实现类如HlsMediaChunk。

DataSource

DataSource is a component from which streams of data can be read.

DefaultDataSource is a DataSource that supports multiple URI schemes. The supported schemes are:

file: For fetching data from a local file (e.g. file:///path/to/media/media.mp4, or just < /path/to/media/media.mp4 > because the implementation assumes that a URI without a scheme is a local file URI).

asset: For fetching data from an asset in the application’s apk (e.g. asset:///media.mp4).

rawresource: For fetching data from a raw resource in the application’s apk (e.g. rawresource:///resourceId, where rawResourceId is the integer identifier of the raw resource).

content: For fetching data from a content URI (e.g. content://authority/path/123).

rtmp: For fetching data over RTMP. Only supported if the project using ExoPlayer has an explicit dependency on ExoPlayer’s RTMP extension.

data: For parsing data inlined in the URI as defined in RFC 2397.

http(s): For fetching data over HTTP and HTTPS (e.g. https://www.something.com/media.mp4), if constructed using DefaultDataSource(Context, TransferListener, String, boolean), or any other schemes supported by a base data source if constructed using DefaultDataSource(Context,TransferListener,DataSource).

DataSource 是可以从中读取数据流的组件

DefaultDataSource是支持多种URI协议的DataSource,支持的协议有:

file:从本地文件中获取数据(例如file:///path/to/media/media.mp4,或者仅仅是< /path/to/media/media.mp4 > 因为实现假定没有协议的URI是本地文件URI)

asset:从应用程序的apk中的资产文件中获取数据(例如 asset:///media.mp4

rawresource:从应用程序的apk中的原始资源获取数据(例如 rawresource:///resourceId, 其中rawResourceId是原始资源的整数标识符)

content:从content URI获取数据(例如 content://authority/path/123

rtmp:使用RTMP协议获取数据,仅适用于项目中添加了RTMP扩展插件作为依赖的情况

data:用于解析 RFC 2397中定义的URI内连数据

http(s):用于通过HTTP和HTTPS协议获取数据(例如https://www.something.com/media.mp4)

Allocation

媒体资源字节数组的分配

Allocator

媒体资源字节数组的分配来源,ExoPlayer提供了Allocator的默认实现DefaultAllocator。