android 移植ffmpeg后so库的使用

宝剑锋从磨砺出,梅花香自苦寒来。这篇文章主要讲述android 移植ffmpeg后so库的使用相关的知识,希望能为你提供帮助。
    今天折腾了一天,可算是有所收获,成功的用jni调用了libffmpeg中的一个方法-----avcodec_version(),至于avcodec_version()是干什么用的我不大清楚,应该是获取版本信息吧,没有深入的去研究ffmpeg。
      这里主要是想把折腾一天所获取的经验记录下来,以免时间长全忘了,也希望能给其他人一点借鉴,不至于和我一样一点头绪都没有连猜带蒙的,本文纯属个人心得,高手可以无视....
      要在android上用ffmpeg首先得奖ffmpeg工程移植到android上,这里就要用到ndk把这个开源工程编译成一个后缀为so的库,这个步骤这里就不多说了 网上的资料也挺多的,我是按照:http://www.cnblogs.com/scottwong/archive/2010/12/17/1909455.html在ubantu环境下编译的,你按照教程上一步一步来应该都没有问题,顺便给下在windows下编译ffmpeg的教程:http://abitno.me/compile-ffmpeg-android-ndk(这个要用非ie浏览器打开)。以上两篇文章给了我很大的指引,在此谢过。。。都是牛人啊~~~
编译完以后你会获得一个libffmpeg.so的文件,那么问题来了,怎么用呢。我在百度,google搜了半天也没有一个详细的教程,总是东一句西一句的,但思路是明确的,就是还得编译一个so文件,这个so里的是jni方法,可以由java层调用的,而这些jni方法里用到的函数则就是来至libffmpeg.so了。思路是有了,但是具体怎么做呢?又经过一顿摸索,n次的编译,终于编译成功了。我是拿一个标准的ndk例子来做的测试就是ndk samples文件夹里的hello-jni工程。进入该工程的jni目录,将ffmpeg的源代码拷到该目录下,做这部的原因是你要编译的so文件里需要调用ffmpeg的方法,自然要引用ffmpeg里的h文件,然后将libffmpeg.so文件拷到ndk目录下的platforms/android-5/arch-arm/usr/lib目录下(你会发现platfroms里有好几个android文件夹如 -3 -4 -5分别代表不同的版本,以防万一我每个目录都拷了,呵呵,应该是只要拷指定目录的),因为等等系统编译的时候要用。接下来就编辑android.mk和hello-jni.c文件了 代码如下
android.mk
C代码   

android 移植ffmpeg后so库的使用

文章图片
  1. #  Copyright  (C)  2009  The  Android  Open  Source  Project   
  2. #   
  3. #  Licensed  under  the  Apache  License,  Version  2.0  (the  "License");    
  4. #  you  may  not  use  this  file  except  in  compliance  with  the  License.   
  5. #  You  may  obtain  a  copy  of  the  License  at   
  6. #   
  7. #            http://www.apache.org/licenses/LICENSE-2.0   
  8. #   
  9. #  Unless  required  by  applicable  law  or  agreed  to  in  writing,  software   
  10. #  distributed  under  the  License  is  distributed  on  an  "AS  IS"  BASIS,   
  11. #  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND,  either  express  or  implied.   
  12. #  See  the  License  for  the  specific  language  governing  permissions  and   
  13. #  limitations  under  the  License.   
  14. #   
  15. LOCAL_PATH  :=  $(call  my-dir)   
  16.    
  17. include  $(CLEAR_VARS)   
  18. PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg   
  19. LOCAL_C_INCLUDES  +=  $(PATH_TO_FFMPEG_SOURCE)   
  20. LOCAL_LDLIBS  :=  -lffmpeg   
  21. LOCAL_MODULE        :=  hello-jni   
  22. LOCAL_SRC_FILES  :=  hello-jni.c   
  23.    
  24. include  $(BUILD_SHARED_LIBRARY)   
【android 移植ffmpeg后so库的使用】 
PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg
这行是定义一个变量,也就是ffmpeg源码的路径
LOCAL_C_INCLUDES += $(PATH_TO_FFMPEG_SOURCE)
这行是指定源代码的路径,也就是刚才拷过去的ffmpeg源码,$(LOCAL_PATH)是根目录,如果没有加这行那么引入ffmpeg库中的h文件编译就会出错说找不到该h文件。
LOCAL_LDLIBS := -lffmpeg
这行很重要,这是表示你这个so运行的时候依赖于libffmpeg.so这个库, 再举个例子:如果你要编译的so不仅要用到libffmpeg.so这个库还要用的libopencv.so这个库的话,你这个参数就应该写成
LOCAL_LDLIBS := -lffmpeg -lopencv
其他的参数都是正常的ndk编译用的了,不明白的话google一下。
 
