ExoPlayer架构详解与源码分析(5)——MediaSource

系列文章目录

ExoPlayer架构详解与源码分析(1)——前言
ExoPlayer架构详解与源码分析(2)——Player
ExoPlayer架构详解与源码分析(3)——Timeline
ExoPlayer架构详解与源码分析(4)——整体架构
ExoPlayer架构详解与源码分析(5)——MediaSource


文章目录

  • 系列文章目录
  • 前言
  • MediaSource
  • MediaSource的实现
    • BaseMediaSource
    • CompositeMediaSource
    • WrappingMediaSource
    • MaskingMediaSource
    • ProgressiveMediaSource
  • 总结


前言

上篇说完整体架构,这里开始分析其中的各个组件,先从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的管理维护之外的几乎所有的工作都交给别人来完成了,它就是下面要重点讲的MediaPeriod,MediaSource只管创建出就好了,ExoPlayer也是主要通过MediaSource关联的MediaPeriod控制媒体的加载释放等。


版权声明 ©
本文为CSDN作者山雨楼原创文章
转载请注明出处
原创不易,觉得有用的话,收藏转发点赞支持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/108853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自己写spring boot starter问题总结

1. Unable to find main class 创建spring boot项目写自己的starterxi写完之后使用install出现Unable to find main class&#xff0c;这是因为spring boot打包需要一个启动类&#xff0c;按照以下写法就没事 <plugins><plugin><groupId>org.springframewo…

不懂的东西

1、 2、 3、 4、 5、我看到那篇 Peace of mind 论文&#xff0c;有一个疑问&#xff0c;为什么论文里的量表用的频率指标&#xff1f;比如Some of the time&#xff0c; Not at all等&#xff0c;而PANAS用的是程度指标&#xff0c;比如moderately&#xff0c;a little等。…

linux加密和安全

sudo实现授权 添加 vim /etc/sudoers luo ALL(root) /usr/bin/mount /deb/cdrom /mnt/ 切换luo用户使用 sudo mount /dev/cdrom /mnt %sudo ALL(ALL:ALL) ALL %sudo 表示该规则适用于sudo用户组中的所有成员。 ALL(ALL:ALL) 表示可以在任何主机上&#xff0c;以任何用户身份来…

Java并发面试题:(五)volatile关键字

volatile 是什么 一旦一个共享变量&#xff08;类的成员变量、类的静态成员变量&#xff09;被volatile修饰之后&#xff0c;那么就具备了两层语义&#xff1a; 1&#xff09;保证了不同线程对这个变量进行操作时的可见性&#xff0c;即一个线程修改了某个变量的值&#xff0c…

iphone xr密码错误太多次 连接itunes

itunes下载的固件在电脑在电脑的“C&#xff1a;\Users\用户名\AppData\Roaming\Apple Computer\iTunes\iPhone Software Updates”文件夹之中。 如果你忘记了 iPhone 密码 - 官方 Apple 支持 (中国) 下载和使用 Windows 10 版 iTunes - 官方 Apple 支持 (中国) 查找手机 iClo…

C# , .netWebApi 实现类似Java 的Ioc 自动装配@Autowired

写C# 一直很羡慕Java的Autowired 自动装配. 因为C# 必须手动在Ioc里注册, 例如 builder.Services.AddSingleton<IHostedService, StartupInitializationService>();但是我们也可以用C# 的反射机制 , 用接口实现自动装配. 写接口, 扩展方法如下: namespace MyFanucApi.S…

vue3+vite+ts同时引入多个iconfont图标

vue3vitets同时引入多个iconfont图标 本文目录 vue3vitets同时引入多个iconfont图标下载iconfont库创建项目库图标加入项目库下载到本地 vue3引入文件存放位置main.ts设置组件中使用 分别引入多个iconfont 下载iconfont库 创建项目库 iconfont官网&#xff1a;https://www.ic…

Docker学习_存储篇

当以默认的方式创建容器时&#xff0c;容器中的数据无法直接和其他容器或宿主机共享。为了解决这个问题需要学习一些Docker 存储卷的知识。 Docker提供了三种存储的方式。 bind mount共享宿主机文件目录volume共享docker存储卷tmpfs mount共享内存 volume* volume方式是容器…

Django使用Token认证(simplejwt库的配置)

目录 官网文档安装项目配置拓展配置 官网文档 https://django-rest-framework-simplejwt.readthedocs.io/en/latest/ 安装 pip install djangorestframework-simplejwt项目配置 REST_FRAMEWORK {...DEFAULT_AUTHENTICATION_CLASSES: (...rest_framework_simplejwt.authent…

【html】利用生成器函数和video元素,取出指定时间的视频画面

