在已建好的android项目中使用ffmpeg

最近项目中要用到FFmpeg,前期的环境搭建用了很长时间,正所谓万事开头难,又一次深刻的领悟到了这个道理~

写篇文章,再次将自己的思路梳理一下,希望也能帮助到有需要的人~

本文参考:

https://juejin.im/entry/5af8384a6fb9a07ac23ad590#comment

https://www.jianshu.com/p/dfe9404e001a

http://www.ihubin.com/blog/android-ffmpeg-demo-3/

前提:本文演示的是将f'fmpeg编译成一个SO库

一、系统环境(与本文环境不同很有可能会编译失败)

  • Mac OS High Sierra 10.13.6
  • NDK-r14b(64bit)
  • FFmpeg 3.3   

二、下载NDK、ffmpeg

1.下载ndk(国内网站),也可以直接去官网,我下载的是android-ndk-r14b-darwin-x86_64.zip

2.配置ndk环境

  • 启动终端,进入当前用户的home目录下
  • 创建.bash_profile文件(如果之前已经创建过该文件,则直接打开):touch .bash_profile
  • 打开.bash_profile文件:open -e .bash.profile

           进入到编辑文件的页面,配置如下环境 :  

         上图中NDK_ROO为你下载的ndk所在位置。

  • 保存文件,关闭
  • 更新刚才的配置:source .bash_profile
  • 查看刚才的配置是否成功:

          在终端输入$PATH,并按enter键,查看结果:

         配置成功!

3.下载并编译ffmpeg

  • 在终端中进入某一目录下,例如Downloads下,输入:git clone https://git.ffmpeg.org/ffmpeg.git
  • 下载完成后,进入到ffmpeg目录下:cd ffmpeg
  • 切换到3.3分支: git checkout -b 3.3 remotes/origin/release/3.3
  • 在ffmpeg目录下找到configure文件,用sublime(或者其他工具)打开,将其中的:

                     

          修改成:          

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'  
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'  
SLIB_INSTALL_LINKS='$(SLIBNAME)'

        保存,退出。

  • 编译脚本文件

         在ffmpeg文件夹下,创建一个ffmpegtemp文件夹和一个ffmpeg_build.sh文件,对于fmpeg_build.sh我是将version.sh文件复制重新命名得到的,具体内容如下:

#!/bin/bash
export TMPDIR=/Users/UserName/Downloads/ffmpeg/ffmpegtemp #这句很重要,不然会报错 unable to create temporary file in
# NDK的路径,根据自己的安装位置进行设置
NDK=/Users/UserName/Downloads/android-ndk-r14b
# 编译针对的平台,可以根据自己的需求进行设置
# 这里选择最低支持android-14, arm架构,生成的so库是放在
# libs/armeabi文件夹下的,若针对x86架构,要选择arch-x86
PLATFORM=$NDK/platforms/android-21/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 \
    --disable-postproc \
    --disable-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 \
    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

        这里一定要注意修改NDK的路径,下载的ndk版本,以及对应的系统架构(是X86,还是arm)

        最后一个位置 ,我选择的是 CPU 类型是 armv7-a(想进一步了解的点这里

脚本准备好了,下面开始编译:

  • 打开终端切换到ffmpeg目录下,执行:chmod +x ffmpeg_build.sh
  • 然后:./ffmpeg_build.sh

此刻耐心等待一下,等等过程中出现下图,证明正在编译~

                               

编译完成后,ffmpeg中会出现一个android的文件夹:

     include文件夹中是一些要引用的头文件,红色箭头所指,就是得到的so文件。

三、在Android项目中引入ffmpeg的so库

  • 打开一个android项目,新建在main下新建一个jni文件夹,并将include文件夹和libffmpeg.so文件复制到jni目录下:

然后将ffmpeg文件下下的ffmpeg.h, ffmpeg.c, ffmpeg_opt.c, ffmpeg_filter.c,cmdutils.c, cmdutils.h, cmdutils_common_opts.h 到jni目录下,这里要注意的是,需要对ffmpeg.c和ffmpeg.h两个文件进行修改,(参考http://www.ihubin.com/blog/android-ffmpeg-demo-4/ ,此文中的step3)

准备工作基本完成,下面开始调用libffmpeg.so

四、搭建开发流程

1.新建一个FFmpegRun.java,用来调用ffmpeg的类:

public class FFmpegRun {
   
    public native static int run(String[] commands);

  
}

2.获取c语言借口的函数声明

点击android studio下面的terminal窗口,切换到项目下的java目录下,执行下面的命定(根据自己的文件名,适当修改)

javah com.example.ffmpegdemo.FFmpegRun

 3. 执行完成以后,刷新一下,会在src/main/java目录下生成一个com_example_ffmpegdemo_FFmpegRun.h的文件,

     把这个文件移动到jni目录下。

4. 在jni目录下手动创建三个文件,分别是Android.mk,Application.mk,com_example_ffmpegdemo_FFmpegRun.c

Android.mk文件内容:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeginvoke
LOCAL_SRC_FILES := com_tangyx_video_ffmpeg_FFmpegRun.c ffmpeg.c ffmpeg_opt.c cmdutils.c ffmpeg_filter.c
LOCAL_C_INCLUDES := /Users/UserName/Downloads/ffmpeg    #这里修改成你的ffmpeg文件夹路径
LOCAL_LDLIBS := -llog -lz -ldl
LOCAL_SHARED_LIBRARIES := ffmpeg

include $(BUILD_SHARED_LIBRARY)

LOCAL_C_INCLUDES的路径记得修改为你当前ffmepg文件夹的路径。
LOCAL_SRC_FILES第一个c文件的引用记得改为你当前jni下生成的c文件。

Application.mk的内容:

APP_ABI := armeabi-v7a
APP_BUILD_SCRIPT := Android.mk
APP_PLATFORM := android-15

 这里要注意:APP_ABI要和包含前面所设置的cpu类型。

com_example_ffmpegdemo_FFmpegRun.c文件的内容:

#include "com_example_ffmpegdemo_FFmpegRun.h"
#include "ffmpeg.h"
#include <string.h>
/*
 * Method:    run
 * Signature: (Ljava/lang/String;)I
 */
JNIEXPORT jint JNICALL Java_com_example_ffmpegdemo_FFmpegRun_run(JNIEnv *env,
        jclass obj, jobjectArray commands) {

    int argc = (*env)->GetArrayLength(env, commands);
    char *argv[argc];

    int i;
    for (i = 0; i < argc; i++) {
        jstring js = (jstring) (*env)->GetObjectArrayElement(env, commands, i);
        argv[i] = (char*) (*env)->GetStringUTFChars(env, js, 0);
    }
    return run(argc, argv);
}

 

第一行的include引用你当前jni下生成的.h文件.

5.开始编译。

打开terminal进入到jni目录下,执行命令:ndk-build

等待编译完成:

编译成功,刷新main项目,会多出2个文件夹,分别是lib和obj

 

lib下的生成了对应框架下需要用到的so文件,把armeabi和armeabi-v7a两个文件夹考到jniLib或者main下面自己创建的libs文件夹下

我这里是自己创建的lib文件夹,所以在app module下build.gradle文件中新

sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
            jni.srcDirs = []
        }
    }

 到这里,基本把ffmpeg集成到了android项目中,下面就是根据业务场景,去使用ffmpeg啦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值