Developer Documentation
Table of Contents
- libavcodec はコーデック(エンコーディングおよびデコーディングの両方)
を含むライブラリです。それをどのように使うかを知るためには ‘libavcodec/apiexample.c’
を見てください。
- libavformat はファイルフォーマットの取り扱い(さまざまなフォーマットの
ための mux および demux コード)を含むライブラリです。これをプレーヤーの中で使うには
‘avplay.c’ を見てください。オーディオまたはビデオストリームを生成するために使うには
‘libavformat/output-example.c’ を見てください。
可能なときには常に共有ライブラリを使うべきです。プログラムをサポート
し公開 API だけを使うようにするために配布者が費す労力を減らすため
です。
libav を商用プログラムに使うことができますが、使っている機能に応じて
LGPL もしくは GPL をライセンスを受け入れなければなりません。
簡単なチェックリストとしては 私たちの法律上の 注意点が書かれたページ を参照してください。
またライセンスの正確な文章については
GPL version 2、
GPL version 3、
LGPL version 2.1、
LGPL version 3
を参照してください。
ソースコードのいかなる変更も該当します。
着手するための最も良い方法は
libav-devel
メーリングリストにパッチを送ることです。
コードは K&R C スタイルで書かれます。これは以下のことを意味します:
-
制御ステートメントでは、以下のようにステートメントや括弧の間に空白を置いて
書式化してください:
for (i = 0; i < filter->input_count; i++) {
-
case ステートメントは常に switch と同じレベルに置いてください:
switch (link->init_state) {
case AVLINK_INIT:
continue;
case AVLINK_STARTINIT:
av_log(filter, AV_LOG_INFO, "circular filter chain detected");
return 0;
-
関数宣言は改行で囲んで書くようにしてください:
const char *avfilter_configuration(void)
{
return LIBAV_CONFIGURATION;
}
-
比較によって NULL をチェックしないようにしてください。‘if (p)’
や ‘if (!p)’ が良く、‘if (p == NULL)’ や ‘if (p != NULL)’
はだめです。
-
シングルステートメントの if の場合、括弧はいりません:
if (!pic || !picref)
goto fail;
-
括弧の中で直後には空白は置かないようにしてください。‘if (ret)’ は
妥当なスタイルです; ‘if ( ret )’ はだめです。
ファイル内でのインデンテーションについて以下のようなガイドラインがあります:
-
インデントサイズは 4 です。
-
表示状態は ’indent -i4 -kr -nut’ によって特定されるものです。
タブ文字は Makefile のほかでは行末の空白文字と同様に禁止されます。
このどちらかを含むコミットは git レポジトリに拒否されます。
-
コードの行を80文字に収まるようにするべきです; しかし、可読性を向上する
場合に限りそのようにしてください。
表示のあり方は ’indent -i4 -kr -nut’ によるものです。
Libav での主な優先事項はバグの個数を最小化するための単純さと小さなコードサイズ
です。
JavaDoc/Doxygen 書式を使って、(以下の例を見て)コードのドキュメントが自動的に
生成できるようにしてください。
自明でない関数はすべてその直前に、その関数が行うことを説明するコメントを持つべき
です。たとえそれが単なる1行の文であっても。
すべての構造体とそのメンバー変数にもドキュメントがあるべきです。
!
を含んだ Qt スタイルや類似の Doxygen 構文は避けてください。つまり
//!
は ///
などで置き換えてください。まマークアップのコマンドには
@ を用いるべきで、\param
ではなく @param
を使ってください。
/**
* @file
* MPEG codec.
* @author ...
*/
/**
* Summary sentence.
* more text ...
* ...
*/
typedef struct Foobar{
int var1; /**< var1 description */
int var2; ///< var2 description
/** var3 description */
int var3;
} Foobar;
/**
* Summary sentence.
* more text ...
* ...
* @param my_parameter description of my_parameter
* @return return value description
*/
int myfunc(int my_parameter)
...
Libav は ISO C90 言語に少しだけ ISO C99 からの追加的な機能を加えた形
でプログラムされています。それらは以下のものです:
-
‘inline’ キーワード;
-
‘//’ コメント;
-
指定構造体初期化子 (‘struct s x = { .i = 17 };’)
-
複合リテラル (‘x = (struct s) { 17, 23 };’)
これらの機能は我々が関知する全てのコンパイラーでサポートされており、
そのため、明確さと性能を絶対に損なわない場合を除いてそれらの使用を
取り除くためのパッチは受理されません。
全てのコードは最近の GCC やその他の現在対応している多くのコンパイラで
コンパイルできなければなりません。互換性を保証するために、別の C99 の
機能や GCC 拡張は使用しないでください。特に次に警戒してください:
-
ステートメントと宣言を混ぜる;
-
‘long long’ (代わりに ‘int64_t’ を使ってください);
-
‘#ifdef __GNUC__’ で保護されていない ‘__attribute__’ や類似のもの;
-
GCC 複合式 (‘(x = ({ int y = 4; y; })’).
全ての名前にはアンダースコア(_)を使い、キャメルケースは使いません。例えば、
‘avfilter_get_video_buffer’ は妥当な関数名ですが、
‘AVFilterGetVideo’ はだめです。唯一の例外は構造体の名前です; これらは
常にキャメルケースであるべきです
変数および関数に名前をつけるときには以下の決まりがあります:
-
ローカル変数にはプレフィックスはいりません。
-
static
と宣言されている変数および関数についてはプレフィックスはいりません。
-
ライブラリの内部で使われている変数および関数には、
ff_
というプレフィックスを
用いるべきです。
例、‘ff_w64_demuxer’。
-
複数のライブラリに渡って内部で使われている変数および関数には、
avpriv_
を
用いてください。例、‘avpriv_aac_parse_header’。
-
エクスポートされている名前には、各ライブラリごとにプレフィックスがあります。
既存のコードを確認して、それに従って名前をつけてください。
-
fprintf と printf は libavformat や libavcodec では禁止されています、
代わりに av_log() を使ってください。
-
必要なときだけキャストを使うべきです。コードを理解しやすくするのでないなら
不要な括弧も避けるべきです。
Libav の整形規則に従うように Vim を設定するため、以下のコード片を ‘.vimrc’
にペーストしてください:
" indentation rules for libav: 4 spaces, no tabs
set expandtab
set shiftwidth=4
set softtabstop=4
set cindent
set cinoptions=(0
" allow tabs in Makefiles
autocmd FileType make set noexpandtab shiftwidth=8 softtabstop=8
" Trailing whitespace and tabs are forbidden, so highlight them.
highlight ForbiddenWhitespace ctermbg=red guibg=red
match ForbiddenWhitespace /\s\+$\|\t/
" Do not highlight spaces at the end of line while typing on that line.
autocmd InsertEnter * match ForbiddenWhitespace /\t\|\s\+\%#\@<!$/
Emacs のために、以下のほぼ同等な行を ‘.emacs.d/init.el’ に追加してください:
(c-add-style "libav"
'("k&r"
(c-basic-offset . 4)
(indent-tabs-mode . nil)
(show-trailing-whitespace . t)
(c-offsets-alist
(statement-cont . (c-lineup-assignments +)))
)
)
(setq c-default-style "libav")
-
貢献は LGPL 2.1、 もしくは LGPL 2.1 で "or any later version" 条項を含んだもの、
もしくは MIT ライセンスで使用許諾されているべきです。"or any later version" 条項
を含んだ GPL 2 も受け入れられますが、 LGPL の方が望ましいです。
-
全てのパッチはコミットされる前にメーリングリストでレビューされなければ
なりません。
-
Libav コーディングスタイルは一貫しているべきです。従うべき変更はコミットを
レビューまたは実装している間に指摘されます。
-
パッチは
git format-patch
を使って生成されるか、直接 git send-email
で送信されるべきです。
コミットに正しい author を設定して適切なクレジットを与えていることを確認して
ください。
-
コミットメッセージは ‘topic: short description’ の形をした最初の短い1行を
先頭にし、1行空けてそのパッチ理由を説明する数行の内容をもつべきです。
バグトラッカーの issue を参照した場合でもそのバグの抜粋を報告しなければ
なりません。
-
作業中のパッチは [WIP] または [RFC] タグをつけてメーリングリストに送られる
べきです。
-
issue について協力して作業するためには、公開の個人的なレポジトリのブランチを
使うべきです。
-
過剰にテストする必要はありません。あなたにとってうまく動作し、かつ他の人にとっても
うまく動作するはずと思うなら、レビューのためのメーリングリストにそれを送ってください。
移植可能性について疑問があるなら、投稿内でそう述べて、特定のハードウェアを持っている
人たちがテストできるようにしてください。
-
無関係な変更を一緒にコミットしないで、それらを自己完結した断片に分けてください。
また、部分 A に 部分 B が依存しているが A は B に依存していない場合には、
A が先に B とは別にコミットすることができ、かつそうするべきだということを
忘れないでください。変更を自己完結した部分にきちんと分けておくことで、コミット
ログのメーリングリスト上にあるそれらをレビューし理解することがより容易に
なります。またこれによって後々にデバッグする場合に助かります。
-
プログラムの振舞い(オプションの名前を変更するなど)や公開 API または ABI を
変更するパッチは徹底的に議論されるべきです。議論からコミットまでの間に
数日をかけるべきです。
予想される振舞いを変えるようなビルドシステム(Makefile や configure スクリプト)
への変更も同じように考えられます。
-
メーリングリスト上で(長い間)議論されたパッチを適用する場合には、ログメッセージ
でそのスレッドを参照してください。
-
libav-devel や
libav-commits
メーリングリストを購読してください。
バグや可能な改善、コミットについての一般的な質問は libav-devel で議論されます。
あなたのコードで問題が明らかになった場合、あなたが反応することを期待
します。
-
振舞いを変更または機能を追加する際にはドキュメントを更新してください。これをするために
どうするのが最善か分からない場合は、[RFC] のパッチを libav-devel に送ってください。
-
参照が残るように、全ての議論と決定は公開の開発者メーリングリストで報告
されるべきです。
(IRC などの)他のメディアは調整やその場の協力のために使うべき
です。
-
アロケートされていないメモリに決して書き込まないでください。配列の終端を越えて書き込まないでください。
信用できないソースから読み込んだ値を配列のインデックスやその他のリスクのあるものとして
使う前に確認してください。確認のために valgrind を常に使ってください。
-
あなたが変更している特定の libav パーツ(libavutil、libavcodec、libavformat)に
ついてバージョンを上げる必要があるかどうか確認することを忘れないでください。
バージョン整数を変更する必要があります。
最初の構成要素をインクリメントすることは、以前のバージョンに対する後方互換性が
ない(例えば公開 API からの関数の削除)ことを意味します。
2番目の構成要素をインクリメントすることは、後方互換である変更
(例えば公開 API に関数を追加する、または既に存在するデータ構造の拡張)を意味します。
3番目の構成要素をインクリメントすることは、注目に値するバイナリ互換である変更
(例えばデコーダーにとって重要であるエンコーダーのバグ修正)を意味します。
-
コンパイラの警告は潜在的なバグ、または良くないスタイルのコードを示唆しています。
それがバグなら、修正されなくてなりません。そうでないなら、そのコードは警告を
生まないように変更すべきです(それが速度低下や曖昧化を引き起こさない限りは)。
ある種の警告があまりにも多くの偽陽性であるなら、その警告は無効にされるべきで、
コードを変更すべきではなりません。
-
新しいファイルを追加したら、それに正式なライセンスヘッダーを与えてください。
でたらめな場所からコピーアンドペースとしないでください。
テンプレートとしての存在しているファイルを使ってください。
我々は自分たちの規則がそれほど厳しくないと考えています。意見がありましたら、我々に連絡してください。
注意、いくつかの規則は MPlayer プロジェクトから借りています。
まず最初に、まだ未読なら上の Coding Rules を読んでください。特に
パッチ投稿に関するルールを読んでください。
既に述べたように、複数の無関係な変更を含んだパッチを投稿しないで
ください。
パッチを提出する際には、unified diff(diff の’-up’ オプション)を送ることを
試みてください。他の diff は読めません :-)
また、各種の無関係な変更が含まれているパッチを提出しないでください。
それを個々の自己完結したパッチに分割してください。これはファイル1つ1つに
分割するということではありません。代わりに、出来る限りパッチを小さくし、
たとえ複数のファイルに渡るとしても1つの個別の変更を含む論理的な1単位として
保つようにしてください。これによってパッチは我々にとってさらにレビュー
しやすくなり、パッチが適用される機会が大幅に増えます。
パッチを調査するための Libav の patcheck ツールを使ってください。
このツールは tools ディレクトリにあります。
予期しない問題を生じないことを調べられるように、パッチを提出する前に Regression Tests を
実行してください。
パッチは base64 (またはパッチが伝送中にだめにならないことが保証されて
いるその他のエンコーディングで)エンコードされた添付ファイルとして、
libav-devel
に投稿されるべきです。
また、そのパッチが行うこと(例えば ’lrint を lrintf で置き換える’)、および
その理由(例えば ’*BSD は C99 準拠でなく lrint() がない’)を教えていただけたら
大いに助かります。こういった説明はコミットメッセージの内容になるべき
です。
また、複数のパッチを送る際には、それぞれのパッチを別々のメールとして送って
ください。同じメールに無関係な複数のパッチを添付しないでください。
可能ならば git send-email
を使ってください。なぜなら余分な苦労なしに
パッチが適切に送れるからです。
あなたのパッチはメーリングリストでレビューされます。あなたはいくつかの変更を
求められたり、レビューからのリクエストを組み入れた修正版を送ることを期待されます。
このプロセスは複数回繰り返されて進むことがあります。パッチが十分よいと判断され次第、
公式の Libav ツリーにコミットされます。
反応するのに数日ください。しかし反応なしにいくらか時間が経過したら、
思い出すようメールを送ってください。いずれパッチは取り扱われるでしょう。
-
コーデックの初期化および完了の関数に av_cold を使いましたか?
-
AVCodec または AVInputFormat/AVOutputFormat 構造体に対し NULL_IF_CONFIG_SMALL の下に
long_name を追加しましたか?
-
‘libavcodec/version.h’ または ‘libavformat/version.h’ のマイナーバージョンナンバーを
上げ(、かつマイクロバージョンナンバーをリセットし)ましたか?
-
‘allcodecs.c’ または ‘allformats.c’ の中にそれを登録しましたか?
-
‘avcodec.h’ に AVCodecID を追加しましたか?
新しいコーデックIDを追加した際には、‘libavcodec/codec_desc.c’ にある
コーデック説明一覧にも項目を追加してください。
-
fourcc がある場合、たとえデコーダーのみの場合でもそれを ‘libavformat/riff.c’
に追加しましたか?
-
Makefile で適切なファイルがコンパイルされるように規則を追加しましたか?
raw demuxer のような、ほかのいくつかの規則によって既にコンパイルされるファイルに単にフォーマットを追加するだけという場合でも、
これを忘れないようにしてください。
-
‘doc/general.texi’ の中のサポートされているコーデックまたはフォーマットの一覧にエントリを
追加しましたか?
-
Changelog にエントリを追加しましたか?
-
それがあるパーサーまたはライブラリに依存する場合には、configure にその依存関係を
追加しましたか?
-
コミットする前に適切なファイルを
git add
しましたか?
-
単独で、つまり
configure --disable-everything --enable-decoder=foo
で(または --enable-demuxer
、あるいは当のコンポーネントが何でも)
コンパイルが通ることを確認しましたか?
-
そのパッチを適用して
make check
が通りますか?
-
そのパッチは最新の Libav git master branch に対するものですか?
-
libav-devel
メーリングリストを購読していますか?
(リストは購読者のみ投稿できます。)
-
その変更が最小であること、そのためより小さなパッチや/またはより単純な最終的な
コードでは同じことが達成できないことを確認しましたか?
-
その変更が重要なコードを速くするためのものなら、それをベンチマークで測りましたか?
-
そのパッチがバッファオーバーフローまたは他のセキュリティの問題を持ち込まない
ことを確認しましたか?
-
decoder または demuxer を壊れたデータでテストしましたか? していない場合は
tools/trasher や noise bitstream filter を見てください。decoder や demuxer は
壊れたデータを入力された際にクラッシュしたり無限ループ(に近い形)で終わるべきではありません。
-
そのパッチには機能的な変更と表面的な変更を混ざっていませんか?
-
タブまたは行末の空白をコードに加えましたか? どちらも禁止されています。
-
そのパッチはあなたが送るメールに添付されていますか?
-
そのパッチの mime type は正しいですか? それは text/x-diff または text/x-patch
であるべきで、text/plain は許されますが、application/octet-stream は許されません。
-
そのパッチがバグを修正しているなら、そのバグの詳しい分析を与えましたか?
-
そのパッチがバグを修正しているなら、サンプルを含めた十分な情報を与えており、
そのためバグを再現することができ修正を調べることができますか?
100kを越えるサンプルをメールに添付するのではなく、代わりに URL の形で提供するように
注意してください。ftp://upload.libav.org にアップロードできます。
-
そのパッチが変更することについて詳しい要約を与えましたか?
-
そのパッチがそのように変更を行う理由について詳しい説明を与えましたか?
-
そのパッチが適用された場合にユーザーから見える利点と欠点についての詳しい要約
を与えましたか?
-
そのパッチによって追加される新しい機能を簡単に調べられるよう例を与えましたか?
-
ベンチマークを取ったなら、それをメールの中で与えましたか?
-
新しいファイルを追加したなら、ライセンスヘッダーを入れましたか?
それは Libav から取ってこられるべきで、どこか他からでたらめにコピーアンド
ペーストされるべきではありません。
-
API/ABI 互換性を壊さない限り、アルファベット順に並んでいるリストでは
その順序を維持するべきです。
-
そうすることで可読性が改善される場合には、似た内容の行は垂直に並べられる
べきです。
-
関数の戻り値を確認し、適切なエラーコードを返すようにしてください。
特に、
malloc()
のようなメモリを確保するための関数はよくチェックされない
ままになっており、これは深刻な問題です。
libav-devel
に投稿された全てのパッチはレビューされるでしょう、そのパッチが
git master branch 向けでないという明確な注意が含まれていない限り。
レビューとコメントはパッチへの回答としてメーリングリスト上に投稿されます。
そしてパッチの提出者は全てのコメントに対処しなければならず、
それは変更したパッチの再提出や議論によってなされます。
パッチの再提出はそれ自体他のパッチと同様にレビューされます。
どこかの時点でコメントなしでレビューを通過したら、それは承認されます。
これは単純で小さなパッチについてはすぐに起こるでしょうが、
大きなパッチは一般的に承認される前に何回も変更されそしてレビューされるに違いありません。
パッチは承認された後でレポジトリにコミットされるでしょう。
我々は全ての提出されたパッチをレビューするでしょうが、ときおりとても忙しく、
特に大きなパッチに対しては数週間に及ぶことがあります。
パッチを再提出する際、そのサイズが多大きくなったりレビューの過程で異なる問題が
持ち上がったりしたときには、それぞれの issue に個別のパッチになるように
そのパッチを分割してください。
パッチを提出する(またはレポジトリにコミットする)前に、少なくとも
それが何も壊さないということを確実にするべきです。
変更されるコードについて既に FATE にテストがあるなら、それを実行するべきです。
そうでなければテストを追加するべきです。
コーデックまたはデミュクサーに対する改善は FATE の結果を変えてしまうことがあります。
その変更を参照する更新をコミットすることと、なぜ予期される結果が変わるかをコメント
で説明することを必ずしてください。
fate.html を参照してください。