Introduction
- 在《AVFoundation开发秘籍》中有提到「苹果公司在 QuickTime File Format Specification 文档中对其细节进 行了详细描述,可在Apple Developer Connection网站上找到该文档。我们建议所有 AV Foundation 开发者都应该至少阅读上述文档中基本知识点的介绍章节,因为了解 相关的知识对之后的应用程序开发有帮助。 p.16」
- 该文档的地址是Introduction to QuickTime File Format Specification
- 本篇文章是对于“Overview of QTFF”这一章节阅读完之后的总结归纳,会标记出重要的关键点,以及对于文档中的图片进行解释,建议读者可以阅读完该文档后再阅读本文。该文档涉及到的一些名词我并没有找到合适的翻译,因此会直接使用英文原文
Media Description
- QuickTime文件存储着媒体的描述(可以被称之为- movie resource,- movie atom,- the movie)
- 描述信息包括音轨数,视频压缩格式,timing information(直译为定时信息),描述媒体数据在哪里存储的索引- 媒体数据是实际的采样数据(在信号处理领域,采样是将信号从连续时间域上的模拟信号转换到离散时间域上的离散信号的过程,以采样器实现。通常采样与量化联合进行,模拟信号先由采样器按照一定时间间隔采样获得时间上离散的信号,再经模数转换器(ADC)在数值上也进行离散化,从而得到数值和时间上都离散的数字信号。很多情况下所说的“采样”就是指这种采样与量化结合的过程),例如视频帧和音频采样
- 媒体数据可以以多种种存储方式存储
- 与描述文件同一个的的QuickTime文件
- 单独文件
- 多个文件
- 数据库
- alternate sources
- 上述文件的组合
 
- 与描述文件同一个的的
 

Atoms
- atom是- QuickTime文件中的基本组成单位
- 每一个atom都有大小字段和类型字段(类似于元数据)来表述atom的字节数以及类型,这些内容会放在任何其他信息之前
- 在某些情况下,在大小和类型之后还会跟着版本,标志字段。拥有这两种字段的atom有时候被称之为full atom
Atom Layout
- Atoms是分层级关系(有些类似于树状结构),一个- atom可以容纳其它的- atom,容纳其它- atom的- atom被称之为- container atom。- Atoms之间的关系同样可以使用父子,兄弟来表述,一个- parent atom一定是一个- container atom,并且层级高于给定的子- atom。类似于树状结构,一个不包含任何- atom的- atom被称之为- leaf atom,通常以一个或多个字段或表的形式包含数据,有些- leaf atom会充当标志或占位符,除了它们的大小和类型字段之外不包含任何数据。
- atom中存储的数据类型不仅是由该- atom的类型字段来决定,也要考虑该- atom的- container atom的类型

- 如图中展示,两个container atom进行嵌套,最里面一层为leaf atom,其中在大小字段和类型字段之后就是数据
- atom一般不需要按照特定顺序进行排列,除了某些特定顺序(e.g.,描述- atom必须在信息- atom之前)
Atom Structure
- 除了大小,类型字段之外,在数据之前可能扩展的大小字段,将一个large atom的掉定义为64位整数。如果使用了扩展的大小字段,则必须把大小字段设置为1。atom实际大小不能小于8字节(类型和大小字段的最小大小)
header fields introduction
- 
Atom size(大小) - 32位无符号整数,表示atom的大小,包括头部与内容以及内部包括的atom
- 大小字段可以包含一些特殊值用于确定atom大小- 
0:仅用于顶级 atom,指定文件中的最后一个atom,并表示该atom扩展到文件的末尾
- 
1:表示使用了扩展的大小字段,扩展大小字段是一个可选的64位字段,在type字段后面,可以容纳包含超过2^32字节的媒体数据 atom 
 
- 
 
- 32位无符号整数,表示
- 
Type(类型) - 32位整数用于表示atom的类型,通常使用ASCII值的四字符字段来表示(e.g.,0x6D6F6F76 = ‘trak’ 0x6D6F6F76 = ‘moov’),非ASCII情况同样存在
- 了解atom的类型可以对数据进行解析,数据可以是字段,表活其它atom的任意组合
- 当遇到位置类型的atom的时候,合理做法是使用atom的大小字段来直接跳过着整个atom以保证一定的向前兼容性(这个优点原文档强调了三遍)
 
- 32位整数用于表示
- 
Extended Size(扩展大小) - 当大小字段被设置成1的时候生效
- 64位无符号整数
 
