Android FFmpeg集成

本文阐述下集成Android集成FFmpeg库的流程,如有不完善的地方,麻烦指出,万分感谢。

硬件环境:MacBook Air

软件环境:Android Studio Narwhal 3 Feature Drop | 2025.1.3+Java 11+

build.gradle.kts(8.13)+NDK 20.0.5594570+ffmpeg 8.0.1

步骤:

(1)下载ffmpeg项目代码

(2)CLANG编译FFmpeg

(3)新建Native C++项目

(4)配置ffmpeg动态库

(5)添加 FFmpeg so库的头文件

(6)native-lib.cpp实现获取 FFmpeg 基础信息

一.下载ffmpeg

官网: https://ffmpeg.org/download.html

git下载:

java 复制代码
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

二.CLANG编译FFmpeg

1.ffmpeg代码修改配置ClANG

修改 configure 脚本

将configure文件拖动到Android studio,修改以下几点:

(1)添加cross_prefix_clang参数:

我们可以搜索 CMDLINE_SET ,可以找到以下代码,然后新增一个命令行选项cross_prefix_clang

(2)修改编译工具路径设置

我们可以搜索 ar_default="{cross_prefix}{ar_default}" , 找到以下代码:

将高亮两行修改为:

(3)新建编译脚本

在 ffmpeg根目录下新建 shell 脚本,命名为: build_android_clang.sh,脚本代码如下:

java 复制代码
#!/bin/bash
set -x
# 目标Android版本
API=29
ARCH=arm64
CPU=armv8-a
TOOL_CPU_NAME=aarch64
#so库输出目录
OUTPUT=/Users/guoxiang/Downloads/ffmpeg/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/Users/guoxiang/Library/Android/sdk/ndk/20.0.5594570
# 编译工具链路径
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
# 编译环境
SYSROOT=$TOOLCHAIN/sysroot

TOOL_PREFIX="$TOOLCHAIN/bin/$TOOL_CPU_NAME-linux-android"
 
CC="$TOOL_PREFIX$API-clang"
CXX="$TOOL_PREFIX$API-clang++"
OPTIMIZE_CFLAGS="-march=$CPU"
function build
{
  ./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=$ARCH  \
  --cpu=$CPU \
  --disable-asm \
  --enable-neon \
  --enable-cross-compile \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --cc=$CC \
  --cxx=$CXX \
  --sysroot=$SYSROOT \
  --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \

  make clean all
  # 这里是定义用几个CPU编译
  make -j8
  make install
}
build

其中两个地方需要根据自己的配置修改

java 复制代码
#so库输出目录
OUTPUT=/Users/guoxiang/Downloads/ffmpeg/android/$CPU
# NDK的路径,根据自己的NDK位置进行设置
NDK=/Users/guoxiang/Library/Android/sdk/ndk/20.0.5594570

修改脚本权限

java 复制代码
chmod +x  build_android_clang.sh

修改完后,终端执行命令:

java 复制代码
 ./build_android_clang.sh

编译完成后,在android/armv8-a目录下会生成lib和include文件夹,这两者分别是so库和头文件所在位置

三.Android studio新建Native C++项目

四.配置ffmpeg动态库

将ffmpeg/android/armv8-a/lib中的so库导入到NativeDemo项目中,如下:

注意:图中高亮地方是依赖so库编译目录为jniLibs目录

五.添加 FFmpeg so库的头文件

将ffmpeg/android/armv8-a/include中的头文件导入到NativeDemo项目中,如下:

注意:图中高亮地方是依赖头文件编译目录

六.native-lib.cpp实现获取 FFmpeg 基础信息

(1)配置CMakeLists.txt如下

Kotlin 复制代码
cmake_minimum_required(VERSION 3.22.1)

#project(nativedemo)

# 支持gnu++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR})

# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir})

# 3. 添加ffmpeg相关的so库
add_library( avutil
        SHARED
        IMPORTED )
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavutil.so )

