ffmpeg 版本0.65

ndk 版本 5c

  1. 编写 mk 文件
    1. 在 /root/ffmpeg/jni 目录中创建一个 Android.mk 文件,内容如下
      include $(all-subdir-makefiles)
    2. 在 /root/ffmpeg/jni/ffmpeg-0.6.1 目录中创建一个 Android.mk 文件,内容如下
      LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscaleLOCAL_MODULE := ffmpeginclude $(BUILD_SHARED_LIBRARY)include $(call all-makefiles-under,$(LOCAL_PATH))
    3. 在 /root/ffmpeg/jni/ffmpeg-0.6.1 目录中创建一个 av.mk 文件,内容如下
      # LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).makinclude $(LOCAL_PATH)/../config.makOBJS :=OBJS-yes :=MMX-OBJS-yes :=include $(LOCAL_PATH)/Makefile# collect objectsOBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)OBJS += $(OBJS-yes)FFNAME := lib$(NAME)FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))FFCFLAGS  = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-signFFCFLAGS += -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))elseC_OBJS := $(OBJS)S_OBJS :=endifC_FILES := $(patsubst %.o,%.c,$(C_OBJS))S_FILES := $(patsubst %.o,%.S,$(S_OBJS))FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))
    4. 在 /root/ffmpeg/jni/ffmpeg-0.6.1/libavcodec 目录中创建一个 Android.mk 文件,内容如下
      LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)include $(LOCAL_PATH)/../av.mkLOCAL_SRC_FILES := $(FFFILES)LOCAL_C_INCLUDES :=        \    $(LOCAL_PATH)        \    $(LOCAL_PATH)/..LOCAL_CFLAGS += $(FFCFLAGS)LOCAL_LDLIBS := -lzLOCAL_STATIC_LIBRARIES := $(FFLIBS)LOCAL_MODULE := $(FFNAME)include $(BUILD_STATIC_LIBRARY)
    5. 在 /root/ffmpeg/jni/ffmpeg-0.6.1/libavformat 目录中创建一个 Android.mk 文件,内容如下
      LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)include $(LOCAL_PATH)/../av.mkLOCAL_SRC_FILES := $(FFFILES)LOCAL_C_INCLUDES :=        \    $(LOCAL_PATH)        \    $(LOCAL_PATH)/..LOCAL_CFLAGS += $(FFCFLAGS)LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindexLOCAL_LDLIBS := -lzLOCAL_STATIC_LIBRARIES := $(FFLIBS)LOCAL_MODULE := $(FFNAME)include $(BUILD_STATIC_LIBRARY)
    6. 在 libavfilter、libavutil、libpostproc 和 libswscale 目录中各创建一个 Android.mk 文件,内容如下
      LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)include $(LOCAL_PATH)/../av.mkLOCAL_SRC_FILES := $(FFFILES)LOCAL_C_INCLUDES :=        \    $(LOCAL_PATH)        \    $(LOCAL_PATH)/..LOCAL_CFLAGS += $(FFCFLAGS)LOCAL_STATIC_LIBRARIES := $(FFLIBS)LOCAL_MODULE := $(FFNAME)include $(BUILD_STATIC_LIBRARY)
  2. 修改 libm.h 文件和 Makefile 文件
    1. 编辑 /root/ffmpeg/jni/ffmpeg-0.6.1/libavutil 目录中的 libm.h 文件,删除以下 static 方法
      #if !HAVE_LRINTstatic av_always_inline av_const longint lrint(double x){    return rint(x);}#endif/* HAVE_LRINT */#if !HAVE_LRINTFstatic av_always_inline av_const longint lrintf(float x){    return (int)(rint(x));}#endif/* HAVE_LRINTF */#if !HAVE_ROUNDstatic av_always_inline av_const double round(double x){    return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);}#endif/* HAVE_ROUND */#if !HAVE_ROUNDFstatic av_always_inline av_const float roundf(float x){    return (x > 0) ? floor(x + 0.5) : ceil(x - 0.5);}#endif/* HAVE_ROUNDF */#if !HAVE_TRUNCFstatic av_always_inline av_const float truncf(float x){    return (x > 0) ? floor(x) : ceil(x);}#endif/* HAVE_TRUNCF */
    2. 编辑 libavcodec、libavfilter、libavformat、libavutil、libpostproc 和 libswscale 目录中的 Makefile 文件,删除
      include $(SUBDIR)../subdir.mak
      include $(SUBDIR)../config.mak
  3. 生成 config.h 文件
    1. 在 /root/ffmpeg/jni/ffmpeg-0.6.1 目录中创建一个 config.sh 文件,使用 Android NDK r4b 编译时内容如下
      PREBUILT=/root/android-ndk-r4b/build/prebuilt/linux-x86/arm-eabi-4.4.0PLATFORM=/root/android-ndk-r4b/build/platforms/android-8/arch-arm./configure --target-os=linux \    --arch=arm \    --enable-version3 \    --enable-gpl \    --enable-nonfree \    --disable-stripping \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffserver \    --disable-ffprobe \    --disable-encoders \    --disable-muxers \    --disable-devices \    --disable-protocols \    --enable-protocol=file \    --enable-avfilter \    --disable-network \    --disable-mpegaudio-hp \    --disable-avdevice \    --enable-cross-compile \    --cc=$PREBUILT/bin/arm-eabi-gcc \    --cross-prefix=$PREBUILT/bin/arm-eabi- \    --nm=$PREBUILT/bin/arm-eabi-nm \    --extra-cflags="-fPIC -DANDROID" \    --disable-asm \    --enable-neon \    --enable-armv5te \    --extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
      使用 Android NDK r5 编译时内容如下
      #!/bin/bashPREBUILT=/root/android-ndk-r5/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86PLATFORM=/root/android-ndk-r5/platforms/android-8/arch-arm./configure --target-os=linux \    --arch=arm \    --enable-version3 \    --enable-gpl \    --enable-nonfree \    --disable-stripping \    --disable-ffmpeg \    --disable-ffplay \    --disable-ffserver \    --disable-ffprobe \    --disable-encoders \    --disable-muxers \    --disable-devices \    --disable-protocols \    --enable-protocol=file \    --enable-avfilter \    --disable-network \    --disable-mpegaudio-hp \    --disable-avdevice \    --enable-cross-compile \    --cc=$PREBUILT/bin/arm-eabi-gcc \    --cross-prefix=$PREBUILT/bin/arm-eabi- \    --nm=$PREBUILT/bin/arm-eabi-nm \    --extra-cflags="-fPIC -DANDROID" \    --disable-asm \    --enable-neon \    --enable-armv5te \    --extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
    2. 打开终端,进入 /root/ffmpeg/jni/ffmpeg-0.6.1 目录,运行下面的命令
      chmod +x config.sh./config.sh
    3. 编辑 /root/ffmpeg/jni/ffmpeg-0.6.1 目录中的 config.h 文件,将
      #define restrict restrict
      修改为
      #define restrict