- 
⚠️: atom内部结构可能在新版本中被改变,时时检查version字段。不要解析大小/扩展大小字段之外的数据
wide atom
- 由于在数据小于2^32字节时,不会使用扩展大小字段(也不提供这个字段),因此扩展atom超出这个限制是一个不太秒的操作,会导致覆盖后面的数据内容,因此引入了一个64位的占位atom,类型为kWideAtomPlaceholderType ('wide')。在有该atom的情况下,可以对前一个atom进行扩展使其超过限制(直接覆盖这个atom),将原atom的大小字段设置成1,并且增加一个扩展大小字段
- wide atom大小为8个字节,只有大小和类型字段,不包括数据。它仅仅是一个占位- atom,可以被覆盖
QT Atoms and Atom Containers
- QT Atoms是一种增强的,更加通用的存储格式,在大小和类型字段后增加了ID和- 子atom计数
- 通过ID可以制订统一类型的多个子atom,也可以解析未知类型的子atom通过遍历子atom树
- QT Atoms通常被包装在- atom container中(⚠️:- atom container与- container atom不是同一种东西,前者不是一个- atom),并且作为- root atom(- root atom总是存在且不包含兄弟姐妹),可以在某些- atom中发现- atom container作为了数据结构。- container atom以一个- QT Atoms header开始,后面是- atom的内容(- child atoms与- data二选一),如果一个- atom包括子元素,那么它也包含子元素的所有数据和子元素
QT atom container header

| Name | Interpretation | 
|---|---|
| Reserved | 必须设置为0的10字节元素 | 
| Lock count | 必须设置为0的16位整数 | 
| Size | 一个32位整数,以字节表示 atom的大小,包括QT Atoms header和atom的内容。如果atom是leaf atom,那么这个字段包含单个atom的大小。container atoms的大小包括所包含的所有atom。您可以使用size和子计数字段遍历atom树 | 
| Type | 一个32位整数,包含 atom类型。如果这是root atom,类型值设置为’sean' | 
| Atom ID | 一个32位整数,包含 atom的ID值。这个值在它的兄弟姐妹之间必须是唯一的。root atom总是有一个atomID值为1。 | 
| Reserved | 必须设置为0的16位整数 | 
| Child count | 一个16位整数,指定一个 atom所包含的子atom数。这个计数只包括直系子节点。如果该字段设置为0,则该原子是leaf atom,只包含数据 | 
| Reserved | 必须设置为0的32位整数 | 
QT Atom Containers

- QT Atom Container是- QuickTime中存储文件的基本结构,一个- atom container是- QT Atoms的树状结构层次结构。您可以将新创建的- QT Atoms container视为不包含子元素的树结构的根
- 每个QT Atoms都有一个偏移量,该偏移量描述了该atom在QT Atoms container中的位置。此外,每个QT Atoms都有一个类型和一个ID。该类型描述了该原子所表示的信息的类型。ID用于区分具有相同类型和相同父atom的子atom;对于给定的父类和类型,atom的ID必须是惟一的。除了atomID之外,每个atom都有一个基于1的索引,该索引描述了它相对于具有相同atom类型的相同父atom的其他子atom的顺序
- 以下三种方法之一唯一地标识QT Atoms:- 通过它在其QT Atoms container中的偏移量
- 通过其父atom、类型和索引
- 通过其父atom、类型和ID
 
- 通过它在其
- ⚠️:由于QT Atoms是数据结构中的偏移量,因此可以在QT Atoms container上的编辑操作(例如插入或删除atom)期间更改它们。对于给定的atom,编辑子atom安全的,但是编辑父atom或兄弟atom会使该atom的偏移量失效

