今天折騰了一天,可算是有所收獲,成功的用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
- # 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 or implied.
- # 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
- /*
- * 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 or implied.
- * 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,
- jobject thiz )
- {
- char str[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代碼中寫上
- static {
- System.loadLibrary("ffmpeg");
- System.loadLibrary("hello-jni");
- }
HelloJni.java
- /*
- * 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 or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.example.hellojni;
- import android.app.Activity;
- import android.widget.TextView;
- import android.os.Bundle;
- public class HelloJni extends Activity
- {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- /* Create a TextView and set its content.
- * the text is retrieved by calling a native
- * function.
- */
- TextView tv = new TextView(this);
- tv.setText( "1111" );
- //System.out.println();
- setContentView(tv);
- tv.setText(String.valueOf(stringFromJNI()));
- }
- /* A native method that is implemented by the
- * 'hello-jni' native library, which is packaged
- * with this application.
- */
- public native String stringFromJNI();
- /* This is another native method declaration that is *not*
- * implemented by 'hello-jni'. This is simply to show that
- * you can declare as many native methods in your Java code
- * as you want, their implementation is searched in the
- * currently loaded native libraries only the first time
- * you call them.
- *
- * Trying to call this function 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 has already been unpacked into
- * /data/data/com.example.HelloJni/lib/libhello-jni.so at
- * installation time by the package manager.
- */
- static {
- System.loadLibrary("ffmpeg");
- System.loadLibrary("hello-jni");
- }
- }
到此就完成了,將程序裝到手機可看到打印出“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
- # 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 or implied.
- # 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
- /*
- * 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 or implied.
- * 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,
- jobject thiz )
- {
- char str[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代碼中寫上
- static {
- System.loadLibrary("ffmpeg");
- System.loadLibrary("hello-jni");
- }
HelloJni.java
- /*
- * 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 or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package com.example.hellojni;
- import android.app.Activity;
- import android.widget.TextView;
- import android.os.Bundle;
- public class HelloJni extends Activity
- {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState)
- {
- super.onCreate(savedInstanceState);
- /* Create a TextView and set its content.
- * the text is retrieved by calling a native
- * function.
- */
- TextView tv = new TextView(this);
- tv.setText( "1111" );
- //System.out.println();
- setContentView(tv);
- tv.setText(String.valueOf(stringFromJNI()));
- }
- /* A native method that is implemented by the
- * 'hello-jni' native library, which is packaged
- * with this application.
- */
- public native String stringFromJNI();
- /* This is another native method declaration that is *not*
- * implemented by 'hello-jni'. This is simply to show that
- * you can declare as many native methods in your Java code
- * as you want, their implementation is searched in the
- * currently loaded native libraries only the first time
- * you call them.
- *
- * Trying to call this function 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 has already been unpacked into
- * /data/data/com.example.HelloJni/lib/libhello-jni.so at
- * installation time by the package manager.
- */
- static {
- System.loadLibrary("ffmpeg");
- System.loadLibrary("hello-jni");
- }
- }
到此就完成了,將程序裝到手機可看到打印出“3426306”,google搜索“ffmpeg 3426306”得知果然是ffmpeg的東西,證明成功的調用了libffmpeg.so庫里的方法了。欣慰啊~~
接下來要做的就是學習ffmpeg庫里的各種函數的使用方法,以實現自己想要的功能了。