Skip to content
uupaa edited this page Sep 10, 2018 · 14 revisions

MPEG-1

ES (Elementary Stream)

エンコードされた Video や Audio データ

PTS (Presentation Time Stamp)

  • コンテンツをいつ出力するかを指定したタイムスタンプ情報。映像と音声の同期のために必要となる
  • STC が PTS の示す時刻になるとデコード結果を映像や音声として出力する
  • 33bits

SCR (System Clock Reference)

  • ストリーム上でのシステムクロック情報
  • 33bits

DeMUX (Demultiplexer)

  • 映像データと音声データを分離する

STC (System Time Clock)

  • システム基準時刻。内部クロック
    • 90kHz
      • MPEG-1のクロックはすべて90kHz単位。STC,SCR,PTS も90KHzを基礎単位とする時刻情報

STD (System Target Decoder)

  • MPEG-1の仮想的なデコーダモデル
         +----+----+
Audio ES | A1 | A2 |
         +----+----+

         +----+----+
Video ES | V1 | V2 |
         +----+----+

           +-----+----+ +-----+----+ +-----+----+ +-----+----+ +-----
Packet     | PH1 | A1 | | PH2 | V1 | | PH3 | A2 | | PH4 | V2 | | ....
           +-----+----+ +-----+----+ +-----+----+ +-----+----+ +-----
                        ↓                       ↓
           +-----+------+-----------------------+------+------+----------
Pack       | SH1 | PKH1 | Some Packets          | PKH2 | .... | ... 
           +-----+------+-----------------------+------+------+----------
  • Pack
    • PKH と 1つ以上の Packet から構成されています。SH を含む事もできます
  • Packet
    • PH と ES から構成されています。PH には PTS や DTS が含まれる場合があります
  • PH (Packet Header)
    • Packet の情報を格納するヘッダです
  • PKH (Pack Header)
    • SCR を含みます
    • 0x000001 で開始します
  • SH (System Header)
    • 制御フラグ, 伝送レート, バッファ制御情報などが含まれます。可変長です
    • 0x000001BB で開始します。図3-10参照

LipSync

  • MPEG-1 においては、音声と映像にずれが発生した場合は、音声を基準にずれを修正します
  • これは人間が音のずれに対してより敏感なためです

MPEG2-TS

MPEG-2 PS

MPEG-2 PS はデータを自由に高速に読み込みができるメディア(DVD, HDD)用の規格です。 一方 MPEG-2 TS は、地上波や通信経路などエラーの検出が必要な環境を想定しています。

MPEG-2 TS

MPEG 2-TS には映像/音声以外の余計な情報が含まれるため、保存には向きません。 MPEG 2-TS は様々なフォーマットの映像を内包できる仕様です。MPEG2 以外にも、 H.264やAACなどをペイロードに格納することができます。

  • MPEG-2 TS は 13818-1:2000 (ISO/IEC) または H.222.0 (ITU-T Rec) として規格化されています

  • H.264 を扱うために拡張された MPEG-2 TS は 13818-1:2000 (E) として規格化されています

  • MPEG2-TS packet image

    • TH: Transport stream Header

    • PES: Packetized Elementary Stream (MPEG2 term)

         +----+---------------+----+---------------+----
         | TH |      PES      | TH |     PES       | ...
         +----+---------------+----+---------------+----
      
          ~~~~~~~~~~~~~~~~~~~~ = MPEG-2 TS Packet
      
  • MPEG-2 TS Packet (Packet)

    • 規格では 188 bytes ( 4 bytes header + 184 bytes payload ) ですが、 192 bytes や 204 bytes に拡張され利用されている事があります。 多くの実装が 188 bytes 以外を読み込めるようになっています。 地デジにおける取り決めは http://www.arib.or.jp/english/html/overview/doc/2-STD-B31v1_7.pdf (P107)を参照のこと。
payload_unit_start_indicator = 1
+-----------+------------------+--------------+
| HEADER(4) | pointer_field(1) | PAYLOAD(183) |
+-----------+------------------+--------------+

payload_unit_start_indicator = 0
+-----------+--------------+
| HEADER(4) | PAYLOAD(184) |
+-----------+--------------+

PSI/SI (13 bits)

Program Specific Information / Service Information.
PID === 0x0000 -> `PAT` Program Association Table
PID === 0x0001 -> `CAT` Conditional Access Table
PID === 0x0002 ->       Transport Stream Description Table
PID === 0x0003 ->       IPMP Control Information Table
PID === 0x0004 -> Reserved
          :
PID === 0x000F -> Reserved
PID === 0x0010 -> Network_PID or Program_map_PID or elementary_PID. PSI/SI では `NIT` として使用
PID === 0x0011 -> Network_PID or Program_map_PID or elementary_PID. PSI/SI では `SDT` として使用
PID === 0x0012 -> Network_PID or Program_map_PID or elementary_PID. PSI/SI では `EIT` として使用
PID === 0x0014 -> Network_PID or Program_map_PID or elementary_PID. PSI/SI では `TOT` として使用
PID === 0x0024 -> Network_PID or Program_map_PID or elementary_PID. PSI/SI では `BIT` として使用
          :
PID === 0x1FFE -> Network_PID or Program_map_PID or elementary_PID.
PID === 0x1FFF -> Null packet

Channel

  • MPEG2 では Channel (番組) はProgram と呼ばれます

payload_unit_start_indicator

The payload_unit_start_indicator is a 1-bit flag which has normative meaning for Transport Stream packets that carry PES packets (refer to 2.4.3.6) or PSI data (refer to 2.4.4).

When the payload of the Transport Stream packet contains PES packet data, the payload_unit_start_indicator has the following significance: a '1' indicates that the payload of this Transport Stream packet will commence with the first byte of a PES packet and a '0' indicates no PES packet shall start in this Transport Stream packet.

Payload が PES パケットデータを含んでいる場合は、
payload_unit_start_indicator は以下のように解釈されます。

- 1なら、ペイロードに PES パケットの先頭が含まれています。
- 0なら、ペイロードに PES パケットの先頭は含まれていません。

If the payload_unit_start_indicator is set to '1', then one and only one PES packet starts in this Transport Stream packet. This also applies to private streams of stream_type 6 (refer to Table 2-34).

When the payload of the Transport Stream packet contains PSI data, the payload_unit_start_indicator has the following significance:

Payload が PSI データを含んでいる場合は、
payload_unit_start_indicator は以下のように解釈されます。

- PSIセクションの最初の1バイトを含んでいる場合は、1になります。
  この場合は、パケットのヘッダとペイロードの間に pointer_field (1byte)が挿入されます

  ```
  | header(4byte) | pointer_field(1byte) | payload (183byte) |
  ```

- PSIセクションの最初の1バイトを含んでいない場合は、0になります。
  この場合は、パケットのヘッダとペイロードの間に pointer_field (1byte)が挿入されません

  ```
  | header(4byte) | payload (184byte) |
  ```

if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. If the Transport Stream packet does not carry the first byte of a PSI section, the payload_unit_start_indicator value shall be '0', indicating that there is no pointer_field in the payload. Refer to 2.4.4.1 and 2.4.4.2. This also applies to private streams of stream_type 5 (refer to Table 2-34).

H.264/AVC

H.264/AVC の Spec は、ITU-T から pdf を無料でダウンロードできる。
ISO/IEC では同じものを有料で販売している。

VCL (Video Coding Layer)

ビデオ符号化レイヤ, 動画符号化を扱う、前段のシステム

NAL (Network Abstraction Layer)

符号化した情報を伝送/蓄積を行う次段のシステム

Source   |       ↓ 映像ソース
---------|--------------------
VCL      |       ↓ 符号化データ
---------|--------------------
NAL      |       ↓ スタートコードの付与, バストストリームへの変換
---------|--------------------
MPEG2-TS |       ↓ 

RBSP

Raw Byte Sequence Payload

  • 圧縮済みの動画の生データ
  • 長さは byte アライメント
    • 長さが 8の倍数以外だったら、RBSP の末尾に RBSP_trailng_bits を付与し byte アラインを行う

RBSP_trailng_bits

