1、提供的能力

codec组件基于FFmpeg做的封装,通过命令行+jni调用FFmpeg库源码的方式提供编解码、封装/解封装、滤镜、重采样等能力,具体包括:

1、编码

原始音频(pcm)、视频(yuv)数据编码(aac、ac3、mp3、h264、h265、mpeg4、mjpeg)

2、解码

编码的音频、视频数据解码成原始数据(pcm、yuv)

3、转码

基于1-2实现转码,如RV40转换为MPEG4格式。有的封装格式标准规定,只支持几种固定的音频、视频编码格式,比如FLV视频支持H263、H264、Screen Video、On2 VP6,音频支持MP3、pcm、AAC、speex,在封装FLV时音频、视频不符合标准的话,会封装失败,比如想把AC3封装进FLV,此时需要转码。

4、封装

音频流、视频流封装成媒体文件

5、解封装

音视频数据(mp4、avi、flv)解封装音频流、视频流

6、转封装

基于3、4、5实现媒体文件格式转换,如mp4 ↔flv。可选定编码格式,也可以直接copy只转换媒体文件格式。

7、滤镜

视频裁剪、编辑、合成、水印等滤镜功能。

2、接口设计

接口分为jni接口、结果回调接口、调用接口。jni接口调用FFmpeg源码实现音视频处理,jni接口分为两部分,一是命令行接口,也就是通过FFmpeg命令行调用FFmpeg动态库,并返回命令执行进度以及执行结果;二是普通的jni接口,有些功能没有必要通过命令行实现,通过调用FFmpeg中源码更容易实现,比如获取FFmpeg版本、媒体文件信息。

2.1、jni接口

    static {System.loadLibrary("keffmpeg");}/*** @return 版本号*/public static native String getVersion();/*** 获取媒体文件(输入/输出)信息,封装信息+视频流信息+音频流信息** @param filePath 文件路径* @return*/public static native String getFileInfo(String filePath);/*** 通过命令行调用FFmpeg中的main方法** @param argc 参数个数* @param argv FFmpeg命令行参数*/public static native void exec(int argc, String[] argv);/*** 终止执行*/public static native void exit();/*** FFmpeg执行结束后的结果回调,由C代码中调用*/public static void onResult(int ret) {LogUtil.d(TAG, "onResult ret:" + ret);CmdExecutor.getInstance().getExecListener().onResult(ret);}/*** FFmpeg执行进度回调,由C代码调用*/public static void onProgress(float progress) {LogUtil.d(TAG, "onProcess:" + progress);CmdExecutor.getInstance().getExecListener().onProgress(progress);}

2.2、回调接口

FFmpeg的执行进度、执行结果需要告知调用方,通过Java中的反射机制获取jclass中的回调方法,JNIEnv调用Java中的回调方法并将C程序的执行结果传递给Java层。

/*** 回调执行Java方法* 参看 Jni反射+Java反射*/
void callJavaMethod(JNIEnv *env, jclass clazz, int ret) {if (clazz == NULL) {LOGE("---------------clazz isNULL---------------");return;}jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "onResult", "(I)V");if (methodID == NULL) {LOGE("---------------methodID isNULL---------------");return;}//调用该java方法(*env)->CallStaticVoidMethod(env, clazz, methodID, ret);
}void callJavaMethodProgress(JNIEnv *env, jclass clazz, float ret) {if (clazz == NULL) {LOGE("---------------clazz isNULL---------------");return;}jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "onProgress", "(F)V");if (methodID == NULL) {LOGE("---------------methodID isNULL---------------");return;}//调用该java方法(*env)->CallStaticVoidMethod(env, clazz, methodID, ret);
}/*** 执行进度回调** @param progress 执行进度,单位:秒*/void onProgress(float progress);/*** 命令执行结束回调** @param code 执行结果,code==0执行完成,!=0命令执行过程中出错*/void onResult(int code);

2.3、调用接口

