開発者ガイド
******

API
===

  * libavcodec はコーデック(エンコーディングおよびデコーディングの両方) を含むライブラリです。それをどのように使うかを知るためには libavcodec/apiexample.c を見てください。

  * libavformat はファイルフォーマットの取り扱い(さまざまなフォーマットのための mux および demux コード)を含むライブラリです。これをプレーヤーの中で使うには avplay.c を見てください。オーディオまたはビデオストリームを生成するために使うには libavformat/output-example.c を見てください。

libav をあなたのプログラムで統合する
=====================

可能なときには常に共有ライブラリを使うべきです。プログラムをサポートし公開 API だけを使うようにするために配布者が費す労力を減らすためです。

libav を商用プログラムに使うことができますが、使っている機能に応じて LGPL もしくは GPL をライセンスを受け入れなければなりません。簡単なチェックリストとしては 私たちの法律上の 注意点が書かれたページ (http://libav.org/legal.html) を参照してください。またライセンスの正確な文章については GPL version 2 (http://git.libav.org/?p=libav.git;a=blob;f=COPYING.GPLv2)、 GPL version 3 (http://git.libav.org/?p=libav.git;a=blob;f=COPYING.GPLv3)、 LGPL version 2.1 (http://git.libav.org/?p=libav.git;a=blob;f=COPYING.LGPLv2.1)、 LGPL version 3 (http://git.libav.org/?p=libav.git;a=blob;f=COPYING.LGPLv3) を参照してください。ソースコードのいかなる変更も該当します。着手するための最も良い方法は libav-devel (https://lists.libav.org/mailman/listinfo/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)
     ...

C 言語の機能
-------

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")

開発ポリシー
======

 1. 貢献は LGPL 2.1、 もしくは LGPL 2.1 で "or any later version" 条項を含んだもの、もしくは MIT ライセンスで使用許諾されているべきです。"or any later version" 条項を含んだ GPL 2 も受け入れられますが、 LGPL の方が望ましいです。

 2. 全てのパッチはコミットされる前にメーリングリストでレビューされなければなりません。

 3. Libav コーディングスタイルは一貫しているべきです。従うべき変更はコミットをレビューまたは実装している間に指摘されます。

 4. パッチは git format-patch を使って生成されるか、直接 git send-email で送信されるべきです。コミットに正しい author を設定して適切なクレジットを与えていることを確認してください。

 5. コミットメッセージは topic: short description の形をした最初の短い1行を先頭にし、1行空けてそのパッチ理由を説明する数行の内容をもつべきです。バグトラッカーの issue を参照した場合でもそのバグの抜粋を報告しなければなりません。

 6. 作業中のパッチは [WIP] または [RFC] タグをつけてメーリングリストに送られるべきです。

 7. issue について協力して作業するためには、公開の個人的なレポジトリのブランチを使うべきです。

 8. 過剰にテストする必要はありません。あなたにとってうまく動作し、かつ他の人にとってもうまく動作するはずと思うなら、レビューのためのメーリングリストにそれを送ってください。移植可能性について疑問があるなら、投稿内でそう述べて、特定のハードウェアを持っている人たちがテストできるようにしてください。

 9. 無関係な変更を一緒にコミットしないで、それらを自己完結した断片に分けてください。また、部分 A に 部分 B が依存しているが A は B に依存していない場合には、 A が先に B とは別にコミットすることができ、かつそうするべきだということを忘れないでください。変更を自己完結した部分にきちんと分けておくことで、コミットログのメーリングリスト上にあるそれらをレビューし理解することがより容易になります。またこれによって後々にデバッグする場合に助かります。

 10. プログラムの振舞い(オプションの名前を変更するなど)や公開 API または ABI を変更するパッチは徹底的に議論されるべきです。議論からコミットまでの間に数日をかけるべきです。予想される振舞いを変えるようなビルドシステム(Makefile や configure スクリプト) への変更も同じように考えられます。

 11. メーリングリスト上で(長い間)議論されたパッチを適用する場合には、ログメッセージでそのスレッドを参照してください。

 12. libav-devel (https://lists.libav.org/mailman/listinfo/libav-devel) や libav-commits (https://lists.libav.org/mailman/listinfo/libav-commits) メーリングリストを購読してください。バグや可能な改善、コミットについての一般的な質問は libav-devel で議論されます。あなたのコードで問題が明らかになった場合、あなたが反応することを期待します。

 13. 振舞いを変更または機能を追加する際にはドキュメントを更新してください。これをするためにどうするのが最善か分からない場合は、[RFC] のパッチを libav-devel に送ってください。

 14. 参照が残るように、全ての議論と決定は公開の開発者メーリングリストで報告されるべきです。 (IRC などの)他のメディアは調整やその場の協力のために使うべきです。

 15. アロケートされていないメモリに決して書き込まないでください。配列の終端を越えて書き込まないでください。信用できないソースから読み込んだ値を配列のインデックスやその他のリスクのあるものとして使う前に確認してください。確認のために valgrind を常に使ってください。

 16. あなたが変更している特定の libav パーツ(libavutil、libavcodec、libavformat)についてバージョンを上げる必要があるかどうか確認することを忘れないでください。バージョン整数を変更する必要があります。最初の構成要素をインクリメントすることは、以前のバージョンに対する後方互換性がない(例えば公開 API からの関数の削除)ことを意味します。 2番目の構成要素をインクリメントすることは、後方互換である変更 (例えば公開 API に関数を追加する、または既に存在するデータ構造の拡張)を意味します。 3番目の構成要素をインクリメントすることは、注目に値するバイナリ互換である変更 (例えばデコーダーにとって重要であるエンコーダーのバグ修正)を意味します。

 17. コンパイラの警告は潜在的なバグ、または良くないスタイルのコードを示唆しています。それがバグなら、修正されなくてなりません。そうでないなら、そのコードは警告を生まないように変更すべきです(それが速度低下や曖昧化を引き起こさない限りは)。ある種の警告があまりにも多くの偽陽性であるなら、その警告は無効にされるべきで、コードを変更すべきではなりません。

 18. 新しいファイルを追加したら、それに正式なライセンスヘッダーを与えてください。でたらめな場所からコピーアンドペースとしないでください。テンプレートとしての存在しているファイルを使ってください。

我々は自分たちの規則がそれほど厳しくないと考えています。意見がありましたら、我々に連絡してください。

注意、いくつかの規則は MPlayer プロジェクトから借りています。

パッチを提出する
========

まず最初に、まだ未読なら上の Coding Rules を読んでください。特にパッチ投稿に関するルールを読んでください。

既に述べたように、複数の無関係な変更を含んだパッチを投稿しないでください。パッチを提出する際には、unified diff(diff の'-up' オプション)を送ることを試みてください。他の diff は読めません :-)

また、各種の無関係な変更が含まれているパッチを提出しないでください。それを個々の自己完結したパッチに分割してください。これはファイル1つ1つに分割するということではありません。代わりに、出来る限りパッチを小さくし、たとえ複数のファイルに渡るとしても1つの個別の変更を含む論理的な1単位として保つようにしてください。これによってパッチは我々にとってさらにレビューしやすくなり、パッチが適用される機会が大幅に増えます。

パッチを調査するための Libav の patcheck ツールを使ってください。このツールは tools ディレクトリにあります。

予期しない問題を生じないことを調べられるように、パッチを提出する前に Regression Tests を実行してください。

パッチは base64 (またはパッチが伝送中にだめにならないことが保証されているその他のエンコーディングで)エンコードされた添付ファイルとして、 libav-devel (https://lists.libav.org/mailman/listinfo/libav-devel) に投稿されるべきです。

また、そのパッチが行うこと(例えば 'lrint を lrintf で置き換える')、およびその理由(例えば '*BSD は C99 準拠でなく lrint() がない')を教えていただけたら大いに助かります。こういった説明はコミットメッセージの内容になるべきです。

また、複数のパッチを送る際には、それぞれのパッチを別々のメールとして送ってください。同じメールに無関係な複数のパッチを添付しないでください。

可能ならば git send-email を使ってください。なぜなら余分な苦労なしにパッチが適切に送れるからです。

あなたのパッチはメーリングリストでレビューされます。あなたはいくつかの変更を求められたり、レビューからのリクエストを組み入れた修正版を送ることを期待されます。このプロセスは複数回繰り返されて進むことがあります。パッチが十分よいと判断され次第、公式の Libav ツリーにコミットされます。

反応するのに数日ください。しかし反応なしにいくらか時間が経過したら、思い出すようメールを送ってください。いずれパッチは取り扱われるでしょう。

新しいコーデックまたはフォーマットチェックリスト
========================

 1. コーデックの初期化および完了の関数に av_cold を使いましたか?

 2. AVCodec または AVInputFormat/AVOutputFormat 構造体に対し NULL_IF_CONFIG_SMALL の下に long_name を追加しましたか?

 3. libavcodec/version.h または libavformat/version.h のマイナーバージョンナンバーを上げ(、かつマイクロバージョンナンバーをリセットし)ましたか?

 4. allcodecs.c または allformats.c の中にそれを登録しましたか?

 5. avcodec.h に AVCodecID を追加しましたか? 新しいコーデックIDを追加した際には、libavcodec/codec_desc.c にあるコーデック説明一覧にも項目を追加してください。

 6. fourcc がある場合、たとえデコーダーのみの場合でもそれを libavformat/riff.c に追加しましたか?

 7. Makefile で適切なファイルがコンパイルされるように規則を追加しましたか? raw demuxer のような、ほかのいくつかの規則によって既にコンパイルされるファイルに単にフォーマットを追加するだけという場合でも、これを忘れないようにしてください。

 8. doc/general.texi の中のサポートされているコーデックまたはフォーマットの一覧にエントリを追加しましたか?

 9. Changelog にエントリを追加しましたか?

 10. それがあるパーサーまたはライブラリに依存する場合には、configure にその依存関係を追加しましたか?

 11. コミットする前に適切なファイルを git add しましたか?

 12. 単独で、つまり configure --disable-everything --enable-decoder=foo で(または --enable-demuxer、あるいは当のコンポーネントが何でも) コンパイルが通ることを確認しましたか?

パッチ提出チェックリスト
============

 1. そのパッチを適用して make check が通りますか?

 2. そのパッチは最新の Libav git master branch に対するものですか?

 3. libav-devel (https://lists.libav.org/mailman/listinfo/libav-devel) メーリングリストを購読していますか? (リストは購読者のみ投稿できます。)

 4. その変更が最小であること、そのためより小さなパッチや/またはより単純な最終的なコードでは同じことが達成できないことを確認しましたか?

 5. その変更が重要なコードを速くするためのものなら、それをベンチマークで測りましたか?

 6. そのパッチがバッファオーバーフローまたは他のセキュリティの問題を持ち込まないことを確認しましたか?

 7. decoder または demuxer を壊れたデータでテストしましたか? していない場合は tools/trasher や noise bitstream filter を見てください。decoder や demuxer は壊れたデータを入力された際にクラッシュしたり無限ループ(に近い形)で終わるべきではありません。

 8. そのパッチには機能的な変更と表面的な変更を混ざっていませんか?

 9. タブまたは行末の空白をコードに加えましたか? どちらも禁止されています。

 10. そのパッチはあなたが送るメールに添付されていますか?

 11. そのパッチの mime type は正しいですか? それは text/x-diff または text/x-patch であるべきで、text/plain は許されますが、application/octet-stream は許されません。

 12. そのパッチがバグを修正しているなら、そのバグの詳しい分析を与えましたか?

 13. そのパッチがバグを修正しているなら、サンプルを含めた十分な情報を与えており、そのためバグを再現することができ修正を調べることができますか? 100kを越えるサンプルをメールに添付するのではなく、代わりに URL の形で提供するように注意してください。ftp://upload.libav.org にアップロードできます。

 14. そのパッチが変更することについて詳しい要約を与えましたか?

 15. そのパッチがそのように変更を行う理由について詳しい説明を与えましたか?

 16. そのパッチが適用された場合にユーザーから見える利点と欠点についての詳しい要約を与えましたか?

 17. そのパッチによって追加される新しい機能を簡単に調べられるよう例を与えましたか?

 18. ベンチマークを取ったなら、それをメールの中で与えましたか?

 19. 新しいファイルを追加したなら、ライセンスヘッダーを入れましたか? それは Libav から取ってこられるべきで、どこか他からでたらめにコピーアンドペーストされるべきではありません。

 20. API/ABI 互換性を壊さない限り、アルファベット順に並んでいるリストではその順序を維持するべきです。

 21. そうすることで可読性が改善される場合には、似た内容の行は垂直に並べられるべきです。

 22. 関数の戻り値を確認し、適切なエラーコードを返すようにしてください。特に、malloc() のようなメモリを確保するための関数はよくチェックされないままになっており、これは深刻な問題です。

パッチのレビューの過程
===========

libav-devel (https://lists.libav.org/mailman/listinfo/libav-devel) に投稿された全てのパッチはレビューされるでしょう、そのパッチが git master branch 向けでないという明確な注意が含まれていない限り。レビューとコメントはパッチへの回答としてメーリングリスト上に投稿されます。そしてパッチの提出者は全てのコメントに対処しなければならず、それは変更したパッチの再提出や議論によってなされます。パッチの再提出はそれ自体他のパッチと同様にレビューされます。どこかの時点でコメントなしでレビューを通過したら、それは承認されます。これは単純で小さなパッチについてはすぐに起こるでしょうが、大きなパッチは一般的に承認される前に何回も変更されそしてレビューされるに違いありません。パッチは承認された後でレポジトリにコミットされるでしょう。

我々は全ての提出されたパッチをレビューするでしょうが、ときおりとても忙しく、特に大きなパッチに対しては数週間に及ぶことがあります。

パッチを再提出する際、そのサイズが多大きくなったりレビューの過程で異なる問題が持ち上がったりしたときには、それぞれの issue に個別のパッチになるようにそのパッチを分割してください。

回帰テスト
=====

パッチを提出する(またはレポジトリにコミットする)前に、少なくともそれが何も壊さないということを確実にするべきです。

変更されるコードについて既に FATE にテストがあるなら、それを実行するべきです。そうでなければテストを追加するべきです。

コーデックまたはデミュクサーに対する改善は FATE の結果を変えてしまうことがあります。その変更を参照する更新をコミットすることと、なぜ予期される結果が変わるかをコメントで説明することを必ずしてください。

fate.html を参照してください。