ExoPlayer架构详解与源码分析(6)——MediaPeriod

系列文章目录

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


文章目录

  • 系列文章目录
  • 前言
  • MediaPeriod
  • MediaPeriod的实现
  • ProgressiveMediaPeriod
  • 总结


前言

上篇看完了MediaSource,发现其中正在发挥作用的是其中的MediaPeriod,如果MediaSource是燃料系统的外壳,那么MediaPeriod就是其外壳下的核心,媒体数据的的加载获取甚至是解析主要就靠它了。

MediaPeriod

先看下整体结构
在这里插入图片描述

MediaPeriod主要用于加载于Timeline中的一个Period对于的媒体数据。换句话说Timeline中有多少个Period就会对于多少个MediaPeriod。
MediaPeriod的所有方法都在播放器内部线程调用。MediaPeriod是在MediaSource.createPeriod创建的,MediaSource中媒体数据的加载读取解复用最终提供数据给Renderer等都通过它来实现。MediaPeriod 中每个轨道对应一个SampleStream,MediaPeriod 在同一时间可能只能为一个SampleStream提供数据,但是当前的SampleStream 可以切换(因为MediaPeriod在读取数据时是单线程的,获取到数据后会同步解析数据,通过TrackId 将其关联到不同的轨道的SampleStream 中,这个后面具体会讲到)。

