exB - extreme B-AREA -

無敵の中年男性!的確な中年男性!難攻不落の中年男性!

お勉強:マルチメディア - 動画再生のきほん

世に出回ってる動画ファイルはずいぶんいい加減なものが多い。

初稿:2005年くらい2013-03-06 大幅加筆修正2013-03-17 記事分割

いくらなんでも長すぎたので4つに記事を分割しました。

はじめに

説明ふっ飛ばしてとにかく再生できればいいって人は動画再生の便利ツールへ直行。Mac のことはわからません

もともとは「ネットで拾った動画が再生できねえ!どうしたらいいんだよ!」(知るかボケ)なんて相談がいっぱい舞い込んできた頃、その都度チャットなりメッセンジャーなりで説明するのがめんどくさくなったので「ここ読んで必要なツール入れろ(棒」のために書き出した。

書いてるうちに、自分でもよくわかってなかったことがいっぱいで詳しく調べはじめたんだけど、だんだん当初の目的から外れてきて、わし自身が正しい認識と理解を得るための備忘録となり、もはや初心者入門の内容ではなくなってしまった。でもたまーに「よくわかった!」(ほんとかよ!)なんて声があるのでがんばって加筆し続けるのだ。

そんなわけで、理屈をちゃんと理解したい人には多少役に立つかもしれないが、わしはプログラマでもエンコ職人でもなく、純粋に至高のオナニーを追及する誇り高き独身中年男性であり、本稿は“様々なエロ動画の再生で躓かないための20年に渡る知識の備蓄”であることをお断りしておく。

エンコードとデコードの必要性 [Encode/Decode]

Encode は符号化。符号化とは「B地区マンセー!」といった可視情報をQuWcsOWMuuODnuODs+OCu+ODvO+8gQ==といった符号に変換すること。Decode はその逆で、符号化された情報を可視情報に戻すこと。つまり圧縮と解凍みたいなもの(あくまでも“みたいなもの”だからな)。これがデータ圧縮の基礎。

厳密には、文字や画像,音声といった様々な情報をコンピュータで扱える単位に変換する作業が符号化。

連続した情報を一定の間隔で取り出すのがサンプリング(標本化)

符号化された情報はそのままでは意味を成し得ない。これを符号化の逆手順でもとに戻す作業が復号化。ディスプレイに表示された JPEG ファイルやスピーカーで鳴ってる MP3 ファイルは、符号化された情報を視覚情報や音声情報に復号化されたもの。

なかでも動画というのは情報量がメチャメチャいっぱい必要で、データがバカでかくなる。いろんな仕組みでもってデータサイズを縮小してあげないとパソコンで扱いにくいことこの上ない。これが動画におけるエンコード。再生時には圧縮に使ったのと同じ仕組みを逆にしてあげる。これがデコード

非圧縮状態のデジタル映像データ(RAW データ)に必要な情報量がどれくらいになるかというと、例えば画面サイズが 640x480ピクセル な VGA の場合、最低でも 640*480=307200 個の情報が必要になる。サイズにすると 307200bit=37.5KB。TV の一般的なフレームレートである 29.97 コマ/秒を掛けてやると1秒の映像は約 1.1MB になる。ちなみにこれで表現できるのは黒白2色(しかも2階調)。24bit フルカラーだと約 26MB/s(約 200Mbps)、1時間で約 90GB にもなってしまう(ちなみに音声は含まれていない)。さらに Full HD(1920x1080)ともなると情報量は VGA の 6.75倍、実に 180MB/s にもなる。何らかの仕組みでもって圧縮しないとどうしようもないのがわかってもらえると思う。

…裏を返せば、1)十分にストレージ容量に余裕があり、2)ストレージから視聴環境への帯域~これにはローカル環境のバスも含まれる~も十分に確保されていて、3)なおかつ大量のデータをスムースに扱える処理能力が伴っていれば、わざわざ圧縮する必要はない。つまりエンコードの本質は対象とする環境に合わせて転送レートを調整することにある。要は帯域管理で、ここを誤解している人は非常に多い。

