近期项目需要解析苹果的HLS流媒体协议,而FFmpeg从0.11.1“Happiness”版本开始,才增加了对HLS协议的支持。目前网上关于FFmpeg编译移植的文章有很多,但大多都是对旧版本的说明。新版本的源码对很多地方做了改动,包括一些变量名、常量名、函数名、函数参数、结构体等,所以在用旧版本的JNI接口时,需要相应地做出改动。这个编译移植工作确实花了本人不少时间,现在总结一下,希望能给到大家一些帮助。说明一点,本文阐述的不一定都正确,大家在编译过程中,难免会遇到各种各样的错误,可以提出来,一起讨论。

编译环境:Ubuntu 12.04、Android NDK r8

一、下载源码、新建工程

下载地址:http://ffmpeg.org/download.html ,下载最新ffmpeg-0.11.1压缩包。

在$NDK_HOME/samples/目录下(我的是/root/Develop/android-ndk-r8/samples/)创建一个FFMPEG-0.11目录,在里面新建一个jni目录,然后把ffmpeg源码解压放在jni里面,源码的文件夹重命名为libffmpeg,所以最后源码的路径是:

/root/Develop/android-ndk-r8/samples/FFMPEG-0.11/jni/libffmpeg

二、配置源代码

1. 创建config_common.sh脚本

在jni目录下创建一个config_common.sh,内容如下:

  1. #!/bin/bash
  2. FFCONFIG_COMMON='
  3. --enable-version3
  4. --disable-gpl
  5. --disable-nonfree
  6. --disable-debug
  7. --disable-ffmpeg
  8. --disable-ffplay
  9. --disable-ffserver
  10. --disable-ffprobe
  11. --disable-encoders
  12. --disable-muxers
  13. --disable-devices
  14. --disable-protocols
  15. --enable-protocol=file
  16. --disable-swscale
  17. --disable-avfilter
  18. --enable-network
  19. --disable-avdevice
  20. --enable-parsers
  21. --disable-decoders
  22. --disable-demuxers
  23. --enable-demuxer=matroska
  24. --disable-demuxer=rm
  25. --disable-demuxer=avi
  26. --disable-demuxer=flv
  27. --disable-demuxer=mov
  28. --enable-demuxer=mp3
  29. --enable-demuxer=mpegps
  30. --enable-demuxer=mpegvideo
  31. --enable-demuxer=asf
  32. --enable-decoder=aac
  33. --enable-decoder=ac3
  34. --enable-decoder=dca
  35. --enable-decoder=flv
  36. --disable-decoder=h263
  37. --disable-decoder=h264
  38. --enable-decoder=svq3
  39. --enable-decoder=amrnb
  40. --enable-decoder=nellymoser
  41. --enable-decoder=pcm_alaw
  42. --enable-decoder=pcm_dvd
  43. --enable-decoder=pcm_mulaw
  44. --enable-decoder=pcm_s16be
  45. --enable-decoder=pcm_s16le
  46. --enable-decoder=pcm_s16le_planar
  47. --enable-decoder=pcm_s24be
  48. --enable-decoder=pcm_s24daud
  49. --enable-decoder=pcm_s24le
  50. --enable-decoder=pcm_s32be
  51. --enable-decoder=pcm_s32le
  52. --enable-decoder=pcm_s8
  53. --enable-decoder=pcm_u16be
  54. --enable-decoder=pcm_u16le
  55. --enable-decoder=pcm_u24be
  56. --enable-decoder=pcm_u24le
  57. --enable-decoder=pcm_u32be
  58. --enable-decoder=pcm_u32le
  59. --enable-decoder=atrac3
  60. --enable-decoder=pcm_u8
  61. --enable-decoder=sipr
  62. --enable-decoder=mjpeg
  63. --enable-decoder=mp1
  64. --enable-decoder=mp2
  65. --enable-decoder=mp3
  66. --enable-decoder=tscc
  67. --enable-decoder=mpeg1video
  68. --enable-decoder=mpeg2video
  69. --enable-decoder=mpeg4
  70. --enable-decoder=ra_144
  71. --enable-decoder=ra_288
  72. --enable-decoder=cook
  73. --enable-decoder=rv10
  74. --enable-decoder=rv20
  75. --enable-decoder=rv30
  76. --enable-decoder=rv40
  77. --enable-decoder=wmav1
  78. --enable-decoder=wmav2
  79. --enable-decoder=wmapro
  80. --disable-decoder=wmv1
  81. --disable-decoder=wmv2
  82. --disable-decoder=wmv3
  83. --enable-decoder=vc1
  84. --enable-decoder=msmpeg4v1
  85. --enable-decoder=msmpeg4v2
  86. --enable-decoder=msmpeg4v3
  87. '

可以根据需要自行配置以上参数。

2. 创建config.sh脚本

