FFmpeg で Dolby Digital Plus JOC を MP4 に mux すると Dolby Atmos として認識されなくなる問題

Last modified date

どうやって問題を認識したのか

Dolby Digital Plus JOC (E-AC-3 JOC) 音声を Android 10 の Dolby Atmos 対応端末の一部 (AQUOS や arrows など) で再生すると、再生中に以下のような通知が出る。ちなみに、JOC (Joint Object Coding) とは、Dolby Digital Plus (Enhanced AC-3、E-AC-3) で Dolby Atmos を実現するためのフォーマットのことである。

arrows NX9 で再生

Dolby ATOMS と誤字っているが、Dolby Atmos として認識されている事はわかる。

同じものを Dolby Atmos 対応の iPhone (iOS 15) / iPad (iPadOS 15) で再生し、AirPods Pro などで聴くと、音量調整画面に「ドルビーアトモス」の表記が出る。

iPad mini (第6世代) + AirPods Pro で再生

iOS 14 / iPadOS 14 以下の場合はログで確認できる。(もちろん iOS 15 / iPadOS 15 でも)

ACDDPAtmosDecoder.cpp:476:Initialize: (0x10f954040) Input format: 12 ch,  48000 Hz, 'ec+3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1536 frames/packet, 0 bytes/frame
ACDDPAtmosDecoder.cpp:479:Initialize: (0x10f954040) Output format: 12 ch,  48000 Hz, Float32, non-inter

12ch は 7.1.4ch のことで、iPhone / iPad は Dolby Atmos を 7.1.4ch にデコードしている。

ec+3 は Dolby Digital Plus JOC (E-AC-3 JOC) のことを指す。

code: ec+3

description: Enhanced AC-3 audio with JOC

The ‘MP4’ Registration Authority

一方、Dolby Digital や Dolby Digital Plus の 2.0ch や 5.1ch、7.1ch 音声を再生すると、先程の Android 端末の通知は「Dolby Audio」となる。

arrows NX9 で再生

iOS 15 / iPadOS 15 では、「マルチチャンネル」という表記になる。

iPad mini (第6世代) + AirPods Pro で再生

不思議なことに、Android や iOS / iPadOS に Dolby Atmos として認識されている Dolby Digital Plus JOC (E-AC-3 JOC) 音声を、FFmpeg で -c:a copy (再エンコードせずそのままコピー) して MP4 コンテナに mux (multiplex: 多重化) すると、Android 10 では「Dolby Audio」、iOS / iPadOS では「マルチチャンネル」として認識されてしまう。

念の為 iPadOS のログを確認すると、こうなっている。

ACDDPAtmosDecoder.cpp:476:Initialize: (0x10f95c040) Input format:  6 ch,  48000 Hz, 'ec-3' (0x00000000) 0 bits/channel, 0 bytes/packet, 1536 frames/packet, 0 bytes/frame
ACDDPAtmosDecoder.cpp:479:Initialize: (0x10f95c040) Output format:  6 ch,  48000 Hz, Float32, non-inter

この Dolby Digital Plus JOC 音声のコア部分 (JOC における Dolby Atmos 非対応機器用の互換用のダウンミックス音声であって、Dolby Digital Plus の Dependent Substream のことではない) は 5.1ch となっているため、6ch は 5.1ch のことを指していると思われる。

ec-3 は Dolby Atmos でない Dolby Digital Plus のことを指している。

code: ec-3

description: Enhanced AC-3 audio

The ‘MP4’ Registration Authority

どうやら、Dolby Digital Plus JOC の 非 Dolby Atmos 部分 (本来 Dolby Atmos 非対応機器用) のみが再生され、JOC が無視されてしまっているようだ。

参考

Dolby Audio の詳細や Dolby Digital Plus JOC の構造等に関しては、以下の記事で解説している。

何が違うのか

-c:a copy だけでは Dolby Atmos 用のメタデータか何かが引き継がれないのかとも思ったが、MediaArea の MediaInfo では問題なく Dolby Digital Plus with Dolby Atmos として認識れさている。

さらに、PC から AV アンプに音声をビットストリーム出力しても、きちんと Dolby Digital Plus with Dolby Atmos として認識されている。

これらのことから、音声ストリーム自体には問題がないようだ。

そこで、Dolby Stream Validator で検証してみると、以下のようなエラーが出た。

ERROR: For [EC3] stream, in MP4, the bitstream indicates Dolby Atmos content (the “addbsil” isn’t 0), but the EC3SpecificBox indicates non-atmos content (the “flag_ec3_extension_type_a” in EC3SpecificBox is FALSE).

validation result: FAILED

Dolby Stream Validator

