首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert)。

下载的文件为压缩包,解压后得到ffmpeg-3.3目录。

修改ffmpeg-3.3的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)'

原因:如果不修改配置,直接进行编译出来的so文件类似libavcodec.so.55.39.101,文件的版本号位于so之后,这样在Android上无法加载,所以需要修改!

编写build_android.sh脚本文件:

在编译FFmpeg之前需要进行配置,设置相应的环境变量等。所有的配置选项都在ffmpeg-3.3/configure这个脚本文件中,执行如下命令可查看所有的配置选项:

$ ./configure –help

下面将配置项和环境变量设置写成一个sh脚本文件来运行以便编译出Android平台需要的so文件出来。

build_android.sh的内容如下:

#!/bin/bash
NDK=/Users/renhui/framework/android-ndk-r14b
SYSROOT=$NDK/platforms/android-/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 \--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

需要确定的是NDK,SYSROOT和TOOLCHAIN是否是本地的环境,并确定cross-prefix指向的路径存在。

保存脚本文件后,将脚本的权限提升:

chmod  build_android.sh  

然后执行脚本,该脚本会完成对ffmpeg的配置,并生成config.h等配置文件,后面的编译会用到。如果未经过配置直接进行编译会提示无法找到config.h文件等错误。

然后执行下面两个命令:

$make
$make install

至此,会在ffmpeg-3.3目录下生成一个android目录,其/android/arm/lib目录下的so库文件就是能够在Android上运行的so库。

创建Demo工程,测试上面生成的so文件能否正常使用:

  1. 创建一个新的Android工程
  2. 在工程根目录下创建jni文件夹
  3. 在jni下创建prebuilt目录,然后:将上面编译成功的so文件放入到该目录下
  4. 创建包含native方法的类,先在src下创建cn.renhui包,然后创建FFmpegNative.java类文件。主要包括加载so库文件和一个native测试方法两部分,其内容如下: 
    package cn.renhui;
    
    public class FFmpegNative {
    
        static {
    System.loadLibrary("avutil-55");
    System.loadLibrary("avcodec-57");
    System.loadLibrary("swresample-2");
    System.loadLibrary("avformat-57");
    System.loadLibrary("swscale-4");
    System.loadLibrary("avfilter-6");
    System.loadLibrary("avdevice-57");
    System.loadLibrary("ffmpeg_codec");
    } public native int avcodec_find_decoder(int codecID);
  1. 用javah创建.头文件: classes目录,执行:javah-jni cn.renhui.FFmpegNative,会在当前目录产生cn_renhui_FFmpegNative.h的C头文件;
  1. 根据头文件名,建立相同名字c文件cn_renhui_FFmpegNative.c,在这个源文件中实现头文件中定义的方法,代码如下:

    #include "cn_renhui_FFmpegNative.h"
    
    #ifdef __cplusplus
    extern "C" {
    #endif JNIEXPORT jint JNICALL Java_cn_renhui_FFmpegNative_avcodec_1find_1decoder
    (JNIEnv *env, jobject obj, jint codecID)
    {
    AVCodec *codec = NULL; /* register all formats and codecs */
    av_register_all(); codec = avcodec_find_decoder(codecID); if (codec != NULL)
    {
    return ;
    }
    else
    {
    return -;
    }
    } #ifdef __cplusplus
    }
    #endif
  1. 编写Android.mk,内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := avcodec--prebuilt
    LOCAL_SRC_FILES := prebuilt/libavcodec-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := avdevice--prebuilt
    LOCAL_SRC_FILES := prebuilt/libavdevice-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := avfilter--prebuilt
    LOCAL_SRC_FILES := prebuilt/libavfilter-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := avformat--prebuilt
    LOCAL_SRC_FILES := prebuilt/libavformat-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := avutil--prebuilt
    LOCAL_SRC_FILES := prebuilt/libavutil-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := avswresample--prebuilt
    LOCAL_SRC_FILES := prebuilt/libswresample-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS)
    LOCAL_MODULE := swscale--prebuilt
    LOCAL_SRC_FILES := prebuilt/libswscale-.so
    include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := ffmpeg_codec
    LOCAL_SRC_FILES := cn_dennishucd_FFmpegNative.c LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
    LOCAL_SHARED_LIBRARIES := avcodec--prebuilt avdevice--prebuilt avfilter--prebuilt avformat--prebuilt avutil--prebuilt include $(BUILD_SHARED_LIBRARY)
  1. 编译so文件,执行ndk-build
  2. 新建一个Activity,进行测试,测试核心代码:
    FFmpegNative ffmpeg = new FFmpegNative();
    
    int codecID = 28;
    
    int res = ffmpeg.avcodec_find_decoder(codecID);
    
    if (res == 0) {
    tv.setText("Success!");
    } else {
    tv.setText("Failed!");
    }

28是H264的编解码ID,可以在ffmpeg的源代码中找到,它是枚举类型定义的。在C语言中,可以换算为整型值。这里测试能否找到H264编解码,如果能找到,说明调用ffmpeg的库函数是成功的,这也表明我们编译的so文件是基本可用。