简言 有的时候想截取视频某一秒的视频画面。 手动截取操作麻烦&#xff0c;还得时刻关注视频播放时间。 于是&#xff0c;我搞出来了一个根据视频自动截取特定时间描述的页面。 效果 实现步骤 获取视频对象根据视频时长生成时间选择表单根据表单选择的时间和视频地址&#x…

【数据仓库】hadoop生态圈与数据仓库

文章目录 1.大数据定义2. Hadoop与数据仓库3. 关系数据库的可扩展性瓶颈4. CAP理论5. Hadoop数据仓库工具5.1. RDS和TDS5.2. 抽取过程5.3. 转换与装载过程5.4. 过程管理和自动化调度5.5&#xff0e;数据目录&#xff08;或者称为元数据管理&#xff09;5.6&#xff0e;查询引擎…

9中间件-Redis、MQ---进阶

mq进阶 RabbitMQ 怎么避免消息丢失&#xff1f; 把消息持久化磁盘&#xff0c;保证服务器重启消息不丢失。 每个集群中至少有一个物理磁盘&#xff0c;保证消息落入磁盘。#RabbitMQ 的消息是怎么发送的&#xff1f; 首先客户端必须连接到 RabbitMQ 服务器才能发布和消费消息&…

笙默考试管理系统-MyExamTest----codemirror(33)

笙默考试管理系统-MyExamTest----codemirror&#xff08;33&#xff09; 目录 一、 笙默考试管理系统-MyExamTest 二、 笙默考试管理系统-MyExamTest 三、 笙默考试管理系统-MyExamTest 四、 笙默考试管理系统-MyExamTest 五、 笙默考试管理系统-MyExamTest 笙默考试…

数仓建设(三)

4) 累积快照事实表 多个业务过程联合分析而构建的事实表&#xff0c;如采购单的流转环节。用于分析事件时间和时间之间的间隔周期。少量的且当前事务型不支持的&#xff0c;如关闭、发货等相关的统计。 4. DWS公共汇总层设计规范 数据仓库的性能是数据仓库建设是否成功的重要标…

PA2019 Terytoria

洛谷P5987 [PA2019] Terytoria 题目大意 在一个平面直角坐标系上&#xff0c;有一个长度为 X X X&#xff0c;宽度为 Y Y Y的地图&#xff0c;这个地图的左边界和右边界是连通的&#xff0c;下边界和上边界也是连通的。 在地图中&#xff0c;有 X Y X\times Y XY个格子以及…

【vue2高德地图api】03-完善展示页,并且调用poi搜索接口

系列文章目录 文章目录 系列文章目录前言一、编写页面内容样式1.1 html内容1.2 css内容解决报错 二、完善api接口变量方法1.data变量2. methods3. computed4. api接口方法 三、配置api接口方法创建map.jsgetParkList方法 移动端控制台插件四、编写components组件在main.js中引入…

算启新程 智享未来 | 紫光展锐携手中国移动共创数智未来

10月11日-13日&#xff0c;2023年中国移动全球合作伙伴大会在广州举行&#xff0c;此次大会以“算启新程 智享未来”为主题&#xff0c;与合作伙伴一起共商融合创新&#xff0c;共创数智未来。作为中国移动每年规模最大、最具影响力的盛会&#xff0c;吸引了数百家世界500强企业…

[机缘参悟-110] :一个IT人对面具的理解:职业面具戴久了,就会忘记原本真实的自己,一个人是忠于职位,还是忠于内心?

目录 一、职业面具戴久了&#xff0c;就会忘记原本真实的自己 二、霸王别姬 三、没有对错&#xff0c;各走各路 3.1 程蝶衣&#xff1a;戏里戏外&#xff0c;忠于角色 3.2 段小楼&#xff1a;戏里戏外&#xff0c;角色分明 3.3 没有对错&#xff0c;各走各路 四、职场中…

视口 css

视口是浏览器上显示网页的一块区域&#xff0c;大小并不局限于浏览器可视区域范围。PC端和移动端视口差别很大。PC端中视口宽度始终与浏览器窗口宽度一致&#xff0c;移动端视口与浏览器窗口宽度完全独立。 PC端 PC端视口大小等于浏览器窗口可视区域大小&#xff0c;无论浏览…

集准测试-架构真题(五十六)

如果数据库单标即可实现业务功能&#xff0c;采用&#xff08;&#xff09;方式进行数据交换与处理较为合适。如果通过数据库不同表的连接操作获取数据才能实现业务功能&#xff0c;这时候采用&#xff08;&#xff09;方式进行数据交换与处理合适。 主动记录数据网关包装器数…