# 基于Ubuntu源码编译ffmpeg ## 编译SDL2(可选) ```shell https://github.com/libsdl-org/SDL/releases/tag/release-2.30.8 # 下载源码 cd sdl/source/folder ./configure --prefix=/usr/local make sudo make install ``` ## 安装ffmpeg依赖 1. 安装包管理工具 aptitude aptitude 与 apt-get一样,是 Debian 系中功能极其强大的包管理工具。 与 apt-get 不同的是,aptitude 在处理依赖问题上更佳一些,当 aptitude 在删除一个包时,会同时删除本身所依赖的包。 ```shell sudo apt install aptitude ``` 2. 安装 yasm、nasm yasm、nasm 是两个汇编器,编译 FFmpeg 需要用到。 安装命令: ```shell sudo aptitude install yasm nasm ``` 3. 其他依赖 FFmpeg 的安装依赖许多库(如,音频编码库,音频解码库,视频编解码库等),这里不介绍每个库的具体作用,按照命令安装即可。 ```shell sudo apt-get install libgmp3-dev sudo apt install pkg-config sudo apt install gnutls-bin sudo aptitude install libaom-dev sudo aptitude install libass-dev sudo aptitude install libbluray-dev sudo aptitude install libfdk-aac-dev sudo aptitude install libmp3lame-dev sudo aptitude install libopencore-amrnb-dev sudo aptitude install libopencore-amrwb-dev sudo aptitude install libopenmpt-dev sudo aptitude install libopus-dev sudo aptitude install libshine-dev sudo aptitude install libsnappy-dev sudo aptitude install libsoxr-dev sudo aptitude install libspeex-dev sudo aptitude install libtheora-dev sudo aptitude install libtwolame-dev sudo aptitude install libvo-amrwbenc-dev sudo aptitude install llibvpx-dev sudo aptitude install libwavpack-dev sudo aptitude install libwebp-dev sudo aptitude install libx264-dev sudo aptitude install libx265-dev sudo aptitude install libxvidcore-dev sudo aptitude install liblzma-dev ``` ## 编译ffmpeg 1. 从官网下载源码 2. 进入根目录编译 ```shell ./configure --enable-shared --enable-gpl --enable-sdl2 --enable-libx264 --enable-libx265 --enable-nvdec --enable-nvenc --enable-cuda --enable-cuvid # 其中 --enable-gpl --enable-libx264 --enable-libx265 必不可少 --enable-sdl2 是ffmpeg播放器需要的 # 由于需要硬件英伟达显卡加速编解码 --enable-nvdec --enable-nvenc --enable-cuda --enable-cuvid # --enable-shared 使make install时,将动态库也正确安装,否则运行ffmpeg时,会显示缺少动态库 make sudo make install # 安装完后,确保安装目录,确保已经配置好动态库搜索的路径, ``` 如果需要硬件英伟达显卡加速编解码,需要安装相关依赖 ```shell sudo apt install libdssialsacompat-dev git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers.git cd nv-codec-headers make sudo make install # ./ffmpeg -hwaccels 查看支持哪些硬件编码 ``` ### 编译ffmeg arm64安卓版本 在源码目录下创建buildarm64.sh,内容如下 ```shell #!/bin/bash export NDK=~/android/android-ndk-r20b #这里配置先你的 NDK 路径 TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64 # 编译到安卓上,尽可能小一些(--enable-small),只是用来解码,也就取消编译封装编码相关的 function build_android { ./configure \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \ --enable-neon \ --enable-gpl \ --disable-sdl2 \ --disable-postproc \ --disable-debug \ --enable-small \ --enable-static \ --enable-shared \ --disable-doc \ --enable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-avdevice \ --disable-doc \ --disable-symver \ --prefix=$PREFIX \ --cross-prefix=$CROSS_PREFIX \ --target-os=android \ --arch=$ARCH \ --cpu=$CPU \ --cc=$CC \ --cxx=$CXX \ --enable-cross-compile \ --sysroot=$SYSROOT \ --extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" make clean make -j16 make install echo "============================ build android arm64-v8a success ==========================" } #arm64-v8a ARCH=arm64 CPU=armv8-a API=21 CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++ SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android- PREFIX=$(pwd)/android/$CPU OPTIMIZE_CFLAGS="-march=$CPU" build_android ``` ```shell chomd +x buildarm64.sh ./buildarm64.sh # 编译好后,对应的源文件和库文件会安装到./android/armv-v8a中 ``` ### 在rk3568上交叉编译ffmpeg 使用瑞芯微上使用其硬件加速编码和解码 创建一个目录 ~/dev 之后所有的操作在这个目录下进行 1. 编译mpp ```shell git clone -b jellyfin-mpp --depth=1 https://github.com/nyanmisaka/mpp.git rkmpp mkdir rkmpp_build pushd rkmpp_build # 在cmake中指定交叉工具链gcc和g++ 改成自己的目录 # 注意在不要安装到本机的系统目录,最好新建一个目录,之后把所有的依赖安装到这个目录 cmake \ -DCMAKE_INSTALL_PREFIX=~/dev/rkffmpeg \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_TEST=OFF \ -DCMAKE_C_COMPILER=/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-gcc \ -DCMAKE_CXX_COMPILER=/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-g++ \ .. make -j $(nproc) make install ``` 2. build rga 创建一个在~/dev 目录下创建cross_file.txt, 将工具链换成自己的,以及安装目录 ```txt [host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'armv8-a' endian = 'little' [binaries] c = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-gcc' cpp = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-g++' ar = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/ar' strip = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/strip' [properties] c_args = ['-fpermissive'] cpp_args = ['-fpermissive'] [paths] prefix = '~/dev/rkffmpeg' libdir = 'lib' ``` ```shell git clone -b jellyfin-rga --depth=1 https://github.com/nyanmisaka/rk-mirrors.git rkrga # 不需要cd 进行 meson setup rkrga rkrga_build \ --prefix=/usr \ --libdir=lib \ --buildtype=release \ --default-library=shared \ -Dcpp_args=-fpermissive \ -Dlibdrm=false \ -cross-file=./cross_file.txt \ -Dlibrga_demo=false meson configure rkrga_build ninja -C rkrga_build install ``` 3. 编译drm 首先去官网下载源码包https://dri.freedesktop.org/libdrm/ 下载完成后,开始解压缩,解压缩完成后,进入源码目录,首先创建install和build目录,然后创建cross_file.txt文件,文件内容如下 ```txt [host_machine] system = 'linux' cpu_family = 'aarch64' cpu = 'armv8-a' endian = 'little' [binaries] c = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-gcc' cpp = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux-g++' ar = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/ar' strip = '/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/strip' [properties] c_args = ['-fpermissive'] cpp_args = ['-fpermissive'] [paths] prefix = '~/dev/rkffmpeg' libdir = 'lib' ``` 然后直接执行指令ninja && ninja install即可使用 4. 编译ffmpeg 上面的依赖编译并安装好后,正式开始编译ffmpeg,添加rk芯片的mpp来加速编解码 在~/dev 下载ffmpeg 进入到源码目录 创建build.sh 内容如下 ```shell #!/bin/bash export TOOLCHAIN=/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/bin/aarch64-linux export GCC=$TOOLCHAIN-gcc export GXX=$TOOLCHAIN-g++ # 编译到开发版,尽可能小一些(--enable-small),取消了一些其它硬件加速和封装 # 更换 cc cxx ar strip 以及--extra-cflags --extra-ldflags function build_android { ./configure \ --sysroot=./ \ --extra-cflags="-I~/dev/rkffmpeg/include" \ --extra-ldflags="-L~/dev/rkffmpeg/lib" \ --prefix=$PREFIX \ --enable-cross-compile \ --arch=arm64 \ --cpu=armv8-a \ ar=/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/ar \ strip=/home/user/baidu/buildroot-cross/gcc_for_rk356x_buildroot/aarch64-rockchip-linux-gnu/bin/strip \ --cc=$GCC \ --cxx=$GXX \ --enable-libdrm \ --disable-nvenc \ --disable-nvdec \ --disable-vdpau \ --disable-vaapi \ --enable-rkmpp \ --enable-rkrga \ --enable-version3 \ --disable-programs \ --disable-avdevice \ --disable-muxers \ --disable-filters \ --enable-neon \ --enable-gpl \ --disable-sdl2 \ --disable-postproc \ --disable-debug \ --enable-small \ --enable-static \ --enable-shared \ --disable-doc \ --enable-ffmpeg \ --disable-ffprobe \ --disable-avdevice \ --disable-doc \ --disable-symver echo "============================ build android arm64-v8a success ==========================" } #arm64-v8a PREFIX=$(pwd)/rk-arm64 build_android ``` 编译 ```shell chmod +x build.sh make clean make -j16 make install ``` 最后把编译好的ffmpeg 放到~/dev/rkffmpeg 中 一并打包移植到开发版上 ## 硬编码 ```c++ // 与软编码相比,没有很多额外的配置 // 仅仅是在查找编码器时按名称查找 hevc_nvenc ,其余和软编码一样 auto pCodec = avcodec_find_encoder_by_name("hevc_nvenc"); // ... // 其次就是注意软编码出来的每一帧数据 前面都会带有SEI增强帧,关键帧后面才是I帧或者P帧 auto naluHeader = (pkt->data[4] & 0x7E) >> 1; // 前四个字节是0x00 00 00 01 分隔符 if (naluHeader == 39) { // SEI auto header = getNextSplit(pkt->data, pkt->size); // 往后找,跳过这个SEI if (header == nullptr) return 0; naluHeader = ((*header) & 0x7E) >> 1; // cout << "naluHeader: " << naluHeader << endl; } ```