可以参考这位大哥的教程:
https://zhuanlan.zhihu.com/p/377407799
<1>下载opencv4.5.5源码 下载地址
<2>下载ffmpeg4.4.2源码 下载地址
每一个版本的opencv 都有对应的ffmpeg 的版本 ,opencv 目录
opencv-4.5.5/3rdparty/ffmpeg
下 ffmpeg.cmake里的ffmpeg_version.cmake可以看出对应的版本
<3>下载ndk 23.1.7779620 下载地址
下载ndk网站https://developer.android.com/ndk/downloads
<4>下载android sdk
Sdk通过android studio下载或者通过sdkmanager
https://developer.android.com/studio/command-line/sdkmanager
#path使用指定的 SDK 路径 sdkmanager --sdk_root=path "platform-tools" "platforms;android-24" "build-tools;30.0.2"
备注:不需要生成libopencv_java4.so,就可以不用设置android sdk,把BUILD_ANDROID_PROJECTS和BUILD_FAT_JAVA_LIB、BUILD_JAVA都关掉。
编译ffmpeg根据自己ndk 路径设置
#根据自己ndk 路径设置
export TOOLCHAIN=/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64
export TARGET=aarch64-linux-android
export API=24
export AR=$TOOLCHAIN/bin/llvm-ar
export CC=$TOOLCHAIN/bin/$TARGET$API-clang
export AS=$CCexport CXX=$TOOLCHAIN/bin/$TARGET$API-clang++
export LD=$TOOLCHAIN/bin/ld
export RANLIB=$TOOLCHAIN/bin/llvm-ranlib
export STRIP=$TOOLCHAIN/bin/llvm-strip
./configure \
--prefix=./build \
--target-os=android \
--enable-shared \
--enable-ffmpeg \
--enable-cross-compile \
--enable-ffplay \
--enable-ffprobe \
--enable-demuxer=rtsp \
--enable-demuxer=rtp \
--enable-protocol=tcp \
--enable-protocol=udp \
--enable-network \
--disable-doc \
--disable-avdevice \
--disable-doc \
--disable-symver \
--disable-asm \
--arch=aarch64 \
--disable-stripping \
--enable-avresample \
--enable-small \
--enable-gpl --disable-debug \
--cc=$CC \
--as=$AS \
--extra-cflags="-fpic"
#有的教程cflags 添加了这些,不理解什么意思,自己编译没有加这些cflag
--extra-cflags=$CFLAG
CFLAG="-D__ANDROID_API__=$API -U_FILE_OFFSET_BITS -DBIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD -Os -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm"
编译opencv
<1> 更改opencv-4.5.5目录下的CMakeLists.txt
1.让with_ffmpeg 默认开启
#注释这三行
## OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" (NOT ANDROID)
# VISIBLE_IF NOT IOS AND NOT WINRT
# VERIFY HAVE_FFMPEG)
#添加下面这一行
OCV_OPTION(WITH_FFMPEG "Include FFMPEG support" ON
VISIBLE_IF NOT IOS AND NOT WINRT
VERIFY HAVE_FFMPEG) #默认开启
2.添加 find_package(PkgConfig QUIET)
# ----------------------------------------------------------------------------
# CHECK FOR SYSTEM LIBRARIES, OPTIONS, ETC..
# 加载pkg-config(环境变量默认没有,所以这个地方的条件进不去)
# CMAKE_CROSSCOMPILING 这是交叉编译变量,所有开启交叉编译后这个变量是有值的
# ----------------------------------------------------------------------------
if(UNIX)
if(NOT APPLE_FRAMEWORK OR OPENCV_ENABLE_PKG_CONFIG)
if(CMAKE_CROSSCOMPILING AND NOT DEFINED ENV{PKG_CONFIG_LIBDIR} AND NOT DEFINED ENV{PKG_CONFIG_SYSROOT_DIR}
AND NOT OPENCV_ENABLE_PKG_CONFIG
)
if(NOT PkgConfig_FOUND)
message(STATUS "OpenCV disables pkg-config to avoid using of host libraries. Consider using PKG_CONFIG_LIBDIR to specify target SYSROOT")
elseif(OPENCV_SKIP_PKG_CONFIG_WARNING)
message(WARNING "pkg-config is enabled in cross-compilation mode without defining of PKG_CONFIG_LIBDIR environment variable. This may lead to misconfigured host-based dependencies.")
endif()
elseif(OPENCV_DISABLE_PKG_CONFIG)
if(PkgConfig_FOUND)
message(WARNING "OPENCV_DISABLE_PKG_CONFIG flag has no effect")
endif()
else()
find_package(PkgConfig QUIET)
endif()
endif()
#-------------------------------添加下一行
find_package(PkgConfig QUIET)
3.添加ANDROID 条件(不改也无所谓),这行只是一个展示
# ========================== VIDEO IO ==========================
status("")
status(" Video I/O:")
if(WITH_1394 OR HAVE_DC1394_2)
status(" DC1394:" HAVE_DC1394_2 THEN "YES (${DC1394_2_VERSION})" ELSE NO)
endif()
if(WITH_FFMPEG OR HAVE_FFMPEG)
if(OPENCV_FFMPEG_USE_FIND_PACKAGE)
status(" FFMPEG:" HAVE_FFMPEG THEN "YES (find_package)" ELSE "NO (find_package)")
elseif(WIN32 OR ANDROID) ####在这一行添加OR ANDROID
status(" FFMPEG:" HAVE_FFMPEG THEN "YES (prebuilt binaries)" ELSE NO)
else()
status(" FFMPEG:" HAVE_FFMPEG THEN YES ELSE NO)
endif()
status(" avcodec:" FFMPEG_libavcodec_VERSION THEN "YES (${FFMPEG_libavcodec_VERSION})" ELSE NO)
status(" avformat:" FFMPEG_libavformat_VERSION THEN "YES (${FFMPEG_libavformat_VERSION})" ELSE NO)
status(" avutil:" FFMPEG_libavutil_VERSION THEN "YES (${FFMPEG_libavutil_VERSION})" ELSE NO)
status(" swscale:" FFMPEG_libswscale_VERSION THEN "YES (${FFMPEG_libswscale_VERSION})" ELSE NO)
status(" avresample:" FFMPEG_libavresample_VERSION THEN "YES (${FFMPEG_libavresample_VERSION})" ELSE NO)
endif()
<2> 修改opencv-4.5.5/modules/videoio/cmake目录下的detect_ffmpeg.cmake
1.这一条可以不用管,只是加了一个注释
# --- FFMPEG --- 通过find_pack查找ffmpeg 编译安装的ffmpeg 默认不支持cmake查找,默认是通过pkg-config查找
if(NOT HAVE_FFMPEG AND OPENCV_FFMPEG_USE_FIND_PACKAGE)
if(OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "1" OR OPENCV_FFMPEG_USE_FIND_PACKAGE STREQUAL "ON")
set(OPENCV_FFMPEG_USE_FIND_PACKAGE "FFMPEG")
endif()
find_package(${OPENCV_FFMPEG_USE_FIND_PACKAGE}) # Required components: AVCODEC AVFORMAT AVUTIL SWSCALE
if(FFMPEG_FOUND OR FFmpeg_FOUND)
set(HAVE_FFMPEG TRUE)
endif()
endif()
#windows 去下载dll
# if(NOT HAVE_FFMPEG AND WIN32 AND NOT ARM AND NOT OPENCV_FFMPEG_SKIP_DOWNLOAD)
# include("${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/ffmpeg.cmake")
# download_win_ffmpeg(FFMPEG_CMAKE_SCRIPT)
# if(FFMPEG_CMAKE_SCRIPT)
# include("${FFMPEG_CMAKE_SCRIPT}")
# set(HAVE_FFMPEG TRUE)
# set(HAVE_FFMPEG_WRAPPER TRUE)
# endif()
# endif()
2.指定ffmepg库路径
因为指定了PKG_CONFIG_PATH这个环境变量后,cmake 通过pkg-config ,然后pkg_check_modules 找不出库的全路径(为什么,目前也没有弄清楚)
根据自己编译ffmpeg 库目录设置
-------------------定位到这行-------------------
if(NOT HAVE_FFMPEG AND PKG_CONFIG_FOUND)
#函数定义在cmake/OpenCVUtils.cmake
ocv_check_modules(FFMPEG libavcodec libavformat libavutil libswscale)
#这个地方为什么要手动指定,没有弄清楚
#指定PKG-CONFIG-PATH 后pkgcfg_lib_xxxx_xxxx是一个no found的状态
#FFMPEG_LIBRARY_DIRS 这变量是pkg_check_modules找出来的
set(pkgcfg_lib_FFMPEG_avformat ${FFMPEG_LIBRARY_DIRS}/libavformat.a)
set(pkgcfg_lib_FFMPEG_avcodec ${FFMPEG_LIBRARY_DIRS}/libavcodec.a)
set(pkgcfg_lib_FFMPEG_avutil ${FFMPEG_LIBRARY_DIRS}/libavutil.a)
set(pkgcfg_lib_FFMPEG_swscale ${FFMPEG_LIBRARY_DIRS}/libswscale.a)
set(pkgcfg_lib_FFMPEG_swresample ${FFMPEG_LIBRARY_DIRS}/libswresample.a)
#手动指定了后需要重新设置FFMPEG_LIBRARIES 、FFMPEG_LINK_LIBRARIES这两个变量
set(FFMPEG_LIBRARIES ${pkgcfg_lib_FFMPEG_avformat} ${pkgcfg_lib_FFMPEG_avcodec} ${pkgcfg_lib_FFMPEG_avutil} ${pkgcfg_lib_FFMPEG_swscale} ${pkgcfg_lib_FFMPEG_swresample})
set(FFMPEG_LINK_LIBRARIES ${FFMPEG_LIBRARIES})
if(FFMPEG_FOUND)
ocv_check_modules(FFMPEG_libavresample libavresample) # optional
#-------------------------------也要重新设置----------------------------
set(pkgcfg_lib_FFMPEG_libavresample_avresample ${FFMPEG_LIBRARY_DIRS}/libavresample.a)
set(FFMPEG_libavresample_LIBRARIES ${pkgcfg_lib_FFMPEG_libavresample_avresample})
#----------------------------------------------------------------------
if(FFMPEG_libavresample_FOUND)
list(APPEND FFMPEG_LIBRARIES ${FFMPEG_libavresample_LIBRARIES})
list(APPEND _used_ffmpeg_libraries libavresample)
endif()
set(HAVE_FFMPEG TRUE)
else()
set(_missing_ffmpeg_libraries "")
foreach (ffmpeg_lib ${_required_ffmpeg_libraries})
if (NOT FFMPEG_${ffmpeg_lib}_FOUND)
list(APPEND _missing_ffmpeg_libraries ${ffmpeg_lib})
endif()
endforeach ()
message(STATUS "FFMPEG is disabled. Required libraries: ${_required_ffmpeg_libraries}."
" Missing libraries: ${_missing_ffmpeg_libraries}")
unset(_missing_ffmpeg_libraries)
endif()
endif()
3.下面会编译测试代码,但是会编译失败,然后会设置HAVE_FFMPEG FALSE,所以要注释这一行
为什么会编译失败(还没有理解,好像是库没有链接上)(这个代码编译通过一次,然后第二次重新改cmake 后然后就一直失败)
if(HAVE_FFMPEG AND NOT HAVE_FFMPEG_WRAPPER AND NOT OPENCV_FFMPEG_SKIP_BUILD_CHECK)
message(FFMPEG_LIBRARIES:::${FFMPEG_LIBRARIES})
try_compile(__VALID_FFMPEG
"${OpenCV_BINARY_DIR}"
"${OpenCV_SOURCE_DIR}/cmake/checks/ffmpeg_test.cpp"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${FFMPEG_INCLUDE_DIRS}"
"-DLINK_LIBRARIES:STRING=${FFMPEG_LIBRARIES}"
OUTPUT_VARIABLE TRY_OUT
)
if(NOT __VALID_FFMPEG)
#message(FATAL_ERROR "FFMPEG: test check build log:\n${TRY_OUT}")
message(STATUS "WARNING: Can't build ffmpeg test code")
#--------------------这一行-----------------------------
#set(HAVE_FFMPEG FALSE)
endif()
endif()
<3>修改opencv-4.5.5/modules/java/CMakeLists.txt
因为build android project的时候会出现ndk not configure,
配置了ndk环境变量ANDROID_NDK、NDK_ROOT 还是会出现这个错误(大概是gradle文件配置的问题)
所以注释掉build android project
不能直接通过BUILD_ANDROID_PROJECTS OFF,关掉后里面就不会生成libopencv_java4.so
*****************定位到这一行*****************
if(ANDROID)
message(" don't generates android project")
#add_subdirectory(android_sdk) # generates ${the_module}_android target
else()
add_subdirectory(jar) # generates ${the_module}_jar target
endif()
<4>设置环境变量
PKG_CONFIG_PATH
这个环境变量是让pkg-config去找到自己刚刚编译的ffmpeg 库
ANDROID_HOME
、ANDROID_SDK_ROOT
、ANDROID_SDK
这三个环境变量是android sdk的,不需要libopencv_java4.so可以不需要指定
export PKG_CONFIG_PATH=/root/tang/ndk/ffmpeg-4.4.1/build/lib/pkgconfig
export ANDROID_HOME=/root/tang/ndk/cmdline-tools/android_sdk
export ANDROID_SDK_ROOT=/root/tang/ndk/cmdline-tools/android_sdk
export ANDROID_SDK=/root/tang/ndk/cmdline-tools/android_sdk
备注:
另一种编译libopencv_java4.so的方法(通过ant)
这种需要安装java环境,还要改cmake文件。(这里面没有介绍0
#下面通过ant 编译需要设置的(当前不需要)
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export ANDROID_NDK=/root/tang/ndk/android-ndk-r23b
export NDK_ROOT=/root/tang/ndk/android-ndk-r23b
set(JAVA_AWT_LIBRARY "$ENV{JAVA_HOME}/lib/libjawt.so")
set(JAVA_JVM_LIBRARY "$ENV{JAVA_HOME}/lib/server/libjvm.so")
set(JAVA_INCLUDE_PATH "$ENV{JAVA_HOME}/include")
set(JAVA_INCLUDE_PATH2 "$ENV{JAVA_HOME}/include/linux")
set(JAVA_AWT_INCLUDE_PATH "$ENV{JAVA_HOME}/include")
执行编译
CMAKE_TOOLCHAIN_FILE
、ANDROID_NDK
这两个路径根据自己ndk目录设置
CMAKE_INSTALL_PREFIX
这个是自己的make install 后的目录
cmake -D CMAKE_TOOLCHAIN_FILE=/root/tang/ndk/android-ndk-r23b/build/cmake/android.toolchain.cmake \
-D CMAKE_INSTALL_PREFIX=./mm_install \
-D CMAKE_BUILD_TYPE=RELEASE \
-D ANDROID_ABI=arm64-v8a \
-D ANDROID_PLATFORM=24 \
-D ANDROID_NDK=/root/tang/ndk/android-ndk-r23b \
-D BUILD_ANDROID_PROJECTS=ON \
-D BUILD_ANDROID_EXAMPLES=OFF \
-D BUILD_SHARED_LIBS=OFF \
-D BUILD_FAT_JAVA_LIB=ON \
-D BUILD_JAVA=ON \
-D ANDROID_STL=c++_static \
-D ANDROID_ARM_NEON=ON \
-D WITH_FFMPEG=ON \
-D CMAKE_CXX_FLAGS="-llog" ..
#要确认videoIO 模块是否是ON
make -jnproc
make install
备注:
如果编译过程中找不到ffmpeg,就需要更改ffmpeg里pkg-config文件把里面的路径改成绝对路径
因为ffmpeg库 的目录指定的是绝对路径,所以更改sdk/native/jni/abi-arm64-v8a/OpenCVModules.cmake
我是把ffmepg库移入到sdk/native/3rdparty/libs/arm64-v8a
这个目录
======================定位到这个地方======================
set_target_properties(ocv.3rdparty.ffmpeg PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "HAVE_FFMPEG"
INTERFACE_LINK_LIBRARIES "/root/tang/ndk/ffmpeg-4.4.1/build/lib/libavformat.a;/root/tang/ndk/ffmpeg-4.4.1/build/lib/libavcodec.a;/root/tang/ndk/ffmpeg-4.4.1/build/lib/libavutil.a;/root/tang/ndk/ffmpeg-4.4.1/build/lib/libswscale.a;/root/tang/ndk/ffmpeg-4.4.1/build/lib/libswresample.a;/root/tang/ndk/ffmpeg-4.4.1/build/lib/libavresample.a"
)
======================改成下面的======================
#我是把ffmpeg库放在和liblibprotubuf.a一个目录
set_target_properties(ocv.3rdparty.ffmpeg PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "HAVE_FFMPEG"
INTERFACE_LINK_LIBRARIES "${_IMPORT_PREFIX}/sdk/native/3rdparty/libs/${ANDROID_ABI}/libavformat.a;${_IMPORT_PREFIX}/sdk/native/3rdparty/libs/${ANDROID_ABI}/libavcodec.a;${_IMPORT_PREFIX}/sdk/native/3rdparty/libs/${ANDROID_ABI}/libavutil.a;${_IMPORT_PREFIX}/sdk/native/3rdparty/libs/${ANDROID_ABI}/libswscale.a;${_IMPORT_PREFIX}/sdk/native/3rdparty/libs/${ANDROID_ABI}/libswresample.a";
)
或者删除下面位置的**\$**,然后自己在工程里面链接ffmpeg 库
set_target_properties(opencv_videoio PROPERTIES
INTERFACE_LINK_LIBRARIES "opencv_core;opencv_imgproc;opencv_imgcodecs;opencv_core;opencv_imgproc;opencv_imgcodecs;$;$;$;$;$;$;$"
)
觉得有用就点个赞
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)