注册监听器、反注册监听器、执行命令、终止执行

    public void registerListener(OnCmdExecListener onCmdExecListener) {if (onCmdExecListener == null) return;if (!mOnCmdExecListenerList.contains(onCmdExecListener)) {mOnCmdExecListenerList.add(onCmdExecListener);}}public void unRegisterListener(OnCmdExecListener onCmdExecListener) {if (onCmdExecListener == null) return;if (mOnCmdExecListenerList.contains(onCmdExecListener)) {mOnCmdExecListenerList.remove(onCmdExecListener);}}public void exec(String[] cmdArray) {if (cmdArray == null || cmdArray.length == 0) return;CodecNative.exec(cmdArray.length, cmdArray);}public void exit() {CodecNative.exit();}public OnCmdExecListener getExecListener() {return mOnCmdExecListener;}

3、编译FFmpeg

1、FFmpeg官网下载源码

Download FFmpeg ,本方案下载的5.0.1 "Lorentz"版本,包含如下库:

libavutil      57. 17.100
libavcodec     59. 18.100
libavformat    59. 16.100
libavdevice    59.  4.100
libavfilter     8. 24.100
libswscale      6.  4.100
libswresample   4.  3.100
libpostproc    56.  3.100

2、配置ndk环境变量

ndk下载地址:NDK 下载  |  Android NDK  |  Android Developers ,本方案使用android-ndk-r17c。

vim编辑bash_profile配置ndk环境变量,vim ~/.bash_profile,如下:

export NDKROOT=/Users/xiaobeizhang/Desktop/ke/ndk/android-ndk-r17c
export PATH=${PATH}:${NDKROOT}

source ~/.bash_profile保存

将ndk目录下的所有文件赋予最高权限,chmod -R 777 ./

3、编辑FFmpeg中的configure文件

由于默认configure脚本编译出来的动态库版本号在文件名后缀.so之后,如:libavcodec.so.7所以需要对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)'

将默认编译器由clang改为gcc

set_default target_os
if test "$target_os" = android; thencc_default="clang"
fi

4、编辑编译脚本

ffmpeg-5.0.1目录下创建编译动态库的脚本,touch build_android.sh

# 清空上次的编译
make clean
ADDI_CFLAGS="-marm"
PLATFORM=arm-linux-androideabi
# NDK路径
NDK=/Users/xiaobeizhang/Desktop/ke/ndk/android-ndk-r17c
# 设置android平台编译器的版本 这里采用Android 4.4
SYSROOT=$NDK/platforms/android-19/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
#编译使用的工具链
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
# 编译产物输出路径
OUTPUT=/Users/xiaobeizhang/Desktop/ke/ffmpeg/ffmpeg-5.0.1/android_out
function build
{
./configure \
--prefix=$OUTPUT \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=android \
--arch=armeabi-v7a \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic -marm" \
--extra-ldflags="-marm" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
#启动4个线程同时编译
make -j4
#生成的二进制文件安装到configure设置的prefix路径
make install
}
build

添加可执行权限,chmod a+x build_android.sh。

上述方式各个库会打包成6个动态库,不方便调用,可采用如下脚本打包成一个动态库:

