android studio 集成ffmpeg_android下vulkan与opengles纹理互通

先放demo源码地址:https://github.com/xxxzhou/aoce 06_mediaplayer

效果图:

b172d5701dcfb9b537e603f1f3b98c11.png

主要几个点:

  • 用ffmpeg打开rtmp流。
  • 使用vulkan Compute shader处理yuv420P/yuv422P数据格式成rgba.
  • 初始化android surface为vulkan的交换链,把如上结果复制到交换链上显示。
  • 如果是opengles surface,如何不通过CPU直接把数据从vulkan复制到opengles里。

这个demo主要是为了验证用vulkan做GPGPU处理后,能输出到vulkan/opengles纹理,后续有可能的话,明年下半年业余时间在这项目用vulkan Compute shader移植GPUImage学习下,设计的运行平台是window/android,你可以在window平台用vscode(安装相应cmake/C++插件)运行查看调试过程,也可以用android studio打开里面的android文件夹,运行06_mediaplayer查看对应如上效果。

集成ffmpeg

window平台自己编译后放入aoce/thirdparty/ffmpeg/x64中,android 我直接用的这位同学编译好的https://github.com/xufuji456/FFmpegAndroid,你也可以在https://github.com/xxxzhou/aoce_thirdparty下载我整理好的。

如下目录放置就好。

590379d594a691235b127284656956a0.png

cmake里填写好相关window/android平台逻辑以后,你可以选择在window端直接用vscode,也可以用MVS打开cmake生成的sln文件,用android studio打开android文件夹,自动Sync gradle引用cmake并编译好相关C++项目。

相应ffmpeg播放器FMediaPlayer的实现我参照了android下的MediaPlayer的接口设计,主要是prepare这个接口让我意识到我在oeip不合理的地方,按照android下的MediaPlayer的接口重新实现了下ffmpeg里播放实现,现在只是简单走了下流程,后期还需要设计各个状态的转化。

用vulkan的Compute shader做GPGPU计算

这个是我在 Vulkan在Android使用Compute shader 就准备做的事,设想是用有序无环图来构建GPU计算流程,这个demo也算是简单验证下这个流程,后续会验证设计的多输入输出部分,如下构建。

    // 生成一张执行图
    vkGraph = AoceManager::Get().getPipeGraphFactory(gpuType)->createGraph();
    auto *layerFactory = AoceManager::Get().getLayerFactory(gpuType);
    inputLayer = layerFactory->crateInput();
    outputLayer = layerFactory->createOutput();
    // 输出GPU数据
    outputLayer->updateParamet({false, true});
    yuv2rgbLayer = layerFactory->createYUV2RGBA();
    // 生成图
    vkGraph->addNode(inputLayer)->addNode(yuv2rgbLayer)->addNode(outputLayer);

其中yuv2rgbLayer现在完成了nv12/yuv420P/yuy422P/yuyvI这些常见格式的解析,贴一段yuv420P的代码,CS代码需要配合线程组的划分来看,大家可以在github查看完整流程,YUV转换的代码主要注意尽量不要多个线程同时读或者写某个地址就好。

void 

用vulkan显示

Vulkan在Android使用Compute shader 里面,我使用native window完成vulkan展示与显示,但是很多时候,窗口并不是特定的,这个项目的设计目标之一也是无窗口使用Vulkan的Compute shader完成图像处理,后续高效支持对接android UI/UE4/Unity3d/window UI SDK都方便。

在这,我们需要查看运行结果,在这我们换种方式,不用native window,不然方便的android UI都不能用了,在native window的实现方式中,我们知道vulkan 交换链只需要ANativeWindow,相应的UI消息循环显示图像处理结果过程我们并不需要,通过查看 android图形框架指明了surface对应的C++类就是ANativeWindow,这样我们可以直接使用surface来完成vulkan 图像呈现工程,相关实现可以看vulkan模块下的vulkanwindow里的initsurface实现。

其中这个demo的window/andorid刷新部分有些不同,window利用本身主线程的窗口空闲时间,把ffmpeg解码线程上的数据经vulkan处理后复制到交换链当前显示图像中,而android本身的Surface没有找到GLSurfaceView.Renderer类似的onDrawFrame时机,所以在android vulkan中,处理与复制呈现给交换链全在ffmpeg解码线程上,不过android 下面的opengles显示又和window一样,主线程直接复制呈现,而ffmpeg解码线程用vulkan处理。

opengles显示

本来我想着用vulkan处理了,就能放弃opengl相关,但是至少现在还不现实,android端本身图像APP,以及对应android上的UE4/Unity3D,opengl es可能是更成熟的选择。

如何把vulkan的计算结果直接复制给opengles,通过文档 android文档AHardwareBuffer 其中有句话AHardwareBuffers可以绑定到EGL/OpenGL和Vulkan原语,通过相应提示用法VK_ANDROID_external_memory_android_hardware_buffer扩展/eglGetNativeClientBufferANDROID,我们继续搜索,查找到 google vulkantest 这里有段源码,详细说明了如何把vulkan里的vkImage绑定到AHardwareBuffer上,opengles部分根据eglGetNativeClientBufferANDROID查找到如何把AHardwareBuffer绑定到对应的opengles纹理上,这样我们通过vkImage-AHardwareBuffer-opengl texture的绑定,对应其封装在aoce_vulkan模块的hardwareImage类中。

AHardwareBuffer后续还可以继续挖,android原生平台提供的多媒体相关的SDK如摄像机,MediaPlay等都有AHardwareBuffer的身影,后续可以尝试直接把相关绑定到vulkan加快运算。

本人android开发并不熟悉,欢迎大家指正其中错误的地方。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值