android全平台编译ffmpeg支持命令行实践
16lz
2021-01-23
音视频实践学习
- android全平台编译ffmpeg以及x264与fdk-aac实践
- ubuntu下使用nginx和nginx-rtmp-module配置直播推流服务器
- android全平台编译ffmpeg合并为单个库实践
- android-studio使用cmake编译ffmpeg实践
- android全平台编译ffmpeg视频解码器实践
- android全平台编译ffmpeg支持命令行实践
- android全平台编译ffmpeg视频推流实践
- android平台下音频编码之编译LAME库转码PCM为MP3
- ubuntu平台下编译vlc-android视频播放器实践
- 图解YU12、I420、YV12、NV12、NV21、YUV420P、YUV420SP、YUV422P、YUV444P的区别
- 图解RGB565、RGB555、RGB16、RGB24、RGB32、ARGB32等格式的区别
- YUV420P、YUV420SP、NV12、NV21和RGB互相转换并存储为JPEG以及PNG图片
- android全平台编译libyuv库实现YUV和RGB的转换
本例基于 android全平台编译ffmpeg合并为单个库实践 进行的
目录
- 环境准备
- 新建cmd工程
- 修改源文件
- 运行输出
环境准备
操作系统 ubuntu 16.05
编译准备好libffmpeg库
和需要include头文件
,我们还需要抽取ffmpeg-3.3.8中
的部分头文件和源文件
笔者整理了一个copy_ffmpeg_files.sh
脚本
FFMPEG_DIR=ffmpeg-3.3.8mkdir includemkdir include/compatmkdir include/libavcodecmkdir include/libavformatmkdir include/libavutilmkdir include/libavdevicemkdir include/libpostproccp $FFMPEG_DIR/compat/va_copy.h include/compat/va_copy.hcp $FFMPEG_DIR/libavcodec/mathops.h include/libavcodec/mathops.hcp $FFMPEG_DIR/libavdevice/avdevice.h include/libavdevice/avdevice.hcp $FFMPEG_DIR/libavdevice/version.h include/libavdevice/version.hcp $FFMPEG_DIR/libavformat/ffm.h include/libavformat/ffm.hcp $FFMPEG_DIR/libavformat/network.h include/libavformat/network.hcp $FFMPEG_DIR/libavformat/os_support.h include/libavformat/os_support.hcp $FFMPEG_DIR/libavformat/url.h include/libavformat/url.hcp $FFMPEG_DIR/libavutil/libm.h include/libavutil/libm.hcp $FFMPEG_DIR/libavutil/internal.h include/libavutil/internal.hcp $FFMPEG_DIR/libavutil/reverse.h include/libavutil/reverse.hcp $FFMPEG_DIR/libavutil/timer.h include/libavutil/timer.hcp $FFMPEG_DIR/libpostproc/postprocess.h include/libpostproc/postprocess.hcp $FFMPEG_DIR/libpostproc/version.h include/libpostproc/version.h#cppmkdir cppcp $FFMPEG_DIR/cmdutils.c cpp/cmdutils.ccp $FFMPEG_DIR/cmdutils.h cpp/cmdutils.hcp $FFMPEG_DIR/cmdutils_common_opts.h cpp/cmdutils_common_opts.h#cp $FFMPEG_DIR/config.h cpp/config.hcp $FFMPEG_DIR/ffmpeg.h cpp/ffmpeg.hcp $FFMPEG_DIR/ffmpeg.c cpp/ffmpeg_mod.ccp $FFMPEG_DIR/ffmpeg_filter.c cpp/ffmpeg_filter.ccp $FFMPEG_DIR/ffmpeg_opt.c cpp/ffmpeg_opt.c
- 文件目录结构如下:
将生成之后的
include
文件夹覆盖到项目中的include目录
本例中即覆盖到ffmpeg-single
组件下的libs/armeabi-v7a
的include目录
新建ffmpeg-single-cmd
工程
将生成的cpp目录
复制到src/main目录下
- 新建
FFmpegCmd类
public class FFmpegCmd { static { System.loadLibrary("ffmpeg"); System.loadLibrary("ffmpeg-cmd"); } public native int exec(int argc, String[] argv);}
- 新建
ffmpeg_cmd.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 "HelloFFmpeg"#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__)#endifint exec(int argc, char **argv);void custom_log(void *ptr, int level, const char *fmt, va_list vl) { FILE *fp=fopen("/storage/emulated/0/Android/data/com.onzhou.ffmpeg.cmd/files/av_log.txt","a+"); if(fp){ vfprintf(fp,fmt,vl); fflush(fp); fclose(fp); }}JNIEXPORT jint JNICALL Java_com_onzhou_ffmpeg_cmd_FFmpegCmd_exec (JNIEnv *env, jobject obj, jint cmdnum, jobjectArray cmdline) { av_log_set_callback(custom_log); int argc = cmdnum; char **argv = (char **) malloc(sizeof(char *) * argc); int i = 0; for (i = 0; i < argc; i++) { jstring string = (*env)->GetObjectArrayElement(env, cmdline, i); const char *tmp = (*env)->GetStringUTFChars(env, string, 0); argv[i] = (char *) malloc(sizeof(char) * 1024); strcpy(argv[i], tmp); } exec(argc, argv); for (i = 0; i < argc; i++) { free(argv[i]); } free(argv); return 0;}
- 新建
ffmpeg_cmd.h
头文件
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_onzhou_ffmpeg_cmd_FFmpegCmd */#ifndef _Included_com_onzhou_ffmpeg_cmd_FFmpegCmd#define _Included_com_onzhou_ffmpeg_cmd_FFmpegCmd#ifdef __cplusplusextern "C" {#endif/* * Class: com_onzhou_ffmpeg_cmd_FFmpegCmd * Method: exec * Signature: (I[Ljava/lang/String;)V */JNIEXPORT jint JNICALL Java_com_onzhou_ffmpeg_cmd_FFmpegCmd_exec (JNIEnv *, jobject, jint, jobjectArray);#ifdef __cplusplus}#endif#endif
build.gradle
中的配置
不多说了,可以参考之前的实践配置
- 配置
CMakeLists.txt文件
cmake_minimum_required(VERSION 3.4.1)add_library(ffmpeg-cmd SHARED src/main/cpp/ffmpeg_cmd.c src/main/cpp/cmdutils.c src/main/cpp/ffmpeg_filter.c src/main/cpp/ffmpeg_opt.c src/main/cpp/ffmpeg_mod.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 src/main/cpp)target_link_libraries(ffmpeg-cmd ffmpeg-single ${log-lib})
修改源文件
- 修改
cmdutils.c
文件
void exit_program(int ret){ if (program_exit) program_exit(ret); exit(ret);}
#改为
int exit_program(int ret){ if (program_exit) program_exit(ret); //exit(ret); return ret;}
- 修改
cmdutils.h
头文件
void exit_program(int ret) av_noreturn;
#改为
int exit_program(int ret) av_noreturn;
- 修改
ffmpeg_mod.c
文件
int main(int argc, char **argv)
#改为
int exec(int argc, char **argv)
在return main_return_code;
之前加上如下代码:
nb_filtergraphs = 0;progress_avio = NULL;input_streams = NULL;nb_input_streams = 0;input_files = NULL;nb_input_files = 0;output_streams = NULL;nb_output_streams = 0;output_files = NULL;nb_output_files = 0;
- 测试执行命令行进行转码
public void onCmdClick(View view) { if (fFmpegCmd == null) { fFmpegCmd = new FFmpegCmd(); } btnTransfer.setEnabled(false); File outputFile = new File(getExternalFilesDir(null), "output.mkv"); if (outputFile.exists()) { outputFile.delete(); } Schedulers.newThread().scheduleDirect(new Runnable() { @Override public void run() { String filePath = getExternalFilesDir(null).getAbsolutePath(); String cmdline = String.format("ffmpeg -i %s/input.mp4 %s/output.mkv", filePath, filePath); String[] argv = cmdline.split(" "); Integer argc = argv.length; fFmpegCmd.exec(argc, argv); } });}
运行输出
项目地址
https://github.com/byhook/ffmpeg4android
参考雷神:
https://blog.csdn.net/leixiaohua1020/article/details/47056365
更多相关文章
- Android 平台简介
- Visual Studio 跨平台开发实战(4) - Xamarin Android 基本控制项
- android中编译资源文件的相关问题
- moodle手机版在android平台上的安装配置
- 写TextView的Selector了解到的android读取xml文件的几点规则
- android私有目录直接读取
- Android基础知识之Manifest文件的组织结构
- android中一些配置文件的参数的意义