ffmpeg动态库在android上的测试

上篇文章介绍了怎样用虚拟机把ffmpeg编译成android可用的动态库,这次把动态库引入eclipse android工程,并调用ffmpeg类库

注意,在网页上粘贴的代码,很多符号会变成中文的,导致很难发现的错误...

如果没有so库的朋友,可以参考我的上一篇博客,之中也有编译好的下载地址,ndk版本是r13,ffmpeg版本是3.1.3,abi是armeabi-v7a,在华为4x上运行通过

下面开始:

1.so库和头文件复制到安卓工程jni目录下,并创建Android.mk,Application.mk,HelloJni.c文件,

Android.mk:指明so库如何引入,编译那些c文件,因为ffmpeg是c写的,所以写c++调用可能会有问题,这个文件描述如何编译动态库

Application.mk:可以指明编译时生成那些目标cpu架构的so,我的华为4x是armeabi-v7a

HelloJni.c:实现java的native方法

JniUtils.java

package com.example.ffmpegtest001;

public class JniUtils {

	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("hello-jni");
	}

	public native String stringFromJNI();

	public native String avformatinfo();

	public native String avcodecinfo();

	public native String avfilterinfo();

	public native String configurationinfo();
}
MainActivity.java
package com.example.ffmpegtest001;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends ActionBarActivity {
	private TextView textView;
	JniUtils jniUtils;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		jniUtils = new JniUtils();
		textView = (TextView) findViewById(R.id.textview);
	}

	public void format(View view) {
		textView.setText(jniUtils.avformatinfo());
	}

	public void codec(View view) {
		textView.setText(jniUtils.avcodecinfo());
	}

	public void filter(View view) {
		textView.setText(jniUtils.avfilterinfo());
	}

	public void config(View view) {
		textView.setText(jniUtils.configurationinfo());
	}

	
}

Android.mk

LOCAL_PATH := $(call my-dir)

#ffmpeg
include $(CLEAR_VARS)
LOCAL_MODULE:= avcodec
LOCAL_SRC_FILES:= libavcodec-57.so
LOCAL_MODULE_FILENAME:=libavcodec-57
include $(PREBUILT_SHARED_LIBRARY)  ##指明此模块需要预编译

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

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

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

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

include $(CLEAR_VARS)
LOCAL_MODULE:= swscale
LOCAL_SRC_FILES:= libswscale-4.so
LOCAL_MODULE_FILENAME:=libswscale-4
include $(PREBUILT_SHARED_LIBRARY)
#end


#my
include $(CLEAR_VARS)
#指明自己模块的名称
LOCAL_MODULE    := hello-jni
#指明自己模块需要的源代码
LOCAL_SRC_FILES := HelloJni.c
#指明.so库的头文件路径
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
#指明需要使用的ndk自带模块
LOCAL_LDLIBS := -llog -lz -landroid
#指明自己模块编译时需要依赖的模块
LOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil swresample swscale
#指明自己的模块编译为动态库
include $(BUILD_SHARED_LIBRARY)
Application.mk
#指明编译时生成armeabi-v7a架构的so文件
APP_ABI := armeabi-v7a 
HelloJni.c

#include <string.h>
//#include "com_example_ffmpegtest001_JniUtils.h"
#include <stdio.h>

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include "include/libavutil/avutil.h"
#include "include/libavfilter/avfilter.h"

//http://www.pps.tv/w_19rt0grxmx.html  很好的视频

//Log
#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 JNICALL Java_com_example_ffmpegtest001_JniUtils_stringFromJNI(
		JNIEnv* env, jobject thiz) {
	//return env->NewStringUTF("Hello from JNI !  Compiled with ABI ");
	return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI ");
}

JNIEXPORT jstring JNICALL Java_com_example_ffmpegtest001_JniUtils_avformatinfo(
		JNIEnv* env, jobject thiz) {
	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(info);
	return (*env)->NewStringUTF(env, info);
}
JNIEXPORT jstring JNICALL Java_com_example_ffmpegtest001_JniUtils_avcodecinfo(
		JNIEnv* env, jobject thiz) {
	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);
	// return env->NewStringUTF(info);

}
JNIEXPORT jstring JNICALL Java_com_example_ffmpegtest001_JniUtils_avfilterinfo(
		JNIEnv* env, jobject thiz) {
	char info[40000] = { 0 };
	avfilter_register_all();
	AVFilter *f_temp = (AVFilter *) avfilter_next(NULL);
	int i = 0;
	while (f_temp != NULL) {
		sprintf(info, "%s[%10s]\n", info, f_temp->name);
		f_temp = f_temp->next;
	}
	return (*env)->NewStringUTF(env, info);
	//  return env->NewStringUTF( info);
}
JNIEXPORT jstring JNICALL Java_com_example_ffmpegtest001_JniUtils_configurationinfo(
		JNIEnv* env, jobject thiz) {
	char info[10000] = { 0 };
	av_register_all();

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

	//LOGE("%s", info);
	//return env->NewStringUTF(info);
	return (*env)->NewStringUTF(env, info);
}
其中每个c方法对应一个java的native方法

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.ihubin.ffmpegstudy.MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:onClick="format"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Format" />

        <Button
            android:onClick="codec"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Codec" />

        <Button
            android:onClick="filter"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Filter" />

        <Button
            android:onClick="config"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Config" />
    </LinearLayout>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <TextView
            android:id="@+id/textview"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </ScrollView>

</LinearLayout>

我的华为4x的运行截图




猜你喜欢

转载自blog.csdn.net/qq_31683775/article/details/78883504
今日推荐