根据上一篇文章《FFmpeg For Android (二) Ubuntu下编译FFmpeg源码》我们熟悉了如何在Ubuntu下编译FFmpeg, 但我们却不知道有何用…
本篇将讲解 移植ffmpeg 的main函数到安卓上 直接执行ffmpeg命令
现在你将可以做很多有趣的app 比如 支持几乎全格式的视频、音频转换、剪切、合并、水印、混合、视频转gif 获取某一帧图片(则获取支持全格式视频的缩略图)等。。。
有木有开始激动了???
1.重新编译FFmpeg, 开启configure相关参数
回到build_andorid.sh文件 编辑–enable一些相关配置
如下(注意把路径换成你系统的路径 并检查路径是否存在 (已经在上一篇说了 这篇不再详细讲解)
NDK=/home/ubuntu/桌面/Android/NDK/android-ndk-r10e
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
function build_android
{
./configure \
--prefix=/home/ubuntu/桌面/Android/FFmpeg/ffmpeg-3.2/android/arm \
--enable-neon \
--enable-hwaccel=h264_vaapi \
--enable-hwaccel=h264_vaapi \
--enable-hwaccel=h264_dxva2 \
--enable-hwaccel=mpeg4_vaapi \
--enable-hwaccels \
--enable-shared \
--enable-jni \
--enable-mediacodec \
--disable-static \
--disable-doc \
--enable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--enable-avdevice \
--disable-doc \
--disable-symver \
--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 -j4
make install
}
ADDI_CFLAGS="-marm"
build_android
然后保存并开始编译FFmpeg
编译好了 得到的so文件变多了, 如图
/home/ubuntu/桌面/Android/FFmpeg/ffmpeg-3.2/android/arm下
2.编写Android C/C++程序
这里 肯定用jni了…
win下也需要安装NDK环境 教程太多太简单 这里不再讲解 请自行解决(能看到这个文章的人一般都装好了 win版的NDK )…
我们回到Windows 打开Android Studio新建一个工程MyFFmpeg
开启Android Studio 对C/C++支持
编辑local.properties文件,添加ndk路径(请按你windows下的ndk实际路径 不要照抄)
ndk.dir=D\:\\Android\\sdk\\ndk-bundle
sdk.dir=D\:\\Android\\sdk
编辑gradle.properties文件
末尾添加
android.useDeprecatedNdk = true
然后rebuild project一下
在MyFFmpeg\app\新建一个该路径的文件夹 jnicode\jni
在jni文件夹新建 prebuilt 文件夹
回到Ubuntu系统 进入
/home/ubuntu/桌面/Android/FFmpeg/ffmpeg-3.2
把已解压并且已编译好的FFmpeg so库一起压缩 , 就是直接压缩ffmpeg-3.2 文件夹
压缩格式选择rar 避免win下不能解压..
呐…压缩好了 如图
直接拖动到win下 (如果你的不支持 请想其他办法)
回到Win下 解压ffmpeg-3.2.rar文件 到我们刚才那个工程的目录里
D:\Android\AndroidStudioProjects\MyFFmpeg\ffmpeg-3.2\
进入复制 fmpeg-3.2\android\arm\lib下的所有so文件到
MyFFmpeg\app\jnicode\jni\prebuilt下
复制整个ffmpeg-3.2\android\arm\include文件夹 到MyFFmpeg\app\jnicode\jni\下
以上两次复制 项目结构变成了这样
编写native方法 , 新建类FFmpegCmd .java 简单的添加一个exec()方法(等会还要改)
package com.toshiba.ffmpeg;
/**
* 作者:东芝(2016/11/23).
*/
public class FFmpegCmd {
public static native int exec(int argc,String[] argv);
}
然后编译为class文件 你可以直接使用android studio的make功能
点击菜单项里的>Build>Make Module app
然后class文件生成到 MyFFmpeg\app\build\intermediates\classes\debug\下
然后使用javah命令去生成头文件
打开win命令行
cd 进入到 刚才那个debug文件夹下执行 javah -jni 包名.类名,如:
javah -jni com.toshiba.ffmpeg.FFmpegCmd
如图
然后看到debug目录下生成了头文件
com_toshiba_ffmpeg_FFmpegCmd.h
把刚才生成的头文件复制到MyFFmpeg\app\jnicode\jni\下
com_toshiba_ffmpeg_FFmpegCmd.h的内容为:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_toshiba_ffmpeg_FFmpegCmd */
#ifndef _Included_com_toshiba_ffmpeg_FFmpegCmd
#define _Included_com_toshiba_ffmpeg_FFmpegCmd
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_toshiba_ffmpeg_FFmpegCmd
* Method: exec
* Signature: (I[Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_toshiba_ffmpeg_FFmpegCmd_exec
(JNIEnv *, jclass, jint, jobjectArray);
#ifdef __cplusplus
}
#endif
#endif
然后, 我们新建一个相同名称的文件 并修改后缀为.c 并导入相关头文件实现其对应函数
com_toshiba_ffmpeg_FFmpegCmd.c的内容为(等会还要改)
#include "com_toshiba_ffmpeg_FFmpegCmd.h"
#include <string.h>
/*
* Class: com_toshiba_ffmpeg_FFmpegCmd
* Method: exec
* Signature: (I[Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_toshiba_ffmpeg_FFmpegCmd_exec
(JNIEnv *env, jclass clazz, jint cmdnum, jobjectArray cmdline){
return 1111;//临时测试数字
}
在 MyFFmpeg\app\jnicode\jni\下 创建Android.mk Application.mk 空文件
Android.mk内容为
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libavutil
LOCAL_SRC_FILES := prebuilt/libavutil-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libswresample
LOCAL_SRC_FILES := prebuilt/libswresample-2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libswscale
LOCAL_SRC_FILES := prebuilt/libswscale-4.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libavcodec
LOCAL_SRC_FILES := prebuilt/libavcodec-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libavformat
LOCAL_SRC_FILES := prebuilt/libavformat-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libavfilter
LOCAL_SRC_FILES := prebuilt/libavfilter-6.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libavdevice
LOCAL_SRC_FILES := prebuilt/libavdevice-57.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES :=com_toshiba_ffmpeg_FFmpegCmd.c
LOCAL_C_INCLUDES := D:\Android\AndroidStudioProjects\MyFFmpeg\ffmpeg-3.2
LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid -lm -pthread -L$(SYSROOT)/usr/lib
LOCAL_SHARED_LIBRARIES := libavcodec libavfilter libavformat libavutil libswresample libswscale libavdevice
include $(BUILD_SHARED_LIBRARY)
如果你不会这里这些语法 那么你肯定是跳级 直接来学ffmpeg了 这些配置的意义和注意事项应该是在你学完jni基础再来看这篇文章才能懂的 建议先去学一遍jni (我等后面有空再写这方面的文章)
先注意两个地方:
LOCAL_SRC_FILES 这里指定so文件或c/cpp等待编译文件的路径
LOCAL_C_INCLUDES 这里是重点 导入ffmpeg的源码 这样方便打包时不会提示缺少xxx文件 当然不会把ffmpeg全部打包进去
LOCAL_SHARED_LIBRARIES 里的名称要和LOCAL_MODULE 里的名称一致
Application.mk内容为
APP_ABI := armeabi-v7a
APP_PLATFORM=android-14
APP_ABI 这里打包只是为了支持ARMv7的设备 其他的请改成 armeabi armeabi-v7a x86以便支持更多设备
APP_PLATFORM 指定哪个版本没太多要求
最后经过上面的一番折腾
项目结构应该是这样子的 (注意观察你的是否跟我的结构一致)
3.移植main函数
到 MyFFmpeg\ffmpeg-3.2\下
复制以下文件
cmdutils.c
cmdutils.h
cmdutils_common_opts.h
config.h
ffmpeg.c
ffmpeg.h
ffmpeg_filter.c
ffmpeg_opt