Android-mac下ffmpeg从0开始编译

0. 题外话

基于ffmpeg4.1版本.(好吧,最后我改成3.3.8版本了)

这次编译真的是惨痛的经历.先是经历了linux空间不足,然后是编译报错

/bin/sh: ranlib/usr/local/lib/libavdevice.a: No such file or directory

这个问题就是

LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'

引号中少了一个空格,网上很多教程都没有空格,改成这样就好了

LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'

最后成功编译出来了 

1. 开始编译的步骤

首先我们需要ffmpeg,ndk.

ffmpeg下载地址

ndk下载地址

注: 我用的是git地址下载的,最好使用git地址.这样切版本比较方便.

ndk就无所谓什么版本了

ndk需要配置环境变量.不然会报

-bash: ndk-build: command not found

ffmpeg下载完成之后.注意tag的切换.因为下载过来是4.1版本的,我们需要切换到3.3.8版本.因为4.1版本会报错

/bin/sh: ranlib/usr/local/lib/libavdevice.a: No such file or directory

git checkout -b n3.3.8

切换完成之后开始编译了

在编译前,在源码中,修改FFmpeg的configure

也就是根目录下的configure

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'  
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'  
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'  

替换为

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

我这边是在3305行左右的样子.我是直接注释了,你也可以替换

先是写入脚本.在ffmpeg下面创建一个build.sh脚本.随便叫什么名字.都可以,反正我是叫build.sh

#!/bin/sh
NDK=你的ndk路径
SYSROOT=$NDK/platforms/android-21/arch-arm
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one(){
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

这里执行命令的时候需要注意.因为涉及到make install.所以,我们需要root权限,所以执行命令为

sudo sh build.sh

注: 如果这里爆出No such file or directory

说明你的系统不适应,修改一下build.sh就可以了,也就是buildone方法里面,每个字段加回车

#!/bin/sh
NDK=你的ndk路径
SYSROOT=$NDK/platforms/android-27/arch-arm
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
function build_one(){

./configure \

--prefix=$PREFIX \

--enable-shared \

--disable-static \

--disable-doc \

--disable-ffmpeg \

--disable-ffplay \

--disable-ffprobe \

--disable-ffserver \

--disable-avdevice \

--disable-doc \

--disable-symver \

--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \

--target-os=linux \

--arch=arm \

--enable-cross-compile \

--sysroot=$SYSROOT \

--extra-cflags="-Os -fpic $ADDI_CFLAGS" \

--extra-ldflags="$ADDI_LDFLAGS" \

$ADDITIONAL_CONFIGURE_FLAG

make clean

make

make install

}
CPU=armeabi-v7a
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

这里编译完成之后,就会在根目录中会出现一个android的文件夹.

然后创建一个可以开始快乐的jni编译了...

现在才是正式开始

先是在工程的目录下面src/main创建一个名字叫jni的文件夹.

然后把android中的include和lib两个文件夹移到jni目录下.

然后右键.File 创建三个文件

Android.mk

Application.mk

ffmpeg-jni.c

创建这三个文件,然后目录结构应该是这样的..

然后就是开始写文件内容了

以下是Android.mk文件的内容

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-57.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat-57.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale-4.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil-55.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter-6.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= libswresample
LOCAL_SRC_FILES:= lib/libswresample-2.so
LOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= FFmpegCodec
LOCAL_SRC_FILES:= ffmpeg-jni.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil swresample swscale
include $(BUILD_SHARED_LIBRARY)

然后接着是Applicaiton.mk的内容

APP_ABI是你要编译的so的cpu支持类型,我就写了一个arm-v7a.可以有别的,这里可选armeabi,x86,mips和all等

APP_PLATFORM指的是最低版

APP_ABI :=armeabi-v7a
APP_PLATFORM := android-21
APP_OPTIM := debug
APP_STL := gnustl_static

最后就是ffmpeg-jni.c的内容了

函数申明语法:JNIEXPORT jstring Java_包名activity名函数名,包名中间的点号.全部变成下划线_

例如:我在包名com.ccx.ffmpeg下面的MainActivity中要使用avcodecInfo这个函数,

JNIEXPORT jstring Java_com_ccx_ffmpeg_MainActivity_avcodecInfo

#include <stdio.h>
#include "libavformat/avformat.h"
#include <libavfilter/avfilter.h>
#include <jni.h>
JNIEXPORT jstring Java_包名_MainActivity_avcodecInfo(JNIEnv* env, jobject obj)
{
char info[4000] = { 0 };
int count = 100; //输出前100个codec名字
av_register_all();//初始化所有decoder和encoder,注册所有容器类型和codec
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL && count > 0){
//输出解码器和编码器
if(c_temp->decode != NULL){
sprintf(info,"%s[Dec]",info);
}
else{
sprintf(info,"%s[Enc]",info);
}
sprintf(info,"%s[%10s]\n",info,c_temp->name);
c_temp = c_temp->next;
count--;
}
return (*env)->NewStringUTF(env, info);
}

然后这些就好了.

cd 到jni目录下..

输入

ndk-build

这样就编译完成了

你会发现在目录中多了两个文件夹,libs和obj文件夹.libs就是已经编译好的so库了.

这个时候就可以开始使用le

猜你喜欢

转载自blog.csdn.net/ci250454344/article/details/83827348
今日推荐