1. 程式人生 > >android-studio使用cmake編譯ffmpeg實踐

android-studio使用cmake編譯ffmpeg實踐

本例使用的是合併的libffmpeg庫,可參考之前的實踐操作 android全平臺編譯ffmpeg合併為單個庫實踐

目錄

配置環境

作業系統: ubuntu 16.05

注意: ffmpeg庫的編譯使用的是android-ndk-r10e版本,使用高版本編譯會報錯

android-studio工程中配合cmake使用的版本則是android-ndk-r16b版本

新建工程ffmpeg-single-hello

  • 配置build.gradle如下
android {
    .
..... defaultConfig { ...... externalNativeBuild { cmake { cppFlags "" } ndk { abiFilters "armeabi-v7a" } } sourceSets { main { //庫地址 jniLibs.
srcDirs = ['libs'] } } } ...... externalNativeBuild { cmake { path "CMakeLists.txt" } } }
  • 新建CMakeLists.txt檔案,配置如下

cmake_minimum_required(VERSION 3.4.1)

add_library(ffmpeg-hello
           SHARED
           src/main/cpp/ffmpeg_hello.
c) find_library(log-lib log) #獲取上級目錄的路徑 get_filename_component(PARENT_DIR ${CMAKE_SOURCE_DIR} PATH) set(LIBRARY_DIR ${PARENT_DIR}/ffmpeg-single) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") set(CMAKE_VERBOSE_MAKEFILE on) add_library(ffmpeg-single SHARED IMPORTED) set_target_properties(ffmpeg-single PROPERTIES IMPORTED_LOCATION ${LIBRARY_DIR}/libs/${ANDROID_ABI}/libffmpeg.so ) #包含標頭檔案 include_directories(${LIBRARY_DIR}/libs/${ANDROID_ABI}/include) target_link_libraries(ffmpeg-hello ffmpeg-single ${log-lib})

筆者這裡考慮到後續的都是基於同一個libffmpeg.so庫,因此不必每個module都放置一個,因此單獨分離了一個元件ffmpeg-single,將所需要的標頭檔案和庫放置在libs目錄
其他的單個庫例子則都是依賴這個庫

  • 新建類FFmpegHello.java
package com.onzhou.ffmpeg.hello;

public class FFmpegHello {

    static {
        System.loadLibrary("ffmpeg");
        System.loadLibrary("ffmpeg-hello");
    }

    public native String urlprotocolinfo();

    public native String avformatinfo();

    public native String avcodecinfo();

    public native String avfilterinfo();

    public native String configurationinfo();

}
  • src/main/cpp目錄新建原始檔ffmpeg_hello.c

#include <jni.h>
#include <stdio.h>
#include <time.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavfilter/avfilter.h"
#include "libavutil/log.h"

#ifdef ANDROID
#include <android/log.h>
#define LOG_TAG    "FFmpegHello"
#define LOGE(format, ...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__)
#define LOGI(format, ...)  __android_log_print(ANDROID_LOG_INFO,  LOG_TAG, format, ##__VA_ARGS__)
#else
#define LOGE(format, ...)  printf(LOG_TAG format "\n", ##__VA_ARGS__)
#define LOGI(format, ...)  printf(LOG_TAG format "\n", ##__VA_ARGS__)
#endif

JNIEXPORT jstring JNICALL Java_com_onzhou_ffmpeg_hello_FFmpegHello_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);
	return (*env)->NewStringUTF(env, info);
}


JNIEXPORT jstring JNICALL Java_com_onzhou_ffmpeg_hello_FFmpegHello_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);
}


JNIEXPORT jstring JNICALL Java_com_onzhou_ffmpeg_hello_FFmpegHello_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);
}

JNIEXPORT jstring JNICALL Java_com_onzhou_ffmpeg_hello_FFmpegHello_avfilterinfo
  (JNIEnv * env, jobject obj){

    char info[40000] = { 0 };

	avfilter_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);
}


JNIEXPORT jstring JNICALL Java_com_onzhou_ffmpeg_hello_FFmpegHello_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);
}
  • 編譯打包執行,輸出如下資訊:

專案地址:
https://github.com/byhook/ffmpeg4android

參考:
https://blog.csdn.net/leixiaohua1020/article/details/47008825