mp4の構成要素
MP4ファイルはBoxとよばれる要素の木構造で構成されている。このBoxはMP4を構成する要素の中で最小単位であり、Atomと呼ばれる。子をもつBoxはContainer boxとも呼ばれる。ちなみにもともとQTFFの方でAtomと呼ばれていて、QTFFを元にMP4が作られたのでそのまま名残でMP4でもAtomと呼ばれているようです。
mp4のBoxは必ずftypeと呼ばれるものから始まり、それ以外のBoxの並び順は、VODで配信する場合はどのような並び順でもOK。だがLODで配信する場合は最初にメタデータを読み込んでから実際のデータを処理する必要があるので、先にmoovという、メタデータが記録されたBox(後述)をロードする必要がある。
Boxの基本構造
- HeaderとData部分で構成される。
- 先頭のオクテット(8Byte)がボックスを識別するためのHeaderになっている。
- オクテットの中でも、最初の4ByteがBoxSize、最後の4ByteがそのType(BoxType)になる。
- このBoxTypeの部分に、
ftype
,pdin
,moov
などのBox固有のIDがASCII文字列で入る。
- Data部については、HeaderのBoxSizeにBox全体のサイズが入っているのでHeaderの終わりからBoxSizeて定義されている位置までがBoxDataになる。
- Headerのサイズは8Byteなので
BoxSize - 8Byte = DataSize
となる。
- Headerのサイズは8Byteなので
ISO/IECでのBox構造定義
aligned(8) class Box (unsigned int(32) box type,
optional unsigned int(8)[16] extended_type) {
unsigned int(32) size;
unsigned int(32) type = boxtype;
if (size == 1) {
unsigned int(64) largesize;
} else if (size == 0) {
// box extends to end of file
}
if (boxtype == 'uuid') {
unsigned int(8)[16] usertype = extended_type;
}
}
以下にmp4のBox一覧を列挙してみる。rootのBoxについてはこれで全部ですが、子要素のBoxは以下に記載しているもの以外にもたくさんあります。ちなみに、特にmoov内のstblがキモになってくる。
sample.mp4
├ ftyp
├ pdin
├ moov
│ ├ mvhd
│ ├ trak(movie)
│ │ ├ tkhd
│ │ ├ tref
│ │ ├ edts
│ │ | └ elst
│ │ └ mdia
│ │ ├ mdhd
│ │ └ minf(Media Information Box)
│ │ └ stbl
│ │ └ stco
│ ├ trak(audio)
│ │ └ ...trak(movie)のchildrenと一緒
│ ├ trak(hint)
│ ├ mvex(extended box)
│ └ ipmc(hint)
├ moof
│ ├ mfhd
│ └ traf
├ mfra
├ mdat
├ free(free space)
├ skip(free space)
│ └ udta(user data)
└ meta
以下にファイルのrootに配置されるボックスについて書いてみる。
ftype(File type)
ファイルがどのtypeに準拠しているかを表す。Boxの並び順としては一番最初に配置されている必要がある。
構造
aligned(8) class FileTypeBox
extends Box(‘ftyp’) {
unsigned int(32) major_brand;
unsigned int(32) minor_version;
unsigned int(32) compatible_brands[]; // to end of the box
}
ftype一覧: http://www.ftyps.com/
minor_version
はmajor_brand
のマイナーバージョンを定義するみたいですが、ほぼ活用されないようなので全部0で埋めても問題ないケースが多いようです。
compatible_brands
は互換性があるmajor_brand
を列挙できるみたいですが、こちらも必須ではないようで、空白でもいけるようです。
moov
moovボックスの中には動画のメタデータが定義されていて、その配下にtrak、mvhdボックスなどのボックスが入れ子になっている。
動画・音声のメディアデータをそれぞれ1trakとし、「movieのtrak」「audioのtrak」というように複数のtrakが同じ階層に配置される。
DRMを扱う場合は、複合の際に使うPSSHなどといったデータもこのボックスに格納される。
trakでは、動画・音声データがどのように配置されているかを記録していて、再生する際はこのtrakの情報を元にメディアデータをシークする。そのため、LODではmoovボックスが最初に読み込まれる必要がある。
そしてtrak配下のmdhdではトラックのメタデータや再生時間などを定義している。
mdat(Media data box)
メディアデータを格納するBoxで、動画・音声両方を格納できる。
mdatをデコードするには、moov -> trak -> mdia -> minf -> stbl配下のメタデータをパースする必要がある。このstbleを読み解くために、他の諸々のBox定義も理解しないといけなくてなかなか難しいらしい。
ユーザー定義Box
記事上部に記載したBox構造を見てみると、Boxではオプショナルでextended_type
というものが定義できる。
ユーザー定義のBoxを使うときはBoxTypeにはuuid
を指定し、extended_typeではユーザが任意に作成した16Byteのuuidを格納する。するとBoxDataでは自由なデータを指定することができ、ユーザー定義Boxとして使うことができる。
Full Box
FullBoxの定義
aligned(8) class FullBox(unsigned int(32) boxtype, unsigned int(8) v, bit(24) f)
extends Box(boxtype) {
unsigned int(8) version = v;
bit(24) flags = f;
}
FullBoxとは、Boxを拡張してversionとflagフィールドをヘッダーに持てるようにしたもの。実際に扱われるのはFull Boxが多かったりする。
参考文献
- ISO/IEC
14496-12 - https://standards.iso.org/ittf/PubliclyAvailableStandards/c041828_ISO_IEC_14496-12_2005%28E%29.zip - unoh.github.com by unoh - https://unoh.github.io/2007/09/12/mp43gpp3gpp2.html