基于FFMPEG3.1.1的第一个Android测试程序

来源:互联网 发布:阿里云远程桌面密码 编辑:程序博客网 时间:2024/04/29 23:58

上篇使用NDK编译出了ffmpeg3.1.1版本的动态链接库。这篇文章我们就写一个简单的JNI程序来测试我们生成的libffmpeg.so库是否可用。

1.在android studio中建立一个工程。并新建jni目录。在里面新建一个ffmpeg文件夹,放入ffmpeg的库libffmpeg.so和头文件,包括:libavcodec libavdevice libavfilter libavformat libavutil libswscale libswresample 。
这里写图片描述

2.在jni目录新建一个c文件。具体方法可百度,这里不在详细解释。jni文件只有一个测试函数testFFmpegLib 里面将调用avcodec的API函数来输出avcodec的version、license 和configuration。把这些信息存入字串中,从java中读取。jni文件内容如下:

#include <jni.h>#include <android/log.h>#include <stdio.h>#include <stdlib.h>#include <libavcodec/avcodec.h>#include <libavutil/common.h>#ifndef __JNI_TEST_H__#define __JNI_TEST_H__#define LOG_TAG ("Tag")#define LOGD(...)   __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)#define LOGI(...)   __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)#ifdef __cplusplusextern "C"{#endifJNIEXPORT jstring JNICALL Java_com_jjws_testanim_JNITest_testFFmpegLib(JNIEnv *env, jobject thiz) {    unsigned int ver = avcodec_version();    const char *config  = avcodec_configuration();    const char *license = avcodec_license();    char *des = NULL;    const char *version_str = "AVCodec Version:";    const char *config_str = "AVCodec Configuration:";    const char *license_str = "AVCodec license:";    jstring jstr = NULL;    int ver_len = 0, config_len = 0, license_len = 0, len = 0;    ver_len = sizeof(unsigned int);    if(config != NULL) {        config_len = strlen(config);    }    if(license != NULL) {        license_len = strlen(license);    }    len = ver_len + config_len + license_len + strlen(version_str) + strlen(config_str) + strlen(license_str) + 4 + 1;    des = (char*)malloc(len);    if(des == NULL)        return NULL;    memset(des, 0x00, len);    strcpy(des, version_str);    sprintf(des+strlen(version_str), "%d", ver);    strcat(des, "\n");    strcat(des, "\n");    strcat(des, license_str);    strcat(des, license);    strcat(des, "\n");    strcat(des, "\n");    strcat(des, config_str);    strcat(des, config);    jstr = (jstring)(*env)->NewStringUTF(env, des);    (*env)->ReleaseStringUTFChars(env, jstr, (const char*)des);    return jstr;}#ifdef __cplusplus}#endif

对应的Android.mk文件内容如下:

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_FFMPEG_PATH := $(LOCAL_PATH)/ffmpegLOCAL_MODULE := libffmpegLOCAL_SRC_FILES := $(LOCAL_FFMPEG_PATH)/libffmpeg.soLOCAL_C_INCLUDES +=     $(LOCAL_FFMPEG_PATH)/libavcodec \            $(LOCAL_FFMPEG_PATH)/libavutil \            $(LOCAL_FFMPEG_PATH)/libavformat \            $(LOCAL_FFMPEG_PATH)/libswscale \                        $(LOCAL_FFMPEG_PATH)/libavdevice \                        $(LOCAL_FFMPEG_PATH)/libavfilter \                        $(LOCAL_FFMPEG_PATH)/libswresampleinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := libJNITestLOCAL_SRC_FILES := JNITest.cLOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/ffmpegLOCAL_LDLIBS := -llogLOCAL_SHARED_LIBRARIES := libffmpeginclude $(BUILD_SHARED_LIBRARY)

Appllication.mk文件内容如下:

APP_OPTIM := debugAPP_ABI := armeabiAPP_PLATFORM := android-19

jni文件对应的java加载动态库的文件内容如下:

public class JNITest {    private static JNITest instance = null;    static {        System.loadLibrary("JNITest");    }    public native String testFFmpegLib();    public JNITest() {    }    public static JNITest getInstance() {        if(instance == null) {            instance = new JNITest();        }        return instance;    }}

测试界面MainActivity的内容如下:

package com.jjws.testanim;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends Activity {     private TextView jnistr;     private JNITest mJNITest = null;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        jnistr = (TextView) findViewById(R.id.jnistr);        mJNITest = JNITest.getInstance();        jnistr.setText(mJNITest.testFFmpegLib());    }}

3.在jni目录执行ndk-build编译命令,即可生成相应的libJNITest.so动态库。不出意外会在libs文件夹生成libJNITest.so和libffmpeg.so库。我的工程是用的jniLibs文件夹。可手动拷贝到jniLibs文件夹,也可在Android.mk中添加shell命令自动拷贝。生成库的结果如下:
编译结果:
这里写图片描述

生成的库:
这里写图片描述

4.连上手机调试,查看结果。
这里写图片描述

从上面测试结果可以看出,成功打印出了avcodec的version, configuration 和 license。说明我们编译出来的库可用。后面可直接使用该库及头文件进行ffmpeg的开发。
FFMPEG是用C编写的。且解构不太清晰,可用的文档很少。中文文档更是稀有。且ffmpeg每个版本之间存在差异。尤其是早起版本,差异很大,很多API的名字及参数个数都做了更改。所以直接下载早起版本的测试程序用这个库编译会报很多错。不过万变不离其宗,只要掌握了ffmpeg的精髓。随便怎么该都没关系。

0 0
原创粉丝点击