- 大多数QT Atoms函数采用两个参数来指定特定的atom:包含atom的atom container,以及atom container数据结构中的atom偏移量。您可以通过调用QTFindChildByID或QTFindChildByIndex来获得atom的偏移量。如果包含该偏移量的QT Atoms container被修改,该偏移量可能会失效
- 在调用任何指定父atom作为参数的QT Atoms函数时,您可以传递常数kParentAtomIsContainer作为atom偏移量,以指示指定的父atom是atom container本身。例如,您可以调用QTFindChildByIndex函数,并为父atom参数传递kParentAtomIsContainer常量,以表明所请求的子atom是atom container本身的子atom
QuickTime Movie Files
- QuickTime Movie Files格式描述了- QuickTime Movie Files的特征。- QuickTime Movie Files包含- QuickTime Movie资源,或者指向一个或多个使用电影引用的外部源。电影使用的媒体采样(例如视频帧或音频采样组)可以包含在电影文件中,或者可以位于一个或多个文件、流或其他源中的- Movie Files的外部
- QuickTime Movie并不局限于视频和音频;它可以使用QuickTime支持的任何媒体类型的子集或组合,包括视频、声音、静态图像、文本、Flash、3D模型和虚拟现实全景图。它支持基于时间的和非线性的交互媒体
- 在支持文件名扩展名的文件系统中,QuickTime Movie Files的扩展名应该是.mov。在Macintosh平台上,QuickTime文件的Mac OS文件类型为“MooV”。QuickTime Movie Files应该总是与MIME类型“video/ QuickTime”相关联,无论电影是否包含视频。
- QuickTime Movie Files的结构是一组- atom的集合,这些- atom一起将该文件标识为QuickTime电影,描述电影的结构,并可能包含播放电影所需的采样数据。并不是所有的- atom都是必需的
- 文件格式是可扩展的,并且不时会引入新的atom类型。如果您的应用程序在QuickTime文件中遇到未知的atom类型,它应该简单地忽略它。这允许在不破坏现有应用程序的情况下扩展文件格式,并提供向前兼容性的度量。因为任何atom中的第一个字段都包含它的大小(包括所包含的任何atom),所以很容易跳到未知atom类型的末尾并继续解析文件。
- 要点:一般来说,atom可以以任何顺序出现。在解析完文件中的所有atom之前,不要断定某个atom不存在。
- 虽然其他atom可以按任意顺序排列,但出于实际原因,在创建QuickTime Movie Files时,您应该使用推荐的顺序。例如,包含电影资源的atom应该在包含电影采样数据的原子之前。如果您遵循这个推荐的atom顺序,那么就有可能在电影文件正在下载的过程中通过网络播放电影
- QuickTime Movie Files必须包含一个电影- atom,它包含电影结构或文件外部一个或多个备用电影源的引用。一般来说,这些替代源将是- QuickTime Movie Files,其中包含电影结构。
- QuickTime Movie Files通常包含一个或多个电影数据- atom,这些- atom包含媒体采样数据,如视频帧和音频采样组。但是,文件中可能没有电影数据- atom,因为电影可能依赖于电影文件外部的采样数据,比如外部数据文件或Internet上的实时流。单个电影数据- atom可以包含用于各种不同媒体的采样数据。一般来说,在一个电影数据- atom中包含一部电影使用的所有媒体样本是可能的。电影数据- atom可能非常大,有时超过2^32字节。

