前言:百度说,FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件)。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移植性和编解码质量,libavcodec里很多codec都是从头开发的。

  说白了ffmpeg就是一个编解码库,我们可以使用android 提供的ndk编译其源码,网上很多资料,这里不是我们考虑的重点。我们的任务是将使用ndk编译好的so文件加入到我们的andriod apk中,让android的apk能够使用ffmpeg提供的音视频编解码功能。


闲话少说,我们开始吧。

一、在你的android项目src下创建包com.xx. 并在其中新建一个类叫做FFmpegOperater.java.  内容如下:

   

package com.xx;public class FFmpegOperater {private static FFmpegOperater mFFmpegOperater;private FFmpegOperater(){}public static FFmpegOperater newInstance(){if(mFFmpegOperater == null){mFFmpegOperater = new FFmpegOperater();}return mFFmpegOperater;}public native int readVersion();//本地方法,在此使用native 关键字声明,在C中实现}

二、生成头文件,此文件包含FFmpegOperater.java中 native 方法的声明(C中)

打开命令行,切换目录到项目的bin/classes/目录下。输入javah -classpath  .  -jni com.xx.FFmpegOperater 然后回车。会在当前目录下生成一个com_xx_FFmpegOperater.h文件。这个文件要copy到jni目录下,下文讲解。


打开此文件是如下内容

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class com_xx_FFmpegOperater */#ifndef _Included_com_xx_FFmpegOperater#define _Included_com_xx_FFmpegOperater#ifdef __cplusplusextern "C" {#endif/* * Class:     com_xx_FFmpegOperater * Method:    readVersion * Signature: ()I */JNIEXPORT jint JNICALL Java_com_xx_FFmpegOperater_readVersion  (JNIEnv *, jobject); //java 中声明的native方法。#ifdef __cplusplus}#endif#endif


三、创建jni(java native interface)

   在项目根目录下创建jni文件夹。此文件夹用于存放本地代码,和我们要加入的第三方库libffmpeg.so.将如下内容加入到jni目录下

         com_xx_FFmpegOperater.c   -----------> 位于java 与C之间,功能是调用ffmpeg提供的函数,并将反回结果通过jni传给java

          com_xx_FFmpegOperater.h    --------->上文中生成的com_xx_FFmpegOperater.h,将此文件放在jni目录下

         Android.mk            -----------> android 提供的makefile。定义编译规则,根据这个规则可以将libffmpeg.so编译到我们的.c 文件中,并生成我们自己的 .so文件供java调用。       

        libs 文件夹 -----------------> 下面放置libffmpeg.so 。

        include文件夹    -------------------->  此文件夹下面是ffmpeg的所有头文件,要调用libffmpeg.so中的函数,必须包含相应的头文件。去ffmpeg的官网可以下载到。

结构图:


依次详细讲解这些内容:

     com_xx_FFmpegOperater.c     承上启下的作用。

#include "com_xx_FFmpegOperater.h"#include "libavutil/avutil.h"#include #define LOG_TAG "ffmpeg"#define LOGW(a)  __android_log_write(ANDROID_LOG_INFO,LOG_TAG,a)JNIEXPORT jint JNICALL Java_com_xx_FFmpegOperater_readVersion (JNIEnv *env, jobject obj){LOGW(avutil_license());return (int)avutil_version();}




Android.mk  定义ndk的编译规则,内容如下:

LOCAL_PATH := $(call my-dir) #表示将当前目录的文件路径,即此Android.mk所在的路径赋值给LOCAL_PATH变量#编译libffmpeg.so 其实就是告诉ndk,它是一个第三方库include $(CLEAR_VARS)  LOCAL_SRC_FILES := libs/libffmpeg.so  #指定libffmpeg.so的路径LOCAL_MODULE :=ffmpeginclude $(PREBUILT_SHARED_LIBRARY) #编译我们的C文件,并将libffmpeg链接过来include $(CLEAR_VARS)LOCAL_MODULE_TAGS := testsLOCAL_MODULE    := myffmpegLOCAL_SRC_FILES := com_xx_FFmpegOperater.cLOCAL_C_INCLUDES := \           #这一行定义所有使用的头文件的路径$(JNI_H_INCLUDE) \$(LOCAL_PATH)/include/ LOCAL_LDLIBS +=-L$(LOCAL_PATH) -lm -llog #要使用的其他库,其中包括libffmpegLOCAL_SHARED_LIBRARIES := liblog libcutils libffmpeg LOCAL_PRELINK_MODULE := falseinclude $(BUILD_SHARED_LIBRARY)include $(call all-makefiles-under,$(LOCAL_PATH))


四、编译

打开终端,切换目录到jni下。输入 ndk-build,回车编译成功。前提你要配置好ndk. 具体配置,请自行百度

编译完成如果没有错误,在刷新一下项目,会自动生成两个文件夹,obj和libs。

obj目录存放的是在编译过程中生成的中间文件。libs文件夹下面是我们要在java里面lode的库文件,这些文件将会在apk被安装是放在系统路径的/data/data/com.xx/libs/目录下。java在载入时就会从这里找。


五、回到FFmpegOperater.java中,在此类中添加静态代码块来load   生成的那两个库文件,libffmpeg.so和libmyffmpeg.so

static {System.loadLibrary("ffmpeg");  //注意,此处要使用“ffmpeg”,而不是“libffmpeg”。这是规定。System.loadLibrary("myffmpeg");}


六、调用

 至此,就可以调用你的native 方法了,在java中。

package com.xx;import android.app.Activity;import android.os.Bundle;public class FFmpegDemoActivity extends Activity {    /** Called when the activity is first created. */    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                int v = FFmpegOperater.newInstance().readVersion();                System.out.println(v);    }}



七、总结:

   我们的目的是在java中调用第三方C库里的函数,所以必须通过jni,将C库链接到我们自己的C代码中,在我自己的C代码中调用第三方C库提供的函数。然后通过jni,将我们的C代码与java代码串起来。


另外,libffmpeg.so是从源码中编译而来的,所以要使用与其相同版本的头文件。

          






更多相关文章

  1. Android的APK安装过程 JVM Dalvik和ART等虚拟机区别以及DEX文件O
  2. android APK应用层到kernel层功能接口调用实现总结
  3. Android通过lame进行音频格式转换
  4. Android(安卓)调用系统相机,拍照,并上传图片所注意的一些问题
  5. 代码文件android:向手机卡上写入文件时总是不成功,解决办法
  6. Android菜鸟日记25-android反编译
  7. Android(安卓)中级学习心得
  8. 在Eclipse下编译Android原生APK方法
  9. Android(安卓)Studio--低版本如何不使用AndroidX编译

随机推荐

  1. iPhone 7销量超华为OPPO!iOS中国份额狂涨
  2. Android 快速简单实现夜间模式
  3. android屏幕信息获取的两种方法
  4. Android类参考---Fragment(三)
  5. Android 代码模拟输入按键
  6. 开源Jamendo在线音乐播放器源码(二)
  7. Android设置RadioButton在文字的右边
  8. arcgis android sdk load local tile
  9. Android开发便签1:AlertDialog的使用
  10. Android之工程目录介绍