android studio之ffmpeg初步使用

ffmpeg提供了强大的多媒体处理功能,并且由于跨平台,所以也可以使用在android 平台.很多第三方平台的后台程序也使用了这个库,如七牛,趣拍等.
下面我要记录在android studio中使用它的步骤:

一.配置ndk,具体请参考博文http://blog.csdn.net/jishoujiang/article/details/52705425
二.下载ffmpeg源码,去官网http://ffmpeg.org/,现在是3.1.3版本;
三.编译该源码,以ubutu系统为例:
(1)修改配置文件:

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

改成:

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

(2)输入脚本
我是使用了别人的脚本,网上有很多,在源码根目录,即ffmpeg-3.1.3下新建build_android.sh,输入:

#!/bin/bash  
NDK=/usr/android-sdk-linux/ndk-bundle
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

function build_one
{
./configure \
    --prefix=$PREFIX \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU 
ADDI_CFLAGS="-marm"
build_one

注意2~4行的ndk路径改成你自己的ndk路径
(3)执行脚本
打开终端,进入ffmpeg-3.1.3目录,执行sudo chmod + xxx build_android.sh;
再执行sudo ./build_android.sh,即开始执行脚本.大概10分钟左右吧,执行完毕,在ffmpeg-3.1.3目录下会生成一个android 的文件夹.里面有一个arm文件夹,再里面是include和lib文件夹,使用chmod + xxx -R命令,对android文件夹添加权限

编译完毕!

四.编译class,新建MainActivity.class ,
新增代码:


   static {
           System.loadLibrary("avcodec-57");
           System.loadLibrary("avfilter-6");
           System.loadLibrary("avformat-57");
           System.loadLibrary("avutil-55");
           System.loadLibrary("swresample-2");
           System.loadLibrary("swscale-4");
           System.loadLibrary("test");   //即Android.mk文件#Program下的LOCAL_MODULE
    }
    public native String urlprotocolinfo();
    public native String avformatinfo();
    public native String avcodecinfo();
    public native String avfilterinfo();
    public native String configurationinfo();
执行javah -d ../jni com.example.test.MainActivity,自动在java下生成jni目录 和com_example_test_MainActivity.h文件,jni下新建com_example_test_MainActivity.c,输入:
#include "com_example_test_MainActivity.h"
#include "include/libavformat/avformat.h"
#include "include/libavfilter/avfilter.h"

#include <stdio.h>
#include <android/log.h>


#define TAG "JNI_TAG"
//为了方便调用,将输出宏定义
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

struct URLProtocol;

/*
 * Class:     com_example_test_MainActivity
 * Method:    urlprotocolinfo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_urlprotocolinfo
        (JNIEnv *env, jobject obj)
{
    char info[40000]={0};
    av_register_all();

    struct URLProtocol *pup = NULL;
    //Input
    struct URLProtocol **p_temp = &pup;
    avio_enum_protocols((void **)p_temp, 0);
    while ((*p_temp) != NULL){
        sprintf(info, "%s[In ][%10s]\n", info, avio_enum_protocols((void **)p_temp, 0));
    }
    pup = NULL;
    //Output
    avio_enum_protocols((void **)p_temp, 1);
    while ((*p_temp) != NULL){
        sprintf(info, "%s[Out][%10s]\n", info, avio_enum_protocols((void **)p_temp, 1));
    }

    LOGE("%s", info);
    LOGD("%s",info);
    return (*env)->NewStringUTF(env, info);

}

/*
 * Class:     com_example_test_MainActivity
 * Method:    avformatinfo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_avformatinfo
        (JNIEnv *env, jobject obj)
{
    char info[40000] = { 0 };

    av_register_all();

    AVInputFormat *if_temp = av_iformat_next(NULL);
    AVOutputFormat *of_temp = av_oformat_next(NULL);
    //Input
    while(if_temp!=NULL){
        sprintf(info, "%s[In ][%10s]\n", info, if_temp->name);
        if_temp=if_temp->next;
    }
    //Output
    while (of_temp != NULL){
        sprintf(info, "%s[Out][%10s]\n", info, of_temp->name);
        of_temp = of_temp->next;
    }
    //LOGE("%s", info);
    return (*env)->NewStringUTF(env, info);

}

/*
 * Class:     com_example_test_MainActivity
 * Method:    avcodecinfo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_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->decode!=NULL){
            sprintf(info, "%s[Dec]", info);
        }
        else{
            sprintf(info, "%s[Enc]", info);
        }
        switch (c_temp->type){
            case AVMEDIA_TYPE_VIDEO:
                sprintf(info, "%s[Video]", info);
                break;
            case AVMEDIA_TYPE_AUDIO:
                sprintf(info, "%s[Audio]", info);
                break;
            default:
                sprintf(info, "%s[Other]", info);
                break;
        }
        sprintf(info, "%s[%10s]\n", info, c_temp->name);


        c_temp=c_temp->next;
    }
    //LOGE("%s", info);

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

}

/*
 * Class:     com_example_test_MainActivity
 * Method:    avfilterinfo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_avfilterinfo
        (JNIEnv *env, jobject obj)
{
    char info[40000] = { 0 };
    av_register_all();
    AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
    while (f_temp != NULL){
        sprintf(info, "%s[%10s]\n", info, f_temp->name);
    }
    //LOGE("%s", info);

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

}

/*
 * Class:     com_example_test_MainActivity
 * Method:    configurationinfo
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_test_MainActivity_configurationinfo
        (JNIEnv *env, jobject obj)
{
    char info[10000] = { 0 };
    av_register_all();

    sprintf(info, "%s\n", avcodec_configuration());

    //LOGE("%s", info);
    return (*env)->NewStringUTF(env, info);

}

五.生成so文件
复制include文件夹和ib下的so文件到生成的main/java/jni目录中,在jni中新建android.mk文件
输入:

LOCAL_PATH := $(call my-dir)

# 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 := test
LOCAL_SRC_FILES :=com_example_test_MainActivity.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include        #头文件搜索路径
LOCAL_LDLIBS :=-llog -lz                         #附加的链接器选项
LOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil swresample swscale
include $(BUILD_SHARED_LIBRARY)

打开android studio终端,进入java目录,执行ndk-build APP_ABI=”armeabi” ,会在main下生成libs和obj两个包,在main下新建jniLibs包,将libs下的armeabi包剪切到jniLibs下,改名为armeabi-v7a,build.gradle新增:

 sourceSets{
        main{
            jni.srcDirs=['jniLibs']
        }
    }

5.验证效果:
MainActivity新增代码:

 protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          String s1 = urlprotocolinfo();
          String s2 = avformatinfo();
          String s3 = avcodecinfo();
          String s4 = avfilterinfo();
          String s5 = configurationinfo();
          Log.e("jni",s1);
          Log.e("jni",s2);
          Log.e("jni",s3);
          Log.e("jni",s4);
          Log.e("jni",s5);
         }

正常打印了五次日志,说明配置成功
ps:如果出现include中的.h文件出现#include “libavutil/version.h”标红的问题,只要改成#include “../libavutil/version.h”就可以了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值