ffmepg-4.1 + android + opencv310,使用videocapture

 

 

项目目的是为了能够再android 上面通过opencv 的cv::VideoCapture 读取视频,但实际上opencv 不支持这样做,具体是通过cmake 中设置的;opencv 读视频默认是通过 ffmpeg 实现的,调研发现 ffmepg 可以编译成android 的库,所以编译步骤是:编译android 版本的 ffmpeg,编译 包含 ffmepg  的 opencv

环境条件:Android的 ABI= arm64-v8,API = android-27(android 8.1)

编译器:android-ndk-r16

  1. 编译android 版本的 ffmpeg

参考了 https://github.com/eudora-jia/android-opencv-ffmpeg 

上面作者使用的是ffmpeg 编译的是动态库,为了方便测试,这里编译成动态库;为了编译方便,直接下载的ffmpeg 编译脚本configure 下 使用build.sh 进行编译

make clean
#自己的ndk路径(相对路径或绝对路径都可以)
export MY_TOOLCHAIN=/home/panxiaogong/3rdparty/android-ndk-r16b/myarm64-andorid-toolchain
#最终的库生成位置为上一级目录的 simplefflib
export PREFIX=../simplefflib
build_one(){
./configure  --target-os=android  --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--disable-x86asm \
--disable-network \
--disable-doc  \
--arch=aarch64 \
--cc=$MY_TOOLCHAIN/bin/clang \
--cxx=$MY_TOOLCHAIN/bin/clang++ \
--disable-stripping \
--nm=$MY_TOOLCHAIN/aarch64-linux-android/bin/nm \
--sysroot=$MY_TOOLCHAIN/sysroot \
--enable-jni \
--enable-mediacodec \
--enable-avresample \
--enable-gpl --enable-shared  --enable-small \
--disable-ffprobe --disable-ffplay   --disable-debug \
--extra-cflags="-fPIC -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -D__ANDROID_API__=21     -march=armv8-a"
}

#make
#make install
build_one

其中我是用的是ndk 的独立工具链,编译器是clang,后面任何编译统一使用clang

--disable-network 屏蔽的是以下错误:

