32blogby StudioMitsu
Archive13 min read

FFmpegのlibavutilとは?機能・使い方・サンプルコードを徹底解説

FFmpegの基盤ライブラリlibavutilを解説。メモリ管理・時間計算・エラーハンドリングの実装例からインストール・よくあるエラーの対処法まで網羅。

FFmpeg を活用して開発を行う際に欠かせないのが、libavutil というライブラリだ。本記事では、libavutil の機能、具体的なユースケース、サンプルコードを交えながら徹底解説する。

この記事でわかること

  • libavutil の基本的な役割と機能
  • どんな場面で libavutil が役立つのか
  • 主要な関数の使い方と実装例
  • libavutil のインストールとセットアップ方法
  • よくあるエラーとその解決方法

libavutil を理解すれば、FFmpeg を活用した開発がよりスムーズになり、高度なメディア処理を実装できるようになる。


libavutil とは?

libavutil の概要

libavutil は FFmpeg のライブラリの一つであり、マルチメディア処理に必要な汎用的なユーティリティ関数を提供する役割を持っている。FFmpeg の他のライブラリと組み合わせて使用され、エンコーディングやデコーディングを補助する重要な機能を担っている。

libavutil の主な特徴:

  • メモリ管理やバッファ操作を簡単にする
  • 数学演算や時間計算をサポート
  • 画像・音声のフォーマット管理や変換を提供
  • ハッシュ計算(MD5, SHA1, HMAC など)を効率的に実行
  • エラーハンドリングやロギング機能を内蔵

他の FFmpeg ライブラリとの違い

FFmpeg には複数のライブラリが存在するが、それぞれの役割は異なる。

ライブラリ名主な役割
libavcodec音声・動画のエンコード / デコード処理
libavformatメディアフォーマットの解析と処理
libavfilter映像・音声のフィルタリング処理
libavutilユーティリティ関数を提供(メモリ管理、数学演算、エラーハンドリングなど)
libswscale映像のリサイズや色空間変換
libswresample音声のリサンプリングやフォーマット変換

libavutil は、これらのライブラリを円滑に動作させるための「基盤」として機能しており、単独ではあまり利用されないが、FFmpeg 開発において不可欠な存在だ。

libavutil のユースケース

libavutil は、以下のような場面で役立つ。

1. メモリ管理を最適化したい

FFmpeg を用いた開発では、大量のデータを扱うためメモリ管理が重要になる。libavutil には、動的メモリ管理のための関数が用意されており、安全で効率的なリソース管理が可能だ。

  • av_malloc() / av_free() で安全にメモリ確保・解放
  • av_buffer_create() でメモリバッファを管理

2. フレームレートやタイムスタンプの計算を簡単にしたい

動画処理では、異なるフレームレートや時間単位を扱うことが多い。av_rescale_q() を使うことで、時間の換算を簡単に行える。

3. 画像や音声のフォーマットを処理したい

  • av_get_pix_fmt_name() でピクセルフォーマットの取得
  • av_samples_get_buffer_size() で音声バッファのサイズ計算

4. エラーハンドリングを簡潔にしたい

FFmpeg の関数はエラーコードを返すことが多い。av_strerror() を使用すると、エラーコードをわかりやすいメッセージに変換できる。

5. ハッシュ計算やチェックサムを求めたい

libavutil には、MD5 や SHA1 などのハッシュ計算を行う関数が含まれている。ファイルの整合性チェックに役立つ。


libavutil の主要な機能

1. メモリ管理

libavutil には、安全なメモリ管理のための関数が揃っている。

主な関数:

  • av_malloc(size_t size) — メモリ確保
  • av_free(void *ptr) — メモリ解放
  • av_buffer_create(uint8_t *data, size_t size, void (*free)(void *opaque, uint8_t *data), void *opaque, int flags) — バッファ管理

使用例:

c
#include <libavutil/mem.h>
#include <stdio.h>

int main() {
    int *data = (int *) av_malloc(sizeof(int) * 10);
    if (!data) {
        printf("メモリ確保に失敗しました\n");
        return 1;
    }
    data[0] = 42;
    printf("data[0] = %d\n", data[0]);
    av_free(data);
    return 0;
}

av_malloc() を使ってメモリを確保し、使用後に av_free() で解放している。通常の malloc / free と同様の使い方だが、FFmpeg の内部アライメント要件に対応しているため、FFmpeg のデータ構造と組み合わせる場合は av_malloc を使うのが安全だ。

2. 数学演算と時間計算

libavutil には、数値計算や時間の変換を簡単にするための関数が用意されている。

主な関数:

  • av_rescale(int64_t a, int64_t b, int64_t c) — 値のスケーリング(a * b / c)
  • av_rescale_q(int64_t a, AVRational bq, AVRational cq) — 時間スケールの変換
  • av_log2(unsigned v) — v の log2 を取得

