SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

FFmpeg APIで、さまざまな動画を操る

FFmpeg APIで、さまざまな動画を操る - 後編

自作アプリケーションに動画の書き出し処理を組み込む

  • このエントリーをはてなブックマークに追加

オープンソースの動画録画・変換・配信ソフトウェアとしてFFmpegが有名となりつつありますが、そのAPIに関してはあまり解説されていません。本稿ではFFmpeg APIについて説明し、自分のプログラムから様々なコーデックを使って動画を扱う方法を説明します。

  • このエントリーをはてなブックマークに追加

はじめに

 こんにちは、hirataraです。

 本稿はFFmpeg APIの解説の後編となります。前編をご覧になっていない方は、前編からお読みください。

前回の記事

サンプル: サムネイル画像を作る 後編

 前編では、動画から最初のフレームを取り込むプログラムを作成しました。後編では、このフレームをFFmpeg APIを使って書き出します。

フレームを静止画としてファイルに書き込む

 それでは、取得したフレームを書き出す処理を書いてみます。今回のサンプルでは動画ではなく画像として書き出すので、実はlibswscaleを使ってフォーマットを変更した物を直接ファイルに出力するだけでもこの仕様を満たすことができます。しかし、FFmpeg APIのエンコーダの利用方法の説明を兼ねるため、ここではあえて"image2"フォーマットを利用して動画と同じようにエンコーダ経由で画像を出力してみます。

 mainルーチンより、フレームの保存処理を次のように呼びます。save_frame()は、これから自分で実装する処理です。

フレームの保存部
/**
 * フレームを画像として保存する
 * @param[in] frame      保存するフレーム
 * @param[in] filename  保存先のPATH
 */
void save_frame(const AVFrame *frame, const char *filename);

int main(int argc, char *argv[]){
    /* ... フレーム読み込み処理(前編で実装済) ...*/

    /* フレームの保存 */
    save_frame(frame, argv[2]);

    /* ... 後略 ...*/
}

 save_frame内の処理は、次のような流れとなります。

  1. 出力するフォーマットの情報を生成
  2. ストリームを開き、動画コーデックを割り当てる
  3. コーデック、ファイルを開き、書き込み準備をする
  4. ヘッダを書き込む
  5. パケットを符号化し、書き込む
  6. 書き込むパケットが無くなるまで5を続ける
  7. 利用したメモリを解放し、終了する

出力するフォーマットの情報を生成

 読み込みの時、AVFormatContext構造体は、既存の動画ファイルを読み込みフォーマットやコーデックを自動判別することで作られました。しかし、書き込みの際は自分で作りたい動画のフォーマットを決定し、AVFormatContext構造体を設定しなければなりません。

 以下のコードで、フォーマットを準備しています。

フレームの保存部
/* 画像出力のフォーマットを準備 */
AVOutputFormat *format = guess_format("image2", NULL, NULL);
if(format == NULL) error("can't find image2 format.");

/* フォーマットコンテキストを作成 */
AVFormatContext *formatCtx = av_alloc_format_context();
if(formatCtx == NULL) error("can't alloc format context.");
formatCtx->oformat  = format;
av_strlcpy(formatCtx->filename, filename, sizeof(formatCtx->filename));

 guess_formatはlibavformat/avformat.hで宣言されている関数で、出力フォーマットを得るために利用します。第1引数がフォーマット名、第2引数がファイル名、第3引数がMIME名となっており、これらの情報から判断して1番ふさわしい物を返してくれます。今回は"image2"フォーマットを使うとすでに決めているので、この値を渡しています。

 続くav_alloc_format_contextでは、フォーマット情報を格納するためのAVFormatContext構造体を確保しています。この構造体のoformatフィールドにAVOutputFormatを、filenameフィールドにはファイル名をセットします。

 なお、ファイル名をセットするために使っているav_strlcpyはlibavutil/avstring.hで宣言されており、文字列のコピーを行うユーティリティ関数となっています。filenameフィールドには、文字列の先頭文字へのポインタではなく、文字配列のコピーを実際に入れる必要があるため、この関数を利用してコピーを行っています。

会員登録無料すると、続きをお読みいただけます

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

次のページ

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加
FFmpeg APIで、さまざまな動画を操る連載記事一覧
この記事の著者

hiratara(ヒラタラ)

1977年に苫小牧市で生まれる。北海道大学理学部数学科卒。小学生の頃、両親に買い与えられたMZ-2500でプログラミングを始めた。学生時代、CGIの自作に没頭し、それ以降WEB開発の魅力に憑かれる。社会人になっても数学好きは変わらず、専門書を買い集めるのが最近の趣味。id:hirataraにてblogを執筆...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/2622 2008/07/14 14:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング