环境 Linux
NDk版本:13
FFmpeg 版本3.3.3
Linux 环境下配置NDK省略。。。。
FFmpeg 解压省略。。。。。
开始进入正题了 稍等片刻
首先进ffmpeg 下的configure 文件中的:
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)'
继续往下走
配置ffmpeg 编译所需要的sh文件
#!/bin/bash
NDK=/home/qichaungguo/NDK/android-ndk-r13
SYSROOT=$NDK/platforms/android-16/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
CPU=arm
PREFIX=/home/qichaungguo/ff
ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--enable-small \
--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
}
build_one
注意替换自己的路径其中PREFIX 是生成的目录。
等待个几分钟吧 一切都好了 就会生成一个include 和lib目录
我们用Android studio 测试一番。
来创建一个项目 ,,,,几分钟过后创建好了。
在main 目录下创建一个jni目录,将编译后的ffmpeg生成的include文件拷贝进去,将lib中的so也拷贝进去。
大概就是这样子:
创建一个cpp文件 写一个测试ffmpeg的类子。
开始上源码:
//
// Created by chuangguo.qi on 2017/8/3.
//
extern "C" {
#include <jni.h>
#include <libavformat/avformat.h>"
#define LOG_TAG "FFMPEGSample"
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
#include "include/libavcodec/avcodec.h"
}
extern "C" {
jint getFFmpegText(JNIEnv *env, jobject obj, jint id) {
av_register_all();
AVCodecID avCodecID = AV_CODEC_ID_H264;
LOGI("%d",avCodecID);
LOGI("%d",id);
AVCodec *vCodec = avcodec_find_decoder(avCodecID);
if (vCodec!=NULL){
return 0;
} else{
return -1;
}
}
static JNINativeMethod gMethods[]={
//(I) 参数 I 返回值
{"getFFmpegText", "(I)I", (void *)getFFmpegText},
};
static const char *ClassName = "com/android/cgcxy/ffmpegdemo/JniUtils";
static int registerNativeMethods(JNIEnv *env) {
jclass clazz;
clazz = env->FindClass(ClassName);
if (clazz == NULL) {
LOGI("class==null");
return JNI_FALSE;
}
if(env->RegisterNatives(clazz, gMethods, sizeof(gMethods)/sizeof(gMethods[0])) < 0){
return JNI_FALSE;
}
return JNI_TRUE;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)
{
LOGE("ERROR: GetEnv failed\n");
goto bail;
}
if (registerNativeMethods(env) < 0) {
LOGE("ERROR: jnitest native registration failed\n");
goto bail;
}
result = JNI_VERSION_1_4;
bail:
return result;
}
}
一切准备就绪 接下我们就去配置 开始生成so了 哈哈 继续哦,,,
创建mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := libavcodec-57.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)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := ffmeng.cpp
LOCAL_LDLIBS += -llog -lz -landroid
LOCAL_MODULE := VideoPlay
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_SHARED_LIBRARIES:= avcodec avformat avutil swresample swscale
include $(BUILD_SHARED_LIBRARY)
这就ok了 ,,,来来 再去走最后一步,配置build:
externalNativeBuild {
ndkBuild {
abiFilters 'armeabi'
cppFlags "-fpermissive", "-fexceptions"
cFlags "-Wno-error=format-security"
}
}
ndk {
stl 'gnustl_static'
}
}
sourceSets {
main {
jniLibs.srcDir file('jni/')
}
}
externalNativeBuild {
ndkBuild {
path 'src\\main\\jni\\Android.mk'
}
}
奇迹将要发生了。。。点击 make project ,在ndkbuild 下会生成所以的so 库 完美 哈哈 结束
哈哈 等等 其中还有个坑 给忘了。。。
common.h 文件会报错 解决办法如下:
//最顶端添加
extern "C"
{
#ifdef __cplusplus
#define __STDC_CONSTANT_MACROS
#endif
}
//在
#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) && !defined(UINT64_C)
#error missing -D__STDC_CONSTANT_MACROS / #define __STDC_CONSTANT_MACROS
#endif
//下面添加如下代码;
/*#ifndef __MICloudPub___H264Decoder__
#define __MICloudPub___H264Decoder__
#ifndef UINT64_C
#define UINT64_C(value) __CONCAT(value, ULL)
#endif*/
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
#define CONFIG_WIN32
#endif
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(EMULATE_INTTYPES)
#define EMULATE_INTTYPES
#endif
#ifndef EMULATE_INTTYPES
#include <inttypes.h>
#else
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#ifdef CONFIG_WIN32
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else /* other OS */
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
#endif /* other OS */
#endif /* EMULATE_INTTYPES */
//解决UINT64_C没定义的问题
#ifndef INT64_C
#define INT64_C(c) (c##LL)
#define UINT64_C(c) (c##ULL)
#endif