### Doc/FFmpeg Command Line # 前言 FFmpeg多媒体库支持的命令行调用分为三个模块:ffmpeg、ffprobe、ffplay。
其中ffmpeg命令行常用于音视频剪切、转码、滤镜、拼接、混音、截图等;
ffprobe用于检测多媒体流格式;ffplay用于播放视频,包括本地与网络视频。
详情可查阅FFmpeg官方文档:[ffmpeg Documentation](https://ffmpeg.org/documentation.html)
更详细命令行处理可查看博客:[FFmpeg命令行汇总](https://blog.csdn.net/u011686167/article/details/120879467)
# 一、ffmpeg命令行 ## 1、命令行参数介绍 | Print help/info: | Description | |:-------------------|:-------------------------------| | --help topic | show help | | -version | show version | | -formats | show available formats | | -muxers | show available muxers | | -demuxers | show available demuxers | | -devices | show available devices | | -codecs | show available codecs | | -decoders | show available decoders | | -encoders | show available encoders | | -protocols | show available protocols | | -filters | show available filters | | -pix_fmts | show available pixel formats | | -sample_fmts | show available sample formats | | -hwaccels | show available HW acceleration | | Global options: | Description | |:-------------------|:-------------------------------| | -v loglevel | set logging level | | -y | overwrite output files | | -n | never overwrite output files | | -filter_threads | number of filter threads | | -vol volume | change audio volume(256=normal)| | main options: | Description | |:-------------------|:-------------------------------| | -f fmt | force format | | -c codec | codec name | | -codec codec | codec name | | -t duration | duration seconds of audio/video| | -to time_stop | record or transcode stop time | | -ss time_off | set the start time offset | | -frames number | set the number of frames | | -discard | discard | | -disposition | disposition | | Video options: | Description | |:-------------------|:-------------------------------| | -vframes number | set the number of video frames | | -r rate | set frame rate (Hz value) | | -s size | set frame size | | -aspect aspect | set aspect ratio (4:3, 16:9) | | -vn | disable video | | -vcodec codec | force video codec | | -vf filter_graph | set video filters | | -ab bitrate | audio bitrate (please use -b:a)| | -b bitrate | video bitrate (please use -b:v)| | Audio options: | Description | |:-------------------|:-------------------------------| | -aframes number | set the number of audio frames | | -aq quality | set audio quality | | -ar rate | set audio sampling rate (in Hz)| | -ac channels | set number of audio channels | | -an | disable audio | | -acodec codec | force audio codec | | -vol volume | change audio volume(256=normal)| | -af filter_graph | set audio filters | 命令行整体格式:以ffmpeg开头,参数之间用空格隔开,每个参数key以"-"开头,后面跟着参数value,输出文件放在命令行最后。
## 2、音频常见操作 ### 2.1 音频转码 直接转码:
ffmpeg -i input.mp3 output.m4a
指定编码器、采样率、声道数转码:
ffmpeg -i input.mp3 -acodec aac -ac 2 -ar 44100 output.m4a
### 2.2 音频剪切 -ss 10指定从第10秒开始,-t 20代表剪切20秒
ffmpeg -i input.mp3 -ss 10 -t 20 cut.mp3
### 2.3 音频拼接 ffmpeg -i concat:"hello.mp3|world.mp3" -acodec copy -vn concat.mp3
### 2.4 音频混音 使用amix,参数inputs代表输入流个数,duration有longest、shortest、first三种模式,weights设置每条流音量权重占比:
ffmpeg -i hello.mp3 -i world.mp3 -filter_complex amix=inputs=2:duration=first -vn mix.mp3
使用amerge,合并成多声道输出:
ffmpeg -i hello.mp3 -i world.mp3 -filter_complex [0:a][1:a]amerge=inputs=2[aout] -map [aout] merge.mp3
### 2.5 空灵音效 aecho接收4个参数:in_gain (0, 1];out_gain (0, 1];delays (0 - 90000];decays (0 - 1.0]
ffmpeg -i input.mp3 -af aecho=0.8:0.8:1000:0.5 echo.mp3
### 2.6 惊悚音效 tremolo接收2个参数:frequency [0.1, 20000.0];depth (0, 1]
ffmpeg -i input.mp3 -af tremolo=5:0.9 tremolo.mp3
### 2.7 搞笑音效 搞笑音效通过调节音速实现,使用atempo:
ffmpeg -i input.mp3 -filter_complex atempo=0.5 atempo.mp3
### 2.8 静音检测 ffmpeg -i input.mp3 -af silencedetect=noise=0.0001 -f null -
### 2.9 修改音量 ffmpeg -i input.mp3 -af volume=0.5 volume.mp3
### 2.10 抽取音频 从视频抽取音频,直接disable视频流:
ffmpeg -i input.mp4 -vn out.mp3
从视频抽取音频,disable视频流,音频进行转码:
ffmpeg -i input.mp4 -acodec aac -vn out.m4a
从视频抽取音频,如果存在多音轨,可指定某个音轨:
ffmpeg -i input.mp4 -map 0:1 -vn out.mp3
## 3、视频常见操作 ### 3.1 视频剪切 基本剪切,指定起始时间、剪切时长:
ffmpeg -i input.mp4 -ss 10 -t 20 -codec copy cut.mp4
精确剪切,包含多音轨,-map 0代表所有track流进行剪切,-accurate_seek代表精确seek:
ffmpeg -i input.mp4 -ss 10 -accurate_seek -t 20 -map 0 -codec copy cut.mp4
### 3.2 视频转码 使用-vcodec指定视频编码,-acodec指定音频编码,-s 640x480指定视频分辨率,
-b 200k指定码率,-r 20指定帧率,这样达到视频压缩效果:
ffmpeg -i input.mp4 -vcodec libx264 -acodec aac -s 640x480 -b 200k -r 20 transcode.mp4
### 3.3 视频截图 使用-vframes指定截图数量,-ss指定起始时间放在-i前面,这样保证先seek到指定位置再截图。
如果是先-i指定输入文件再-ss,是从时间0开始解码,直到指定时间再截图,这样效率太低:
ffmpeg -ss 10 -i input.mp4 -f image2 -vframes 1 -an screenshot.jpg
### 3.4 图片水印 使用-filter_complex指定位置overlay=x:y,如下所示:
ffmpeg -i input.mp4 -i logo.png -filter_complex overlay=10:20 pic_watermark.mp4
如果要灵活设置左上角、右上角、左下角、右下角位置,可以使用case语句,其中main_w代表视频宽度,
main_h代表视频高度,overlay_w代表水印宽度,overlay_h代表水印高度:
``` public static String obtainOverlay(int offsetX, int offsetY, int location) { switch (location) { case 2: return "overlay='(main_w-overlay_w)-" + offsetX + ":" + offsetY + "'"; case 3: return "overlay='" + offsetX + ":(main_h-overlay_h)-" + offsetY + "'"; case 4: return "overlay='(main_w-overlay_w)-" + offsetX + ":(main_h-overlay_h)-" + offsetY + "'"; case 1: default: return "overlay=" + offsetX + ":" + offsetY; } } public static String[] addWaterMarkImg(String inputPath, String imgPath, int location, int offsetXY, String outputPath) { String overlay = obtainOverlay(offsetXY, offsetXY, location); String waterMarkCmd = "ffmpeg -i %s -i %s -filter_complex %s -preset:v superfast %s"; waterMarkCmd = String.format(waterMarkCmd, inputPath, imgPath, overlay, outputPath); return waterMarkCmd.split(" "); } ``` ### 3.5 GIF水印 使用-ignore_loop 0代表GIF循环显示,其他操作与图片水印一致:
ffmpeg -i input.mp4 -ignore_loop 0 -i logo.gif -filter_complex overlay=10:20 gif_mark.mp4
### 3.6 去除水印 使用delogo命令,然后指定水印位置:
ffmpeg -i input.mp4 -filter_complex delogo=x=10:y=20:w=90:h=30 delogo.mp4
### 3.7 视频拼接 视频拼接分为垂直拼接、水平拼接,还有前后拼接,这里主要介绍垂直与水平拼接,其中使用hstack做水平拼接,vstack做垂直拼接:
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex hstack out.mp4
### 3.8 视频翻转 使用reverse实现视频翻转,但是处理比较耗时:
ffmpeg -i input.mp4 -vf reverse -an output.mp4
### 3.9 视频降噪 使用-nr代表noise reduction,进行视频降噪:
ffmpeg -i in.mp4 -nr 500 out.mp4
### 3.10 视频抽帧 ffmpeg -ss 20 -accurate_seek -t 10 -i input.mp4 -an -r 5 %3d.jpg
### 3.11 播放速度 使用setpts设置视频速度,atempo设置音频速度:
ffmpeg -i in.mp4 -filter_complex [0:v]setpts=%.2f*PTS[v];[0:a]atempo=%.2f[a] -map [v] -map [a] out.mp4
### 3.12 黑白视频 ffmpeg -i in.mp4 -vf lutyuv='u=128:v=128' out.mp4 # 二、ffplay命令行 ffplay主要用于播放视频,也可以播放网络流,示例如下:
ffplay -i beyond.mp4
# 三、ffprobe命令行 ffprobe主要用于检测多媒体信息,包括时长、视频分辨率、帧率、音频采样率、声道数、每个stream流信息等等。
支持显示形式包括:json和xml,例如-print_format json
ffprobe -i input.mp4 -show_streams -show_format -print_format json
如果要显示每帧数据信息,使用-show_frames可以显示pts、packet_size、duration、frame_type等信息:
ffprobe -i input.mp4 -show_frames
如果只要显示视频流,使用-select_streams v。其中v代表video,a代表audio,s代表subtitle。
ffprobe -i input.mp4 -show_frames -select_streams v
--- ### Doc/FFmpeg Compile Shell # 前言 FFmpeg是一个跨平台的多媒体库,也是目前音视频领域应用最广泛的库。包括libavcodec、libavformat、libavutil、
libavdevice、libavfilter、libswscale、libswresample、libpostproc等模块。其中avcodec用于编解码,
avformat用于解封装,avutil是提供工具类,avdevice用于各平台的设备接入,avfilter提供滤镜操作,
swscale提供图像缩放与像素格式转换,swresample提供音频重采样,postproc提供高级处理。
更详细编译脚本可查看博客:[FFmpeg编译脚本分析](https://blog.csdn.net/u011686167/article/details/120390739)
# 一、准备工作 ## 1、下载ffmpeg源码 使用git命令:git clone https://github.com/FFmpeg/FFmpeg.git。 ## 2、下载ndk源码 在Android开发者文档可以下载到ndk源码,[ndk下载链接](https://developer.android.com/ndk/downloads)。 根据实际需求选择对应ndk版本,建议下载ndk-r20b稳定版。mac电脑配置ndk系统环境变量步骤如下: (1)、在命令行输入vim ~/.bash_profile (2)、输入i进行编辑模式 (3)、编写export NDK_PATH=xxx/xxx/android-ndk-r20b (4)、按下esc退出编辑模式,输入:wq保存并退出 # 二、编译ffmpeg源码 ## 1、分析configure结构 在FFmpeg源码目录有个configure配置脚本,使用./configure --help进行查看,可以看到如下结构的编译选项:
| Help options: | Description | |:------------------------|:----------------------------| | --help | print this message | | --list-decoders | show all available decoders | | --list-encoders | show all available encoders | | --list-hwaccels | show all available hardware | | --list-demuxers | show all available demuxers | | --list-muxers | show all available muxers | | --list-parsers | show all available parsers | | --list-protocols | show all available protocols| | --list-filters | show all available filters | | Licensing options: | Description | |:------------------------|:----------------------------| | --enable-gpl | allow use of GPL code | | --enable-version3 | upgrade (L)GPL to version 3 | | --enable-nonfree | allow use of nonfree code | | Configuration options: | Description | |:------------------------|:----------------------------| | --prefix=PREFIX | install in PREFIX | | --disable-static | do not build static libs | | --enable-shared | build shared libraries [no] | | --enable-small | optimize for size | | --disable-all | disable components, libs | | --disable-autodetect | disable detect external libs| | Program options: | Description | |:------------------------|:----------------------------| | --disable-programs | don't build command line | | --disable-ffmpeg | disable ffmpeg build | | --disable-ffplay | disable ffplay build | | --disable-ffprobe | disable ffprobe build | | Component options: | Description | |:------------------------|:----------------------------| | --disable-avdevice | disable libavdevice build | | --disable-avcodec | disable libavcodec build | | --disable-avformat | disable libavformat build | | --disable-swresample | disable libswresample build | | --disable-swscale | disable libswscale build | | --disable-postproc | disable libpostproc build | | --disable-avfilter | disable libavfilter build | | --disable-pthreads | disable pthreads | | --disable-network | disable network support | | Individual component: | Description | |:------------------------|:----------------------------| | --disable-everything | disable all components | | --disable-encoder=NAME | disable encoder NAME | | --enable-encoder=NAME | enable encoder NAME | | --disable-encoders | disable all encoders | | --disable-decoder=NAME | disable decoder NAME | | --enable-decoder=NAME | enable decoder NAME | | --disable-decoders | disable all decoders | | --disable-muxer=NAME | disable muxer NAME | | --enable-muxer=NAME | enable muxer NAME | | --disable-muxers | disable all muxers | | --disable-demuxer=NAME | disable demuxer NAME | | --enable-demuxer=NAME | enable demuxer NAME | | --disable-demuxers | disable all demuxers | | --enable-parser=NAME | enable parser NAME | | --disable-parser=NAME | disable parser NAME | | --disable-parsers | disable all parsers | | --enable-protocol=NAME | enable protocol NAME | | --disable-protocol=NAME | disable protocol NAME | | --disable-protocols | disable all protocols | | --enable-filter=NAME | enable filter NAME | | --disable-filter=NAME | disable filter NAME | | --disable-filters | disable all filters | | External library: | Description | |:------------------------|:-----------------------------------------| | --disable-avfoundation | disable Apple AVFoundation framework | | --enable-jni | enable JNI support [no] | | --enable-libaom | enable AV1 video codec via libaom [no] | | --enable-libass | enable libass subtitles rendering [no] | | --enable-libdav1d | enable AV1 decoding via libdav1d [no] | | --enable-libfdk-aac | enable AAC de/encoding via libfdk-aac | | --enable-libfontconfig | enable libfontconfig [no] | | --enable-libfreetype | enable libfreetype, needed for drawtext | | --enable-libfribidi | enable libfribidi, improves drawtext | | --enable-libmp3lame | enable MP3 encoding via libmp3lame [no] | | --enable-libopencv | enable video filtering via libopencv [no]| | --enable-libopenh264 | enable H.264 encoding via OpenH264 [no] | | --enable-libopus | enable Opus de/encoding via libopus [no] | | --enable-librtmp | enable RTMP[E] support via librtmp [no] | | --enable-libshine | enable fixed-point MP3 encoding | | --enable-libsoxr | enable Include libsoxr resampling [no] | | --enable-libspeex | enable Speex de/encoding via libspeex | | --enable-libtensorflow | enable TensorFlow as a DNN module [no] | | --enable-libvorbis | enable Vorbis en/decoding via libvorbis | | --enable-libvpx | enable VP8 and VP9 de/encoding via libvpx| | --enable-libx264 | enable H.264 encoding via x264 [no] | | --enable-libx265 | enable HEVC encoding via x265 [no] | | --enable-mediacodec | enable Android MediaCodec support [no] | | --enable-opengl | enable OpenGL rendering [no] | | --enable-openssl | enable openssl, needed for https support | | Toolchain options: | Description | |:------------------------|:----------------------------| | --arch=ARCH | select architecture | | --cpu=CPU | select the minimum CPU | | --cross-prefix=PREFIX | use PREFIX for compile tool | | --enable-cross-compile | assume a cross-compiler | | --sysroot=PATH | root of cross-build tree | | --target-os=OS | compiler targets OS | | --toolchain=NAME | set tool according to name | | --nm=NM | use nm tool NM [nm -g] | | --ar=AR | use archive tool AR [ar] | | --as=AS | use assembler AS | | --strip=STRIP | use strip tool STRIP [strip]| | --cc=CC | use C compiler CC [gcc] | | --cxx=CXX | use C compiler CXX [g++] | | --ld=LD | use linker LD | | --host-cc=HOSTCC | use host C compiler HOSTCC | | --host-cflags=HCFLAGS | use HCFLAGS when compiling | | --host-ld=HOSTLD | use host linker HOSTLD | | --host-ldflags=HLDFLAGS | use HLDFLAGS when linking | | --host-extralibs=HLIBS | use libs HLIBS when linking | | --host-os=OS | compiler host OS | | --extra-cflags=ECFLAGS | add ECFLAGS to CFLAGS | | --extra-cxxflags=ECFLAGS| add ECFLAGS to CXXFLAGS | | --extra-ldflags=ELDFLAGS| add ELDFLAGS to LDFLAGS | ## 2、修改so后缀 默认编译出来的so库包括avcodec、avformat、avutil、avdevice、avfilter、swscale、
avresample、swresample、postproc,编译出来so是个软链接,真正so名字后缀带有一长串主版本号与子版本号,
这样的so名字在Adnroid平台无法识别。所以我们需要修改一下,打开该文件并搜索SLIBNAME,找到如下命令行:
``` 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)' ``` ## 3、修改hevc_mvs.c 在linux或者mac平台交叉编译过程中,可能在libavcodec/hevc_mvs.c报错: ``` libavcodec/hevc_mvs.c: In function 'derive_spatial_merge_candidates': libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function) ((y ## v) >> s->ps.sps->log2_min_pu_size)) ^ libavcodec/hevc_mvs.c:204:14: note: in definition of macro 'TAB_MVF' tab_mvf[(y) * min_pu_width + x] ^ libavcodec/hevc_mvs.c:274:16: note: in expansion of macro 'TAB_MVF_PU' (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA)) ^ libavcodec/hevc_mvs.c:368:23: note: in expansion of macro 'AVAILABLE' is_available_b0 = AVAILABLE(cand_up_right, B0) && ^ libavcodec/hevc_mvs.c:208:15: note: each undeclared identifier is reported only once for each function it appears in ((y ## v) >> s->ps.sps->log2_min_pu_size)) ^ libavcodec/hevc_mvs.c:204:14: note: in definition of macro 'TAB_MVF' tab_mvf[(y) * min_pu_width + x] ^ libavcodec/hevc_mvs.c:274:16: note: in expansion of macro 'TAB_MVF_PU' (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA)) ``` 原因是hevc_mvs.c会引用libavutil/timer.h文件(参考:ijkplayer#issues#4093) ``` #if CONFIG_LINUX_PERF #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #endif ``` 在sys/ioctl.h中最终会引用asm/termbits .h文件有#define B0 0000000,导致与hevc_mvs.c的B0命名冲突。
解决方法有2种:把B0改为b0、xB0改为xb0、yB0改为yb0。
或者在脚本添加:export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-linux-perf"
## 4、编译脚本 在ffmpeg源码根目录创建一个shell脚本,比如命名为build_ffmpeg.sh,以mac编译环境为例,
ndk旧版本已经过时,google官方放弃了gcc交叉编译工具链,转而使用clang编译工具链,因为clang编译速度快、效率高。
下面例子是采用ndk新版的clang进行编译(如果是使用虚拟机在linux环境交叉编译FFmpeg,下面的darwin改为linux)。具体如下:
``` /* Detailed source-code truncated for AI context efficiency. */ ``` 按照上面shell脚本分为4段。第一段make clean清除缓存,set -e设置编译出错后马上退出,archbit=xx指定cpu架构是32位还是64位。
第二段if...else...fi用来条件编译不同cpu架构对应字段的值。第三段用export关键字声明宏定义,其中PREFIX是指定输出文件路径。
第四段是一个执行函数,按照ffmpeg的configure规范进行编写。函数里面的enable代表开启,disable代表关闭,也就是对ffmpeg进行剪裁,
根据我们需要的功能进行enable。make命令是执行编译,make install命令是执行安装。最后的build_android是执行函数。
初次执行shell脚本,需要修改脚本权限,使用linux命令:chmod 777 build_ffmpeg.sh。执行脚本只需要一行命令,
即在命令行输入./build_ffmpeg.sh。编译过程中,命令行会不断打印编译日志,等待命令行输出INSTALL xxx关键字代表编译完成。
## 5、编译问题分析 编译过程中,可能会出现这样那样的问题,比如ndk配置不对、脚本语法不对。但不用慌,编译输出窗口会描述出错原因,
在ffbuild/config.log会告诉你问题的具体原因所在,顺着思路一般可以找到问题的答案。
# 三、so库剪裁 ffmpeg强大之处在于支持按需编译,进行弹性剪裁。可以使用--disable-everything关闭所有模块,
可以使用enable/disable来开启关闭某个模块,或者某个编解码器、某个封装器、某个协议。
## 1、encoders与decoders encoder和decoder在libavcodec模块,可以用./configure --list-encoders或者ffmpeg --encoders查看支持的编码器。
同样地,可以用./configure --list-decoders或者ffmpeg --decoders查看支持的解码器。我们可以先--disable-encoders,
--enable-encoder=aac,h264 其中lib开头的表示第三方库。
## 2、muxers与demuxers muxer和demuxer在libavformat模块,可用./configure --list-muxers或者ffmpeg --muxers查看支持的封装器。
同样地,可用./configure --list-demuxers或者ffmpeg --demuxers查看支持的解封装器。先--disable-muxers,再--enable-muxer=mp3
## 3、protocols protocol也是在libavformat模块中,./configure --list-protocols或者ffmpeg --protocols查看支持的协议,
## 4、parsers parser在libavfilter模块中,提供各种filter,比如音频:amix、atempo,视频:rotate、hflip,
我们可以根据需求--enable-parser来开启,可使用./configure --list-parsers查看具体列表。
# 四、编译过程分析 编译过程包括:预编译、编译、汇编、链接。详细可以查阅书籍<程序员的自我修养> ## 1、预编译 预编译处理(.c/.cpp->.i),对源文件的伪指令进行处理。 伪指令包括:宏定义(#define)、条件编译指令(#ifdef #elseif #endif)、头文件包含指令(#include) ## 2、编译 编译(.i->.s),对经过预编译处理文件进行语法分析,编译为汇编文件。 ## 3、汇编 汇编(.i->.o),把汇编代码翻译为机器码,也就是二进制的目标文件。 ## 4、链接 链接(.o->.so/.a/.lib),把所有目标文件链接成动态库、静态库文件。 ## 5、FFmpeg的makefile分析 makefile主要发生在汇编阶段,把所有依赖的目标文件添加进去。以FFmpeg的AVFilter模块makefile为例(有省略): ``` /* Detailed source-code truncated for AI context efficiency. */ ``` --- ### Doc/JNI Develop Practice # 前言 JNI是Java本地接口,定义Android从应用代码(以Java或kotlin编程语言编写)到本地代码(C/C++编写)交互编译成字节码的一种方式。
文档[Java Native Interface Specification](https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html)
### NDK编译脚本 [Android.mk与CMake编译](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/NDK_compile_shell.md) ### 相关介绍文章如下: [NDK编译脚本](https://blog.csdn.net/u011686167/article/details/106458899)
[JNI开发规范](https://blog.csdn.net/u011686167/article/details/81784979)
[JNI全面介绍与最佳实践](https://blog.csdn.net/u011686167/article/details/124132719)
--- ### Doc/Multimedia Knowledge # 前言 音视频多媒体涉及语音信号处理、数字图像处理、信息论、封装协议、编解码、渲染、网络传输、视频特效、音频特效等等。在特定场景,
还会结合AI、机器学习ML、计算机视觉CV、自然语言理解NLP。比如AI智能编码,抽取视频帧用计算机视觉做人脸识别,用NLP做语音理解。
### 1、音视频基本概念 [基本概念](https://blog.csdn.net/u011686167/article/details/108314078) ### 2、视频封装格式 [视频封装](https://blog.csdn.net/u011686167/article/details/108426708) ### 3、音频封装格式 [音频封装](https://blog.csdn.net/u011686167/article/details/108565360) ### 4、音视频编码 [编码器介绍](https://blog.csdn.net/u011686167/article/details/108590762) ### 5、音视频解码 [解码解码器介绍](https://blog.csdn.net/u011686167/article/details/108743947) ### 6、音效(均衡器、混响、重低音) [基本音效](https://blog.csdn.net/u011686167/article/details/109191399) ### 7、杜比音效AC3与AC4 [杜比音效](https://blog.csdn.net/u011686167/article/details/113576628) ### 8、杜比视觉Dolby-Vision与HDR [杜比视觉](https://blog.csdn.net/u011686167/article/details/113624068) ### 9、Matroska封装格式 [Matroska封装格式上](https://blog.csdn.net/u011686167/article/details/113791392) [Matroska封装格式下](https://blog.csdn.net/u011686167/article/details/113796271) ### 10、新一代视频AV1编码器 [AV1编码器](https://blog.csdn.net/u011686167/article/details/113806322) ### 11、Android图像渲染框架 [Android图像渲染](https://blog.csdn.net/u011686167/article/details/118035545) --- ### Doc/Multimedia Protocol ## 多媒体协议与书籍 多媒体开发涉及非常多的多媒体协议,在这里整理一些常用的多媒体协议与多媒体书籍,
欢迎大家补充其他相关协议与书籍,共同维护良好的开源社区。
### 多媒体协议 常见的流媒体传输协议包括:RTP、SRTP、RTMP、RTCP、RTSP,流媒体应用协议有HLS、DASH,
WebRTC网络传输协议有SDP、ICE、NAT、STUN、TURN等,常用视频编码协议有H264,
常用的视频封装格式有mp4,关于C语言标准有C11、C17等,详细列表如下: | protocol | download | password | |:----------------|:------------------------------------------------|:----------------| | H264 | https://pan.baidu.com/s/1I1Sfw0y8g_XQmylzWBnV6A | vm5i | | HLS | https://pan.baidu.com/s/1cDl8FdJfioviWasApObVcg | w5vh | | RTP | https://pan.baidu.com/s/13K1ZHXytq8_k-TT1Nu7P7g | eg3s | | SRTP | https://pan.baidu.com/s/1fw3deX0GC3AYtzMt7RosWg | v87w | | SDP | https://pan.baidu.com/s/10mCBI93awj4FkSOFy3_hbQ | ks6g | | RTCP | https://pan.baidu.com/s/1Q5ZQS5Mh_D3g9JfNQ7J9sg | c046 | | RTMP | https://pan.baidu.com/s/1Vm4mi2KOdaelLcx9t426Mw | c1wu | | RTSP | https://pan.baidu.com/s/1mxEwMaXjL4ml3jixmdr2lw | n6hx | | RTP(WebRTC) | https://pan.baidu.com/s/1saXyutLmuBiiCRbzkmzyyQ | 8gvc | | HTTP2 | https://pan.baidu.com/s/1a2LE3vkjhBpGfLALTk0YRA | fwxk | | STUN | https://pan.baidu.com/s/1o6G80R6880rT4My6fVXtEg | 933a | | ICE | https://pan.baidu.com/s/1AEJxzf1Nflg98u35Eg3Yyg | 1u1w | | NAT | https://pan.baidu.com/s/1Kcup8UZhnF15lqgSIkNAWw | w3oz | | C11 | https://pan.baidu.com/s/1AH7-cT6jPpgkN-fcsxZiqQ | p0ay | | C++20 | https://pan.baidu.com/s/1Alsm2Ve8hiMb_UhYMnGPYg | 79ej | | MP4 | https://pan.baidu.com/s/13WrU60CYPCRshPrmLOTtKA | fa0f | | DASH | https://pan.baidu.com/s/1-38Erd4a9mtEUKzD3GMaig | ctz7 | | DASH(ISO) | https://pan.baidu.com/s/1UnxkaPeKVIsmddaYIrADdw | buav | | H265(ITU-T) | https://pan.baidu.com/s/1SypB6m9cQbB-IYyUy4EvFg | n8tz | ### 多媒体书籍 音频开发书籍包括:音乐理论、音频信号处理与编码、DSP语音降噪、3D声音环绕,
视频开发书籍包括:数字图像与视频处理、视频编码全角度详解,
渲染方面是OpenGL,硬件加速指令有neon,详细列表如下: | book | download | password | |:----------------|:------------------------------------------------|:----------------| | OpenGL | https://pan.baidu.com/s/1j8_UD217vNeV6SWi5G3ySw | snvo | | Theory of Music | https://pan.baidu.com/s/1pDpChcrhqOUBL8Dl9xq8UQ | b38b | | neon guide | https://pan.baidu.com/s/1mOTnhIyulNASN90IAzHzdA | f2bw | | CodingForNeon | https://pan.baidu.com/s/1R-Lf94AnHk_hUwZQyLuxSQ | 5iyj | | HybridReverb | https://pan.baidu.com/s/19LV36iTBKPGFDQZkoCosiw | jjlq | | 数字图像与视频处理 | https://pan.baidu.com/s/1oBAtwAFU0pfnhf_cQUs6dg | pi17 | | 视频编码全角度详解 | https://pan.baidu.com/s/1WBdEFF4MWcZDnheeR4XvCA | vyfo | | 音频信号处理与编码 | https://pan.baidu.com/s/1qwSrRrcs1eipph9QLxrEXg | q9xc | | DSP语音降噪 | https://pan.baidu.com/s/1z2i6vXf9xn_Uq2_T6TE8rA | h7a1 | | 3D声音环绕 | https://pan.baidu.com/s/1URAnDx_eNXJhsQUSUVLKDA | u8n0 | | 音视频开发进阶指南 | / | / | | HEVC算法与架构 | https://pan.baidu.com/s/1l8IwSACejk4ZZe10Dh6OdQ | kgfg | | A Tour of C++ | https://pan.baidu.com/s/16mg_1aafhcM68-NYHT6XhQ | ycvm | | C++标准库 | https://pan.baidu.com/s/1QPXbjnYArNmwZY4TCZ5aWA | 3xyv | | C程序语言 | https://pan.baidu.com/s/132cTecL7RArkx2eaGGZOmw | wzrj | | C++程序语言 | https://pan.baidu.com/s/1joKa0qt_xl57QdRRL7Ud9g | br5q | --- ### Doc/Multimedia Work ### 音视频工作方向概要 音视频工作方向包括:直播、短视频、流媒体传输、视频播放器、音乐播放器、音视频算法、
流媒体后端、音视频编辑、图像处理(个人概括,具体方向不限于此)。
--- ### Doc/NDK Compile Shell # 前言 Android NDK以前默认使用Android.mk与Application.mk进行构建,但是在Android Studio2.2之后推荐使用CMake进行编译。
CMake是跨平台编译工具,全称为cross platform make,内建c、c++、java自动相依性分析功能。NDK通过工具链支持CMake,
工具链文件是用于自定义交叉编译工具链的CMake文件。用于NDK的工具链位于/build/cmake/android.toolchain.cmake,
关于CMake更多详情请参考官网:[cmake官网](https://cmake.org/documentation/)。下面对比下Android.mk与CMakeLists.txt的语法。
更详细脚本分析可查看博客:[NDK编译脚本分析](https://blog.csdn.net/u011686167/article/details/106458899)
# 一、Android.mk语法 以动态库编译hello模块为例,完整脚本如下: ``` WORKING_DIR := $(call my-dir) LOCAL_PATH := $(WORKING_DIR) include $(CLEAR_VARS) LOCAL_ARM_MODE := arm LOCAL_MODULE := libffmpeg LOCAL_SRC_FILES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE).so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/include include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_ARM_MODE := arm #模块名称 LOCAL_MODULE := hello #源文件 LOCAL_SRC_FILES := hello.c #头文件路径 LOCAL_C_INCLUDES := $(LOCAL_PATH) #系统库依赖 LOCAL_LDLIBS := -llog -lz -lm -landroid #第三方动态库 LOCAL_SHARED_LIBRARIES := libffmpeg #以动态库形式编译 include $(BUILD_SHARED_LIBRARY) ``` ## 1、LOCAL_MODULE 声明模块名称,例如这里编译出来的动态库名称为libhello.so。 ## 2、LOCAL_SRC_FILES 声明源文件列表,文件之间用空格分开,需要换行时使用'\'换行符。 ## 3、LOCAL_C_INCLUDES 声明头文件路径,例如$(LOCAL_PATH)/xxx ## 4、LOCAL_CPP_EXTENSION 指定C++源文件除.cpp以外的文件扩展名,例如这样LOCAL_CPP_EXTENSION := .cpp .cxx .cc ## 5、LOCAL_CPP_FEATURES 指定依赖c++的某些功能,例如RTTI(运行时类型信息): LOCAL_CPP_FEATURES := rtti 使用c++异常检测: LOCAL_CPP_FEATURES := exceptions ## 6、LOCAL_CFLAGS 在编译c和c++源文件时编译系统要传递的编译器标记,即指定额外的宏定义或编译选项。 LOCAL_CFLAGS += -I ## 7、LOCAL_STATIC_LIBRARIES 共享静态库,作为第三方库被引用 LOCAL_STATIC_LIBRARIES := libavcodec libavutil libavformat libavfilter ## 8、LOCAL_SHARED_LIBRARIES 共享动态库,与共享静态库一样作为第三方库被引用 LOCAL_SHARED_LIBRARIES := libffmpeg ## 9、LOCAL_LDLIBS 额外链接器,一般为系统库,使用-l来引用 LOCAL_LDLIBS := -lz -lm ## 10、 LOCAL_ARM_MODE ndk默认使用thumb模式来生成目标二进制文件,每条指令为16位宽。也可以指定为ARM模式,来生成32位ARM的目标文件:
LOCAL_ARM_MODE := arm ## 11、LOCAL_ARM_NEON 用于开启NEON指令加速,仅对armeabi-v7a平台有效。为模块开启NEON: LOCAL_ARM_NEON := true 为单独源文件开启NEON: LOCAL_SRC_FILES := hello.c.neon ## 12、TARGET_ARCH 用于指向CPU架构,包括x86、x86_64、armeabi-v7a、 arm64-v8a ## 13、TARGET_PLATFORM 目标平台,对应Android API级别号,例如Android5.0系统镜像对应Android API级别21:android-21 ## 14、打印信息 可用warning、debug、info、error级别来打印信息,如果是打印error信息,会终止编译。以warning为例: $(warning 'This is a test') ## 15、if条件判断 采用ifeq关键字,然后左右变量放在括号体内,用逗号分隔: ``` ifeq($(TARGET_ABI), arm64-v8a) $(debug 'This is arm64-v8a') endif ``` # 二、Application.mk语法 Android.mk依赖Application.mk文件进行编译,一般Application.mk脚本如下所示:
``` APP_STL := c++_static APP_DEBUG := false APP_OPTIM := release APP_CPPFLAGS := -frtti APP_PLATFORM := android-16 APP_ABI := armeabi-v7a arm64-v8a ``` ## 1、APP_ABI 与Android.mk的TARGET_ABI对应,包括CPU架构有:x86、x86_64、armeabi-v7a、arm64-v8a,支持所有平台这样表示:
APP_ABI := all ## 2、APP_BUILD_SCRIPT 指向编译脚本的路径,一般Android.mk和Application.mk都位于jni目录,默认指向jni/Android.mk路径,如果是其他路径,
需要使用此变量来指定绝对路径: APP_BUILD_SCRIPT := /xx/xx/Android.mk ## 3、APP_OPTIM 编译优化选项,调试模式为debug,发布模式为release。在调试模式下,会保留symbol符号表;在发布模式下,会开启优化,去掉symbol符号表。 ## 4、APP_PLATFORM 指定编译平台,面向于Android API级别,对应gradle声明的minSdkVersion。如果不声明,默认为ndk支持的最低API版本 ## 5、APP_STL 声明使用c++的标准库,默认为system STL。其他选项包括c++_static、c++_shared和none # 三、CMakeLists.txt语法 以编译hello模块以及依赖ffmpeg模块为例: ``` cmake_minimum_required(VERSION 3.4.1) #添加动态库,包含源文件路径 add_library( hello SHARED src/main/jni/hello.c) #添加第三方动态库 add_library( ffmpeg SHARED IMPORTED ) #指定第三方库路径 set_target_properties( ffmpeg PROPERTIES IMPORTED_LOCATION ../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libffmpeg.so ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") #指定头文件路径 include_directories(src/main/cpp) if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a") include_directories(src/main/cpp/include/armeabi-v7a) message("This is armeabi-v7a") elseif(${CMAKE_ANDROID_ARCH_ABI} MATCHES "arm64-v8a") include_directories(src/main/cpp/include/arm64-v8a) message("This is arm64-v8a") endif() #查找系统库 find_library( # Sets the name of the path variable. log-lib log ) #链接目标库 target_link_libraries( hello ffmpeg ${log-lib} ) ``` ## 1、add_library 传递三个参数,第一个参数是模块名称,第二个参数是SHARED或者STATIC。如果是源文件模块,第三个参数是源文件列表;
如果是第三方库,第三个参数是IMPORTED。 ## 2、set_target_properties 用于指定第三方库路径,IMPORT_LOCATION一般是指向src/main/cpp目录 ## 3、include_directories 用于指定头文件路径,头文件路径可以有多个 ## 4、find_library 用于查找系统库,比如Android系统的log日志库 ## 5、target_link_libraries 链接目标库,把依赖库都链接到目标库中 ## 6、if条件判断 与Android.mk稍有差异,CMake采用if...MATCHES形式,例如: if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a") ...... endif() ## 7、打印日志 与Android.mk不同的是,CMake采用message函数来打印日志,括号体传入msg内容 message("hello, cmake") ## 8、命令行参数 命令行参数前面统一加上-D,常用的参数: * -DANRDOID_ABI :android的ABI架构平台 * -DANDROID_NDK :ndk路径 * -DANDROID_ARM_MODE :arm模式/thumb模式 * -DANDROID_ARM_NEON :是否开启arm neon加速,针对armeabi-v7a平台 * -DANDROID_TOOLCHAIN :编译工具链 * -DANDROID_NATIVE_API_LEVEL :与ANDROID_PLATFORM相同,对应minSdkVersion * -DCMAKE_BUILD_TYPE :编译类型,debug或release * -DCMAKE_MAKE_PROGRAM :编译程序 * -DCMAKE_TOOLCHAIN_FILE :编译文件 ## 9、命令行编译 以cmake作为关键字,后面带着指定参数,示例如下: ``` cmake \ -DANDROID_ABI=armeabi-v7a \ -DANDROID_NDK=${HOME}/Android/Sdk/ndk-bundle \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.6.3155560/bin/ninja \ -DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake \ -DANDROID_NATIVE_API_LEVEL=23 \ -DANDROID_TOOLCHAIN=clang ``` # 四、ndk编译配置 ## 1、Android.mk方式配置 在gradle的defaultConfig配置ndk: ``` defaultConfig { ...... ndk { moduleName "hello" abiFilters "armeabi-v7a", "arm64-v8a" } } ``` 然后配置jni源文件路径: ``` sourceSets { main { jniLibs.srcDir 'src/main/libs' // Enable to use libs jni.srcDirs 'src/main/jni' // Enable the automatic ndk-build } } ``` 另外配置Android.mk文件绝对路径: ``` externalNativeBuild { ndkBuild { "src/main/jni/Android.mk" } } ``` ## 2、CMake方式配置 前两步与Android.mk方式一样,配置脚本路径稍有差异: ``` externalNativeBuild { cmake { path "CMakeLists.txt" } } ``` 另外在defaultConfig设置cppFlags: ``` externalNativeBuild { cmake { cppFlags "" } } ``` # 五、ndk编译过程 ## 1、ndk-build编译 在命令行输入ndk-build后,会根据声明所支持的平台依次编译。首先是armeabi-v7a平台架构,把hello.c源文件编译成hello
目标文件,然后链接成libhello.so动态库,最终安装到libs/armeabi-v7a目录下。 ## 2、cmake在Gradle中编译 编译arm64-v8a平台架构的hello模块。首先把hello.c源文件编译成hello.c.o目标文件,然后链接成libhello.so动态库。
生成的debug模式动态库在/build/intermediates/cmake/debug/obj/arm64-v8a目录下。 --- ### Doc/Player Framework # 前言 ijkplayer是一款跨平台的播放器,支持Android与iOS端,核心部分基于ffmpeg,
支持Android的mediacodec硬解与iOS的videotoolbox硬解,视频图像采用OpenGL进行渲染。
许多主流播放器都使用ijkplayer作为播放方案。
## 1、ijkplayer的API详细介绍 [API介绍](https://blog.csdn.net/u011686167/article/details/121317933) ## 2、ijkplayer的时序图与状态图分析 [时序图与状态图](https://blog.csdn.net/u011686167/article/details/121322757) ## 3、ijkplayer自定义协议播放加密视频 [自定义协议](https://blog.csdn.net/u011686167/article/details/121341461) ## 4、ijkplayer音频解码播放架构分析 [音频解码播放](https://blog.csdn.net/u011686167/article/details/121411150) ## 5、ijkplayer视频解码播放架构分析 [视频解码播放](https://blog.csdn.net/u011686167/article/details/121432094) ## 6、ijkplayer播放器架构从原型到升级 [播放器整体架构](https://blog.csdn.net/u011686167/article/details/121440104) ## 7、ijkplayer音视频同步策略分析 [音视频同步](https://blog.csdn.net/u011686167/article/details/121446345) --- ### README # FFmpegAndroid ### [FFmpeg官方文档](https://ffmpeg.org/) ### [FFmpeg编译流程](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/FFmpeg_compile_shell.md) ### [FFmpeg常用命令行](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/FFmpeg_command_line.md) ### [FFmpeg源码分析](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/FFmpeg_sourcecode.md) ### [JNI与NDK开发](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/JNI_develop_practice.md) ### [音视频知识汇总](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/multimedia_knowledge.md) ### [ijkplayer播放器架构](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/player_framework.md) ---------------------------------------------------------------------------------------------------- 常见的流媒体传输协议包括:RTP、RTMP、RTCP、RTSP,流媒体应用协议有HLS、DASH,
WebRTC设计传输协议有SDP、ICE、NAT、STUN等,常用视频编码协议有H264、HEVC、VVC,
常用的视频封装格式有mp4,关于C/C++语言标准有C11、C20++等,书籍包括音视频编解码等。
详细列表可以查阅:[多媒体协议与书籍](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/multimedia_protocol.md) 音视频工作方向包括:直播、短视频、流媒体传输、视频播放器、音乐播放器、音视频算法、
流媒体后端、音视频编辑、图像处理(个人概括,具体方向不限于此)。
详情可查阅:[音视频工作方向](https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/multimedia_work.md) ### 音视频基础知识: ### 音视频进阶成长: ### 音视频开源库: ### Joining the group to learn FFmpeg: ---