RBSP の末尾に配置する詰め物です。

  • 先頭が 1 で、それ以降は 0 のビット列
    • 7bit の隙間がある場合は、0b1000000 で埋める
    • 4bit の隙間がある場合は、0b1000 で埋める
    • 2bit の隙間がある場合は、0b10 で埋める
    • 1bit の隙間がある場合は、0b1 で埋める

NAL Unit

  • NAL Header + RBSP

NAL Header

  • 長さは 1 byte, 先頭が 0 で、

  • nal_ref_idc (参照ピクチャとなるスライスが含まれているかどうか)

  • nal_unit_type (NAL Unit の type を示す識別子)

    nal_unit_type Subject
    0 未定義
    1 IDR 以外のピクチャの一部(スライス)
    2 データパーティショニングAで符号化されたスライス
    3 データパーティショニングBで符号化されたスライス
    4 データパーティショニングCで符号化されたスライス
    5 IDR ピクチャ
    6 SEI
    7 SPS
    8 PPS
    9 AU デリミタ
    10 End of Sequence
    11 End of Stream
    12 Filler Data (フォーマットを整えるために挿入される詰め物。ダミーデータ)
    13 SPS拡張, FRExt で使用
    14 .. 18 Reserved
    19 補助スライス, FRExt で使用
    20 .. 23 Reserved
    24 .. 31 未定義

IDR Picture

Instantaneous Decoding Refresh

  • 先頭の画像。アニメーションで言うところの Key Frame となる画像。それ単体で成立する画像を意味します

SPS

Sequence Parameter set

  • シーケンス全体のパラメタです。ヘッダ情報です
  • 省略が可能です。省略されている場合は、それまでに現れた最後(latest)の SPS を流用します

PPS

Picture Parameter set

  • ピクチャ全体のパラメタです
  • 省略が可能です。省略されている場合は、それまでに現れた最後(latest)の PPS を流用します

SEI

Supplemental Enhancement Information

  • VCL の符号化には必要がない付加情報です
  • ユーザデータなども SEI に格納することができます

AU デリミタ

Access Unit Delimiter

  • アクセスユニットの先頭を示します
  • アクセスユニットに含まれるスライスの種類が格納されています

End of Sequence

シーケンスの終端を示します

End of Stream

映像/音声ストリーム全体の終端を示します

Filler Data

データ量が少なすぎて規格の仕様を満たせない場合に挿入される無意味なデータです

VCL NAL ユニットと 非VCL NAL ユニット

  • VCL NAL ユニットとは、nal_unit_type が 1 〜 5 のもので、VCL で生成された NAL ユニットを意味します
  • 非VCL NAL ユニットとは、SPS や PPS の事で、nal_unit_type が 6以上のものを意味します

シーケンス

NAL Unit

nal_unit( NumBytesInNALunit ) {                             Categories  Descriptor

    forbidden_zero_bit                                      All         f(1)        1 bit, 常に 0
    nal_ref_idc                                             All         u(2)        2 bit, 0 以外なら参照すべき idc があります
    nal_unit_type                                           All         u(5)        5 bit, 
    NumBytesInRBSP = 0
    nalUnitHeaderBytes = 1
    if ( nal_unit_type == 14 || nal_unit_type == 20 ) {
        svc_extension_flag                                  All         u(1)
        if( svc_extension_flag ) {
            nal_unit_header_svc_extension( )                All             // specified in Annex G
        } else {
            nal_unit_header_mvc_extension( )                All             // specified in Annex H
        }
        nalUnitHeaderBytes += 3
    }
    for( i = nalUnitHeaderBytes; i < NumBytesInNALunit; i++ ) {
        if( i + 2 < NumBytesInNALunit && next_bits( 24 ) == 0x000003 ) {
            rbsp_byte[ NumBytesInRBSP++ ]                   All         b(8)
            rbsp_byte[ NumBytesInRBSP++ ]                   All         b(8)
            i += 2
            emulation_prevention_three_byte                 All         f(8)    // equal to 0x03
        } else {
            rbsp_byte[ NumBytesInRBSP++ ]                   All         b(8)
        }
    }

}

圧縮データの階層構造

  1. シーケンスレイヤ

    • シーケンスデータ。圧縮された画像データ

      +-------+----+   +-------+----+   +-------
      | GOP   | SH | + | GOP   | SH | + | ....
      +-------+----+   +-------+----+   +-------
      
  2. GOP レイヤ

    • 15枚程度の Bピクチャ, Pピクチャ, Iピクチャ をまとめたもの

      +-------+   +---++---++---++---++---++---++---++---+     +---+
      | GOP   | = | B || P || B || P || B || P || B || P | ... | I |
      +-------+   +---++---++---++---++---++---++---++---+     +---+
      
  3. ピクチャレイヤ

    • 1つのピクチャ(B or P or I)を 16 line でスライスしたもの。 1 line = 1px と考えても良い

      +-------------------------+
      | slice#1                 | 16 line
      +-------------------------+
      | slice#2                 |
      +-------------------------+
      |      :                  |
      +-------------------------+
      | slice#n                 |
      +-------------------------+
      
  4. スライスレイヤ

    • 1つのスライスを 16 画素でさらにスライスしたもの。1画素 = 1px と考えても良い

      +-------------------------+   +----+----+----+----+----+-----+----+
      | slice#n                 | = | MB | MB | MB | MB | MB | ... | MB |
      +-------------------------+   +----+----+----+----+----+-----+----+
      
  5. マクロブロックレイヤ

    • 1つのマクロブロックは4つのYとCb,Crで構成されている

               +-----+-----+   +----+   +----+
      +----+   |  Y  |  Y  | + | Cb | + | Cr | 8
      | MB | = |-----+-----+   +----+   +----+
      +----+   |  Y  |  Y  |              8
               +-----+-----+
                    16
      
  6. ブロックレイヤ

  • GOP (Group of Picture), 15枚程度の画像群
  • SH (Sequence Header), 画像の開始点
  • MB (Macro Block), 4つの Y(輝度), 1つの Cb, 1つの Cr で構成される画素情報

CRC32/MPEG2

MPEG2 の CRC32 は、CRC32/MPEG2 と呼ばれ、通常の CRC32 とは計算式と初期値が異なる。

