http://blog.sina.com.cn/s/blog_69a04cf40100x1fr.html

从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmpeg开发的。如今最火的智能手机操作系统Android上的很多第三方视频播放器也是基于FFmpeg实现全格式支持。由于Android通常跑在ARM处理器上,而且Android使用了自己的libc库(即bionic),因此要在Android上编译和使用FFmpeg需要做一些移植工作,好在FFmpeg本身用C写成,很好地支持跨平台移植,实现这个目的并不难,事实上已经有很多前辈做过这方面的工作并公开了他们的成果,大概列一下:

1.     Rockplayer:

http://rockplayer.freecoder.org/index_cn.html

http://blog.csdn.net/harry_helei/article/details/6322767

2.     havlenapetr:

http://github.com/havlenapetr/FFMpeg

http://blog.csdn.net/scut1135/article/details/6536157

http://hi.baidu.com/eefolks/blog/item/e0329e4682859129cefca351.html

http://ajavn.com/anzhuotuandui/4351.html

3.     halfninja:

https://github.com/halfninja/android-ffmpeg-x264

4.     olvaffe's:

http://gitorious.org/~olvaffe/ffmpeg/ffmpeg-android

http://www.nujk.com/ffmpeg-on-android

5.     流媒体开发论坛 - 罗索工作室:

http://www.rosoo.net/a/201108/14834.html

http://bbs.rosoo.net/thread-6252-1-1.html

最近本人工作中也需要在Android上使用FFmpeg,有了前人的基础就不必自己从头做起,我选择了Rockplayer的方案进行实践。Rockplayer是Android上最有名的第三方视频播放器之一,其开发者根据LGPL协议公开了所使用的FFmpeg源码,该方案用Android NDK将FFmpeg源码编译生成一个单独的共享库libffmpeg.so,其中静态链接了libavformat、libavcodec、libavutil等模块,要使用FFmpeg只需要调用这一个.so即可。当然有了这个库还只是第一步,要利用FFmpeg开发一个自己的播放器或者把FFmpeg集成到Android本身的播放引擎stagefright中还需要很多其他工作,包括针对硬件平台进行优化。目前我做的只是编译出libffmpeg.so以及将FFmpeg自带的工具ffmpeg在adb shell中跑起来。我是在Android 3.2(Honeycomb)上编译FFmpeg,所用NDK版本为r7,在Android的其他版本上编译也大同小异。下面把具体编译步骤描述如下,假定NDK安装在~/android-ndk-r7:

1.   首先从FFmpeg官网下载最新的release版本源码ffmpeg-0.10.tar.gz解压缩到Android源码树的external/ffmpeg/下(通常第三方源码都放在external这个文件夹下)。

2.   修改$ANDROID_BUILD_TOP/external/ffmpeg/libavdevice/v 4l.c,在
#include <linux/videodev.h> 之上增加2行:

typedef __signed__ long long __s64;

typedef unsigned long long __u64;

否则编译不过。

3.   准备一个编译脚本build_android.sh并放在$ANDROID_BUILD_TOP/external/ffmpeg/下面,这个脚本也是Rockplayer提供的,需做一些修改,其内容附在后面。

4.   在$ANDROID_BUILD_TOP/external/ffmpeg/下面运行./build_android.sh开始编译FFmpeg,编译好的libffmpeg.so会放在文件夹android里面,一共有3个版本分别对应3种ARM体系结构,包括armv7-a、armv7-a-vfp、armv6_vfp,根据所运行的硬件平台选取其中一个版本。为了编译使用FFmpeg的程序时可以方便地找到libffmpeg.so,可将它复制到$OUT/system/lib/和$OUT/obj/lib/,当然这一步也可以加在build_android.sh中做。

5.   接下来就是编译可执行文件ffmpeg了,这个工具可以在命令行下完成FFmpeg提供的几乎所有功能包括编码、解码、转码等,也是用来调试和验证很有用的工具。其实上述编译完后在$ANDROID_BUILD_TOP/external/ffmpeg/下也会生成ffmpeg,但是在设备上无法运行。为了编出能在设备上运行的ffmpeg,可以写一个简单的Android.mk,其内容如下:

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \

cmdutils.c \

ffmpeg.c

