FFmpeg 4.1.3 + Ubuntu 18.04 + Android Studio 3.4.1编译

FFmpeg 4.1.3 + Ubuntu 18.04 + Android Studio 3.4.1编译

  • 环境搭建
    • 安装配置 Ubuntu
    • 下载 NDK
    • 下载 FFmpeg
  • 编译 FFmpeg
  • Android交叉编译

环境搭建

安装配置 Ubuntu

  1. 安装Ubuntu 18.04(我使用的是Windows10应用商店里的版本,后期引入头文件比较方便)
    启动系统后会提示设置用户名密码,按照提示设置就好,进入系统后执行以下命令提高到root权限(方便操作,不然老提示你权限不足)

    sudo su

  2. 安装完成后执行以下命令:

    apt-get update
    apt-get install yasm
    apt-get install pkg-config

下载 NDK

版本是NDK17c(这个版本匹配度最高,修改最少)
需要下载两个版(源码编译和android studio编译分别会用到):

  • Ubuntu 下载(下载到Ubuntu中)
    下载完成后用unzip工具解压缩

    apt-get install unzip
    unzip android-ndk-r17c-linux-x86_64.zip

  • Windows 下载(下载到Windows中)
    下载完成后用winRAR工具解压缩

下载 FFmpeg

版本是4.1.3 下载 (下载到Ubuntu中)
下载完成后用tar解压

tar -zxvf ffmpeg-4.1.3.tar.bz2

编译 FFmpeg

  1. 编写编译脚本
    在Ubuntu下进入FFmpeg-n4.1.3目录,用vim或vi工具创建文件build_android.sh,在文件中编写以下内容:

       #!/bin/bash
       clear
       
       function build_android
       {
       ./configure \
       --prefix=$PREFIX \
       --enable-shared \
       --disable-static \
       --disable-ffmpeg \
       --disable-ffplay \
       --disable-ffprobe \
       --target-os=android \
       --disable-doc \
       --enable-cross-compile \
       --cross-prefix=$CROSS_PREFIX \
       --arch=$ARCH \
       --sysroot=$SYSROOT \
       --extra-cflags="-I$NDK/sysroot/usr/include/arm-linux-androideabi -isysroot $NDK/sysroot -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" \
       --enable-neon
       make clean all
       make -j4
       make install 
       }
       
       NDK=/home/wuppa/android-ndk-r17c #填写自己ndk的解压路径
       
       #armv7-a
       API=26
       ARCH=arm
       CPU=armv7-a
       PREFIX=$(pwd)/android/$CPU
       TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
       SYSROOT=$NDK/platforms/android-$API/arch-$ARCH
       CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
       
       build_android
    
  2. 设置脚本权限

    chmod 777 build_android.sh

  3. 执行脚本

    ./build_android.sh

  4. 检查编译结果
    编译完后,在FFmpeg-n4.1.3目录下,会生成android目录,进入目录可以看到armv7-a目录,进入目录会看到如下目录:
    图片
    -include里就是编译完的头文件;
    -lib里就是编译好的.so文件;

    到这里FFmpeg的源码就编译成功了!!!