AAC

  • MPEG-2 AAC (ISO/IEC 13818-7)
    • 日本の地デジで採用されているAACはこちらの方式です
  • MPEG-4 AAC (ISO/IEC 14496-3)(JIS X 4332-3)
    • MPEG-2 AAC の後継規格です。中身はほぼ同じ物なのですがライセンス料金に差があるとの事です
  • ADTS
    • MPEG-2 AAC や MPEG-4 AAC で利用されるコンテナフォーマットの1つです
    • | ADTS ヘッダ + AAC Data | フォーマットで構成されます
    • ADTD ヘッダは 7 byte の CRC 無し版と、 9 byte の CRC 有り版があります
    • in MPEG-TS System
      • MPEG-2 TS システム(PES packet)にAACを含める場合は、AACデータにはADTSヘッダを付与する必要があります
      • AAC データに ADTS を付与し、それらを PES Packet に変換し、さらに Mux して TS パケットに変換します
    • | AAAAAAAA | AAAABCCD | EEFFFFGH | HHIJKLMM | MMMMMMMM | MMMOOOOO | OOOOOOPP | CRC無し
    • | QQQQQQQQ | QQQQQQQQ | CRC有り +2byte
      • A (12 bit) 同期ワード, 常に 0xfff
      • B ( 1 bit) MPEGバージョン, 0 = MPEG-4, 1 = MPEG-2
      • C ( 2 bit) 常に 00
      • D ( 1 bit) CRCの有無, 0 = CRC有り, 1 = CRC無し
      • E ( 2 bit) Profile value (MPEG-2 Audio Object type - 1) 00 = Main, 01 = LC, 10 = SSR
        • 通常は LC が利用されます
      • F ( 4 bit) MPEG-4 AAC サンプリング周波数
      • G ( 1 bit) プライベートストリーム (0=エンコーディング、1=デコーディング)
      • H ( 3 bit) MPEG-4 AAC チャンネル構成 (後述、0の時は、チャンネル構成は帯域内のPCEで送信される)
      • I ( 1 bit) オリジナル (0=エンコーディング、1=デコーディング)
      • J ( 1 bit) ホーム (0=エンコーディング、1=デコーディング)
      • K ( 1 bit) 著作権で保護されたストリーム (0=エンコーディング、1=デコーディング)
      • L ( 1 bit) 著作権の開始 (0=エンコーディング、1=デコーディング)
      • M (13 bit) フレーム全体の長さ。ADTSヘッダーの長さ(7byteまたは9byte)も含みます
      • O (11 bit) バッファー占有量
      • P ( 2 bit) ADTSフレーム内のAACフレーム(RDB)の数。ADTSフレーム - 1の値になります
      • Q (16 bit) CRC (プロテクションの有無=0の場合のみ)
      • Link: http://wiki.multimedia.cx/index.php?title=ADTS
    • MPEG-4 AAC サンプリング周波数 (F)
      • 0000 - 96000 Hz
      • 0001 - 88200 Hz
      • 0010 - 64000 Hz
      • 0011 - 48000 Hz
      • 0100 - 44100 Hz
      • 0101 - 32000 Hz
      • 0110 - 24000 Hz
      • 0111 - 22050 Hz
      • 1000 - 16000 Hz
      • 1001 - 12000 Hz
      • 1010 - 11025 Hz
      • 1011 - 8000 Hz
      • 1100 - 7350 Hz
      • 1101 - Reserved
      • 1110 - Reserved
      • 1111 - それ以外(周波数が明示的に書かれている場合はこの値になります)
    • MPEG-4 AAC チャンネル構成 (H)
      • 000 帯域内のPCEで送信される
      • 001 1 ch - (Front: center)
      • 010 2 ch - (Front: left, right)
      • 011 3 ch - (Front: left, center, right)
      • 100 4 ch - (Front: left, center, right)(Rear: center)
      • 101 5 ch - (Front: left, center, right)(Rear: left, right)
      • 110 5.1 ch - (Front: left, center, right)(Rear: left, right, subwoofer)
      • 111 7.1 ch - (Front: left, center, right)(Side: left, right)(Rear: left, right, subwoofer)
  • ATDS AAC
    • ATDS ヘッダを付与した AAC データの事です
  • RAW AAC
    • ADTS ヘッダの付いていない 生のAAC データの事です
    • MPEG-2 AAC や MPEG-4 AAC の生データ部分に相当します
    • 拡張子は.aac です
    • 一般的な動画プレイヤーでは再生できないため、通常は mp4m4a ファイル形式に変換します
  • HE-AAC (MPEG-4 AAC Version 3)
    • SBR を追加し、低ビットレートにおける音質を改善した AAC の上位規格です
      • HE-AAC v1 と HE-AAC v2 があります
    • 従来の MPEG-4 AAC は対比上 AAC-LC(Low Complexity) と呼ばれます
    • およそ半分ほどのビットレートで AAC-LC と同等の音質を実現しています
    • AAC-LC しか対応していない従来のプレイヤーは SBR 部分を無視して再生できるため、後方互換性があります

MPEG-2

MPEG2-TS packet image

TH: Transport stream Header
PES: Packetized Elementary Stream (MPEG-2 term)

+----+---------------+----+---------------+----
| TH |      PES      | TH |     PES       | ...
+----+---------------+----+---------------+----

~~~~~~~~~~~~~~~~~~~~~~ -> MPEG-2 TS Packet (188 byte)
  • payload_unit_start_indicator

    • PES パケットのペイロード部分に余計な1byteが含まれているかどうかを示すフラグです。

    The payload_unit_start_indicator is a 1-bit flag which has normative meaning for Transport Stream packets that carry PES packets (refer to 2.4.3.6) or PSI data (refer to 2.4.4).

    When the payload of the Transport Stream packet contains PES packet data, the payload_unit_start_indicator has the following significance: a '1' indicates that the payload of this Transport Stream packet will commence with the first byte of a PES packet and a '0' indicates no PES packet shall start in this Transport Stream packet.

    Payload が PES パケットデータを含んでいる場合は、
    payload_unit_start_indicator は以下のように解釈されます。
    
    - 1なら、ペイロードに PES パケットの先頭が含まれています。
    - 0なら、ペイロードに PES パケットの先頭は含まれていません。
    

    If the payload_unit_start_indicator is set to '1', then one and only one PES packet starts in this Transport Stream packet. This also applies to private streams of stream_type 6 (refer to Table 2-34).

    When the payload of the Transport Stream packet contains PSI data, the payload_unit_start_indicator has the following significance:

    Payload が PSI データを含んでいる場合は、
    payload_unit_start_indicator は以下のように解釈されます。
    
    - PSIセクションの最初の1バイトを含んでいる場合は、1になります。
      この場合は、パケットのヘッダとペイロードの間に pointer_field (1byte)が挿入されます
    
      ```
      | header(4byte) | pointer_field(1byte) | payload (183byte) |
      ```
    
    - PSIセクションの最初の1バイトを含んでいない場合は、0になります。
      この場合は、パケットのヘッダとペイロードの間に pointer_field (1byte)が挿入されません
    
      ```
      | header(4byte) | payload (184byte) |
      ```
    

    if the Transport Stream packet carries the first byte of a PSI section, the payload_unit_start_indicator value shall be '1', indicating that the first byte of the payload of this Transport Stream packet carries the pointer_field. If the Transport Stream packet does not carry the first byte of a PSI section, the payload_unit_start_indicator value shall be '0', indicating that there is no pointer_field in the payload. Refer to 2.4.4.1 and 2.4.4.2. This also applies to private streams of stream_type 5 (refer to Table 2-34).

payload_unit_start_indicator = 1 のパケット構造

+-----------+------------------+--------------+
| HEADER(4) | pointer_field(1) | PAYLOAD(183) |
+-----------+------------------+--------------+

payload_unit_start_indicator = 0 のパケット構造

+-----------+--------------+
| HEADER(4) | PAYLOAD(184) |
+-----------+--------------+

MPEG-4 part 10 (MPEG-4 AVC/H264)

MPEG-4 part 10 の規格書は、ITU-T から無料でダウンロードできます( ISO/IEC では同じものを有料で販売しています )。