LOCAL_C_INCLUDES :=

LOCAL_SHARED_LIBRARIES := \

libffmpeg

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := ffmpeg

include $(BUILD_EXECUTABLE)

将这个Android.mk放在$ANDROID_BUILD_TOP/external/ffmpeg/下面,运行mm,编好的ffmpeg在$OUT/system/bin/中。

6.   将上面编好的libffmpeg.so和ffmpeg分别用adb push复制到设备的/system/lib/和/system/bin/,push之前可先对libffmpeg.so做一下strip否则太大。现在就可以在adb shell中运行ffmpeg了,使用方法与在PC上相同。当然如果要用到其他开源库例如x264那么还需要把它们也移植到Android。

以上是基本的步骤,仅供参考,可以根据具体情况修改build_android.sh里面的配置选项。如前所述,编译FFmpeg只是第一步,后续还有很多工作需要做,今后如果有进展再贴上来。

最后附上build_android.sh供参考,在此也感谢Rockplayer的开发者:

#!/bin/bash

######################################################

# FFmpeg builds script for Android+ARM platform

#

# This script is released under term of

#   CDDL (http://www.opensource.org/licenses/cddl1)

# Wrote by pinxue (~@gmail.com) from RockPlayer.com

#                                   2010-8 ~ 2011-4

######################################################

######################################################

# Usage:

#   put this script in top of FFmpeg source tree

#   ./build_android

#

# It generates binary for following architectures:

#     ARMv6

#     ARMv6+VFP

#     ARMv7+VFPv3-d16 (Tegra2)

#     ARMv7+Neon (Cortex-A8)

#

# Customizing:

# 1. Feel free to change ./configure parameters for more features

# 2. To adapt other ARM variants

#       set $CPU and $OPTIMIZE_CFLAGS

#       call build_one

######################################################

NDK=~/android-ndk-r7

PLATFORM=$NDK/platforms/android-8/arch-arm/

PREBUILT=../../prebuilt/linux-x86/toolchain/arm-eabi-4.4.3

function build_one

