FFmpeg のコンパイルと統合

Javaは一度書いたらどこでも実行できますが、Cは異なり、プラットフォームごとに違いがあるため、一度だけ書くことはできず、各プラットフォームのコンパイルも異なります。たとえば、Android の ndk ツールチェーン、プラットフォームごとにライブラリが異なります。

この記事では、主に win プラットフォームでの ffmpeg のコンパイルと統合について説明します。

1. クロスコンパイル

クロスコンパイル: クロスコンパイルとは、プログラムのコンパイル環境が実際の動作環境と一致しないこと、つまり、あるプラットフォームで実行可能なコードが別のプラットフォームで生成されることを意味します。

なぜクロスコンパイルが必要なのか、実際、その理由はすでに述べたとおりです。異なるプラットフォーム間の違いにより、命令セットが異なります。たとえば、上記の勝利は Intel 命令セットですが、ほぼ 100% Android携帯電話のライブラリはarm命令セットなので、win上でコンパイルしたライブラリをそのままAndroidで使用することは絶対に不可能なので、クロスコンパイルが必要です。

クロスコンパイルは主に Android ndk ツールキットに基づいています

以下は、一般的に使用されるコンポーネントの一般的なリストです。

  • ARMクロスコンパイラ

  • ビルドツール

  • Java ネイティブ インターフェイス ヘッダー ファイル

  • Cライブラリ

  • 数学ライブラリ

  • 最小限の C++ ライブラリ

  • ZLib 圧縮ライブラリ

  • POSIX スレッド

  • Android ロギング ライブラリ

  • Android ネイティブ アプリケーション API

  • OpenGL ES ライブラリ

  • OpenSL ES ライブラリ

Android が提供する NDK とディレクトリの構造を見てみましょう。

  • ndk-build: このシェル スクリプトは Android NDK ビルド システムの開始点であり、通常、プロジェクト内でこのコマンドを実行するだけで、対応するダイナミック リンク ライブラリをコンパイルできます。

  • ndk-gdb: このシェル スクリプトを使用すると、GUN デバッガーでネイティブ コードをデバッグでき、Java コードのようなネイティブ コードをデバッグするように AS で設定できます。

  • ndk-stack: このシェル スクリプトは、ネイティブ コードがクラッシュしたときにグループがスタック情報を分析するのに役立ちます。

  • build: このディレクトリには、NDK ビルド システムのすべてのモジュールが含まれています。

  • プラットフォーム: このディレクトリには、さまざまな Android ターゲット バージョンをサポートするヘッダー ファイルとライブラリ ファイルが含まれています。NDK ビルド システムは、特定の構成に従って、指定されたプラットフォームでヘッダー ファイルとライブラリ ファイルを参照します。

  • ツールチェーン: このディレクトリには、NDK で現在サポートされているさまざまなプラットフォーム (ARM、X86、MIPS) 用のクロスコンパイラーが含まれています。現在は ARM の方が一般的に使用されています。ビルド システムは、特定の構成に応じて異なるクロス コンパイラーを選択します。

ツールチェーンは通常、次のようなツールを提供します。

  • CC: C ソース ファイルをコンパイルおよび処理してアセンブリ ファイルを生成するコンパイラ。

  • AS: アセンブリ ファイルからターゲット ファイルを生成します (アセンブリ ファイルは命令ニーモニックを使用し、AS はそれをマシン コードに変換します)。

  • AR: ライブラリ操作に使用される Packer は、このツールを通じてライブラリからオブジェクト コード モジュールを削除または追加できます。

  • LD: リンカー。以前に生成されたオブジェクト コードにアドレス空間を割り当て、複数のオブジェクト ファイルをライブラリまたは実行可能ファイルにリンクします。

  • GDB:動作中のプログラムのコードデバッグができるデバッグツール。

  • ストリップ: 最終的に生成された実行可能ファイルまたはライブラリ ファイルを入力として取得し、その中のソース コードを削除します。

  • NM: 静的ライブラリ ファイル内のシンボル テーブルを表示します。

  • Objdump: 静的ライブラリまたは動的ライブラリのメソッド シグネチャを表示します。