看下几个重要的方法定义

  • prepare异步准备当前的MediaPeriod,因为是异步的方法入参提供了一个Callback在prepared后通知调用者,在通知调用者前搜先会调用MediaSource的onSourceInfoRefreshed通知MediaSource更新Timeline,然后完成解轨道数据的解析提供给getTrackGroups方法,目的是提前准备好Timeline,如果prepare失败就会调用MediaPeriod的maybeThrowPrepareError方法

  • maybeThrowPrepareError功能如上,这个方法只会在prepare完成前调用

  • getTrackGroups获取解析出的轨道数据,因为解析轨道是prepare时完成的,所以这个方法只能在prepared之后调用。

  • selectTracks执行轨道选择,这是一个重要的方法,就是在这个方法中将轨道数据提供给上层使用者的确切的说是Renderer,同时Renderer也通过mayRetainStreamFlags 告诉MediaPeriod使用保留当前的SampleStream。MediaPeriod如果创建了新的流或者更新了SampleStream也会通过streamResetFlags=true来告诉Renderer需要重置当前的Renderer了。另外每次调用都应该更新TrackSelections。同样这个方法肯定也只能在prepared之后调用。

      long selectTracks(@NullableType ExoTrackSelection[] selections,//TrackSelector提供的轨道选择boolean[] mayRetainStreamFlags,//需要保留的流@NullableType SampleStream[] streams,//提供的数据流boolean[] streamResetFlags,//需要替换的流long positionUs);//当前的播放位置,如果当前的period还没有播放,这个值就是起始播放位置
    
  • seekToUs Seek到指定位置。仅当至少选择一个轨道时才会调用此方法。

  • continueLoading 当需要继续加载数据时调用,MediaPeriod在prepareing或者prepared后都可以调用这个方法。

  • reevaluateBuffer 释放SampleStream的相关缓存,同样这个方法肯定也只能在prepared之后调用。

  • getStreamKeys 当MediaPeriod由多个播放源时,如HLS,这个方法返回一个多个源关于选中轨道的KeyList

MediaPeriod接口定义了数据解析的大致过程:

  1. prepare准备数据源,完成后selectTracks向外提供出SampleStream
  2. continueLoading 继续加载数据填充SampleStream
  3. 将使用完的数据通过reevaluateBuffer释放

MediaPeriod的实现

在这里插入图片描述
可以看到基本每一种ExoPlayer支持的媒体都实现了一个MediaPeriod,ProgressiveMediaPeriod相对比较基础和典型,后面也将重点解析它,剩余其他几种类型的可以先做了解,后面有时间再扩充。

ProgressiveMediaPeriod

ProgressiveMediaSource的MediaPeriod实现,主要用于渐进式媒体文件的加载,如本地或远程的单个视频文件,
先看下ProgressiveMediaPeriod整体结构
在这里插入图片描述
ProgressiveMediaPeriod主要分2部分:

  • 数据存取 管理缓存获取的数据,主要交由SampleQueue来负责,需要提供高效的缓存读写能力保证数据的持续性。
  • 数据加载解析 加载主要由DataSource负责,主要工作是获取媒体数据供解析器读取,解析器主要指的是Extractor,主要负责将获取的数据解析到不同的SampleQueue中。

上图中并没有MediaPeriod提到的SampleStream,其实ProgressiveMediaPeriod内部类中实现了SampleStream ,通过内部类将
对SampleStream 操作通过trackid关联转发给SampleQueue来实现,所以上图中的SampleQueue其实就是相当于SampleStream。

private final class SampleStreamImpl implements SampleStream {private final int track;public SampleStreamImpl(int track) {this.track = track;}@Overridepublic boolean isReady() {return ProgressiveMediaPeriod.this.isReady(track);}@Overridepublic void maybeThrowError() throws IOException {ProgressiveMediaPeriod.this.maybeThrowError(track);}@Overridepublic int readData(FormatHolder formatHolder, DecoderInputBuffer buffer, @ReadFlags int readFlags) {return ProgressiveMediaPeriod.this.readData(track, formatHolder, buffer, readFlags);}@Overridepublic int skipData(long positionUs) {return ProgressiveMediaPeriod.this.skipData(track, positionUs);}}/* package */ int readData(int sampleQueueIndex,FormatHolder formatHolder,DecoderInputBuffer buffer,@ReadFlags int readFlags) {if (suppressRead()) {return C.RESULT_NOTHING_READ;}maybeNotifyDownstreamFormat(sampleQueueIndex);int result =//sampleQueueIndex查询对应的sampleQueues读取数据sampleQueues[sampleQueueIndex].read(formatHolder, buffer, readFlags, loadingFinished);if (result == C.RESULT_NOTHING_READ) {maybeStartDeferredRetry(sampleQueueIndex);}return result;}

Extractor和DataSource那一块还没扩展开,目前就已经很复杂了,DrmSessionManager和LoadErrorHandlingPolicy不是主线任务就跳过了,重点关注Loder、SampleQueue、DataSource、Extractor。


总结

MediaPeriod接口只是定义了标准的执行逻辑,具体如何实现其中定义的每个方法其实每种MediaPeriod实现都会有很大的差异,因为媒体结构本身就千变万化。ProgressiveMediaPeriod实现了其中一种相对基础的媒体类型,但是结构也很复杂,预计下面分多篇将ProgressiveMediaPeriod的SampleQueue、Loder、DataSource、Extractor分析一遍,下篇先从SampleQueue说起。


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

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

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

相关文章

【LeetCode】102. 二叉树的层序遍历

题目链接 文章目录 Python3方法一: 广度优先搜索 (BFS) ⟮ O ( n ) ⟯ \lgroup O(n) \rgroup ⟮O(n)⟯方法二: 深度优先搜索 (DFS) ⟮ O ( n ) ⟯ \lgroup O(n) \rgroup ⟮O(n)⟯ C方法一: 广度优先搜索 (BFS) ⟮ O ( n ) ⟯ \lgroup O(n…

“Can‘t open workbook - unsupported file type: XML“

java开发,增删改查,涉及到导入excel时,有的excel导入失败提示"Cant open workbook - unsupported file type: XML"。着急赶工期,告诉客户先把excel另存为xls格式,再重新导入。现在有点空余时间,好…

力扣每日一题66:加一

题目描述: 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外,这个整数不会以零开头。 示例 1: 输…

二十三种设计模式全面解析-单例设计模式:解密全局独一无二的实例创造者

在软件开发中,有一种设计模式被誉为"独一无二的实例创造者",它就是单例设计模式。无论你是初学者还是有经验的开发人员,了解并掌握单例模式都是非常重要的。本文将以通俗易懂的方式,全面解析单例设计模式,并…

Android 中如何使用 App Links

1. 简介 什么是 App Links呢?App Links 是 Android 6.0 (API 级别23) 引入的新功能,它是基于 DeepLinking,允许应用自动处理网站的 URL,而无需提示用户启动相应的应用。 例如:如果你在手机浏览器中输入了某个网站&am…

esp32-S3 + visual studio code 开发环境搭建

一、首先在下面链接网页中下载esp-idf v5.1.1离线安装包 ,并安装到指定位置。dl.espressif.cn/dl/esp-idf/https://dl.espressif.cn/dl/esp-idf/ 安装过程中会提示需要长路径支持,所以windows系统需要开启长路径使能 Step 1: 打开运行&…

springboot 拦截器 导致fastjson 大小写失效

实体类 public class Info{JsonFeild(“sDqClose”)private String sDqClose;private String sDqHigh; }拦截器 Configuration EnableWebMvc public class WebMvcConfigurerConfig implements WebMvcConfigurer {private CorsConfiguration buildConfig() {CorsConfiguration …

uniapp解决iOS切换语言——原生导航栏buttons文字不生效

uniapp 切换语言原生导航栏buttons文字不生效? 文章目录 uniapp 切换语言原生导航栏buttons文字不生效?效果图page.json配置解决方式 效果图 场景:在 tabbar 页面中,配置 原生导航栏 buttons ,切换语言时,不…

设计大师都在用!电商设计素材网站大公开

双十一即将到来,想必各电商平台的设计师早已开启电商设计项目。找到合适的电商设计模板是电商设计成功的关键因素。高质量的电商设计模板素材不仅能够提升网站的吸引力,还能提升用户体验,从而增加商品的交易率。 Pixso资源社区 在寻找电商设计…

中央设备状态监控系统CMS如何帮助半导体晶圆厂提高产品良率

中央设备状态监控系统(CMS)在半导体晶圆厂中扮演着关键角色,帮助企业提高产品的良率。本文将介绍CMS是什么、当前半导体晶圆厂产品良率面临的挑战,并重点探讨CMS如何通过实时数据监控、故障预测和预警、以及统计分析和过程改进等方…

ESP32网络开发实例-将 ESP32 连接到 EMQX Cloud MQTT Broker

将 ESP32 连接到 EMQX Cloud MQTT Broker 文章目录 将 ESP32 连接到 EMQX Cloud MQTT Broker1、MQTT介绍2、软件准备3、硬件准备4、代码实现5、MQTT测试在本文中,将介绍使用 EMQX Cloud MQTT 服务器。 首先,我们将介绍如何将 ESP32 开发板连接到 EMQX Cloud MQTT 服务器。 我…

Stable Diffusion AI绘图

提示词: masterpiece, best quality, 1girl, (anime), (manga), (2D), half body, perfect eyes, both eyes are the same, Global illumination, soft light, dream light, digital painting, extremely detailed CGI anime, hd, 2k, 4k background 反向提示词&…

Django 实战开发(一)项目搭建

1.项目搭建 用pycharm 编辑器可以直接 New 一个 Django 项目 2.新建应用 python manage.py startapp demo项目结构如下: 3.编写第一个Django 视图函数 /demo/views: from django.http import HttpResponse def welcome(request):return HttpResponse("welcome to dja…

持续集成部署-k8s-服务发现-Service

持续集成部署-k8s-服务发现-Service:配置讲解及基础命令 1. Service 简介2. 基础命令3. 基于 Service 访问外部服务4. 代理外部域名5. Endpoints 常用类型1. Service 简介 在K8s中,Service 是一种可以暴露一个或多个Pod的稳定的网络终点,从而形成逻辑上的应用服务单元,为服…

Azure - 机器学习企业级服务概述与介绍

目录 一、什么是 Azure 机器学习?大规模生成业务关键型机器学习模型 二、Azure 机器学习适合哪些人群?三、Azure 机器学习的价值点加快价值实现速度协作并简化 MLOps信心十足地开发负责任地设计 四、端到端机器学习生命周期的支持准备数据生成和训练模型…

WebGL笔记:矩阵的变换之平移的实现

矩阵的变换 变换 变换有三种状态:平移、旋转、缩放。当我们变换一个图形时,实际上就是在移动这个图形的所有顶点。解释 webgl 要绘图的话,它是先定顶点的,就比如说我要画个三角形,那它会先把这三角形的三个顶点定出来…

重大技术问题,iPhone 15 Pro Max面临“烧屏门”风波 | 百能云芯

近期,社交媒体平台上陆续涌现大量用户和数码博主就iPhone 15 Pro Max出现烧屏问题的投诉与评论。 烧屏问题是OLED屏幕常见的一个缺陷,这是由OLED屏幕发光机制引发的,OLED屏幕可视为由无数微小的灯泡-像素点构成,这些像素点可以独立…

Mac电脑怎么在Dock窗口预览,Dock窗口预览工具DockView功能介绍

DockView是一款Mac电脑上的软件,它可以增强Dock的功能,让用户更方便地管理和切换应用程序。 DockView的主要功能是在 DockQ,栏上显示每个窗口的缩略图,并提供了一些相关的操作选项。当用户将鼠标悬停在Dock栏上的应用程序图标上时…

PyCharm中文使用详解

PyCharm是一个Python IDE,可以帮助程序员节省时间,提高生产力。那么具体怎么用呢?本文介绍了PyCharm的安装、插件、外部工具、专业功能等,希望对大家有所帮助。 之前没有系统介绍过PyCharm。如何配置环境,如何DeBug&a…

2024 王道考研-数据结构(线性表_2)

第二章 线性表算法题(线性表的链式存储) 二、综合应用题 1.设计一个递归算法,删除不带头结点的单链表L中所有值为x的结点。 设f(L,x)的功能是删除以L为首结点指针的单链表中所有值等于x的结点,显然有f(L->next,x)的功能是删除以L->next为首结点指…