四、开始编译 FFmpeg

很多人在用 havlenapetr 的方法编译 FFmpeg 时只得到一个 1599 字节 1.6KB 大小的 libffmpeg.so 文件,无论是用 Android NDK r4b 编译还是用 Android NDK r5 编译结果都是如此,很让人抓狂。我也很郁闷,最后花时间研究了一下 NDK,终于发现了解决方法,而且 Android NDK r4b 和 Android NDK r5 的情况还是完全不同的,请继续往下读。

  1. 使用 Android NDK r4b 编译

    打开 android-ndk-r4b/build/toolchains/arm-eabi-4.4.0 目录中的 setup.mk 文件,你会发现 Google 在里面定义了一个用于编译动态库的 cmd-build-shared-library 函数。在cmd-build-shared-library 函数中 Google 使用了 PRIVATE_WHOLE_STATIC_LIBRARIES 函数。但是你在 android-ndk-r4b/build/core 目录中的 build-binary.mk 文件里却找不到 PRIVATE_WHOLE_STATIC_LIBRARIES 函数…… 外?WHY?终于搞清楚了,原来得不到正确的 libffmpeg.so 文件不是我的错,而是 Android NDK r4b 的 BUG!你妹啊!你大爷啊!坑爹呢这是!发布前不做测试吗!居然漏掉一个函数!!!(我敢说这是个 BUG 是因为 Google 在 Android NDK r5 中修复了这个 BUG)

    木办法,只好手动替 Google 修补这个 BUG。好在修改方法很简单,只需要照 build-binary.mk 文件里的 PRIVATE_STATIC_LIBRARIES 增加一个 PRIVATE_WHOLE_STATIC_LIBRARIES 就行了。具体方法见下图

    修改前的 build-binary.mk 文件

    修改后的 build-binary.mk 文件

    保存 build-binary.mk 文件之后,运行下面的命令编译

    /root/android-ndk-r4b/ndk-build NDK_PROJECT_PATH=/root/ffmpeg

    接着你会看到 warning 不停的出现在屏幕上,熬过这段心惊肉跳的时间之后,你会看到 libffmpeg.so 文件已经被编译生成了。


    看看 /root/ffmpeg/obj/local/armeabi 目录中的 libffmpeg.so 文件,文件大小是 12.2MB

    再看看 /root/ffmpeg/libs/local/armeabi 目录中的 libffmpeg.so 文件,文件大小是 3.2MB

  2. 使用 Android NDK r5 编译

    打开 android-ndk-r5/build/core 目录中的 build-binary.mk 文件,发现 Google 这次没有忘记 PRIVATE_WHOLE_STATIC_LIBRARIES,但还最后编译得到的 libffmpeg.so 文件大小还是不正确。 这次的问题是,android-ndk-r5 默认是使用 arm-linux-androideabi-4.4.3 编译,而不是 arm-eabi-4.4.0。但 android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3 目录中的 setup.mk 文件里定义的 cmd-build-shared-library 函数并没有将静态库文件链接在一起生成动态库文件。所以解决的办法就是在执行 ndk-build 时加上 NDK_TOOLCHAIN 参数,指定使用 arm-eabi-4.4.0 来编译。完整命令如下

    /root/android-ndk-r5/ndk-build NDK_PROJECT_PATH=/root/ffmpeg NDK_TOOLCHAIN=arm-eabi-4.4.0 NDK_PLATFORM=android-8
     
     
     
     
     
  1. /* * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *//** * @file * Replacements for frequently missing libm functions */#ifndef AVUTIL_LIBM_H#define AVUTIL_LIBM_H#include <math.h>#include "config.h"#include "attributes.h"#if !HAVE_EXP2#undef exp2#define exp2(x) exp((x) * 0.693147180559945)#endif /* HAVE_EXP2 */#if !HAVE_EXP2F#undef exp2f#define exp2f(x) ((float)exp2(x))#endif /* HAVE_EXP2F */#if !HAVE_LLRINT#undef llrint#define llrint(x) ((long long)rint(x))#endif /* HAVE_LLRINT */#if !HAVE_LLRINTF#undef llrintf#define llrintf(x) ((long long)rint(x))#endif /* HAVE_LLRINT */#if !HAVE_LOG2#undef log2#define log2(x) (log(x) * 1.44269504088896340736)#endif /* HAVE_LOG2 */#if !HAVE_LOG2F#undef log2f#define log2f(x) ((float)log2(x))#endif /* HAVE_LOG2F */#if !HAVE_LRINT#undef lrint#define lrint(x) ((long int)(rint((double)x)))#endif /* HAVE_LRINT */#if !HAVE_LRINTF#undef lrintf#define lrintf(x) ((long int)(rint((float)x)))#endif /* HAVE_LRINTF */#if !HAVE_ROUND#undef round#define round(x) ((double)(((double)x > 0) ? floor((double)x + 0.5) : ceil((double)x - 0.5)))#endif /* HAVE_ROUND */#if !HAVE_ROUNDF#undef roundf#define roundf(x) ((float)(((float)x > 0) ? floor((float)x + 0.5) : ceil((float)x - 0.5)))#endif /* HAVE_ROUNDF */#if !HAVE_TRUNCF#undef truncf#define truncf(x) ((float)(((float)x > 0) ? floor((float)x) : ceil((float)x)))#endif /* HAVE_TRUNCF */#endif /* AVUTIL_LIBM_H */
    LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := LIB1LOCAL_SRC_FILES := libavcodec.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := LIB2LOCAL_SRC_FILES := libavformat.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := LIB3LOCAL_SRC_FILES := libavutil.ainclude $(PREBUILT_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := hello-jniLOCAL_SRC_FILES := hello-jni.cLOCAL_STATIC_LIBRARIES := LIB1 LIB2 LIB3include $(BUILD_SHARED_LIBRARY)
  2. LOCAL_PATH := $(call my-dir)


    include $(CLEAR_VARS)
    LOCAL_MODULE := avcodec
    LOCAL_SRC_FILES := libavcodec.a
    LOCAL_CFLAGS :=-Ilibavcodec
    LOCAL_EXPORT_C_INCLUDES := libavcodec
    LOCAL_EXPORT_CFLAGS := -Ilibavcodec
    LOCAL_EXPORT_LDLIBS := -llog
    include $(PREBUILT_STATIC_LIBRARY)


    include $(CLEAR_VARS)
    LOCAL_MODULE := avformat
    LOCAL_SRC_FILES := libavformat.a
    LOCAL_CFLAGS :=-Ilibavformat
    LOCAL_EXPORT_C_INCLUDES := libavformat
    LOCAL_EXPORT_CFLAGS := -Ilibavformat
    LOCAL_EXPORT_LDLIBS := -llog
    include $(PREBUILT_STATIC_LIBRARY)


    include $(CLEAR_VARS)
    LOCAL_MODULE := avutil
    LOCAL_SRC_FILES := libavutil.a
    LOCAL_CFLAGS :=-Ilibavutil
    LOCAL_EXPORT_C_INCLUDES := libavutil
    LOCAL_EXPORT_CFLAGS := -Ilibavutil
    LOCAL_EXPORT_LDLIBS := -llog


    include $(PREBUILT_STATIC_LIBRARY)




    include $(CLEAR_VARS)
    LOCAL_MODULE := swscale
    LOCAL_SRC_FILES :=libswscale.a
    LOCAL_CFLAGS :=-Ilibswscale
    LOCAL_EXPORT_C_INCLUDES := libswscale
    LOCAL_EXPORT_CFLAGS := -I$libswscale
    LOCAL_EXPORT_LDLIBS := -llog
    include $(PREBUILT_STATIC_LIBRARY)






    include $(CLEAR_VARS)
    LOCAL_MODULE := hello-jni
    LOCAL_SRC_FILES := hello-jni.c
    LOCAL_LDLIBS := -L$(LOCAL_PATH) -lm -lz -lbz2
    LOCAL_STATIC_LIBRARIES := avcodec avformat avutil swscale


    include $(BUILD_SHARED_LIBRARY)


     

更多相关文章

  1. 实例讲解Android中如何实现图片的异步加载功能
  2. Android(安卓)MediaPlayer重复播放问题
  3. Android(安卓)couldn't find xxx.so 问题解决 兼容解决
  4. Android(安卓)编译出错版本匹配问题解决办法
  5. android开发笔记之Button的圆角和按下效果
  6. 【Android(安卓)基础】Progressbar 实现Loading动画
  7. Android(安卓)studio更新自身或者SDK以后出错问题解决
  8. Android通过xml文件配置数据库
  9. Android打包签名——生成keystore到完成签名

随机推荐

  1. Python 爬完评论只会做词云?情感分析了解
  2. 可视化日志服务器搭建
  3. 体检异常率97%,这届90后身体到底有多差
  4. 监控流媒体服务器的搭建和使用
  5. 《Python知识手册》更新V2.1版,添加部分Py
  6. 老板让我从Word中复制出1000张图片?
  7. 我想找个这样的男朋友,要求高吗?
  8. 用 Python 读取巴菲特最近的持仓数据
  9. B站晚会大火的 140 万个理由!
  10. C语言的一些练习以及写一个猜数字游戏