使用例:

c
#include <libavutil/mathematics.h>
#include <inttypes.h>
#include <stdio.h>

int main() {
    int64_t value = av_rescale(1000, 3, 2);
    printf("スケーリング結果: %" PRId64 "\n", value); // 1500
    return 0;
}

時間スケールの変換は特に重要だ。動画処理では 1/timebase の単位でタイムスタンプが管理されており、フレームレートが異なるストリーム間での変換に av_rescale_q() が必須になる。

3. 画像・音声処理

libavutil には、画像や音声データの処理に役立つ関数が多数用意されている。

主な関数:

  • av_get_pix_fmt_name(enum AVPixelFormat pix_fmt) — ピクセルフォーマット名を取得
  • av_image_fill_arrays() — 画像バッファをセットアップ
  • av_samples_get_buffer_size() — 指定された音声フォーマットのバッファサイズを計算

ピクセルフォーマットの取得:

c
#include <libavutil/pixdesc.h>
#include <stdio.h>

int main() {
    enum AVPixelFormat pix_fmt = AV_PIX_FMT_YUV420P;
    const char *name = av_get_pix_fmt_name(pix_fmt);
    printf("ピクセルフォーマット: %s\n", name); // yuv420p
    return 0;
}

音声バッファサイズの計算:

c
#include <libavutil/channel_layout.h>
#include <libavutil/samplefmt.h>
#include <stdio.h>

int main() {
    int buffer_size = av_samples_get_buffer_size(NULL, 2, 1024, AV_SAMPLE_FMT_S16, 0);
    printf("音声バッファサイズ: %d バイト\n", buffer_size);
    return 0;
}

4. エラーハンドリングとロギング

libavutil には、FFmpeg のエラー処理を簡単にするための関数が備わっている。

主な関数:

  • av_strerror(int errnum, char *errbuf, size_t errbuf_size) — エラーコードを人間が読める文字列に変換
  • av_log(void *avcl, int level, const char *fmt, ...) — ログメッセージを出力
  • av_log_set_level(int level) — ログレベルを設定

エラーメッセージの取得:

c
#include <libavutil/error.h>
#include <stdio.h>

int main() {
    char errbuf[128];
    int errnum = AVERROR(EINVAL);
    av_strerror(errnum, errbuf, sizeof(errbuf));
    printf("エラー: %s\n", errbuf);
    return 0;
}

ログの出力:

c
#include <libavutil/log.h>

int main() {
    av_log_set_level(AV_LOG_DEBUG); // DEBUGレベル以上のログを表示
    av_log(NULL, AV_LOG_INFO, "FFmpeg のログメッセージです\n");
    return 0;
}

ログレベルには AV_LOG_QUIETAV_LOG_PANICAV_LOG_ERRORAV_LOG_WARNINGAV_LOG_INFOAV_LOG_DEBUG などがある。開発中は AV_LOG_DEBUG に設定すると詳細な内部ログが確認できる。


libavutil のインストールとセットアップ

libavutil を使用するためには、FFmpeg を適切にインストールし、必要なライブラリをコンパイルする必要がある。

Ubuntu でのインストール

bash
sudo apt update
sudo apt install ffmpeg libavutil-dev

最新版をソースからインストールしたい場合:

bash
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
cd ffmpeg
./configure
make -j$(nproc)
sudo make install

macOS でのインストール

bash
brew install ffmpeg

開発環境でライブラリをリンクする場合は以下のように設定する。

bash
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig

Windows でのインストール

Windows では MSYS2 を使った開発環境の構築を推奨する。

  1. https://ffmpeg.org/download.html から Windows 用の開発ライブラリ付きのビルドをダウンロード
  2. ZIP ファイルを解凍し、環境変数にパスを追加
  3. コマンドプロンプトで ffmpeg -version を実行して確認

C 言語での libavutil 利用設定

C 言語で libavutil を使う場合、pkg-config を利用してコンパイルフラグを取得できる。

bash
gcc -o my_program my_program.c $(pkg-config --cflags --libs libavutil)

よくあるエラーとその解決方法

1. undefined reference to 'av_malloc'

エラーの原因: libavutil のライブラリが正しくリンクされていない。

解決策: コンパイル時に pkg-config を使用して適切にリンクする。

bash
gcc -o my_program my_program.c $(pkg-config --cflags --libs libavutil)

または手動でリンクする場合:

bash
gcc -o my_program my_program.c -lavutil -lavcodec -lavformat

2. libavutil.so.XX: cannot open shared object file

エラーの原因: 共有ライブラリ libavutil.so が見つからない。通常、ライブラリのパスが環境変数 LD_LIBRARY_PATH に設定されていないことが原因だ。

解決策:

bash
# ライブラリパスを確認
ldd /usr/local/bin/ffmpeg | grep libavutil

