flutter封装IjkPlayer播放器原理分析
flutter封装IjkPlayer播放器原理分析
初衷:出于flutter尽可能的投入实际应用场景,觉得有必要解决播放器的问题,用flutter将控制界面(播放、暂停、进度条等操作)统一,而播放器(视频编解码、渲染)采用原生方案。为此进行了一些探索。
播放器封装,控制界面采用flutter,而渲染界面使用原生View,对于flutter使用原生界面,官方提供了两种方式,一种是PlatformView,另外一种是Texture。(其中PlatformView区分Android和iOS,在Android平上上叫做 AndroidView,而在iOS平台,叫UIKitView。)
下面就两种方式分别介绍一下,最后看看个人封装公司播放器遇到的一系列问题。
一、PlatformView在android平台的基本使用
写了个Demo怎么使用AndroidView生成和调用原生TextView,及利用id操作原生view
Demo地址:https://github.com/stdroom/PlatformViewTest.git
核心步骤:
- 在Android工程中编写并注册原生组件
- 实现原生组件PlatformView提供原生view
- 创建PlatformViewFactory用于生成PlatformView
- 创建FlutterPlugin用于注册原生组件
- 在Flutter工程中调用原生View,创建AndroidView组件并告诉它组件的注册名称即可
二、flutter外接纹理的使用(根据fijkplayer播放器封装原理介绍)
- 项目地址:https://github.com/befovy/fijkplayer
- 项目文档:https://fijkplayer.befovy.com/docs/zh/
- 参考链接:https://juejin.cn/post/6844904071296450567
1、外接纹理关键步骤:
原理:通过TextureRegistry.SurfaceTextureEntry 这个entry拿到的这个surfaceTexture,是塞给了一个Surface,然后视频播放器将一帧帧的数据画到Surface上,这样,就能够实现数据共享了,也就是说,flutter端通过entry的那个textureId,就能用Texture展示数据了。
1.1 native代码层生成textureId
long setupSurface() {
setup();
if (mSurfaceTextureEntry == null) {
TextureRegistry.SurfaceTextureEntry surfaceTextureEntry = mEngine.createSurfaceEntry();
mSurfaceTextureEntry = surfaceTextureEntry;
if (surfaceTextureEntry != null) {
mSurfaceTexture = surfaceTextureEntry.surfaceTexture();
mSurface = new Surface(mSurfaceTexture);
}
if (!mJustSurface) {
mIjkMediaPlayer.setSurface(mSurface);
}
}
if (mSurfaceTextureEntry != null)
return mSurfaceTextureEntry.id();
else {
Log.e("FIJKPLAYER", "setup surface, null SurfaceTextureEntry");
return 0;
}
}
1.2 flutter层用textureId创建Texture即可
Widget buildTexture() {
Widget tex = _textureId > 0 ? Texture(textureId: _textureId) : Container();
if (_degree != 0 && _textureId > 0) {
return RotatedBox(
quarterTurns: _degree ~/ 90,
child: tex,
);
}
return tex;
}
2、项目结构
3、代码时序图
三、公司播放器KoolMediaPlayer封装实现及遇到的问题
项目地址:git@git.koolearn-inc.com:android/KooFlutterPlayer.git
- 拆解KoolMediaPlayer jar中的类到java中,测试能否正常运行
- 搭建KooFlutterPlayer插件工程
- 参考仿照Fijkplayer项目编辑Android和flutter层代码
- 集成KoolMediaPlayer
- 编译发现64位问题,协调视频组处理,未果
- 编译32位,然后将32的flutter.so拷贝出来到32目录下,编译成功
- 找到一个mp4视频,使用ffmpeg命令转m3u8视频,放到电脑上
- 运行发现声音响一下就结束了,没有图像
- 替换成fijkplayer发现声音可以正常播放,但没有图像 下一步打算:调试fijkplayer成功之后,再继续看看KoolMediaPlayer
遇到的核心问题:
- 播放器库没有64位的so
- ios播放器集成不太容易
四、本文用到的一些重要命令
相关命令 flutter build apk --target-platform android-arm
flutter create --org com.koolearn.flutterplayer --platforms=android,ios -a java -i objc --template=plugin --description "A Flutter plugin for using devices informations in Android" KooFlutterPlayer
ffmpeg mp4 转m3u8:
ffmpeg -i aliyunmedia.mp4 -f segment -segment_time 60 -segment_format mpegts -segment_list /Users/leixun/Downloads/videofolder/video_name.m3u8 -c copy -bsf:v h264_mp4toannexb -map 0 /Users/leixun/Downloads/videofolder/video_name-%04d.ts
adb 连接网易mumu :
adb kill-server && adb server && adb shell