Android音视频-FFmpeg编译为单个so与测试调用

前面我们整出了FFmpeg的多个so文件,配置的过程走了一遍,这里我们在重新来走一遍配置过程,其实变动的地方不是很多。

编译单个FFmpeg so库

编译环境

  • 编译电脑系统:MacOS(10.13.3)
  • 编译NDK版本:NDK(r15c)
  • FFMpeg版本:3.3.6

配置编译文件

我们在下载的FFmpeg的根目录下面新建一个文件build_android_single.sh.里面的内容如下:

#!/bin/bash
export TMPDIR=/Users/yehu/Study/Android/MultiMedia/FFmpeg/ffmpeg-3.3.6/ffmpegtemp #这句很重要,不然会报错 unable to create temporary file in
# NDK的路径,根据自己的安装位置进行设置
NDK=/Users/yehu/Downloads/android-ndk-r15c
# 编译针对的平台,可以根据自己的需求进行设置
# 这里选择最低支持android-14, arm架构,生成的so库是放在
# libs/armeabi文件夹下的,若针对x86架构,要选择arch-x86
PLATFORM=$NDK/platforms/android-14/arch-arm
# 工具链的路径,根据编译的平台不同而不同
# arm-linux-androideabi-4.9与上面设置的PLATFORM对应,4.9为工具的版本号,
# 根据自己安装的NDK版本来确定,一般使用最新的版本
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one
{
./configure \
    --prefix=$PREFIX \
    --target-os=linux \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --arch=arm \
    --sysroot=$PLATFORM \
    --extra-cflags="-I$PLATFORM/usr/include" \
    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
    --disable-shared \
    --enable-runtime-cpudetect \
    --enable-gpl \
    --enable-small \
    --enable-cross-compile \
    --disable-debug \
    --enable-static \
    --disable-doc \
    --disable-asm \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --enable-postproc \
    --enable-avdevice \
    --disable-symver \
    --disable-stripping \
$ADDITIONAL_CONFIGURE_FLAG
sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
make clean
make -j4
make install
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$PLATFORM/usr/lib \
-L$PLATFORM/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
    libavcodec/libavcodec.a \
    libavdevice/libavdevice.a \
    libpostproc/libpostproc.a \
    libavfilter/libavfilter.a \
    libswresample/libswresample.a \
    libavformat/libavformat.a \
    libavutil/libavutil.a \
    libswscale/libswscale.a \
    -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
    $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
}
# arm v7vfp
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
PREFIX=./android/$CPU-vfp
ADDITIONAL_CONFIGURE_FLAG=
build_one

注意事项:
在网上搜索的大多数配置是没有把libpostproc和libavdevice这两个库添加进去的我的配置中加入了,现在为了保持和我前面编译的单个的so的所有so的数目功能相同。关键配置如下:

    #...
    --enable-postproc \
    --enable-avdevice \
    #...

    $PREFIX/libffmpeg.so \
    #...
    libavdevice/libavdevice.a \
    libpostproc/libpostproc.a \
    #...
}

开始编译等待完成,其中可能出现错误的这份配置文件我感觉就是配置的路径上面在不同机器上面的错误了。编译成功以后看到输出的so文件:



引入单个FFmpeg so进入项目中

倒入so和头文件

首先我们把刚才编译好的so拿进来,并且引入头文件和要调用FFmpeg的c文件,c文件的实现是前面一样的获取FFmpeg的基本信息:



配置CmakeLists.txt文件

下面我们就不用配置加入那八个so了,只要一个整合的libffmpeg.so文件即可:

cmake_minimum_required(VERSION 3.4.1)

#C++编译
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

set(jnilibs "${CMAKE_SOURCE_DIR}/src/main/jniLibs")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${jnilibs}/${ANDROID_ABI})

add_library( # Sets the name of the library.
             basicinfo-lib
             # Sets the library as a shared library.
             SHARED
             # Provides a relative path to your source file(s).
             src/main/cpp/basicinfo-lib.c)

#第三方so存放的根目录
SET(
    third_path
    ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}
    )
#引入源文件.h目录
include_directories( ${CMAKE_SOURCE_DIR}/src/main/cpp/include)


#设置libavcodec.so
add_library(
              libffmpeg
              SHARED
              IMPORTED
)

set_target_properties(libffmpeg
                      PROPERTIES IMPORTED_LOCATION
                      ${third_path}/libffmpeg.so
)


target_link_libraries(
                       basicinfo-lib
                       libffmpeg
                       ${log-lib})

Java层调用

我们在BasicInfoActivity里面进行native方法的调用:

package com.lyman.ffmpeg_cmake_single;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

public class BasicInfoActivity extends AppCompatActivity {
    private static final String TAG = "BasicInfoActivity";
    private TextView mContentTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_basic_info);
        mContentTV = findViewById(R.id.tv_content);
    }

    public void onClickProtocol(View view) {
        mContentTV.setText(urlprotocolinfo());
    }

    public void onClickFormat(View view) {
        mContentTV.setText(avformatinfo());
    }

    public void onClickCodec(View view) {
        mContentTV.setText(avcodecinfo());
    }

    public void onClickFilter(View view) {
        mContentTV.setText(avfilterinfo());
    }

    public void onClickConfigure(View view) {
        mContentTV.setText(configurationinfo());
    }

    public native String urlprotocolinfo();

    public native String avformatinfo();

    public native String avcodecinfo();

    public native String avfilterinfo();

    public native String configurationinfo();

    static {
        System.loadLibrary("basicinfo-lib");
    }
}

OK,到这里就搞定了,但是运行同样有之前遇到的问题




这个问题出现的原因我没有去探究是为什么同样的在gradle里面配置如下即可解决:

Android{
//...
packagingOptions {
        pickFirst 'lib/armeabi-v7a/libbasicinfo-lib.so'
    }
//...
}

本篇完整参考工程代码:查看

参考博客:
雷神
FFmpeg编译配置文件参考

猜你喜欢

转载自blog.csdn.net/lyman_ye/article/details/79461266