Android交叉编译

  1. 创建Android jni项目
    FFmpeg 4.1.3 + Ubuntu 18.04 + Android Studio 3.4.1编译_第1张图片

  2. 复制文件
    在项目下创建ffmpeg目录,并创建子目录armeabi-v7a,将之前编好的lib目录下的动态库复制到此目录。
    将源码中fftools目录中如图所示的.h.c文件拷贝到ffmpeg目录。
    FFmpeg 4.1.3 + Ubuntu 18.04 + Android Studio 3.4.1编译_第2张图片

  3. 修改ffmpeg.h ffmpeg.c cmdutils.h cmdutils.c文件
    在ffmpeg.c中找到main函数(在文件最后),将名称改为run,并在头文件中声明该函数。
    在cmdutils.h文件中找到"0x%"PRIx64所在的行,在PR前加入一个空格,不然编译会报错。

  4. 编写jni调用文件
    在cpp目录下创建ffmpeg-cmd.cpp文件并编写以下内容:

    #include <jni.h>
    #include <string>
    #include "android/log.h"
    
    extern "C" {
    #include "ffmpeg.h"
    #include "libavutil/avutil.h"
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavfilter/avfilter.h"
    }
    
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG  , "ffmpeg-lib", __VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR  , "ffmpeg-lib", __VA_ARGS__)
    
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_demo_ffmpeg_FFmpegCmd_run(JNIEnv *env, jclass type, jobjectArray cmd) {
        int cmdLen = env->GetArrayLength(cmd);
        char *argCmd[cmdLen] ;
        jstring buf[cmdLen];
    
        for (int i = 0; i < cmdLen; ++i) {
            buf[i] = static_cast<jstring>(env->GetObjectArrayElement(cmd, i));
            char *string = const_cast<char *>(env->GetStringUTFChars(buf[i], JNI_FALSE));
            argCmd[i] = string;
            LOGD("argCmd=%s",argCmd[i]);
        }
    
        int retCode = run(cmdLen, argCmd);
        LOGD("ffmpeg-invoke: retCode=%d",retCode);
    
        return retCode;
    }
    
  5. 修改CMakeList.txt文件

    cmake_minimum_required(VERSION 3.4.1)
    
    set(CMAKE_CXX_FLAGS "-std=c++11")
    include_directories(自己的ndk路径\\sysroot\\usr\\include\\arm-linux-androideabi)
    include_directories(对应的Ubuntu在windows中的路径(每个人不一样,自己百度)\\FFmpeg-n4.1.3)
    include_directories(自己项目路径\\app\\src\\main\\cpp\\ffmpeg)
    
    #ffmpeg库设置
    add_library(
            avcodec
            SHARED
            IMPORTED)
    set_target_properties(
            avcodec
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libavcodec.so)
    
    add_library(
            avdevice
            SHARED
            IMPORTED)
    set_target_properties(
            avdevice
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libavdevice.so)
    
    add_library(
            avfilter
            SHARED
            IMPORTED)
    set_target_properties(
            avfilter
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libavfilter.so)
    
    add_library(
            avformat
            SHARED
            IMPORTED)
    set_target_properties(
            avformat
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libavformat.so)
    
    add_library(
            avutil
            SHARED
            IMPORTED)
    set_target_properties(
            avutil
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libavutil.so)
    
    add_library(
            swresample
            SHARED
            IMPORTED)
    set_target_properties(
            swresample
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libswresample.so)
    
    add_library(
            swscale
            SHARED
            IMPORTED)
    set_target_properties(
            swscale
            PROPERTIES IMPORTED_LOCATION
            ${CMAKE_SOURCE_DIR}/ffmpeg/${ANDROID_ABI}/libswscale.so)
    
    #本地cpp文件配置
    add_library(
            ffmpeg-cmd
            SHARED
            ffmpeg/cmdutils.c
            ffmpeg/ffmpeg_filter.c
            ffmpeg/ffmpeg_opt.c
            ffmpeg/ffmpeg_hw.c
            ffmpeg/ffmpeg.c
            ffmpeg-cmd.cpp)
    
    find_library(
            log-lib
            log)
    
    target_link_libraries(
            ffmpeg-cmd
            avcodec
            avdevice
            avfilter
            avformat
            avutil
            swresample
            swscale
            -landroid
            ${log-lib})
    
  6. 修改build.gradle文件
    FFmpeg 4.1.3 + Ubuntu 18.04 + Android Studio 3.4.1编译_第3张图片

  7. 创建FFmpegCmd.java文件并写入如下内容:

    public class FFmpegCmd {
        static {
            System.loadLibrary("avutil");
            System.loadLibrary("swresample");
            System.loadLibrary("avcodec");
            System.loadLibrary("avformat");
            System.loadLibrary("swscale");
            System.loadLibrary("avfilter");
            System.loadLibrary("avdevice");
            System.loadLibrary("ffmpeg-cmd");
        }
    
        public static native int run(String[] cmd);
    }
    
  8. 修改MainActivity如下:

    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ffmpegTest();
        }
    
        private void ffmpegTest() {
            new Thread() {
                @Override
                public void run() {
                    long startTime = System.currentTimeMillis();
                    String input = "/sdcard/mv.mp4";
                    String output = "/sdcard/output.mp4";
                    String cmd = "ffmpeg -i %s -ss 00:00:01 -t 00:00:03 %s";
                    cmd = String.format(cmd, input, output);
                    FFmpegCmd.run(cmd.split(" "));
                }
            }.start();
        }
    } 
    
  9. 编译运行
    在系统的根目录中放一个mv.mp4文件,点击运行开始编译项目,如果一切顺利,在手机里的根目录里会生成output.mp4文件,这个文件是原视频裁剪后得到的。

参考了如下博文:
编译FFmpeg4.1.3并移植到Android app中使用(最详细的FFmpeg-Android编译教程)

文中错误欢迎指正!!!

你可能感兴趣的:(FFmpeg,FFmpeg,Android,Ubuntu)