NAL Unit取得【mp4ファイル生成解説】
2025/05/04

mp4動画ファイル生成について、プログラマー向けに解説します。 大まかな流れとしては、各フレーム画像をエンコードし、mp4フォーマットに合わせてまとめます。 本記事では、全4工程中2番目の、エンコード結果から NAL Unit を取得する処理について、詳述します。
なお、実際にこれを用いて作られたWebアプリケーションがこの記事などにありますので、 プログラマー以外の方も、ぜひお試しください。

プログラミングブログ記事一覧
[PR]
mp4動画ファイル生成の工程
当ブログにおける、mp4動画ファイルを生成する工程は、以下の4ステップです。
本記事では「2.エンコード結果から NAL Unit を取得」を解説します。
VideoEncoderのエンコード結果

前工程で、VideoEncoderを使用してエンコードすることで、フレームごとのバイナリデータが取得でき、それを配列に保存していました。
各フレームのバイナリデータを詳細に確認すると、図のように、それぞれ複数の「NAL Unit」と呼ばれるもので構成されています。 mp4動画ファイル生成のためには、この解析が必要です。
NAL Unit
NAL Unit には、複数のフォーマットがあり、
今回は annexb を指定しました。この形式は、スタートコードと呼ばれる「00 00 00 01」または「00 00 01」 が区切りになります。 データ長がすぐにはわからず、今回の用途では扱いづらいです。 そのため、1回だけ内容を解析して、内容の長さがわかる AvcC 形式に変換しておきます。
AvcC形式の「データ長」には、NAL Unit ヘッダーの1バイトと、データ本体のバイト数の合計値を入れます。 データ長を収める自身のバッファサイズ(基本4バイト)は含めません。
注意点として、スタートコードのサイズが可変で、AvcC形式のデータ長は固定のため、AnnexB形式をAvcC形式に変換すると、サイズが変わる可能性があります。 そのため、スタートコードをデータ長に書き換えるのではなく、新たにバイナリデータを作る必要があります。
NAL Unit ヘッダー

次に、各 NAL Unit を解析するために、まず、先頭1バイトのNAL Unit ヘッダーを解析します。
ここで必要な情報は、 NAL Unit タイプ、つまり下位5ビットです。 具体的には 0x1f で & を取り、その値により処理を分岐します。
NAL Unit ヘッダー解析プログラム例
switch( iNalUnitHeader & 0x1f ) { // Instantaneous Decoding Refresh (IDR) picture case 0x05: // キーフレーム保存コード(略) // Non Instantaneous Decoding Refresh (Non-IDR) picture case 0x01: // フレームデータ保存コード(略) break; // Sequence Parameter Set (SPS) case 0x07: // SPS保存コード(略) break; // Picture Parameter Set (PPS) case 0x08: // PPS保存コード(略) break; }
NAL Unit タイプ
NAL Unit タイプ
内容
0x01
差分フレームデータ
0x05
キーフレームデータ
0x07
Sequence Parameter Set (SPS)
0x08
Picture Parameter Set (PPS)
NAL Unit タイプは数種類ありますが、当ブログのアプリケーションでは表の4種類のみ取り出します。
0x01 と 0x05 フレームデータ
動画圧縮には、画像をそのまま圧縮エンコードするキーフレームと、前画像からの差分を取得して圧縮エンコードする差分フレームがあります。
それぞれ対応する NAL Unit があり、0x01なら差分フレーム、0x05ならキーフレームです。 この2種類の NAL Unit は1フレームに必ず1つ含まれているので、確保して、配列に保持しておきます。
また、キーフレームのフレーム番号は、次の工程で必要になるため、別途保持しておきます。 前記コード例で case 0x05 に break が無いのは意図的で、キーフレーム専用処理のあと、フレーム共通処理を行っています。
0x07 と 0x08 パラメーターセット
NAL Unit には、エンコードのパラメーターが収められた、 0x07 SPS と、0x08 PPS も存在します。 1フレーム目のエンコードデータの中に含まれています。
この2つのパラメーターセットは、mp4動画ファイルに必須の情報のため、別途保管しておきます。
なお、このパラメーターセットは、VideoEncoder に annexb フォーマットを指定することで、取得できます。 それ以外のフォーマットでは、エンコードデータに含まれているかは不定のようで、手元で試したところ、含まれる環境と含まれない環境がありました。
その他
その他の NAL Unit は破棄します。
例えば、筆者が確認した範囲では、各フレームの最初に 0x06 (Supplemental Enhancement Information [SEI]) が来ますが、無視して問題ありません。 もしかしたら、筆者の知識不足で、必要なものがある可能性はありますが、破棄して動いていますので、現時点では問題無さそうです。
結果
これらの処理をして、図のように、フレームデータの配列と、SPSとPPSが取得できていれば、この工程は完了です。次の工程では、主にこの情報を用いて mp4のフォーマットであるボックス形式のファイルを生成します。 そちらはボックス形式のバイナリデータ生成の記事で詳細に解説していますので、併せてご覧ください。
なお、キーフレームは1フレーム目の他、途中で再度現れる場合もあります。
実践コード
本記事で解説した内容は、概念はmp4ファイルフォーマットに特有のものですが、 プログラミングは一般的な範囲のため、ソースコード例はほとんど載せていません。
もし、本記事に関する実際のコードを参考にされたい場合は、 この記事など、各mp4クリエイター記事のソースから、import 先を調べてみてください。 プログラムを読める方に限定するため、ここではあえて不親切にさせていただきますが、コードの再利用は、悪意の無い範囲でしたら、まったく問題ありません
[PR]
まとめ
本記事では、mp4動画ファイルを生成する工程のうち、エンコード結果から NAL Unit を取得する処理について解説しました。 次は、これを用いて mp4のフォーマットであるボックス形式のファイルを生成します。 詳細は解説記事の公開までお待ち下さい。
補足
- 本記事に記載のプログラムソースコードは、悪意のない範囲で自由に使用・改変していただいて問題ありません。ただし、ご自身の判断と責任でお願いします。
- 画像内のラスタライズ文字フォントにOpen Font LicenseのNoto Sans Japaneseを使用しております。
- ※各社の登録商標または商標について「®」「™」等の表記はしておりません。
- (本記事公開後)本記事公開後に公開された記事へのリンクを追加しております。
カテゴリー:プログラミング解説,mp4ファイル生成解説
[PR]
