说明:以下内容均为基于网络公开的ExoPlayer官方源码进行的解读
OldExo源码本体也是来源于Github并非涉及任何公司相关任何代码
本文主要针对于,自己的设备解码能力(比如底层集成ffmpeg 、qti、android 、需要付费的格式等等)大于ExoPlayer自己封装的固有Extractor,基于现在Android架构通俗的来说,就是MediaPlayer可以播,但是ExoPlayer播不了的情况。
底层集成的优势在于,不需要每个app都来集成,那样每个app都非常庞大,工作繁琐也很难以统一,第三方app使用系统播放器也没有相关的能力。
ExoPlayer现在已被集成到Media3.AndroidX,但仍然没有解决此问题。
通过寻找多年历史的蛛丝马迹,我们可以看到,是因为每台设备的解码能力不同,而且在我们实际开发中,会发现有些文件duration等一些参数存在问题,需要兼容。ExoPlayer作为一个通用播放器不可能面面俱到,故舍弃了此方案,选用了需要明确指出Extractor的方案。
该方案会导致,明明底层软硬解支持的情况下,却会因为封装视频container组合的不符合Exo
固有的Extractor组合直接抛出失败异常,一般呈现Source Error非常模糊,这一点需要这篇文章的人相信已经有了深刻的理解
ExoPlayer现版本,需要指定Extractor,或者通过ffmpeg拓展格式,但这回导致设备底层原本支持的格式会出现不支持,如果你是做自己的设备,比如手机、平板、车载等,你是明确知道能力的。
核心修改思想如下,咱们长话短说,下面是我简化整理的,ExoPlayer解码过程,和codec解码过程的区别,其核心就是替换的Extractor的read过程,也就是将inputBufff填满的过程。所以如果想打通就必须再次进入Android.MediaExtractor
所以说我们想要对接底层的解码能力,就必须换掉ExoExtractor,不需要再去遍历sniff,换为通用的MediaExtractor,让其走到底层,自行去寻找分发软硬解能力。
再根据上述我整理的api调用图,可以看到,Extractor在exo中是通过sniff打分来判断是执行哪个真正的Extractor。经过层层封装最终其实在MediaSource中创建最初的Factory。所以
思路1:就是替换整个MediaSoure,使其直接走codec原始调用。
思路2:是自定义通用Extractor,sniff放到最前面且始终返回true,再对接Extractor.read
目前我们先实现思路1
想要既使用ExoPlayer的Api又对接底层解码能力的记录 ,我们需要改掉read填充buffer的部分
FrameworkSampleSource sampleSource = new FrameworkSampleSource(
context, uri, null);
MediaCodecVideoTrackRenderer videoRenderer = new MediaCodecVideoTrackRenderer(context,
sampleSource, MediaCodecSelector.DEFAULT, MediaCodec.VIDEO_SCALING_MODE_SCALE_TO_FIT, 5000,
mainHandler, player, 50);
MediaCodecAudioTrackRenderer audioRenderer = new MediaCodecAudioTrackRenderer(sampleSource,
MediaCodecSelector.DEFAULT, null, true, mainHandler, player,
AudioCapabilities.getCapabilities(context), AudioManager.STREAM_MUSIC);
TrackRenderer textRenderer = new TextTrackRenderer(sampleSource, player,
mainHandler.getLooper());
FrameworkSampleSource相关代码已经在ExoPlayer,Github上被删除,先贴上谷歌历史代码,基于此思路基本可以打通,就整合代码替换繁琐,后续补充详细整改资源,
https://github.com/RexSuper/ExoPlayeOldDemo