Dolby Digital Plus のビットストリーム内の addbsil には Dolby Atmos のフラグが立っているにも関わらず、MP4 コンテナ内の EC3SpecificBox の flag_ec3_extension_type_a には Dolby Atmos フラグ立っていない、といった状況のようだ。詳細は [PDF] ETSI のホワイトペーパー にて。

これを FFmpeg でなんとかできないものかと、ffprobe で MP4 ファイルの情報を比較してみると、以下の部分が違っていた。

Dolby Atmos として扱われる Dolby Digital Plus (1)

major_brand     : mp42
minor_version   : 1
compatible_brands: mp42dby1isom

Dolby Atmos として扱われる Dolby Digital Plus (2)

major_brand     : dby1
minor_version   : 0
compatible_brands: dby1isommp42

Dolby Atmos として扱われる Dolby Digital Plus (3)

major_brand     : mp42
minor_version   : 1
compatible_brands: mp42dby1

5.1ch として扱われてしまう Dolby Digital Plus (FFmpeg で mux したもの)

major_brand     : isom
minor_version   : 512
compatible_brands: isomiso2avc1mp41

ffprobe では addbsil や flag_ec3_extension_type_a については確認できなかったものの、やはり Dolby Digital Plus のビットストリームのメタデータ自体には違いはなく、MP4 コンテナのメタデータ、具体的には Major Brand (major_brand) や Compatible Brands (compatible_brands) が違っていた。

うち、Dolby Atmos として認識される MP4 ファイルに共通して入っている dby1 が、どうやら Dolby 関連の Brand らしい。

code: dby1

description: MP4 files with Dolby content (e.g. Dolby AC-4, Dolby Digital Plus, Dolby TrueHD (Dolby MLP))

The ‘MP4’ Registration Authority

一方 FFmpeg で MP4 を mux した際は、デフォルトでは Major Brand が isom、Compatible Brands が isom、iso2、avc1、mp41 となるようで、そこに dby1 の姿はない。

Compatible Brands に dby1 を追加することで、もしかすると Dolby Atmos として認識してくれるのかもしれない。

何を試したのか

FFmpeg で flag_ec3_extension_type_a を操作する方法は分からなかったので、とりあえず Major Brand と Compatible Brands だけでもなんとかしてみようと思った。

FFmpeg で mux する際に -brand dby1 してみると、 Major Brand が dby1 に、Compatible Brands が dby1、iso2、avc1、mp41 になった。これを AQUOS / arrows や iPhone / iPad で再生してみたところ、Dolby Atmos としては扱われなかった。どうやら mp42 も必要らしい。

-brand mp42 では Major Brand が mp42 に、Compatible brands は mp42、iso2、avc1、mp41 となり、dby1 が入らない。これも Dolby Atmos として扱われなかったことから、mp42 と dby1 の両方が必要ということになる。

-brand mp42,dby1-brand mp42dby1isom を試してみても、 -brand mp42 と同じ結果になり、dby1 は無視された。

直接メタデータを叩こうと、-metadata:g compatible_brands=mp42dby1isom をしてもうまく行かなかった。

FFmpeg では、MP4 の Major Brand は任意の値に設定することはできても、Compatible Brands は FFmpeg が用意した Major Brand ごとのプリセットにしか設定できないようだ。

そもそも、Compatible Brands に mp42 と dby1 を同時設定できたところで、MP4 コンテナに「Dolby Digital Plus のビットストリームには Dolby Atmos 用の JOC のデータが含まれている」という情報 (flag_ec3_extension_type_a) を持たせることができるのかどうかは不明ではあるが…。

どう解決したのか

色々調べていると、どうやら The Dolby MP4 streaming muxer (dlb_mp4base) であれば、--mpeg4-brand で Major Brand を、--mpeg4-comp-brand で Compatible Brands を、それぞれ任意の値に設定することができるらしいという情報を得た。

dlb_mp4base は Dolby 公式ツールであるため、dby1 にも対応しているし、Dolby AC-4 や Dolby Vision の mux もできるときた。これならもしかすると何とかできるかもしれない。

せっかくなので、一括変換するバッチファイルを作成した。以下は、既に FFmpeg で mux した MP4 を Dolby Atmos として読み込ませるべく、FFmpeg で一度 demux し、dlb_mp4base で再度 mux している。

FFmpeg (ffmpeg.exe) と dlb_mp4base (mp4muxer.exe) の PATH は既に通している、あるいはカレントディレクトリに置いてあるものとする。

@echo off

md dlb_mp4base
for %%f in (*.mp4) do (
ffmpeg.exe -i "%%f" -c:v copy -an "dlb_mp4base\%%f.264"
ffmpeg.exe -i "%%f" -c:a copy -vn "dlb_mp4base\%%f.eac3"
ren "dlb_mp4base\%%f.eac3" "*.ec3"
mp4muxer.exe -i "dlb_mp4base\%%f.264" -i "dlb_mp4base\%%f.ec3" -o "dlb_mp4base\%%f" --mpeg4-comp-brand mp42,iso6,isom,dby1
del "dlb_mp4base\%%f.264"
del "dlb_mp4base\%%f.ec3"
)