2018年8月20号补充说明:目前最新版本的FFmpeg版本号为4.0.1 ,上面的方法能继续正常使用

将 FFmpeg 移植到 Android平台 (完整版)的更多相关文章

  1. FFmpeg 学习(三):将 FFmpeg 移植到 Android平台

    首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert). 下载的文件为压缩包,解压后得到ffmpeg-3. ...

  2. cygwin编译ffmpeg移植到android平台问题集锦

    编译环境: windows xp Cygwin 1.1.3.1 NDK r9 1.提示各种command not found 比如 ./config.sh: line 6: $'--arch=arm\ ...

  3. 基于Cocos2d-x-1.0.1的飞机大战游戏迁移到Cocos2d-x-3.0版本,并移植到Android平台成功运行

    一.版本迁移中的问题 1.游戏元素Sprite.Label.Action等等的创建函数名都改为create. 2.函数的回调callfunc_selectorcallfuncN_selectorcal ...

  4. Windows下将ImageMagick移植到Android平台

    Windows下将ImageMagick移植到Android平台 原文链接  http://www.pedant.cn/2014/06/18/imagemagick-ported-android/ I ...

  5. J2ME项目移植到Android平台六大注意事项

    很多J2ME项目如何移植到Android平台呢?Java虽然号称是跨平台应用但是目前的移植问题还是比较严重的,不知道未来Sun推出JavaFx或F3时会出现什么问题,如何从J2ME移植到Android ...

  6. Unity3D之移植学习笔记:移植到Android平台更好的方法

    接上文,之前我们采用了直接将Unity项目导出为Eclipse项目来修改的方式,这种做法存在的一个最大的问题就是:每当Unity被修改之后,都需要重新导出,而每次导出的项目在Android平台方面的J ...

  7. Android照片墙完整版,的完美结合LruCache和DiskLruCache

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/34093441 在上一篇文章其中,我们学习了DiskLruCache的概念和基本使用 ...

  8. ffmpeg 移植到 android 并使用

    同步更新至个人blog:http://dxjia.cn/2015/07/ffmpeg-porting-to-android/ 空闲做了个小应用,从视频里截图,然后再将截图拼接为一个gif动画: 起初使 ...

  9. Android照片墙完整版,完美结合LruCache和DiskLruCache

    转载地址:http://blog.csdn.net/guolin_blog/article/details/34093441#comments 在上一篇文章当中,我们学习了DiskLruCache的概 ...

随机推荐

  1. ABPZero中的Name和SurName处理

    使用ABPzero的朋友们都知道,User表中有Name和Surname两个字段,这两个字段对于国内的用户来说相当的不友好. 我们在尝试了很多的方法之后,发现无法完美将他们干掉. 所以尝试使用了一个比 ...

  2. win7下用SSH连接linux虚拟机

    本文来自转载:原文 [需求] 在win7环境下用SSH(SecureShell)连接本地的一台虚拟机上ubuntu(11.10)系统  [环境] win7,ubuntu,vmware(8.0) [方案 ...

  3. superslide2插件

    地址:http://www.superslide2.com/ 做自适应要注意该宽度和高度 等比缩放

  4. Redis技术分享

    环境介绍: 开发环境: spring3+tomcat7+maven3+redis-3.0.7 运行环境: Linux 前言: 项目中引入redis背景: 项目中最初将科目.打印.利润表.资产负债表.现 ...

  5. open vswitch常用操作

    以下操作都需要root权限运行,在所有命令中br0表示网桥名称,eth0为网卡名称. 添加网桥: #ovs-vsctl add-br br0 列出open vswitch中的所有网桥: #ovs-vs ...

  6. JS的块级作用域

    今天带来的是 "对<你不知道的js>中块级作用域的总结" 分享: 1)用with从对象中创建出来的作用域只在with声明中而非外部作用域有效,同时可以访问已有对象的属性 ...

  7. 利用Unity3D实现多平台增强现实网络游戏的一种方案

    这几天去厦门参加了VALSE2017会议,对于其中某个环节展示的有关增强现实游戏的部分印象深刻.因为前两年一度沉迷于利用各类引擎开发游戏,所以也曾经以Pokemon GO为模板开发过一款多平台增强现实 ...

  8. Struts2框架的基本使用(二)

    上一篇 Struts2框架的基本使用 我们限于篇幅,最后简单介绍了Action的配置问题,本篇接着介绍有关框架的一些其他基本用法,主要内容如下: Action的基本配置 result的基本配置 Str ...

  9. 【算法系列学习】codeforces D. Mike and distribution 二维贪心

    http://codeforces.com/contest/798/problem/D http://blog.csdn.net/yasola/article/details/70477816 对于二 ...

  10. CentOS下的yum命令

    yum命令是rpm的一款前端工具,可以安装.更新.卸载rpm包,可以从指定服务器下下载rpm包并安装,可以自动解决依赖问题. 语法: yum [options] [command] [package ...