ffmpeg 中hello-jni demo 示例

来源:互联网 发布:优酷网络 编辑:程序博客网 时间:2024/05/17 00:55

android移植ffmpegso库的使用

今天折腾了一天,可算是有所收获,成功的用jni调用了libffmpeg中的一个方法-----avcodec_version(),至于avcodec_version()是干什么用的我不大清楚,应该是获取版本信息吧,没有深入的去研究ffmpeg

这里主要是想把折腾一天所获取的经验记录下来,以免时间长全忘了,也希望能给其他人一点借鉴,不至于和我一样一点头绪都没有连猜带蒙的,本文纯属个人心得,高手可以无视....

要在android上用ffmpeg首先得奖ffmpeg工程移植到android上,这里就要用到ndk把这个开源工程编译成一个后缀为so的库,这个步骤这里就不多说了网上的资料也挺多的,我是按照:http://www.cnblogs.com/scottwong/archive/2010/12/17/1909455.htmlubantu环境下编译的,你按照教程上一步一步来应该都没有问题,顺便给下在windows下编译ffmpeg的教程:http://abitno.me/compile-ffmpeg-android-ndk(这个要用非ie浏览器打开)。以上两篇文章给了我很大的指引,在此谢过。。。都是牛人啊~~~

编译完以后你会获得一个libffmpeg.so的文件,那么问题来了,怎么用呢。我在百度,google搜了半天也没有一个详细的教程,总是东一句西一句的,但思路是明确的,就是还得编译一个so文件,这个so里的是jni方法,可以由java层调用的,而这些jni方法里用到的函数则就是来至libffmpeg.so了。思路是有了,但是具体怎么做呢?又经过一顿摸索,n次的编译,终于编译成功了。我是拿一个标准的ndk例子来做的测试就是ndksamples文件夹里的hello-jni工程。进入该工程的jni目录,将ffmpeg的源代码拷到该目录下,做这部的原因是你要编译的so文件里需要调用ffmpeg的方法,自然要引用ffmpeg里的h文件,然后将libffmpeg.so文件拷到ndk目录下的platforms/android-5/arch-arm/usr/lib目录下(你会发现platfroms里有好几个android文件夹如-3 -4-5分别代表不同的版本,以防万一我每个目录都拷了,呵呵,应该是只要拷指定目录的),因为等等系统编译的时候要用。接下来就编辑android.mkhello-jni.c文件了代码如下

android.mk

C代码

  1. # Copyright (C) 2009 TheAndroid 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 orimplied.

  12. #See the License for the specific language governing permissions and

  13. #limitations under the License.

  14. #

  15. LOCAL_PATH:= $(call my-dir)

  16. include$(CLEAR_VARS)

  17. PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg

  18. LOCAL_C_INCLUDES+= $(PATH_TO_FFMPEG_SOURCE)

  19. LOCAL_LDLIBS:= -lffmpeg

  20. LOCAL_MODULE:= hello-jni

  21. LOCAL_SRC_FILES:= hello-jni.c

  22. include$(BUILD_SHARED_LIBRARY)

#Copyright (C) 2009 The Android Open Source Project

#

#Licensed under the Apache License, Version 2.0 (the "License");

#you may not use this file except in compliance with the License.

#You may obtain a copy of the License at

#

# http://www.apache.org/licenses/LICENSE-2.0

#

#Unless required by applicable law or agreed to in writing, software

#distributed under the License is distributed on an "AS IS"BASIS,

#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.

#See the License for the specific language governing permissions and

#limitations under the License.

#

LOCAL_PATH:= $(call my-dir)


include$(CLEAR_VARS)

PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg

LOCAL_C_INCLUDES+= $(PATH_TO_FFMPEG_SOURCE)

LOCAL_LDLIBS:= -lffmpeg

LOCAL_MODULE := hello-jni

LOCAL_SRC_FILES:= hello-jni.c


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 orimplied.

  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. jobjectthiz )

  32. {

  33. charstr[25];

  34. sprintf(str,"%d", avcodec_version());

  35. return(*env)->NewStringUTF(env, str);

  36. }

/*

*Copyright (C) 2009 The Android Open Source Project

*

*Licensed under the Apache License, Version 2.0 (the "License");

*you may not use this file except in compliance with the License.

*You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

*Unless required by applicable law or agreed to in writing, software

*distributed under the License is distributed on an "AS IS"BASIS,

*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.

*See the License for the specific language governing permissions and

*limitations under the License.

*

*/

#include<string.h>

#include<stdio.h>