libavformat/udp.c:290:28: error: member reference base type '__be32' (aka 'u

--extra-cflags 中的 -D__ANDROID_API__=21 ,(和板子的 android-27 不冲突)为了屏蔽由于ndk 的原因爆出的以下错误:

undefined reference to `stderr'  

参考 https://stackoverflow.com/questions/39322852/android-ndk-undefined-reference-to-stderr  

 

编译过程:

./configure  --prefix=/your/install/path

./build.sh  

make -j

make install

  编译 android 的 opencv 

编译脚本如下 build.sh:

#!/usr/bin/env bash

set -eu

# shellcheck source=/dev/null
#. "$(dirname "$0")/../config.sh"

OPENCV_ROOT=/your/home/android/opencv-3.1.0
BUILD_DIR=/your/home/android/opencv-3.1.0/build_android4ffmpeg
ANDROID_ABI=arm64-v8a
NDK_ROOT=/your/home/android-ndk-r16b
INSTALL_DIR=/your/home/android/opencv-3.1.0/build_install4ffmpeg
if [ "${ANDROID_ABI}" = "armeabi" ]; then
    API_LEVEL=19
else
    API_LEVEL=27
fi

rm -rf "${BUILD_DIR}"
mkdir -p "${BUILD_DIR}"
pushd "${BUILD_DIR}"



#-D WITH_OPENMP=ON \ opencv  只是为了读取图像 没有必要启用
cmake -DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
      -DCMAKE_TOOLCHAIN_FILE="${NDK_ROOT}/build/cmake/android.toolchain.cmake" \
      -DANDROID_NDK="${NDK_ROOT}" \
      -DANDROID_NATIVE_API_LEVEL=${API_LEVEL} \
      -DANDROID_ABI="${ANDROID_ABI}" \
      -DANDROID_STL=c++_shared \
      -DCMAKE_BUILD_TYPE=Debug \
      -D WITH_CUDA=OFF \
      -D WITH_MATLAB=OFF \
      -D WITH_FFMPEG=ON \
      -D BUILD_ANDROID_EXAMPLES=OFF \
      -D BUILD_DOCS=OFF \
      -D BUILD_PERF_TESTS=OFF \
      -D BUILD_TESTS=OFF \
      -D BUILD_WITH_DEBUG_INFO=ON \
      -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}/opencv" \
      ..

#make -j
#rm -rf "${INSTALL_DIR}/opencv"
#make install/strip
#git clean -fd 2> /dev/null || true

popd

其中      -D WITH_FFMPEG=ON ,是编译时添加ffmpeg,设置这个远远不够,需要继续更改opencv 的CmakeLists.txt 脚本,

 

 

 

再CmakeLists.txt 里面搜索WITH_FFMPEG 到此处

 

#更改为android 支持ffmpeg
OCV_OPTION(WITH_FFMPEG         "Include FFMPEG support"                      ON   IF ( NOT IOS AND NOT WINRT) )

 然后进入opencv 的cmake 文件夹,打开OpenCVFindLibsVideo.cmake 然后修改为:

ocv_clear_vars(HAVE_FFMPEG HAVE_FFMPEG_CODEC HAVE_FFMPEG_FORMAT HAVE_FFMPEG_UTIL HAVE_FFMPEG_SWSCALE HAVE_FFMPEG_RESAMPLE HAVE_GENTOO_FFMPEG HAVE_FFMPEG_FFMPEG)
if(WITH_FFMPEG)
  if(WIN32 AND NOT ARM) #为了ffmepg 编译进去,这里暂时注释掉官方的写法 2019-03-17 pxg
    include("${OpenCV_SOURCE_DIR}/3rdparty/ffmpeg/ffmpeg.cmake")
  elseif(TRUE)
    CHECK_MODULE(libavcodec HAVE_FFMPEG_CODEC)
    CHECK_MODULE(libavformat HAVE_FFMPEG_FORMAT)
    CHECK_MODULE(libavutil HAVE_FFMPEG_UTIL)
    CHECK_MODULE(libswscale HAVE_FFMPEG_SWSCALE)
    CHECK_MODULE(libavresample HAVE_FFMPEG_RESAMPLE)

    CHECK_INCLUDE_FILE(libavformat/avformat.h HAVE_GENTOO_FFMPEG)
    CHECK_INCLUDE_FILE(ffmpeg/avformat.h HAVE_FFMPEG_FFMPEG)
    #if(NOT HAVE_GENTOO_FFMPEG AND NOT HAVE_FFMPEG_FFMPEG)
    #  if(EXISTS /usr/include/ffmpeg/libavformat/avformat.h OR HAVE_FFMPEG_SWSCALE)
    #    set(HAVE_GENTOO_FFMPEG TRUE)
    #  endif()
    #endif()
    #if(HAVE_FFMPEG_CODEC AND HAVE_FFMPEG_FORMAT AND HAVE_FFMPEG_UTIL AND HAVE_FFMPEG_SWSCALE)
    #  set(HAVE_FFMPEG TRUE)
    #endif()

    if(HAVE_FFMPEG)
      # Find the bzip2 library because it is required on some systems
      FIND_LIBRARY(BZIP2_LIBRARIES NAMES bz2 bzip2)
      if(NOT BZIP2_LIBRARIES)
        # Do an other trial
        FIND_FILE(BZIP2_LIBRARIES NAMES libbz2.so.1 PATHS /lib)
      endif()
    else()
      MESSAGE(STATUS  "start to find ffmpeg include")
      #find_path(FFMPEG_INCLUDE_DIR "libavformat/avformat.h"
      #          PATHS /your/path/android/ffmpeg4opencv/simplefflib PATH_SUFFIXES include
      #          DOC "The path to FFMPEG headers")
      set(FFMPEG_INCLUDE_DIR /your/path/android/ffmpeg4opencv/simplefflib/include)
    if(FFMPEG_INCLUDE_DIR)
        set(HAVE_GENTOO_FFMPEG TRUE)
        set(FFMPEG_LIB_DIR "${FFMPEG_INCLUDE_DIR}/../lib" CACHE PATH "Full path of FFMPEG library directory")
        #find_library(FFMPEG_CODEC_LIB "avcodec" HINTS "${FFMPEG_LIB_DIR}")
        #find_library(FFMPEG_FORMAT_LIB "avformat" HINTS "${FFMPEG_LIB_DIR}")
        #find_library(FFMPEG_UTIL_LIB "avutil" HINTS "${FFMPEG_LIB_DIR}")
        #find_library(FFMPEG_SWSCALE_LIB "swscale" HINTS "${FFMPEG_LIB_DIR}")
        #find_library(FFMPEG_RESAMPLE_LIB "avresample" HINTS "${FFMPEG_LIB_DIR}")

        #if(FFMPEG_CODEC_LIB)
        #  MESSAGE(STATUS "FFMPEG_CODEC_LIB found")
          set(HAVE_FFMPEG_CODEC 1)
        #endif()
        #if(FFMPEG_FORMAT_LIB)
          set(HAVE_FFMPEG_FORMAT 1)
        #endif()
        #if(FFMPEG_UTIL_LIB)
          set(HAVE_FFMPEG_UTIL 1)
        #endif()
        #if(FFMPEG_SWSCALE_LIB)
          set(HAVE_FFMPEG_SWSCALE 1)
        #endif()
          set(HAVE_FFMPEG_RESAMPLE 1)
        if(FFMPEG_CODEC_LIB AND FFMPEG_FORMAT_LIB AND
           FFMPEG_UTIL_LIB AND FFMPEG_SWSCALE_LIB)
          set(ALIASOF_libavcodec_VERSION "Unknown")
          set(ALIASOF_libavformat_VERSION "Unknown")
          set(ALIASOF_libavutil_VERSION "Unknown")
          set(ALIASOF_libswscale_VERSION "Unknown")
          set(HAVE_FFMPEG 1)
          if(FFMPEG_RESAMPLE_LIB)
            set(HAVE_FFMPEG_RESAMPLE 1)
            set(ALIASOF_libavresample_VERSION "Unknown")
          endif()
        endif()
      endif(FFMPEG_INCLUDE_DIR)
      SET(HAVE_FFMPEG TRUE)
      if(HAVE_FFMPEG)
        set(VIDEOIO_LIBRARIES ${VIDEOIO_LIBRARIES} "${FFMPEG_LIB_DIR}/libavcodec.a" "${FFMPEG_LIB_DIR}/libswresample.a" 
            "${FFMPEG_LIB_DIR}/libavformat.a" "${FFMPEG_LIB_DIR}/libavutil.a"
            "${FFMPEG_LIB_DIR}/libswscale.a")
        if(HAVE_FFMPEG_RESAMPLE)
          set(VIDEOIO_LIBRARIES ${VIDEOIO_LIBRARIES} "${FFMPEG_LIB_DIR}/libavresample.a")
          MESSAGE(STATUS "${VIDEOIO_LIBRARIES}")
        endif()
        ocv_include_directories(${FFMPEG_INCLUDE_DIR})
      endif(HAVE_FFMPEG)
    endif()
  endif()
endif(WITH_FFMPEG)


​​​​​​之后执行build.sh 之后即开始编译

编译sample

实例代码如下:

#include <opencv2/opencv.hpp>
#include <iostream>

int main(int argc, char* argv[])
{

std::string videoFileName(argv[1]);
cv::VideoCapture capture(videoFileName);
if (!capture.isOpened()) {
        capture.release();
        return 0;
    }
printf("read video successfully\n");

return 0;
}

编译脚本build.sh 如下

NDK_ROOT=/your/home/android-ndk-r16b


rm -rf build-android-aarch64
mkdir -p build-android-aarch64
pushd build-android-aarch64
cmake     -DCMAKE_TOOLCHAIN_FILE=$NDK_ROOT/build/cmake/android.toolchain.cmake   \
          -DANDROID_ABI="arm64-v8a" \
          -DCMAKE_BUILD_TYPE=Debug \
          -DANDROID_STL=c++_shared \
          -DANDROID_PLATFORM=android-27 \
          ..


make -j
#make install

popd

CMakeLists.txt 如下:注意 需要添加ffmpeg 的静态库

cmake_minimum_required(VERSION 3.14)

SET(DEMO    video_reader)
PROJECT(${DEMO})
SET(NDK_DIR  $ENV{HOME}/android-ndk-r16b)
SET(OMP_DIR  ${NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080/lib/linux/aarch64)
SET(OpenCV_DIR $ENV{HOME}/opencv-3.1.0/build_install4ffmpeg/opencv/sdk/native/jni)
SET(CMAKE_CXX_FLAGS    "${CMAKE_CXX_FLAGS}  -fno-rtti   -fPIC -Wall -fopenmp -O3 ")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall  -O3 ")
#-fno-rtti  这个flag 可以解决 error: undefined reference to 'typeinfo for    http://www.cnblogs.com/beautiful-scenery/p/3589529.html?utm_source=tuicool 
# 但可能错过例如 undefined reference to `__kmpc_for_static_init_4' 等未知符号名错误

#openmp 开启多线程加速
option(_OPENMP "openmp support" ON)


if(_OPENMP)
    find_package(OpenMP)
    # For CMake < 3.9, we need to make the target ourselves
    if(NOT TARGET OpenMP::OpenMP_CXX)
        find_package(Threads REQUIRED)
        add_library(OpenMP::OpenMP_CXX IMPORTED INTERFACE)
        set_property(TARGET OpenMP::OpenMP_CXX
          PROPERTY INTERFACE_COMPILE_OPTIONS ${OpenMP_CXX_FLAGS})
        # Only works if the same flag is passed to the linker; use CMake 3.9+ otherwise (Intel, AppleClang)
        set_property(TARGET OpenMP::OpenMP_CXX
          PROPERTY INTERFACE_LINK_LIBRARIES ${OpenMP_CXX_FLAGS} Threads::Threads)
    endif()
endif()




#使用opencv config.cmake
find_package(OpenCV QUIET COMPONENTS core highgui imgproc imgcodec   video)
 if (NOT OpenCV_FOUND)
      find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc  imgcodecs)
 endif()

