网站后台管理系统使用方法,以网站内容建设和运维为主,最快做网站的语言,肥东网站建设系列文章目录
ExoPlayer架构详解与源码分析#xff08;1#xff09;——前言 ExoPlayer架构详解与源码分析#xff08;2#xff09;——Player ExoPlayer架构详解与源码分析#xff08;3#xff09;——Timeline ExoPlayer架构详解与源码分析#xff08;4#xff09;—…系列文章目录
ExoPlayer架构详解与源码分析1——前言 ExoPlayer架构详解与源码分析2——Player ExoPlayer架构详解与源码分析3——Timeline ExoPlayer架构详解与源码分析4——整体架构 ExoPlayer架构详解与源码分析5——MediaSource 文章目录 系列文章目录前言MediaSourceMediaSource的实现BaseMediaSourceCompositeMediaSourceWrappingMediaSourceMaskingMediaSourceProgressiveMediaSource 总结 前言
上篇说完整体架构这里开始分析其中的各个组件先从MediaSource看起继续拿运载火箭做对比MediaSource在整个运载火箭中的角色就类似于燃料系统确保火箭顺利升空燃料系统是其中重要的一环需要能在运行过程从持续稳定的提供燃料。ExoPlayer也一样为了保证能够持续的渲染出媒体内容就得保证MediaSource持续稳定提供需要的数据。
MediaSource
继续扩充下我们的版图 MediaSource定义了媒体信息以及提供媒体数据给播放器主要有2个职责
为播放器提供定义其媒体时序结构的Timeline并在媒体时序结构发生变化时提供新的Timeline。初始化是提供一个PlaceholdTimeline当prepareSource 完成时一般就能获取到真实的Timeline然后调用传递给prepareSource 的MediaSourceCallers 上的onSourceInfoRefreshed 来更新这些新的Timeline。为其Timeline中的Period提供 MediaPeriod 实例。 MediaPeriods是通过调用createPeriod获得的并为播放器提供加载和读取媒体的方式。
应用代码不应该直接调用MediaSource 里的方法而应该让ExoPlayer在合适的时间调用。 MediaSource实例可以重复使用但只能同时用于一个 ExoPlayer 实例。 不同MediaSource 方法只能在应用程序线程或内部播放线程其中一个上调用。每个方法文档上都明确了可以调用的线程。
看下几个重要的方法定义
getInitialTimeline主线程调用当真实Timeline未知时立即返回初始PlaceholderTimeline或者为返回null 让播放器创建初始Timeline。getMediaItem主线程调用返回当前的MediaItem可以看到MediaSource里也可能保存了MediaItem。prepareSource内部播放线程调用注册 MediaSourceCaller主要用来为播放器提供一个回调获取最新的Timeline。另外在播放某些播放资源需要先获取真实的媒体源时这里会提前解析媒体资源如播放HLS时这个时候会去获取解析M3U8文件prepareSource完成后会立即刷新Timeline。 void prepareSource(MediaSourceCaller caller,Nullable TransferListener mediaTransferListener,PlayerId playerId);interface MediaSourceCaller {void onSourceInfoRefreshed(MediaSource source, Timeline timeline);}createPeriod在内部播放线程调用返回一个由periodId区分的新的MediaPerods对象只能在真实的源已经准备好后再调用也就是上面的prepareSource确保源已经准备完成参数id就是MediaPerods唯一区分startPositionUs想要播放的开始位置allocator是一个缓存分配器这个后面讲MediaPerods会提到MediaPerods创建完成后也会perpare完成后一般就可以获取媒体的基本数据如时长、轨道等这个时候会反过来通知MediaSource刷新Timeline。 MediaPeriod createPeriod(MediaPeriodId id, Allocator allocator, long startPositionUs);MeidiaSource大致工作流程就是创建时初始化出一个Timeline然后prepareSource准备数据源之后createPeriod创建Period然后讲工作交给Period整个过程都在刷新Timeline。
MediaSource的实现 BaseMediaSource
MediaSource虚函数实现主要用于多个MediaSourceEventListener的处理分发触发多个MediaSourceCaller的onSourceInfoRefreshed还保存上一次的Timeline。
CompositeMediaSource
由多个子MediaSource组成的复合MediaSource将所有方法调用转发给各个子的MediaSource
WrappingMediaSource
继承自CompositeMediaSource实现只包含了一个子MediaSource的MediaSource 。
MaskingMediaSource
一个MediaSource 主要作用是当实际媒体结果未知时用一个PlaceholderTimeline来表示Timeline 当获取实际的媒体结构时采用实际的Timeline替换PlaceholderTimeline。
public MaskingMediaSource(MediaSource mediaSource, boolean useLazyPreparation) {super(mediaSource);this.useLazyPreparation useLazyPreparation mediaSource.isSingleWindow();window new Timeline.Window();period new Timeline.Period();Nullable Timeline initialTimeline mediaSource.getInitialTimeline();if (initialTimeline ! null) {timeline MaskingTimeline.createWithRealTimeline(initialTimeline, /* firstWindowUid */ null, /* firstPeriodUid */ null);hasRealTimeline true;} else {timeline MaskingTimeline.createWithPlaceholderTimeline(mediaSource.getMediaItem());}}ProgressiveMediaSource
继承自BaseMediaSource主要用于渐进式媒体文件的播放如本地或远程的单个视频文件 Override//prepareprotected void prepareSourceInternal(Nullable TransferListener mediaTransferListener) {transferListener mediaTransferListener;drmSessionManager.setPlayer(/* playbackLooper */ checkNotNull(Looper.myLooper()), getPlayerId());drmSessionManager.prepare();notifySourceInfoRefreshed();}Override//ProgressiveMediaPeriod在获取到Timeline相关信息后会回调更新Timelinepublic void onSourceInfoRefreshed(long durationUs, boolean isSeekable, boolean isLive) {// 优先实现之前的durationUs durationUs durationUs C.TIME_UNSET ? timelineDurationUs : durationUs;if (!timelineIsPlaceholder timelineDurationUs durationUs timelineIsSeekable isSeekable timelineIsLive isLive) {// 没有发生变更return;}timelineDurationUs durationUs;timelineIsSeekable isSeekable;timelineIsLive isLive;timelineIsPlaceholder false;notifySourceInfoRefreshed();}//刷新TimeLineprivate void notifySourceInfoRefreshed() {Timeline timeline new SinglePeriodTimeline(timelineDurationUs,timelineIsSeekable,/* isDynamic */ false,/* useLiveConfiguration */ timelineIsLive,/* manifest */ null,mediaItem);if (timelineIsPlaceholder) {timeline new ForwardingTimeline(timeline) {Overridepublic Window getWindow(int windowIndex, Window window, long defaultPositionProjectionUs) {super.getWindow(windowIndex, window, defaultPositionProjectionUs);window.isPlaceholder true;return window;}Overridepublic Period getPeriod(int periodIndex, Period period, boolean setIds) {super.getPeriod(periodIndex, period, setIds);period.isPlaceholder true;return period;}};}//触发监听refreshSourceInfo(timeline);}总结
没了就这么多燃料系统这么简陋的吗当然不会因为它把除了Timeline的管理维护之外的几乎所有的工作都交给别人来完成了它就是下面要重点讲的MediaPeriodMediaSource只管创建出就好了ExoPlayer也是主要通过MediaSource关联的MediaPeriod控制媒体的加载释放等。 版权声明 © 本文为CSDN作者山雨楼原创文章 转载请注明出处 原创不易觉得有用的话收藏转发点赞支持