ffmpeg+安卓+yolo+RK3399部署

news/2024/7/11 1:02:24 标签: ffmpeg, android, YOLO

一次满足多项需求.
首先, 思路是, 使用ffmpeg解码本地mp4文件, 在无需任何其他改动的情况下, 就可以直接播放rtsp流, 这个是使用ffmpeg的好处.
ffmpeg本身是c语言的, 所以需要编译成jni的库,
https://note.youdao.com/s/6XeYftc
具体过程在这里, 用windows/macOS, Ubuntu应该都是可以的, 因为NDK对应了所有的平台, 另外值得注意的是内置的交叉编译工具的平台, 最新的版本的NDK是没有交叉编译工具链的, 这里应该叫交叉链编译工具, 所以要下载21版本的NDK
编译好的ffmpeg lib, 有两部分, 头文件跟库文件, 库文件又分32位平台跟64位平台.
在这里插入图片描述
像这样整理好目录即可.
整个ffmpeg的文件夹, 放在带jni c++功能的安卓项目的cpp文件夹中, 这里记住, cpp文件夹就放c/cpp语言的jni代码, java目录就放java/kt代码.
接下来是rknn_api
历史经验告诉我, 如果rknn的应用库如果跟驱动版本差异大, 会有一些不知名的问题, 所以理论上需要让他们保持一致
在这里插入图片描述
上图中驱动版本偏低, 而且目前github上最新的版本是1.7.5
这个跟rknn的库必须配套, 好在rk在这方面做得还挺好, github更新挺及时的.
去rk3399pro对应的npu的github上, clone这个仓库下来.
https://github.com/airockchip/RK3399Pro_npu
它的README说得听清楚了, 如果需要升级, 就应该分清楚, 你的npu的平台是基于usb的架构,还是pcie, 我一开始还以为没可能不同代理商使用不同方案吧, 结果发现还真是.

那么如何查看当前板子是usb的, 还是pcie的呢?
在这里插入图片描述
就是无论是ubuntu系统, 还是安卓系统, 通过shell进去, 安卓就是adb 的shell, 然后运行npu_transfer_proxy devices
如果你是usb的npu, 可能会提示你没有npu, 这个时候别慌, 先点一根烟…
然后which命令, 找找npu_transfer_proxy这个命令是否存在,存在的话, 就用npu_transfer_proxy & 让它后台跑起来, 然后再使用npu_tranfser_proxy devices查看自己npu 的类型.
分清楚硬件上, npu是什么类型之后, 如果是usb, 对应的驱动仓库的文件夹就是npu_firmware/npu_fw, 如果是pcie, 就是npu_pcie_fw, 然后看板子上跑的是啥操作系统是ubuntu, 就在ubuntu上搜一下有没有boot.img这个文件, 一般在/usr/share/npu_fw或者/usr/share/npu_pcie_fw下面, 找到之后, 把仓库里面的5个文件都复制过去, 建议先把原来的备份一下, 这样万一出问题也可以后悔.

在这里插入图片描述

接下来, 尝试找到一个可执行程序, 叫做npu_upgrade, 理论上应该也在/usr/share/npu_fw目录下面, 然后手动更新一下npu:
sudo ./npu_upgrade MiniLoaderAll.bin uboot.img trust.img boot.img

过几秒钟, 就会提示你升级完成了. 这个时候驱动的部分就ok了, 安卓的做法也是一样, 只不过安卓的npu的路径在/vendor/etc/npu_fw 下面.

接下来回到安卓的项目目录, rknn_api稍微复杂一点, 因为分为安卓/Linux, 也有arm64-v8a跟armeabi-v7a的差别, 不过不用慌, 记住一点, 安卓/Linux好选, 3399pro是基于64位的架构, 所以都以arm64-v8a作为目标.
在安卓项目的cpp文件夹, 建一个目录叫libs, 然后分别把rknn_api的库复制进去, 我这里仅仅复制了arm64的库

rknn_api的头文件rknn_api.h就直接放在include目录即可.

在这里插入图片描述

 cmake_minimum_required(VERSION 3.22.1)
# cmake_minimum_required(VERSION 3.18.1)
# cmake_minimum_required(VERSION 3.6.4111459)

project("myapplicationffmpegplayerkt")

set(FFMPEG ${CMAKE_SOURCE_DIR}/ffmpeg)  # ffmpeg的路径
# set(RTMP ${CMAKE_SOURCE_DIR}/rtmp) # rtmp的路径
set(RKNN ${CMAKE_SOURCE_DIR}/rknn)

include_directories(${RKNN}/include)  # 导入rknn的头文件
include_directories(${FFMPEG}/include)  # 导入ffmpeg的头文件

# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${FFMPEG}/libs/${CMAKE_ANDROID_ARCH_ABI}")  # 导入ffmpeg的库文件
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${RTMP}/libs/${CMAKE_ANDROID_ARCH_ABI}") # rtmp库指定

