/* Copyright (c) MediaArea.net SARL. All Rights Reserved. * * Use of this source code is governed by a BSD-style license that can * be found in the License.html file in the root of the source tree. */ //--------------------------------------------------------------------------- // Pre-compilation #include "MediaInfo/PreComp.h" #ifdef __BORLANDC__ #pragma hdrstop #endif //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Setup.h" //--------------------------------------------------------------------------- //*************************************************************************** // Infos (Common) //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_AC3_YES) || defined(MEDIAINFO_DOLBYE_YES) || defined(MEDIAINFO_DVDV_YES) || defined(MEDIAINFO_MPEG4_YES) || defined(MEDIAINFO_MPEGPS_YES) || defined(MEDIAINFO_MPEGTS_YES) || defined(MEDIAINFO_MIXML_YES) //--------------------------------------------------------------------------- #include "ZenLib/Conf.h" #include using namespace ZenLib; namespace MediaInfoLib { //--------------------------------------------------------------------------- extern const float64 Mpegv_frame_rate[16]; //--------------------------------------------------------------------------- extern const int32u AC3_SamplingRate[]= { 48000, 44100, 32000, 0,}; //--------------------------------------------------------------------------- const char* AC3_Mode[] = { "CM", "ME", "VI", "HI", "D", "C", "E", "VO", }; //--------------------------------------------------------------------------- const char* AC3_Mode_String[] = { "Complete Main", "Music and Effects", "Visually Impaired", "Hearing Impaired", "Dialogue", "Commentary", "Emergency", "Voice Over", }; //--------------------------------------------------------------------------- const char* AC3_Surround[]= { "", "Not Dolby Surround encoded", "Dolby Surround encoded", "", }; //--------------------------------------------------------------------------- extern const int16u AC3_BitRate[]= { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640, }; //--------------------------------------------------------------------------- extern const int8u AC3_Channels[]= {2, 1, 2, 3, 3, 4, 4, 5}; //--------------------------------------------------------------------------- static const char* AC3_dynrngprof[]= { "Film Standard", "Film Light", "Music Standard", "Music Light", "Speech", }; extern std::string AC3_dynrngprof_Get(int8u Value) { if (!Value) return {}; if (Value>sizeof(AC3_dynrngprof)/sizeof(AC3_dynrngprof[0])) return std::to_string(Value); return AC3_dynrngprof[Value - 1]; } //--------------------------------------------------------------------------- } //NameSpace //--------------------------------------------------------------------------- #endif //... //--------------------------------------------------------------------------- //*************************************************************************** // //*************************************************************************** //--------------------------------------------------------------------------- #if defined(MEDIAINFO_AC3_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Audio/File_Ac3.h" #include #include #if MEDIAINFO_EVENTS #include "MediaInfo/MediaInfo_Config_MediaInfo.h" #include "MediaInfo/MediaInfo_Events_Internal.h" #endif //MEDIAINFO_EVENTS #include "MediaInfo/MediaInfo_Internal.h" using namespace ZenLib; using namespace std; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Infos //*************************************************************************** //--------------------------------------------------------------------------- const int32u AC3_SamplingRate2[]= { 24000, 22050, 16000, 0,}; //--------------------------------------------------------------------------- const char* AC3_ChannelPositions[]= { "Dual mono", "Front: C", "Front: L R", "Front: L C R", "Front: L R, Back: C", "Front: L C R, Back: C", "Front: L R, Side: L R", "Front: L C R, Side: L R", }; //--------------------------------------------------------------------------- const char* AC3_ChannelPositions2[]= { "1+1", "1/0/0", "2/0/0", "3/0/0", "2/1/0", "3/1/0", "2/2/0", "3/2/0", }; //--------------------------------------------------------------------------- const char* AC3_ChannelLayout_lfeoff[]= { "M M", "M", "L R", "L R C", "L R S", "L R C Cs", "L R Ls Rs", "L R C Ls Rs", }; //--------------------------------------------------------------------------- const char* AC3_ChannelLayout_lfeon[]= { "1+1 LFE", "C LFE", "L R LFE", "L R C LFE", "L R S LFE", "L R C LFE Cs", "L R LFE Ls Rs", "L R C LFE Ls Rs", }; //--------------------------------------------------------------------------- extern const char* AC3_roomtyp[]= { "Large", "Small", "3", }; //--------------------------------------------------------------------------- extern const char* AC3_dmixmod[]= { "Lt/Rt", "Lo/Ro", "3", }; //--------------------------------------------------------------------------- extern string AC3_Level_Value(int8u Index, float Start, float Multiplier) { return Index == 7 ? string("-inf") : Ztring::ToZtring((Start - (int)Index * Multiplier), 1).To_UTF8(); } //--------------------------------------------------------------------------- extern void AC3_Level_Fill(File__Analyze* A, size_t StreamPos, int8u Index, float Start, float Multiplier, const char* Name) { string Value = AC3_Level_Value(Index, Start, Multiplier); A->Fill(Stream_Audio, StreamPos, Name, Value); A->Fill_SetOptions(Stream_Audio, StreamPos, Name, "N NT"); string Name_String = string(Name) + "/String"; A->Fill(Stream_Audio, StreamPos, Name_String.c_str(), Value + " dB"); A->Fill_SetOptions(Stream_Audio, StreamPos, Name_String.c_str(), "Y NTN"); } //--------------------------------------------------------------------------- int16u AC3_acmod2chanmap[]= { 0xA000, 0x4000, 0xA000, 0xE000, 0xA100, 0xE100, 0xB800, 0xF800, }; //--------------------------------------------------------------------------- Ztring AC3_chanmap_ChannelPositions (int16u chanmap) { Ztring Front; Ztring Side; Ztring Back; Ztring More; for (int8u Pos=0; Pos<16; Pos++) { if (chanmap&(1<<(15-Pos))) { switch (Pos) { case 0 : Front+=__T(" L"); break; case 1 : Front+=__T(" C"); break; case 2 : Front+=__T(" R"); break; case 3 : Side+=__T(" L"); break; case 4 : Side+=__T(" R"); break; case 5 : { bool HasR=false; if (Front.find(__T(" R"))!=string::npos) { Front.resize(Front.size()-2); HasR=true; } Front+=__T(" C C"); if (HasR) Front+=__T(" R"); } break; case 6 : Back+=__T(" L R"); break; case 7 : if (Back.empty()) Back=__T(" C"); else Back=__T(" L C R"); break; case 15 : More+=__T(", LFE"); break; default: ; } } } Ztring ToReturn; if (!Front.empty()) { ToReturn+=__T("Front:")+Front; } if (!Side.empty()) { if (!ToReturn.empty()) ToReturn+=__T(", "); ToReturn+=__T("Side:")+Side; } if (!Back.empty()) { if (!ToReturn.empty()) ToReturn+=__T(", "); ToReturn+=__T("Back:")+Back; } ToReturn+=More; return ToReturn; } //--------------------------------------------------------------------------- int8u AC3_chanmap_Channels (int16u chanmap) { int8u Channels=0; for (int8u Pos=0; Pos<16; Pos++) { if (chanmap&(1<<(15-Pos))) { switch (Pos) { case 5 : case 6 : case 9 : case 10 : case 11 : case 13 : Channels+=2; break; default: Channels++; break; } } } return Channels; } //--------------------------------------------------------------------------- static const char* AC3_chanmap_ChannelLayout_List[16] = { "L", "C", "R", "Ls", "Rs", "Lc Rc", "Lrs Rrs", "Cs", "Ts", "Lsd Rsd", "Lw Rw", "Lvh Rvh", "Vhc", // Cvh is a typo in specs "Lts Rts", "LFE2", "LFE", }; Ztring AC3_chanmap_ChannelLayout (int16u chanmap, const Ztring &ChannelLayout0) { Ztring ToReturn=ChannelLayout0; for (int8u Pos=5; Pos<15; Pos++) // Custom ones only { if (chanmap&(1<<(15-Pos))) { if (!ChannelLayout0.empty()) ToReturn+=__T(' '); ToReturn+=Ztring().From_UTF8(AC3_chanmap_ChannelLayout_List[Pos]); } } return ToReturn; } //--------------------------------------------------------------------------- static const char* AC3_nonstd_bed_channel_assignment_mask_ChannelLayout_List[17] = { "L", "R", "C", "LFE", "Ls", "Rs", "Lrs", "Rrs", "Lvh", // Lfh in spec but same as Lvh from E-AC-3 "Rvh", // Rfh in spec but same as Rvh from E-AC-3 "Lts", // Ltm in spec but same as Lts from E-AC-3 "Rts", // Rtm in spec but same as Rts from E-AC-3 "Lrh", "Rrh", "Lw", "Rw", "LFE2", }; static int8s AC3_nonstd_bed_channel_assignment_mask_ChannelLayout_Reordering[17] = { 0, 0, 0, 0, 0, 0, 0, 0, 6, // Wide channels before top layer 6, // Wide channels before top layer -2, -2, -2, -2, -2, -2, 0, }; Ztring AC3_nonstd_bed_channel_assignment_mask_ChannelLayout(int32u nonstd_bed_channel_assignment_mask) { Ztring ToReturn; for (int8u i=0; i<17; i++) { int8u i2=i+AC3_nonstd_bed_channel_assignment_mask_ChannelLayout_Reordering[i]; if (nonstd_bed_channel_assignment_mask&(1<1) ToReturn|=(1<<(j++)); } else j+=AC3_bed_channel_assignment_mask_ChannelLayout_Mapping[i]; } return ToReturn; } //--------------------------------------------------------------------------- const int16u AC3_FrameSize[27][4]= { { 128, 138, 192, 0}, { 160, 174, 240, 0}, { 192, 208, 288, 0}, { 224, 242, 336, 0}, { 256, 278, 384, 0}, { 320, 348, 480, 0}, { 384, 416, 576, 0}, { 448, 486, 672, 0}, { 512, 556, 768, 0}, { 640, 696, 960, 0}, { 768, 834, 1152, 0}, { 896, 974, 1344, 0}, {1024, 1114, 1536, 0}, {1280, 1392, 1920, 0}, {1536, 1670, 2304, 0}, {1792, 1950, 2688, 0}, {2048, 2228, 3072, 0}, {2304, 2506, 3456, 0}, {2560, 2786, 3840, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 0, 0, 0, 0}, { 768, 0, 0, 0}, }; //--------------------------------------------------------------------------- int16u AC3_FrameSize_Get(int8u frmsizecod, int8u fscod) { bool Padding=(frmsizecod%2)?true:false; int16u frame_size_id=frmsizecod/2; if (frame_size_id>26 || fscod>3) return 0; int16u FrameSize=AC3_FrameSize[frame_size_id][fscod]; if (fscod==1 && Padding) FrameSize+=2; // frame lengths are padded by 1 word (16 bits) at 44100 Hz return FrameSize; } //--------------------------------------------------------------------------- // CRC_16_Table // A CRC is computed like this: // Init: int32u CRC_16 = 0x0000; // for each data byte do // CRC_16=(CRC_16<<8) ^ CRC_16_Table[(CRC_16>>8)^(data_byte)]; extern const int16u CRC_16_Table[256] = { 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 }; int CRC16_Init(int16u *Table, int16u Polynomial) { for (size_t Pos=0; Pos<256; Pos++) { Table[Pos]=(int16u)Pos<<8; for(int8u bit=0; bit<8; bit++) { if (Table[Pos]&0x8000) Table[Pos]=(Table[Pos]<<1)^Polynomial; else Table[Pos]=Table[Pos]<<1; } } return 0; } //--------------------------------------------------------------------------- extern const float64 AC3_dynrng[]= { 6.02, 12.04, 18.06, 24.08, -18.06, -12.04, - 6.02, 0.00, }; //--------------------------------------------------------------------------- extern const float64 AC3_compr[]= { 6.02, 12.04, 18.06, 24.08, 30.10, 36.12, 42.14, 48.16, -42.14, -36.12, -30.10, -24.08, -18.06, -12.04, - 6.02, 0.00, }; //--------------------------------------------------------------------------- const char* AC3_HD_StreamType(int8u StreamType) { switch (StreamType) { case 0xBA : return "TrueHD"; case 0xBB : return "MLP"; default : return ""; } } //--------------------------------------------------------------------------- int32u AC3_HD_SamplingRate(int8u SamplingRate) { if (SamplingRate==0xF) return 0; return ((SamplingRate&8)?44100:48000)<<(SamplingRate&7) ; } //--------------------------------------------------------------------------- static const int8u AC3_TrueHD_ChannelCountPerBit[13]= { 2, //LR 1, //C 1, //LFE 2, //LRs 2, //LRvh 2, //LRc 2, //LRrs 1, //Cs 1, //Ts 2, //LRsd 2, //LRw 1, //Cvh 1, //LFE2 }; //--------------------------------------------------------------------------- int8u AC3_TrueHD_Channels(int16u ChannelsMap) { int8u Channels=0; for (int8u Pos=0; Pos<13; Pos++) Channels+=AC3_TrueHD_ChannelCountPerBit[Pos]*((ChannelsMap>>Pos)&0x1); return Channels; } //--------------------------------------------------------------------------- std::string AC3_TrueHD_Channels_Positions(int16u ChannelsMap, bool Bit11=false) { std::string Text; if ((ChannelsMap&0x0003)==0x0003) Text+="Front: L C R"; else { if (ChannelsMap&0x0001) Text+="Front: C"; if (ChannelsMap&0x0002) Text+="Front: L, R"; } if (ChannelsMap&0x08) Text+=", Side: L R"; if (ChannelsMap&0x80) Text+=", Back: C"; if ((ChannelsMap&0x0810)==0x0810 && Bit11) Text+=", vh: L C R"; else { if (ChannelsMap&0x0010 && !Bit11) Text+=", vh: L R"; if (ChannelsMap&0x0800) Text+=", vh: C"; } if (ChannelsMap&0x0020) Text+=", c: L R"; if (ChannelsMap&0x0040) Text+=", Back: L R"; if (ChannelsMap&0x0100) Text+=", s: T"; if (ChannelsMap&0x0200) Text+=", sd: L R"; if (ChannelsMap&0x0400) Text+=", w: L R"; if (ChannelsMap&0x0004) Text+=", LFE"; if (ChannelsMap&0x1000) Text+=", LFE2"; return Text; } //--------------------------------------------------------------------------- Ztring AC3_TrueHD_Channels_Positions2(int16u ChannelsMap, bool Bit11=false) { int8u Front=0, Surround=0, Rear=0, LFE=0; if (ChannelsMap&0x0001) Front++; if (ChannelsMap&0x0002) Front+=2; if (ChannelsMap&0x08) Surround+=2; if (ChannelsMap&0x80) Surround++; if (ChannelsMap & 0x0010) Rear+=2; //vh if (!Bit11) { if (ChannelsMap&0x0800) Rear++; //vh if (ChannelsMap&0x0020) Rear+=2; //c if (ChannelsMap&0x0040) Rear+=2; //rs if (ChannelsMap&0x0100) Rear+=2; //s if (ChannelsMap&0x0200) Rear+=2; //sd if (ChannelsMap&0x0400) Rear+=2; //w if (ChannelsMap&0x0004) LFE++; if (ChannelsMap&0x1000) LFE++; } Ztring Text; Text+=Ztring::ToZtring(Front); Text+=__T('/')+Ztring::ToZtring(Surround); Text+=__T('/')+Ztring::ToZtring(Rear); Text+=__T('.')+Ztring::ToZtring(LFE); return Text; } //--------------------------------------------------------------------------- static const size_t AC3_TrueHD_ChannelLayoutNames_Size=13; const char* AC3_TrueHD_ChannelLayoutNames[AC3_TrueHD_ChannelLayoutNames_Size]= { "L R", "C", "LFE", "Ls Rs", "Tfl Tfr", "Lsc Rsc", "Lb Rb", "Cb", "Tc", "Lsd Rsd", "Lw Rw", "Tfc", "LFE2", }; static const size_t AC3_TrueHD_ChannelLayoutNames2_Size=1; const char* AC3_TrueHD_ChannelLayoutNames2[AC3_TrueHD_ChannelLayoutNames2_Size]= { "Tsl Tsr", }; std::string AC3_TrueHD_Channels_ChannelLayout(int16u ChannelsMap, bool Bit11=false) { if (ChannelsMap==2) return "M"; std::string Text; for (size_t i=0; i<16; i++) if (ChannelsMap&(1<=AC3_TrueHD_ChannelLayoutNames_Size) || (Bit11 && i>=4 && i-4>=AC3_TrueHD_ChannelLayoutNames2_Size)) { Text+='+'; //Unknown layout return Text; } Text+=(Bit11 && i>=4)?AC3_TrueHD_ChannelLayoutNames2[i-4]:AC3_TrueHD_ChannelLayoutNames[i]; } return Text; } //--------------------------------------------------------------------------- static const int32u AC3_MLP_Channels[32]= { 1, 2, 3, 4, 3, 4, 5, 3, 4, 5, 4, 5, 6, 4, 5, 4, 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; //--------------------------------------------------------------------------- static const int32u AC3_MLP_Resolution[16]= { 16, 20, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; //--------------------------------------------------------------------------- const char* Ac3_emdf_payload_id[16]= { "Container End", "Programme loudness data", "Programme information", "E-AC-3 substream structure", "Dynamic range compression data for portable devices", "Programme Language", "External Data", "Headphone rendering data", "", "", "", "OAMD", "", "Personalized Audio Mix-Graph", "JOC", "", }; //--------------------------------------------------------------------------- int32u Ac3_variable_bits(BitStream_Fast &Search2, int8u Bits) { int32u Info = 0; for (;;) { Info += Search2.Get4(Bits); if (!Search2.GetB()) break; Info <<= Bits; Info += (1 << Bits); } return Info; } //--------------------------------------------------------------------------- bool Ac3_EMDF_Test(const BitStream_Fast &Search) { BitStream_Fast Search2(Search); Search2.Skip(16); //syncword size_t Size=((size_t)Search2.Get2(16))*8+17; //emdf_container_length if (Size>Search2.Remain()) return false; size_t End=Search2.Remain()-Size; if (Search2.Get1(2)) //emdf_version return false; if (Search2.Get1(3) == 0x7) //key_id Ac3_variable_bits(Search2, 3); for (;;) { int8u emdf_payload_id=Search2.Get1(5); if (!emdf_payload_id) break; if (emdf_payload_id == 0x1F) Ac3_variable_bits(Search2, 5); bool smploffste=Search2.GetB(); if (smploffste) Search2.Skip(12); if (Search2.GetB()) //duratione Ac3_variable_bits(Search2, 11); //duration if (Search2.GetB()) //groupide Ac3_variable_bits(Search2, 2); //groupid if (Search2.GetB()) //codecdatae return false; //must be 0 if (!Search2.GetB()) //discard_unknown_payload { bool payload_frame_aligned=false; if (!smploffste) { payload_frame_aligned=Search2.GetB(); if (payload_frame_aligned) Search2.Skip(2); } if (smploffste || payload_frame_aligned) Search2.Skip(7); } size_t emdf_payload_size=((size_t)Ac3_variable_bits(Search2, 8))*8; Search2.Skip(emdf_payload_size); } int8u protection_length_primary=Search2.Get1(2); switch (protection_length_primary) { case 0: return false; case 1: protection_length_primary=8; break; case 2: protection_length_primary=32; break; case 3: protection_length_primary=128; break; default: ; } int8u protection_bits_secondary=Search2.Get1(2); switch (protection_bits_secondary) { case 0: protection_bits_secondary=0; break; case 1: protection_bits_secondary=8; break; case 2: protection_bits_secondary=32; break; case 3: protection_bits_secondary=128; break; default: ; } Search2.Skip(protection_length_primary); Search2.Skip(protection_bits_secondary); return Search2.Remain()>=17?true:false; } //--------------------------------------------------------------------------- /* static const int8u ecplsubbndtab[]= { 13, 19, 25, 31, 37, 49, 61, 73, 85, 97, 109, 121, 133, 145, 157, 169, 181, 193, 205, 217, 229, 241, 253, }; */ //*************************************************************************** // Constructor/Destructor //*************************************************************************** //--------------------------------------------------------------------------- File_Ac3::File_Ac3() :File__Analyze() { //Configuration #if MEDIAINFO_EVENTS ParserIDs[0]=MediaInfo_Parser_Ac3; StreamIDs_Width[0]=0; #endif //MEDIAINFO_EVENTS #if MEDIAINFO_TRACE Trace_Layers_Update(8); //Stream #endif //MEDIAINFO_TRACE MustSynchronize=true; Buffer_TotalBytes_FirstSynched_Max=64*1024; Buffer_TotalBytes_Fill_Max=1024*1024; PTS_DTS_Needed=true; StreamSource=IsStream; Frame_Count_NotParsedIncluded=0; //In Frame_Count_Valid=0; MustParse_dac3=false; MustParse_dec3=false; MustParse_dmlp=false; CalculateDelay=false; //Buffer Save_Buffer=NULL; //Temp Frame_Count_HD=0; addbsi_Buffer=NULL; addbsi_Buffer_Size=0; fscod=0; fscod2=0; frmsizecod=0; bsid_Max=(int8u)-1; Formats[0]=0; Formats[1]=0; for (int8u Pos=0; Pos<8; Pos++) for (int8u Pos2=0; Pos2<9; Pos2++) { frmsizplus1_Max[Pos][Pos2]=0; acmod_Max[Pos][Pos2]=(int8u)-1; lfeon_Max[Pos][Pos2]=false; bsmod_Max[Pos][Pos2]=0; cmixlev_Max[Pos][Pos2]=(int8u)-1; surmixlev_Max[Pos][Pos2]=(int8u)-1; roomtyp_Max[Pos][Pos2]=(int8u)-1; dmixmod_Max[Pos][Pos2]=(int8u)-1; dsurmod_Max[Pos][Pos2]=0; chanmape_Max[Pos][Pos2]=false; chanmap_Max[Pos][Pos2]=0; } numblkscod=(int8u)-1; dsurexmod=0; dheadphonmod=0; substreamid_Independant_Current=0; substreams_Count=0; joc_complexity_index_Container=(int8u)-1; joc_complexity_index_Stream=(int8u)-1; num_dynamic_objects=(int8u)-1; nonstd_bed_channel_assignment_mask=(int32u)-1; dxc3_Parsed=false; HD_MajorSync_Parsed=false; Core_IsPresent=false; HD_IsPresent=false; HD_HasAtmos=false; dynrnge_Exists=false; TimeStamp_IsPresent=false; TimeStamp_IsParsing=false; TimeStamp_Parsed=false; TimeStamp_Count=0; BigEndian=true; IgnoreCrc_Done=false; } //--------------------------------------------------------------------------- File_Ac3::~File_Ac3() { delete[] addbsi_Buffer; } //*************************************************************************** // Streams management //*************************************************************************** //--------------------------------------------------------------------------- void File_Ac3::Streams_Fill() { if (dxc3_Parsed) { if (Count_Get(Stream_Audio)==0) Stream_Prepare(Stream_Audio); } if (HD_MajorSync_Parsed) { if (Count_Get(Stream_Audio)==0) Stream_Prepare(Stream_Audio); if (HD_BitRate_Max) Fill(Stream_Audio, 0, Audio_BitRate_Maximum, (HD_BitRate_Max*AC3_HD_SamplingRate(HD_SamplingRate2)+8)>>4); if (HD_StreamType==0xBA) //TrueHD { { Fill(Stream_Audio, 0, Audio_Format, "MLP FBA"); Fill(Stream_Audio, 0, Audio_Codec, "MLP FBA"); } if (HD_HasAtmos) { Fill(Stream_Audio, 0, Audio_Format_Profile, "MLP FBA 16-ch / MLP FBA"); Fill(Stream_Audio, 0, Audio_Codec_Profile, "MLP FBA 16-ch / MLP FBA"); } Fill(Stream_Audio, 0, Audio_BitRate_Mode, "VBR"); Fill(Stream_Audio, 0, Audio_Compression_Mode, "Lossless"); Ztring Sampling; Sampling.From_Number(AC3_HD_SamplingRate(HD_SamplingRate1)); Fill(Stream_Audio, 0, Audio_SamplingRate, Sampling); Fill(Stream_Audio, 0, Audio_Channel_s_, AC3_TrueHD_Channels(HD_Channels2)); Fill(Stream_Audio, 0, Audio_ChannelPositions, AC3_TrueHD_Channels_Positions(HD_Channels2, HD_flags&(1<<11))); Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, AC3_TrueHD_Channels_Positions2(HD_Channels2, HD_flags&(1<<11))); Fill(Stream_Audio, 0, Audio_ChannelLayout, AC3_TrueHD_Channels_ChannelLayout(HD_Channels2, HD_flags&(1<<11))); } if (HD_StreamType==0xBB) //TrueHD { { Fill(Stream_Audio, 0, Audio_Format, "MLP"); Fill(Stream_Audio, 0, Audio_Codec, "MLP"); } Fill(Stream_Audio, 0, Audio_BitRate_Mode, "VBR"); Fill(Stream_Audio, 0, Audio_Compression_Mode, "Lossless"); Fill(Stream_Audio, 0, Audio_SamplingRate, AC3_HD_SamplingRate(HD_SamplingRate2)); if (HD_SamplingRate1!=HD_SamplingRate2) Fill(Stream_Audio, 0, Audio_SamplingRate, AC3_HD_SamplingRate(HD_SamplingRate2)); Fill(Stream_Audio, 0, Audio_Channel_s_, AC3_MLP_Channels[HD_Channels1]); if (MediaInfoLib::Config.LegacyStreamDisplay_Get() && HD_Channels1!=HD_Channels2) Fill(Stream_Audio, 0, Audio_Channel_s_, AC3_MLP_Channels[HD_Channels1]); Fill(Stream_Audio, 0, Audio_BitDepth, AC3_MLP_Resolution[HD_Resolution2]); if (MediaInfoLib::Config.LegacyStreamDisplay_Get() && HD_Resolution1!=HD_Resolution2) Fill(Stream_Audio, 0, Audio_BitDepth, AC3_MLP_Resolution[HD_Resolution1]); } } bool HasJOC = joc_num_objects_map.size()==1 && (joc_num_objects_map.begin()->second >= Frame_Count_Valid / 8 || joc_num_objects_map.begin()->second >= Frame_Count / 8); //Accepting that some frames do not contain JOC if (HasJOC || HD_HasAtmos) { if (Count_Get(Stream_Audio)==0) Stream_Prepare(Stream_Audio); if (HasJOC) { Fill(Stream_Audio, 0, Audio_Format_Profile, bsid_Max<=0x09?"AC-3 JOC":"E-AC-3 JOC"); Fill(Stream_Audio, 0, Audio_Codec_Profile, bsid_Max<=0x09?"AC-3 JOC":"E-AC-3 JOC"); } if (dxc3_Parsed && joc_complexity_index_Container!=(int8u)-1) Fill(Stream_Audio, 0, "ComplexityIndex", joc_complexity_index_Container); if (dxc3_Parsed && joc_complexity_index_Container==(int8u)-1 && joc_complexity_index_Stream!=(int8u)-1) Fill(Stream_Audio, 0, "ComplexityIndex", "Not present"); if (joc_complexity_index_Stream!=(int8u)-1 && joc_complexity_index_Stream!=joc_complexity_index_Container) Fill(Stream_Audio, 0, "ComplexityIndex", joc_complexity_index_Stream); if (dxc3_Parsed && joc_complexity_index_Container!=(int8u)-1 && joc_complexity_index_Stream==(int8u)-1) Fill(Stream_Audio, 0, "ComplexityIndex", "Not present"); if (num_dynamic_objects!=(int8u)-1) Fill(Stream_Audio, 0, "NumberOfDynamicObjects", num_dynamic_objects); if (nonstd_bed_channel_assignment_mask !=(int32u)-1) { Ztring BedChannelConfiguration=AC3_nonstd_bed_channel_assignment_mask_ChannelLayout(nonstd_bed_channel_assignment_mask); size_t BedChannelCount=0; if (!BedChannelConfiguration.empty()) for (size_t i=0; iFrame_Count/2) // In case of corrupted stream, check that there is a minimal count of timestamps TimeStamp_BitRate+=float32_int32s(AC3_SamplingRate[fscod]/Divider/12.0); // 12 = 1536 samples per frame / 128 bits per timestamp frame Fill(Stream_Audio, 0, Audio_BitRate, BitRate/Divider); if (TimeStamp_BitRate) Fill(Stream_Audio, 0, Audio_BitRate_Encoded, BitRate/Divider+TimeStamp_BitRate); if (CalculateDelay && Buffer_TotalBytes_FirstSynched>100 && BitRate>0) { Fill(Stream_Audio, 0, Audio_Delay, (float)Buffer_TotalBytes_FirstSynched*8*1000/BitRate, 0); Fill(Stream_Audio, 0, Audio_Delay_Source, "Stream"); } } Fill(Stream_Audio, 0, Audio_ServiceKind, AC3_Mode[bsmod_Max[0][0]]); Fill(Stream_Audio, 0, Audio_ServiceKind_String, AC3_Mode_String[bsmod_Max[0][0]]); if ((MediaInfoLib::Config.LegacyStreamDisplay_Get() || Retrieve(Stream_Audio, 0, Audio_ChannelLayout).empty()) && acmod_Max[0][0]!=(int8u)-1) { int8u Channels=AC3_Channels[acmod_Max[0][0]]; Ztring ChannelPositions; ChannelPositions.From_UTF8(AC3_ChannelPositions[acmod_Max[0][0]]); Ztring ChannelPositions2; ChannelPositions2.From_UTF8(AC3_ChannelPositions2[acmod_Max[0][0]]); Ztring ChannelLayout; ChannelLayout.From_UTF8(lfeon_Max[0][0]?AC3_ChannelLayout_lfeon[acmod_Max[0][0]]:AC3_ChannelLayout_lfeoff[acmod_Max[0][0]]); if (lfeon_Max[0][0]) { Channels+=1; ChannelPositions+=__T(", LFE"); ChannelPositions2+=__T(".1"); } if (Ztring::ToZtring(Channels)!=Retrieve(Stream_Audio, 0, Audio_Channel_s_)) Fill(Stream_Audio, 0, Audio_Channel_s_, Channels); if (ChannelPositions!=Retrieve(Stream_Audio, 0, Audio_ChannelPositions)) Fill(Stream_Audio, 0, Audio_ChannelPositions, ChannelPositions); if (ChannelPositions2!=Retrieve(Stream_Audio, 0, Audio_ChannelPositions_String2)) Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, ChannelPositions2); if (Retrieve(Stream_Audio, 0, Audio_ChannelLayout).empty()) Fill(Stream_Audio, 0, Audio_ChannelLayout, ChannelLayout); } if (!Retrieve(Stream_Audio, 0, Audio_Format_Profile).empty()) Fill(Stream_Audio, 0, Audio_Format_Profile, "AC-3"); if (!Retrieve(Stream_Audio, 0, Audio_Codec_Profile).empty()) Fill(Stream_Audio, 0, Audio_Codec_Profile, "AC-3"); if ((MediaInfoLib::Config.LegacyStreamDisplay_Get() && __T("CBR")!=Retrieve(Stream_Audio, 0, Audio_BitRate_Mode)) || Retrieve(Stream_Audio, 0, Audio_BitRate_Mode).empty()) Fill(Stream_Audio, 0, Audio_BitRate_Mode, "CBR"); } //E-AC-3 else if (bsid_Max<=0x10) { for (size_t Pos=0; Pos<8; Pos++) if (acmod_Max[Pos][0]!=(int8u)-1) { if (Count_Get(Stream_Audio)==0) Stream_Prepare(Stream_Audio); if (Retrieve(Stream_Audio, 0, Audio_Format).empty()) { Fill(Stream_Audio, 0, Audio_Format, Formats[0]?"AC-3":"E-AC-3"); Fill(Stream_Audio, 0, Audio_Codec, Formats[0] ?"AC-3":"AC3+"); } if (acmod_Max[1][0]!=(int8u)-1) Fill(Stream_Audio, 0, Audio_ID, 1+Pos); Fill(Stream_Audio, 0, Audio_BitRate_Mode, "CBR"); int32u SamplingRate; if (fscod!=3) SamplingRate=AC3_SamplingRate[fscod]; else SamplingRate=AC3_SamplingRate2[fscod2]; Fill(Stream_Audio, 0, Audio_SamplingRate, SamplingRate); if (numblkscod!=(int8u)-1) { int8u numblks=numblkscod==3?6:numblkscod+1; int32u frmsiz_Total=0; for (size_t Pos2=0; Pos2<8; Pos2++) frmsiz_Total+=frmsizplus1_Max[Pos][Pos2]; int32u TimeStamp_Size=0; if (TimeStamp_Count==Frame_Count || TimeStamp_Count>Frame_Count/2) // In case of corrupted stream, check that there is a minimal count of timestamps TimeStamp_Size=16; if (frmsiz_Total) Fill(Stream_Audio, 0, Audio_BitRate, ((int64u)frmsiz_Total)*SamplingRate/32/numblks); if (TimeStamp_Size) Fill(Stream_Audio, 0, Audio_BitRate_Encoded, ((int64u)frmsiz_Total+TimeStamp_Size)*SamplingRate/32/numblks); } if (acmod_Max[Pos][1]!=(int8u)-1) { int16u chanmap_Final=0; for (int8u Pos2=0; Pos2<9; Pos2++) if (acmod_Max[Pos][Pos2]!=(int8u)-1) { if (chanmape_Max[Pos][Pos2]) chanmap_Final|=chanmap_Max[Pos][Pos2]; else { chanmap_Final|=AC3_acmod2chanmap[acmod_Max[Pos][Pos2]]; if (lfeon_Max[Pos][Pos2]) chanmap_Final|=1; // LFE position in chanmap is bit 0 } } Fill(Stream_Audio, 0, Audio_Format_Profile, "E-AC-3+Dep"); Fill(Stream_Audio, 0, Audio_Codec_Profile, "E-AC-3+Dep"); Fill(Stream_Audio, 0, Audio_Channel_s_, AC3_chanmap_Channels(chanmap_Final)); Fill(Stream_Audio, 0, Audio_ChannelPositions, AC3_chanmap_ChannelPositions(chanmap_Final)); Ztring ChannelPositions2; ChannelPositions2.From_UTF8(AC3_ChannelPositions2[acmod_Max[0][0]]); //TODO: handle the dependancy if (lfeon_Max[Pos][0]) { ChannelPositions2+=__T(".1"); } Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, ChannelPositions2); if (MediaInfoLib::Config.LegacyStreamDisplay_Get() || Retrieve(Stream_Audio, 0, Audio_ChannelLayout).empty()) { Ztring ChannelLayout; ChannelLayout.From_UTF8(lfeon_Max[0][0]?AC3_ChannelLayout_lfeon[acmod_Max[0][0]]:AC3_ChannelLayout_lfeoff[acmod_Max[0][0]]); Fill(Stream_Audio, 0, Audio_ChannelLayout, AC3_chanmap_ChannelLayout(chanmap_Final, ChannelLayout)); } } if (!Retrieve(Stream_Audio, 0, Audio_Format_Profile).empty()) Fill(Stream_Audio, 0, Audio_Format_Profile, Retrieve(Stream_Audio, 0, Audio_Format)); if (!Retrieve(Stream_Audio, 0, Audio_Codec_Profile).empty()) Fill(Stream_Audio, 0, Audio_Codec_Profile, Retrieve(Stream_Audio, 0, Audio_Format)); Fill(Stream_Audio, 0, Audio_ServiceKind, AC3_Mode[bsmod_Max[0][0]]); Fill(Stream_Audio, 0, Audio_ServiceKind_String, AC3_Mode_String[bsmod_Max[0][0]]); if ((MediaInfoLib::Config.LegacyStreamDisplay_Get() || Retrieve(Stream_Audio, 0, Audio_Channel_s_).empty()) && acmod_Max[Pos][0]!=(int8u)-1) { int8u Channels=AC3_Channels[acmod_Max[Pos][0]]; Ztring ChannelPositions; ChannelPositions.From_UTF8(AC3_ChannelPositions[acmod_Max[Pos][0]]); Ztring ChannelPositions2; ChannelPositions2.From_UTF8(AC3_ChannelPositions2[acmod_Max[0][0]]); if (lfeon_Max[Pos][0]) { Channels+=1; ChannelPositions+=__T(", LFE"); ChannelPositions2+=__T(".1"); } Fill(Stream_Audio, 0, Audio_Channel_s_, Channels); Fill(Stream_Audio, 0, Audio_ChannelPositions, ChannelPositions); Fill(Stream_Audio, 0, Audio_ChannelPositions_String2, ChannelPositions2); Fill(Stream_Audio, 0, Audio_ChannelLayout, lfeon_Max[0][0]?AC3_ChannelLayout_lfeon[acmod_Max[0][0]]:AC3_ChannelLayout_lfeoff[acmod_Max[0][0]]); } } } if (HD_MajorSync_Parsed) { //Filling Maximum bitrate with the constant core bitrate for better coherancy ZtringList List; List.Separator_Set(0, __T(" / ")); List.Write(Retrieve(Stream_Audio, 0, Audio_BitRate)); if (List.size()>=2) Fill(Stream_Audio, 0, Audio_BitRate_Maximum, List[1]); } //Dolby Metadata if (Core_IsPresent) { //Endianess Fill(Stream_Audio, 0, Audio_Format_Settings_Endianness, BigEndian?"Big":"Little"); Fill(Stream_Audio, 0, "bsid", bsid_Max); Fill(Stream_Audio, 0, "dialnorm", FirstFrame_Dolby.dialnorm==0?-31:-FirstFrame_Dolby.dialnorm); Fill_SetOptions(Stream_Audio, 0, "dialnorm", "N NT"); Fill(Stream_Audio, 0, "dialnorm/String", Ztring::ToZtring(FirstFrame_Dolby.dialnorm==0?-31:-FirstFrame_Dolby.dialnorm)+__T(" dB")); Fill_SetOptions(Stream_Audio, 0, "dialnorm/String", "Y NTN"); if (FirstFrame_Dolby.compre) { float64 Value; if (FirstFrame_Dolby.compr ==0) Value=0; //Special case in the formula else Value=AC3_compr[FirstFrame_Dolby.compr>>4]+20*std::log10(((float)(0x10+(FirstFrame_Dolby.compr&0x0F)))/32); Fill(Stream_Audio, 0, "compr", Value, 2); Fill_SetOptions(Stream_Audio, 0, "compr", "N NT"); Fill(Stream_Audio, 0, "compr/String", Ztring::ToZtring(Value, 2)+__T(" dB")); Fill_SetOptions(Stream_Audio, 0, "compr/String", "Y NTN"); } if (FirstFrame_Dolby.dynrnge) { float64 Value; if (FirstFrame_Dolby.dynrng==0) Value=0; //Special case in the formula else Value=AC3_dynrng[FirstFrame_Dolby.dynrng>>5]+20*std::log10(((float)(0x20+(FirstFrame_Dolby.dynrng&0x1F)))/64); Fill(Stream_Audio, 0, "dynrng", Value, 2); Fill_SetOptions(Stream_Audio, 0, "dynrng", "N NT"); Fill(Stream_Audio, 0, "dynrng/String", Ztring::ToZtring(Value, 2)+__T(" dB")); Fill_SetOptions(Stream_Audio, 0, "dynrng/String", "Y NTN"); } for (int8u Pos=0; Pos<8; Pos++) for (int8u Pos2=0; Pos2<9; Pos2++) { if (acmod_Max[Pos][Pos2]==(int8u)-1) break; else { if (acmod_Max[Pos][Pos2]==2) { Fill(Stream_Audio, 0, "dsurmod", dsurmod_Max[Pos][Pos2]); Fill_SetOptions(Stream_Audio, 0, "dsurmod", "N NT"); Fill(Stream_Audio, 0, "dsurmod/String", AC3_Surround[dsurmod_Max[Pos][Pos2]]); Fill_SetOptions(Stream_Audio, 0, "dsurmod/String", "Y NTN"); } Fill_SetOptions(Stream_Audio, 0, "bsid", "N NT"); Fill(Stream_Audio, 0, "acmod", acmod_Max[Pos][Pos2]); Fill_SetOptions(Stream_Audio, 0, "acmod", "N NT"); Fill(Stream_Audio, 0, "lfeon", (lfeon_Max[Pos][Pos2])?1:0); Fill_SetOptions(Stream_Audio, 0, "lfeon", "N NT"); } } } //TimeStamp if (TimeStamp_IsPresent) { Ztring TimeCode_FrameRate=Ztring::ToZtring(TimeStamp_FirstFrame.GetFrameRate(), 3); auto TimeStamp_FirstFrame_String=TimeStamp_FirstFrame.ToString(); int64s TimeStamp_FirstFrame_Milliseconds=TimeStamp_FirstFrame.ToMilliseconds(); if (TimeStamp_FirstFrame_SampleNumber) { TimeStamp_FirstFrame_String+='-'+to_string(TimeStamp_FirstFrame_SampleNumber); auto SamplingRate=Retrieve(Stream_Audio, 0, Audio_SamplingRate).To_int32u(); if (SamplingRate) { TimeStamp_FirstFrame_String+='S'; TimeStamp_FirstFrame_String+=to_string(SamplingRate); TimeStamp_FirstFrame_Milliseconds+=((int32u)TimeStamp_FirstFrame_SampleNumber)*1000/SamplingRate; } } Fill(Stream_Audio, 0, "TimeCode_FirstFrame", TimeStamp_FirstFrame_String); Fill_SetOptions(Stream_Audio, 0, "TimeCode_FirstFrame", "N YCY"); Fill(Stream_Audio, 0, "TimeCode_FirstFrame/String", TimeStamp_FirstFrame_String+" ("+TimeCode_FrameRate.To_UTF8()+" fps), embedded in stream"); Fill_SetOptions(Stream_Audio, 0, "TimeCode_FirstFrame/String", "Y NTN"); Fill(Stream_Audio, 0, "TimeCode_FirstFrame_FrameRate", TimeCode_FrameRate); Fill_SetOptions(Stream_Audio, 0, "TimeCode_FirstFrame_FrameRate", "N YFY"); Fill(Stream_Audio, 0, "TimeCode_Source", "Stream"); Fill_SetOptions(Stream_Audio, 0, "TimeCode_Source", "N YTY"); Fill(Stream_Audio, 0, Audio_Delay, TimeStamp_FirstFrame_Milliseconds); Fill(Stream_Audio, 0, Audio_Delay_Source, "Stream"); Fill(Stream_Audio, 0, Audio_Delay_Settings, TimeStamp_FirstFrame.IsDropFrame()?"drop_frame_flag=1":"drop_frame_flag=0"); } //Samples per frame int16u SamplesPerFrame; if (bsid_Max<=0x08) SamplesPerFrame=1536; else if (bsid_Max<=0x09) SamplesPerFrame=768; // Unofficial hack for low sample rate (e.g. 22.05 kHz) else if (bsid_Max>0x0A && bsid_Max<=0x10 && numblkscod!=(int8u)-1) SamplesPerFrame=256*(numblkscod==3?6:(numblkscod+1)); else if (HD_MajorSync_Parsed && (HD_StreamType==0xBA || HD_StreamType==0xBB)) // TrueHD or MLP { int64u HD_SamplingRate=Retrieve_Const(Stream_Audio, 0, Audio_SamplingRate).To_int64u(); if (HD_SamplingRate<44100) SamplesPerFrame=0; //Unknown else if (HD_SamplingRate<=48000) SamplesPerFrame=40; else if (HD_SamplingRate<=96000) SamplesPerFrame=80; else if (HD_SamplingRate<=192000) SamplesPerFrame=160; else SamplesPerFrame=0; //Unknown } else SamplesPerFrame=0; if (SamplesPerFrame) Fill(Stream_Audio, 0, Audio_SamplesPerFrame, SamplesPerFrame); // Commercial name if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("E-AC-3") || Retrieve(Stream_Audio, 0, Audio_Format_Profile).find(__T("E-AC-3"))==0) { if (HasJOC) Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "Dolby Digital Plus with Dolby Atmos"); else Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "Dolby Digital Plus"); } else if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("MLP FBA") || Retrieve(Stream_Audio, 0, Audio_Format_Profile).find(__T("MLP FBA"))==0) { if (HasJOC || HD_HasAtmos) Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "Dolby TrueHD with Dolby Atmos"); else Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "Dolby TrueHD"); } else if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("MLP") || Retrieve(Stream_Audio, 0, Audio_Format_Profile).find(__T("MLP"))==0) { Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "MLP Lossless"); } else if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("AC-3")) Fill(Stream_Audio, 0, Audio_Format_Commercial_IfAny, "Dolby Digital"); Fill(Stream_General, 0, General_Format, Retrieve(Stream_Audio, 0, Audio_Format), true); Fill(Stream_General, 0, General_Format_Profile, Retrieve(Stream_Audio, 0, Audio_Format_Profile)); Fill(Stream_General, 0, General_Format_Commercial_IfAny, Retrieve(Stream_Audio, 0, Audio_Format_Commercial_IfAny)); // Other metadata if (cmixlev_Max[0][0]<=2) { string Value = Ztring::ToZtring(-3 - ((float)cmixlev_Max[0][0]) * 1.5, 1).To_UTF8(); Fill(Stream_Audio, 0, "cmixlev", Value); Fill_SetOptions(Stream_Audio, 0, "cmixlev", "N NT"); Fill(Stream_Audio, 0, "cmixlev/String", Value + " dB"); Fill_SetOptions(Stream_Audio, 0, "cmixlev/String", "Y NTN"); } if (surmixlev_Max[0][0]<=2) { string Value = (surmixlev_Max[0][0] == 2 ? string("-inf") : to_string(-3 - (int)surmixlev_Max[0][0] * 3)); Fill(Stream_Audio, 0, "surmixlev", Value + " dB"); Fill_SetOptions(Stream_Audio, 0, "surmixlev", "N NT"); Fill(Stream_Audio, 0, "surmixlev/String", Value + " dB"); Fill_SetOptions(Stream_Audio, 0, "surmixlev/String", "Y NTN"); } if (roomtyp_Max[0][0]!=(int8u)-1) { string Value = to_string(80 + mixlevel_Max[0][0]); Fill(Stream_Audio, 0, "mixlevel", Value); Fill_SetOptions(Stream_Audio, 0, "mixlevel", "N NT"); Fill(Stream_Audio, 0, "mixlevel/String", Value + " dB"); Fill_SetOptions(Stream_Audio, 0, "mixlevel/String", "Y NTN"); if (roomtyp_Max[0][0]) { Fill(Stream_Audio, 0, "roomtyp", AC3_roomtyp[roomtyp_Max[0][0] - 1]); Fill_SetOptions(Stream_Audio, 0, "roomtyp", "Y NTY"); } } if (dmixmod_Max[0][0]!=(int8u)-1) { if (dmixmod_Max[0][0]) { Fill(Stream_Audio, 0, "dmixmod", AC3_dmixmod[dmixmod_Max[0][0] - 1]); Fill_SetOptions(Stream_Audio, 0, "dmixmod", "Y NTY"); } AC3_Level_Fill(this, 0, ltrtcmixlev_Max[0][0], 3, 1.5, "ltrtcmixlev"); AC3_Level_Fill(this, 0, ltrtsurmixlev_Max[0][0], 3, 1.5, "ltrtsurmixlev"); AC3_Level_Fill(this, 0, lorocmixlev_Max[0][0], 3, 1.5, "lorocmixlev"); AC3_Level_Fill(this, 0, lorosurmixlev_Max[0][0], 3, 1.5, "lorosurmixlev"); if (adconvtyp_Max[0][0]) { Fill(Stream_Audio, 0, "adconvtyp", "HDCD"); Fill_SetOptions(Stream_Audio, 0, "adconvtyp", "Y NTY"); } } } //--------------------------------------------------------------------------- void File_Ac3::Streams_Finish() { //Stats if (!dialnorms.empty()) { int8u Minimum_Raw=1; int8u Maximum_Raw=31; float64 Sum_Intensity=0; int64u Count=0; for (int8u Pos=0; (size_t)Pos(Pos==0?31:Pos)) Maximum_Raw=(Pos==0?31:Pos); Sum_Intensity+=dialnorms[Pos]*pow(10, -((float64)Pos)/10); Count+=dialnorms[Pos]; } if (Count) { float64 Average_dB = log10(Sum_Intensity / Count) * 10; Fill(Stream_Audio, 0, "dialnorm_Average", Average_dB, 0); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Average", "N NT"); Fill(Stream_Audio, 0, "dialnorm_Average/String", Ztring::ToZtring(Average_dB, 0) + __T(" dB")); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Average/String", "Y NTN"); Fill(Stream_Audio, 0, "dialnorm_Minimum", -Minimum_Raw); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Minimum", "N NT"); Fill(Stream_Audio, 0, "dialnorm_Minimum/String", Ztring::ToZtring(-Minimum_Raw) + __T(" dB")); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Minimum/String", "Y NTN"); Fill(Stream_Audio, 0, "dialnorm_Maximum", -Maximum_Raw); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Maximum", "N NTN"); Fill(Stream_Audio, 0, "dialnorm_Maximum/String", Ztring::ToZtring(-Maximum_Raw) + __T(" dB")); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Maximum/String", "Y NTN"); Fill(Stream_Audio, 0, "dialnorm_Count", Count); Fill_SetOptions(Stream_Audio, 0, "dialnorm_Count", "N NTN"); } } if (!comprs.empty()) { float64 Minimum_dB=47.89; float64 Maximum_dB=-48.16; float64 Sum_Intensity=0; int64u Count=0; for (size_t Pos=0; Pos>4]+20*std::log10(((float)(0x10+(Pos&0x0F)))/32); if (Minimum_dB>Value) Minimum_dB=Value; if (Maximum_dB>5]+20*std::log10(((float)(0x20+(Pos&0x1F)))/64); if (Minimum_dB>Value) Minimum_dB=Value; if (Maximum_dBParseSpeed>=1) { Frame_Count_ForDuration=Frame_Count; //We have the exact count of frames Fill(Stream_Audio, 0, Audio_StreamSize, File_Offset+Buffer_Offset+Element_Size-File_Offset_FirstSynched); } else if (bsid_Max<=9 && frmsizecods.size()==1 && fscods.size()==1 && Frame_Count_HD==0) { int16u Size=AC3_FrameSize_Get(frmsizecods.begin()->first, fscods.begin()->first); if (Size) { if (TimeStamp_IsPresent) Size+=16; Frame_Count_ForDuration=(File_Size-File_Offset_FirstSynched)/Size; //Only complete frames Fill(Stream_Audio, 0, Audio_StreamSize, Frame_Count_ForDuration*Size); } } if (Frame_Count_ForDuration) { Clear(Stream_Audio, 0, Audio_BitRate); //HD part if (Frame_Count_HD) { int32u HD_SamplingRate=AC3_HD_SamplingRate(HD_SamplingRate1); if (HD_SamplingRate) { int8u FrameDuration; //In samples if (HD_SamplingRate<44100) FrameDuration=0; //Unknown else if (HD_SamplingRate<=48000) FrameDuration=40; else if (HD_SamplingRate<=96000) FrameDuration=80; else if (HD_SamplingRate<=192000) FrameDuration=160; else FrameDuration=0; //Unknown if (FrameDuration) { int64u SamplingCount=Frame_Count_HD*FrameDuration; Fill(Stream_Audio, 0, Audio_Duration, SamplingCount/(((float64)HD_SamplingRate)/1000), 0); Fill(Stream_Audio, 0, Audio_SamplingCount, SamplingCount); Fill(Stream_Audio, 0, Audio_BitRate, (File_Size-File_Offset_FirstSynched)/(SamplingCount/(((float64)HD_SamplingRate)/1000))*8, 0); } Fill(Stream_Audio, 0, Audio_FrameCount, Frame_Count_HD); } } if (Core_IsPresent) { Fill(Stream_Audio, 0, Audio_FrameCount, Frame_Count_ForDuration); if (AC3_SamplingRate[fscod]) { float64 FrameDuration; if (bsid_Max<=0x08) FrameDuration=32; else if (bsid_Max<=0x09) FrameDuration=16; // Unofficial hack for low sample rate (e.g. 22.05 kHz) else FrameDuration=0; if (FrameDuration) { FrameDuration*=((float64)48000)/AC3_SamplingRate[fscod]; //32 ms for 48 KHz, else proportional (34.83 for 44.1 KHz, 48 ms for 32 KHz) Fill(Stream_Audio, 0, Audio_SamplingCount, Frame_Count_ForDuration*1536); Fill(Stream_Audio, 0, Audio_Duration, Frame_Count_ForDuration*FrameDuration, 0); if (frmsizecod/2<19) { int32u BitRate=AC3_BitRate[frmsizecod/2]*1000; int32u Divider=bsid_Max == 9?2:1; // Unofficial hack for low sample rate (e.g. 22.05 kHz) Fill(Stream_Audio, 0, Audio_BitRate, BitRate/Divider); } } } } } } else if (FrameInfo.PTS!=(int64u)-1 && FrameInfo.PTS>PTS_Begin) { Fill(Stream_Audio, 0, Audio_Duration, float64_int64s(((float64)(FrameInfo.PTS-PTS_Begin))/1000000)); float64 FrameDuration; if (bsid_Max<=0x08) FrameDuration=32; else if (bsid_Max<=0x09) FrameDuration=16; // Unofficial hack for low sample rate (e.g. 22.05 kHz) else if (bsid_Max>0x0A && bsid_Max<=0x10) { int8u numblks=numblkscod==3?6:numblkscod+1; FrameDuration=((float64)32)/6*numblks; } else FrameDuration=0; if (FrameDuration) Fill(Stream_Audio, 0, Audio_FrameCount, float64_int64s(((float64)(FrameInfo.PTS-PTS_Begin))/1000000/FrameDuration)); } } //--------------------------------------------------------------------------- void File_Ac3::Read_Buffer_Unsynched() { delete[] Save_Buffer; Save_Buffer=NULL; if (File_GoTo==0) Synched_Init(); } //--------------------------------------------------------------------------- #if MEDIAINFO_SEEK size_t File_Ac3::Read_Buffer_Seek (size_t Method, int64u Value, int64u /*ID*/) { GoTo(0); Open_Buffer_Unsynch(); return 1; } #endif //MEDIAINFO_SEEK //*************************************************************************** // Buffer - Synchro //*************************************************************************** //--------------------------------------------------------------------------- bool File_Ac3::FileHeader_Begin() { //Specific cases if (MustParse_dac3 || MustParse_dec3) return true; //Must have enough buffer for having header if (Buffer_Size<4) return false; //Must wait for more data //False positives detection: detect Matroska files, AC-3 parser is not smart enough if (!FileHeader_Begin_0x000001()) { Finish("AC-3"); return false; } //All should be OK... return true; } //*************************************************************************** // Buffer - Synchro //*************************************************************************** //--------------------------------------------------------------------------- bool File_Ac3::Synchronize() { //Specific cases if (MustParse_dac3 || MustParse_dec3) return true; //Synchronizing while (Buffer_Offset+8<=Buffer_Size) { if (!FrameSynchPoint_Test()) return false; //Need more data if (Synched) break; Buffer_Offset++; } //Parsing last bytes if needed if (Buffer_Offset+8>Buffer_Size) { //We must keep more bytes in order to detect TimeStamp if (Frame_Count==0) { if (Buffer_Offset>=16) Buffer_Offset-=16; else Buffer_Offset=0; return false; } if (Buffer_Offset+7==Buffer_Size && CC3(Buffer+Buffer_Offset+4)!=0xF8726F && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+6==Buffer_Size && CC2(Buffer+Buffer_Offset+4)!=0xF872 && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+5==Buffer_Size && CC1(Buffer+Buffer_Offset+4)!=0xF8 && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+4==Buffer_Size && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+3==Buffer_Size && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+2==Buffer_Size && CC2(Buffer+Buffer_Offset)!=0x0B77 && CC2(Buffer+Buffer_Offset)!=0x770B) Buffer_Offset++; if (Buffer_Offset+1==Buffer_Size && CC1(Buffer+Buffer_Offset)!=0x0B && CC1(Buffer+Buffer_Offset)!=0x77) Buffer_Offset++; return false; } //Testing if we have TimeStamp if (Buffer_Offset>=16) { if ( Buffer[Buffer_Offset-0x10+0x00]==0x01 //Magic value? Always 0x01 && Buffer[Buffer_Offset-0x10+0x01]==0x10 //Size? Always 0x10 && Buffer[Buffer_Offset-0x10+0x02]==0x00 //First byte of HH? Always 0x00 && (Buffer[Buffer_Offset-0x10+0x03]>>4 )<0x6 //Second byte of HH? First 4 bits must be <0x6 && (Buffer[Buffer_Offset-0x10+0x03]&0xF)<0xA //Second byte of HH? Second 4 bits must be <0xA && Buffer[Buffer_Offset-0x10+0x04]==0x00 //First byte of MM? Always 0x00 && (Buffer[Buffer_Offset-0x10+0x05]>>4 )<0x6 //Second byte of MM? First 4 bits must be <0x6 && (Buffer[Buffer_Offset-0x10+0x05]&0xF)<0xA //Second byte of MM? Second 4 bits must be <0xA && Buffer[Buffer_Offset-0x10+0x06]==0x00 //First byte of SS? Always 0x00 && (Buffer[Buffer_Offset-0x10+0x07]>>4 )<0x6 //Second byte of SS? First 4 bits must be <0x6 && (Buffer[Buffer_Offset-0x10+0x07]&0xF)<0xA //Second byte of SS? Second 4 bits must be <0xA && Buffer[Buffer_Offset-0x10+0x08]==0x00 //First byte of FF? Always 0x00 && (Buffer[Buffer_Offset-0x10+0x09]>>4 )<0x4 //Second byte of FF? First 4 bits must be <0x4 && (Buffer[Buffer_Offset-0x10+0x09]&0xF)<0xA //Second byte of FF? Second 4 bits must be <0xA && !(Buffer[Buffer_Offset-0x10+0x00]==0x00 //We want at least a byte not zero, in order to differentiate TimeStamp from padding && Buffer[Buffer_Offset-0x10+0x01]==0x00 && Buffer[Buffer_Offset-0x10+0x0C]==0x00 && Buffer[Buffer_Offset-0x10+0x0D]==0x00 && Buffer[Buffer_Offset-0x10+0x0E]==0x00 && Buffer[Buffer_Offset-0x10+0x0F]==0x00)) { TimeStamp_IsPresent=true; Buffer_Offset-=16; } } //Synched return true; } //--------------------------------------------------------------------------- void File_Ac3::Synched_Init() { if (!Frame_Count_Valid) Frame_Count_Valid=Config->ParseSpeed>=0.3?32:(IsSub?1:2); //FrameInfo PTS_End=0; if (!IsSub) { FrameInfo.DTS=0; //No DTS in container FrameInfo.PTS=0; //No PTS in container } DTS_Begin=FrameInfo.DTS; DTS_End=FrameInfo.DTS; if (Frame_Count_NotParsedIncluded==(int64u)-1) Frame_Count_NotParsedIncluded=0; //No Frame_Count_NotParsedIncluded in the container } //--------------------------------------------------------------------------- bool File_Ac3::Synched_Test() { //Specific cases if (MustParse_dac3 || MustParse_dec3) return true; //Must have enough buffer for having header if (Buffer_Offset+(TimeStamp_IsPresent?16:0)+6>Buffer_Size) return false; //TimeStamp if (TimeStamp_IsPresent && !TimeStamp_Parsed) { if (!( Buffer[Buffer_Offset+0x00]==0x01 //Magic value? Always 0x01 && Buffer[Buffer_Offset+0x01]==0x10 //Size? Always 0x10 && Buffer[Buffer_Offset+0x02]==0x00 //First byte of HH? Always 0x00 && (Buffer[Buffer_Offset+0x03]>>4 )<0x6 //Second byte of HH? First 4 bits must be <0x6 && (Buffer[Buffer_Offset+0x03]&0xF)<0xA //Second byte of HH? Second 4 bits must be <0xA && Buffer[Buffer_Offset+0x04]==0x00 //First byte of MM? Always 0x00 && (Buffer[Buffer_Offset+0x05]>>4 )<0x6 //Second byte of MM? First 4 bits must be <0x6 && (Buffer[Buffer_Offset+0x05]&0xF)<0xA //Second byte of MM? Second 4 bits must be <0xA && Buffer[Buffer_Offset+0x06]==0x00 //First byte of SS? Always 0x00 && (Buffer[Buffer_Offset+0x07]>>4 )<0x6 //Second byte of SS? First 4 bits must be <0x6 && (Buffer[Buffer_Offset+0x07]&0xF)<0xA //Second byte of SS? Second 4 bits must be <0xA && Buffer[Buffer_Offset+0x08]==0x00 //First byte of FF? Always 0x00 && (Buffer[Buffer_Offset+0x09]>>4 )<0x4 //Second byte of FF? First 4 bits must be <0x4 && (Buffer[Buffer_Offset+0x09]&0xF)<0xA)) //Second byte of FF? Second 4 bits must be <0xA TimeStamp_IsPresent=false; } if (TimeStamp_IsPresent && !TimeStamp_Parsed) Buffer_Offset+=16; //Quick test of synchro if (!FrameSynchPoint_Test()) { if (TimeStamp_IsPresent && !TimeStamp_Parsed && Buffer_Offset>=16) Buffer_Offset-=16; return false; //Need more data } if (!Synched) return true; //TimeStamp if (TimeStamp_IsPresent && !TimeStamp_Parsed) { Buffer_Offset-=16; if (Synched) { TimeStamp_IsParsing=true; TimeStamp_Parsed=false; } else { TimeStamp_IsParsing=false; TimeStamp_Parsed=false; } } //We continue return true; } //*************************************************************************** // Buffer - Demux //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_DEMUX bool File_Ac3::Demux_UnpacketizeContainer_Test() { if (TimeStamp_IsPresent) Buffer_Offset+=16; if (!HD_IsPresent && Frame_Count==0 && Save_Buffer==NULL) { //Searching HD part size_t Buffer_Offset_Save=Buffer_Offset; Buffer_Offset++; Synched=false; while (Buffer_Offset+8<=Buffer_Size) { if (!FrameSynchPoint_Test()) { Buffer_Offset=Buffer_Offset_Save; return false; //Need more data } if (Synched) break; Buffer_Offset++; } Buffer_Offset=Buffer_Offset_Save; if (!Synched) { Synched=true; if (TimeStamp_IsPresent) Buffer_Offset-=16; return false; //Need more data } } if (Save_Buffer) { Demux_TotalBytes-=Buffer_Offset; Demux_Offset-=Buffer_Offset; File_Offset+=Buffer_Offset; swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); } if (Buffer[Buffer_Offset]==0x0B && Buffer[Buffer_Offset+1]==0x77) { int8u bsid=Buffer[Buffer_Offset+5]>>3; if (bsid<=0x08) FrameInfo.DUR=32000000; else if (bsid<=0x09) FrameInfo.DUR=16000000; // Unofficial hack for low sample rate (e.g. 22.05 kHz) else if (bsid>0x0A && bsid<=0x10) { numblkscod=(Buffer[Buffer_Offset+4]>>4)&0x3; int64u numblks=numblkscod==3?6:numblkscod+1; FrameInfo.DUR=32000000*numblks/6; } Demux_Offset=Buffer_Offset+Core_Size_Get(); //Core part if (HD_IsPresent) { if (TimeStamp_IsPresent) Buffer_Offset-=16; if (Save_Buffer) { swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); Demux_TotalBytes+=Buffer_Offset; Demux_Offset+=Buffer_Offset; File_Offset-=Buffer_Offset; } return true; //No AC-3 demux } } else { Demux_Offset=Buffer_Offset+HD_Size_Get(); } if (Demux_Offset>Buffer_Size && File_Offset+Buffer_Size!=File_Size) { if (TimeStamp_IsPresent) Buffer_Offset-=16; if (Save_Buffer) { swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); Demux_TotalBytes+=Buffer_Offset; Demux_Offset+=Buffer_Offset; File_Offset-=Buffer_Offset; } return false; //No complete frame } Demux_UnpacketizeContainer_Demux(); if (Save_Buffer) { swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); Demux_TotalBytes+=Buffer_Offset; Demux_Offset+=Buffer_Offset; File_Offset-=Buffer_Offset; } if (TimeStamp_IsPresent) Buffer_Offset-=16; return true; } #endif //MEDIAINFO_DEMUX //*************************************************************************** // Buffer - Global //*************************************************************************** //--------------------------------------------------------------------------- void File_Ac3::Read_Buffer_OutOfBand() { if (MustParse_dmlp) { dmlp(); return; } } //--------------------------------------------------------------------------- void File_Ac3::Read_Buffer_Continue() { if (MustParse_dac3) { dac3(); return; } if (MustParse_dec3) { dec3(); return; } } //*************************************************************************** // Buffer - Per element //*************************************************************************** //--------------------------------------------------------------------------- void File_Ac3::Header_Parse() { //TimeStamp if (TimeStamp_IsParsing) { Header_Fill_Size(16); Header_Fill_Code(2, "TimeStamp"); return; } if (Save_Buffer) { File_Offset+=Buffer_Offset; swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); } //Filling if ((Buffer[Buffer_Offset]==0x0B && Buffer[Buffer_Offset+1]==0x77) || (Buffer[Buffer_Offset]==0x77 && Buffer[Buffer_Offset+1]==0x0B)) { Header_Fill_Size(Core_Size_Get()); Header_Fill_Code(0, "syncframe"); //Little Endian management if (Save_Buffer) { swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); File_Offset-=Buffer_Offset; } return; } //MLP or TrueHD specific int16u Size; BS_Begin(); Skip_S1( 4, "CRC?"); Get_S2 (12, Size, "Size"); BS_End(); Skip_B2( "Timestamp?"); //Little Endian management if (Save_Buffer) { swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); } //Filling if (Size<2) { Synched=false; Size=2; } Size*=2; Header_Fill_Size(Size); Header_Fill_Code(1, "HD"); } //--------------------------------------------------------------------------- void File_Ac3::Data_Parse() { if (Element_Code != 2) // Not time stamp TimeStamp_Parsed=false; //Currently, only one kind of intermediate element is detected (no TimeStamp and HD part together), and we don't know the precise specification of MLP nor TimeStamp, so we consider next eleemnt is TimeStamp if (Save_Buffer) { File_Offset+=Buffer_Offset; swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); } //Parsing switch (Element_Code) { case 0 : Core(); break; case 1 : Element_Info1C((FrameInfo.PTS!=(int64u)-1), __T("PTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PTS)/1000000))); Element_Info1(Frame_Count); HD(); break; case 2 : TimeStamp(); break; default: ; } //Little Endian management if (Save_Buffer) { delete[] Buffer; Buffer=Save_Buffer; Save_Buffer=NULL; Buffer_Offset=Save_Buffer_Offset; Buffer_Size=Save_Buffer_Size; File_Offset-=Buffer_Offset; } } //--------------------------------------------------------------------------- void File_Ac3::Core() { while (Element_Offset0x10) return; //Not supported //Counting if (Frame_Count==0) { Core_IsPresent=true; PTS_Begin=FrameInfo.PTS; } if (bsid==0x09) Frequency_b=AC3_SamplingRate2[fscod]; // Unofficial hack for low sample rate (e.g. 22.05 kHz) else { if (fscod!=3) Frequency_b=AC3_SamplingRate[fscod]; else Frequency_b=AC3_SamplingRate2[fscod2]; } if (bsid>0x0A) { int64u numblks = numblkscod == 3 ? 6 : numblkscod + 1; TS_Add(numblks*256); } else TS_Add(1536); if (File_Offset+Buffer_Offset+Element_Size==File_Size) Frame_Count_Valid=Frame_Count; //Finish frames in case of there are less than Frame_Count_Valid frames //Filling if (!Status[IsAccepted]) Accept("AC-3"); if (!Status[IsFilled] && Frame_Count>=Frame_Count_Valid) { Fill("AC-3"); //No more need data if (!IsSub && Config->ParseSpeed<1.0) Finish("AC-3"); } FILLING_END(); } //--------------------------------------------------------------------------- void File_Ac3::Core_Frame() { //Save true Element_Size (if Core+substreams, Element_Size is for all elements, and we want to limit to core) int64u Element_Size_Save=Element_Size; bsid=CC1(Buffer+Buffer_Offset+Element_Offset+5)>>3; if (bsid<=0x09) { int8u fscod =(Buffer[(size_t)(Buffer_Offset+4)]&0xC0)>>6; int8u frmsizecod= Buffer[(size_t)(Buffer_Offset+4)]&0x3F; //Filling fscods[fscod]++; frmsizecods[frmsizecod]++; Element_Size=Element_Offset+AC3_FrameSize_Get(frmsizecod, fscod); if (Element_Size>Element_Size_Save) Element_Size=Element_Size_Save; // Not expected, but trying to parse the begining } else if (bsid>0x0A && bsid<=0x10) //E-AC-3 only { int16u frmsiz=CC2(Buffer+Buffer_Offset+(size_t)Element_Offset+2)&0x07FF; Element_Size=Element_Offset+2+frmsiz*2; if (Element_Size>Element_Size_Save) Element_Size=Element_Size_Save; // Not expected, but trying to parse the begining } if (Element_Offset==Element_Size) Element_Size=Element_Size_Save; // Something went wrong, using the whole packet //Pre-parsing, finding some elements presence int16u auxdatal; if (Buffer[Buffer_Offset+(Element_Size)-3]&0x02) //auxdatae auxdatal=(((int16u)Buffer[Buffer_Offset+(Element_Size)-4])<<6) |( Buffer[Buffer_Offset+(Element_Size)-3] >>2); else auxdatal=(int16u)-1; //auxdata is empty BitStream_Fast Search(Buffer+Buffer_Offset+Element_Offset, Element_Size-Element_Offset); while(Search.Remain()>18) { if (Search.Peek2(16)==0x5838 && Ac3_EMDF_Test(Search)) break; Search.Skip(1); } if (Search.Remain()>18) EMDF_RemainPos=Search.Remain(); else EMDF_RemainPos=(size_t)-1; //Parsing int16u frmsiz=0, chanmap=0; int8u dialnorm=(int8u)-1, dialnorm2=(int8u)-1, compr=(int8u)-1, compr2=(int8u)-1, dynrng=(int8u)-1, dynrng2=(int8u)-1, cmixlev=(int8u)-1, surmixlev=(int8u)-1, mixlevel=(int8u)-1, roomtyp=(int8u)-1, dmixmod=(int8u)-1, ltrtcmixlev=(int8u)-1, ltrtsurmixlev=(int8u)-1, lorocmixlev=(int8u)-1, lorosurmixlev=(int8u)-1; int8u strmtyp=0, substreamid=0, acmod=0, bsmod=0, dsurmod=0; bool compre=false, compr2e=false, dynrnge=false, dynrng2e=false; bool lfeon=false, chanmape=false; bool addbsie=false, adconvtyp=false; if (bsid<=0x09) { Element_Begin1("synchinfo"); Skip_B2( "syncword"); Skip_B2( "crc1"); BS_Begin(); Get_S1 (2, fscod, "fscod - Sample Rate Code"); Param_Info2(AC3_SamplingRate[fscod], " Hz"); Get_S1 (6, frmsizecod, "frmsizecod - Frame Size Code"); Param_Info2C(frmsizecod/2<19,AC3_BitRate[frmsizecod/2]*1000, " bps"); Element_End0(); Element_Begin1("bsi"); Get_S1 (5, bsid, "bsid - Bit Stream Identification"); Get_S1 (3, bsmod, "bsmod - Bit Stream Mode"); Param_Info1(AC3_Mode[bsmod]); Get_S1 (3, acmod, "acmod - Audio Coding Mode"); Param_Info1(AC3_ChannelPositions[acmod]); if ((acmod&1) && acmod!=1) //central present Get_S1 (2, cmixlev, "cmixlev - Center Mix Level"); if (acmod&4) //back present Get_S1 (2, surmixlev, "surmixlev - Surround Mix Level"); if (acmod==2) Get_S1 (2, dsurmod, "dsurmod - Dolby Surround Mode"); Param_Info1(AC3_Surround[dsurmod]); Get_SB ( lfeon, "lfeon - Low Frequency Effects"); Get_S1 (5, dialnorm, "dialnorm - Dialogue Normalization"); Get_SB ( compre, "compre - Compression Gain Word Exists"); if (compre) Get_S1 (8, compr, "compr - Compression Gain Word"); TEST_SB_SKIP( "langcode - Language Code Exists"); Skip_S1(8, "langcod - Language Code"); TEST_SB_END(); TEST_SB_SKIP( "audprodie - Audio Production Information Exists"); Get_S1 (8, mixlevel, "mixlevel - Mixing Level"); Get_S1 (2, roomtyp, "roomtyp - Room Type"); TEST_SB_END(); if (acmod==0) //1+1 mode { Get_S1 (5, dialnorm2, "dialnorm2 - Dialogue Normalization"); Get_SB ( compr2e, "compr2e - Compression Gain Word Exists"); if (compr2e) Get_S1 (8, compr2, "compr2 - Compression Gain Word"); TEST_SB_SKIP( "langcod2e - Language Code Exists"); Skip_S1(8, "langcod2 - Language Code"); TEST_SB_END(); TEST_SB_SKIP( "audprodi2e - Audio Production Information Exists"); Skip_S1(8, "mixlevel2 - Mixing Level"); Skip_S1(2, "roomtyp2 - Room Type"); TEST_SB_END(); } Skip_SB( "copyrightb - Copyright Bit"); Skip_SB( "origbs - Original Bit Stream"); if (bsid==0x06) { TEST_SB_SKIP( "xbsi1e"); Get_S1 (2, dmixmod, "dmixmod"); Get_S1 (3, ltrtcmixlev, "ltrtcmixlev"); Get_S1 (3, ltrtsurmixlev, "ltrtsurmixlev"); Get_S1 (3, lorocmixlev, "lorocmixlev"); Get_S1 (3, lorosurmixlev, "lorosurmixlev"); TEST_SB_END(); TEST_SB_SKIP( "xbsi2e"); Get_S1 (2, dsurexmod, "dsurexmod"); Get_S1 (2, dheadphonmod, "dheadphonmod"); Get_SB ( adconvtyp, "adconvtyp"); Skip_S1(8, "xbsi2"); Skip_SB( "encinfo"); TEST_SB_END(); } else { TEST_SB_SKIP( "timecod1e"); Skip_S2(14, "timecod1"); TEST_SB_END(); TEST_SB_SKIP( "timecod2e"); Skip_S2(14, "timecod2"); TEST_SB_END(); } TEST_SB_GET (addbsie, "addbsie"); int8u addbsil; Get_S1 (6, addbsil, "addbsil"); for (int8u Pos=0; Pos<=addbsil; Pos++) //addbsil+1 bytes Skip_S1(8, "addbsi"); TEST_SB_END(); Element_End0(); Element_Begin1("audblk"); for (int8u Pos=0; Pos0x0A && bsid<=0x10) { /* Not finished, for reference only static const size_t MAX_AUD_BLK = 6; static const size_t MAX_CHANNELS = 5; struct Aud_Blk { bool cplstre; bool cplinu; bool lfeexpstr; int8u blkmixcfginfo; int8u cplexpstr; int8u chexpstr[MAX_CHANNELS]; }; Aud_Blk aud_blks[MAX_AUD_BLK]; struct Aud_Chan_Blk { bool blksw; bool chahtinu; bool chincpl; bool chinspx; bool cplcoe; bool dithflag; bool ecplparam1e; bool firstspxcos; bool firstcplcos; bool rsvdfieldse; bool spxcoe; int8u chactivegaqbins; //todo int8u chbwcod; int8u convexpstr; int8u deltbae; int8u endmant; int8u frmchexpstr; int8u mstrspxco; int8u spxblnd; int8u strtmant; }; Aud_Chan_Blk aud_chan_blk[MAX_CHANNELS]; bool firstcplleak = false; //*/ Element_Begin1("synchinfo"); Skip_B2( "syncword"); Element_End0(); Element_Begin1("bsi"); BS_Begin(); size_t Bits_Begin=Data_BS_Remain(); Get_S1 ( 2, strmtyp, "strmtyp"); Get_S1 ( 3, substreamid, "substreamid"); Get_S2 (11, frmsiz, "frmsiz"); Get_S1 ( 2, fscod, "fscod"); Param_Info2(AC3_SamplingRate[fscod], " Hz"); if (fscod==3) { Get_S1 ( 2, fscod2, "fscod2"); Param_Info2(AC3_SamplingRate2[fscod2], " Hz"); numblkscod=3; } else Get_S1 ( 2, numblkscod, "numblkscod"); Get_S1 (3, acmod, "acmod - Audio Coding Mode"); Param_Info1(AC3_ChannelPositions[acmod]); Get_SB ( lfeon, "lfeon - Low Frequency Effects"); Get_S1 (5, bsid, "bsid - Bit Stream Identification"); Get_S1 (5, dialnorm, "dialnorm"); TEST_SB_GET(compre, "compre"); Get_S1 (8, compr, "compr"); TEST_SB_END(); if (acmod==0) //1+1 mode { Get_S1 (5, dialnorm2, "dialnorm2"); TEST_SB_GET(compr2e, "compr2e"); Get_S1 (8, compr2, "compr2"); TEST_SB_END(); } if (strmtyp==1) //dependent stream { TEST_SB_GET (chanmape, "chanmape"); Get_S2(16, chanmap, "chanmap"); Param_Info1(AC3_chanmap_ChannelPositions(chanmap)); TEST_SB_END(); } TEST_SB_SKIP( "mixmdate"); int8u mixdef; if(acmod > 0x2) Get_S1 (2, dmixmod, "dmixmod"); if((acmod&0x1) && (acmod>0x2)) { Get_S1 (3, ltrtcmixlev, "ltrtcmixlev"); Get_S1 (3, lorocmixlev, "lorocmixlev"); } if(acmod>0x4) { Get_S1 (3, ltrtsurmixlev, "ltrtsurmixlev"); Get_S1 (3, lorosurmixlev, "lorosurmixlev"); } if(lfeon) { TEST_SB_SKIP( "lfemixlevcode"); Skip_S1 (5, "lfemixlevcod"); TEST_SB_END(); } if(strmtyp == 0x0) { TEST_SB_SKIP( "pgmscle"); Skip_S1 (6, "pgmscl"); TEST_SB_END(); if (acmod == 0x0) { TEST_SB_SKIP( "pgmscle12e"); Skip_S1 (6, "pgmscl12e"); TEST_SB_END(); } TEST_SB_SKIP( "extpgmscle"); Skip_S1 (6, "extpgmscl"); TEST_SB_END(); Get_S1 (2, mixdef, "mixdef"); if(mixdef == 0x1) { Skip_S1 (1, "premixcmpsel"); Skip_S1 (1, "drcsrc"); Skip_S1 (3, "premixcmpscl"); } else if(mixdef == 0x2) Skip_S2 (12, "mixdata"); else if(mixdef == 0x3) { int8u mixdeflen; Get_S1 (5, mixdeflen, "mixdeflen"); TEST_SB_SKIP( "mixdata2e"); Skip_S1 (6, "premixcmpsel"); Skip_S1 (1, "drcsrc"); Skip_S1 (3, "premixcmpscl"); TEST_SB_SKIP( "extpgmlscle"); Skip_S1 (4, "extpgmlscl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmcscle"); Skip_S1 (4, "extpgmcscl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmrscle"); Skip_S1 (4, "extpgmrscl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmlssle"); Skip_S1 (4, "extpgmlssl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmrssle"); Skip_S1 (4, "extpgmrssl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmlfescle"); Skip_S1 (4, "extpgmlfescl"); TEST_SB_END(); TEST_SB_SKIP( "dmixscle"); Skip_S1 (4, "dmixscl"); TEST_SB_END(); TEST_SB_SKIP( "addche"); TEST_SB_SKIP( "extpgmaux1scle"); Skip_S1 (4, "extpgmaux1scl"); TEST_SB_END(); TEST_SB_SKIP( "extpgmaux2scle"); Skip_S1 (4, "extpgmaux2scl"); TEST_SB_END(); TEST_SB_END(); TEST_SB_END(); TEST_SB_SKIP( "mixdata3e"); Skip_S1 (5, "spchdat"); TEST_SB_SKIP( "addspchdate"); Skip_S1 (5, "spchdat1"); Skip_S1 (2, "spchan1att"); TEST_SB_SKIP( "addspdat1e"); Skip_S1 (5, "spchdat2"); Skip_S1 (2, "spchan2att"); TEST_SB_END(); TEST_SB_END(); TEST_SB_END(); Skip_S2 (8*(mixdeflen+2), "mixdata"); //Skip_S1 (, "mixdatafill"); } if(acmod<0x2) { TEST_SB_SKIP( "paninfoe"); Skip_S1 (6, "panmean"); Skip_S1 (8, "paninfo"); TEST_SB_END(); if(acmod==0x0) { TEST_SB_SKIP( "paninfo2e"); Skip_S1 (6, "panmean2"); Skip_S1 (8, "paninfo2"); TEST_SB_END(); } } TEST_SB_SKIP( "frmmixcfginfoe"); if(numblkscod==0x0) { int8u blkmixcfginfo; Get_S1 (5, blkmixcfginfo, "blkmixcfginfo[0]"); //aud_blks[0].blkmixcfginfo = blkmixcfginfo; } else { int8u nb_blocks_per_syncframe = numblkscod == 3 ? 6 : (numblkscod + 1); for (int8u blk = 0; blk < nb_blocks_per_syncframe; ++blk) { TEST_SB_SKIP( "blkmixcfginfoe"); int8u blkmixcfginfo; Get_S1 (5, blkmixcfginfo, "blkmixcfginfo[x]"); //aud_blks[blk].blkmixcfginfo = blkmixcfginfo; TEST_SB_END(); } } TEST_SB_END(); } TEST_SB_END(); TEST_SB_SKIP( "infomdate"); Get_S1 (3, bsmod, "bsmod - Bit Stream Mode"); Param_Info1(AC3_Mode[bsmod]); Skip_SB( "copyrightb - Copyright Bit"); Skip_SB( "origbs - Original Bit Stream"); if (acmod==0x2) { Get_S1 (2, dsurmod, "dsurmod"); Get_S1 (2, dheadphonmod, "dheadphonmod"); } if (acmod>=0x6) Get_S1 (2, dsurexmod, "dsurexmod"); TEST_SB_SKIP( "audprodie"); Get_S1 (5, mixlevel, "mixlevel"); Get_S1 (2, roomtyp, "roomtyp"); Skip_S1(1, "adconvtyp"); TEST_SB_END(); if (acmod==0x0) { TEST_SB_SKIP( "audprodi2e"); Skip_S1(5, "mixlevel2"); Skip_S1(2, "roomtyp2"); Skip_S1(1, "adconvtyp2"); TEST_SB_END(); } if (fscod < 0x3) Skip_S1(1, "sourcefscod"); TEST_SB_END(); if (strmtyp==0x0 && numblkscod!=0x3) Skip_S1(1, "convsync"); if (strmtyp == 0x2) { int8u blkid = 0; if (numblkscod==0x3) blkid = 1; else Get_S1(1, blkid, "blkid"); if (blkid) Get_S1(6, frmsizecod, "frmsizecod"); } TEST_SB_GET (addbsie, "addbsie"); int8u addbsil; Get_S1 (6, addbsil, "addbsil"); if (addbsil+1!=addbsi_Buffer_Size) { delete[] addbsi_Buffer; addbsi_Buffer_Size=addbsil+1; addbsi_Buffer=new int8u[addbsi_Buffer_Size]; } for (int8u Pos=0; Pos<=addbsil; Pos++) //addbsil+1 bytes Get_S1 (8, addbsi_Buffer[Pos], "addbsi"); TEST_SB_END(); Element_End0(); /* Not finished, for reference only int8u numblks = numblkscod == 3 ? 6 : (numblkscod + 1); Element_Begin1("audfrm"); int8u snroffststr, ncplblks = 0; bool expstre = true, ahte = false; bool transproce, blkswe, dithflage, bamode, frmfgaincode, dbaflde, skipflde, spxattene; if (numblkscod==0x3) { Get_SB(expstre, "expstre"); Get_SB(ahte, "ahte"); } Get_S1 (2, snroffststr, "snroffststr"); Get_SB (transproce, "transproce"); Get_SB (blkswe, "blkswe"); Get_SB (dithflage, "dithflage"); Get_SB (bamode, "bamode"); Get_SB (frmfgaincode, "frmfgaincode"); Get_SB (dbaflde, "dbaflde"); Get_SB (skipflde, "skipflde"); Get_SB (spxattene, "spxattene"); if (acmod>0x1) { aud_blks[0].cplstre = 1; aud_blks[0].cplinu = 0; for (int8u blk = 1; blk < numblks; ++blk) { Get_SB (aud_blks[blk].cplstre, "cplstre[x]"); if (aud_blks[blk].cplstre==1) Get_SB (aud_blks[blk].cplinu, "cplinu[x]"); else aud_blks[blk].cplinu = aud_blks[blk - 1].cplinu; } } else { for(int8u blk = 0; blk < numblks; ++blk) aud_blks[blk].cplinu = 0; } if (expstre) { for(int8u blk = 0; blk < numblks; ++blk) { if (aud_blks[blk].cplinu==1) Get_S1 (2, aud_blks[blk].cplexpstr, "cplexpstr[x]"); for (int8u Pos=0; Pos 0x1 && ncplblks > 0) Get_S1(5, frmcplexpstr, "frmcplexpstr"); for (int8u Pos=0; Pos firstchincpl) aud_chan_blk[Pos].rsvdfieldse = true; else aud_chan_blk[Pos].rsvdfieldse = false; aud_chan_blk[Pos].firstcplcos = false; } else { Get_SB (aud_chan_blk[Pos].ecplparam1e, "ecplparam1e"); if (Pos > firstchincpl) Get_SB (aud_chan_blk[Pos].rsvdfieldse, "rsvdfieldse"); else aud_chan_blk[Pos].rsvdfieldse = false; } if (aud_chan_blk[Pos].ecplparam1e) { if (aud_chan_blk[Pos].ecplparam1e) { for (size_t bnd = 0; bnd < necplbnd; bnd++) Skip_S1(5, "ecplamp[ch][bnd]"); } if (aud_chan_blk[Pos].rsvdfieldse) Skip_BS(9 * (necplbnd - 1), "reserved"); if (Pos > firstchincpl) Skip_SB( "reserved"); } } else aud_chan_blk[Pos].firstcplcos = true; } } } //aud_chan_blk_init(acmod, cplbegf); for (int8u Pos = 0; Pos0x0 && chgaqmod<0x3) { for (size_t n = 0; n < chgaqsections; ++n) Skip_SB( "chgaqgain[ch][n]"); } else if (chgaqmod==0x3) { for (size_t n = 0; n < chgaqsections; ++n) Skip_S1(5, "chgaqgain[ch][n]"); } aud_chan_blk[Pos].endmant = cplstrtmant; int8u* chgaqbin = new int8u [aud_chan_blk[Pos].endmant]; if (aud_chan_blk[Pos].chahtinu == 0) { for (size_t i = 0; i < aud_chan_blk[Pos].endmant; ++i) chgaqbin[i] = 0; } else { int8u endbap = 17; if (chgaqmod < 2) endbap = 12; aud_chan_blk[Pos].chactivegaqbins = 0; for (size_t i = 0; i < aud_chan_blk[Pos].endmant; ++i) { if (hebap[i] > 7 && hebap[i] < endbap) { chgaqbin[i] = 1; ++aud_chan_blk[Pos].chactivegaqbins; } else if (hebap[i] >= endbap) chgaqbin[i] = -1; else chgaqbin[i] = 0; } } for (size_t bin = 0; bin < aud_chan_blk[Pos].endmant; ++bin) { if (!cplahtinu) { for (size_t i = cplstrtmant; i < cplendmant; ++i) cplgaqbin[i] = 0; } else { int8u endbap = 17; if (cplgaqmod < 2) endbap = 12; cplactivegaqbins = 0; } if (chgaqbin[bin]) { for (size_t n = 0; n < 6; n++) { //TODO // {pre_chmant[n][ch][bin]} ........................... // (0-16); } } else { //TODO // pre_chmant[0][ch][bin] .................................................; // (0-9); } } aud_chan_blk[Pos].chahtinu = -1; } if (aud_blks[blk].cplinu && aud_chan_blk[Pos].chincpl && !got_cplchan) { size_t ncplmant = 12 * ncplsubnd; if (cplahtinu==0) { for (size_t bin = 0; bin < ncplmant; ++bin) { //TODO // cplmant[bin] ...........................; // (0-16); } got_cplchan = true; } else if (cplahtinu==1) { Get_S1 (2, cplgaqmod, "cplgaqmod"); if (lfeahtinu == 0) { for (size_t bin = 0; bin < lfeendmant; bin++) lfegaqbin[bin] = 0; } else { int8u endbap = 17; if (lfegaqmod<2) endbap = 12; for (size_t bin = 0; bin < lfeendmant; bin++) { if (hebap[bin] > 7 && hebap[bin] < endbap) { lfegaqbin[bin] = 1; ++lfeactivegaqbins; } else if (hebap[bin] >= endbap) lfegaqbin[bin] = -1; else lfegaqbin[bin] = 0; } } if (cplgaqmod>0x0 && cplgaqmod<0x3) { size_t cplgaqsections = cplactivegaqbins; for (size_t n = 0; n < cplgaqsections; n++) Skip_SB( "cplgaqgain[n]"); } else if (cplgaqmod == 0x3) { size_t cplgaqsections = cplactivegaqbins / 3; if (cplactivegaqbins % 3) ++cplgaqsections; for (size_t n = 0; n < cplgaqsections; n++) Skip_S1(5, "cplgaqgain[n]"); } for (size_t bin = 0; bin < ncplmant; ++bin) { if (cplgaqbin[bin]) { for (size_t n = 0; n < 6; ++n) { //TODO // pre_cplmant[n][bin] ...........................; // (0-16); } } else { //TODO // pre_cplmant[0][bin] .................................................; // (0-9); } } got_cplchan = true; cplahtinu = -1; } else got_cplchan = true; } } if (lfeon) { int8u nlfemant = 7; if (lfeahtinu == 0) { for (size_t bin = 0; bin < nlfemant; ++bin) { //TODO // lfemant[bin]..............................; // (0-16); } } else if (lfeahtinu == 1) { size_t lfegaqsections = 0; Get_S1 (2, lfegaqmod, "lfegaqmod"); if (lfeahtinu!=0) { size_t sumgaqbins = 0; for (size_t bin = 0; bin < lfeendmant; bin++) sumgaqbins += lfegaqbin[bin]; switch (lfegaqmod) { case 0: { lfegaqsections = 0; break; } case 1: case 2: { lfegaqsections = lfeactivegaqbins; break; } case 3: { lfegaqsections = lfeactivegaqbins / 3; if (lfeactivegaqbins % 3) lfegaqsections++; break; } }; } if (lfegaqmod>0x0 && lfegaqmod<0x3) { for (size_t n = 0; n < lfegaqsections; ++n) Skip_SB( "lfegaqgain[n]"); } else if (lfegaqmod==0x3) { for (size_t n = 0; n < lfegaqsections; ++n) Skip_S1(5, "lfegaqgain[n]"); } for (size_t bin = 0; bin < nlfemant; ++bin) { if (lfegaqbin[bin]) { for (size_t n = 0; n < 6; ++n) { //TODO // pre_lfemant[n][bin] ..............................; // (0-16); } } else { //TODO // pre_lfemant[0][bin] ....................................................; // (0-9); } } lfeahtinu = (int8u)-1; } } Element_End0(); } //*/ } else Skip_XX(Element_Size-Element_Offset, "Unknown"); if (bsid<=0x10) { size_t BitsAtEnd=18; //auxdatae+errorcheck if (auxdatal!=(int16u)-1) BitsAtEnd+=auxdatal+14; //auxbits+auxdatal if (Data_BS_Remain()>=BitsAtEnd) { if (EMDF_RemainPos!=(size_t)-1 && BitsAtEndBitsAtEnd) Skip_BS(Data_BS_Remain()-BitsAtEnd, bsid<=0x0A?"(Unparsed audblk(continue)+5*audblk+padding)":"(Unparsed bsi+6*audblk+padding)"); Element_Begin1("auxdata"); if (auxdatal!=(int16u)-1) { Skip_BS(auxdatal, "auxbits"); Skip_S2(14, "auxdatal"); } Skip_SB( "auxdatae"); Element_End0(); Element_Begin1("errorcheck"); Skip_SB( "encinfo"); BS_End(); Skip_B2( "crc2"); Element_End0(); } else BS_End(); if (Element_Offset0x10) return; //Not supported Formats[bsid<=0x09?0:1]++; // addbsi if (!joc_num_objects_map.empty() && addbsie && addbsi_Buffer_Size >= 2 && (addbsi_Buffer[0]&0x01)) { joc_complexity_index_Stream = addbsi_Buffer[1]; } //Information if (strmtyp>1) strmtyp=0; //TODO: check a file with strmtyp==2 if (strmtyp==0) substreamid_Independant_Current=substreamid; if (bsid_Max==(int8u)-1 || bsid>bsid_Max) bsid_Max=bsid; //Specific to first frame if (!frmsizplus1_Max[substreamid_Independant_Current][strmtyp+substreamid]) { frmsizplus1_Max[substreamid_Independant_Current][strmtyp+substreamid]=((bsid<=0x09)?(frmsizecod/2<19?AC3_BitRate[frmsizecod/2]*4:0):((frmsiz+1)*2)); acmod_Max[substreamid_Independant_Current][strmtyp+substreamid]=acmod; lfeon_Max[substreamid_Independant_Current][strmtyp+substreamid]=lfeon; bsmod_Max[substreamid_Independant_Current][strmtyp+substreamid]=bsmod; cmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=cmixlev; surmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=surmixlev; mixlevel_Max[substreamid_Independant_Current][strmtyp+substreamid]=mixlevel; roomtyp_Max[substreamid_Independant_Current][strmtyp+substreamid]=roomtyp; dmixmod_Max[substreamid_Independant_Current][strmtyp+substreamid]=dmixmod; ltrtcmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=ltrtcmixlev; ltrtsurmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=ltrtsurmixlev; lorocmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=lorocmixlev; lorosurmixlev_Max[substreamid_Independant_Current][strmtyp+substreamid]=lorosurmixlev; adconvtyp_Max[substreamid_Independant_Current][strmtyp+substreamid]=adconvtyp; dsurmod_Max[substreamid_Independant_Current][strmtyp+substreamid]=dsurmod; chanmape_Max[substreamid_Independant_Current][strmtyp+substreamid]=chanmape; chanmap_Max[substreamid_Independant_Current][strmtyp+substreamid]=chanmap; FirstFrame_Dolby.dialnorm=dialnorm; if (compre) FirstFrame_Dolby.compr=compr; if (dynrnge) FirstFrame_Dolby.dynrng=dynrng; FirstFrame_Dolby.compre=compre; FirstFrame_Dolby.dynrnge=dynrnge; } //Stats if (dialnorms.empty()) dialnorms.resize(32); if (dialnorm!=(int8u)-1) dialnorms[dialnorm]++; if (compre) { if (comprs.empty()) comprs.resize(256); if (compr!=(int8u)-1) comprs[compr]++; } if (dynrnge) { //Saving new value dynrnge_Exists=true; } if (!dynrnge) dynrng=0; if (dynrngs.empty()) dynrngs.resize(256); if (dynrng!=(int8u)-1) dynrngs[dynrng]++; FILLING_END(); } //--------------------------------------------------------------------------- void File_Ac3::emdf() { //JOC reinit joc_complexity_index_Stream=(int8u)-1; num_dynamic_objects=(int8u)-1; nonstd_bed_channel_assignment_mask=(int32u)-1; Element_Begin1("emdf"); emdf_sync(); emdf_container(); Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::emdf_sync() { int16u emdf_container_length; Element_Begin1("emdf_sync"); Skip_S2(16, "syncword"); Get_S2 (16, emdf_container_length, "emdf_container_length"); Element_End0(); RemainAfterEMDF=Data_BS_Remain()-emdf_container_length*8; //emdf_container_length coherency was already tested in sync layer } //--------------------------------------------------------------------------- void File_Ac3::emdf_container() { size_t Start = Data_BS_Remain(); int32u version, key_id; Element_Begin1("emdf_container"); Get_S4 (2, version, "emdf_version"); if (version == 3) { int32u add; Get_V4(2, add, "emdf_version addition"); version += add; } if (version) { Skip_BS(Data_BS_Remain()-RemainAfterEMDF, "(Unparsed emdf_container data)"); Element_End0(); return; } Get_S4 (3, key_id, "key_id"); if (key_id == 7) { int32u add; Get_V4 (3, add, "key_id addition"); key_id += add; } int32u emdf_payload_id = 0; for(;;) { Element_Begin1("emdf_payload"); Get_S4 (5, emdf_payload_id, "emdf_payload_id"); if (emdf_payload_id==0x1F) { int32u add; Get_V4 (5, add, "emdf_payload_id addition"); emdf_payload_id += add; } if (emdf_payload_id<16) Element_Info1(Ac3_emdf_payload_id[emdf_payload_id]); if (emdf_payload_id == 0x00) { Element_End0(); break; } emdf_payload_config(); int32u emdf_payload_size = 0; Get_V4 (8, emdf_payload_size, "emdf_payload_size"); size_t emdf_payload_End=Data_BS_Remain()-emdf_payload_size*8; //emdf_payload_size coherency was already tested in sync layer Element_Begin1("emdf_payload_bytes"); switch (emdf_payload_id) { case 11: object_audio_metadata_payload(); break; case 14: joc(); break; default: Skip_BS(emdf_payload_size*8, "(Unknown)"); } size_t RemainginBits=Data_BS_Remain(); if (RemainginBits>=emdf_payload_End) { if (RemainginBits>emdf_payload_End) Skip_BS(RemainginBits-emdf_payload_End, "(Unparsed bits)"); } else { //There is a problem, too many bits were consumed by the parser. //TODO: prevent the parser to consume more bits than count of bits in this element if (Data_BS_Remain() >= RemainAfterEMDF) Skip_BS(Data_BS_Remain() - RemainAfterEMDF, "(Problem during emdf_payload parsing)"); else Skip_BS(Data_BS_Remain(), "(Problem during emdf_payload parsing, going to end directly)"); Element_End0(); Element_End0(); break; } Element_End0(); Element_End0(); } emdf_protection(); Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::emdf_payload_config() { Element_Begin1("emdf_payload_config"); bool smploffste = false; Get_SB (smploffste, "smploffste"); if (smploffste) { Skip_S2(11, "smploffst"); Skip_SB( "reserved"); } TEST_SB_SKIP( "duratione"); Skip_V4(11, "duration"); TEST_SB_END(); TEST_SB_SKIP( "groupide"); Skip_V4(2, "groupid"); TEST_SB_END(); TEST_SB_SKIP( "codecdatae"); Skip_S1(8, "reserved"); TEST_SB_END(); bool discard_unknown_payload = false; Get_SB(discard_unknown_payload, "discard_unknown_payload"); if (!discard_unknown_payload) { bool payload_frame_aligned = false; if (!smploffste) { Get_SB (payload_frame_aligned, "payload_frame_aligned"); if (payload_frame_aligned) { Skip_SB( "create_duplicate"); Skip_SB( "remove_duplicate"); } } if (smploffste || payload_frame_aligned) { Skip_S1(5, "priority"); Skip_S1(2, "proc_allowed"); } } Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::emdf_protection() { int8u len_primary = 0, len_second = 0; Element_Begin1("emdf_protection"); Get_S1(2, len_primary, "protection_length_primary"); Get_S1(2, len_second, "protection_length_secondary"); switch (len_primary) { //case 0: break; //protection_length_primary coherency was already tested in sync layer case 1: len_primary = 8; break; case 2: len_primary = 32; break; case 3: len_primary = 128; break; default:; //Cannot append, read only 2 bits }; switch (len_second) { case 0: len_second = 0; break; case 1: len_second = 8; break; case 2: len_second = 32; break; case 3: len_second = 128; break; default:; //Cannot append, read only 2 bits }; Skip_BS(len_primary, "protection_bits_primary"); if (len_second) Skip_BS(len_primary, "protection_bits_secondary"); Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::object_audio_metadata_payload() { Element_Begin1("object_audio_metadata_payload"); int8u oa_md_version_bits; Get_S1 (2, oa_md_version_bits, "oa_md_version_bits"); if (oa_md_version_bits == 0x3) { int8u oa_md_version_bits_ext; Get_S1 (3, oa_md_version_bits_ext, "oa_md_version_bits_ext"); oa_md_version_bits += oa_md_version_bits_ext; } int8u object_count_bits; Get_S1 (5, object_count_bits, "object_count_bits"); num_dynamic_objects = object_count_bits + 1; if (object_count_bits == 0x1F) { int8u object_count_bits_ext; Get_S1 (7, object_count_bits_ext, "object_count_bits_ext"); num_dynamic_objects += object_count_bits_ext; } program_assignment(); //TODO: next Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::program_assignment() { Element_Begin1("program_assignment"); bool b_dyn_object_only_program = false; Get_SB (b_dyn_object_only_program, "b_dyn_object_only_program"); if (b_dyn_object_only_program) { bool b_lfe_present; Get_SB (b_lfe_present, "b_lfe_present"); if (b_lfe_present) { nonstd_bed_channel_assignment_mask=(1<<3); if (num_dynamic_objects!=(int8u)-1) num_dynamic_objects--; } } else { int8u content_description_mask; Get_S1 (4, content_description_mask, "content_description_mask"); if (content_description_mask & 0x1) { bool b_bed_object_chan_distribute, b_multiple_bed_instances_present; Get_SB (b_bed_object_chan_distribute, "b_bed_object_chan_distribute"); Get_SB (b_multiple_bed_instances_present, "b_multiple_bed_instances_present"); int32u num_bed_instances = 1; if (b_multiple_bed_instances_present) { int8u num_bed_instances_bits = 0; Get_S1 (3, num_bed_instances_bits, "num_bed_instances_bits"); num_bed_instances = num_bed_instances_bits + 2; } for (int32u bed = 0; bed < num_bed_instances; ++bed) { Element_Begin1("Bed"); bool b_lfe_only = true; Get_SB (b_lfe_only, "b_lfe_only"); if (!b_lfe_only) { bool b_standard_chan_assign; Get_SB (b_standard_chan_assign, "b_standard_chan_assign"); if (b_standard_chan_assign) { int16u bed_channel_assignment_mask; Get_S2 (10, bed_channel_assignment_mask, "bed_channel_assignment_mask"); nonstd_bed_channel_assignment_mask=AC3_bed_channel_assignment_mask_2_nonstd(bed_channel_assignment_mask); } else Get_S3 (17, nonstd_bed_channel_assignment_mask, "nonstd_bed_channel_assignment_mask"); } Element_End0(); } } if (content_description_mask & 0x2) Skip_S1(3, "intermediate_spatial_format_idx"); if (content_description_mask & 0x4) { int8u num_dynamic_objects_bits; Get_S1(5, num_dynamic_objects_bits, "num_dynamic_objects_bits"); if (num_dynamic_objects_bits == 0x1F) { int8u num_dynamic_objects_bits_ext = 0; Get_S1 (7, num_dynamic_objects_bits_ext, "num_dynamic_objects_bits_ext"); num_dynamic_objects_bits += num_dynamic_objects_bits_ext; } num_dynamic_objects = num_dynamic_objects_bits + 1; } else num_dynamic_objects = 0; if (content_description_mask & 0x8) { int8u reserved_data_size_bits; Get_S1 (4, reserved_data_size_bits, "reserved_data_size_bits"); int8u padding = 8 - (reserved_data_size_bits % 8); Skip_S1(reserved_data_size_bits, "reserved_data()"); if (padding) Skip_S1(padding, "padding"); } } Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc() { Element_Begin1("joc"); joc_header(); joc_info(); joc_data(); if (joc_ext_config_idx > 0) joc_ext_data(); Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc_header() { Element_Begin1("joc_header"); Skip_S1(3, "joc_dmx_config_idx"); int8u joc_num_objects_bits = 0; Get_S1 (6, joc_num_objects_bits, "joc_num_objects_bits"); joc_num_objects = joc_num_objects_bits + 1; joc_num_objects_map[joc_num_objects] ++; Get_S1 (3, joc_ext_config_idx, "joc_ext_config_idx"); Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc_info() { Element_Begin1("joc_info"); int8u joc_clipgain_x_bits, joc_clipgain_y_bits; int16u joc_seq_count_bits; Get_S1 (3, joc_clipgain_x_bits, "joc_clipgain_x_bits"); Get_S1 (5, joc_clipgain_y_bits, "joc_clipgain_y_bits"); Get_S2 (10, joc_seq_count_bits, "joc_seq_count_bits"); for (int8u obj = 0; obj < joc_num_objects; obj++) { TEST_SB_SKIP("b_joc_obj_present[obj]"); //TODO TEST_SB_END(); } Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc_data_point_info() { Element_Begin1("joc_data_point_info"); //TODO Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc_data() { Element_Begin1("joc_data"); //TODO Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::joc_ext_data() { Element_Begin1("joc_ext_data"); //TODO Element_End0(); } //--------------------------------------------------------------------------- void File_Ac3::HD() { //Parsing int32u Synch; Peek_B3(Synch); if (Synch==0xF8726F) { if (Buffer_Offset+28>Buffer_Size) { Trusted_IsNot("Not enough data"); return; //Need more data } //Testing /* Not working int16u CRC_16_Table_HD[256]; CRC16_Init(CRC_16_Table_HD, 0x002D); int16u CRC_16=0x0000; const int8u* CRC_16_Buffer=Buffer+Buffer_Offset; while(CRC_16_Buffer>8)^(*CRC_16_Buffer)]; CRC_16_Buffer++; } CRC_16^=LittleEndian2int16u(Buffer+Buffer_Offset+24); */ Element_Info1("major_sync"); Element_Begin1("major_sync_info"); int32u format_sync; Get_B4(format_sync, "major_sync"); HD_StreamType=(int8u)format_sync; Param_Info1(AC3_HD_StreamType(HD_StreamType)); if ((HD_StreamType&0xFE)!=0xBA) { Skip_XX(Element_Size-Element_Offset, "Data"); return; } HD_format_info(); Skip_B2( "signature"); Get_B2 (HD_flags, "flags"); Skip_B2( "reserved"); BS_Begin(); Get_SB ( HD_IsVBR, "variable_rate"); Get_S2 (15, HD_BitRate_Max, "peak_data_rate"); 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"); Skip_S1( 2, "reserved"); Skip_S1( 2, "extended_substream_info"); if (HD_StreamType==0xBA) { Element_Begin1("substream_info"); Get_SB ( HD_HasAtmos, "16-channel presentation is present"); Skip_S1(3, "8-ch presentation"); Skip_S1(2, "6-ch presentation"); Skip_S1(2, "reserved"); Element_End0(); } else Skip_S1(8, "Unknown"); BS_End(); Element_Begin1("channel_meaning"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); Skip_B1( "Unknown"); if (HD_StreamType==0xBA) { BS_Begin(); Skip_S1( 7, "Unknown"); bool HasExtend; Get_SB ( HasExtend, "extra_channel_meaning_present"); BS_End(); if (HasExtend) { unsigned char Extend = 0; unsigned char Unknown = 0; bool HasContent = false; BS_Begin(); Get_S1( 4, Extend, "extra_channel_meaning_length"); size_t After=(((size_t)Extend)+1)*16-4; if (After>=Data_BS_Remain()) After=0; else After=Data_BS_Remain()-After; if (HD_HasAtmos) { Element_Begin1("16ch_channel_meaning"); Skip_S1(5, "16ch_dialogue_norm"); Skip_S1(6, "16ch_mix_level"); Get_S1 (5, num_dynamic_objects, "16ch_channel_count"); num_dynamic_objects++; program_assignment(); Element_End0(); } size_t RemainginBits=Data_BS_Remain(); if (RemainginBits>After) Skip_BS(RemainginBits-After, "(Unparsed bits)"); BS_End(); } } else Skip_B1( "Unknown"); Element_End0(); Skip_B2( "major_sync_info_CRC"); Element_End0(); } else if (!HD_MajorSync_Parsed) { return; // Wait for major sync } int64u PosBeforeDirectory=Element_Offset; BS_Begin(); for (int8u i=0; i>=4; crc^=Value; } for (int8u i=0; i>=4; crc^=Value; } if (crc!=0xF) { return; } HD_MajorSync_Parsed=true; if (HD_SubStreams_Count==1 && HD_StreamType==0xBB) //MLP with only 1 stream { HD_Resolution2=HD_Resolution1; HD_SamplingRate2=HD_SamplingRate1; } FILLING_END(); /* if (HD_MajorSync_Parsed) { Element_Begin1("Sizes"); std::vector Sizes; for (int8u Pos=0; Pos1 && Frame_Count_Valid<10000) Frame_Count_Valid*=32; } if (!Status[IsFilled] && !Core_IsPresent && Frame_Count>=Frame_Count_Valid) { Fill("AC-3"); //No more need data if (!IsSub && Config->ParseSpeed<1.0) Finish("AC-3"); } FILLING_END(); } void File_Ac3::HD_format_info() { if (HD_StreamType==0xBA) { Element_Begin1("format_info"); BS_Begin(); Get_S1 ( 4, HD_SamplingRate1, "audio_sampling_frequency"); Param_Info2(AC3_HD_SamplingRate(HD_SamplingRate1), " Hz"); Skip_SB( "6ch_multichannel_type"); Skip_SB( "8ch_multichannel_typ"); Skip_S1( 2, "reserved"); Skip_S1( 2, "2ch_presentation_channel_modifier"); Skip_S1( 2, "6ch_presentation_channel_modifier"); Get_S1 ( 5, HD_Channels1, "6ch_presentation_channel_assignment"); Param_Info1(AC3_TrueHD_Channels(HD_Channels1)); Param_Info1(Ztring().From_UTF8(AC3_TrueHD_Channels_Positions(HD_Channels1))); Get_S1 ( 2, dsurexmod, "8ch_presentation_channel_modifier"); Get_S2 (13, HD_Channels2, "8ch_presentation_channel_assignment"); Param_Info1(AC3_TrueHD_Channels(HD_Channels2)); Param_Info1(Ztring().From_UTF8(AC3_TrueHD_Channels_Positions(HD_Channels2))); BS_End(); HD_Resolution2=HD_Resolution1=24; //Not sure HD_SamplingRate2=HD_SamplingRate1; if (dsurexmod && !(HD_Channels2&(1<<3))) dsurexmod=0; //Only if Ls/Rs Element_End0(); } 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; } } //--------------------------------------------------------------------------- void File_Ac3::TimeStamp() { // Format looks like a Sync word 0x0110 then SMPTE ST 339 Time stamp //Parsing int16u SampleNumber; int8u H1, H2, M1, M2, S1, S2, F1, F2, FrameRate; bool DropFrame; Skip_B2( "Sync word"); BS_Begin(); Skip_S2(10, "H"); Get_S1 ( 2, H1, "H"); Get_S1 ( 4, H2, "H"); Skip_S2( 9, "M"); Get_S1 ( 3, M1, "M"); Get_S1 ( 4, M2, "M"); Skip_S2( 9, "S"); Get_S1 ( 3, S1, "S"); Get_S1 ( 4, S2, "S"); Skip_S2( 9, "F"); Get_SB ( DropFrame, "Drop frame"); Get_S1 ( 2, F1, "F"); Get_S1 ( 4, F2, "F"); Get_S2 (16, SampleNumber, "Sample number"); Skip_S2( 9, "Unknown"); Skip_SB( "Status"); Get_S1 ( 4, FrameRate, "Frame rate"); Param_Info1(Mpegv_frame_rate[FrameRate]); Skip_SB( "Status"); Skip_SB( "Drop frame"); BS_End(); Skip_B2( "User private"); FILLING_BEGIN(); TimeCode Temp(H1*10+H2, M1*10+M2, S1*10+S2, F1*10+F2, (int32u)(float64_int64s(Mpegv_frame_rate[FrameRate])-1), TimeCode::DropFrame(DropFrame).FPS1001(float64_int64s(Mpegv_frame_rate[FrameRate])!=Mpegv_frame_rate[FrameRate])); #if MEDIAINFO_TRACE if (Trace_Activated) { auto Temp_String=Temp.ToString(); if (SampleNumber) Temp_String+='-'+to_string(SampleNumber); Element_Info1(Temp_String); } #endif //MEDIAINFO_TRACE if (TimeStamp_Count==0) { TimeStamp_FirstFrame=Temp; TimeStamp_FirstFrame_SampleNumber=SampleNumber; } TimeStamp_IsParsing=false; TimeStamp_Parsed=true; TimeStamp_Count++; FILLING_END(); } //--------------------------------------------------------------------------- void File_Ac3::dac3() { BS_Begin(); Get_S1 (2, fscod, "fscod"); Get_S1 (5, bsid, "bsid"); Get_S1 (3, bsmod_Max[0][0], "bsmod"); Get_S1 (3, acmod_Max[0][0], "acmod"); Get_SB ( lfeon_Max[0][0], "lfeon"); Get_S1 (5, frmsizecod, "bit_rate_code"); frmsizecod*=2; Skip_S1(5, "reserved"); BS_End(); MustParse_dac3=false; dxc3_Parsed=true; } //--------------------------------------------------------------------------- void File_Ac3::dec3() { //Parsing BS_Begin(); int8u num_ind_sub; Skip_S2(13, "data_rate"); Get_S1 ( 3, num_ind_sub, "num_ind_sub"); for (int8u Pos=0; Pos<=num_ind_sub; Pos++) { Element_Begin1("independent substream"); int8u num_dep_sub; Get_S1 (2, fscod, "fscod"); Get_S1 (5, bsid, "bsid"); if (bsid_Max0) Skip_S2(9, "chan_loc"); else Skip_SB( "reserved"); Element_End0(); } if (Data_BS_Remain()) { Skip_S1( 7, "reserved"); TEST_SB_SKIP( "flag_ec3_extension_type_joc"); Get_S1 ( 8, joc_complexity_index_Container, "joc_complexity_index"); TEST_SB_END(); } BS_End(); if (Element_Offset>4, " bps"); Skip_S8(33, "reserved"); BS_End(); if (Element_Offset>3; int16u Size=0; if (bsid<=0x09) { int8u fscod =(CC1(Buffer+Buffer_Offset+4)>>6)&0x03; int8u frmsizecod=(CC1(Buffer+Buffer_Offset+4) )&0x3F; Size=AC3_FrameSize_Get(frmsizecod, fscod); } else if (bsid>0x0A && bsid<=0x10) { int16u frmsiz=CC2(Buffer+Buffer_Offset+2)&0x07FF; Size=2+frmsiz*2; } if (Size>=6) { if (Buffer_Offset+Size>Buffer_Size) return false; //Need more data if (CRC_Compute(Size)) { Synched=true; return true; } } } if (Buffer[Buffer_Offset+0]==0x77 && Buffer[Buffer_Offset+1]==0x0B) //AC-3 LE { bsid=CC1(Buffer+Buffer_Offset+4)>>3; int16u Size=0; if (bsid<=0x09) { int8u fscod =(CC1(Buffer+Buffer_Offset+5)>>6)&0x03; int8u frmsizecod=(CC1(Buffer+Buffer_Offset+5) )&0x3F; Size=AC3_FrameSize_Get(frmsizecod, fscod); } else if (bsid>0x0A && bsid<=0x10) { int16u frmsiz=LittleEndian2int16u(Buffer+Buffer_Offset+2)&0x07FF; Size=2+frmsiz*2; //TODO: case with multiple substreams } if (Size>=6) { size_t Size_Total=Core_Size_Get(); if (Element_IsWaitingForMoreData() || Buffer_Offset+Size_Total>=Buffer_Size) return false; //Need more data Save_Buffer=Buffer; Save_Buffer_Offset=Buffer_Offset; Save_Buffer_Size=Buffer_Size; { int8u* Buffer_Little=new int8u[Size_Total]; for (size_t Pos=0; Pos+1File_Ac3_IgnoreCrc_Get(); IgnoreCrc_Done=true; } if (IgnoreCrc && !Status[IsAccepted]) //Else there are some wrong synchronizations { MediaInfo_Internal MI; Ztring ParseSpeed_Save=MI.Option(__T("ParseSpeed_Get"), __T("")); Ztring Demux_Save=MI.Option(__T("Demux_Get"), __T("")); MI.Option(__T("ParseSpeed"), __T("0")); MI.Option(__T("Demux"), Ztring()); size_t MiOpenResult=MI.Open(File_Name); MI.Option(__T("ParseSpeed"), ParseSpeed_Save); //This is a global value, need to reset it. TODO: local value MI.Option(__T("Demux"), Demux_Save); //This is a global value, need to reset it. TODO: local value if (MiOpenResult) { Ztring Format=MI.Get(Stream_General, 0, General_Format); if (Format!=__T("AC-3") && Format!=__T("E-AC-3")) IgnoreCrc=false; } else IgnoreCrc=false; // Problem } if (IgnoreCrc) return true; int16u CRC_16=0x0000; const int8u* CRC_16_Buffer=Buffer+Buffer_Offset+2; //After syncword const int8u* CRC_16_Buffer_5_8=Buffer+Buffer_Offset+(((Size>>2)+(Size>>4))<<1); //Magic formula to meet 5/8 frame size from Dolby const int8u* CRC_16_Buffer_EndMinus3=Buffer+Buffer_Offset+Size-3; //End of frame minus 3 const int8u* CRC_16_Buffer_End=Buffer+Buffer_Offset+Size; //End of frame while(CRC_16_Buffer>8)^(*CRC_16_Buffer)]; //CRC bytes inversion if (CRC_16_Buffer==CRC_16_Buffer_EndMinus3 && bsid<=0x09 && ((*CRC_16_Buffer)&0x01)) //CRC inversion bit { CRC_16_Buffer++; CRC_16=(CRC_16<<8) ^ CRC_16_Table[(CRC_16>>8)^((int8u)(~(*CRC_16_Buffer)))]; CRC_16_Buffer++; CRC_16=(CRC_16<<8) ^ CRC_16_Table[(CRC_16>>8)^((int8u)(~(*CRC_16_Buffer)))]; } CRC_16_Buffer++; //5/8 intermediate test if (CRC_16_Buffer==CRC_16_Buffer_5_8 && bsid<=0x09 && CRC_16!=0x0000) break; } return (CRC_16==0x0000); } //--------------------------------------------------------------------------- size_t File_Ac3::Core_Size_Get() { bool IsLE=(Buffer[Buffer_Offset+0]==0x77); int16u Size=1; bsid=(Buffer[(size_t)(Buffer_Offset+5-IsLE)]&0xF8)>>3; if (bsid<=0x09) { int8u fscod =(Buffer[(size_t)(Buffer_Offset+4+IsLE)]&0xC0)>>6; int8u frmsizecod= Buffer[(size_t)(Buffer_Offset+4+IsLE)]&0x3F; //Filling fscods[fscod]++; frmsizecods[frmsizecod]++; Size=AC3_FrameSize_Get(frmsizecod, fscod); } else if (bsid>0x0A && bsid<=0x10) { int16u frmsiz =((int16u)(Buffer[(size_t)(Buffer_Offset+2+IsLE)]&0x07)<<8) | ( Buffer[(size_t)(Buffer_Offset+3-IsLE)] ); //Filling Size=2+frmsiz*2; } substreams_Count=0; int8u substreams_Count_Independant=0; int8u substreams_Count_Dependant=0; for (;;) { if (Buffer_Offset+Size+6>Buffer_Size) { if (!IsSub && !Save_Buffer && File_Offset+Buffer_Offset+Size>3; if (bsid<=0x09 || bsid>0x10) break; //Not E-AC-3 int8u substreamid=(Buffer[Buffer_Offset+Size+2+IsLE]>>3)&0x07; if (substreamid!=substreams_Count_Independant) break; //Problem if (substreamid!=substreams_Count_Dependant) break; //Problem int8u strmtyp = Buffer[Buffer_Offset+Size+2+IsLE]>>6; if (substreamid==0 && strmtyp==0) break; //Next block int16u frmsiz =((int16u)(Buffer[(size_t)(Buffer_Offset+Size+2+IsLE)]&0x07)<<8) | ( Buffer[(size_t)(Buffer_Offset+Size+3-IsLE)] ); //Filling Size+=2+frmsiz*2; if (strmtyp == 0) { substreams_Count_Independant++; substreams_Count_Dependant=0; } else substreams_Count_Dependant++; substreams_Count++; } return Size; } //--------------------------------------------------------------------------- size_t File_Ac3::HD_Size_Get() { size_t Size=BigEndian2int16u(Buffer+Buffer_Offset)&0x0FFF; Size*=2; return Size; } //--------------------------------------------------------------------------- void File_Ac3::Get_V4(int8u Bits, int32u &Info, const char* Name) { Info = 0; #if MEDIAINFO_TRACE int8u Count = 0; #endif //MEDIAINFO_TRACE for (;;) { Info += BS->Get4(Bits); #if MEDIAINFO_TRACE Count += Bits; #endif //MEDIAINFO_TRACE if (!BS->GetB()) break; Info <<= Bits; Info += (1 << Bits); } #if MEDIAINFO_TRACE if (Trace_Activated) { Param(Name, Info, Count); Param_Info(__T("(") + Ztring::ToZtring(Count) + __T(" bits)")); } #endif //MEDIAINFO_TRACE } //--------------------------------------------------------------------------- void File_Ac3::Skip_V4(int8u Bits, const char* Name) { #if MEDIAINFO_TRACE if (Trace_Activated) { int32u Info = 0; Get_V4(Bits, Info, Name); } else #endif //MEDIAINFO_TRACE { do BS->Skip(Bits); while (BS->GetB()); } } } //NameSpace #endif //MEDIAINFO_AC3_YES