在jni目录下创建一个config.sh,内容如下:

  1. #!/bin/bash
  2. source config_common.sh            /*这里执行上面的config_common.sh脚本*/
  3. cd libffmpeg               /*进入libffmpeg目录*/
  4. PREBUILT=/root/Develop/android-ndk-r8/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86
  5. PLATFORM=/root/Develop/android-ndk-r8/platforms/android-14/arch-arm
  6. ./configure --target-os=linux \
  7. --arch=arm \
  8. --enable-shared \
  9. --enable-cross-compile \
  10. --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
  11. --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
  12. --strip=$PREBUILT/bin/arm-linux-androideabi-strip \
  13. --extra-cflags="-fPIC -DANDROID" \
  14. --extra-ldflags="-Wl,-T,$PREBUILT/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtbegin.o $PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtend.o -lc -lm -ldl" \
  15. $FFCONFIG_COMMON
  16. cd ..                       /*返回jni目录*/
  17. ndk-build clean

3.  执行config.sh脚本

然后打开终端,执行以下命令:

$chmod +x config.sh /*赋予config.sh执行权限*/
$./config.sh

如果配置正确的话,显示出来的最后两行是这样的:

License:LGPL version 3 or later
Creating config.mak and config.h...

若出现WARNING:/root/Develop/android-ndk-8/.............../arm-linux-androideabi-pkg-config not found, library detection may fail. 可忽略。

4. 修改config.h

进入jni/libffmpeg/目录,在刚刚生成的config.h中找到这句:

#define restrict restrict

因为Android的gcc并不认得restrict这个关键字,所以把它改写成:

#define restrict

如果需要联网的话,还需要将config.h中的以下定义置为1:

#define CONFIG_NETWORK 1
#define CONFIG_HTTP_PROTOCOL 1
#define CONFIG_HTTPPROXY_PROTOCOL 1
#define CONFIG_HTTPS_PROTOCOL 1
#define CONFIG_TCP_PROTOCOL 1
#define CONFIG_UDP_PROTOCOL 1
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
#define HAVE_STRUCT_ADDRINFO 1
#define HAVE_SOCKLEN_T 1

#define HAVE_INET_ATON 0

相应的,config.mak中也需要修改为:

CONFIG_NETWORK=yes
CONFIG_HTTP_PROTOCOL=yes
CONFIG_HTTPPROXY_PROTOCOL=yes
CONFIG_HTTPS_PROTOCOL=yes 
CONFIG_TCP_PROTOCOL=yes
CONFIG_UDP_PROTOCOL=yes
HAVE_STRUCT_SOCKADDR_STORAGE=yes
HAVE_STRUCT_ADDRINFO=yes
HAVE_SOCKLEN_T=yes

!HAVE_INET_ATON=yes

5. 修改libm.h文件

将/libavutil/libm.h中所有的static函数全部注释掉。

6. 修改Makefile文件

分別修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale目录下的Makefile文件,将下面一句注释掉:

include $(SUBDIR)../config.mak

7. 新建av.mk脚本

在/jni/libffmpeg下建立一个脚本文件av.mk,內容如下:

# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale

#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak

OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile
ifdef ADDITION_INC
include $(ADDITION_INC)
endif

# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)

FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS = -DHAVE_AV_CONFIG_H $(CFLAGS)
FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"

ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))

ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif

C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))

FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))

8. 新建Android.mk脚本

在jni目录下新建Android.mk,內容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := ExportJNI.cpp ExportPlayer.cpp PacketQueue.cpp /*其中ExportJNI.cpp是我编写的JNI接口*/
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libswscale libavutil libpostproc ffmpeg libsubtitle /*注意Libraries的顺序*/
LOCAL_MODULE := export /*最终生成libexport.so*/ 
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := -D__STDC_CONSTANT_MACROS -I$(LOCAL_PATH)/libffmpeg/ -I$(LOCAL_PATH)/libsubtitle/
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))

在jni/libffmpeg目录下新建Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := settings.c MyLog.cpp       /*如果不需要打印输出等辅助功能,这行可删去*/
LOCAL_MODULE := ffmpeg
LOCAL_ARM_MODE := arm
include $(BUILD_STATIC_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))

在jni/libffmpeg/libavformat目录下新建Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
LOCAL_ARM_MODE := arm
include $(BUILD_STATIC_LIBRARY)

在jni/libffmpeg/libavcodec目录下新建Android.mk:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ADDITION_INC := $(LOCAL_PATH)/arm/Makefile
include $(LOCAL_PATH)/../av.mk
ADDITION_INC :=

LOCAL_SRC_FILES := $(FFFILES)

LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
ifeq ($(TARGET_ARCH_ABI),armeabi)
LOCAL_CFLAGS += -DUSE_INT
endif

LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
LOCAL_ARM_MODE := arm
include $(BUILD_STATIC_LIBRARY)