#include<android/log.h>

#include<stdlib.h>

#include<jni.h>

#include<ffmpeg/libavcodec/avcodec.h>

/*This is a trivial JNI example where we use a native method

*to return a new VM String. See the corresponding Java source

*file located at:

*

* apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java

*/

jstring

Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env,

jobjectthiz )

{

charstr[25];

sprintf(str,"%d", avcodec_version());



return(*env)->NewStringUTF(env, str);

}

#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. }

static{

System.loadLibrary("ffmpeg");

System.loadLibrary("hello-jni");

}

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 orimplied.

  13. *See the License for the specific language governing permissions and

  14. *limitations under the License.

  15. */

  16. packagecom.example.hellojni;

  17. importandroid.app.Activity;

  18. importandroid.widget.TextView;

  19. importandroid.os.Bundle;

  20. publicclass HelloJni extends Activity

  21. {

  22. /**Called when the activity is first created. */

  23. @Override

  24. publicvoid onCreate(Bundle savedInstanceState)

  25. {

  26. super.onCreate(savedInstanceState);

  27. /*Create a TextView and set its content.

  28. *the text is retrieved by calling a native

  29. *function.

  30. */

  31. TextViewtv = new TextView(this);

  32. tv.setText("1111" );

  33. //System.out.println();

  34. setContentView(tv);

  35. tv.setText(String.valueOf(stringFromJNI()));

  36. }

  37. /*A native method that is implemented by the

  38. *'hello-jni' native library, which is packaged

  39. *with this application.

  40. */

  41. publicnative String stringFromJNI();

  42. /*This is another native method declaration that is *not*

  43. *implemented by 'hello-jni'. This is simply to show that

  44. *you can declare as many native methods in your Java code

  45. *as you want, their implementation is searched in the

  46. *currently loaded native libraries only the first time

  47. *you call them.

  48. *

  49. *Trying to call this function will result in a

  50. *java.lang.UnsatisfiedLinkError exception !

  51. */

  52. publicnative String unimplementedStringFromJNI();

  53. /*this is used to load the 'hello-jni' library on application

  54. *startup. The library has already been unpacked into

  55. */data/data/com.example.HelloJni/lib/libhello-jni.so at

  56. *installation time by the package manager.

  57. */

  58. static{

  59. System.loadLibrary("ffmpeg");

  60. System.loadLibrary("hello-jni");

  61. }

  62. }

/*

*Copyright (C) 2009 The Android Open Source Project

*

*Licensed under the Apache License, Version 2.0 (the "License");

*you may not use this file except in compliance with the License.

*You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

*Unless required by applicable law or agreed to in writing, software

*distributed under the License is distributed on an "AS IS"BASIS,

*WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.

*See the License for the specific language governing permissions and

*limitations under the License.

*/

packagecom.example.hellojni;


importandroid.app.Activity;

importandroid.widget.TextView;

importandroid.os.Bundle;



publicclass HelloJni extends Activity

{

/** Called when the activityis first created. */

@Override

public void onCreate(BundlesavedInstanceState)

{

super.onCreate(savedInstanceState);


/* Create a TextView andset its content.

* the text is retrievedby calling a native

* function.

*/

TextView tv = newTextView(this);

tv.setText( "1111");

//System.out.println();

setContentView(tv);

tv.setText(String.valueOf(stringFromJNI()));

}


/* A native method that isimplemented by the

* 'hello-jni' nativelibrary, which is packaged

* with this application.

*/

public native String stringFromJNI();


/* This is another nativemethod declaration that is *not*

* implemented by'hello-jni'. This is simply to show that

* you can declare as manynative methods in your Java code

* as you want, theirimplementation is searched in the

* currently loaded nativelibraries only the first time

* you call them.

*

* Trying to call thisfunction will result in a

*java.lang.UnsatisfiedLinkError exception !

*/

public native String unimplementedStringFromJNI();


/* this is used to load the'hello-jni' library on application

* startup. The library hasalready been unpacked into

*/data/data/com.example.HelloJni/lib/libhello-jni.so at

* installation time by thepackage manager.

*/

static {

System.loadLibrary("ffmpeg");

System.loadLibrary("hello-jni");

}

}

到此就完成了,将程序装到手机可看到打印出“3426306”google搜索“ffmpeg3426306”得知果然是ffmpeg的东西,证明成功的调用了libffmpeg.so库里的方法了。

接下来要做的就是学习ffmpeg库里的各种函数的使用方法,以实现自己想要的功能了。



原创粉丝点击