add_library( swresample
        SHARED
        IMPORTED )
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswresample.so )

add_library( avcodec
        SHARED
        IMPORTED )
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavcodec.so )

add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavfilter.so )

add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswscale.so )

add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavformat.so )

add_library( avdevice
        SHARED
        IMPORTED)
set_target_properties( avdevice
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavdevice.so )

# 查找代码中使用到的系统库
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 )

# 配置目标so库编译信息
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).
        native-lib.cpp
)

# 指定编译目标库时,cmake要链接的库
target_link_libraries(

        # 指定目标库,native-lib 是在上面 add_library 中配置的目标库
        native-lib

        # 4. 连接 FFmpeg 相关的库
        avutil
        swresample
        avcodec
        avfilter
        swscale
        avformat
        avdevice

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

(2)build.gradle.kts中添加cmake和viewBinding

Kotlin 复制代码
  externalNativeBuild {
        cmake {
            path = file("src/main/cpp/CMakeLists.txt")
            version = "3.22.1"
        }
    }
    buildFeatures {
        viewBinding = true
    }

(3)在创建的MainActivity中实现如下代码:

Kotlin 复制代码
package com.example.nativedemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import com.example.nativedemo.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val result = ffmpegInfo()
        binding.sampleText.text = result
    }

    companion object {
        //加载native-lib静态库
        init {
            System.loadLibrary("native-lib")
        }
    }

    /**
     * 获取ffmpeg的基本信息
     */
    external fun ffmpegInfo(): String
}

(4)native-lib.cpp中实现如下方法:

Kotlin 复制代码
extern "C" {
JNIEXPORT jstring JNICALL
Java_com_example_nativedemo_MainActivity_ffmpegInfo(
        JNIEnv *env,
        jobject mainActivty) {
    char info[40000] = {0};
    void *iter = NULL;
    const AVCodec *c_temp = NULL;
    while ((c_temp = av_codec_iterate(&iter)) != NULL) {
        if (av_codec_is_decoder(c_temp)) {
            printf("Decoder: %s\n", c_temp->name);
        }
        switch (c_temp->type) {
            case AVMEDIA_TYPE_VIDEO:
                sprintf(info, "%s(video):", info);
                break;
            case AVMEDIA_TYPE_AUDIO:
                sprintf(info, "%s(audio):", info);
                break;
            default:
                sprintf(info, "%s(other):", info);
                break;
        }
        sprintf(info, "%s[%s]\n", info, c_temp->name);
    }

    return env->NewStringUTF(info);
}
}

(5)运行NativeDemo项目,MainActivity中的TextView会显示ffmpeg音视频编解码的基本信息,如下图示:

代码地址:

https://gitee.com/daxiangzaici/native-demo.git

相关推荐
好多渔鱼好多2 小时前
【流媒体】FFmpeg技术介绍与构建方法
ffmpeg
墨雪不会编程2 小时前
C++【string篇4】string结尾篇——字符编码表、乱码的来源及深浅拷贝
android·开发语言·c++
没有羊的王K2 小时前
下载安装FFmpeg教程
ffmpeg
汤姆yu3 小时前
基于android的大学学校食堂点餐系统
android
爱吃生蚝的于勒3 小时前
【Linux】零基础学习命名管道-共享内存
android·linux·运维·服务器·c语言·c++·学习
开开心心_Every3 小时前
视频无损压缩工具:大幅减小体积并保持画质
游戏·微信·pdf·excel·音视频·语音识别·tornado
EasyCVR3 小时前
解析视频融合平台EasyCVR视频智能分析技术背后的技术支撑
人工智能·音视频
kkoral3 小时前
【FFmpeg 智慧园区场景应用】1.实战命令清单
ffmpeg
天虎3 小时前
使用VS2019编译ShiftMediaProject版本FFmpeg
ffmpeg