Mac交叉编译Android FFmpeg

2023年 9月 25日 64.1k 0

最近在学习Android上的FFmpeg开发。记录下在Mac上交叉编译和使用Android FFmpeg库的过程。

1. 交叉编译

# 1.下载ffmpeg-4.2.2源码
wget https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2
# 2. 解压
# 3. 运行configure脚本配置项目
./configure --disable-x86asm

在当前文件夹下创建编译脚本build_android_arm64-v8a_clang.sh:

#!/bin/zsh

export NDK=~/Library/Android/android-ndk-r20b #这里配置先你的 NDK 路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64

#arm64-v8a
ARCH=arm64
CPU=armv8-a
API=21
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"

#armv7-a
#ARCH=arm
#CPU=armv7-a
#API=21
#CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
#CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
#SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
#CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
#PREFIX=$(pwd)/android/$CPU
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "

function build_android {

	./configure 
		--prefix=$PREFIX 
		--enable-neon 
		--enable-hwaccels 
		--enable-gpl 
		--disable-postproc 
		--disable-debug 
		--enable-small 
		--enable-jni 
		--enable-mediacodec 
		--enable-decoder=h264_mediacodec 
		--enable-static 
		--enable-shared 
		--disable-doc 
		--enable-ffmpeg 
		--disable-ffplay 
		--disable-ffprobe 
		--disable-avdevice 
		--disable-doc 
		--disable-symver 
		--cross-prefix=$CROSS_PREFIX 
		--target-os=android 
		--arch=$ARCH 
		--cpu=$CPU 
		--cc=$CC 
		--cxx=$CXX 
		--enable-cross-compile 
		--sysroot=$SYSROOT 
		--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" 
		--extra-ldflags="$ADDI_LDFLAGS"

	  make clean
	  make -j16
	
	echo "============================ build android arm64-v8a success =========================="

}

build_android

运行脚本编译,之后会在android/armv8-a/lib/下生成动态和静态库。

# 修改 build_android_arm64-v8a_clang.sh 可执行权限  
chmod +x build_android_arm64-v8a_clang.sh  
# 运行编译脚本  
./build_android_arm64-v8a_clang.sh

2. Android上集成测试

新建Android项目。

2.1 JNI接口

  • 将生成目录的头文件和库文件放入下面目录。注意库文件要放在app/src/jniLibs/arm64-v8a目录下。
    image.png
  • 创建FFMediaPlayer.java,作为java层接口。
  • package com.zzakafool.androidffmpeg;
    
    public class FFMediaPlayer {
        static {
            System.loadLibrary("learn-ffmpeg");
        }
    
        public static String GetFFmpegVersion() {
            return native_GetFFmpegVersion();
        }
    
        private static native String native_GetFFmpegVersion();
    }
    
  • app/src/main/cpp/下添加对应native实现FFMediaPlayer.cpp
  • #include 
    #include 
    //#include "util/LogUtil.h"
    #include "jni.h"
    
    //由于 FFmpeg 库是 C 语言实现的,告诉编译器按照 C 的规则进行编译
    extern "C" {
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    };
    
    extern "C"
    JNIEXPORT jstring JNICALL
    Java_com_zzakafool_androidffmpeg_FFMediaPlayer_native_1GetFFmpegVersion(JNIEnv *env, jclass clazz) {
        // TODO: implement native_GetFFmpegVersion()
        char strBuffer[1024 * 4] = {0};
        strcat(strBuffer, "libavcodec : ");
        strcat(strBuffer, AV_STRINGIFY(LIBAVCODEC_VERSION));
        strcat(strBuffer, "nlibavformat : ");
        strcat(strBuffer, AV_STRINGIFY(LIBAVFORMAT_VERSION));
        strcat(strBuffer, "nlibavutil : ");
        strcat(strBuffer, AV_STRINGIFY(LIBAVUTIL_VERSION));
        strcat(strBuffer, "nlibavfilter : ");
        strcat(strBuffer, AV_STRINGIFY(LIBAVFILTER_VERSION));
        strcat(strBuffer, "nlibswresample : ");
        strcat(strBuffer, AV_STRINGIFY(LIBSWRESAMPLE_VERSION));
        strcat(strBuffer, "nlibswscale : ");
        strcat(strBuffer, AV_STRINGIFY(LIBSWSCALE_VERSION));
        strcat(strBuffer, "navcodec_configure : n");
        strcat(strBuffer, avcodec_configuration());
        strcat(strBuffer, "navcodec_license : ");
        strcat(strBuffer, avcodec_license());
    //    LOGCATE("GetFFmpegVersionn%s", strBuffer);
        return env->NewStringUTF(strBuffer);
    }
    
  • app/src/main/cpp/下添加CMakeLists.txt
  • # Sets the minimum version of CMake required to build the native library.
    cmake_minimum_required(VERSION 3.4.1)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
    
    set(jnilibs ${CMAKE_SOURCE_DIR}/../jniLibs)
    set(libname learn-ffmpeg)
    
    include_directories(
            include
            ${CMAKE_SOURCE_DIR}/util
    )
    
    link_directories(
            ${jnilibs}/${ANDROID_ABI})
    
    file(GLOB src-files
            ${CMAKE_SOURCE_DIR}/*.cpp)
    
    add_library( # Sets the name of the library.
            ${libname}
    
            # Sets the library as a shared library.
            SHARED
    
            # Provides a relative path to your source file(s).
            ${src-files}
            )
    
    set(third-party-libs
            avformat
            avcodec
            avfilter
            swresample
            swscale
            avutil
            )
    
    set(native-libs
            android
            EGL
            GLESv3
            OpenSLES
            log
            m
            z
            )
    
    target_link_libraries( # Specifies the target library.
            ${libname}
    
            # Links the target library to the log library
            # included in the NDK.
            ${log-lib}
            ${third-party-libs}
            ${native-libs}
            )
    
  • 在Activity中调用对应的接口。
  • import static com.zzakafool.androidffmpeg.R.id.*;
    
    import android.os.Bundle;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.zzakafool.androidffmpeg.R.id;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            ((TextView)findViewById(text_view)).setText(FFMediaPlayer.GetFFmpegVersion());
        }
    }
    
  • 运行App
  • image.png

    参考资料

    FFmpeg 开发(01):FFmpeg 编译和集成

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论