美文网首页
iOS FFmpeg集成支持AV1解码器dav1d并将AV1转为

iOS FFmpeg集成支持AV1解码器dav1d并将AV1转为

作者: Macanzy | 来源:发表于2019-12-27 11:52 被阅读0次

    1. AV1解码器

    • AV1是由AOM联盟制定的一个开源、免版权费的视频编码格式,目标是解决H265昂贵的专利费用和复杂的专利授权问题并成为新一代领先的免版权费的编码标准。
    • 当前开源的解码器有libaom和dav1d,ffmpeg在4.0的版本中已经支持了使用libaom库来实现AV1格式的编码和解码。
    • 在4.2版本中实现了使用dav1d库进行解码。

    2. 编译dav1d

    2.1 下载源码

    git clone https://code.videolan.org/videolan/dav1d.git

    2.2 编译环境配置

    Meson (0.47 or higher)
    Ninja
    nasm (2.13.02 or higher)

    brew install meson
    brew install ninja
    brew install nasm
    

    2.3 编译

    1.cd到下载下来的dav1d文件下;
    2.执行meson build --buildtype release

    [root@17:09:56]dav1d$meson build --buildtype release
    The Meson build system
    Version: 0.52.0
    Source dir: /Users/macos/Desktop/av1test/dav1d
    Build dir: /Users/macos/Desktop/av1test/dav1d/build
    Build type: native build
    Project name: dav1d
    Project version: 0.5.2
    C compiler for the host machine: cc (clang 11.0.0 "Apple clang version 11.0.0 (clang-1100.0.33.12)")
    C linker for the host machine: APPLE ld 520
    Host machine cpu family: x86_64
    Host machine cpu: x86_64
    Run-time dependency threads found: YES 
    Checking for function "clock_gettime" : YES 
    Check usable header "stdatomic.h" : YES 
    Check usable header "unistd.h" : YES 
    Check usable header "io.h" : NO 
    Checking for function "getopt_long" : YES 
    Checking for function "posix_memalign" : YES 
    Compiler for C supports arguments -fvisibility=hidden: YES 
    Compiler for C supports arguments -Wundef: YES 
    Compiler for C supports arguments -Werror=vla: YES 
    Compiler for C supports arguments -Wno-maybe-uninitialized: NO 
    Compiler for C supports arguments -Wno-missing-field-initializers: YES 
    Compiler for C supports arguments -Wno-unused-parameter: YES 
    Compiler for C supports arguments -Werror=missing-prototypes: YES 
    Compiler for C supports arguments -Wshorten-64-to-32: YES 
    Compiler for C supports arguments -fomit-frame-pointer: YES 
    Compiler for C supports arguments -ffast-math: YES 
    Compiler for C supports arguments -fno-stack-check: YES 
    Compiler for C supports arguments -mpreferred-stack-boundary=5: NO 
    Compiler for C supports arguments -mstack-alignment=32: YES 
    Configuring config.h using configuration
    Configuring config.asm using configuration
    Program nasm found: YES (/usr/local/bin/nasm)
    Configuring version.h using configuration
    Program doxygen found: NO
    Configuring cli_config.h using configuration
    Library m found: YES
    Program objcopy found: NO
    Build targets in project: 15
    Found ninja-1.9.0 at /usr/local/bin/ninja
    

    3.执行ninja -C build

    [root@17:10:03]dav1d$ninja -C build
    ninja: Entering directory `build'
    [118/118] Linking target tools/dav1d.
    
    编译默认是生成动态库
    • 生成的动态库在dav1d/build/src,dylib文件就是我们需要的,@@文件夹中是一些临时文件;
    [root@17:18:53]src$ls
    25a6634@@dav1d@sha             25a6634@@dav1d_entrypoint@sta
    25a6634@@dav1d_bitdepth_16@sta libdav1d.4.dylib
    25a6634@@dav1d_bitdepth_8@sta  libdav1d.dylib
    
    • 输出头文件目录在dav1d/build/include/dav1d,但只包含version.h文件,需要把version.h拷贝到dav1d/include/dav1d。目录结构是这样的:
    [root@17:27:44]dav1d$ls
    common.h     dav1d.h      meson.build  version.h
    data.h       headers.h    picture.h    version.h.in
    

    3. 编译FFmpeg增加dav1d解码器支持

    3.1 编写dav1d.pc

    • FFmpeg的configure脚本会执行一个简单的程序来检测dav1d库是否存在以及版本是否满足要求,编写dav1d.pc如下:
    #替换成你自己的路径
    prefix=/Users/macos/Desktop/av1test/ffmpeg-4.2.1/dav1d
    exec_prefix=${prefix}
    libdir=${exec_prefix}/lib
    includedir=${prefix}/include
    
    Name:dav1d 
    Description: dav1d
    Version: 1.0.1
    Requires:
    Conflicts:
    Libs: -L${libdir} -ldav1d
    Libs.private: 
    Cflags: -I${includedir}
    
    • libdirincludedir指定了dav1d的头文件和库的路径
    • dav1d.pc放到/usr/lib/pkgconfig下,新版的macOS系统需要修改权限,点击查看权限修改方法

    3.2 编译dav1d

    • 创建cross_file.txt文件内容如下,后面的paths就是dav1d的头文件和静态库生成的路径。这样编出来的静态库是arm64架构的,x86_64模拟器架构还不支持。
    # This is a cross compilation file from OSX Yosemite to iPhone
    # Apple keeps changing the location and names of files so
    # these might not work for you. Use the googels and xcrun.
    
    [binaries]
    c = 'clang'
    cpp = 'clang++'
    ar = 'ar'
    strip = 'strip'
    
    [properties]
    sys_root = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer'
    
    c_args = ['-arch', 'arm64', '-mios-version-min=8.0', '-fembed-bitcode', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
    cpp_args = ['-arch', 'arm64', '-mios-version-min=8.0', '-fembed-bitcode', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
    c_link_args = ['-arch', 'arm64', '-mios-version-min=8.0', '-fembed-bitcode', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
    cpp_link_args = ['-arch', 'arm64', '-mios-version-min=8.0', '-fembed-bitcode', '-isysroot', '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk']
    
    has_function_printf = true
    has_function_hfkerhisadf = false
    
    [host_machine]
    system = 'darwin'
    cpu_family = 'aarch64'
    cpu = 'arm'
    endian = 'little'
    
    #后面dav1d的头文件和静态库生成的路径
    [paths]
    prefix = '/Users/macos/dav1d_lib'
    libdir = 'lib'
    bindir = 'bin'
    
    • 然后直接修改源码中的meson.build文件增加该设置:
    project('dav1d', ['c'],
        version: '0.4.0',
        default_options: ['c_std=c99',
                          'warning_level=2',
                          'buildtype=release',
                          'b_ndebug=if-release',
                          'default_library=static',
                          'b_bitcode=true',
                          'b_asneeded=false'],
        meson_version: '>= 0.47.0')
    
    • 最后执行
    meson build  --cross-file cross_file.txt
    ninja -C build
    cd build
    meson install
    
    • 此时/dav1d/build/src文件夹下会生成libdav1d.a静态库,这个静态库就是我们需要用的
    [root@10:33:49]src$ls
    25a6634@@dav1d@sha             25a6634@@dav1d_entrypoint@sta
    25a6634@@dav1d@sta             libdav1d.4.dylib
    25a6634@@dav1d_bitdepth_16@sta libdav1d.a
    25a6634@@dav1d_bitdepth_8@sta  libdav1d.dylib
    

    3.3 下载FFmpeg

    https://github.com/FFmpeg/FFmpeg
    

    3.4 编译FFmpeg

    • cd到下载好的FFmpeg文件夹下,运行下面命令,然后是漫长的等待。
    ./configure --prefix=../buildout --enable-shared --disable-static --enable-libdav1d
    # 编译后检查一下config.h中DAV1D是否配置成功了,如`#define CONFIG_LIBDAV1D 1`。
    make
    make install
    

    3.5 集成到FFmpeg

    • 下载FFmpeg iOS构建脚本
    https://github.com/kewlbear/FFmpeg-iOS-build-script.git
    
    • 添加DAV1D相关,为防止添加错误,我把我改完后的脚本粘贴如下
    #!/bin/sh
    
    # directories
    FF_VERSION="4.2.1"
    #FF_VERSION="snapshot-git"
    if [[ $FFMPEG_VERSION != "" ]]; then
      FF_VERSION=$FFMPEG_VERSION
    fi
    SOURCE="ffmpeg-$FF_VERSION"
    FAT="FFmpeg-iOS"
    
    SCRATCH="scratch"
    # must be an absolute path
    THIN=`pwd`/"thin"
    
    # absolute path to x264 library
    #X264=`pwd`/fat-x264
    
    #FDK_AAC=`pwd`/../fdk-aac-build-script-for-iOS/fdk-aac-ios
    
    DAV1D=`pwd`/dav1d
    
    CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \
                     --disable-doc --enable-pic"
    
    if [ "$X264" ]
    then
        CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-libx264"
    fi
    
    if [ "$FDK_AAC" ]
    then
        CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libfdk-aac --enable-nonfree"
    fi
    
    if [ "$DAV1D" ]
    then
        CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libdav1d"
    fi
    
    # avresample
    #CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-avresample"
    
    ARCHS="arm64"
    
    COMPILE="y"
    LIPO="y"
    
    DEPLOYMENT_TARGET="8.0"
    
    if [ "$*" ]
    then
        if [ "$*" = "lipo" ]
        then
            # skip compile
            COMPILE=
        else
            ARCHS="$*"
            if [ $# -eq 1 ]
            then
                # skip lipo
                LIPO=
            fi
        fi
    fi
    
    if [ "$COMPILE" ]
    then
        if [ ! `which yasm` ]
        then
            echo 'Yasm not found'
            if [ ! `which brew` ]
            then
                echo 'Homebrew not found. Trying to install...'
                            ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \
                    || exit 1
            fi
            echo 'Trying to install Yasm...'
            brew install yasm || exit 1
        fi
        if [ ! `which gas-preprocessor.pl` ]
        then
            echo 'gas-preprocessor.pl not found. Trying to install...'
            (curl -L https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl \
                -o /usr/local/bin/gas-preprocessor.pl \
                && chmod +x /usr/local/bin/gas-preprocessor.pl) \
                || exit 1
        fi
    
        if [ ! -r $SOURCE ]
        then
            echo 'FFmpeg source not found. Trying to download...'
            curl http://www.ffmpeg.org/releases/$SOURCE.tar.bz2 | tar xj \
                || exit 1
        fi
    
        CWD=`pwd`
        for ARCH in $ARCHS
        do
            echo "building $ARCH..."
            mkdir -p "$SCRATCH/$ARCH"
            cd "$SCRATCH/$ARCH"
    
            CFLAGS="-arch $ARCH"
            if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
            then
                PLATFORM="iPhoneSimulator"
                CFLAGS="$CFLAGS -mios-simulator-version-min=$DEPLOYMENT_TARGET"
            else
                PLATFORM="iPhoneOS"
                CFLAGS="$CFLAGS -mios-version-min=$DEPLOYMENT_TARGET -fembed-bitcode"
                if [ "$ARCH" = "arm64" ]
                then
                    EXPORT="GASPP_FIX_XCODE5=1"
                fi
            fi
    
            XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'`
            CC="xcrun -sdk $XCRUN_SDK clang"
    
            # force "configure" to use "gas-preprocessor.pl" (FFmpeg 3.3)
            if [ "$ARCH" = "arm64" ]
            then
                AS="gas-preprocessor.pl -arch aarch64 -- $CC"
            else
                AS="gas-preprocessor.pl -- $CC"
            fi
    
            CXXFLAGS="$CFLAGS"
            LDFLAGS="$CFLAGS"
            if [ "$X264" ]
            then
                CFLAGS="$CFLAGS -I$X264/include"
                LDFLAGS="$LDFLAGS -L$X264/lib"
            fi
            if [ "$FDK_AAC" ]
            then
                CFLAGS="$CFLAGS -I$FDK_AAC/include"
                LDFLAGS="$LDFLAGS -L$FDK_AAC/lib"
            fi
            if [ "$DAV1D" ]
            then
                CFLAGS="$CFLAGS -I$DAV1D/include"
                LDFLAGS="$LDFLAGS -L$DAV1D/lib"
            fi
            
    
            TMPDIR=${TMPDIR/%\/} $CWD/$SOURCE/configure \
                --target-os=darwin \
                --arch=$ARCH \
                --cc="$CC" \
                --as="$AS" \
                $CONFIGURE_FLAGS \
                --extra-cflags="$CFLAGS" \
                --extra-ldflags="$LDFLAGS" \
                --prefix="$THIN/$ARCH" \
            || exit 1
    
            make -j3 install $EXPORT || exit 1
            cd $CWD
        done
    fi
    
    if [ "$LIPO" ]
    then
        echo "building fat binaries..."
        mkdir -p $FAT/lib
        set - $ARCHS
        CWD=`pwd`
        cd $THIN/$1/lib
        for LIB in *.a
        do
            cd $CWD
            echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2
            lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1
        done
    
        cd $CWD
        cp -rf $THIN/$1/include $FAT
    fi
    
    echo Done
    
    
    • 在dav1d文件夹中新建lib文件夹,然后将/dav1d/build/src文件夹下的libdav1d.a拷贝到lib文件夹下面
    • 将ffmpeg-4.2.1文件中的config.h剪切出来,运行FFmpeg iOS构建脚本,然后漫长的等待。。。
    sh build-ffmpeg.sh 
    
    • 运行完成之后会生成FFmpeg-iOS文件夹,将其和上面生成的dav1d的头文件、静态库拖入工程中,结构如下:
      工程结构

    4. iOS 下 集成 FFmpeg

    • 在Link Binary With Libraries 里添加
    libz.tbd
    libbz2.tbd
    libiconv.tbd
    CoreMedia.framework
    VideoToolbox.framework
    AVFoundation.framework
    
    库结构
    • 设置 Header Search Paths 和 Library Search Paths 路径


      Header路径
    Library路径
    • 后面就是解决各种编译报错,这些度娘都可以搜到。
    最后附上带有转码进度的av1转成mp4的demo

    相关文章

      网友评论

          本文标题:iOS FFmpeg集成支持AV1解码器dav1d并将AV1转为

          本文链接:https://www.haomeiwen.com/subject/ixrloctx.html