{

# -fasm : required. Android header file uses asm keyword instead of __asm__ , but most of c dialect (like ansi,c99,gnu99) implies -fno-asm.

#   ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/asm/byteorder.h: In function '___arch__swab32':

#   ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/asm/byteorder.h:25: error: expected ')' before ':' token

# -fno-short-enums : optimized.  Else FFmpeg obj will generate a huge number of warning for variable-size enums,

#   though we may suppress them by --no-enum-size-warning, it would be better to avoid it.

#   .../ld: warning: cmdutils.o uses variable-size enums yet the output is to use 32-bit enums; use of enum values across objects may fail

# --extra-libs="-lgcc" : required. Else cannot solve some runtime function symbols

#   ... undefined reference to `__aeabi_f2uiz'

# --enable-protocols : required. Without this option, the file open always fails mysteriously.

#   FFmpeg's av_open_input_file will invoke file format probing functions, but because most of useful demuxers has flag of zero

#   which cause them are ignored during file format probling and fall to url stream parsing,

#   if protocols are disabled, the file:// url cannot be opened as well.

# $PREBUILT/bin/arm-eabi-ar d libavcodec/libavcodec.a inverse.o : required.

#   FFmpeg includes two copies of inverse.c both in libavutil and libavcodec for performance consideration (not sure the benifit yet)

#   Without this step, final ld of generating libffmpeg.so will fail silently, if invoke ld through gcc, gcc will collect more reasonable error message.

# -llog: debug only, FFmpeg itself doesn't require it at all.

#   With this option, we may simply includes "utils/Log.h" and use LOGx() to observe FFmpeg's behavior

#   PS, it seems the toolchain implies -DNDEBUG somewhere, it would be safer to use following syntax

#    #ifdef NDEBUG

#        #undef NDEBUG

#        #define HAVE_NDEBUG

#    #endif

#    #include "utils/Log.h"

#    #ifdef HAVE_NDEBUG

#        #define NDEBUG

#        #undef HAVE_NDEBUG

#    #endif

# --whole-archive : required. Else ld generate a small .so file (about 15k)

# --no-stdlib : required. Android doesn't use standard c runtime but invited its own wheal (bionic libc) because of license consideration.

# space before \ of configure lines: required for some options. Else next line will be merged into previous lines's content and cause problem.

#   Especially the --extra-cflags, the next line will pass to gcc in this case and configure will say gcc cannot create executable.

# many options mentioned by articles over internet are implied by -O2 or -O3 already, need not repeat at all.

# two or three common optimization cflags are omitted because not sure about the trade off yet. invoke NDK build system with V=1 to find them.

# -Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x mentioned by almost every articles over internet, but it is not required to specify at all.

# -Dipv6mr_interface=ipv6mr_ifindex : required. Android inet header doesn't use ipv6mr_interface which is required by rfc, seems it generate this user space header file directly from kernel header file, but Linux kernel has decided to keep its own name for ever and ask user space header to use rfc name.

# HAVE_SYS_UIO_H : required. Else:

# In file included from ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/linux/socket.h:29,

#                 from ~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/sys/socket.h:33,

#                 from libavformat/network.h:35,

#                 from libavformat/utils.c:46:

#~/android/android-ndk-r4/build/platforms/android-5/arch-arm//usr/include/linux/uio.h:19: error: redefinition of 'struct iovec'

#

# --disable-doc : required because of strange bug of toolchain.

./configure --target-os=linux \

--prefix=$PREFIX \

--enable-cross-compile \

--extra-libs="-lgcc" \

--arch=arm \

--cc=$PREBUILT/bin/arm-eabi-gcc \

--cross-prefix=$PREBUILT/bin/arm-eabi- \

--nm=$PREBUILT/bin/arm-eabi-nm \

--sysroot=$PLATFORM \

--extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums  -fno-strict-aliasing -finline-limit=300 $OPTIMIZE_CFLAGS " \

--disable-shared \

--enable-static \

--extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -ldl -llog" \

--enable-parsers \

--enable-encoders  \

--enable-decoders \

--enable-muxers \

--enable-demuxers \

--enable-swscale  \

--enable-swscale-alpha \

--disable-ffplay \

--disable-ffprobe \

--disable-ffserver \

--enable-network \

--enable-indevs \

--disable-bsfs \

--enable-filters \

--enable-avfilter \

--enable-protocols  \

--enable-asm \

$ADDITIONAL_CONFIGURE_FLAG

#make clean

make  -j4 install

$PREBUILT/bin/arm-eabi-ar d libavcodec/libavcodec.a inverse.o

$PREBUILT/bin/arm-eabi-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -soname libffmpeg.so -shared -nostdlib  -z,noexecstack -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libavfilter/libavfilter.a libswscale/libswscale.a libavdevice/libavdevice.a libswresample/libswresample.a -lc -lm -lz -ldl -llog  --warn-once  --dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/arm-eabi/4.4.3/libgcc.a

}

#arm v6

CPU=armv6

OPTIMIZE_CFLAGS="-marm -march=$CPU"

PREFIX=./android/$CPU

ADDITIONAL_CONFIGURE_FLAG=

#build_one

#arm v7vfpv3

CPU=armv7-a

OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU "

PREFIX=./android/$CPU

ADDITIONAL_CONFIGURE_FLAG=

build_one

#arm v7vfp

CPU=armv7-a

OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "

PREFIX=./android/$CPU-vfp

ADDITIONAL_CONFIGURE_FLAG=

build_one

#arm v7n

CPU=armv7-a

OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"

PREFIX=./android/$CPU

ADDITIONAL_CONFIGURE_FLAG=--enable-neon

build_one

#arm v6+vfp

CPU=armv6

OPTIMIZE_CFLAGS="-DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU"

PREFIX=./android/${CPU}_vfp

ADDITIONAL_CONFIGURE_FLAG=

build_one

