libavcodec / libavformat を使ってみる 1

ちょっと特殊なエンコード処理をしてみたい気分だったので、ffmpegを参考に、libavcodec, libavformat あたりを使ってみることにしました。

とりあえず今日は、動画ファイルのコーデック名を出力するようなプログラムを組んでみました。

Mac OS X で開発した場合は、MacPortsで ffmpeg をインストールし、XCodeの新規プロジェクトで Command Line Tool C で作成します。そのあと、プロジェクトの設定のビルドのタブで、ヘッダ検索パスに Ports でインストールしたヘッダなどが含まれる /opt/local/inculude あたりを設定し、プロジェクトに libavcodec.a と libavformat.a を加えるとビルドできるようなるはずです。

まず、ヘッダをインクルードします。libavcodec, libavformat は、次のヘッダをインクルードすると使えます。

#include <avcodec.h>
#include <avformat.h>

libavcodec, libavformat を使うプログラムでは、最初に av_register_all() を呼び出して、初期化します。

av_register_all();

今回は、ファイルの情報を調べたいので、av_open_input_file() を使って、ファイルの情報を得ます。この関数で得た AVFormatContext 構造体に、たくさんの情報が入ります。ここで得た AVFormatContext は、不要になったら av_close_input_file() で解放する必要があります。必要な引数は第二引数までで、動画のフォーマットを強制したい場合などに以降の引数は使用します。今回は自動判別して欲しいので、第三引数からは何も指定しません。

AVFormatContext *format;
if ( av_open_input_file( &format, filename, NULL, 0, NULL ) ) {
	puts( "Couldn't open file" );
}

次に、 av_find_stream_info() を使ってストリームの情報を付加します。

if ( av_find_stream_info( format ) < 0 ) {
		puts( "Couldn't find stream information" );
		return -1;
	}

ストリームの情報も得られたところで、各々のストリームのコーデックを出力します。

for ( int i = 0; i < format->nb_streams; i++ ) {
	printf( "stream #%dn", i );
	printf( "tcodec type: %dn", format->streams[i]->codec->codec_type );

	enum CodecID codec_id = format->streams[i]->codec->codec_id;
	AVCodec *codec = avcodec_find_decoder( codec_id );
	if ( codec ) {
		printf("tcodec name: %sn", codec->name );
	} else {
		printf( "tcodec id %d is not foundn", codec_id );
	}
}

format->nb_streams にストリーム数が書かれているので、その分だけ情報を出力します。 各ストリームの情報は、format->streams に入っています。AVStream 構造体の配列になっています。そしてその中の codec がコーデックの情報を表わしており、それは AVCodecContext 構造体です。この中のコーデックIDを得ることにより、IDから avcodec_find_decoder() を用いてデコーダを得ることができます。デコーダには、そのデコーダのコーデックの情報が入っていて、そのコーデックの名前も得ることができます。こうして、デコーダからコーデック名を得ることができるわけです。

このあとに、上で得たデコーダのコンテキストから、実際のデコーダを生成すれば、ストリームをデコードすることができるわけです。

サンプルソース: main.c

参考文献:
http://www.inb.uni-luebeck.de/~boehme/using_libavcodec.html
svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg

コメント投稿