FFmpeg Makefile to CMakeLists.txt

2021年5月23日 · 1034 字 · 3 分钟

想了解学习下 FFmpeg 的源码,并希望可以自己编译调试。

官网介绍的开发环境中 IDE 是 Eclipse, 本人不熟悉。自己常用的是 CLion/CMake。但是 FFmpeg 是基于 Makefile 文件构建的, CLion 好像不支持,(已经支持了,我也是写这篇日志的时候才知道,详见官网说明,感觉还没开始就已经结束了,汗~)。

CLion 虽支持 Makefile,你只是调试 ffmpeg, ffplay, ffprobe 等自带的 application 应该没有多大问题。如果你想自己写一个新的 application,那你就得修改 configure 脚本或者 Makefile 文件了。 那我还是选择用 CMake 吧。

编译说明

编译脚本

build.sh

#/bin/bash
#
# 下载,编译 nasm, libx264, libav*, ffmpeg 
# 将 ffmpeg 目录下 Makefile “翻译” 成 CMakeLists.txt
# 使用 cmake, clang/clang++ 编译 ffmpeg

function mkdir_env () {
    CUR_DIR=`pwd`
    mkdir -p ffmpeg && cd ffmpeg && mkdir -p sources bin build
    cd sources && SOURCES=`pwd`
    cd ../bin && BIN=`pwd`
    cd ../build && BUILD=`pwd`
    echo $SOURCES $BIN $BUILD $CUR_DIR
    # PATH="$BIN:$PATH"
}

function dl_dep () {
    apt-get update -qq && apt-get -y install \
    autoconf \
    automake \
    build-essential \
    cmake \
    git-core \
    libass-dev \
    libfreetype6-dev \
    libgnutls28-dev \
    libtool \
    libvorbis-dev \
    meson \
    ninja-build \
    pkg-config \
    texinfo \
    wget \
    yasm \
    zlib1g-dev
}

function build_nasm () {
    cd $SOURCES && \
    wget https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.bz2 && \
    tar xjvf nasm-2.15.05.tar.bz2 && \
    cd nasm-2.15.05 && \
    ./autogen.sh && \
    PATH="$BIN:$PATH" ./configure --prefix="$BUILD" --bindir="$BIN" && \
    make -j 8 && \
    make install
}

function build_libx264 () {
    cd $SOURCES && \
    git -C x264 pull 2> /dev/null || git clone --depth 1 https://code.videolan.org/videolan/x264.git && \
    cd x264 && \
    PATH="$BIN:$PATH" PKG_CONFIG_PATH="$BUILD/lib/pkgconfig" ./configure --prefix="$BUILD" --bindir="$BIN" --enable-static --enable-pic && \
    PATH="$BIN:$PATH" make -j8 && \
    make install
}

function build_ffmpeg () {
    cd $SOURCES && \
    wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \
    tar xjvf ffmpeg-snapshot.tar.bz2
    
    cd $SOURCES/ffmpeg && \
    PATH="$BIN:$PATH" PKG_CONFIG_PATH="$BUILD/lib/pkgconfig" ./configure \
    --prefix="$BUILD" \
    --pkg-config-flags="--static" \
    --extra-cflags="-I$BUILD/include" \
    --extra-ldflags="-L$BUILD/lib" \
    --extra-libs="-lpthread -lm" \
    --ld="g++" \
    --bindir="$BIN" \
    --disable-all \
    --disable-autodetect \
    --disable-w32threads \
    --disable-os2threads \
    --disable-alsa \
    --disable-appkit \
    --disable-avfoundation \
    --disable-bzlib \
    --disable-coreimage \
    --disable-iconv \
    --disable-libxcb \
    --disable-libxcb-shm \
    --disable-libxcb-xfixes \
    --disable-libxcb-shape \
    --disable-lzma \
    --disable-sndio \
    --disable-schannel \
    --disable-sdl2 \
    --disable-securetransport \
    --disable-xlib \
    --disable-zlib \
    --disable-amf \
    --disable-audiotoolbox \
    --disable-cuda-llvm \
    --disable-cuvid \
    --disable-d3d11va \
    --disable-dxva2 \
    --disable-ffnvcodec \
    --disable-nvdec \
    --disable-nvenc \
    --disable-v4l2-m2m \
    --disable-vaapi \
    --disable-vdpau \
    --disable-videotoolbox \
    --enable-ffmpeg \
    --enable-small \
    --enable-avcodec \
    --enable-avformat \
    --enable-avfilter \
    --enable-swresample \
    --enable-swscale \
    --enable-decoder=h264 \
    --enable-encoder=rawvideo,libx264 \
    --enable-parser=h264 \
    --enable-protocol=file \
    --enable-demuxer=mov \
    --enable-muxer=rawvideo,mp4 \
    --enable-filter=scale \
    --enable-nonfree \
    --enable-gpl \
    --enable-libx264
    
    make --just-print > make.log && \
    PATH="$BIN:$PATH" make -j 8 && \
    make install
}