MPEG-4

  • GOP (Group of Picture), 15枚程度の画像群

  • SH (Sequence Header), 画像の開始点

  • MB (Macro Block), 4つの Y(輝度), 1つの Cb, 1つの Cr で構成される画素情報

  • Byte stream format (ByteStream format)

    • MPEG-4 part 10 AVC/H264 の規格書の Annex B で定義されているバイトデータのフォーマットで、連続する StartCode + EBSP で構成されるバイトデータです
    • MPEG-2 TS に搭載されたH.264データを元にMP4ファイルを生成するには、以下の手順でデータ変換を行う必要があります
      1. fetch M3U8 file
      2. parse M3U8 file
      3. fetch *.ts file
      4. parse TSPacket
      5. parse PESPacket
      6. parse ByteStream
      7. parse NAL file format
      8. parse AUD, SPS, PPS, SEI, IDR, ...
      9. build AccessUnit
      10. Mux
      11. build mp4 file
  • VCL (Video Coding Layer)

    • ビデオ符号化レイヤ, 動画符号化を扱う、前段のシステムの事をVCLと呼びます
  • VCL-NALUnit

    • 圧縮されたスライスデータ(映像データ)そのものを指します
  • Non-VCL-NALUnit

    • 映像データではないメタデータ(補助的な情報)です。AUD, SPS, PPS, SEI などが Non-VCL-NALUnit に該当します
  • NAL (Network Abstraction Layer)

    • 符号化した情報を伝送/蓄積を行うVCLの次段のシステムです
    • 1個以上の NAL Unit が連続している Stream です。
    • | NALUnit | NALUnit | ...
  • NALUnit (Network Abstraction Layer Unit)

    • NALUnit = NALUnitHeader + EBSP
    • AVC の世界におけるデータの基本的な単位が NALUnit です
    • NALUnit はバイト単位でアライメントされています
    • VideoやAudio情報を保持しているNAL Unitは VCL NALユニットと呼び、メタデータをもったNAL Unitは非VCAL NALユニットとも呼ばれます
      • VCL NALユニットかどうかは、nal_unit_type で判別できます
    • NALUnit には2つの Stream(バイナリデータフォーマット) があります
      1. ByteStream (NAL Uints in Byte-stream Format)( StartCode + NALUnitHeader + EBSP )
        • このフォーマットでは NALUnit の長さは明確に格納されていません。先頭からStartCode(00 00 01)を探すことでNALUnitの区切りとバイトサイズを知ることができます
        • StartCode は 00 00 01 です。先頭に複数の余計な 00 が含まれていてもOKです
          • 00 00 01 の他に 00 00 00 0100 00 00 00 01 なども合法です
          • 他の Stream に変換する場合は、EP3B( 00 00 03 0x ) を 00 00 0x にデコードする必要があります
        • MPEG-2 TS に格納されているバイトデータはこのフォーマットです
        • ffmpeg -o で拡張子を .264 にした場合に生成される生データもこのフォーマットです
      2. NAL file format ( NALUnitSize + NALUnitHeader + EBSP )
        • mp4 の mdat box に格納されているバイトデータはこちらのフォーマットです
        • NALUnitSize には NALUnit のバイト数がビックエンディアンで格納されています
    • NALUnit はピクチャ情報を含む VCL-NALUnit と、ピクチャ情報を含まない Non-VCL-NALUnit の2つに大きく分類できます
    • MPEG-4 part 10 AVC の規格書では、NALUnitから -> NALUnitHeader と RBSP を取り出す擬似コードが nal_unit 関数として説明されています
      • emulation_prevention_three_byte も nal_unit 関数の中でデコードしています
  • StartCode

    • StartCode = 00(0個以上) + 00 00 01
    • 00 00 01 から構成されるバイト列です。先頭に余計な00が複数存在する場合があります
  • NALUnitSize, NumBytesInNALunit

    • NALUnit のサイズを示す情報です
    • NALUnit のサイズが 4 byte なら | 00 00 00 04 | NALUnit | になります
    • 通常 4 byte ですが 1 byte または 2 byte のケースもありえます
      • AVCDecoderConfigurationRecord.lengthSizeMinusOne + 1 が2 なら NALUnitSize のサイズは 2 になります
  • NALUnitHeader, NALHeader

    • NALUnit の先頭1byteです。NALUnit の内容をデコードするための情報が含まれています

    • NALUnit の内容を知るには、先頭1byte (NALUnitHeader) を読み込み, 0 + nal_ref_idc(2) + nal_unit_type(5) に分解します

    • nal_unit_type

      • nal_unit_type が 5 ならその NALUnit は IDR ピクチャです。VCL-NALUnit です
      • nal_unit_type が 9 ならその NALUnit は AUD です。AccessUnit の切れ目を意味します。Non-VCL-NALUnit です
      • nal_unit_type が 7 ならその NALUnit は SPS です。AccessUnit 全体に対するメタ情報が格納されています。Non-VCL-NALUnit です
      • nal_unit_type が 8 ならその NALUnit は PPS です。ピクチャに対するメタ情報が格納されています。Non-VCL-NALUnit です
    • nal_ref_idc

      • nal_ref_idc00 ならこのNALUnitがピクチャ予測のために参照されない事を意味しています(つまり一度読んだら速やかに廃棄可能なNALUnitという事になります)。
      • 00 以外ならその AccessUnit には SPSやPPSやスライスデータが含まれており、他のNALUnitやピクチャ予測から参照されるデータを含んでいるという意味になります(つまり読み込んだ後にすぐさま廃棄できません)
      |ABBCCCCC|    bit index field
      |~       | -> 1   0     zero `0`
      | ~~     | -> 2   1     nal_ref_idc (参照ピクチャとなるスライスが含まれているかどうか)
      |   ~~~~~| -> 5   2     nal_unit_type (NAL Unit の type を示す識別子)
      
      nal_unit_type Subject
      0 未定義
      1 IDR 以外のピクチャの一部(スライス)
      2 データパーティショニングAで符号化されたスライス
      3 データパーティショニングBで符号化されたスライス
      4 データパーティショニングCで符号化されたスライス
      5 IDR ピクチャ
      6 SEI
      7 SPS
      8 PPS
      9 AU デリミタ
      10 End of Sequence
      11 End of Stream
      12 Filler Data (フォーマットを整えるために挿入される詰め物。ダミーデータ)
      13 SPS拡張, FRExt で使用
      14 .. 18 Reserved
      19 補助スライス, FRExt で使用
      20 .. 23 Reserved
      24 .. 31 未定義
  • AccessUnit

    • AccessUnit 1枚のピクチャ(フレーム)を生成するために必要な NALUnit の集まりの事です。
    • AccessUnit は AUD(Access Unit Delimiter) を検索することで見つける事ができます。
    +-----+-----+-----+-----+---------++-----+-----------++-----+-----------+
    | AUD | SPS | PPS | SEI | IDR ... || AUD | ...       || AUD | ...       |
    +-----+-----+-----+-----+---------++-----+-----------++-----+-----------+
    <---------- Access Unit ----------><-- Access Unit --><-- Access Unit -->
    
  • EBSP (Encapsulate Byte Sequence Payload), EP3B (Emulation Prevention Three byte), emulation_prevention_three_byte

    • EP3B (00 00 03 0x) を含む(かもしれない)バイトデータです。

    • StartCode の 00 00 01 と類似したビットパターンが ByteStream 内に存在すると適切にパースができなくなってしまいます。

    • このような状態を避けるため、ByteStream(EBSP) においては以下の特定のパターンのバイト列が、別のバイト列に置換した状態で格納されています。

    • EBSP を RBSP に変換するには 00 00 03 0x00 00 0x にデコードする必要があります。x には 0〜3 の値が入ります

      EBSP RBSP
      00 00 03 00 00 00 00
      00 00 03 01 00 00 01
      00 00 03 02 00 00 02
      00 00 03 03 00 00 03
  • RBSP (Raw Byte Sequence Payload), Syntax Element

    • NALUnitHeader + RBSP という文脈で説明されている場合は、NALUnit の 2byte目以降のデータです
    • EP3B を含まないバイトデータです
    • RBSP の末尾はバイトアライメントが行われます。1byte に満たない部分には 1 が出力され、次に連続した 0 が Byte 境界まで埋め込まれます
      • RBSPのデータが3bit余る場合は、xxx + 1 + 0000 が RBSPの末尾に埋め込まれ xxx10000 になります
      • デコードは、最後のByteをLSBからMSBの方向に見ていきます(右から左に見ていきます)。1 が現れたらそこまでが padding データです
  • RBSP_trailng_bits

    • RBSP の末尾に配置する詰め物です
    • 先頭が 1 で、それ以降は 0 のビット列です
      • 7bit の隙間がある場合は、0b1000000 で埋めます
      • 4bit の隙間がある場合は、0b1000 で埋めます
      • 2bit の隙間がある場合は、0b10 で埋めます
      • 1bit の隙間がある場合は、0b1 で埋めます
  • SODB (string of data bits)

    • NALUnit に含まれる raw バイナリデータです。
    • バイナリデータを Bit単位で考えたものが SODBで、Byte単位で考えたものが RBSP です。
  • Stream, MPEG Stream

    • MPEG における Stream とは バイナリデータフォーマットの事です、 MPEG では様々なフォーマットのバイナリデータを扱うためフォーマットを識別するための名前がついています
    • ES (Elementary Stream)
      • 生オーディオデータやビデオデータは ES と呼ばれます
      • ES を Mux して得られたデータは System Stream (MPEG1) や Program Stream (MPEG-2 PS)と呼ばれます
    • PES (Packetized Elementary Stream)
      • ES をネットワークに流しやすいように分割しパケット化したものを PES と呼びます
      • PES には再生時刻に関する情報(PCR, OPCR)を含む事ができます
        • PCR, OPCR は 27MHz(27 * 1000 * 1000) で駆動するクロックです。現実世界の1秒は PCR では 27000000 になります
        • デコーダは時刻情報が含まれている場合に、これらを使って音声と動画を同期させる事が可能になります
      • 用途に応じて TS と PS があります
    • TS (Transport Stream)
      • ネットワークに流しやすいようにパケット化されたデータは Transport Stream (MPEG-2 TS)と呼ばれます
    • PS (Program Stream)
      • HDD,テープ,円盤メディアなどに保存しやすい形でパケット化されたデータは Program Stream (MPEG-2 PS)と呼ばれます
      • PS と PS は lossless (無劣化)で相互に変換することが可能です。
    • NALUnit in Byte Stream Format (H264 Byte stream format)
      • StartCode(00 00 00 01 や 00 00 01) を区切りとする NAL Unit のバイナリストリームです
      • | 00 00 00 01 | NALUnit | 00 00 01 | NALUnt | ...
    • NAL, NAL Stream
      • 1個以上の NAL Unit が連続している Stream です。
      • | NALUnitSize | NALUnit | NALUnitSize | NALUnit | ...
  • marker_bit ビット列がスタートコード(0x000001等)と一致してしまうことを避けるために ガードコードとしてmarker_bitが所々挿入されています。 marker_bit 自体は情報を持っていないため読み飛ばします。

  • AU (Access Unit)

    • 1つのピクチャを構成するために必要な情報を収めたNALUnitの集合です
    • 一般的な AU は連続したNALUnit(AUD, SPS, PPS, SEI, IDR...) から構成されます
    • AU に SPS や PPS が含まれない場合は、1つ前の SPS や PPS をコピーして使用する必要があるようです TODO: 要確認
  • AUD (Access unit delimiter)(AU デリミタ)

    • アクセスユニットの先頭を示します
    • アクセスユニットに含まれるスライスの種類が格納されています
    • nal_unit_type は 9 です
    • 00 00 01 09 F0 から構成されるバイト列です
  • End of Sequence

    • シーケンスの終端を示します
  • End of Stream

    • 映像/音声ストリーム全体の終端を示します
  • Filler Data

    • データ量が少なすぎて規格の仕様を満たせない場合に挿入される無意味なデータです
  • SPS (Sequence parameter set)

    • nal_unit_type は 7 です
    • AU 全体に関する重要なメタ情報が格納されています
      • seq_parameter_set_id, このSPSデータを示すユニークなIDです。PPS からはこのIDで参照されます。重要なデータです
      • profile_idc, H.264 profile です。Baseline profile は 0xE0(224) です
      • level_idc, H.264 Level です Level 30 は 0x1E(30) です
      • num_ref_frames, 参照しているフレーム数です。 TODO: 参照している? 参照されている?
      • pic_width_in_mbs_minus1, ピクチャの幅-1の値です。+1 することで幅が得られます
      • pic_height_in_map_units_minus1, ピクチャの高さ-1の値です。+1 することで高さが得られます
    • 省略が可能です。省略されている場合は、それまでに現れた最後(latest)の SPS を流用することになっています(普通はあります)
  • PPS (Picture parameter set)

    • nal_unit_type は 8 です
    • ピクチャに関するメタ情報が格納されています
      • pic_parameter_set_id, このPPSデータを示すユニークなIDです。slice からはこのIDで参照されます。重要なデータです
      • seq_parameter_set_id, このPPSデータと関連する SPS のIDです。
      • entropy_coding_mode_flag, CAVLC or CABAC の情報です。Baseline Profileでは CAVLCが、MainProfile では CABAC が使用されます
    • 省略が可能です。省略されている場合は、それまでに現れた最後(latest)の PPS を流用することになっています(普通はあります)
  • SEI (Supplemental enhancement information)

    • nal_unit_type は 6 です
    • SEI は符号化には必要がない、表示やバッファ管理上有用な情報を提供する NALUnit です
      • Recovery point, シーク後に表示を復帰するための情報などが格納されています
    • SEI NALUnit は、複数のSEI Message を含んでいる事があります
    • ユーザデータなども SEI に格納することができます
      • ffmpeg が生成するエンコード時に使用した設定情報が User Date に格納されていたりします
  • IDR picture (Instantaneous Decoding Refresh picture), Multiple Reference Frames

    • 先頭の画像。アニメーションで言うところの Key Frame となる画像です。それ単体で成立する画像を意味します
    • IDRはIフレーム(または SIフレーム)の一種です。通常のIフレートの動作に加え、後続のフレームがIDRフレームよりも前方を参照する事を禁止する効果があります。
      • ビデオシーケンスにおける最初のピクチャは、必ずIDRピクチャになります
      • いわゆるキーフレームになります。プレイヤーなどのシーク動作はIDR単位で行われます
      • H.264 の前身となる MPEG-4 ASP では、参照できるフレームは直前のフレームのみでしたが、H.264 ではその制限がなくなり 複数のフレームを参照したり離れたフレームを参照できる可能になりました。 このことから直前のIフレームやPフレームを飛び越え、更に前のフレームも参照可能になりましたが、 これはデコーダにとっては傍迷惑な仕様であり、このような問題を解決するために、無軌道な前方の参照を禁止する新しいIフレーム = IDR が必要になりました。
    • IDR picture は他のピクチャやスライスを参照する必要がないため POC や frame 番号は 0 にリセットされます
    • 通常は IDR picture を 0.5 〜 2秒間隔で挿入することで、意図した場所へのシークが可能なムービーを作成します
  • seq_parameter_set_id

    • PPSから参照されるSPSのIDです。0〜31の値です
  • pic_parameter_set_id

    • スライスから参照されるPPSのIDです。0〜31の値です
  • log2_max_frame_num_minus4

    • MaxFrameNum を算出するためのパラメタです。
    • MaxFrameNum は MaxFrameNum = Math.pow(2, log2_max_frame_num_minus4 + 4) で計算できます
  • MMCO5 (memory_management_control_operation equal to 5)

    • memory_management_control_operation が 5 の場合は frame_num の扱いが一部変化します

    Any coded slice NAL unit or coded slice data partition A NAL unit of the primary coded picture of the current access unit shall be different from any coded slice NAL unit or coded slice data partition A NAL unit of the primary coded picture of the previous access unit in one or more of the following ways:

    – frame_num differs in value. The value of frame_num used to test this condition is the value of frame_num that appears in the syntax of the slice header, regardless of whether that value is inferred to have been equal to 0 for subsequent use in the decoding process due to the presence of memory_management_control_operation equal to 5.

    NOTE 1 – A consequence of the above statement is that a primary coded picture having frame_num equal to 1 cannot contain a memory_management_control_operation equal to 5 unless some other condition listed below is fulfilled for the next primary coded picture that follows after it (if any).

  • slice_header

    • TODO:
    • slice_header は2段階で読み込む必要があります
    • 1段目は、
    • 2段目は、1段目から得られた SPSのIDとPPSのIDを参照しデコード処理を進めます
  • slice_id

    • スライス毎に設定されているIDです。nal_unit_type が 2 〜4 の場合に必要になります
    • 値の範囲には一定の制限があります
      • if (separate_colour_plane_flag === 0) { ... }
      • if (separate_colour_plane_flag === 1) { ... }
      • if (MbaffFrameFlag === 0) { ... }
      • if (MbaffFrameFlag === 0) { ... }
  • Baseline profile

    • I と P スライスしか利用できません
    • NALUnit の nal_unit_type には 2〜4の値(Coded slice data partition A/B/C)は登場しません
    • SPS.frame_mbs_only_flag は必ず 1 になります。
      • frame_mbs_only_flag equal to 1, it is specifies that every coded picture of the coded video sequence is a coded frame containing only frame macroblocks.

    • SPS の以下のパラメタには以下の制限があります
      • chroma_format_idc は利用しません
      • bit_depth_luma_minus8 は利用しません
      • bit_depth_chroma_minus8 は利用しません
      • qpprime_y_zero_transform_bypass_flag は利用しません
      • seq_scaling_matrix_present_flag は利用しません
    • PPS の以下のパラメタには以下の制限があります
      • weighted_pred_flag は利用しません
      • weighted_bipred_idc は利用しません
      • entropy_coding_mode_flag は利用しません
      • num_slice_groups_minus1 は 0 から 7 までの値になります
      • transform_8x8_mode_flag は利用しません
      • pic_scaling_matrix_present_flag は利用しません
      • second_chroma_qp_index_offset は利用しません
    • CAVLC の以下のパラメタに制限があります(内容省略)
    • Macroblock layer の以下のパラメタに制限があります(内容省略)
    • profile_idc を 66 にし、constraint_set0_flag を 1 に constraint_set1_flag を 1 にしてください
      • つまり、profile_idc に 0x42(66) をセットし次の1byteに 0xE0(224) をセットします
  • Level

    • Level に応じたビットレートの制限があります
      • Level 3.0 は、最大フレームサイズ(MaxFS)が 1620, 最大ビットレート(MaxBR)が 10000 です
  • primary_pic_type

    • AccessUnit にどんなスライスが含まれているかを示す値です。この値を見ることで、AccessUnit の処理方針の目安を決める事ができます

    • ただし ffmpeg が生成するデータでは常に primary_pic_type = 7 になっており、この値を指標として利用することは難しい(できない)ようです

      primary_pic_type slice_type
      values that may be present in the primary coded picture
      Name of slice_type
      0 2, 7 I
      1 0, 2, 5, 7 P, I
      2 0, 1, 2, 5, 6, 7 P, B, I
      3 4, 9 SI
      4 3, 4, 8, 9 SP, SI
      5 2, 4, 7, 9 I, SI
      6 0, 2, 3, 4, 5, 7, 8, 9 P, I, SP, SI
      7 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 P, B, I, SP, SI
  • slice_type

    • AVC では 1枚のピクチャに複数のsliceが含まれています。sliceは混在が可能です。
    • slice_type が5以上なら、そのピクチャに含まれる全ての slice が同じ種類である事を意味します。
      • slice_type = 7 の場合は、そのピクチャに含まれる全ての slice が I Picture です

        slice_type Name of slice_type
        0 P (P slice)
        1 B (B slice)
        2 I (I slice)
        3 SP (SP slice)
        4 SI (SI slice)
        5 P (P slice)
        6 B (B slice)
        7 I (I slice)
        8 SP (SP slice)
        9 SI (SI slice)
  • CAVLC (Context-Adaptive Variable Length Coding)

    • コンテクスト適応型可変長符号化方式です。圧縮率はそれほど高くありません
    • Baseline profile で使用されます
  • CABAC (Context-Adaptive Binary Arithmetic Coding), UVLC

    • コンテクスト適応型2値算術符号化方式。CAVLC よりも時間はかかりますが圧縮率は10〜15%ほど高くなります
    • Main profile 以上で使用できます
  • Exp-Golomb (Exponential-Golomb coding)

    • 整数を符号化する方法の1つです。
    • 0 は 1 に、1 は 010 に符号化されます
  • MPEG圧縮データの6階層構成

    • MPEG で圧縮されたデータは6つのレイヤーで区分されています
      1. シーケンスレイヤー, GOP + SH を 1対としたパケットを処理するレイヤーです
      2. GOPレイヤー, GOP の中に含まれる複数の I/B/P ピクチャを処理するレイヤーです
      3. ピクチャレイヤー, 1枚の画像を16ライン程で上から順番に切り取ったスライスという単位で処理するレイヤーです
      4. スライスレイヤー, スライスを横方向に16ライン幅で切り取ったマクロブロックという単位で処理するレイヤーです
      5. マクロブロックレイヤー, マクロブロックを4分割したブロックや、更にYUV毎に処理するレイヤーです
      6. ブロックレイヤー(DCT処理単位), ブロックを処理するレイヤーです
  • Sequence (シーケンス)

    • 15枚程度の連続した Picture をまとめたものを Sequence と呼びます
    • Sequence は | GOP + SH | GOP + SH ... から構成されるデータ構造です
    • GOP は 15枚程度の I/B/P Pictureから構成されています
      • GOP単位で各画像の差分を抽出し、I,B,Pピクチャを作り、圧縮率を稼ぐのがMPEGの基本戦略です
    • SH はSequence Header の略です。画像の開始点はSHの切れ目からになります
    • I, B, P ピクチャは、さらに画像を横方向に切り取った slice で構成されています
  • Picture (Frame)

    • 1枚の画像(ピクチャ,フレーム)は複数のスライスから構成されています
    • I Picture, B Picture, P Picture などの種類があります
    • MPEG-2/MPEG-4 では Picture が基本の単位ですが、AVC では slice が基本単位となります
      • MPEG-2/MPEG-4 では 1 Picture が 1 Frame に相当し、Picture 毎に符号化モードが存在しましたが、 AVC では slice 単位で符号化モードが決められています。
      • AVC では 1つの Picture の中に、異なるタイプの slice を混在させる事が可能です
        • 1つの Picture の中に1種類の slice だけが存在する事を示すには、slice_type の値を 5〜9にするか、 AUD の primary_pic_type を使って明示します
  • Picture 境界(先頭のPicture)

    • AVCデータがMPEG-2 System(MPEG-2 TS や MPEG-2 PS)を経由する場合は、必ずAUDが付与されているため、 先頭のピクチャかどうかをあまり意識する必要はありません
    • AUD が存在しないバイトストリームを扱う場合は、先頭のPicture かどうかを調べる必要があります
      • 以下の条件に該当する場合は先頭のPictureです
      • frame_num が異なる
      • field_pic_flag が異なる
      • frame_num が同じだが POC (Picture Order Count) の値が異なる
      • nal_ref_idc が異なる
      • IDRピクチャで idr_pic_idc が異なる
  • slice

  • frame_num

    • slice header の中にあります。そのsliceがどのframeに所属するかの情報です
  • I Picture (Intra Picture)

    • 他のピクチャを参照することなく画面を得られるピクチャです。最も基本的なピクチャになります
  • P Picture (Predictive Picture)

    • 1つ前のピクチャを参照することで得られるピクチャです
  • B Picture (Bi-direction predictiv Picture)

    • H.264 では、過去や未来の2枚のピクチャを参照することで得られるピクチャです
    • Baseline profile では利用できません
  • SI slice

    • SI slice はストリームの切り替えを行うための特殊なI sliceです。ffmpeg からは生成されません
  • SP slice

    • SP slice はストリームの切り替えを行うための特殊なP sliceです。ffmpeg からは生成されません
  • YUV Colour Formats

    • yuv4:2:0 などを指定できます。
    • ffmpeg で利用できる x264コーデックには yuv4:2:0 しか指定できません
  • MP4 file format version 2. ".mp4"

    • MP4 file format は ISO/IEC 14496-14:2003 で規定されています。 この規格書は、2001年に発行された ISO/IEC 14496-1:2001 を上書きするもので、 コミュニティからは MPEG-4 file format version 2 または MP4v2 と呼ばれています。
    • 拡張子が ".264" の物は MP4 コンテナに入っていない生の H.264 ビデオストリーム(moovの中身)です。
  • ISOBMFF (ISO Base Media File Format)

    • MP4Box 構造のことです
    • ISO/IEC 14496-12 で定義されています
  • VLC (Variable Length Coding)

    • ハフマン符号をベースとした可変長符号化です
  • IOD (Initial Object Descriptor)

    • 14496-14 で定義されています TODO: 詳細を記述
  • OD (Object Descriptors)

    • 14496-14 の 3.1.3 で定義されています
  • PCR (Program clock reference), OPCR (Original Program clock reference)

    • MPEG-2 TS における時刻情報です
    • MPEG-2 TS の PCR を AVC の PTS として持ちまわる事ができれば PTS の計算を省略できます(TODO: 要確認 → 出来ませんでした)
    • PCR は 27MHz(33bit * 300 + 9bit) でClockを管理しています
  • PCR Wrap-around

    • 33bit 部分は 90kHz の解像度を持ち、9bit の値(0〜299)の値を加える事で、900kHz * 300 = 27MHz の精度を出すように工夫されています
    • この33bit部分がラウンドアップし0に戻ることを PCR Wrap-around と呼びます。この現象は 0x1FFFFFFFF = 8589934591 (26:30:43.717) で発生します
    • PCR Wrap-around が発生すると音声と映像の同期が取れなくなり、映像に乱れが発生します
  • DTS (decoding time stamp, 復号時刻), PTS (presentation time stamp, 表示時刻)

    • MPEG-4 におけるI, P, B ピクチャを表示する時刻を指定するのが PTS で、デコードの順番を指示するのが DTS です。
    • PTS は DTS とその周辺情報などから算出しなければならない状況があるとか
  • PTS (Presentation Time Stamp)

    • コンテンツをいつ出力するかを指定したタイムスタンプ情報(33 bits)です。映像と音声の同期のために必要になります
    • デコーダは STC が PTS の示す時刻になるとデコード結果を映像や音声として出力します
  • STC (System Time Clock)

    • システム基準時刻です。内部クロックです
    • 90 kHz で駆動します
    • MPEG-1 のクロックはすべて90kHz単位です。STC, SCR, PTS も90KHzを基礎単位とする時刻情報となります
  • SCR (System Clock Reference)

    • ストリーム上でのシステムクロック情報(33 bits)です。
  • LipSync

    • MPEG-1 においては、音声と映像にずれが発生した場合は、音声を基準にずれを修正します
    • これは人間が音のずれに対してより敏感なためです
  • Mux (Multiplexing, Multiplexer)

    • Audio Elementary Stream と Video Elementary Stream を多重化することを Multiplexing (Mux, ミュックス) と呼びます。
  • Demux (Demultiplexing, Demultiplexer)

  • ESDescriptor (Elementary Stream Descriptor)

    • 14496-14 の 3.1.2 で定義されています
    • Audio Object Descriptor と Video Object Descriptor のビットストリームは Elementary Stream です
    • シーンを構成するそれぞれのオブジェクト毎にESDescriptorが存在します
  • BIFS (BInary Format for Scene description)

    • VRML (Visual Reality Modeling Language)を拡張したシーン記述言語です
    • 規格書には存在しますが、実装した民生品はありません
  • POC (Picture Order Count)

  • MMCO5 (memory_management_control_operation equal to 5)

  • MP4Boxes

    • MP4 box type 一覧 http://www.mp4ra.org/atoms.html

    • "ctts" atom, which has to be written when muxing b-frames into MP4

      ctts box は Bフレームを書き出す場合に必要です。つまり ctts がある場合は B フレームが存在します

    • "vol", which is placed on every keyframe in AVI, but has to be seperated from the movie data in MP4

      vol プロパティはキーフレーム毎に必要です。TODO: ??

  • ES (Elementary Stream)

    • 生オーディオデータやビデオデータは ES と呼ばれます
  • PS (Parameter Set)

    • sequence parameter set と picture parameter set を総称して Parameter Set と呼びます
  • Parameter Set Elementary Stream

    • elementary stream containing samples made up of only sequence and picture parameter set NAL units synchronized with the video elementary stream.

      このタイプのエレメンタリストリームに含まれるデータは、映像ストリームと同期した SPS と PPS の NALUnit です。他の種類のデータは含まれません

  • VideoES (VIDEO Elementary Stream)

    • elementary stream containing access units made up of NAL units for coded picture data

      このタイプのエレメンタリストリームに含まれるデータは、符号化された画像データです。他の種類のデータは含まれません

