FFmpeg For Android (三) 移植main函数到安卓上执行ffmpeg命令

本文介绍了如何将FFmpeg的main函数移植到Android应用中,实现视频、音频的转换、剪切、合并等功能。通过重新编译FFmpeg,配置Android项目,使用JNI,并提供了一个简单的测试例子,展示了如何在Android上执行ffmpeg命令。
摘要由CSDN通过智能技术生成

根据上一篇文章《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
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值