# 清空上次的编译
make clean
ADDI_CFLAGS="-marm"
PLATFORM=arm-linux-androideabi
# NDK路径
NDK=/Users/xiaobeizhang/Desktop/ke/ndk/android-ndk-r17c
# 设置android平台编译器的版本 这里采用Android 4.4
SYSROOT=$NDK/platforms/android-17/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
#编译使用的工具链
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
# 编译产物输出路径
OUTPUT=/Users/xiaobeizhang/Desktop/ke/ffmpeg/ffmpeg-5.0.1/android_out_single
function build
{
./configure \--target-os=android \--prefix=$OUTPUT \--enable-cross-compile \--enable-static \--disable-shared \--disable-doc \--disable-ffmpeg \--disable-ffplay \--disable-ffprobe \--disable-avdevice \--disable-doc \--disable-symver \--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \--arch=arm \--sysroot=$SYSROOT \--extra-cflags="-I$ASM -isysroot $ISYSROOT -D__ANDROID_API__=17 -U_FILE_OFFSET_BITS -Os -fPIC -DANDROID -Wno-deprecated -mfloat-abi=softfp -marm" \--extra-ldflags="$ADDI_LDFLAGS" \$ADDITIONAL_CONFIGURE_FLAG
make clean
#启动4个线程同时编译
make -j4
#生成的二进制文件安装到configure设置的prefix路径
make install
# 打包$TOOLCHAIN/bin/arm-linux-androideabi-ld \-rpath-link=$SYSROOT/usr/lib \-L$SYSROOT/usr/lib \-L$PREFIX/lib \-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \$OUTPUT/libffmpeg.so \libavcodec/libavcodec.a \libavfilter/libavfilter.a \libavformat/libavformat.a \libavutil/libavutil.a \libswresample/libswresample.a \libswscale/libswscale.a \-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a# strip 精简文件$TOOLCHAIN/bin/arm-linux-androideabi-strip  $OUTPUT/libffmpeg.so
}
build

上述方式各个库先打包成静态库,最后链接为动态库,最后通过strip去符号。

5、生成产物

ffmpeg-5.0.1目录新建android_out目录用于存放产物。运行脚本,生成lib和include,lib中为动态库、include中为头文件。

4、集成FFmpeg

4.1、动态库

动态库采用armeabi-v7a架构,32位/64位的CPU都可以使用,并减少包提交。

4.2、FFmpeg源文件

命令行方式需要将FFmpeg中的部分源码(ffmpeg.c、cmdutils.c)做修改,命令行参数需要传入ffmpeg.c中的main方法,需要在ffmpeg.c的print_report中计算处理时长。

4.3、jni以及native

调用FFmpeg头文件以及源码文件

4.4、cmakeList

cmake版本注意版本不要太高,3.10以上的版本在链接目标库时经常失败,我采用的3.6。

cmake_minimum_required(VERSION 3.4.1)
add_library(# Sets the name of the library.keffmpeg# Sets the library as a shared library.SHARED# Provides a relative path to your source file(s).src/main/cpp/ffmpeg/cmdutils.csrc/main/cpp/ffmpeg/ffmpeg.csrc/main/cpp/ffmpeg/ffmpeg_filter.csrc/main/cpp/ffmpeg/ffmpeg_opt.csrc/main/cpp/ffmpeg_cmd.csrc/main/cpp/ffmpeg_thread.csrc/main/cpp/ffmpeg_base.cpp)
# 设置ffmpeg库所在路径的目录
set(distribution_DIR ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI})
# 添加libffmpeg.so库
add_library(ffmpegSHAREDIMPORTED )
# 指定libffmpeg.so库的位置
set_target_properties(ffmpegPROPERTIES IMPORTED_LOCATION${distribution_DIR}/libffmpeg.so )# 添加头文件路径
include_directories(src/main/cpp)
include_directories(src/main/cpp/ffmpeg)
include_directories(src/main/cpp/include)# 查找日志库
find_library(log-lib log)
find_library(android-lib android)# 将其他库链接到目标库keffmpeg
target_link_libraries(keffmpegffmpeg${log-lib} ${android-lib})

