AS移植FFmpeg(Ubuntu平台)

如今随着视频应用的流行,我们也有必要学习下这方面的知识了。现在市场上绝大多数的视频应用都是使用的FFmpeg进行视频处理,今天我们就来尝试将FFmpeg移植到Android平台。

下载FFmpeg编译好的.so文件

点击标题下载我已经编译好的so文件,将下载的文件解压复制到Android工程目录app/src/main/jni里面,如果没有文件夹则创建文件夹。关于如何编译FFmpeg的so文件,我将在下一篇文章里面分享,因为编译会麻烦很多,所以先让大家能够轻易的使用FFmpeg才是最佳的打开方式。

编写native方法。

public class FFmpegNative {
    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("avdevice-57");
        System.loadLibrary("ffmpeg_codec");//自己编写的c文件的so
    }
    public  native String getStringFromNative();
}

执行build->make project

在AS里面执行build->make project命令,生成classes文件,最终的classes文件会在debug目录下
build->make project

生成.h文件

cd目录 在终端输入java -jni com.you_name._your_package.FFmpegNative,FFmpegNative是Java文件的名字,此命令会生成一个.h文件
.h文件

编写.c文件

将.h拷贝到jni目录下,编写c文件命名与头文件相同 .c文件
将头文件的方法规范拷贝到c文件,实现方法,注意的是,这里的返回值的编写,java的字符编码是utf16,而安卓是utf8,如:

JNIEXPORT jstring JNICALL Java_com_bear_ffmpeg_FFmpegNative_getStringFromNative
        (JNIEnv *env , jobject obj){

      av_register_all();

      char wd[512];
      sprintf(wd, "AVCODEC VERSION %u\n"
        , avcodec_version()
        );
      return (*env)->NewStringUTF(env, wd);

  }

Android.mk

在jni目录下编写Android.mk文件

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := avcodec-57
LOCAL_SRC_FILES := prebuilt/libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avdevice-57
LOCAL_SRC_FILES := prebuilt/libavdevice-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avfilter-6
LOCAL_SRC_FILES := prebuilt/libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avformat-57
LOCAL_SRC_FILES := prebuilt/libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := avutil-55
LOCAL_SRC_FILES := prebuilt/libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := swresample-2
LOCAL_SRC_FILES := prebuilt/libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := swscale-4
LOCAL_SRC_FILES := prebuilt/libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := ffmpeg_codec
LOCAL_SRC_FILES := com_bear_ffmpeg_FFmpegNative.c

LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
LOCAL_SHARED_LIBRARIES := libavformat-57 libavcodec-57 libswscale-4 libavutil-55 libswresample-2 libavdevice-57 libavfilter-6
include $(BUILD_SHARED_LIBRARY)

Application.mk

在jni目录下编写Application.mk(这里的暂时只能够用于arm处理器)

APP_ABI :=armeabi,armeabi-v7a
APP_PLATFORM := android-21
APP_OPTIM := release

APP_STL := gnustl_static

执行ndk-build

使用终端cd到app/src/main目录,执行“ndk-build”,编译so库。
注意:有时候会出现错误:找不到编译的规则,可以在jni目录下创建一个空的util.c文件解决
将生成的so库从app/src/main/libs拷贝一份到app/Libs

修改buld.gradle

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'


    defaultConfig {
        applicationId "com.bear.ffmpeg"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk {
            moduleName "ffmpeg_codec"//c库的名字
            ldLibs "log", "z", "m","android","jnigraphics"
            abiFilters "arm64-v8a","armeabi","armeabi-v7a"
        }
        sourceSets.main{
            jni.srcDirs=[]//禁用自动ndk,在编写c代码的时候建议注释掉,因为这句话会停用c的语法提示功能
            jniLibs.srcDir "src/main/libs"
        }


    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

完成!

现在就可以在调用jni的方法了! 一些注意事项:

*so库的文件名不要写错了 *最后运行时请禁用ndk自动运行 *运行时提示找不到so库,可以再生成一次头文件,并且ndk-build,然后运行

Search by:GoogleBingBaidu