ただし、バージョンの異なる ndk ではツールが異なります。一部の新しい ndk には ar、strip などが含まれていない可能性があります。これらのツールは、別の名前が付けられているか、新しい ndk の他の場所に配置されている可能性があります (例: 21.1.6352462 (win) を見つけました)ストリップと ar が含まれていますが、バージョン 24.0.8215888 には関連するライブラリがなく、これらのバージョンには nm ライブラリもありません。ffmpeg をコンパイルすると、nm が見つからないというメッセージが表示されます。幸いなことに、nm は必要ありません。パニック、関連するツールが見つからない場合は、パス設定に問題があるか、現在のバージョンの ndk にそのようなツールが存在しないか、名前が変更されている可能性があります。何を確認するための情報を見つける必要があります。新しいバージョンのツールが呼び出されるか、古いバージョンの ndk をダウンロードするだけです

 [学習アドレス]: FFmpeg/WebRTC/RTMP/NDK/Android オーディオおよびビデオ ストリーミング メディアの高度な開発https://link.zhihu.com/?target=https%3A//ke.qq.com/course/3202131%3FflowToken % 3D1042495 [記事の特典]: より多くの音声およびビデオ学習教材パッケージ、大昌面接の質問、技術ビデオ、学習ロードマップを無料で入手できます。教材には (C/C++、Linux、FFmpeg webRTC rtmp hls rtsp ffplay srs など) が含まれます。必要です1079654574 をクリックしてグループに参加し、受け取ることができます~

2.FFmpegをコンパイルする

優れた C++ 開発者は、C++ コンパイルについて一定の理解を持っている必要があります。クロスコンパイルについては前の記事で紹介しましたので、今度は ffmpeg をコンパイルする方法を学びましょう

ffmpeg 公式 Web サイトでソース コードをダウンロードします。

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

自分のニーズに応じて、必要なバージョンを切り替えてください。

ffmpeg のコンパイルは、実際には非常に簡単です。素晴らしい ffmpeg 開発者が、configure というスクリプトを提供しているためです。実際、私たちが作成したコンパイル スクリプトは、コンパイル ツールの場所を指定してから、configure スクリプトを呼び出してコンパイルするというものです。

win11 で ffmpeg をコンパイルしています。msys2 ツールをダウンロードして、関連する環境を構成する必要があります。環境を構成するには、管理者として msys2 を実行する必要があります。そうしないと、例外が報告されます。

pacman -S make yasm diffutils pkg-config #在msys2上安装必要软件

次に、ffmpeg フォルダーにスクリプト ファイルを構築し、次の内容を貼り付けます。

 #!/bin/sh
​
NDK_PATH=/c/workspace/android_sdk/ndk/21.1.6352462
​
BUILD_PLATFORM=windows-x86_64
​
API=21
​
ANDROID_ARMV5_CFLAGS="-march=armv5te"
ANDROID_ARMV7_CFLAGS="-march=armv7-a -mfloat-abi=softfp -mfpu=neon"
ANDROID_ARMV8_CFLAGS="-march=armv8-a"
ANDROID_X86_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
ANDROID_X86_64_CFLAGS="-march=x86-64 -msse4.2 -mpopcnt -m64 -mtune=intel"
​
​
# params($1:arch,$2:arch_abi,$3:compiler,$4:cross_prefix,$5:cflags)
build_bin() {
​
    echo "-------------------star build $2-------------------------"
​
    ARCH=$1         # arm arm64 x86 x86_64
    # CPU
    ANDROID_ARCH_ABI=$2     # armeabi armeabi-v7a x86 mips
​
    COMPILER=$3
​
    PREFIX=$(pwd)/dist/${ANDROID_ARCH_ABI}/
​
    TOOLCHAIN=${NDK_PATH}/toolchains/llvm/prebuilt/${BUILD_PLATFORM}
​
    CC=${TOOLCHAIN}/bin/${COMPILER}-clang
​
    CXX=${TOOLCHAIN}/bin/${COMPILER}-clang++
​
    SYSROOT=${TOOLCHAIN}/sysroot
​
    CROSS_PREFIX=${TOOLCHAIN}/bin/$4-
​
    CFLAGS=$5
​
    echo "pwd==$(pwd)"
    echo "ARCH==${ARCH}"
    echo "PREFIX==${PREFIX}"
    echo "SYSROOT=${SYSROOT}"
    echo "CFLAGS=${CFLAGS}"
    echo "CC==${CC}"
    echo "CROSS_PREFIX=${CROSS_PREFIX}"
​
    sh ./configure \
        --prefix=${PREFIX} \
        --enable-neon \
        --enable-hwaccels \
        --enable-gpl \
        --disable-postproc \
        --disable-debug \
        --enable-small \
        --enable-jni \
        --enable-mediacodec \
        --enable-decoder=h264_mediacodec \
        --disable-static \
        --enable-shared \
        --disable-doc \
        --enable-ffmpeg \
        --disable-ffplay \
        --disable-ffprobe \
        --disable-avdevice \
        --disable-doc \
        --disable-symver \
        --target-os=android \
        --arch=${ARCH} \
        --cc=$CC \
        --sysroot=$SYSROOT \
        --enable-cross-compile \
        --cross-prefix=${CROSS_PREFIX} \
        --extra-cflags="-Os -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $CFLAGS" \
        --extra-cxxflags="-D__thumb__ -fexceptions -frtti" \
        --extra-ldflags="-L${SYSROOT}/usr/lib" \
​
    make clean
    make -j8
    make install
​
​
    echo "-------------------$2 build end-------------------------"
}
​
​
# build armeabi
# build_bin arm armeabi arm-linux-androideabi arm-linux-androideabi "$ANDROID_ARMV5_CFLAGS"
​
#build armeabi-v7a
#build_bin arm armeabi-v7a armv7a-linux-androideabi${API} arm-linux-androideabi "$ANDROID_ARMV7_CFLAGS"
​
#build arm64-v8a
 build_bin arm64 arm64-v8a aarch64-linux-android${API} aarch64-linux-android "$ANDROID_ARMV8_CFLAGS"