基于FFmpeg的编解码器设计实现方案相关推荐

  1. 激光测距仪传感器,基于EFM32控制器开发设计_方案

    随着现代科技的发展以及人们生活水平的提高,便携式激光测距仪在各行各业中都有广泛的应用,如建筑业,高尔夫,行车速度与车距测量.激光是一种电磁波,具有方向性强.单色性好.相干性好.亮度高等特性,使其成为测 ...

  2. 北大国际医院:基于互联网医疗的移动诊疗方案分析与设计

     1  前言 在北大国际医院,对互联网医疗的理解与应用结合了自身的特点及优势.一方面,北医系统内诸多主任专家.学科带头人作为科室骨干定期在国际医院出诊.同时,提供优质的医疗服务和就医环境是医院的重 ...

  3. 自适应控制---模型参考自适应控制(一)基于局部参数最优化的设计方法(MIT方案)

    模型参考自适应简介 基于局部参数最优化的设计方法(MIT方案) 举例 n<=4时的劳斯判据: n=1时,特征方程为:,各系数为正. n=2时,特征方程为,各系数为正. n=3时,特征方程为,各系 ...

  4. QT软件开发-基于FFMPEG设计视频播放器-解码音频(三)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...

  5. QT软件开发-基于FFMPEG设计录屏与rtsp、rtmp推流软件(支持桌面与摄像头)(一)

    QT软件开发-基于FFMPEG设计录屏与rtsp.rtmp推流软件(支持桌面与摄像头)(一) https://xiaolong.blog.csdn.net/article/details/126954 ...

  6. QT软件开发-基于FFMPEG设计录屏与rtsp、rtmp推流软件(支持桌面与摄像头)(四)

    QT软件开发-基于FFMPEG设计录屏与rtsp.rtmp推流软件(支持桌面与摄像头)(一) https://xiaolong.blog.csdn.net/article/details/126954 ...

  7. QT软件开发-基于FFMPEG设计视频播放器-软解图像(一)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...

  8. 动态口令设计系列一:基于共享密钥的动态口令方案

    2019独角兽企业重金招聘Python工程师标准>>> 由于传统的静态口令存在容易泄露(输入型泄密.传输型泄密.共享型泄密.记录型泄密.时间越长泄密危险性越高)且一旦泄露全线崩溃.不 ...

  9. QT软件开发-基于FFMPEG设计视频播放器-GPU硬解、OpenGL渲染、解码音频完整例子(六)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...

  10. QT软件开发-基于FFMPEG设计视频播放器-GPU硬解、OpenGL渲染(四)

    QT软件开发-基于FFMPEG设计视频播放器-CPU软解视频(一) https://xiaolong.blog.csdn.net/article/details/126832537 QT软件开发-基于 ...

最新文章

  1. 600页!分享珍藏很久的《推荐系统学习手册》(附下载链接及入门经验)
  2. JavaScript开发区块链只需200行代码
  3. 判断手机所属三大运营商 移动、联通、电信
  4. (转)用来理解Java的8个图表
  5. java内存四大区,jvm基础-内存区域
  6. 根据DbSchema生成代码2
  7. Mysql优化_ORDER BY和GROUP BY 的优化讲解(单路排序和双路排序)
  8. qemu-kvm命令行参数
  9. tablix“Tablix1”有一个具有内部成员的详细信息成员
  10. 面试时,如何向公司提问?
  11. JBOSS常用端口说明
  12. C++/CLI思辨录之Object的对象布局
  13. 美通企业日报 | 猫途鹰联手携程打造中国顶级旅行平台;强生战略合作阿里旗下Lazada...
  14. Android 静默安装
  15. themeleaf基本语法
  16. 助推外贸高质量发展,玉湖冷链模式引发服贸行业高度关注
  17. 家用计算机做raid有用吗,磁盘阵列是什么?家用有必要磁盘阵列吗
  18. 解决:IOS无法使用微软账号登录,显示“无法登录,请使用IMAP并重新登录“
  19. 前端进度报告(2018.6.3)
  20. (线段树)P5459 [BJOI2016]回转寿司

热门文章

  1. java jsp传值乱码_关于JSP乱码问题(页面传值产生的乱码)
  2. .NET 使用MD5加盐加密
  3. 计算机excel减法函数,excel减法函数的使用
  4. 安卓桌面壁纸_苹果iPhone全面屏桌面壁纸 第88期 苹果x手机专用高清壁纸
  5. CAD转JPG如何才能清晰?来看这两个方法
  6. Excel常用功能总结
  7. echar 数据显示在小圆点里
  8. 微信小程序合成海报_微信小程序生成海报实现方式
  9. 条码检测系统——基于MATLAB的一维条码识别
  10. Lua包管理工具Luarocks