播放器性能的极致优化,就是要发现播放流程中一点一滴的耗时,然后分析这些耗时,并提出有效的方式解决这些耗时.了解过ExoPlayer播放器的同学们都知道ExoPlayer的解码是依赖Android系统提供的原生的解码模块,即MediaCodec来实行视频和音频解码的.

基于我们对MediaCodec使用方式和原理的熟悉,我们在使用MediaCodec的时候,首先要初始化,codec configure, codec start等流程,经过这些流程,codec分配内存来存储input buffer 和 output buffer

这块耗时对视频播放而言是无法避免的,不管是网络视频还是本地视频, codec 初始化--->configure ---> start ---> 上屏这部分的耗时都是无法避免的.

我们抓一下一个1080P的本地视频的systrace, 显示如下:

可以发现: video decoder和audio decoder创建/configure/start耗时了170ms, 直接占用了绝大部分耗时, 确实是耗时的大头.

目前ExoPlayer最新的版本是2.12.2, 而且保持着凉州一个小版本, 两个月一个大版本的更新节奏, google的工作效率还是比较高的.
针对codec 复用, 在2.10版本之前和2.10之后的版本, 使用方式和原理还是有所不同的.

ExoPlayer 2.10版本之前的codec复用

  • disabled状态, 在此状态下, 渲染器没有要播放的媒体流并且不保存解码器实例。

  • enabled状态, 在此状态下,渲染器可以播放媒体流,并在可能的情况下(例如,在读取流的格式之后)获取解码器实例。

  • started状态, 在此状态下,渲染器使用持有的解码器实例来播放视频

在2.10之前的版本中,只要视频渲染器保持在启用和启动状态,ExoPlayer就会尽可能重复使用视频解码器。特别是,这意味着从播放列表中的一种媒体过渡到另一种媒体时,视频解码器将被重用。在渲染列表过渡到禁用状态时,音频解码器不会在此类播放列表过渡中重用,视频或音频解码器也不会重用。重要的是,重新准备播放器以播放其他MediaSource会导致这种类型的状态转换,因此在这种情况下不会重复使用解码器。

一句话, 想复用codec实例,不能调用stop方法,不能将codec置为disabled状态

ExoPlayer 2.10版本之后的codec复用

2.10版本可以保证在播放新的视频源的时候复用播放器解码器资源.即使当前的渲染器持有的解码器实例已经被置为disabled状态

复用解码器实例可以减少多个视频源之间切换导致的丢帧的问题,更加可以节省时间.下面是复用解码器实例之后的systrace耗时:

解码器实例复用要求

解码器实例可以复用,肯定是有条件的,例如上一个视频播放的是VP9的视频,下一个视频播放的是H265的视频,那么解码器实例肯定不能复用.
具体是什么条件了,我们还是查看源码确认一下:
MediaCodecRenderer.java有两个子类, MediaCodecVideoRenderer.java和MediaCodecAudioRenderer.java

