当前位置: 首页 > news >正文

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作者山雨楼原创文章
转载请注明出处
原创不易,觉得有用的话,收藏转发点赞支持

相关文章:

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

系列文章目录 ExoPlayer架构详解与源码分析(1)——前言 ExoPlayer架构详解与源码分析(2)——Player ExoPlayer架构详解与源码分析(3)——Timeline ExoPlayer架构详解与源码分析(4)—…...

控制一个游戏对象的旋转和相机的缩放

介绍 这段代码是一个Unity游戏开发脚本,它用于控制一个游戏对象的旋转和相机的缩放。以下是代码的主要功能: 控制游戏对象的旋转: 通过按下Q键和W键,用户可以选择以逆时针或顺时针方向绕游戏对象的Y轴进行旋转。旋转角度和速度可…...

【数据结构】线性表(二)单链表及其基本操作(创建、插入、删除、修改、遍历打印)

目录 前文、线性表的定义及其基本操作(顺序表插入、删除、查找、修改) 四、线性表的链接存储结构 1. 单链表(C语言) a. 链表节点结构 b. 创建新节点 c. 在链表末尾插入新节点 d. 删除指定节点 e. 修改指定节点的数据 f. …...

label的作用是什么?是怎么用的?(1)

Label(标签)在不同的上下文中有不同的作用和用途。以下是几种常见的用途和用法: 1. 数据标注:在机器学习和数据科学中,标签用于标识数据样本的类别或属性。标注数据是监督学习中的一项重要任务,它为算法提…...

C- 使用原子变量实现自旋锁

自旋锁 自旋锁(Spinlock)是一种常用于多线程编程中的低开销锁,其特点是当线程尝试获取锁而锁已被其他线程占用时,该线程会处于一个持续的忙等待(busy-wait)状态,直到它可以获取到锁为止。这种方…...

汇编的指令

减法类指令: 不带借位的减法: sub dest,src;dest(dest)-(src) 注意: 1、源操作数和目的操作数不能同时为段寄存器或存储单元 2、对标志位有影响,主要影响CF、ZF、OF、SF。 带借位的减法: sbb dest,src;dest(dest)-(…...

《数据结构、算法与应用C++语言描述》使用C++语言实现数组队列

《数据结构、算法与应用C语言描述》使用C语言实现数组队列 定义 队列的定义 队列(queue)是一个线性表,其插入和删除操作分别在表的不同端进行。插入元素的那一端称为队尾(back或rear),删除元素的那一端称…...

零基础如何学习自动化测试

现在很多测试人员有些急于求成,没有任何基础想当然的,要在一周内上手自动化测试。 在自动化的过程中时候总有人会犯很低级的问题,有语法问题,有定位问题,而且有人居然连__init__.py 文件名都弄错误,还有将…...

系统架构师备考倒计时16天(每日知识点)

1.信息化战略与实施 2.UML图(12个) 3.结构化设计(耦合) 4.SMP与AMP的区别(多核处理器的工作方式) 多核处理器一般有SMP和AMP两种不同的工作方式: SMP(对称多处理技术):将2颗完全一样的处理器封…...

【MySQL系列】- Select查询SQL执行过程详解

【MySQL系列】- Select查询SQL执行过程详解 文章目录 【MySQL系列】- Select查询SQL执行过程详解一、SQL查询语句的执行过程二、SQL执行过程详解2.1. 连接器2.2. 查询缓存2.3. 分析器2.4. 优化器2.5. 执行器 三、undo log 和 redo log作⽤3.1. redo log (重做日志&a…...

软考高级信息系统项目管理师系列之:信息系统项目管理师论文评分参考标准

软考高级信息系统项目管理师系列之:信息系统项目管理师论文评分参考标准 论文满分是 75 分,论文评分可分为优良、及格与不及格 3 个档次。评分的分数可分为: 60 分至 75 分优良(相当于百分制 80 分至 100 分)。45 分至 59 分及格(相当于百分制 60 分至 79 分)。0 分至 44 分…...

MyBatis--多案例让你熟练使用CRUD操作

目录 一、前期准备 二、两种实现CRUD方式 三、增加数据(INSERT) 四、删除数据(DELETE) 五、查询数据(SELECT) 六、更新数据(UPDATE) 一、前期准备 1.创建maven项目并在pom文件…...

用Python造轮子

目录 背景安装setuptools库准备要打包的代码创建setup.py文件打包生成whl文件把库装到电脑上使用这个库 背景 如何把自己写的代码,打包成库方便其他人使用 安装setuptools库 正所谓想要富先修路,先把造轮子要用的库装上 pip install wheel pip insta…...

ARM 堆栈寻址类型区分

文章目录 堆栈指向分类堆栈指向数据分类满递增与满递减空递增与空递减 堆栈指向分类 根据堆栈指针的指向的方向不同,可以划分为向上生成型和向下生成型。 向上生成型: 随着数据的入栈,堆栈的指针逐渐增大,称为:递增…...

每日一练 | 网络工程师软考真题Day43

1、在生成树协议〔STP〕IEEE 802.1d中,根据 来选择根交换机。 A.最小的MAC地址 B.最大的MAC地址 C.最小的交换机ID D.最大的交换机ID 2、在快速以太网物理层标准中,使用两对5类无屏蔽双绞线的是 。 A&…...

jsonXML格式化核心代码

json格式化&#xff1a; 依赖&#xff1a; <dependency><groupId>com.jayway.jsonpath</groupId><artifactId>json-path</artifactId><version>2.6.0</version><scope>compile</scope> </dependency> string t…...

PTQ量化和QAT量化

目录 1--PTQ量化 2--QAT量化 1--PTQ量化 PTQ量化表示训练后量化&#xff08;Post Training Quantization&#xff09;。使用一批校准数据对训练好的模型进行校准&#xff0c;将训练好的FP32网络直接转换为定点计算的网络&#xff0c;过程中无需对原始模型进行任何训练&#x…...

【Django 02】数据表构建、数据迁移与管理

1. Django 构建数据表创建与数据迁移 1.1 数据表创建 1.1.1 模块功能 如前所述&#xff0c;models.py文件主要用一个 Python 类来描述数据表。运用这个类,可以通过简单的 Python 代码来创建、检索、更新、删除 数据库中的记录而无需写一条又一条的SQL语句。今天的例子就是在…...

一天吃透Java集合面试八股文

内容摘自我的学习网站&#xff1a;topjavaer.cn 常见的集合有哪些&#xff1f; Java集合类主要由两个接口Collection和Map派生出来的&#xff0c;Collection有三个子接口&#xff1a;List、Set、Queue。 Java集合框架图如下&#xff1a; List代表了有序可重复集合&#xff0c…...

高级深入--day36

Settings Scrapy设置(settings)提供了定制Scrapy组件的方法。可以控制包括核心(core),插件(extension),pipeline及spider组件。比如 设置Json Pipeliine、LOG_LEVEL等。 参考文档:Settings — Scrapy 1.0.5 文档 内置设置参考手册 BOT_NAME 默认: scrapybot 当您使用 sta…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

力扣热题100 k个一组反转链表题解

题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象&#xff1a; android studio报错&#xff1a; [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决&#xff1a; 不要动CMakeLists.…...

实战三:开发网页端界面完成黑白视频转为彩色视频

​一、需求描述 设计一个简单的视频上色应用&#xff0c;用户可以通过网页界面上传黑白视频&#xff0c;系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观&#xff0c;不需要了解技术细节。 效果图 ​二、实现思路 总体思路&#xff1a; 用户通过Gradio界面上…...