# not found となっていた場合、パスを追加
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH

# システムにライブラリを登録
sudo ldconfig

3. AV_LOG_ERROR: Codec not found

エラーの原因: FFmpeg のコーデックが正しくインストールされていない。

解決策: FFmpeg のコンパイル時に必要なコーデックを有効にする。

bash
./configure --enable-gpl --enable-libx264 --enable-libmp3lame
make -j$(nproc)
sudo make install

インストール済みのコーデックを確認する場合:

bash
ffmpeg -codecs | grep x264

4. Segmentation fault(セグメンテーションフォルト)

エラーの原因: メモリの不正アクセス。av_malloc() で確保したメモリを解放せずに再利用したり、不正なポインタを参照している可能性がある。

解決策:

  • av_malloc() で確保したメモリは必ず av_free() で解放する
  • デバッグツール gdb を使用してエラーの原因を特定する
bash
gdb --args ./my_program
run
bt

libavutil の具体的な活用例

1. メディアファイルの MD5 ハッシュ計算

libavutil には、MD5 ハッシュを計算する機能がある。メディアファイルの整合性を確認する際に便利だ。

c
#include <libavutil/md5.h>
#include <stdio.h>
#include <string.h>

int main() {
    AVMD5 *md5 = av_md5_alloc();
    unsigned char digest[16];
    const char *data = "Hello, FFmpeg!";

    av_md5_init(md5);
    av_md5_update(md5, (const uint8_t*)data, strlen(data));
    av_md5_final(md5, digest);

    printf("MD5: ");
    for (int i = 0; i < 16; i++) {
        printf("%02x", digest[i]);
    }
    printf("\n");

    av_free(md5);
    return 0;
}

2. タイムスタンプの変換

動画のフレームレートが異なる場合、正確なタイムスタンプの計算が必要だ。libavutil の av_rescale_q() を利用すると、異なる時間基準間でスケーリングが可能だ。

c
#include <libavutil/mathematics.h>
#include <libavutil/rational.h>
#include <inttypes.h>
#include <stdio.h>

int main() {
    AVRational src_time_base = {1, 30}; // 30 FPS の timebase
    AVRational dst_time_base = {1, 1000}; // ミリ秒単位

    int64_t frame_number = 300; // 10秒目のフレーム(30fps × 10秒)

    int64_t milliseconds = av_rescale_q(frame_number, src_time_base, dst_time_base);
    printf("変換後のタイムスタンプ: %" PRId64 " ミリ秒\n", milliseconds); // 10000
    return 0;
}

30FPS の動画でフレーム番号 300 は、ミリ秒に変換すると 10,000ms(10秒)になる。

3. 実用的なエラーハンドリングパターン

実際の FFmpeg アプリケーションでは、ほぼすべての API 呼び出しでエラーチェックが必要だ。libavutil の av_strerror() を活用した安全なパターン:

c
#include <libavutil/error.h>
#include <libavformat/avformat.h>
#include <inttypes.h>
#include <stdio.h>

// エラーチェックマクロ
#define CHECK_ERROR(ret, msg) \
    do { \
        if (ret < 0) { \
            char errbuf[128]; \
            av_strerror(ret, errbuf, sizeof(errbuf)); \
            fprintf(stderr, "%s: %s\n", msg, errbuf); \
            return ret; \
        } \
    } while (0)

int open_media_file(const char *filename) {
    AVFormatContext *fmt_ctx = NULL;
    int ret;

    ret = avformat_open_input(&fmt_ctx, filename, NULL, NULL);
    CHECK_ERROR(ret, "ファイルを開けませんでした");

    ret = avformat_find_stream_info(fmt_ctx, NULL);
    CHECK_ERROR(ret, "ストリーム情報の取得に失敗しました");

    printf("フォーマット: %s\n", fmt_ctx->iformat->name);
    printf("再生時間: %" PRId64 " 秒\n", fmt_ctx->duration / AV_TIME_BASE);

    avformat_close_input(&fmt_ctx);
    return 0;
}

int main() {
    return open_media_file("input.mp4");
}

このパターンを使えば、どのステップで何のエラーが起きたかを明確にトレースできる。


まとめ

libavutil は、FFmpeg を活用した開発において不可欠なライブラリだ。メモリ管理・数学演算・画像処理・エラーハンドリングなど、多岐にわたる機能を提供する。

  • メモリ管理: av_malloc() / av_free() で安全なリソース管理
  • 時間計算: av_rescale_q() で異なる timebase 間のスケーリング
  • エラーハンドリング: av_strerror() でエラーコードを人間が読める形式に変換
  • ロギング: av_log() / av_log_set_level() でデバッグ情報を制御
  • ハッシュ計算: av_md5_* でファイルの整合性チェック

libavutil を適切に活用することで、より高性能で安全なメディア処理アプリケーションを開発できるようになる。