FFmpeg在Android上的移植之第一步的更多相关文章

  1. Android上掌纹识别第一步:基于OpenCV的6种肤色分割 源码和效果图

    Android上掌纹识别第一步:基于OpenCV的6种肤色分割 源码和效果图 分类: OpenCV图像处理2013-02-21 21:35 6459人阅读 评论(8) 收藏 举报   原文链接  ht ...

  2. FFmpeg在Android上的移植优化步骤

    http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...

  3. ffmpeg在android上输出滑屏问题处理

    ffmpeg部分机器上有花屏的问题 原代码例如以下: while(av_read_frame(formatCtx, &packet)>=0 && !_stop & ...

  4. ffmpeg在am335x上的移植

    交叉编译工具:arm-linux-gcc 一.先下载一下文件 1. yasm-1.2.0.tar.gz 2. x264-snapshot-20140424-2245.tar.bz2 3. xvidco ...

  5. 转: CentOS上安装LAMP之第一步:Apache环境及安装过程报错解决方案(纯净系统环境)

    传送门:http://blog.csdn.net/zhangatle/article/details/77416996  小心坑!填完就懂怎么安装了 Note:要从零开始搭建,就不要嫌中间遇到各种问题 ...

  6. FFmpeg的Android平台移植—编译篇

    摘要:本文主要介绍将FFmpeg音视频编解码库移植到Android平台上的编译和基本测试过程. 环境准备: ubuntu-12.04.5 android-ndk64-r10-linux-x86_64. ...

  7. uboot在s3c2440上的移植(1)

    一.移植环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand,Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2.tgz u-b ...

  8. 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题2---CMAKE配置问题

    实际上这里说的是移植的第一步,下载到源码后,我用的是opencv2.4.9,解压缩,然后可以利用cmake-gui来进行configure配置,这里面需要设置交叉编译的工具链,具体的可以参考[Linu ...

  9. Openstack(企业私有云)万里长征第一步——安装

    一.前言 单位新进了十几台服务器,建了一个高标准的一体化机房,状似刘姥姥进大观园的我,从机房规划到企业私有云搭建一一重头学来,除了机房泥墙其他基本都涉猎到了. 从企业私有云这个名字就能看出这是多么复杂 ...

随机推荐

  1. 每天一道LeetCode--344. Reverse String

    Write a function that takes a string as input and returns the string reversed. Example:Given s = &qu ...

  2. SQL中char、varchar、nvarchar

    char    char是定长的,也就是当你输入的字符小于你指定的数目时,char(8),你输入的字符小于8时,它会再后面补空值.当你输入的字符大于指定的数时,它会截取超出的字符.   nvarcha ...

  3. Sql Server Row_Number() 学习

    Row_Number(): row_number()主要是为选出的每一条记录按照一定的排序方式生成一个行序号. 语法: ROW_NUMBER ( ) OVER ( [ PARTITION BY val ...

  4. 如何用C#代码查找某个路径下是否包含某个文件

      string path = "f:\\哈哈"; if (Directory.Exists(path)) { MessageBox.Show("存在文件夹") ...

  5. iOS使用keychain存储密码

    iOS设备中的Keychain是一个安全的存储容器.通常情况下,可以用NSUserDefaults存储数据信息,但是对于一些私密信息,比如账号.密码等等,就需要使用更为安全的keychain了.苹果自 ...

  6. 智捷公开课马上开始了-欢迎大家一起讨论学习-第一系列读《Swift开发指南(修订版) 》看Swift视频教程

    引用: 智捷课堂携手51CTO学院.图灵教育联合举办iOS线上培训就业班系列体验公开课. 分享移动开发.移动设计方向最新,最热,最抢眼技术热点以及设计经验.我们每周将最少举办一次公开课,同时会提前安排 ...

  7. js选中下拉框的默认选项

    //这是修改时选中 $("#type").find("option[value='"+factory+"']").attr("se ...

  8. windows时间同步出错

    http://jingyan.baidu.com/article/fd8044faf1f7ae5030137a7d.html

  9. java与C#用protobuf通信--java如何转换protobuf-net中的bcl.Decimal对象

    公司内部有些C#服务使用proto-net,引入了bcl.proto中的bcl.Decimal.bcl.DateTime等.对于java的proto生成代码需要对bcl.Decimal.bcl.Dat ...

  10. CSS3/jQuery创意盒子动画菜单

    作为前端开发者,各种各样的jQuery菜单见过不少,这款jQuery/CSS3菜单却是别具一格,菜单项嵌入到九宫格中,像小盒子一样,加上温馨的背景,菜单整体外观十分可爱.点击菜单项,盒子就会展开,展示 ...