Atmos Detection
Created by: ndjamena
TrueHD
00 9A FF D8 F8 72 6F BA 00 57 A0 0F B7 52 00 00 00 00 85 87 20 3C 01 80 45 56 E3 06 E3 00 07 DD
Atmos
B1 68 FF D8 F8 72 6F BA 00 67 80 4F B7 52 10 00 00 00 89 FA 43 FC 00 00 4B 4F E9 07 E9 01 1F C6
OK, see that '01' on the thirtieth byte? (third to the right)
THAT is atmos.
_Correction_
The third byte signals a header extension, as displayed in the code samples below. If the extension is empty then it's not atmos. (Apparently normal TrueHD files exist with that extension active, yet empty).-
_New Information:_ https://github.com/MediaArea/MediaInfoLib/commit/8b9e16985005da448a6c03939f7fcd073b360b52
This is Delphi code to detect atmos:
function ParseThdMajorSyncHeader(buffer: TPAByte; len: int64; ...) : integer; begin
atmos := false;
if (len >= 32) and (TPCardinal(@buffer[4])^ = $ba6f72f8) then begin
if buffer[29] and 1 <> 0 then begin
headerSize := 32 + (buffer[30] shr 4) * 2;
atmos := true;
end else
headerSize := 30;
And this is the code in the next version of MediaInfo:
Element_Begin1("MajorSync");
Skip_B3( "Synch");
Get_B1 (HD_StreamType, "Stream type"); Param_Info1(AC3_HD_StreamType(HD_StreamType));
if (HD_StreamType==0xBA)
{
BS_Begin();
Get_S1 ( 4, HD_SamplingRate1, "Sampling rate"); Param_Info2(AC3_HD_SamplingRate(HD_SamplingRate1), " Hz");
Skip_S1( 8, "Unknown");
Get_S1 ( 5, HD_Channels1, "Channels (1st substream)"); Param_Info1(AC3_TrueHD_Channels(HD_Channels1)); Param_Info1(Ztring().From_Local(AC3_TrueHD_Channels_Positions(HD_Channels1)));
Skip_S1( 2, "Unknown");
Get_S2 (13, HD_Channels2, "Channels (2nd substream)"); Param_Info1(AC3_TrueHD_Channels(HD_Channels2)); Param_Info1(Ztring().From_Local(AC3_TrueHD_Channels_Positions(HD_Channels2)));
BS_End();
HD_Resolution2=HD_Resolution1=24; //Not sure
HD_SamplingRate2=HD_SamplingRate1;
}
else if (HD_StreamType==0xBB)
{
BS_Begin();
Get_S1 ( 4, HD_Resolution1, "Resolution1"); Param_Info2(AC3_MLP_Resolution[HD_Resolution1], " bits");
Get_S1 ( 4, HD_Resolution2, "Resolution2"); Param_Info2(AC3_MLP_Resolution[HD_Resolution2], " bits");
Get_S1 ( 4, HD_SamplingRate1, "Sampling rate"); Param_Info2(AC3_HD_SamplingRate(HD_SamplingRate1), " Hz");
Get_S1 ( 4, HD_SamplingRate2, "Sampling rate"); Param_Info2(AC3_HD_SamplingRate(HD_SamplingRate2), " Hz");
Skip_S1(11, "Unknown");
Get_S1 ( 5, HD_Channels1, "Channels"); Param_Info1(AC3_MLP_Channels[HD_Channels1]);
BS_End();
HD_Channels2=HD_Channels1;
}
else
{
Skip_XX(Element_Size-Element_Offset, "Data");
return;
}
Skip_B6( "Unknown");
BS_Begin();
Get_SB ( HD_IsVBR, "Is VBR");
Get_S2 (15, HD_BitRate_Max, "Maximum bitrate"); Param_Info2((HD_BitRate_Max*(AC3_HD_SamplingRate(HD_SamplingRate2)?AC3_HD_SamplingRate(HD_SamplingRate2):AC3_HD_SamplingRate(HD_SamplingRate1))+8)>>4, " bps");
Get_S1 ( 4, HD_SubStreams_Count, "SubStreams_Count");
Skip_S1( 4, "Unknown");
BS_End();
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
Skip_B1( "Unknown");
BS_Begin();
Skip_S1( 7, "Unknown");
bool HasExtend;
Get_SB ( HasExtend, "Has Extend");
BS_End();
if (HasExtend)
{
unsigned char Extend = 0;
unsigned char Unknown = 0;
bool HasContent = false;
BS_Begin();
Get_S1( 4, Extend, "Extend Header");
Get_S1( 4, Unknown, "Unknown");
if (Unknown)
HasContent = true;
BS_End();
for (Extend = (Extend * 2) + 1; Extend > 0; Extend--)
{
Get_B1(Unknown, "Unknown");
if (Unknown)
HasContent = true;
}
if (HasContent)
HD_HasAtmos=true; //Currently only Atmos is known as having data here
}
Element_End0();
_New Information:_ https://github.com/MediaArea/MediaInfoLib/commit/8b9e16985005da448a6c03939f7fcd073b360b52
And THIS:
https://github.com/foo86/dcadec/issues/37
Is how you detect DTS:X.
There seems to be additional data present after normal frequency band data in each XLL frame. That can be possibly attributed to DTS:X metadata. With the following patch applied you'll see lots of XLL: NNNN bits left [0x2000850] messages where amount of extra bits fluctuates from few hundred to tens of thousands. 0x2000850 signature is the same for all frames (probably a sync word).
There is no need to fully parse the band data, you just need to get to the NAVI table by parsing/skipping XLL common header and channel set sub-headers (each header contains its size so there is no need to parse all the fields). From NAVI table you can calculate total size of band data and skip over it to DTS:X signature.