在libavfilter、libavutil、libpostproc和libswscale目录下都分別新建Android.mk:

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
include$(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES:= $(FFFILES)
LOCAL_C_INCLUDES:= \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS+= $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES:= $(FFLIBS)
LOCAL_MODULE:= $(FFNAME)
include$(BUILD_STATIC_LIBRARY)

9. 新建Application.mk脚本

在jni目录下创建一个Application.mk,内容如下:

APP_STL := stlport_static
APP_ABI := armeabi

三、 NDK编译

在FFMPEG-0.11/下执行ndk-build:

$/ FFMPEG-0.11# ndk-build

编译过程需要十分钟左右,最后会在FFMPEG-0.11/obj/local/armeabi/目录下生成libavcodec.a、libavformat.a、libavutil.a、libffmpeg.a、libswscale.a和libpostproc.a以及libexport.so,在FFMPEG-0.11/libs/armeabi/目录下生成libexport.so。

转载:http://superonion.iteye.com/blog/1609777

FFmpeg 移植 Android的更多相关文章

  1. ffmpeg 移植到 android 并使用

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

  2. Cocos2dx-3.0版本 从开发环境搭建(Win32)到项目移植Android平台过程详解

    作为重量级的跨平台开发的游戏引擎,Cocos2d-x在现今的手游开发领域占有重要地位.那么问题来了,作为Cocos2dx的学习者,它的可移植特性我们就需要掌握,要不然总觉得少一门技能.然而这个时候各种 ...

  3. How to Build FFmpeg for Android

    http://www.roman10.net/how-to-build-ffmpeg-for-android/ ffmpeg is an open-source platform for record ...

  4. 关于文章“cocos2dx移植android平台-我的血泪史”需要注意事项

    关于文章"cocos2dx移植android平台-我的血泪史"需要注意事项 在上次转载的这篇文章中,按照配置一步一步的下去.发现工程中在Android.mk中有一处错误.直接bui ...

  5. cocos2dx使用了第三方库照样移植android平台-解决iconv库的移植问题

    当我写这篇文章的时候我是怀着激动的心情的,因为我又解决了一个技术问题.你可能对题目还一知半解,这是什么意思,我之所以要写这篇文章就是要解决当我们在cocos2dx中使用了第三方库的时候,移植到andr ...

  6. Cocos2d-x移植Android 常见问题处理办法

    1.函数.变量出现"could not be resolved "问题 出现此问题通常是没有找到cocos2d-x声明的头文件.在eclipse将cocos2d的头文件文件夹引入. ...

  7. Ffmpeg移植S3C2440

    Ffmpeg移植过程: FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证.它的移植同样遵循LGPL或GPL移植方法:configure.make.make ...

  8. cocos2dx-3.0(21) 移植android平台 说多了都是泪

    ----我的生活,我的点点滴滴! ! 网上3.0的教程真心少.能够说没有吧,大多都是2.x 或者 3.0測试版之类的,因为我心大,没有照着2.x去搞,后来搞完后总结了一下,发觉事实上3.0的移植and ...

  9. Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】

    2014.5.16 为了验证一下下载的CM11的源码有没有问题,决定编译一下cm官方支持的机器,手上正好有台nexus7 2012,就拿它为例测试一下在mac os x平台的整个编译过程. 1. 最开 ...

随机推荐

  1. JavaScript实现延时提示框

    <html> <head> <meta charset="utf-8"> <title>无标题文档</title> &l ...

  2. Websphere 手动模拟删除应用操作

    Websphere  手动模拟删除应用操作 切记:不要在程序还在运行的时候,直接的remove掉应用程序,不然,会发生意外的错误.       最近,在项目中,不小心手动移除了正在运行的应用,发现se ...

  3. 三维重建:Kinect几何映射-SDK景深数据处理

    此文大量使用XML,非C类的代码,看看图即可. 原文链接:Kinect for Windows SDK开发入门(五):景深数据处理 3. 对物体进行测量 像上篇文章中对深度值测量原理进行讨论的那样,像 ...

  4. spring boot的项目名称问题

    spring boot直接执行main函数时是不需要加项目名称,但是可以在application配置文件中配置server.context-path=/*来配置项目名称: spring mvc的运行方 ...

  5. 前端web通过flask操作数据库-增删改查

    后端python代码: #coding:utf8 from flask import Flask,request,render_template import pymysql as mysql imp ...

  6. MongoDB经典入门(2)--shell命令

    MongoDB是MongoDB自带的交互式Javascript shell,用来对MongoDB进行操作和管理的交互式环境. 使用 "./mongo --help" 可查看相关连接 ...

  7. 洛谷P2827 蚯蚓 队列 + 观察

    我们不难发现先被切开的两半一定比后被切开的两半大,这样就天然的生成了队列的单调性,就可以省去一个log.所以,我们开三个队列,分别为origin,big,smallorigin, big, small ...

  8. python3发送邮件

    import smtplib from email.mime.text import MIMEText from email.utils import formataddr import psutil ...

  9. 报错The jarsigner could not be found. Make sure to run with the build with a JDK。的解决方法

    这种报错是因为eclipse启动时没有走你设置的jdk路径,eclipse走的路径/bin下没有jarsigner.exe.所以报错,解决办法: 指定eclipse启动jdk 按住alt键,用鼠标拖动 ...

  10. Webpack 学习记录之概念

    1 什么是webpack webpack是一个模块打包器,可以递归的构建一个依赖关系图,其中包含每个程序需要的每个模块,然后将所有模块打包成一个或多个bundle.他和其他的工具最大的不同在于他支持c ...