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

  • 相关阅读:
    qemu-kvm磁盘读写的缓冲(cache)的五种模式
    关于追踪qemu 源码函数路径的一个方法
    准备升大三啦
    关于Vim的一个配置文件
    POJ 3253
    hihocoder 第二十五周 spfa 最短路
    POJ 2718 穷举
    《鸟哥Linux私房菜基础学习篇》命令索引
    博文流
    《SDN核心技术剖析和实战指南》3.3读书笔记
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/7207656.html
Copyright © 2011-2022 走看看