function test_ffmpeg () {
    ls -lh $BIN
    wget https://file-examples-com.github.io/uploads/2017/04/file_example_MP4_1280_10MG.mp4 -O $BIN/in.mp4
    $BIN/ffmpeg -i $BIN/in.mp4 -vf scale=iw*.5:ih*.5 -vcodec h264 -acodec copy $BIN/out.mp4 -y
}

function get_cmakelists () {
    cp $CUR_DIR/CMakeLists.txt $SOURCES/ffmpeg/
    cd $SOURCES/ffmpeg
    arr=(libavfilter libavformat libavcodec libswresample libswscale libavutil fftools)
    for tag in "${arr[@]}"; do
        echo "=======================================> $tag"
        temp=`cat make.log | grep "printf \"CC\|printf \"X86" \
        | grep -o "\-c \-o.*.c\|\" .*; nasm" \
        | grep -o "\.o.*\|\" .*; nasm" \
        | grep -o "\ .*" \
        | grep -o ".*\.c\|.*\.o" \
        | grep $tag \
        | tr '\n' ' '`
        echo $temp
        sed -i "s|<$tag>|$temp|g" CMakeLists.txt
    done
}

function build_c_ffmpeg () {
    apt install -y clang  # 用 clang 编译链接
    mkdir -p $SOURCES/ffmpeg/build && cd $SOURCES/ffmpeg/build
    cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=/usr/bin/clang ..
    make -j 8
}

function test_c_ffmpeg () {
    $SOURCES/ffmpeg/build/ffmpeg -i $BIN/in.mp4 -vf scale=iw*.5:ih*.5 -vcodec h264 -acodec copy $SOURCES/ffmpeg/build/out.mp4 -y
}

mkdir_env
dl_dep
build_nasm
build_libx264
build_ffmpeg
test_ffmpeg

get_cmakelists
build_c_ffmpeg
test_c_ffmpeg

上述脚本中涉及的 CMakeLists.txt 内容如下

cmake_minimum_required(VERSION 3.10)
project(ffmpeg)

set(CMAKE_CXX_STANDARD 14)

add_definitions(-D_ISOC99_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_POSIX_C_SOURCE=200112
        -D_XOPEN_SOURCE=600 -DPIC -DHAVE_AV_CONFIG_H -DBUILDING_avfilter -DBUILDING_avformat)
        
set(CMAKE_C_FLAGS "-std=c11 -fomit-frame-pointer -fPIC  -g \
                    -Wdeclaration-after-statement -Wall -Wdisabled-optimization -Wpointer-arith -Wredundant-decls \
                    -Wwrite-strings -Wtype-limits -Wundef -Wmissing-prototypes -Wno-pointer-to-int-cast \
                    -Wstrict-prototypes -Wempty-body -Wno-parentheses -Wno-switch -Wno-format-zero-length \
                    -Wno-pointer-sign -Wno-unused-const-variable -Wno-char-subscripts \
                    -O0 -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=format-security \
                    -Werror=implicit-function-declaration -Werror=missing-prototypes -Werror=return-type \
                    -Werror=vla -Wformat -fdiagnostics-color=auto")

SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--fatal-warnings -fPIC \
                            -Wl,-z,noexecstack \
                            -Wl,-z,now \
                            -Wl,-z,relro \
                            -Wl,-z,defs \
                            -Wl, -rdynamic")


include_directories(
        ${CMAKE_SOURCE_DIR}                       # for ./config.h
        ${CMAKE_SOURCE_DIR}/../../build/include   # for libx264
)

add_library(avfilter STATIC <libavfilter>)
add_library(avformat STATIC <libavformat>)
add_library(avcodec STATIC <libavcodec>)
add_library(swresample STATIC <libswresample>)
add_library(swscale STATIC <libswscale>)
add_library(avutil STATIC <libavutil>)


add_executable(ffmpeg <fftools>)

target_link_libraries(ffmpeg dl pthread dl m
        ${CMAKE_SOURCE_DIR}/../../build/lib/libx264.a
        avfilter
        avformat
        avcodec
        swresample
        swscale
        avutil
        pthread m dl m m m pthread m)

编译步骤

# 启动 docker 容器, 进入 bash
docker run -it --name temp ubuntu:18.04 /bin/bash
# 从宿主机复制文件到容器
docker cp build.sh temp:/
docker cp CMakeLists.txt temp:/
# 容器中执行
bash build.sh