MPEG-4 圧縮データレイヤー構造

Source    |       ↓ 映像ソース
----------|--------------------
VCL       |       ↓ 符号化データ (Video Coding Layer)
----------|--------------------
NAL       |       ↓ 1byteのスタートコードの付与, バイトストリームへの変換 (Network Abstraction Layer)
----------|--------------------
MPEG-2 TS |       ↓

MPEG-4 圧縮されたピクチャデータの階層構造

  1. シーケンスレイヤ

    • シーケンスデータ。圧縮された画像データ

      +-------+----+   +-------+----+   +-------
      | GOP   | SH | + | GOP   | SH | + | ....
      +-------+----+   +-------+----+   +-------
      
  2. GOP レイヤ

    • 15枚程度の Bピクチャ, Pピクチャ, Iピクチャ をまとめたもの

      +-------+   +---++---++---++---++---++---++---++---+     +---+
      | GOP   | = | B || P || B || P || B || P || B || P | ... | I |
      +-------+   +---++---++---++---++---++---++---++---+     +---+
      
  3. ピクチャレイヤ

    • 1つのピクチャ(B or P or I)を 16 line でスライスしたもの。 1 line = 1px と考えても良い

      +-------------------------+
      | slice#1                 | 16 line
      +-------------------------+
      | slice#2                 |
      +-------------------------+
      |      :                  |
      +-------------------------+
      | slice#n                 |
      +-------------------------+
      
  4. スライスレイヤ

    • 1つのスライスを 16 画素でさらにスライスしたもの。1画素 = 1px と考えても良い

      +-------------------------+   +----+----+----+----+----+-----+----+
      | slice#n                 | = | MB | MB | MB | MB | MB | ... | MB |
      +-------------------------+   +----+----+----+----+----+-----+----+
      
  5. マクロブロックレイヤ

    • 1つのマクロブロックは4つのYとCb,Crで構成されている

               +-----+-----+   +----+   +----+
      +----+   |  Y  |  Y  | + | Cb | + | Cr | 8
      | MB | = |-----+-----+   +----+   +----+
      +----+   |  Y  |  Y  |              8
               +-----+-----+
                    16
      
  6. ブロックレイヤ