解説

md dlb_mp4base

まず作業用フォルダ兼出力先フォルダとして、dlb_mp4base フォルダを生成。


for %%f in (*.mp4) do (

)

カレントディレクトリの全ての .mp4 ファイルに対して () 内の処理を行う。ファイル名は %%f に代入される。


ffmpeg.exe -i "%%f" -c:v copy -an "dlb_mp4base\%%f.264"

dlb_mp4base は入力として .mp4 などは受け付けていないようなので、FFmpeg で映像と音声を demux。まずは映像から。今回作業した映像のコーデックは全て MPEG-4 AVC (H.264) のため、拡張子 .264 で出力。


ffmpeg.exe -i "%%f" -c:a copy -vn "dlb_mp4base\%%f.eac3"

こちらは音声の出力。dlb_mp4base は Dolby Digital Plus (Enhanced AC-3) 音声の拡張子が .ec3 でないと認識しないようだが、FFmpeg は .ec3 では出せないようなので、一旦 .eac3 で出力。


ren "dlb_mp4base\%%f.eac3" "*.ec3"

Dolby Digital Plus 音声の拡張子を .eac3 から .ec3 へ変更。なお、dlb_mp4base はファイル名に日本語などが含まれていると処理できないので、そういった場合もここでリネームしておくと良い。


mp4muxer.exe -i "dlb_mp4base\%%f.264" -i "dlb_mp4base\%%f.ec3" -o "dlb_mp4base\%%f" --mpeg4-comp-brand mp42,iso6,isom,dby1

demux した映像と音声を dlb_mp4base に入力し、Compatible Brands を mp42、iso6、isom、dby1 とした上で、MP4 に mux。

ヘルプ (mp4muxer.exe -h で表示される他、GitHub 上の ソースコードからも読むことができる) によると、msdh も入れることが推奨されている。

mp4muxer usage examples:

To create an audio-only .mp4 file with EC-3 audio:
mp4muxer -o output.mp4 -i audio.ec3 –mpeg4-comp-brand mp42,iso6,isom,msdh,dby1

To multiplex AC-4 audio and H.264 video:
mp4muxer -o output.mp4 -i audio.ac4 -i video.h264 –mpeg4-comp-brand mp42,iso6,isom,msdh,dby1

dlb_mp4base

しかし、 msdh は MPEG-DASH 用の Brand で、今回はローカル再生したいだけなので、不必要と判断し省いている。

code: msdh
description: Media Segment conforming to the general format type for ISO base media file format.
specification: DASH

The ‘MP4’ Registration Authority

--mpeg4-brand を指定しない場合は (Compatible Brands に mp42 を入れなくとも) Major Brand は mp42 になる。

なお、今回は元のファイルは拡張子が .mp4 のため 出力ファイル名を %%f としても問題ないが、MKV や TS 等の場合は %%f.mp4 とする必要がある。その場合ファイル名が hoge.mkv.mp4 などとなってしまうので、気になる場合は ren コマンドで適宜修正すればよい。


del "dlb_mp4base\%%f.264"
del "dlb_mp4base\%%f.ec3"

一時ファイルを削除。


これを行うことで、AQUOS / arrows や iPhone / iPad にて MP4 内の Dolby Digital Plus を Dolby Atmos として扱うことができるようになった。

また、Dolby Stream Validator のチェックもパスできるようになった。

なお、一部のファイルでは

ERROR: For [EC3] stream, the bitstream fails the validation in "DDPInfoLib". 
validation result: FAILED

というエラーが出てしまうが、DDPInfoLib について検索しても、見事に何の情報もない。(今検索するとこの記事だけがヒットするようになっているはず)

とりあえず再生する分には問題がなかったし、ZTE の AXON 7 に元から入っている Leaf トレーラーを何もいじらずそのまま検証かけてもこのエラーが出たりもしたため (AmazeHorizon は問題なし)、とりあえずこのままで行こうと思う。

余談その1: Amazon Music や Apple Music ではどうしているのか

別記事で解析の際取得した、Amazon Music や Apple Music の Dolby Atmos 音源の入った MP4 ファイルではどうなっているのかを確認してみる。

まずは Amazon Music。Amazon Music は Dolby Atmos のフォーマットとしては、Echo Studio やサウンドバー向けには E-AC-3 JOC を、スマホやタブレット向けには AC-4 IMS を使用しているが、MP4 コンテナのメタデータは共通で以下の通りだった。

