NDK23_FFmpeg编译

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序,需要编译出so库文件,拿到Android Q项目中使用

NDK开发汇总

一 环境准备

Linux:ubuntu16.04.7
NDK:android-ndk-r17c
FFmpeg:ffmpeg-4.0.3.tar.bz2
下载FFmpeg:

wget http://ffmpeg.org/releases/ffmpeg-4.0.2.tar.bz2

解压

tar -xvf ffmpeg-4.0.2.tar.bz2

解压tar包失败报错

gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now

解决

 tar -xvf 文件名

二 FFmpeg配置编译脚本

解压后目录下有个configure文件,本质上是一个脚本文件(#!/bin/sh开头),直接编译太复杂,会报错,通过./configure --help 查看帮助信息 或者vim configure查看内容。
configure用来生成一个makefile

查看configure配置

prefix:最终生成的文件在那个目录 pwd 当前目录
swresample 重采样
swscale 缩放
 postproc 后期处理
 -avfilter 字幕水印
 muxers混合封装
-cross-compile 交叉编译
--cross prefix=$TOOLCHAIN/bin/$CPU- 指定交叉编译链
cflags =$FLAG $INCLUDES”传给gcc编译器的参数,打开AS想,  externalNativeBuild /build.ninja会有内容,注意路径
-system或者sysroot 指定头文件
--arch=arm 要指定的架构
# \ 换行连接符

需要一个静态的FFmpeg库,能够在Android项目中被使用,这就要编写一个脚本文件

vim build.sh

build.sh的内容配置如下

#!/bin/bash
NDK_ROOT=/home/a/android-ndk-r17c
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64
#从as的 externalNativeBuild/xxx/build.ninja
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -O0 -fPIC"
INCLUDES=" -isystem $NDK_ROOT/sources/android/support/include"

PREFIX=./android/armeabi-v7a_lsn11

./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/$CPU- \
--disable-shared \
--enable-static \
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot/" \
--arch=arm \
--target-os=android 

# 清理一下 
make clean
#执行makefile
make install

注意NDK_ROOT 要改为自己的ndk路径

开始编译:

./build.sh

编译成功后的库在PREFIX设置的路径下:
在这里插入图片描述

如果需要动态库,静态库生成动态库

gcc -share -o libMain.so -wq,--whole-archive libMain.a -wl,--no -whole-archive

三 简单调用

1 新建项目(支持C++),拷贝include文件所有头文件和lib文件夹下所有.a文件到cpp目录下

在这里插入图片描述

2 CmakeList.txt中配置

引入头文件:

include_directories(src/main/cpp/include)

引入.a库文件

set(CMAKE_CXX_FLAGS “ C M A K E C X X F L A G S − L {CMAKE_CXX_FLAGS} -L CMAKECXXFLAGSL{CMAKE_SOURCE_DIR}/src/main/cpp/libs/${ANDROID_ABI}”)
#链接库
target_link_libraries( # Specifies the target library.
native-lib
avcodec avfilter avformat avutil swresample swscale
${log-lib} )



cmake_minimum_required(VERSION 3.4.1)


add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )



find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

include_directories(src/main/cpp/include)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/cpp/libs/${ANDROID_ABI}")

target_link_libraries( # Specifies the target library.
                    native-lib
                    avcodec avfilter avformat avutil swresample swscale

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
                       

3 Build.gradle指定平台

defaultConfig {
    
    
        applicationId "com.cn.ray.myapplication"
        minSdkVersion 24
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
    
    
            cmake {
    
    
                cppFlags ""
                abiFilters 'armeabi-v7a'
            }
        }
    }

4 native-lib.cpp使用

#include <jni.h>
#include <string>
extern "C"{
    
    
#include <libavcodec/avcodec.h>
}

extern "C" JNIEXPORT jstring

JNICALL
Java_com_cn_ray_myapplication_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    
    
    std::string hello = "Hello from C++";
    av_version_info();
    return env->NewStringUTF(av_version_info());
}

四 注意

  1. NDK和FFmpeg的版本要对应一直,这里用ndk中的gcc编译的,新的FFmpeg有可能报Clang找不到,需要用新的NDK或者用旧版本的FFmpeg
  2. error.h 找不到,

解决:搜索ndk中error.h的路径,指定路径不正确,注意区别system和sysroot

  1. libavcodec/hq_hqadata.c:7607:5:error expected expression at end of input
    14,20,9,36,14,50,9,1,17,23,22,23,18

解决:查看hq_hqadata.c文件7607行,发现后面没有内容了(可以单独解约FFmpeg对比),说明文件损坏了,需要重新解压

  1. 编译FFmpeg报错:

error:cannot open crend_so.o:No such file or directory 要指定sysroot

  1. 其他报错:

一般会有提示生成了一个log错误文件,打开文件,查看最后面error信息,根据信息修改

猜你喜欢

转载自blog.csdn.net/baopengjian/article/details/108408884