hello-jni.c
C代码   
android 移植ffmpeg后so库的使用

文章图片
  1. /* 
  2.   *  Copyright  (C)  2009  The  Android  Open  Source  Project 
  3.   * 
  4.   *  Licensed  under  the  Apache  License,  Version  2.0  (the  "License");  
  5.   *  you  may  not  use  this  file  except  in  compliance  with  the  License. 
  6.   *  You  may  obtain  a  copy  of  the  License  at 
  7.   * 
  8.   *            http://www.apache.org/licenses/LICENSE-2.0 
  9.   * 
  10.   *  Unless  required  by  applicable  law  or  agreed  to  in  writing,  software 
  11.   *  distributed  under  the  License  is  distributed  on  an  "AS  IS"  BASIS, 
  12.   *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND,  either  express  or  implied. 
  13.   *  See  the  License  for  the  specific  language  governing  permissions  and 
  14.   *  limitations  under  the  License. 
  15.   * 
  16.   */   
  17. #include  < string.h>    
  18. #include  < stdio.h>    
  19. #include  < android/log.h>    
  20. #include  < stdlib.h>      
  21. #include  < jni.h>    
  22. #include  < ffmpeg/libavcodec/avcodec.h>    
  23. /*  This  is  a  trivial  JNI  example  where  we  use  a  native  method 
  24.   *  to  return  a  new  VM  String.  See  the  corresponding  Java  source 
  25.   *  file  located  at: 
  26.   * 
  27.   *      apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java 
  28.   */   
  29. jstring   
  30. Java_com_example_hellojni_HelloJni_stringFromJNI(  JNIEnv*  env,   
  31.                                                                                                     jobject  thiz  )   
  32. {   
  33.         char  str[25];    
  34.         sprintf(str,  "%d",  avcodec_version());      
  35.    
  36.    
  37.         return  (*env)-> NewStringUTF(env,  str);    
  38. }   
  #include < ffmpeg/libavcodec/avcodec.h>
这行是因为下面要用到avcodec_version()这个函数。
 
      改完这两个文件以后就可以编译了~~用ndk-build命令编译完后在工程的libs/armeabi目录底下就会有一个libhello-jni.so文件了!(两行眼泪啊~终于编译成功了)
      编译完成后就可以进行测试了,记得将libffmpeg.so也拷到armeabi目录底下,并在java代码中写上
Java代码   
android 移植ffmpeg后so库的使用

文章图片
  1. static  {   
  2.               System.loadLibrary("ffmpeg");    
  3.         System.loadLibrary("hello-jni");    
  4.         }   
        HelloJni.java
Java代码   
android 移植ffmpeg后so库的使用

