zoukankan      html  css  js  c++  java
  • 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代码  收藏代码
    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)  

     

    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代码  收藏代码
    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代码  收藏代码
    1. static {  
    2.        System.loadLibrary("ffmpeg");  
    3.        System.loadLibrary("hello-jni");  
    4.     }  

         HelloJni.java

    Java代码  收藏代码
    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代码  收藏代码
    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)  

     

    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代码  收藏代码
    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代码  收藏代码
    1. static {  
    2.        System.loadLibrary("ffmpeg");  
    3.         System.loadLibrary("hello-jni");  
    4.     }  

         HelloJni.java

     

     

    Java代码  收藏代码
    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库里的各种函数的使用方法,以实现自己想要的功能了。

  • 相关阅读:
    word设置的密码忘了怎么办?
    Navicat Report Viewer 设置 HTTP 的方法
    如何处理Navicat Report Viewer 报表
    excel密码忘记了怎么办
    Beyond Compare文本比较搜索功能详解
    Popular Cows POJ
    Problem B. Harvest of Apples HDU
    网络流模型整理
    The Shortest Statement CodeForces
    Vasya and Multisets CodeForces
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7207656.html
Copyright © 2011-2022 走看看