建立好NDK環境後
移植到Android平台
接下來寫在Android studio寫一個示例,調用ffmpeg中方法
建一個工程:在src/main下建一個jni目錄
建一個工程:在src/main下建一個jni目錄
將lib文件夾中的pkgconfig目錄刪除,只保留so文件,然後將include和lib兩個目錄一起copy到你的 jni資料夾下去編譯,下圖因為我已經編譯完成會有其他檔案
建置好支援JNI的Android專案後,先別急著開始寫C/C++程式,應該要先規劃好Java程式中哪些地方需要使用到由C/C++程式語言實作的方法或是函數,這些方法都需要先使用native修飾子來進行宣告,並且使用System類別下的loadLibrary方法來讀入指定名稱的.so函式庫。用以下程式為例:
MainActivity.java
import android.support.v7.app.AppCompatActivity;.xml
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView infoText = (TextView)findViewById(R.id.text_libinfo);
infoText.setMovementMethod(ScrollingMovementMethod.getInstance());
Button button = (Button)this.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
infoText.setText(avcodecinfo());
}
});
}
//JNI
public native String avcodecinfo();
static{
System.loadLibrary("avutil-55");
System.loadLibrary("swresample-2");
System.loadLibrary("avcodec-57");
System.loadLibrary("avformat-57");
System.loadLibrary("swscale-4");
System.loadLibrary("avfilter-6");
System.loadLibrary("sffhelloworld");
}
}
<?xml version="1.0" encoding="utf-8"?>接著再使用JDK提供的「javah」工具,來將指定類別轉換成JNI使用的標頭檔
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.cheng.myapplication.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:id="@+id/textView" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_marginTop="122dp"
android:id="@+id/text_libinfo" />
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:layout_alignParentStart="true"
android:layout_marginTop="13dp"
android:id="@+id/button" />
</RelativeLayout>
在MainActivity.java按右鍵 -> External Tools -> Javah
執行完畢後,在jni ([c])目錄中會出現 標頭檔.h
將使用javah產生出來的.h檔案移動到「jni」目錄下,然後在別的.c或是.cpp檔案中include,並實作出其中宣告的函數
simplest_ffmpeg_helloworld.c
//Android.mk
// Created by cheng on 2016/11/29.
//
#include "com_example_cheng_myapplication_MainActivity.h"
#include <stdio.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#ifdef ANDROID
#include <jni.h>
#include <android/log.h>
#define LOGE(format, ...) __android_log_print(ANDROID_LOG_ERROR, "(>_<)", format, ##__VA_ARGS__)
#else
#define LOGE(format, ...) printf("(>_<) " format "\n", ##__VA_ARGS__)
#endif
JNIEXPORT jstring Java_com_example_cheng_myapplication_MainActivity_avcodecinfo(JNIEnv *env, jobject obj){
char info[40000]={0};
av_register_all();
AVCodec *c_temp = av_codec_next(NULL);
while (c_temp != NULL){
if(c_temp != NULL){
sprintf(info, "%s[Dec]\n", info);
}else{
sprintf(info, "%s[Enc]\n", info);
}
switch(c_temp->type){
case AVMEDIA_TYPE_VIDEO:
sprintf(info, "%s[Video]\n", info);
break;
case AVMEDIA_TYPE_AUDIO:
sprintf(info, "%s[Audio]\n", info);
break;
default:
sprintf(info, "%s[Other]\n", info);
break;
}
sprintf(info, "%s[%10s]\n", info,c_temp->name);
c_temp = c_temp->next;
}
return (*env).NewStringUTF(info);
}
LOCAL_PATH := $(call my-dir)LOCAL_MODULE = "xxxx"就是System.loadLibrary的名子
# FFmpeg library
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)
# Program
include $(CLEAR_VARS)
LOCAL_MODULE := libsffhelloworld
LOCAL_SRC_FILES := simplest_ffmpeg_helloworld.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale
include $(BUILD_SHARED_LIBRARY)
預設的情況下,NDK只會編譯出armeabi架構的.so檔案,可以用在任何ARM架構的Android裝置上。如果要針對ARMv7架構優化,或是使.so檔能在x86架構或是MIPS架構上執行的話,可以在「jni」目錄下,增加「Application.mk」檔案,並且設定「APP_ABI」參數的值。
例如要編譯出ARM與x86的.so檔案,可以這樣設定:
Application.mk
APP_ABI := armeabi開始編譯目標so,在Studio中的Terminal面板中:執行ndk-build (在此之前記得要在local.properties下配置ndk目錄)
之後編譯有問題
建立build.gradle(app)
defaultConfig {
applicationId "com.example.cheng.myapplication"
minSdkVersion 19
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk{
moduleName "libsffhelloworld"
}
sourceSets.main{
jni.srcDirs=[]
jniLibs.srcDir "src/main/jniLibs"
}
}
在gradle.properties android.useDeprecatedNdk=true
在 libavutil\common.h 加入
#define __STDC_CONSTANT_MACROS
#define inline __inline
#ifndef INT64_C
#define INT64_C(c) (c ## LL)
#define UINT64_C(c) (c ## ULL)
#endif
接這又出現錯誤= =
要再.h檔加入
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#endif
再編譯一次成功的話就燒入吧
Reference:
http://blog.csdn.net/hejjunlin/article/details/52661331
https://magiclen.org/android-jni/
http://jojosula001.pixnet.net/blog/post/173475381-%5Bwindows%5D-using-ffmpeg-in-visual-c%2B%2B
https://github.com/dxjia/ffmpeg-compile-shared-library-for-android
http://blog.csdn.net/leixiaohua1020/article/details/47008825












































