ExoPlayer漫谈之解码器复用
播放器性能的极致优化,就是要发现播放流程中一点一滴的耗时,然后分析这些耗时,并提出有效的方式解决这些耗时.了解过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漫谈之解码器复用相关推荐
- 音视频技术开发周刊 | 179
每周一期,纵览音视频技术领域的干货. 新闻投稿:contribute@livevideostack.com. WebRTC的现状和未来:专访W3C WebRTC Chair Bernard Aboba ...
- 抖音世界杯直播的低延迟是怎么做到的?
动手点关注 干货不迷路 世界杯已经结束了,梅西带领阿根廷时隔三十六年之后终于如愿捧杯.抖音直播提供的 4K 超高清超低延迟看播能力给亿万观众留下了深刻的印象,决赛的 PCU 达到 3700w+,在这样 ...
- 【翻译】安卓新播放器EXOplayer介绍
[翻译]安卓新播放器EXOplayer介绍 http://developer.android.com/guide/topics/media/exoplayer.html 前言: Playing vid ...
- 【FFmpeg】使用 FFmpeg 处理音视频格式转换流程 ( 解复用 | 解码 | 帧处理 | 编码 | 复用 )
FFmpeg 系列文章目录 [FFmpeg]Windows 搭建 FFmpeg 命令行运行环境 [FFmpeg]FFmpeg 相关术语简介 [FFmpeg]FFmpeg 相关术语简介 二 [FFmpe ...
- 【FFmpeg】FFmpeg 相关术语简介 ( 容器 | 媒体流 | 数据帧 | 数据包 | 编解码器 | 复用 | 解复用 )
文章目录 一.FFmpeg 简介 二.FFmpeg 相关术语 1.容器 2.媒体流 3.数据帧 4.数据包 5.编解码器 6.复用 7.解复用 博客资源 一.FFmpeg 简介 FFmpeg 是 &q ...
- 【Android 内存优化】自定义组件长图组件 ( 获取图像宽高 | 计算解码区域 | 设置图像解码属性 复用 像素格式 | 图像绘制 )
文章目录 一.获取图像真实宽高 二.计算解码区域 三.设置解码参数 内存复用 像素格式 四.图像绘制 五.执行效果 六.源码及资源下载 官方文档 API : BitmapRegionDecoder 在 ...
- 【转】软件工程能力漫谈:比质量更重要的,是项目管理能力
转自:软件工程能力漫谈:比质量更重要的,是项目管理能力 | ArchSummit 章淼老师在软件工程能力方面,积累了多年的经验,这个话题他之前也分享过多次,整体上内容有修改调整. 章老师博士毕业后在清 ...
- H.264软件解码器在PXA270平台上的优化
罗 嵘,何 苦 时间:2009年04月24日 摘 要: 研究了嵌入式系统中H.264 Baseline软件解码器设计和优化的问题,提出了四种有效的优化方法,并在PXA270平台上进行了测试.测试结果显 ...
- ExoPlayer用户手册
贴上原网址:https://google.github.io/ExoPlayer/guide.html 非完全翻译,有需要可以原网址自取,我发现网上也蛮多这个指导的翻译,可以去看看~ 开始啦!: Ex ...
最新文章
- 区块链隐私:交易还是计算?
- php 这样写日志 sleep你会了吗?
- Linux学习进阶!!
- 伺服电机要计算机控制,计控 - it610.com
- 龙芯购买MIPS指令集的授权
- elementos php开发,PHPWord
- 使用Macsome Audiobook Converter for Mac转换有声读物?
- 基于web的库存管理系统
- 怎么在html5中视频加字幕,视频转换王如何加字幕 在视频中添加文字的方法
- 【学习笔记】英文科技论文常见英语句式积累
- 设置wsl2桥接模式和设置ip
- JAVA-----乱码的处理 乱码的解决方法总结
- 命令行设置RTC alarm
- xp计算机管理下的服务显示不出来,WinXP系统任务栏不显示打开窗口的三种解决方案...
- 1.中心化账本缺点/哈希函数/什么是区块链
- 承接WEB应用开发、软件开发、网站开发
- matlab画简单长方形,matlab在图像中画长方形(框)
- 域名怎么卖:建站出售
- TestNG教程四TestNG用例失败重试
- Android - System.currentTimeMillis()计算时间差出现负数(NITZ和NTP机制学习)