ByteStream, NAL file format

ByteStream.toNALUnit

ByteStream.toNALUnit(stream:ByteStreamUint8Array):NALUnitArray は、 Annex B ByteStream を NALUnit の配列に変換します。

コードを読み解くには ITU-T H.264 を参照してください。

ByteStream は 00 00 01 ... から始まるバイト列を1区切りとしています。この 00 00 01 をスタートコードと呼びます。

スタートコードの前に複数の余計な 00 が存在する場合もありますが、これらも正常なデータです。00 は適切に読み飛ばす必要があります。

00 00 00 00 00 01 nn nn といったバイト列は余計な00を読み飛ばし、00 00 01 nn nn として解釈する必要があります

MPEG-2 TS から取得できるバイナリデータは Byte stream format

MPEG-2 TS から取得できるバイナリデータは ByteStream format です

ByteStream 化された NALUnit は以下のようになっており、 スタートコードから次のスタートコードまでが1つのNALUnitに相当します。

+---------------+----------++---------------+----------+------
| 00 00 01      | NAL Unit || 00 00 01      | NAL Unit | ...
+---------------+----------++---------------+----------+------

ByteStream.toNALUnit の引数 stream に指定できるデータはこのフォーマットです。

MP4 が要求するバイナリデータは NAL file foramt