​
#build x86
# build_bin x86 x86 i686-linux-android${API} i686-linux-android "$ANDROID_X86_CFLAGS"
​
#build x86_64
# build_bin x86_64 x86_64 x86_64-linux-android${API} x86_64-linux-android "$ANDROID_X86_64_CFLAGS"

関連説明:

  • CC: C コンパイラのパスを指定します。

  • CROSS_PREFIX: クロスコンパイル ツール ファイル パスの統一プレフィックスを指定します。各ツールの最終的なファイル パスは、クロスプレフィックス + ツール名です。たとえば、上記のスクリプトのプレフィックスが TOOLCHAIN/bin/arm-linux-androideabi- の場合、ar ツールのパスは TOOLCHAIN/bin/arm になります。 -linux-androideabi-ar

  • target-os: ターゲット プラットフォームを指定します。ffmpeg は各プラットフォームで実行でき、各プラットフォームの一部の構成は異なるため、指定する必要があります。

さらに、コンパイル スクリプトには多くの有効化と無効化があります。これらは構成スクリプト内のコンパイル オプションです。たとえば、--enable-shared はダイナミック ライブラリをコンパイルすることを意味するため、上記のスクリプトは最終的に so ファイルを生成します。ファイルの代わりに。

これらのコンパイル オプションは、configure --help を使用して見つけることができます。

これらの有効なコンパイル オプションであっても、CC のようなオプションであっても、これらはすべて設定スクリプトを設定しています。テキスト モードで設定ファイルを開くと、次の内容が表示されます。

--cc=CC                  use C compiler CC [$cc_default]
--target-os=OS           compiler targets OS [$target_os]
--enable-shared          build shared libraries [no]

コンパイル スクリプトの実行後、コンパイルが成功すると、lib フォルダーに関連する so ライブラリが表示されます。

3.FFmpegの統合

まず、cmakelist がどのように書かれているかを見てください。

# 设置最小使用版本
cmake_minimum_required(VERSION 3.18.1)
​
project("demo")
​
include_directories(include)
​
# 添加本地so库 native-lib:这个是声明引用so库的名称 SHARED:表示共享so库文件
# 构建so库的源文件
add_library(
        demo
        SHARED
        native-lib.cpp
)
​
set(SO_DIR ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
​
# 使用系统ndk 提供的库,如 log库
# log-lib 这个指定的是在NDK库中每个类型的库会存放一个特定的位置,而log库存放
# 在log-lib中
# log 指定使用log库
find_library(
        log-lib
        log
)
​
message("c_CMAKE_SOURCE_DIR:" ${CMAKE_SOURCE_DIR} )
​
# 加载avcodec-57库
add_library( avcodec
        SHARED
        IMPORTED)
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavcodec.so)
​
add_library( avutil
        SHARED
        IMPORTED)
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavutil.so)
​
add_library( swresample
        SHARED
        IMPORTED)
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswresample.so)
​
add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavfilter.so)
​
add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libavformat.so)
​
add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${SO_DIR}/libswscale.so)
#----------------------end-----------------------
​
# 如果你本地的库(native-lib)想要调用log库的方法,
# 那么就需要配置这个属性,意思是把NDK库关联到本地库。
# 第一个参数表示本地的库 native-lib 要调用到log库的方法,即要被关联的库名称,log-lib 要关联的库名称
target_link_libraries(
        demo
        #ffmpeg------start----------
        avcodec
        avutil
        swresample
        avfilter
        avformat
        swscale
        #ffmpeg------end------------
        ${log-lib}
)

実はこれらの書き方は非常に簡単で、間違えたら書き間違えたということになりますので、そこだけ注意してください。すべてのコードは私の github にアップロードされました

元のリンク: FFmpeg のコンパイルと統合 - Nuggets

おすすめ

転載: blog.csdn.net/irainsa/article/details/130773521