/* 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" //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #if defined(MEDIAINFO_DTS_YES) //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- #include "MediaInfo/Audio/File_Dts.h" #include "ZenLib/Utils.h" #include "ZenLib/BitStream.h" #include "MediaInfo/TimeCode.h" #include "MediaInfo/MediaInfo_Config_MediaInfo.h" #if MEDIAINFO_EVENTS #include "MediaInfo/MediaInfo_Events.h" #endif //MEDIAINFO_EVENTS #include using namespace ZenLib; using namespace std; //--------------------------------------------------------------------------- namespace MediaInfoLib { //*************************************************************************** // Infos //*************************************************************************** //--------------------------------------------------------------------------- static constexpr int64u CHUNK_AUPR_HDR=0x415550522D484452LL; static constexpr int64u CHUNK_BUILDVER=0x4255494C44564552LL; static constexpr int64u CHUNK_CORESSMD=0x434F524553534D44LL; static constexpr int64u CHUNK_DTSHDHDR=0x4454534844484452LL; static constexpr int64u CHUNK_EXTSS_MD=0x45585453535F4D44LL; static constexpr int64u CHUNK_FILEINFO=0x46494C45494E464FLL; static constexpr int64u CHUNK_TIMECODE=0x54494D45434F4445LL; static constexpr int64u CHUNK_STRMDATA=0x5354524D44415441LL; //--------------------------------------------------------------------------- void Merge_FillTimeCode(File__Analyze& In, const string& Prefix, const TimeCode& TC_Time, float FramesPerSecondF, bool DropFrame, TimeCode::rounding Rounding=TimeCode::Nearest, int32u Frequency=0); //--------------------------------------------------------------------------- static const float TC_Frame_Rate_Table[]= { // Value 0 means "not indicated" 24/1.001, 24, 25, 30/1.001, // Drop 30/1.001, 30, // Drop 30, }; static constexpr size_t TC_Frame_Rate_Table_Size=sizeof(TC_Frame_Rate_Table)/sizeof(*TC_Frame_Rate_Table); static bool TC_Frame_Rate_IsDrop(int8u Value) { return Value==4 || Value==6; } //--------------------------------------------------------------------------- static const int16u DTS_HD_RefClockCode[]= { 32000, 44100, 48000, }; static constexpr size_t DTS_HD_RefClockCode_Size=sizeof(DTS_HD_RefClockCode)/sizeof(*DTS_HD_RefClockCode); //--------------------------------------------------------------------------- static const int16u CRC_CCIT_Table[256]= { 0x0000, 0x2110, 0x4220, 0x6330, 0x8440, 0xA550, 0xC660, 0xE770, 0x0881, 0x2991, 0x4AA1, 0x6BB1, 0x8CC1, 0xADD1, 0xCEE1, 0xEFF1, 0x3112, 0x1002, 0x7332, 0x5222, 0xB552, 0x9442, 0xF772, 0xD662, 0x3993, 0x1883, 0x7BB3, 0x5AA3, 0xBDD3, 0x9CC3, 0xFFF3, 0xDEE3, 0x6224, 0x4334, 0x2004, 0x0114, 0xE664, 0xC774, 0xA444, 0x8554, 0x6AA5, 0x4BB5, 0x2885, 0x0995, 0xEEE5, 0xCFF5, 0xACC5, 0x8DD5, 0x5336, 0x7226, 0x1116, 0x3006, 0xD776, 0xF666, 0x9556, 0xB446, 0x5BB7, 0x7AA7, 0x1997, 0x3887, 0xDFF7, 0xFEE7, 0x9DD7, 0xBCC7, 0xC448, 0xE558, 0x8668, 0xA778, 0x4008, 0x6118, 0x0228, 0x2338, 0xCCC9, 0xEDD9, 0x8EE9, 0xAFF9, 0x4889, 0x6999, 0x0AA9, 0x2BB9, 0xF55A, 0xD44A, 0xB77A, 0x966A, 0x711A, 0x500A, 0x333A, 0x122A, 0xFDDB, 0xDCCB, 0xBFFB, 0x9EEB, 0x799B, 0x588B, 0x3BBB, 0x1AAB, 0xA66C, 0x877C, 0xE44C, 0xC55C, 0x222C, 0x033C, 0x600C, 0x411C, 0xAEED, 0x8FFD, 0xECCD, 0xCDDD, 0x2AAD, 0x0BBD, 0x688D, 0x499D, 0x977E, 0xB66E, 0xD55E, 0xF44E, 0x133E, 0x322E, 0x511E, 0x700E, 0x9FFF, 0xBEEF, 0xDDDF, 0xFCCF, 0x1BBF, 0x3AAF, 0x599F, 0x788F, 0x8891, 0xA981, 0xCAB1, 0xEBA1, 0x0CD1, 0x2DC1, 0x4EF1, 0x6FE1, 0x8010, 0xA100, 0xC230, 0xE320, 0x0450, 0x2540, 0x4670, 0x6760, 0xB983, 0x9893, 0xFBA3, 0xDAB3, 0x3DC3, 0x1CD3, 0x7FE3, 0x5EF3, 0xB102, 0x9012, 0xF322, 0xD232, 0x3542, 0x1452, 0x7762, 0x5672, 0xEAB5, 0xCBA5, 0xA895, 0x8985, 0x6EF5, 0x4FE5, 0x2CD5, 0x0DC5, 0xE234, 0xC324, 0xA014, 0x8104, 0x6674, 0x4764, 0x2454, 0x0544, 0xDBA7, 0xFAB7, 0x9987, 0xB897, 0x5FE7, 0x7EF7, 0x1DC7, 0x3CD7, 0xD326, 0xF236, 0x9106, 0xB016, 0x5766, 0x7676, 0x1546, 0x3456, 0x4CD9, 0x6DC9, 0x0EF9, 0x2FE9, 0xC899, 0xE989, 0x8AB9, 0xABA9, 0x4458, 0x6548, 0x0678, 0x2768, 0xC018, 0xE108, 0x8238, 0xA328, 0x7DCB, 0x5CDB, 0x3FEB, 0x1EFB, 0xF98B, 0xD89B, 0xBBAB, 0x9ABB, 0x754A, 0x545A, 0x376A, 0x167A, 0xF10A, 0xD01A, 0xB32A, 0x923A, 0x2EFD, 0x0FED, 0x6CDD, 0x4DCD, 0xAABD, 0x8BAD, 0xE89D, 0xC98D, 0x267C, 0x076C, 0x645C, 0x454C, 0xA23C, 0x832C, 0xE01C, 0xC10C, 0x1FEF, 0x3EFF, 0x5DCF, 0x7CDF, 0x9BAF, 0xBABF, 0xD98F, 0xF89F, 0x176E, 0x367E, 0x554E, 0x745E, 0x932E, 0xB23E, 0xD10E, 0xF01E, }; uint16_t Dts_CRC_CCIT_Compute(const uint8_t* Buffer, size_t Size) { uint16_t C = 0xFFFF; const uint8_t *End = Buffer + Size; while (Buffer < End) C = (C >> 8) ^ CRC_CCIT_Table[((uint8_t)C) ^ *Buffer++]; return C; } //--------------------------------------------------------------------------- static const char* DTS_FrameType[]= { "Termination", "Normal", }; //--------------------------------------------------------------------------- static const int32u DTS_SamplingRate[]= { 0, 8000, 16000, 32000, 0, 0, 11025, 22050, 44100, 0, 0, 12000, 24000, 48000, 96000, 192000, }; //--------------------------------------------------------------------------- static const int32u DTS_BitRate[]= { 32000, 56000, 64000, 96000, 112000, 128000, 192000, 224000, 256000, 320000, 384000, 448000, 512000, 576000, 640000, 754500, 960000, 1024000, 1152000, 1280000, 1344000, 1408000, 1411200, 1472000, 1509750, 1920000, 2048000, 3072000, 3840000, 0, 0, 0, }; //--------------------------------------------------------------------------- static const int8u DTS_Channels[]= { 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 6, 6, 7, 8, 8, }; //--------------------------------------------------------------------------- static const int8u DTS_Resolution[]= {16, 20, 24, 24}; //--------------------------------------------------------------------------- const char* DTS_ChannelPositions[16]= { "Front: C", "Front: C C", "Front: L R", "Front: L R", "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", "Front: L C C R, Side: L R", "Front: L C R, Side: L R", "Front: L R, Side: L R, Back: L R", "Front: L C R, Side: L R, Back: L R", "Front: L R, Side: L R, Back: L C C R", "Front: L C R, Side: L R, Back: L C R", }; //--------------------------------------------------------------------------- const char* DTS_ChannelPositions2[16]= { "1/0/0", "2/0/0", "2/0/0", "2/0/0", "2/0/0", "3/0/0", "2/1/0", "3/1/0", "2/2/0", "3/2/0", "4/2/0", "3/2/0", "2/2/2", "3/2/2", "2/2/4", "3/2/3", }; //--------------------------------------------------------------------------- static const char* DTS_ChannelLayout[16]= { "M", "M M", "L R", "L R", "Lt Rt", "C L R", "L R Cs", "C L R Cs", "L R Ls Rs", "C L R Ls Rs", "Cl Cr L R Ls Rs", "C L R Ls Rs", "C L R Ls Rs Lrs Rrs", "C L R Ls Rs Lrs Rrs", "L R Ls Rs Rls Cs Cs Rrs", "C L R Ls Rs Rls Cs Rrs", }; //--------------------------------------------------------------------------- static const char* DTS_ExtensionAudioDescriptor[]= { "Channel Extension", "Reserved", "Frequency Extension", "Channel Extension + Frequency Extension", "", "", "", "", }; //--------------------------------------------------------------------------- std::string DTS_HD_SpeakerActivityMask (int16u SpeakerActivityMask, bool AddCs=false, bool AddLrsRrs=false) { std::string Text; if ((SpeakerActivityMask&0x0003)==0x0003) Text+="Front: L C R"; else { if (SpeakerActivityMask&0x0001) Text+="Front: C"; if (SpeakerActivityMask&0x0002) Text+="Front: L R"; } if (SpeakerActivityMask&0x0004) Text+=", Side: L R"; if (SpeakerActivityMask&0x0010 || AddCs) Text+=", Back: C"; if ((SpeakerActivityMask&0x00A0)==0x00A0) Text+=", High: L C R"; else { if (SpeakerActivityMask&0x0020 || AddLrsRrs) Text+=", High: L R"; if (SpeakerActivityMask&0x0080) Text+=", High: C"; } if (SpeakerActivityMask&0x0800) Text+=", Side: L R"; if (SpeakerActivityMask&0x0040) Text+=", Back: L R"; if (SpeakerActivityMask&0x0100) Text+=", TopCtrSrrd"; if (SpeakerActivityMask&0x0200) Text+=", Ctr: L R"; if (SpeakerActivityMask&0x0400) Text+=", Wide: L R"; if (SpeakerActivityMask&0x2000) Text+=", HiSide: L R"; if ((SpeakerActivityMask&0xC000)==0x0C000) Text+=", HiRear: L C R"; else { if (SpeakerActivityMask&0x4000) Text+=", HiRear: C"; if (SpeakerActivityMask&0x8000) Text+=", HiRear: L R"; } if (SpeakerActivityMask&0x0008) Text+=", LFE"; if (SpeakerActivityMask&0x1000) Text+=", LFE2"; return Text; } //--------------------------------------------------------------------------- std::string DTS_HD_SpeakerActivityMask2 (int16u SpeakerActivityMask, bool AddCs=false, bool AddLrsRrs=false) { std::string Text; if ((SpeakerActivityMask&0x0003)==0x0003) Text+="3"; else { if (SpeakerActivityMask&0x0001) Text+="1"; else if (SpeakerActivityMask&0x0002) Text+="2"; else Text+="0"; } if (SpeakerActivityMask&0x0004) Text+="/2"; else if ((SpeakerActivityMask&0x0840)==0x0000) Text+="/0"; if (SpeakerActivityMask&0x0010 || AddCs) Text+="/1"; else if ((SpeakerActivityMask&0x0840)==0x0000) Text+="/0"; if ((SpeakerActivityMask&0x00A0)==0x00A0) Text+=".3"; else { if (SpeakerActivityMask&0x0020 || AddLrsRrs) Text+=".2"; if (SpeakerActivityMask&0x0080) Text+=".2"; } if (SpeakerActivityMask&0x0800) Text+="/2"; if (SpeakerActivityMask&0x0040) Text+="/2"; if (SpeakerActivityMask&0x0100) Text+=".1"; if (SpeakerActivityMask&0x0200) Text+=".2"; if (SpeakerActivityMask&0x0400) Text+=".2"; if (SpeakerActivityMask&0x2000) Text+=".2"; if ((SpeakerActivityMask&0xC000)==0x0C000) Text+=".3"; else { if (SpeakerActivityMask&0x4000) Text+=".1"; if (SpeakerActivityMask&0x8000) Text+=".2"; } if (SpeakerActivityMask&0x0008) Text+=".1"; if (SpeakerActivityMask&0x1000) Text+=".1"; return Text; } //--------------------------------------------------------------------------- std::string DTS_HD_SpeakerActivityMask_ChannelLayout (int16u SpeakerActivityMask, bool AddCs=false, bool AddLrsRrs=false) { std::string Text; if (SpeakerActivityMask==1) return "M"; if (SpeakerActivityMask&0x0001) Text+=" C"; if (SpeakerActivityMask&0x0002) Text+=" L R"; if (SpeakerActivityMask&0x0004) Text+=" Ls Rs"; if (SpeakerActivityMask&0x0008) Text+=" LFE"; if (SpeakerActivityMask&0x0010 || AddCs) Text+=" Cs"; if (SpeakerActivityMask&0x0020) Text+=" Lh Rh"; if (SpeakerActivityMask&0x0040 || AddLrsRrs) Text+=" Lsr Rsr"; if (SpeakerActivityMask&0x0080) Text+=" Ch"; if (SpeakerActivityMask&0x0100) Text+=" Oh"; if (SpeakerActivityMask&0x0200) Text+=" Lc Rc"; if (SpeakerActivityMask&0x0400) Text+=" Lw Rw"; if (SpeakerActivityMask&0x0800) Text+=" Lss Rss"; if (SpeakerActivityMask&0x1000) Text+=" LFE2"; if (SpeakerActivityMask&0x2000) Text+=" Lhs Rhs"; if (SpeakerActivityMask&0x4000) Text+=" Chr"; if (SpeakerActivityMask&0x8000) Text+=" Lhr"; if (!Text.empty()) Text.erase(0, 1); return Text; } //--------------------------------------------------------------------------- static const char* DTS_HD_TypeDescriptor[]= { "Music", "Effects", "Dialog", "Commentary", "Visually Impaired", "Hearing Impaired", "Isolated Music Object", "Music and Effects", "Dialog and Commentary", "Effects and Commentary", "Isolated Music Object and Commentary", "Isolated Music Object and Effects", "Karaoke", "Music, Effects, Dialog", "Complete Audio Presentation", "", }; //--------------------------------------------------------------------------- static int32u DTS_HD_MaximumSampleRate[]= { 8000, 16000, 32000, 64000, 128000, 22050, 44100, 88200, 176400, 352800, 12000, 24000, 48000, 96000, 192000, 384000, }; //--------------------------------------------------------------------------- static int8u DTS_HD_SamplePerFrames_Factor[]= { 0, 1, 2, 3, 4, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, }; //--------------------------------------------------------------------------- enum extension { Ext_Padding4, Ext_Core, Ext_LBR, Ext_X96, Ext_XLL, Ext_XXCH, Ext_XCh, Ext_XBR, Ext_Aux, Ext_Max }; static int32u DTS_Extension_Mapping[]= { 0x00000000, 0x02b09261, 0x0A801921, 0x1D95F262, 0x41A29547, 0x47004A03, 0x5A5A5A5A, 0x655E315E, 0x9A1105A0, }; static_assert(sizeof(DTS_Extension_Mapping)/sizeof(decltype(*DTS_Extension_Mapping))==Ext_Max, ""); static const char* DTS_Extension_Names[]= { "Padding", "Core", "LBR (Low Bit Rate)", "X96 (96 kHz / 24-bit)", "XLL (LossLess)", "XXCH (More Than 5.1 Channels)", "XCh (6.1 Channels)", "XBR (Extended Bit Rate)", "Aux", }; static_assert(sizeof(DTS_Extension_Names)/sizeof(decltype(*DTS_Extension_Names))==Ext_Max, ""); static size_t DTS_Extension_Index_Get(int32u SyncWord) { for (size_t i=0; i1) { bool IsNotSame=false; for (size_t i=1; iPTS_Begin) { Fill(Stream_Audio, 0, Audio_Duration, ((float64)(FrameInfo.PTS-PTS_Begin))/1000000, 0, true); float64 SamplesPerFrame=Retrieve(Stream_Audio, 0, Audio_SamplesPerFrame).To_float64(); float64 SamplingRate=Retrieve(Stream_Audio, 0, Audio_SamplingRate).To_float64(); if (SamplesPerFrame && SamplingRate) Fill(Stream_Audio, 0, Audio_FrameCount, ((float64)(FrameInfo.PTS-PTS_Begin))/1000000000/(SamplesPerFrame/SamplingRate), 0, true); } } //*************************************************************************** // Buffer - File header //*************************************************************************** //--------------------------------------------------------------------------- bool File_Dts_Common::FileHeader_Begin() { //Must have enough buffer for having header if (Buffer_Size<4) return false; //Must wait for more data //False positives detection: Detect WAV files, the parser can't detect it easily, there is only 70 bytes of beginning for saying WAV switch (CC4(Buffer)) { case 0x52494646 : //"RIFF" case 0x000001FD : //MPEG-PS private Finish("DTS"); return false; default : ; } //All should be OK... if (!Frame_Count_Valid) Frame_Count_Valid=Config->ParseSpeed>=0.3?32:(IsSub?1:2); return true; } //--------------------------------------------------------------------------- void File_Dts_Common::FileHeader_Parse() { //DTSHDHDR header //https://www.atsc.org/wp-content/uploads/2015/03/Non-Real-Time-Content-Delivery.pdf if (IsSub || CC8(Buffer)!=CHUNK_DTSHDHDR || CC4(Buffer+8)) return; int64u StreamSize=-1; int16u Bitw_Stream_Metadata; bool Header_Parsed=false; int64u Num_Samples_Orig_Audio_At_Max_Fs=0; int32u Num_Frames_Total, TimeStamp, Max_Sample_Rate_Hz=0, Ext_Ss_Avg_Bit_Rate_Kbps=0, Ext_Ss_Peak_Bit_Rate_Kbps=0; int16u Core_Ss_Bit_Rate_Kbps=0, Samples_Per_Frame_At_Max_Fs=0, Codec_Delay_At_Max_Fs=0; int8u RefClockCode, TC_Frame_Rate=-1; while (StreamSize==-1 && Element_Size-Element_Offset>=16) { int64u Name, Size; Element_Begin1("Element"); Element_Begin1("Header"); Get_C8 (Name, "Name"); Get_B8 (Size, "Size"); Element_End0(); Ztring ToShow; for (int i=0; i<8; i++) ToShow.append(1, (ZenLib::Char)((Name>>(56-i*8)))&0xFF); Element_Name(ToShow); if (Name!=CHUNK_STRMDATA && Size>Element_Size-Element_Offset) { Element_End0(); Element_WaitForMoreData(); return; } auto End=Element_Offset+Size; switch (Name) { case CHUNK_AUPR_HDR: { int16u Bitw_Aupres_Metadata; Skip_B1( "Audio_Pres_Index"); Get_B2 (Bitw_Aupres_Metadata, "Bitw_Aupres_Metadata"); Skip_Flags(Bitw_Aupres_Metadata, 3, "Presence of a LBR coding componen"); Skip_Flags(Bitw_Aupres_Metadata, 2, "Presence of a lossless coding component"); Skip_Flags(Bitw_Aupres_Metadata, 1, "Location of a backward compatible core coding component"); Skip_Flags(Bitw_Aupres_Metadata, 0, "Presence of a backward compatible core coding component"); Get_B3 (Max_Sample_Rate_Hz, "Max_Sample_Rate_Hz"); Get_B4 (Num_Frames_Total, "Num_Frames_Total"); Get_B2 (Samples_Per_Frame_At_Max_Fs, "Samples_Per_Frame_At_Max_Fs"); Get_B5 (Num_Samples_Orig_Audio_At_Max_Fs, "Num_Samples_Orig_Audio_At_Max_Fs"); Skip_B2( "Channel_Mask"); Get_B2 (Codec_Delay_At_Max_Fs, "Codec_Delay_At_Max_Fs"); if ((Bitw_Aupres_Metadata&3)==3) { Skip_B3( "BC_Core_Max_Sample_Rate_Hz"); Skip_B2( "BC_Core_Bit_Rate_Kbps"); Skip_B2( "BC_Core_Channel_Mask"); } if (Bitw_Aupres_Metadata&4) { Skip_B1( "LSB_Trim_Percent"); } break; } case CHUNK_CORESSMD: { Skip_B3( "Core_Ss_Max_Sample_Rate_Hz"); Get_B2 (Core_Ss_Bit_Rate_Kbps, "Core_Ss_Bit_Rate_Kbps"); Skip_B2( "Core_Ss_Channel_Mask"); Skip_B4( "Core_Ss_Frame_Payload_In_Bytes"); break; } case CHUNK_DTSHDHDR: { Skip_B4( "Hdr_Version"); Get_B1 (RefClockCode, "Time_Code RefClockCode"); RefClockCode>>=6; Param_Info1C(RefClockCode=Samples_Per_Frame_At_Max_Fs) SamplingCount+=Codec_Delay_At_Max_Fs; // If less, we guess it is a delay inside the frame and first samples should be discarded, else it is complete frames, so need to add to sample count as the frames are decoded Fill(Stream_Audio, 0, Audio_SamplingCount, SamplingCount); } int32u BitRate_Nominal=Core_Ss_Bit_Rate_Kbps+Ext_Ss_Avg_Bit_Rate_Kbps; if (BitRate_Nominal) { BitRate_Nominal*=1000; Fill(Stream_General, 0, General_OverallBitRate, BitRate_Nominal); Fill(Stream_Audio, 0, Audio_BitRate_Nominal, BitRate_Nominal); } if (Ext_Ss_Peak_Bit_Rate_Kbps) { int32u BitRate_Maximum=Core_Ss_Bit_Rate_Kbps+Ext_Ss_Peak_Bit_Rate_Kbps; BitRate_Maximum*=1000; Fill(Stream_General, 0, General_OverallBitRate_Maximum, BitRate_Maximum); Fill(Stream_Audio, 0, Audio_BitRate_Maximum, BitRate_Maximum); } Fill(Stream_Audio, 0, Audio_StreamSize, StreamSize); Stream_Offset_Max=File_Offset+Element_Offset+StreamSize; FILLING_END() } //*************************************************************************** // Buffer - Gobal //*************************************************************************** //--------------------------------------------------------------------------- bool File_Dts_Common::Header_Begin() { if (Stream_Offset_Max==-1 || File_Offset+Buffer_Offset!=Stream_Offset_Max || File_Size==-1) return true; //Handling DTSHDHDR footer if (File_Offset+Buffer_Size=16) { int64u Name, Size; Element_Begin1("Element"); Element_Begin1("Header"); Get_C8 (Name, "Name"); Get_B8 (Size, "Size"); Element_End0(); Ztring ToShow; for (int i=0; i<8; i++) ToShow.append(1, (ZenLib::Char)((Name>>(56-i*8)))&0xFF); Element_Name(ToShow); auto End=Element_Offset+Size; switch (Name) { case CHUNK_BUILDVER: { size_t Element_Offset_End=(size_t)Element_Offset; while (Element_Offset_EndBuffer_Size) { if (Buffer_Offset+5==Buffer_Size) { int64u Value=CC5(Buffer+Buffer_Offset); if ((Value&0xFFFFFFFFFCLL)!=0x7FFE8001FCLL //16 bits and big endian Core && (Value&0xFFFFFFFF00LL)!=0xFE7F018000LL //16 bits and little endian Core && (Value&0xFFFFFFFFF7LL)!=0x1FFFE80007LL //14 bits and big endian Core && (Value&0xFFFFFFFFF0LL)!=0xFF1F00E8F0LL //14 bits and little endian Core && (Value&0xFFFFFFFF00LL)!=0x6458202500LL) //16 bits and big endian HD Buffer_Offset++; } if (Buffer_Offset+4==Buffer_Size) { int32u Value=CC4(Buffer+Buffer_Offset); if (Value!=0x7FFE8001 //16 bits and big endian Core && Value!=0xFE7F0180 //16 bits and little endian Core && Value!=0x1FFFE800 //14 bits and big endian Core && Value!=0xFF1F00E8 //14 bits and little endian Core && Value!=0x64582025) //16 bits and big endian HD Buffer_Offset++; } if (Buffer_Offset+3==Buffer_Size) { int32u Value=CC3(Buffer+Buffer_Offset); if (Value!=0x7FFE80 //16 bits and big endian Core && Value!=0xFE7F01 //16 bits and little endian Core && Value!=0x1FFFE8 //14 bits and big endian Core && Value!=0xFF1F00 //14 bits and little endian Core && Value!=0x645820) //16 bits and big endian HD Buffer_Offset++; } if (Buffer_Offset+2==Buffer_Size) { int16u Value=CC2(Buffer+Buffer_Offset); if (Value!=0x7FFE //16 bits and big endian Core && Value!=0xFE7F //16 bits and little endian Core && Value!=0x1FFF //14 bits and big endian Core && Value!=0xFF1F //14 bits and little endian Core && Value!=0x6458) //16 bits and big endian HD Buffer_Offset++; } if (Buffer_Offset+1==Buffer_Size) { int8u Value=CC1(Buffer+Buffer_Offset); if (Value!=0x7F //16 bits and big endian Core && Value!=0xFE //16 bits and little endian Core && Value!=0x1F //14 bits and big endian Core && Value!=0xFF //14 bits and little endian Core && Value!=0x64) //16 bits and big endian HD Buffer_Offset++; } return false; } //Synched return true; } //--------------------------------------------------------------------------- bool File_Dts::Synched_Test() { //Padding while (Buffer_OffsetBuffer_Size) return false; //Quick test of synchro if (!FrameSynchPoint_Test()) return false; //Need more data if (!Synched) { if (Stream_Offset_Max!=-1 && File_Offset+Buffer_Offset==Stream_Offset_Max && File_Size!=-1) Synched=true; // It is the file footer return true; } //We continue return true; } //--------------------------------------------------------------------------- void File_Dts::Read_Buffer_Unsynched() { FrameInfo=frame_info(); } //*************************************************************************** // Buffer - Demux //*************************************************************************** //--------------------------------------------------------------------------- #if MEDIAINFO_DEMUX bool File_Dts::Demux_UnpacketizeContainer_Test() { int32u Value=CC4(Buffer+Buffer_Offset); if (Value==0x7FFE8001) { int16u Size=((BigEndian2int24u(Buffer+Buffer_Offset+5)>>4)&0x3FFF)+1; Demux_Offset=Buffer_Offset+Size; if (Buffer_Offset+Size>Buffer_Size && File_Offset+Buffer_Size!=File_Size) return false; //No complete frame Demux_UnpacketizeContainer_Demux(); } return true; } #endif //MEDIAINFO_DEMUX //*************************************************************************** // Buffer - Per element //*************************************************************************** //--------------------------------------------------------------------------- void File_Dts::Header_Parse() { Header_Fill_Size(Original_Size); } //*************************************************************************** // Elements //*************************************************************************** //--------------------------------------------------------------------------- void File_Dts::Data_Parse() { if (Save_Buffer) { File_Offset+=Buffer_Offset; swap(Buffer, Save_Buffer); swap(Buffer_Offset, Save_Buffer_Offset); swap(Buffer_Size, Save_Buffer_Size); if (!Word) Element_Size=Element_Size*14/16; } //Parsing int32u Sync; Peek_B4 (Sync); if (Sync==0x64582025) { //HD Element_Name("HD"); Element_Info1(Ztring::ToZtring(Frame_Count-(Core_Exists?1:0))); Element_Code=1; Element_Begin1("Header"); int16u ExtSSHeaderSize; int8u SubStreamIndex, NumAssets, NumAudioPresent; bool isBlownUpHeader, StaticFieldsPresent; Skip_B4( "Sync"); Skip_B1( "UserDefinedBits"); BS_Begin(); int64u EndBS=Data_BS_Remain(); Get_S1 (2, SubStreamIndex, "ExtSSIndex"); Get_SB (isBlownUpHeader, "HeaderSizeType"); int8u ExtraSize=((int8u)isBlownUpHeader)<<2; Get_S2 ( 8+ExtraSize, ExtSSHeaderSize, "ExtSSHeaderSize"); if (ExtSSHeaderSize<4) { Element_End0(); return; } auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, ExtSSHeaderSize-4); if (CRC) { Element_Info1("CRC NOK"); Element_End0(); return; } Param_Info2(ExtSSHeaderSize+1, " bytes"); Get_S3 (16+ExtraSize, HD_size, "ExtSSFsize"); HD_size++; Param_Info2(HD_size, " bytes"); TESTELSE_SB_GET(StaticFieldsPresent, "StaticFieldsPresent"); std::vector ActiveExSSMasks; Info_S1(2, RefClockCode, "RefClockCode"); Param_Info1C(RefClockCode2) Skip_SB( "TotalNumChs"); //else is 0 if (HD_TotalNumberChannels>6) Skip_SB( "EmbeddedSixChFlag"); //else is 0 TESTELSE_SB_SKIP( "SpkrMaskEnabled"); Get_S1 (2, SpeakerActivityMaskBits, "NumBits4SAMask"); Param_Info2(4+SpeakerActivityMaskBits*4, " bits"); SpeakerActivityMaskBits=4+SpeakerActivityMaskBits*4; Get_S2 (SpeakerActivityMaskBits, HD_SpeakerActivityMask, "SpkrActivityMask"); Param_Info1(DTS_HD_SpeakerActivityMask(HD_SpeakerActivityMask).c_str()); TESTELSE_SB_ELSE( "SpkrMaskEnabled"); SpeakerActivityMaskBits=0; TESTELSE_SB_END(); Get_S1 (3, SpeakerRemapSetsCount, "NumSpkrRemapSets"); for (int8u Pos=0; Pos=2 && (Frame_Count>=Frame_Count_Valid || (Frame_Count_Valid && (File_Size-Buffer_TotalBytes_FirstSynched)/Frame_Count_ValidParseSpeed<1.0) { if (Stream_Offset_Max!=-1) GoTo(Stream_Offset_Max); else Finish("DTS"); } } FILLING_END(); } //--------------------------------------------------------------------------- void File_Dts::Extensions() { //Parsing for (auto Size : Asset_Sizes) { if (Element_Code) Element_Begin1("Asset"); if (Size<4) { Skip_XX(Size, "?"); continue; } auto Element_Size_Save=Element_Size; Element_Size=Element_Offset+Size; while (Element_Size-Element_Offset>=4) { Element_Begin0(); int32u SyncWord; Get_B4(SyncWord, "Sync Word"); auto Index=DTS_Extension_Index_Get(SyncWord); Element_Name(Index!=(size_t)-1?Ztring().From_UTF8(DTS_Extension_Names[Index]):Ztring::ToZtring(SyncWord, 16)); switch (Index) { #define CASE(EXT) case Ext_##EXT : EXT(); break; CASE(Padding4); CASE(LBR); CASE(X96); CASE(XLL); CASE(XXCH); CASE(XCh); CASE(XBR); CASE(Aux); #undef CASE default: Extensions_Resynch(false); } Element_End0(); } Element_Size=Element_Size_Save; if (Element_Code) Element_End0(); } Asset_Sizes.clear(); //Filling FILLING_BEGIN(); if (Count_Get(Stream_Audio)==0 && Frame_Count>=Frame_Count_Valid) { Accept("DTS"); Fill("DTS"); //No more need data if (!IsSub && Config->ParseSpeed<1.0) Finish("DTS"); } FILLING_END(); if (Element_Size-Element_Offset>=6) { int64u SyncWord; Peek_B6(SyncWord); if (SyncWord==0x3A429B0A0011) { Element_Begin1("After assets?"); Element_Begin1("Header"); Skip_B6( "SyncWord"); Element_End0(); Extensions2(); Element_End0(); } } if (Element_Size>Element_Offset) Skip_XX(Element_Size-Element_Offset, "(Unknown)"); } //--------------------------------------------------------------------------- void File_Dts::Extensions_Resynch(bool Known) { if (Element_Size-Element_Offset<4) return; auto Element_Offset_Sav=Element_Offset; auto Element_Offset_Max=Element_Size-3; auto Base=Buffer+Buffer_Offset; auto AlignmentBytes=Element_Offset%4; if (AlignmentBytes) Element_Offset+=4-AlignmentBytes; while (Element_Offset1) { bool IsNok=false; if (Element_Code) { // HD switch (Index) { case Ext_X96: case Ext_XLL: case Ext_XXCH: break; default: IsNok=true; } } else { // Core switch (Index) { case Ext_XCh: IsNok=!ExtendedCoding || (ExtensionAudioDescriptor!=0 && ExtensionAudioDescriptor!=3); break; case Ext_XXCH: IsNok=!ExtendedCoding || (ExtensionAudioDescriptor!=6); break; case Ext_X96: IsNok=!ExtendedCoding || (ExtensionAudioDescriptor!=2 && ExtensionAudioDescriptor!=3); break; case Ext_Aux: IsNok=!AuxiliaryData; break; default: IsNok=true; } } if (!IsNok) break; } Element_Offset+=4; } if (Element_Offset!=Element_Offset_Sav) { swap(Element_Offset, Element_Offset_Sav); if (Element_Size-Element_Offset_Sav<=3) Element_Offset_Sav=Element_Size; Skip_XX(Element_Offset_Sav-Element_Offset, Known?"(Not parsed)":"(Unknown)"); } } //--------------------------------------------------------------------------- void File_Dts::Extensions_Padding() { auto Begin=Buffer+Buffer_Offset+(size_t)Element_Offset; auto Current=Begin; auto Size=Element_Size-Element_Offset; auto PaddingBytes=4-(Element_Offset%4); if (PaddingBytes!=4 && PaddingBytes<=Size) { int32u Padding; switch (PaddingBytes) { case 1 : Padding=BigEndian2int8u(Current); break; case 2 : Padding=BigEndian2int16u(Current); break; default: Padding=BigEndian2int24u(Current); } if (Padding) { Skip_XX(PaddingBytes, "(Unknown)"); return; } Current+=PaddingBytes; } auto End=decltype(Begin)((((size_t)Current+Size)>>2)<<2); while (Current>2; if (HeaderSize<=3) return; auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, HeaderSize-3); if (CRC) { Element_Info1("CRC NOK"); Extensions_Resynch(false); return; } } else { // Core auto MaxSize=Element_Size-Element_Offset+3; int16u Begin; Peek_B2(Begin); int16u Size=Begin>>4; if (MaxSize<95 || Size<95 || Size!=MaxSize) { Extensions_Resynch(false); return; } Skip_XX(Size-3, "(Not parsed)"); } FILLING_BEGIN(); Presence.set(Element_Code?presence_Extended_X96:presence_Core_X96); FILLING_END(); Extensions_Resynch(true); } //--------------------------------------------------------------------------- void File_Dts::AfterAssets() { // Found in DTS:X content when after assets, no idea about what it is auto MaxSize=Element_Size-Element_Offset; if (MaxSize<2) return; int16u Begin; Peek_B2(Begin); if (Begin!=0x0011) return; Skip_B2( "?"); } //--------------------------------------------------------------------------- void File_Dts::XLL() { //Coherency check auto MaxSize=Element_Size-Element_Offset+3; if (MaxSize<8) return; int16u Begin; Peek_B2(Begin); int8u Version=Begin>>12; if (Version) return; int8u HeaderSize=Begin>>4; if (HeaderSize<8) return; auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, HeaderSize-3); if (CRC) { Element_Info1("CRC NOK"); Extensions_Resynch(false); return; } FILLING_BEGIN(); Presence.set(presence_Extended_XLL); FILLING_END(); // Parsing int32u LLFrameSize; int16u ChSetHeaderSize; int8u Bits4FrameFsize, NumChSetsInFrame, SegmentsInFrame, Bits4SSize, Bits4ChMask; bool ScalableLSBs; Element_Begin1("Header"); auto Element_Offset_Start=Element_Offset; BS_Begin(); int64u EndBS=Data_BS_Remain(); Skip_S1(4, "Version"); Skip_S1(8, "HeaderSize"); Param_Info1(HeaderSize); Get_S1 (5, Bits4FrameFsize, "Bits4FrameFsize"); Param_Info1(Bits4FrameFsize+1); Get_S4 (Bits4FrameFsize+1, LLFrameSize, "LLFrameSize minus 1"); if (LLFrameSize<6) { BS_End(); Element_End0(); Skip_XX(Element_Size-Element_Offset, "(Unknown)"); return; } auto Element_Size_Save=Element_Size; Element_Size=Element_Offset_Start-3+LLFrameSize; Get_S1 (4, NumChSetsInFrame, "NumChSetsInFrame"); NumChSetsInFrame++; Param_Info1(NumChSetsInFrame); Get_S1 (4, SegmentsInFrame, "SegmentsInFrame"); Param_Info1(1<>6; auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, ChSetHeaderSize+1); if (CRC) { Skip_XX(Element_Size-Element_Offset, "(Unknown)"); Element_Size=Element_Size_Save; return; } Element_Begin1("Channel Set"); BS_Begin(); int64u EndBS=Data_BS_Remain(); int8u ChSetLLChannel, BitResolution, FreqIndex, ReplacementSet; Skip_S2(10, "ChSetHeaderSize"); Get_S1 (4, ChSetLLChannel, "ChSetLLChannel"); ChSetLLChannel+=1; Skip_BS(ChSetLLChannel, "ResidualChEncode"); Get_S1 (5, BitResolution, "BitResolution"); BitResolution++; if (((int8s)HD_BitResolution_Real)<((int8s)BitResolution)) HD_BitResolution_Real=BitResolution; Skip_S1(5, "BitWidth"); Get_S1 (4, FreqIndex, "FreqIndex"); Param_Info1(DTS_HD_MaximumSampleRate[FreqIndex]); if (((int8s)HD_MaximumSampleRate_Real)<((int8s)FreqIndex)) HD_MaximumSampleRate_Real=FreqIndex; Skip_S1(2, "FsInterpolate"); Get_S1 (2, ReplacementSet, "ReplacementSet"); if (ReplacementSet) Skip_SB( "ActiveReplaceSet"); if (One2OneMapChannels2Speakers) { bool PrimaryChSet, DownmixCoeffCodeEmbedded, ChMaskEnabled; Get_SB ( PrimaryChSet, "PrimaryChSet"); Get_SB ( DownmixCoeffCodeEmbedded, "DownmixCoeffCodeEmbedded"); if (DownmixCoeffCodeEmbedded) Skip_SB( "DownmixEmbedded"); if (DownmixCoeffCodeEmbedded && PrimaryChSet) Skip_S1(3, "LLDownmixType"); Skip_SB( "HierChSet"); if (DownmixCoeffCodeEmbedded) { //TODO } else { Get_SB ( ChMaskEnabled, "ChMaskEnabled"); if (ChMaskEnabled) { Info_S4(Bits4ChMask, ChMask, "Mask"); Param_Info1(DTS_HD_SpeakerActivityMask(ChMask).c_str()); } } } Skip_BS((ChSetHeaderSize-1)*8-(EndBS-Data_BS_Remain()), "(Not parsed)"); BS_End(); Skip_B2 ( "CRC16SubHeader"); Param_Info1("OK"); Element_End0(); } size_t Count=(1<DTS_SamplingRate[sample_frequency]) { Count*=2; if (DTS_HD_MaximumSampleRate[HD_MaximumSampleRate_Real]>DTS_SamplingRate[sample_frequency]*2) Count*=2; } size_t NaviByteCount=(Count*Bits4SSize+7)/8+2; CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, NaviByteCount); if (CRC) { auto Buffer_Temp=Buffer+Buffer_Offset+Element_Offset+NaviByteCount; auto Buffer_End=Buffer+Buffer_Offset+(size_t)Element_Size; while (CRC && Buffer_Temp>8)^CRC_CCIT_Table[((uint8_t)CRC)^*Buffer_Temp++]; if (CRC) { Skip_XX(Element_Size-Element_Offset, "(Unknown)"); Element_Size=Element_Size_Save; return; } Count=(Buffer_Temp-(Buffer+Buffer_Offset+Element_Offset)-2)*8/Bits4SSize; } auto SegmentSize_Size=2+(Count*Bits4SSize+7)/8; if (Element_Size-Element_Offset base sampling rate } BS_End(); Skip_B2( "CRC16"); Param_Info1("OK"); Element_End0(); if (Element_Size-Element_Offset>2; if (HeaderSize<8) return; auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, HeaderSize-3); if (CRC) { Element_Info1("CRC NOK"); Extensions_Resynch(false); return; } FILLING_BEGIN(); Presence.set(Element_Code?presence_Extended_XXCH:presence_Core_XXCH); FILLING_END(); // Parsing Element_Begin1("Header"); vector ChSetFsizeXXCHs; int16u CoreSpkrActivityMask; int8u HeaderSizeXXCH, Bits4SpkrMaskXXCH, NumChSetsInXXCH; bool bCRCPresent4ChSetHeaderXXCH; auto Element_Offset_Start=Element_Offset; BS_Begin(); int64u EndBS=Data_BS_Remain(); Skip_S1(6, "HeaderSizeXXCH minus 1"); Get_SB ( bCRCPresent4ChSetHeaderXXCH, "CRCPresent4ChSetHeaderXXCH"); Get_S1 (5, Bits4SpkrMaskXXCH, "Bits4SpkrMaskXXCH minus 1"); Bits4SpkrMaskXXCH++; Get_S1 (2, NumChSetsInXXCH, "NumChSetsInXXCH minus 1"); for (int8u nChSet=0; nChSet<=NumChSetsInXXCH; nChSet++) { int16u ChSetFsizeXXCH; Get_S2 (14, ChSetFsizeXXCH, "ChSetFsizeXXCH minus 1"); if (bCRCPresent4ChSetHeaderXXCH && ChSetFsizeXXCH<=1) { BS_End(); Element_End0(); Skip_XX(Element_Size-Element_Offset, "(Unknown)"); return; } ChSetFsizeXXCHs.push_back(ChSetFsizeXXCH); } Get_S2 (Bits4SpkrMaskXXCH, CoreSpkrActivityMask, "CoreSpkrActivityMask"); auto RemainingBits=(HeaderSize-5)*8-(EndBS-Data_BS_Remain()); if (RemainingBits) { int8u Padding=(int8u)-1; if (RemainingBits<8) Peek_S1(RemainingBits, Padding); Skip_BS(RemainingBits, Padding?"(Unknown)":"Padding");; } BS_End(); Skip_B2 ( "CRC16Header"); Param_Info1("OK"); Element_End0(); int32u ChSetFsizeXXCHs_Total=0; for (auto ChSetFsizeXXCH : ChSetFsizeXXCHs) ChSetFsizeXXCHs_Total+=ChSetFsizeXXCH; if (Element_Size-Element_Offset>1; if (bCRCPresent4ChSetHeaderXXCH) { auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, XXCHChSetHeaderSize+1); if (CRC) { Skip_XX(Element_Size-Element_Offset, "(Unknown)"); return; } XXCHChSetHeaderSize-=2; } Element_Begin1("Channel Set"); Element_Begin1("Header"); BS_Begin(); Skip_S1(7, "XXCHChSetHeaderSize minus 1"); Skip_BS(XXCHChSetHeaderSize*8+1, "(Not parsed)"); BS_End(); if (bCRCPresent4ChSetHeaderXXCH) { Skip_B2 ( "CRC16HeaderChSet"); Param_Info1("OK"); XXCHChSetHeaderSize+=2; } Element_End0(); Skip_XX(ChSetFsizeXXCHs[i]-XXCHChSetHeaderSize, "(Not parsed)"); Element_End0(); } Extensions_Padding(); } //--------------------------------------------------------------------------- void File_Dts::XCh() { //Coherency check auto MaxSize=Element_Size-Element_Offset+3; if (MaxSize<95) return; int16u Begin; Peek_B2(Begin); int16u Size=Begin>>6; if (Size<95 || (Size!=MaxSize && Size-1!=MaxSize)) // Is last item and manage legacy bitstreams return; FILLING_BEGIN(); Presence.set(Element_Code?presence_Extended_XCh:presence_Core_XCh); FILLING_END(); //Parsing int16u XChFSIZE; int8u AMODE; BS_Begin(); Get_S2 (10, XChFSIZE, "Primary Frame Byte Size"); Get_S1 ( 4, AMODE, "Extension Channel Arrangement"); Skip_BS(Data_BS_Remain(), "(Not parsed)"); BS_End(); FILLING_BEGIN(); if (!Element_Code) Core_XCh_AMODE=AMODE; FILLING_END(); Extensions_Padding(); } //--------------------------------------------------------------------------- void File_Dts::XBR() { //Coherency check auto MaxSize=Element_Size-Element_Offset+3; if (MaxSize<8) return; int8u Begin; Peek_B1(Begin); int8u HeaderSize=Begin>>2; if (HeaderSize<8) return; auto CRC=Dts_CRC_CCIT_Compute(Buffer+Buffer_Offset+Element_Offset, HeaderSize-3); if (CRC) { Element_Info1("CRC NOK"); Extensions_Resynch(false); return; } FILLING_BEGIN(); Presence.set(presence_Extended_XBR); FILLING_END(); // Parsing Element_Begin1("Header"); vector ChSetFsizes; int8u NumChSetsInXBR; auto Element_Offset_Start=Element_Offset; BS_Begin(); int64u EndBS=Data_BS_Remain(); Skip_S1(6, "HeaderSizeXBR minus 1"); Get_S1 (2, NumChSetsInXBR, "NumChSetsInXBR minus 1"); for (int8u nChSet=0; nChSet<=NumChSetsInXBR; nChSet++) { int16u ChSetFsize; Get_S2 (14, ChSetFsize, "ChSetFsize minus 1"); ChSetFsizes.push_back(ChSetFsize); } int32u ChSetFsizes_Total=0; auto RemainingBits=(HeaderSize-5)*8-(EndBS-Data_BS_Remain()); if (RemainingBits) { int8u Padding=(int8u)-1; if (RemainingBits<8) Peek_S1(RemainingBits, Padding); Skip_BS(RemainingBits, Padding?"(Unknown)":"Padding");; } BS_End(); Skip_B2 ( "CRC16Header"); Param_Info1("OK"); Element_End0(); int32u ChSetFsizeXXCHs_Total=0; for (auto ChSetFsize : ChSetFsizes) ChSetFsizes_Total+=ChSetFsize; if (Element_Size-Element_OffsetBuffer_Size) return false; //Need more data bool isBlownUpHeader=(Buffer[Buffer_Offset+5]&0x20)?true:false; if (isBlownUpHeader) Size=((Buffer[Buffer_Offset+6]&0x01)<<19) | ( Buffer[Buffer_Offset+7] <<11) | ( Buffer[Buffer_Offset+8] << 3) | ( Buffer[Buffer_Offset+9] >> 5); else Size=((Buffer[Buffer_Offset+6]&0x1F)<<11) | ( Buffer[Buffer_Offset+7] << 3) | ( Buffer[Buffer_Offset+8] >> 5); Size++; Original_Size=Size; } else { if (Word) { if (Buffer_Offset+8>Buffer_Size) return false; //Need more data if (BigEndian) Size=((Buffer[Buffer_Offset+5]&0x03)<<12) | ( Buffer[Buffer_Offset+6] << 4) | ( Buffer[Buffer_Offset+7] >> 4); else Size=((Buffer[Buffer_Offset+4]&0x03)<<12) | ( Buffer[Buffer_Offset+7] << 4) | ( Buffer[Buffer_Offset+6] >> 4); Size++; Original_Size=Size; } else { if (Buffer_Offset+10>Buffer_Size) return false; //Need more data if (BigEndian) Size=((Buffer[Buffer_Offset+6]&0x03)<<12) | ( Buffer[Buffer_Offset+7] << 4) | ((Buffer[Buffer_Offset+8]&0x3C)>> 2); else Size=((Buffer[Buffer_Offset+7]&0x03)<<12) | ( Buffer[Buffer_Offset+6] << 4) | ((Buffer[Buffer_Offset+9]&0x3C)>> 2); Size++; Original_Size=Size*16/14; } } if (Buffer_Offset+Original_Size>Buffer_Size) return false; //Need more data if (!Word || !BigEndian) { Save_Buffer=Buffer; Save_Buffer_Offset=Buffer_Offset; Save_Buffer_Size=Buffer_Size; //Preparing new buffer if (Word) { int8u* Buffer_Little=new int8u[Size]; for (size_t Pos=0; Pos+1