同様のことはネット配信にもいえる。再生側からみたストリーミングとプログレッシブダウンロードの最大の違いは配信側が帯域管理をするかしないかである。ただし最近は HTTP ストリーミングのようにウェブサーバでも擬似的な帯域管理を行うケースもある(リクエストに応じてレスポンスのファイルを変えるだけなので厳密な帯域管理ではない)。

余談

RAW は「ナマ」という意味で、IT の世界では手の加えられていない非圧縮の状態を指す。写真が好きな方(オレ)であればデジカメの撮影でも RAW というのを耳にしたことがあるかもしれない。弊害があってもやはりナマに限る、というお話(ピュア。

なおアナログ映像は仕組みが根本的に異なるので比較が難しい。そもそもアナログの定義は連続的な物理量であるため原理的にはオリジナルを忠実にコピーすることが可能であるが、その精度は記録/再生する機器の性能に依存するため、オリジナルと完全に一致する記録/再生は現在の技術では不可能である。デジタルの定義は不連続な情報ゆえ、当然ながら存在しないものの再現はできないが、存在する情報であればアナログよりもずっと高い精度で取り扱うことができる、といった感じ。

再生の流れ

Windows ベースのお話なので他の OS でどうなってるかはわからないけど大筋は同じと思う。たぶん。

構成要素と基本構造

コーデック [codec]
Encode / Decode を行うプログラム。符号化と復号の仕組みのこと。再生時に必要なのは復号するデコーダーだけでよいので、一般にコーデックというとデコーダーを指すことが多く、またデコーダーについては無償提供されているものも多い。自分で動画を作成する場合には符号化プログラムであるエンコーダーも必要となる。また映像と音声は別々に記録されるためエンコードもそれぞれ行われる。つまり映像と音声それぞれにコーデックが必要、ということ。
・・・コーデックは Compression / Decompression (圧縮/伸長)の略という説明もあちこちで見かけるが、コーデックは別に動画圧縮だけを指してるわけじゃないので符号化されたデータが必ずしも圧縮されるとは限らない。たとえば冒頭で例にした SMTP などで用いられる BASE64、イーサネットや USB 3.0 で使われている 8b/10b など符号化後のほうがサイズが大きくなる方式も存在する。そのため Encode / Decode もしくは Coder / Decoder の略のほうがふさわしいように思う。
参考:UIC|BASE64

8b/10b エンコードにおいて実際のデータは物理層を流れるデータ 10 のうち 8 で、残りはシリアル転送で同期用の信号(クロック)を埋め込むことによるオーバーヘッド(8bit のデータを 10bit に伸長するから 8b/10b )。つまり 100BASE-T の実効速度はワイヤスピード(100Mbit)に対し 0.8 = 10MB/s が理論上のリミットとなる。たまーに「 15MB/s 出た!」とかわけのわからないこといってる人いたけど単にキャッシュ拾ってそう見えてるだけだから。実際には 8MB/s 出たら上出来よ。ちなみに USB3.1 や PCI Express 3.0 ではオーバーヘッドを軽減した 128b/130b が採用されている。これまでの説明でわかると思うが、128bit のデータに対して 2bit のクロックを埋め込むので実効速度はワイヤスピードの 0.984615385 と大幅に効率が良くなっている(精度はシビアだろうが。

コンテナ/ファイルフォーマットとストリーム
符号化(エンコード)された映像や音声の連続した並びはストリームと呼ばれ、最終的にひとつのファイルに収められる。この映像と音声を格納するための器・・・言い換えればファイル保存形式がコンテナで、コンテナに格納された映像データと音声データ、というのが動画ファイルの基本構造。これはしっかり頭に入れておくこと。
コンテナに格納することでストリームの組み合わせの柔軟性や拡張性が高まり、各種メタ情報の扱いも楽になる。NTSC や PAL といったロケーションの違いを吸収するのもコンテナの役目だ。コンテナ内のストリーム格納場所がトラックで、多くのコンテナは映像と音声で最低でも2つのトラックが存在する。DVD や Blu-Ray の吹き替えとオリジナル、エディターズノートなどのように3つ以上のストリームを格納できるものはマルチトラックと呼ばれる(DVD や Blu-Ray はコンテナとは違うが、ひとつの器の中の格納場所という点では同じ)。
映像や音声にどんなコーデックを使えるのかはコンテナによって決まっているので好き勝手な組み合わせをしてよいわけではない。しかし困ったことに、ときどきこれを無視して未対応の映像や音声が格納されていることも(もちろん仕様に反するのでトラブルの元でしかない)。AVI コンテナと VBR の組み合わせはその代表例だろう。
なお、放送業界やビデオ撮影分野ではラッパーという呼び方が定着しているが、コンテナと同義と思ってよい。多重化についてもラッピングで通っている。

これは憶測だけど、コンテナ=箱ではなくラッピング=包むなのは、原理的に一度の撮影や放送で扱うストリームを複数の器に格納するという概念自体がなかったことが大きく影響しているのではないか。ポスプロ作業でもデスクトップでノンリニア編集が一般化するまでは 1ソース 1テープ、コンテナはまさに物理的な箱だったわけで。

スプリッタ [spriter]
実際に動画を再生するには、デコードの前にまずコンテナに格納されているデータを映像と音声に分ける作業が必要となる。この切り分けを行うのがスプリッタで、コンテナによってスプリッタも異なる。ソースフィルタと呼ぶこともある。

厳密にはスプリッタのさらに前段階で配信なども含めた様々なデータを受け入れる窓口となってソースの違いを吸収するのがソースフィルタだが、ASF リーダーをはじめソースフィルタとスプリッタ両方の機能を受け持つフィルタも多いため、本稿ではあえて分けないことにした。

DirectShow と DirectShow Filter

※これは完全に Windows 依存の話。

コンテナから映像と音声を取り出してデコードする一連の処理を再生ソフトがすべて受け持つのは、スプリッタやデコーダーの多さや新しいコーデックへの対応を考えるとあまり頭のいいやり方ではない。あらかじめスプリッタやデコードの機能を取りまとめる窓口を用意し、この窓口とやりとりすることで再生ソフトの処理を一部肩代わりしてもらうほうが全体の見通しもよくなる。この窓口の仕組みが DirectShow、スプリッタやデコーダーが窓口に提供する機能が DirectShow Filter である(んまあ、スプリッタやデコーダーと同じ働きと考えていい)。デコードされた映像を実際に描画するレンダラーや音声の出口となる Default DirectShow Device も含めて、重ね合わせたフィルタのように順次処理が行われている。

整理すると DirectShow はソースファイル→ソースフィルタ/スプリッタ(パーサ)→デコーダー→レンダラー(※映像の場合)という一連のデータの流れで、スプリッタやデコーダーなどの機能はフィルタとして適用される。DirectShow は再生支援の仕組みや手順、スプリッタはコンテナから映像と音声のデータを取り出して分離するもの、コーデック(デコーダー)は符号化された映像や音声をもとに戻すもの、DirectShow Filter は DirectShow におけるスプリッタやデコーダーの呼び名ってこと。

DirectShow の流れ(上は映像、下は音声)、ざっくりいうならこの逆がエンコードになる

DirectShow による一連の流れでどのようなフィルタが使われているかは Microsoft 純正ツールの GraphEdit で調べることができる。ただこれ Windows SDK(ソフトウェア開発キット)の同梱物なんだけど SDK は 500MB くらいあるんだよね(XP 版の場合、Vista 以降だとさらにデカいはず)。本格的な開発をするわけじゃないなら互換ツールの GraphStudio でいいと思う。

たぶん DirectShow が何をやってるか理解できるかどうかが、子離れ(何)できるかどうかの境界線ではないか。オレ様の適当な殴り書きよりきちんとした説明をしているサイトはたくさんあるから、正確に理解したいならそっちを見たほうがよい。このへんとか。

なお DirectShow は Windows 依存要素だけど、コンテナからストリームを取り出しデコードするのはプラットフォーム関係ない共通手順なので、Mac なら Mac、UNIX なら UNIX 用のスプリッタとコーデックは必要になる。

Media Foundation について

DirectShow の後継 API として、Windows Vista から Media Foundation が導入されている。COM ベースとなり DirectShow よりも I/O 処理などのパフォーマンスが向上しているほか、より強力な DRM とか DRM とか DRM がウリなので男爵的には不安いっぱいなのだが、デスクトップ OS の主流が完全に Windows 7~ に移行するまではコンテンツプロバイダが DirectShow を見捨てることはないと勝手に思ってる。

2014年4月追記:

とうとう XP に死亡宣告がなされた。Windows の主流は完全に 7/8 となりナインをふっ飛ばして 2桁時代に入らんとするこの頃。

かつて DirectShow が登場したときは Video for Windows≒AVI の限界が明確だったし、DirectShow を標準採用した Windows 98 への乗り換え需要も大きかったこともあって自然と移行も進んだけど、VfW≒AVI もまた根強い支持がありハッキングによる延命が施されてきた。対して今回は消費者にとって別に困ってることがないのよね・・・ DirectShow はそれなりに完成した仕組みだし今のところどうしても Media Foundation を使わないといけないのは DXVA2 くらいで、むしろ Media Foundation 対応のコーデック開発が遅々として進まないことこそ困りもの。

ま、いずれは DirectShow は Media Foundation によって置き換わるんだろうけど、当面の間は二刀流が続きそうで。

参考:MSDN|メディア プラットフォーム

2015年8月追記:

思い切って Windows 10 にアップグレードしたが、標準APIが Media Foundation であることに変わりはないので、各種フィルタ関連の事情は7環境と同じとみてよさそう。

要点をまとめると、Windows のマルチメディアフレームワークには DirectShow と Media Foundation があり、それぞれ 32bit / 64bit が存在するよ(コーデックとそれを利用するソフトウェアでちゃんと合わせないと使えないよ、というお話。

そのほか再生における基本事項

多重化と分離

動画において映像と音声は別々に記録(符号化)される。この符号化された映像&音声のストリームをひとつの回線やコンテナに格納することを多重化と呼ぶ。英語では Multiplexing(マルチプレクサ)で、単に Mux で通る(結合ではないことに注意)。逆にコンテナからストリームを抽出するのが分離で英語では Demultiplexing(デマルチプレクサ)、やはり Demux で通る。

上記図解に示すとおり異なるコンテナどうしをくっつけるのが結合( Concat )で、要するに“連結”と思えばよし。多重化と分離( Mux と Demux )はコンテナを扱う際の必須概念だけどネットを見渡すと多重化と結合の区別がついていないような人がかなり多い。ソフトウェアの紹介記事ですら混同してるものもあるので、ツール選びの際に間違えないよう。なお結合の逆で多重化における分離に相当するのは分割( Split )となる。

多重化・分離はコンテナの出し入れなので基本的にストリームそのものには手を加えないが、複数のソース映像をひとつのストリームにすることもできる。その場合コーデックはもちろん解像度やビットレート、使用アルゴリズムなどのプロファイルが厳密に一致している必要がある。これは結合でも同じ。

というか異なるコンテナのストリームを単一のコンテナに格納するのが結合なのでその過程で分離と多重化も必ず発生する。一度結合してしまうと結合前の個別のストリームに再分離するのは難しい(結合ポイントをフレーム単位で指定し分割できるツールもあるが、それはもはや分離ではない)。

多重化にしても結合にしても映像と音声の同期がポイントになってくるけど、コンテナとストリーム(コーデック)の組み合わせによっては音ズレしやすいものもある。特にタイムコードの概念がないコンテナと可変ビットレートや可変フレームレートの組み合わせは同期の難易度が高い。タイムコードについては MPEG の基本で触れてるのでそっちも参照のこと。

FourCC について

もうひとつ大事なことがあった。DirectShow にしても何にしても、あるファイルで映像コーデックに何が用いられているのかわからないとどうしようもない。これを判別するための識別子として白羽の矢が当たったのが FourCC で、その名の示すとおりファイルのヘッダに 4文字の ID が埋め込まれている。たとえば H.264/AVC なら“AVC1”といった具合に。

FourCC は RIFF 形式におけるデータフォーマット識別子で、別にコーデック判別が目的で作られたものではないのだが、事実上コーデック識別子としての利用が中心となっている。

再生プログラムはこの4文字を見てコーデックを判断し、デコーダーを選択するわけ。FourCC が間違ってたら当然正常に再生はできないけれども、普通はエンコード時に勝手に設定されるのでバイナリエディタで編集でもしない限り問題ない・・・はず。

FourCC はコーデック単位で定義されているため、たとえば DivX もバージョンによって FourCC は異なるし、“原則として”同じコーデックに異なる FourCC が割り当てられることもない(そのことをちゃんと理解していれば FLV5 で散々悩むことなどなかった)。

なお拡張子はコンテナの種類を識別するための人間向けの目印で、システム的にもファイルを実行するアプリケーション選択の目安でしかない。要するにファイル名の一部でしかないんだから名前=拡張子を変えただけでコンテナの種類やファイルの中身まで変わるなんてことはないのはちょっと考えればわかることかと。

音声の識別子

FourCC で定義されているのは映像コーデックの識別子で、音声は含まれない。音声は映像の FourCC のようなわかりやすい統一基準がないようで、いくら調べてもわからない。とりあえず 0x0000 形式の FormatTag や codecID 、GUID などによって判断されているようだ。

参考:Supported codecs and format of their CodecPrivate blocks PDF

参考記事

他の章の題材も含める。追記ありの記事は信頼性が高いけど、古くなって当たり前くらいの心持ちで読むほうがよい。

あと、ソースや外部リンクのない、己のページビュー稼ぎに必死になってるような記事はどれほど秀逸でもなんかムカつくので取り上げてない(そういうポリシーで秀逸な記事はほとんどお目にかかれないがねw

GOM Player|動画の知識
初心者向け解説としてはよくできてるし、こういうコーナーを設けるのは良心的と思う。
TMPGEnc-LABO
わしが愛用している TMPGEnc シリーズを作っている株式会社ぺガシスのおべんきょうコーナー。
妖精現実フェアリアル 記事アーカイブ
Ogg/Matoroska 系の経緯を把握するのに非常に参考になった。後日追記(これは、とても、重要だ)も多くかなり信頼できる。
ageha was here
動画を勉強すると一度は訪れるんじゃないだろうか。すでに更新は放棄されている。慣れないとコンテンツの並びがわかりづらい。語り調子も独特だけどMPEG-4までの知識や情報を一通り把握できるほか、心構えも身に付く。動画エンコードのアプローチには是非目を通しておくべき。
LostTechnology|Movie
うちと似た切り口でうちよりもずっとわかりやすい。作り手の伊織舞也氏からは、なんとなくわしと同じ臭いを感じる。
2ちゃんねる | 【AVI/ASF/MKV】最強コンテナ決定戦【MOV/MP4/OGG】
2007年のスレだけど未だに生きてる。あまり荒れずに進行してるし時折硬派な書き込みもあるので一読の価値あり。
MSDN | AVI ファイル フォーマット
開発者向けだけど、ちゃんと取り組むなら目を通すべきだ。

なるべく一次情報かそれに準ずるソースに基づいて記述するよう心がけてるけど、間違ってたら教えて。

脚注

物理層
コンピュータが持つべき通信機能を階層構造に分割した OSI 参照モデルにおける第一層。電波やメタルケーブル、光ファイバーなどデータの流れる媒体と、ビット転送を行うためのコネクションを確立・維持・解放する手段を規定する。
またフレーム / パケット / セグメントなど、各階層ごとに扱いやすいサイズに分割されたデータのカプセル化が行われる。
その際ヘッダ情報が加えられるぶん本来のデータよりもサイズが増える。従来よりも分割(カプセル化)するサイズを大幅に増やしたジャンボフレーム・ジャンボパケットなども登場しているが、どのみち物理層で確実にオーバーヘッドが発生するので実効速度が理論値の 100パーセントは事実上不可能(研究室などの実験用に一発勝負なポイント・ツー・ポイントの専用設備を作ればできるかもしれない)。ちなみに OS が拾っているのはデータリンク層よりも上のデータ。