MP4 に埋め込んで使用するバイナリデータは NAL file format (H.264 Raw Stream) です。 それぞれの NALUnit の前に 4byte の NALUnitSize が存在します

+--------------------+----------++--------------------+----------+------
| NALUnitSize(4byte) | NAL Unit || NALUnitSize(4byte) | NAL Unit | ...
+--------------------+----------++--------------------+----------+------

NALUnit.toSNALUnit( ByteStream.toNALUnit(stream) ) でこのフォーマットに変換できます。

ffmpeg で 拡張子を.264 にすると、H.264 Raw Stream を出力できます。

ffmpeg が生成する H.264 Raw Stream には AUD, SPS, PPS は含まれず、IDR などのピクチャ情報と SEI のみが含まれます。

SPS と PPS は、MPEG-4 part 15 AVCDecoderConfigurationRecord に格納されます。

aligned(8) class AVCDecoderConfigurationRecord {
    unsigned int(8) configurationVersion = 1;
    unsigned int(8) AVCProfileIndication;
    unsigned int(8) profile_compatibility;
    unsigned int(8) AVCLevelIndication;
    bit(6) reserved = ‘111111’b;
    unsigned int(2) lengthSizeMinusOne;
    bit(3) reserved = ‘111’b;
    unsigned int(5) numOfSequenceParameterSets;
    for (i=0; i< numOfSequenceParameterSets; i++) {
        unsigned int(16) sequenceParameterSetLength ;
        bit(8*sequenceParameterSetLength) sequenceParameterSetNALUnit;
    }
    unsigned int(8) numOfPictureParameterSets;
    for (i=0; i< numOfPictureParameterSets; i++) {
        unsigned int(16) pictureParameterSetLength;
        bit(8*pictureParameterSetLength) pictureParameterSetNALUnit;
    }
}

Eaxmple

ADDR    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
------ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ---- ASCII ----- --- RULE ---
000000 00 00 00 01 09 f0 00 00 00 01 67 64 00 0a ac b8 ..........gd....
       ~~~~~~~~~~~ ~~~~~                                                    AUD
                         ~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~                      SPS
000010 40 8d 08 00 00 03 00 08 00 00 03 00 10 20 00 00 @............ ..
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                            SPS
                                                 ~~~~~