MediaCodecVideoRenderer.java

  @Overrideprotected DecoderReuseEvaluation canReuseCodec(MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {DecoderReuseEvaluation evaluation = codecInfo.canReuseCodec(oldFormat, newFormat);@DecoderDiscardReasons int discardReasons = evaluation.discardReasons;if (newFormat.width > codecMaxValues.width || newFormat.height > codecMaxValues.height) {discardReasons |= DISCARD_REASON_VIDEO_MAX_RESOLUTION_EXCEEDED;}if (getMaxInputSize(codecInfo, newFormat) > codecMaxValues.inputSize) {discardReasons |= DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;}return new DecoderReuseEvaluation(codecInfo.name,oldFormat,newFormat,discardReasons != 0 ? REUSE_RESULT_NO : evaluation.result,discardReasons);}
  • 首先当前的视频的最大分辨率不能超过codec支持的最大解码分辨率

  • 其次视频的输入size不能超过codec的input buffer size

MediaCodecAudioRenderer.java

  @Overrideprotected DecoderReuseEvaluation canReuseCodec(MediaCodecInfo codecInfo, Format oldFormat, Format newFormat) {DecoderReuseEvaluation evaluation = codecInfo.canReuseCodec(oldFormat, newFormat);@DecoderDiscardReasons int discardReasons = evaluation.discardReasons;if (getCodecMaxInputSize(codecInfo, newFormat) > codecMaxInputSize) {discardReasons |= DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;}return new DecoderReuseEvaluation(codecInfo.name,oldFormat,newFormat,discardReasons != 0 ? REUSE_RESULT_NO : evaluation.result,discardReasons);}
  • 音频的输入size不能超过codec的input buffer size

我们如何复用解码器

  • 保证你播放的视频的格式是相同的,例如短视频信息流都是H264/AAC编码格式

  • 如果使用ExoPlayer播放器,最好使用同一个ExoPlayer实例,因为codec实例是封装在ExoPlayer实例中的

  • 当重新prepare新的视频时,在调用prepare之前不能调用stop函数,因为stop函数会释放解码器实例

  • 如果你要调用stop函数的情况下还想保持解码器实例不被释放,你需要调用setForegroundMode(...)函数,这个函数的使用方式是比较复杂的,不能误用

https://exoplayer.dev/doc/reference/com/google/android/exoplayer2/ExoPlayer.html#setForegroundMode-boolean-

打开了ForegroundMode模式,意味着解码器资源在调用stop的时候都不会被释放,当然这是在复用解码器资源的场景下使用的,使用的时候要小心一些,在最终的时候还是要记得释放资源的,不然会出现问题.

技术交流,欢迎加我微信:ezglumes ,拉你入技术交流群。

推荐阅读:

音视频面试基础题

OpenGL ES 学习资源分享

开通专辑 | 细数那些年写过的技术文章专辑

NDK 学习进阶免费视频来了

推荐几个堪称教科书级别的 Android 音视频入门项目

觉得不错,点个在看呗~

ExoPlayer漫谈之解码器复用相关推荐

  1. 音视频技术开发周刊 | 179

    每周一期,纵览音视频技术领域的干货. 新闻投稿:contribute@livevideostack.com. WebRTC的现状和未来:专访W3C WebRTC Chair Bernard Aboba ...

  2. 抖音世界杯直播的低延迟是怎么做到的?

    动手点关注 干货不迷路 世界杯已经结束了,梅西带领阿根廷时隔三十六年之后终于如愿捧杯.抖音直播提供的 4K 超高清超低延迟看播能力给亿万观众留下了深刻的印象,决赛的 PCU 达到 3700w+,在这样 ...

  3. 【翻译】安卓新播放器EXOplayer介绍

    [翻译]安卓新播放器EXOplayer介绍 http://developer.android.com/guide/topics/media/exoplayer.html 前言: Playing vid ...

  4. 【FFmpeg】使用 FFmpeg 处理音视频格式转换流程 ( 解复用 | 解码 | 帧处理 | 编码 | 复用 )

    FFmpeg 系列文章目录 [FFmpeg]Windows 搭建 FFmpeg 命令行运行环境 [FFmpeg]FFmpeg 相关术语简介 [FFmpeg]FFmpeg 相关术语简介 二 [FFmpe ...

  5. 【FFmpeg】FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 | 复用 | 解复用 )

    文章目录 一.FFmpeg 简介 二.FFmpeg 相关术语 1.容器 2.媒体流 3.数据帧 4.数据包 5.编解码器 6.复用 7.解复用 博客资源 一.FFmpeg 简介 FFmpeg 是 &q ...

  6. 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )

    文章目录 一.获取图像真实宽高 二.计算解码区域 三.设置解码参数 内存复用 像素格式 四.图像绘制 五.执行效果 六.源码及资源下载 官方文档 API : BitmapRegionDecoder 在 ...

  7. 【转】软件工程能力漫谈:比质量更重要的,是项目管理能力

    转自:软件工程能力漫谈:比质量更重要的,是项目管理能力 | ArchSummit 章淼老师在软件工程能力方面,积累了多年的经验,这个话题他之前也分享过多次,整体上内容有修改调整. 章老师博士毕业后在清 ...

  8. H.264软件解码器在PXA270平台上的优化

    罗 嵘,何 苦 时间:2009年04月24日 摘 要: 研究了嵌入式系统中H.264 Baseline软件解码器设计和优化的问题,提出了四种有效的优化方法,并在PXA270平台上进行了测试.测试结果显 ...

  9. ExoPlayer用户手册

    贴上原网址:https://google.github.io/ExoPlayer/guide.html 非完全翻译,有需要可以原网址自取,我发现网上也蛮多这个指导的翻译,可以去看看~ 开始啦!: Ex ...

最新文章

  1. 区块链隐私:交易还是计算?
  2. php 这样写日志 sleep你会了吗?
  3. Linux学习进阶!!
  4. 伺服电机要计算机控制,计控 - it610.com
  5. 龙芯购买MIPS指令集的授权
  6. elementos php开发,PHPWord
  7. 使用Macsome Audiobook Converter for Mac转换有声读物?
  8. 基于web的库存管理系统
  9. 怎么在html5中视频加字幕,视频转换王如何加字幕 在视频中添加文字的方法
  10. 【学习笔记】英文科技论文常见英语句式积累
  11. 设置wsl2桥接模式和设置ip
  12. JAVA-----乱码的处理 乱码的解决方法总结
  13. 命令行设置RTC alarm
  14. xp计算机管理下的服务显示不出来,WinXP系统任务栏不显示打开窗口的三种解决方案...
  15. 1.中心化账本缺点/哈希函数/什么是区块链
  16. 承接WEB应用开发、软件开发、网站开发
  17. matlab画简单长方形,matlab在图像中画长方形(框)
  18. 域名怎么卖:建站出售
  19. TestNG教程四TestNG用例失败重试
  20. Android - System.currentTimeMillis()计算时间差出现负数(NITZ和NTP机制学习)

热门文章

  1. Error using symconvertChar (sym使用报错)
  2. 利用Python进行简单杜邦分析
  3. JVM的内存区域划分(jdk7和jdk8)
  4. 《大话数据结构》读书笔记(二)
  5. 《矩阵理论》大萌课程笔记 - 线性空间与子空间
  6. 上海有牛逼的互联网公司 薪资待遇汇总
  7. unity人物旋转移动代码_Unity3D实现人物移动示例
  8. 企业数仓DQC数据质量管理实践篇
  9. LeetCode打卡:870.优势洗牌
  10. 打造稳定可靠聪明的智慧酒店系统