ffmpeg动态库在android上的测试

来源:互联网 发布:linux磁盘分区挂载 编辑:程序博客网 时间:2024/06/05 03:43

上篇文章介绍了怎样用虚拟机把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;@Overrideprotected 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)#ffmpeginclude $(CLEAR_VARS)LOCAL_MODULE:= avcodecLOCAL_SRC_FILES:= libavcodec-57.soLOCAL_MODULE_FILENAME:=libavcodec-57include $(PREBUILT_SHARED_LIBRARY)  ##指明此模块需要预编译include $(CLEAR_VARS)LOCAL_MODULE:= avfilterLOCAL_SRC_FILES:= libavfilter-6.soLOCAL_MODULE_FILENAME:=libavfilter-6include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= avformatLOCAL_SRC_FILES:= libavformat-57.soLOCAL_MODULE_FILENAME:=libavformat-57include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= avutilLOCAL_SRC_FILES:= libavutil-55.soLOCAL_MODULE_FILENAME:=libavutil-55include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= swresampleLOCAL_SRC_FILES:= libswresample-2.soLOCAL_MODULE_FILENAME:=libswresample-2include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= swscaleLOCAL_SRC_FILES:= libswscale-4.soLOCAL_MODULE_FILENAME:=libswscale-4include $(PREBUILT_SHARED_LIBRARY)#end#myinclude $(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__)#endifJNIEXPORT 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);//Inputwhile (if_temp != NULL) {sprintf(info, "%s[In ][%10s]\n", info, if_temp->name);if_temp = if_temp->next;}//Outputwhile (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的运行截图




阅读全文
0 0
原创粉丝点击