000020 00 01 68 ee 0f 2c 8b 00 00 01 06 05 ff ff 5b dc ..h..,........[.
       ~~~~~ ~~~~~~~~~~~~~~                                                 PPS
                            ~~~~~~~~ ~~~~~~~~~~~~~~~~~                      SEI
   :
   :
000280 3d 31 3a 31 2e 30 30 00 80 00 00 01 65 88 84 37 =1:1.00.....e..7
       ~~~~~~~~~~~~~~~~~~~~~~~~~~                                           SEI
                                  ~~~~~~~~ ~~~~~~~~~~~                      IDR
000290 7c ff ff e1 16 c4 4a e9 16 66 9e 80 a8 3f ad eb |.....J..f...?..
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002a0 19 17 6f 2e ed 71 93 90 da 5f b0 f2 00 33 18 d4 ..o..q..._...3..
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002b0 b1 56 27 f9 e4 fb a4 ae fa 52 0a 8e 05 e4 e4 ae .V'......R......
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002c0 07 a8 ee 0e 0e 77 f3 e2 03 5d 00 ee 2a 25 31 0a .....w...]..*%1.
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002d0 ff 9d 5e af 17 01 66 1e 2c 9b 30 00 24 c0 65 95 ..^...f.,.0.$.e.
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002e0 29 37 33 7e 9c 46 ab c7 71 aa 90 f0 7d 2a 20 db )73~.F..q...}* .
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
0002f0 fb 9a 31 ba bc e7 15 0c 11 96 98 9f df a2 06 bf ..1.............
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                      IDR
000300 71 af b9 ac a9 61 00 00 00 01 09 f0 00 00 00 01 q....a..........
       ~~~~~~~~~~~~~~~~~                                                    IDR
                         ~~~~~~~~~~~ ~~~~~                                  AUD
                                           ~~~~~~~~~~~                      SPS

Question

  1. 5枚のpng を合成した png.all.mp4 を ts に変換し、先頭のtsをmp4に変換したファイル assets/ff/png.all.mp4.00.ts.mp4 の mdat を見ると、BoxSize = 1958 もあり、明らかに大きい。

    mdat の内容を更にみると、AUD, SPS, PPS, SEI, IDR の後に AUD, SPS, PPS, IDR が 4つ存在する。 5つ分のIDRピクチャのほかに本来は不要なAUD,SPS,PPS,SEIが存在する状態になっているが、実際に利用されているIDRは1つのみである

    この様子は、testAVC_dump_ffmpeg_created_mp4_file_question1 で再現できる

    function testAVC_dump_ffmpeg_created_mp4_file_question1() {
        var verifyFile = "../assets/ff/png.all.mp4.00.ts.mp4";
    
        TypedArray.toArrayBuffer(verifyFile, function(buffer) {
            console.log("LOAD FROM: ", verifyFile, buffer.byteLength);
            global.mp4box = AVC.MP4Parser.parse( new Uint8Array(buffer) );
        });
    }
    
    console.dir(global.mp4box);
    HexDump(global.mp4box.root.mdat.data);

EBSP, RBSP, SODB

SODB, RBSP, EBSP の関係は以下の図のようになります。

EBSP の 00 00 03 0x は、 RBSP では 00 00 0x として解釈する必要があります(x には 0〜3 の数字が入ります)。 mdat に埋め込まれるバイナリデータは EBSP の 00 00 03 0x のままであり、RBSP の 00 00 0x ではありません。

NALUnitHeader をパースする段階では EBSP から RBSP を生成し、生成した RBSP をパースします。

+-------------------+   +------------++----------+     +------------++----------+
| H.264 Byte Stream | = | Start Code || NALUnit  | ... | Start Code || NALUnit  |
+-------------------+   +------------++----------+     +------------++----------+

+-------------------+   +---------------++------+
| NALUnit           | = | NALUnitHeader || EBSP |
+-------------------+   +---------------++------+

+-------------------+   +----+     +----+----+----+----+     +----+
| EBSP              | = | xx | ... | 00 | 00 | 03 | 0x | ... | xx |
+-------------------+   +----+     +----+----+----+----+     +----+

+-------------------+   +------+     +------++---------------++----------------------------+
| RBSP              | = | SODB | ... | SODB || RBSP stop bit || rbsp_alignment_zero_bit... |
+-------------------+   +------+     +------++---------------++----------------------------+

                        +------+     +------++---------------++----------------------------+
                        | 0xFF | ... | 0xFF ||       `1`     || `0000000` ... `0`          |
                        +------+     +------++---------------++----------------------------+

source

MP4 Sample, Chunk, Table

MP4 Box 構造から、ビデオとオーディオの切れ目を知るためには、stsc と stco を参照します。 さらに stsz の内容からフレームごとのデータの位置とサイズを知る事ができます。 再生時にビデオとオーディオの同期を取るには stts を参照してビデオの各フレーム、オーディオフレーム(格納単位)ごとの再生時間、さらに再生すべき時刻を取得します。

  • Sample
    • Sample は 1つのピクチャを構成する最小の単位のことです
    • IDR, Iピクチャなどの KeyFrame を構成する AccessUnit が含まれています
    • Sample のサイズ, 表示時刻などのヘッダ情報は、moov に格納されます
    • Sample のデータ(Stream)は mdat に格納されます
    • MP4 においては映像のヘッダとデータは別々の場所に格納されます
  • Chunk は複数の Sample をグループとしてまとめた単位のことです。
    • Chunk のデコード方法は stsd (Sample Description) で定義します
    • Sample Description は Chunk のデコード方法を記したもので、avc1avcC を総称したものです
  • avc1
    • avc1 にはピクチャを復元するために必要となる width, heightframe_count` が記載されています
  • avcC
    • avcC にはピクチャを復元するために必要となる SPS と PPS が格納されています
  • stts はサンプルの再生時間のリストです
  • stco はチャンクがファイルの何処に配置されているか(offset)のリストです
    • stco.chunk_offset に指定する値はファイルの先頭からのオフセット値ではなくmdat + 4 byte からのオフセット値です
    • stco.chunk_offset = 0 なら mdat の先頭にチャンクがあるという意味になります
 mdat Stream

| mdat         | | stsc         | | stsz         | | stsd          |

+--------------+ +--------------+ +--------------+ +---------------+
|              | |              | | Sample 1     | | Sample        |
|              | |              | +--------------+ | Description   |
|              | | Chunk 1      | | Sample 2     | |               |
|              | |              | +--------------+ |               |
|              | |              | | Sample 3     | |               |
|              | +--------------+ +--------------+ +---------------+
|              | +--------------+ +--------------+ +---------------+
|              | |              | | Sample 4     | | Sample        |
|              | |              | +--------------+ | Description   |
|              | | Chunk 2      | | Sample 5     | |               |
|              | |              | +--------------+ |               |
|              | |              | | Sample 6     | |               |
|              | +--------------+ +--------------+ +---------------+
|              | +--------------+ +--------------+ +---------------+
|              | | Chunk 3      | | Sample 7     | | Description   |
|              | +--------------+ +--------------+ +---------------+
|              | +--------------+ +--------------+ +---------------+
|              | | Chunk 4      | | Sample 8     | | Description   |
+--------------+ +--------------+ +--------------+ +---------------+

Sample Description: width, height, frame_count, profile, level, SPS, PPS

Appendix

stco.chunk_offset

stco.chunk_offset は、Sample が格納されているファイル内アドレスの先頭を意味します。

  • mdat のデータ部分の先頭アドレスを示します
  • mdat が複数存在する場合は、entry_count が複数になります

例: 以下の a.mp4 において、stco.samples[0].chunk_offset の値は mdat box のデータ部分の先頭アドレス(0x0030) を示します。この値はファイルの先頭を0としたオフセット値です。

a.mp4
0000 00 00 00 20 66 74 79 70 69 73 6F 6D 00 00 02 00 ....ftypisom....
0010 69 73 6F 6D 69 73 6F 32 61 76 63 31 6D 70 34 31 isomiso2avc1mp41
0020 00 00 00 08 66 72 65 65 00 00 03 C4 6D 64 61 74 ....free....mdat
0030 00 00 02 AD ....
     ^
    this

{
  "stco": {
    "BoxHead": 1664,
    "BoxSize": 20,
    "BoxType": "stco",
    "version": 0,
    "flags": 0,
    "entry_count": 1,
    "samples": [{
        "chunk_offset": 48
    }]
  }
}

Link

Clone this wiki locally