文章图片
  1. /* 
  2.   *  Copyright  (C)  2009  The  Android  Open  Source  Project 
  3.   * 
  4.   *  Licensed  under  the  Apache  License,  Version  2.0  (the  "License");  
  5.   *  you  may  not  use  this  file  except  in  compliance  with  the  License. 
  6.   *  You  may  obtain  a  copy  of  the  License  at 
  7.   * 
  8.   *            http://www.apache.org/licenses/LICENSE-2.0 
  9.   * 
  10.   *  Unless  required  by  applicable  law  or  agreed  to  in  writing,  software 
  11.   *  distributed  under  the  License  is  distributed  on  an  "AS  IS"  BASIS, 
  12.   *  WITHOUT  WARRANTIES  OR  CONDITIONS  OF  ANY  KIND,  either  express  or  implied. 
  13.   *  See  the  License  for  the  specific  language  governing  permissions  and 
  14.   *  limitations  under  the  License. 
  15.   */   
  16. package  com.example.hellojni;    
  17.    
  18. import  android.app.Activity;    
  19. import  android.widget.TextView;    
  20. import  android.os.Bundle;    
  21.    
  22.    
  23. public  class  HelloJni  extends  Activity   
  24. {   
  25.         /**  Called  when  the  activity  is  first  created.  */   
  26.         @Override   
  27.         public  void  onCreate(Bundle  savedInstanceState)   
  28.         {   
  29.                 super.onCreate(savedInstanceState);    
  30.    
  31.                 /*  Create  a  TextView  and  set  its  content. 
  32.                   *  the  text  is  retrieved  by  calling  a  native 
  33.                   *  function. 
  34.                   */   
  35.                 TextView    tv  =  new  TextView(this);    
  36.                 tv.setText(  "1111"  );    
  37.                 //System.out.println();    
  38.                 setContentView(tv);    
  39.                 tv.setText(String.valueOf(stringFromJNI()));    
  40.         }   
  41.    
  42.         /*  A  native  method  that  is  implemented  by  the 
  43.           *  \'hello-jni\'  native  library,  which  is  packaged 
  44.           *  with  this  application. 
  45.           */   
  46.         public  native  String    stringFromJNI();    
  47.    
  48.         /*  This  is  another  native  method  declaration  that  is  *not* 
  49.           *  implemented  by  \'hello-jni\'.  This  is  simply  to  show  that 
  50.           *  you  can  declare  as  many  native  methods  in  your  Java  code 
  51.           *  as  you  want,  their  implementation  is  searched  in  the 
  52.           *  currently  loaded  native  libraries  only  the  first  time 
  53.           *  you  call  them. 
  54.           * 
  55.           *  Trying  to  call  this  function  will  result  in  a 
  56.           *  java.lang.UnsatisfiedLinkError  exception  ! 
  57.           */   
  58.         public  native  String    unimplementedStringFromJNI();    
  59.    
  60.         /*  this  is  used  to  load  the  \'hello-jni\'  library  on  application 
  61.           *  startup.  The  library  has  already  been  unpacked  into 
  62.           *  /data/data/com.example.HelloJni/lib/libhello-jni.so  at 
  63.           *  installation  time  by  the  package  manager. 
  64.           */   
  65.         static  {   
  66.                     System.loadLibrary("ffmpeg");    
  67.                 System.loadLibrary("hello-jni");    
  68.         }   
  69. }   
    到此就完成了,将程序装到手机可看到打印出“3426306”,google搜索“ffmpeg 3426306”得知果然是ffmpeg的东西,证明成功的调用了libffmpeg.so库里的方法了。欣慰啊~~
      接下来要做的就是学习ffmpeg库里的各种函数的使用方法,以实现自己想要的功能了。
    今天折腾了一天,可算是有所收获,成功的用jni调用了libffmpeg中的一个方法-----avcodec_version(),至于avcodec_version()是干什么用的我不大清楚,应该是获取版本信息吧,没有深入的去研究ffmpeg。
      这里主要是想把折腾一天所获取的经验记录下来,以免时间长全忘了,也希望能给其他人一点借鉴,不至于和我一样一点头绪都没有连猜带蒙的,本文纯属个人心得,高手可以无视....
      要在android上用ffmpeg首先得奖ffmpeg工程移植到android上,这里就要用到ndk把这个开源工程编译成一个后缀为so的库,这个步骤这里就不多说了 网上的资料也挺多的,我是按照:http://www.cnblogs.com/scottwong/archive/2010/12/17/1909455.html在ubantu环境下编译的,你按照教程上一步一步来应该都没有问题,顺便给下在windows下编译ffmpeg的教程:http://abitno.me/compile-ffmpeg-android-ndk(这个要用非ie浏览器打开)。以上两篇文章给了我很大的指引,在此谢过。。。都是牛人啊~~~
编译完以后你会获得一个libffmpeg.so的文件,那么问题来了,怎么用呢。我在百度,google搜了半天也没有一个详细的教程,总是东一句西一句的,但思路是明确的,就是还得编译一个so文件,这个so里的是jni方法,可以由java层调用的,而这些jni方法里用到的函数则就是来至libffmpeg.so了。思路是有了,但是具体怎么做呢?又经过一顿摸索,n次的编译,终于编译成功了。我是拿一个标准的ndk例子来做的测试就是ndk samples文件夹里的hello-jni工程。进入该工程的jni目录,将ffmpeg的源代码拷到该目录下,做这部的原因是你要编译的so文件里需要调用ffmpeg的方法,自然要引用ffmpeg里的h文件,然后将libffmpeg.so文件拷到ndk目录下的platforms/android-5/arch-arm/usr/lib目录下(你会发现platfroms里有好几个android文件夹如 -3 -4 -5分别代表不同的版本,以防万一我每个目录都拷了,呵呵,应该是只要拷指定目录的),因为等等系统编译的时候要用。接下来就编辑android.mk和hello-jni.c文件了 代码如下
android.mk
C代码   
android 移植ffmpeg后so库的使用

文章图片
  1. #  Copyright  (C)  2009  The  Android  Open  Source  Project   
  2. #   

      推荐阅读