Basic atom types of a QuickTime file
| Atom type | Use | 
|---|---|
| ‘ftyp’ | 文件类型兼容性——标识文件类型并将其与类似的文件类型(如MPEG-4文件和JPEG-2000文件)区分开来 | 
| ‘moov’ | 关于电影的电影资源元数据(曲目的数量和类型、样本数据的位置,等等)。描述在哪里可以找到电影数据以及如何解析这些数据 | 
| ‘mdat’ | 电影样本数据媒体样本,如视频帧和音频采样组。通常这些数据只能通过使用电影资源来解释 | 
| ‘free’ | 文件中可用的未使用空间 | 
| ‘skip’ | 文件中可用的未使用空间 | 
| ‘wide’ | 如果紧跟着的 atom超过2^32字节,则保留的空间可以被扩展的大小字段覆盖,而不会替换紧跟着的atom的内容 | 
| ‘pnot’ | 参考电影预览数据 | 
The File Type Compatibility Atom
- file type compatibility atom,也称为- file type atom,允许读者确定这是否是一种读者能够理解的文件类型。具体地说,- file type atom标识文件与之兼容的文件类型规范。这允许读者区分密切相关的文件类型,例如- QuickTime movie files、MPEG-4和JPEG-2000文件(所有这些文件都可能包含- file type atom、电影- atom和电影数据- atom)
- 当一个文件与多个规范兼容时,file type atom会列出所有兼容类型,并在兼容类型中指出首选类型或最佳用途。例如,使用QuickTime兼容文件格式的音乐播放器可能会识别出一个文件作为该播放器的音乐文件的最佳用途,但也会识别出它是QuickTime电影
- file type atom还有另外一个用途,就是区分相同文件类型的不同版本或规范,允许它传递比文件扩展名或MIME类型更多的信息。- file type atom还具有文件内部的优势,与文件扩展名或MIME类型相比,它不太容易发生意外更改
- 注意:这里描述的文件类型atom在功能上与MPEG-4和JPEG-2000的ISO规范中定义的文件类型框相同
- file type atom是可选的,但强烈推荐使用。如果存在,它必须是文件中的第一个重要- atom,位于电影- atom(以及任何自由空间- atom、预览- atom或电影数据- atom)之前
- file type atom的- atom类型值为’ftyp',包含以下字段:
| type | use | 
|---|---|
| Size | 一个32位无符号整数,指定该 atom中的字节数 | 
| Type | 一个32位无符号整数,用来标识 atom类型,通常用4个字符的代码表示;该字段必须设置为’ftyp' | 
| Major_Brand | 一个32位无符号整数,应该设置为’qt ‘(注意后面的两个ASCII空格字符) QuickTime Movie Files。如果一个文件与多个品牌兼容,那么所有这些品牌都会列在Compatible_Brands字段中,而Major_Brand标识首选品牌或最佳用途 | 
| Minor_Version | 一个32位字段,指示文件格式规范版本。对于 QuickTime Movie Files,它采用四个二进制编码的十进制值的形式,表示QuickTime文件格式规范的世纪、年份和月份,后面跟着一个二进制编码的十进制0。例如,对于2004年6月的小版本,该字段被设置为BCD值2004 06 00 | 
| Compatible_Brands[ ] | 列出兼容文件格式的一系列无符号32位整数。主要品牌必须出现在兼容品牌列表中。允许一个或多个值为零的“占位符”条目;这样的条目应该被忽略 | 
- 如果没有一个Compatible_Brands字段被设置为’qt ‘,那么该文件不是QuickTime Movie Files,并且与本规范不兼容。应用程序应该返回错误并关闭文件,或者调用适合于指定类型之一(最好是主类型)的文件导入器。当前,当试图打开文件类型、文件扩展名或MIME类型将其标识为QuickTime影片,但其文件类型atom不包含“qt”类型时,QuickTime返回一个错误。
- ⚠️:这个错误的一个常见来源是一个MPEG-4文件不正确地命名为.mov文件扩展名,或者MIME类型不正确地设置为“video/quicktime”。只有当MPEG-4文件使用Mac OS文件类型、文件扩展名或MIME类型被正确识别为MPEG-4文件时,QuickTime才会自动导入。
- 如果你创建的文件类型与QuickTime文件格式完全兼容,Compatible_Brand字段之一必须设置为’qt ‘;否则QuickTime将不会将该文件识别为QuickTime影片。
- ⚠️:以这种方式使用QuickTime文件格式受到苹果公司的许可。
Free Space Atoms
- 
free和skip atom都指定电影数据文件中的未使用空间。这些atom只包含一个atom头(大小和类型字段),后面跟着适当数量的可用空间字节。当读取QuickTime电影时,您的应用程序可以安全地跳过这些atom。在编写或更新影片时,可以重用与这些atom类型相关联的空间。
- 
wide atom通常位于电影数据原子之前。wide atom仅由类型和大小字段组成。这占用了8字节的空间——足够将扩展大小的字段添加到后面的atom头中,而不会替换该atom的内容。如果一个atom的大小超过2^32字节,并且它前面有一个wide atom,您可以通过重写现有的atom头和前面的wide atom创建一个包含扩展大小字段的新atom头。
Movie Data Atoms
- 与free atom和skip atom一样,电影数据atom的结构非常简单。它由一个atom头(atom大小和类型字段)组成,后面是电影的媒体数据。应用程序只能通过使用存储在movieatom中的元数据来理解该atom中的数据。这个atom可以非常大,可能超过2^32字节,在这种情况下,size字段将被设置为1,头将包含一个64位的扩展大小字段。
Preview Atoms
- preview atom包含允许您查找与QuickTime影片关联的预览图像的信息。预览图像,或海报,是适合在打开对话框中显示给用户的代表性图像

- preview atom有一个- atom类型值’pnot’,在它的- atom头后面,包含了以下字段:
| Type | Use | 
|---|---|
| Size | 一个32位整数,指定此 preview atom中的字节数 | 
| Type | 标识 atom类型的32位整数;这个字段必须设置为’pnot’ | 
| Modification date | 一个32位无符号整数,其中包含一个日期,指示预览最后一次更新的时间。数据是标准的Macintosh格式 | 
| Version number | 必须设置为0的16位整数 | 
| Atom type | 一个32位整数,指示包含预览数据的 atom类型。通常,这被设置为’PICT’来指示一个QuickDraw图片 | 
| Atom index | 一个16位整数,它标识将使用指定类型的哪个 atom作为预览。通常,此字段被设置为1,应该使用atom类型字段中指定的类型的第一个atom | 
 
             
            