major_brand     : mp41
minor_version   : 0
compatible_brands: iso8isommp41dashcmfc

Amazon Music は iso8、isom、mp41、dash、cmfc となっている (それぞれの詳細は こちら )。dby1 も mp42 もないが、これでも Dolby Stream Validator には怒られていない。とはいえ Amazon Music はアプリ内でソフトウェアでコードを行っているため、本件のような問題は起きない。

一方端末側の E-AC-3 JOC デコーダーを使用する Apple Music ではどうか。

major_brand     : iso5
minor_version   : 1
compatible_brands: isomiso5hlsfcmfcccea

Apple Music は isom、iso5、hlsf、cmfc、ccea となっている。こちらも mp42 も dby1 もないが、Dolby Stream Validator には怒られないし、スマホやタブレットにも Dolby Atmos だと認識される。

ということは、flag_ec3_extension_type_a さえ適切に設定されていれば、Major Brand や Minor Brands は特に関係なかったということである。今までの苦労は何だったのか。

余談その2: Apple と HEVC と Dolby Vision の話

dlb_mp4base では、Dolby Vision の mux をすることもできる。Base Layer (BL) + Reference Processing Unit (RPU) の単層 Dolby Vision はもちろん、そこに Enhancement Layer (EL) も加えた2層式の Dolby Vision を扱うことも可能となっている。使い方に関してはプロファイルごとに異なるので、ヘルプを参照してほしい。

(参考) Dolby Vision 対応スマホ / タブレットはこちら:

なお、dlb_mp4base では UHD BD で使用される Dolby Vision Profile 7 (BL が UHD BD の HDR10 互換 (7.6) の2層 12bit Dolby Vision) の mux にも対応しているのだが、Dolby Stream Validator に

WARNING: For [DoVi] stream, in MP4, the profile 7 is not supported.

と怒られてしまう (エラーではなく警告ではあるが)。

端末が対応していないプロファイルの Dolby Vision を扱う際や、そもそも Dolby Vision 非対応な機器で再生する場合は、2層の Dolby Vision であれば映像の Base Layer のみと音声 (+必要に応じて字幕なども) を demux し、MP4 に mux したほうがファイルサイズは少なく済む。Dolby Vision のプロファイルについて 詳細はこちら

参考までに、iPhone / iPad が対応している Dolby Vision のプロファイルを載せておく (ソース)。

  • Profile 5: 単層 (BL + RPU) で 10bit。BL は独自の IPT 色空間を使用しており、非対応機器との互換性なし (5.0)。Apple TV+ 等で仕様。
  • Profile 8: 単層 (BL + RPU) で 10bit。BL は HDR10 互換のもの (8.1) と SDR 互換のもの (8.2) と HLG 互換のもの (8.4) とがある。うち iPhone / iPad が対応しているのは、HLG ベースの Profile 8.4 のみ。Profile 8.4 は、iPhone のカメラの Dolby Vision 撮影で使用。

AQUOS (R2 / R2 compact / R3 / R5G / R6、zero / zero2) が対応している Dolby Vision は以下の通り (ソース)。

  • Profile 4: 単層 (BL + RPU) で 10bit。BL は SDR 互換 (4.2)。用途不明。
  • Profile 5: 先述の通り。
  • Profile 8: 仕様は先述の通り。AQUOS が 8.1、8.2、8.4のどれに対応しているのかまでは不明。
  • Profile 9: 単層 (BL + RPU) で8bit。BL は SDR 互換 (9.2)。用途不明。

なお、dlb_mp4base で MPEG-H HEVC (H.265) を mux した場合、映像の Codec ID (FourCC) は強制的に hev1 (非 Dolby Vision) か dvhe (Dolby Vision) になるのだが、iPhone / iPad は hvc1 (非 Dolby Vision) か dvh1 (Dolby Vision) の HEVC しか対応していない (再生方法によっては再生できる場合もあるが、推奨されていない)。

FFmpeg であれば -tag:v hvc1 で hvc1 を指定することもできるのだが、hev1 や hvc1 は MP4 などのコンテナフォーマット用のメタデータであり、FFmpeg で demux する際に -c:v copy -tag:v hvc1 hoge.265 などをしても意味はない。

SDR であれば AVC にでも変換すればいいが、HDR の AVC となると Dolby Vision の Profile 0.2 (今は使われない)、Profile 1 (今は使われない) 、Profile 9.2 といった、いずれも FFmpeg 等では変換できない上に、そもそも iPhone / iPad が非対応なフォーマットぐらいしかない。

なので、現状 HDR な HEVC と Dolby Atmos な Dolby Digital Plus / Dolby AC-4 の組み合わせをうまく iPhone / iPad で再生する手段はない。困った。


井戸水

ガジェットやオーディオビジュアルが好きな人。

コメントを残す…