增强axmol引擎视频播放之 - android视频播放支持

接续“增强axmol引擎视频播放之 - windows视频播放支持”,本文将描述如何在Android实现渲染视频到纹理。

一、调研

虚幻引擎实现方案:使用Android系统MediaPlayer,先将视频渲染到TextureSurface,再从TextureSurface读取RGBA像素数据,传给虚幻引擎Native层达到将视频纹理渲染到场景对象的目的。而axmol是MIT licensed开源引擎,自然不会使用虚幻引擎的方案,于是,通过多方调研,发现Google官方出品ExoPlayer2且作为androidx.media3的一部分发布,官方有很快上手入门的播放视频的demo,通过初步研究发现ExoPlayer2更灵活且开源。 于是决定使用ExoPlayer2并借鉴官方demo实现axmol的android视频纹理渲染支持。

google/ExoPlayer
https://github.com/androidx/media
二、实现步骤

获取ExoPlayer解码的原始视频NV12数据可行性
通过初步研究确定,ExoPlayer默认也只支持将视频渲染到Surface或SurfaceTexture, 但Google官方文档说明APIMediaCodec.configure 是支持ByteBuffer模式的,该API定义如下:

public void configure (MediaFormat format, 
                Surface surface, 
                MediaCrypto crypto, 
                int flags)

核心要点:第二个参数surface的解释:

Surface: Specify a surface on which to render the output of this decoder. Passnullassurfaceif the codec does not generate raw video output (e.g. not a video decoder) and/or if you want to configure the codec forByteBufferoutput.

大致意思是,如果想要底层适配解码器,将适配raw数据解码到ByteBuffer,则surface必须传null,这就是关键所在了。也就说明获取NV12是可行的。

  1. 尝试修改ExoPlayer支持ByteBuffer模式

下载仓库:https://github.com/google/ExoPlayer

通过分析MediaCodecVideoRenderer.java,发现ExoPlayer不持ByteBuffer模式,重写相关方法,获取的bytebuffer数据长度时1字节的原因如下:

MediaCodecVideoRenderer.java做了强制处理,即使通过ExoPlayer接口传入了空surface,内部也会创建PlaceHolderSurface,最后调用MediaCodec.configure时,surface参数始终不为空 。

尝试继承MediaCodecVideoRenderer.java发现有些需要控制MediaCodec模式的变量或方法是private 权限,于是只有完整复制一份MediaCodecVideoRenderer.java 在进行必要修改确保MediaCodec工作在ByteBuffer模式: AxmolVideoRenderer.java 放入引擎java代码目录,这样也能避免修改ExoPlayer package。

  1. 有了AxmolVideoRenderer.java,就可以通过如下方案实现AndroidMediaEngine:

Java: AxmolMediaEngine: 实现视频播放、暂停等功能,并将NV12 buffer传给Natvie
C++: AndroidMediaEngine实现MediaEngine的所有相关接口,通过JNI调用Java AxmolMediaEngine接口
MedaiEngine的跨平台策略和抽象工程模式,保证了ui::MediaPlayer(原ui::VideoPlayer)平台无关性。

具体代码请访问相关patch提交:Improve media-engine for android, linux by halx99 · Pull Request #1228 · axmolengine/axmol

你可能感兴趣的:(axmol,android,音视频,android,studio,axmol)