file(GLOB src_file *.cpp)   # 查找所有的cpp源文件, 相当于把所有的cpp都纳入编译

add_library(
        native-lib   # 生成的so库的名字
        SHARED       # 动态库
        ${src_file}) # 所有的cpp文件

target_link_libraries(
        native-lib  # 生成的so库的名字

        ${RKNN}/libs/${ANDROID_ABI}/librknn_api.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libavcodec.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libavdevice.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libavfilter.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libavutil.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libavformat.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libswresample.so
        ${FFMPEG}/libs/${ANDROID_ABI}/libswscale.so
        # 引入的库不分先后
        # -Wl,--start-group
        # avcodec avfilter avformat avutil swresample swscale
        # -Wl,--end-group

        log # 引入log库
        z # 引入z库
        # rtmp # rtmp 后面会专门介绍 rtmp交叉编译+FFmpeg结合编译

        EGL
        GLESv2
        android # 引入android库
        OpenSLES # 引入OpenSLES库
)

CMakLists.txt长这样.
引入链接库的方法就是直接指向库文件就行.
安卓工程中, 唯一值得一提的就是修改app下面的build.gradle了.

在这里插入图片描述

这里要使用arm64-v8a提示ndk的交叉编译器编译出来的jni库, 只需要arm64的, 因为3399是arm64平台, 理论上我 猜测, 因为安卓我确实不熟, 我猜测, 也可以用add语法, 加入其他平台的, 编译的时候会一起打包到apk文件中, 到时候应用层也好, 系统层也好, 能跟据自己的系统类型, 来选择对应的库.
接着通过jni运行rknn的例程, 就会发现, 驱动层跟应用层都已经升级到了1.7.5:
在这里插入图片描述
下面的示例代码是用一张原始640x640图片做的输入, ffmpeg融入的部分参考我github里面的ktplayer, 因为涉及商用利益冲突, 就不放完整的代码了.

https://github.com/MontaukLaw/rknn_android_3399_pro

承接各类部署工程, 目前熟悉的平台有, RK1106, 1126, 3588, 3399pro, 3568, 海思3516DV300(仅限推拉流), 有兴趣各位客官老爷们站内信.


http://www.niftyadmin.cn/n/5091844.html

相关文章

【算法1-4】递推与递归-P1002 [NOIP2002 普及组] 过河卒

## 题目描述 棋盘上 A 点有一个过河卒,需要走到目标 B 点。卒行走的规则:可以向下、或者向右。同时在棋盘上 C 点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为“马拦过河卒”。 棋盘用坐标表示&#…

奖励函数是平稳的是什么意思

在强化学习中,"奖励函数是平稳的"通常指的是奖励信号(reward signal)在不同时间步骤或状态下是稳定的,即其统计性质在整个学习过程中不发生明显的变化。这是一种有关奖励函数的性质,有助于学习算法更好地理解…

探索服务器的无限潜能:创意项目、在线社区与更多可能

文章目录 1. 创意项目的孵化器1.1 托管你的应用1.2 测试和开发1.3 制定和实施你的计划 2. 构建在线社区2.1 自定义社交网络2.2 数据控制2.3 扩展和改进 3. 其他创意可能性3.1 博客和媒体网站3.2游戏服务器3.3 云存储3.4 数据分析3.5 远程办公 结论 🎉欢迎来到Java学…

CVPR 2023 | 数据驱动的解释对分布外数据具有鲁棒性吗?

论文链接: https://arxiv.org/abs/2303.16390 代码链接: https://github.com/tangli-udel/DRE 01. 研究背景:数据驱动的解释对分布外数据具有鲁棒性吗? 近年来,将黑盒机器学习(ML)模型用于高风…

ROS-6.参数的使用

参数的使用 参数服务结构命令行的使用方式运行小海龟命令介绍查看参数获取参数值设置参数保存参数到文件从文件导入参数 通过程序操作创建节点修改cmake编译运行 参数服务结构 ros中存在参数服务管理服务,管理这所有参数,所有节点剋订阅和发布这些节点 …

动态链接:程序内部的“共享单车”

目录 背景 链接可以分动、静,共享运行省内存 地址无关很重要,相对地址解烦恼 PLT 和 GOT,动态链接的解决方案 小结 背景 我们知道,程序的链接,是把对应的不同文件内的代码段,合并到一起,成…

基于SpringBoot+vue的汽车销售管理系统

文章目录 项目介绍主要功能截图:登录首页新订单客户管理添加库存车辆库存管理报表管理员工管理 部分代码展示设计总结项目获取方式 🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简…

LangChain结合milvus向量数据库以及GPT3.5结合做知识库问答之一 --->milvus的docker compose安装

https://github.com/milvus-io/milvus/releaseshttps://github.com/milvus-io/milvus/releases 以下步骤均在Linux环境中进行: 将milvus-standalone-docker-compose.yml下载到本地。 1、新建一个目录milvus 2、将milvus-standalone-docker-compose.yml放到milvu…