写这篇博客的时候,哥心里是愉快的,困扰了一个星期的问题解决了。进入正题

我做这个一开始也是什么都吧知道,在这里我就以我的步骤来串出全文

第一步 ,下载和编译ffmpeg源码

    下载就不提了,编译ffmpeg源码的步骤如下 我的编译环境是windows+ndk+cygwin

    1:解压源码到一个文件夹下 我的是 e:/ffmpeg/jni下,解压后的目录相当于是e:/ffmpeg/jni/ffmpeg****,为了方便把文件名改成ffmpeg,相当于源码目录是e:/ffmpeg/jni/ffmpeg

(我使用的源码版本是0.7.13);

   2:创建config.sh文件在源码的根目录下。这个文件的创建让我吃尽苦头 ,下面我一一道来,希望大家不要重蹈我的覆辙。

      a.当在windows下创建这个文件的时候,这个文件的格式是不对的,直接创建这个文件后执行./config.sh命令,cygwin会报出config.sh文件里每一行定义的操作的找不到,比如 **---** unkonw options 的错误 (这个错误当时没有复制下来,好像是这个格式的)。----------------我解决的办法是 在unbunto上创建好这个文件,然后再考到windows上去

     b.当创建config.sh的时候,大家都是从网站上复制代码的,这里也是容易出问题的,因为从网站上复制的代码会带有很多附带的字符,一定要看清楚,复制好,这里报的错误忘记了是什么样的,总之,别复制了多余的字符。

    c.这个文件的内容,需要根据你自己的要求复制 ,这里我说下我自己犯的错误,困扰了我一周

       以下是我复制的内容

"-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"

     当我复制好以后,并且按照下面的步骤做完,到最后编译通过了,我去他娘的,我以为真成功了,在我的项目中调用guess_format,和find_encode_coder()这两个方法 始终返回空,而这里面到底是这么执行的,在NDK里又调试不了,受不了了,我就按照源码里的例子一行一行考过来,还是返回空,没法调试,只能是瞎猜,第一会不会是版本不同导致的,下个低版本的再编译一次,还是一样,再下个高版本的试试,没有变化。第二会不会是我的ndk的andriod.mk文件写的有问题,结果我有去研究mk的写法,如今对mk也是一知半解,搜索各种帖子,大家都有感觉,就是机会所有的帖子都是一个版本的。我又去网站发帖询问,访问的人寥寥无几。我草他妈啊,这到底是咋回事啊,我心里在暗骂。

   之后还是各种纠结,最后在今天发现了问题所在。------------------------------------注意了,是这个config.sh的内容导致的,我当时就暗骂,这个内容在所有的帖子上几乎都是一模一样的,所有没有人能怀疑会是这个的问题,我就试问发这些的人都没有试过啊。  解决问题是::::::::::::enable 开启模块 ,disable是关闭模块 ,这上面几乎把所有的模块的关闭了,我们编译的时候必须根据自己的需求打开,就是把disable 改成enable 。我试过吧所有的disable 改成enable都没有问题,除了--disable-devices这一行会有问题。

  后面我 会上传我的config.sh供大家参考。

   3.在cygwin中cd到源码跟目录,执行

chmod +x config.sh
   ./config.sh

   命令会生成一个config.h文件,文件里需要改一行

#define restrict restrict改成#define restrict


4.修改Makefile文件和编写android.mk文件,编辑 /root/ffmpeg/jni/ffmpeg-0.6.1/libavutil 目录中的 libm.h 文件,这个和网上的都一样,大家可以参考。


 


5.执行$NDK/ndk-build命令。注意这个命令根据自己的来。


第二步 在android项目中调用


调用分2中,一种是静态库的调用,一种是动态库的调用,我对这两个理解得不是很好,所有不能总结,只能说出我的调用过程


a.静态库的调用


1:把ffmpeg的头文件都拷贝的项目的jni目录下


2:编写android.mk文件 。


我的写法如下

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
MODULE_LIBS := "F:/wk/cemera/jni/libs"
LOCAL_C_INCLUDES := \
  $(LOCAL_PATH)/include \
  $(LOCAL_PATH)
LOCAL_MODULE := camera
LOCAL_SRC_FILES := camera.c vst.c mai.c
LOCAL_LDFLAGS := $(MODULE_LIBS)/libpostproc.a \
$(MODULE_LIBS)/libavformat.a \
$(MODULE_LIBS)/libavcodec.a \
     $(MODULE_LIBS)/libswscale.a \
     $(MODULE_LIBS)/libavutil.a
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)

 

在这里我分享一下我的总结,不一定对,还请指教 。

在调用静态库的时候,可以有LOCAL_LDLIBS或者是LOCAL_STATIC_LDLIBS这两个的区别是 当你的项目中用到的静态库需要从你这个项目中编译得到的,就可以用LOCAL_STATIC_LDLIBS(例如ndk目录中的two-lib例子),当你的项目中用到的静态库是第三方的,没有源码,只用.a文件和头文件,就用LOCAL_LDLIBS,赋给它的静态库是库文件的全名,不要省略后缀和lib字符。

路径问题,调用静态库的时候需要些全路径,不要使用系统的变量(local——path),用这个变量会报出找不到库文件的错误,可以自己定义一个变量,我就是这样做的。

b.调用动态库

和静态库差不多,把上面的调用静态库的那句删掉(LOCAL_LDLIBS),在LOCAL_LDLIBS加上你要使用的动态库名字,需要省略后缀和lib字符,我是把动态库文件拷贝到了ndk的lib目录下的,其他方法没有试过。其中-L表示的是系统目录的库文件。

好了,基本差不多了,有什么错误,及时指出,避免耽误他人!!!