add_definitions(-std=c++11)

INCLUDE_DIRECTORIES(${OpenCV_DIR}/jni/include)
#INCLUDE_DIRECTORIES(${DLIB_DIR}/include)                  
#INCLUDE_DIRECTORIES(${NCNN_DIR}/include) 
INCLUDE_DIRECTORIES(include)


#LINK_DIRECTORIES(${DLIB_DIR}/lib)
#LINK_DIRECTORIES(${NCNN_DIR}/lib) 
#link_directories(./)
#LINK_DIRECTORIES(build-android-aarch64)

link_libraries(log)
link_libraries(${OpenCV_LIBS})
link_libraries(${NDK_DIR}/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/5.0.300080/lib/linux/aarch64/libomp.a)
aux_source_directory(src SRC_PATH)


#ADD_LIBRARY(drivers  SHARED ${SRC_PATH})

add_executable(${DEMO}  src/demo.cpp)
set_property(TARGET ${DEMO}  PROPERTY POSITION_INDEPENDENT_CODE TRUE)
TARGET_LINK_LIBRARIES(${DEMO} /your/home/ffmpeg4opencv/simplefflib/include/../lib/libavcodec.a)

TARGET_LINK_LIBRARIES(${DEMO} /your/home/3rdparty/android/ffmpeg4opencv/simplefflib/include/../lib/libswresample.a)
TARGET_LINK_LIBRARIES(${DEMO} /your/home/3rdparty/android/ffmpeg4opencv/simplefflib/include/../lib/libavutil.a)

 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值