text: /*  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.
   */
  
  //---------------------------------------------------------------------------
  #ifndef MediaInfo_File__AnalyzeMinimizeSizeH
  #define MediaInfo_File__AnalyzeMinimizeSizeH
  //---------------------------------------------------------------------------
  
  //***************************************************************************
  // Class File__Analyze
  //***************************************************************************
  
  class File__Analyze : public File__Base
  {
  public :
      //***************************************************************************
      // Constructor/Destructor
      //***************************************************************************
  
      File__Analyze();
      virtual ~File__Analyze();
  
      //***************************************************************************
      // Open
      //***************************************************************************
  
      void    Open_Buffer_Init        (                    int64u File_Size);
      void    Open_Buffer_Init        (File__Analyze* Sub);
      void    Open_Buffer_Init        (File__Analyze* Sub, int64u File_Size);
      void    Open_Buffer_OutOfBand   (                    const int8u* Buffer, size_t Buffer_Size) {File__Analyze::Buffer=Buffer; File__Analyze::Buffer_Size=Buffer_Size; Element_Offset=0; Element_Size=Buffer_Size; Read_Buffer_OutOfBand(); File__Analyze::Buffer=NULL; File__Analyze::Buffer_Size=0; Element_Offset=0; Element_Size=0;}
      void    Open_Buffer_OutOfBand   (File__Analyze* Sub                     , size_t Buffer_Size);
      void    Open_Buffer_OutOfBand   (File__Analyze* Sub) {Open_Buffer_OutOfBand(Sub, Element_Size-Element_Offset);};
      void    Open_Buffer_Continue    (                    const int8u* Buffer, size_t Buffer_Size);
      void    Open_Buffer_Continue    (File__Analyze* Sub, const int8u* Buffer, size_t Buffer_Size, bool IsNewPacket=true, float64 Ratio=1.0);
      void    Open_Buffer_Continue    (File__Analyze* Sub, size_t Buffer_Size) {if (Element_Offset+Buffer_Size<=Element_Size) Open_Buffer_Continue(Sub, Buffer+Buffer_Offset+(size_t)Element_Offset, Buffer_Size); Element_Offset+=Buffer_Size;}
      void    Open_Buffer_Continue    (File__Analyze* Sub) {if (Element_Offset<=Element_Size) Open_Buffer_Continue(Sub, Buffer+Buffer_Offset+(size_t)Element_Offset, (size_t)(Element_Size-Element_Offset)); Element_Offset=Element_Size;}
      void    Open_Buffer_Position_Set(int64u File_Offset);
      void    Open_Buffer_CheckFileModifications();
      #if MEDIAINFO_SEEK
      size_t  Open_Buffer_Seek        (size_t Method, int64u Value, int64u ID);
      #endif //MEDIAINFO_SEEK
      #if MEDIAINFO_ADVANCED2
      void    Open_Buffer_SegmentChange();
      #endif //MEDIAINFO_ADVANCED2
      void    Open_Buffer_Unsynch     ();
      void    Open_Buffer_Update      ();
      void    Open_Buffer_Update      (File__Analyze* Sub);
      void    Open_Buffer_Finalize    (bool NoBufferModification=false);
      void    Open_Buffer_Finalize    (File__Analyze* Sub);
  
      //***************************************************************************
      // In/Out (for parsers)
      //***************************************************************************
  
      //In
      std::string ParserName;
      #if MEDIAINFO_EVENTS
          size_t  StreamIDs_Size;
          int64u  StreamIDs[16];
          int8u   StreamIDs_Width[16];
          int8u   ParserIDs[16];
          void    Event_Prepare (struct MediaInfo_Event_Generic* Event);
      #endif //MEDIAINFO_EVENTS
      #if MEDIAINFO_DEMUX
          int8u   Demux_Level; //bit 0=frame, bit 1=container, bit 2=elementary (eg MPEG-TS), bit 3=ancillary (e.g. DTVCC), default with frame set
          bool    Demux_random_access;
          bool    Demux_UnpacketizeContainer;
          bool    Demux_IntermediateItemFound;
          size_t  Demux_Offset;
          int64u  Demux_TotalBytes;
          File__Analyze* Demux_CurrentParser;
      #endif //MEDIAINFO_DEMUX
      Ztring  File_Name_WithoutDemux;
      bool   PTS_DTS_Needed;
      enum ts_type
      {
          TS_NONE=0,
          TS_PTS=1,
          TS_DTS=2,
          TS_ALL=TS_PTS|TS_DTS,
      };
      void   TS_Clear(ts_type Type=TS_ALL);
      void   TS_Set(int64s Ticks, ts_type Type=TS_ALL);
      void   TS_Set(File__Analyze* Parser, ts_type Type=TS_ALL);
      void   TS_Add(int64s Ticks, ts_type Type=TS_ALL);
      void   TS_Ajust(int64s Ticks);
      int64s Frequency_c; //Frequency of the timestamp of the container (e.g. 90000 for MPEG-PS)
      int64s Frequency_b; //Frequency of the timestamp of the bitstream (e.g. 48000 for AC-3)
      #if MEDIAINFO_ADVANCED2
      static const int64s NoTs=0x8000000000000000LL;
      int64s PTSb; //In 1/Frequency_b if sub, in 1/(Frequency_c*Frequency_b) if in a container
      int64s DTSb; //In 1/Frequency_b if sub, in 1/(Frequency_c*Frequency_b) if in a container
      #endif //MEDIAINFO_ADVANCED2
      struct frame_info
      {
          int64u Buffer_Offset_End;
          int64u PCR; //In nanoseconds
          int64u PTS; //In nanoseconds
          int64u DTS; //In nanoseconds
          int64u DUR; //In nanoseconds
          #if MEDIAINFO_ADVANCED2
          int64s PTSc; //In 1/Frequency_c
          int64s DTSc; //In 1/Frequency_c
          int64u Frame_Count_AfterLastTimeStamp;
          #endif //MEDIAINFO_ADVANCED2
  
          frame_info()
          {
              Buffer_Offset_End=(int64u)-1;
              PCR=(int64u)-1;
              PTS=(int64u)-1;
              DTS=(int64u)-1;
              DUR=(int64u)-1;
              #if MEDIAINFO_ADVANCED2
              PTSc=NoTs;
              DTSc=NoTs;
              Frame_Count_AfterLastTimeStamp=0;
              #endif //MEDIAINFO_ADVANCED2
          }
      };
      frame_info FrameInfo;
      frame_info FrameInfo_Previous;
      frame_info FrameInfo_Next;
      std::vector<int64u> Offsets_Stream;
      std::vector<int64u> Offsets_Buffer;
      size_t              Offsets_Pos;
      int8u*              OriginalBuffer;
      size_t              OriginalBuffer_Size;
      size_t              OriginalBuffer_Capacity;
      #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
          struct servicedescriptor
          {
              string language;
          };
          typedef std::map<int8u, servicedescriptor> servicedescriptors608;
          typedef std::map<int8u, servicedescriptor> servicedescriptors708;
          struct servicedescriptors
          {
              #if defined(MEDIAINFO_EIA608_YES)
                  std::map<int8u, servicedescriptor> ServiceDescriptors608;
              #endif
              #if defined(MEDIAINFO_EIA708_YES)
                  std::map<int8u, servicedescriptor> ServiceDescriptors708;
              #endif
          };
          servicedescriptors* ServiceDescriptors;
      #endif
      #if defined(MEDIAINFO_TELETEXT_YES)
          struct teletext
          {
              std::map<std::string, Ztring>           Infos;
              stream_t                                StreamKind;
              size_t                                  StreamPos;
  
              teletext()
                  : StreamKind(Stream_Max)
                  , StreamPos((size_t)-1)
              {}
          };
          std::map<int16u, teletext>*                 Teletexts; //Key is teletext_magazine_number
      #endif
  
      //Out
      int64u PTS_Begin;                  //In nanoseconds
      #if MEDIAINFO_ADVANCED2
      int64u PTS_Begin_Segment;          //In nanoseconds
      #endif //MEDIAINFO_ADVANCED2
      int64u PTS_End;                    //In nanoseconds
      int64u DTS_Begin;                  //In nanoseconds
      int64u DTS_End;                    //In nanoseconds
      int64u Frame_Count;
      int64u Frame_Count_Previous;
      int64u Frame_Count_InThisBlock;
      int64u Field_Count;
      int64u Field_Count_Previous;
      int64u Field_Count_InThisBlock;
      int64u Frame_Count_NotParsedIncluded;
      int64u FrameNumber_PresentationOrder;
      bool   Synched;                    //Data is synched
      bool   UnSynched_IsNotJunk;        //Data is actually synched
      bool   MustExtendParsingDuration;  //Data has some substreams difficult to detect (e.g. captions), must wait a bit before final filling
  
  protected :
      //***************************************************************************
      // Streams management
      //***************************************************************************
  
      virtual void Streams_Accept()                                               {};
      virtual void Streams_Fill()                                                 {};
      virtual void Streams_Update()                                               {};
      virtual void Streams_Finish()                                               {};
  
      //***************************************************************************
      // Synchro
      //***************************************************************************
  
      virtual bool Synchronize()    {Synched=true; return true;}; //Look for the synchro
      virtual bool Synched_Test()   {return true;}; //Test is synchro is OK
      virtual void Synched_Init()   {}; //When synched, we can Init data
      bool Synchro_Manage();
      bool Synchro_Manage_Test();
  
      //***************************************************************************
      // Buffer
      //***************************************************************************
  
      //Buffer
      virtual void Read_Buffer_Init ()          {}; //Temp, should be in File__Base caller
      virtual void Read_Buffer_OutOfBand ()     {Open_Buffer_Continue(Buffer, Buffer_Size);} //Temp, should be in File__Base caller
      virtual void Read_Buffer_Continue ()      {}; //Temp, should be in File__Base caller
      virtual void Read_Buffer_CheckFileModifications() {} //Temp, should be in File__Base caller
      virtual void Read_Buffer_AfterParsing ()  {}; //Temp, should be in File__Base caller
      #if MEDIAINFO_SEEK
      virtual size_t Read_Buffer_Seek (size_t, int64u, int64u); //Temp, should be in File__Base caller
      size_t Read_Buffer_Seek_OneFramePerFile (size_t, int64u, int64u);
      #endif //MEDIAINFO_SEEK
      #if MEDIAINFO_ADVANCED2
      virtual void Read_Buffer_SegmentChange () {}; //Temp, should be in File__Base caller
      #endif //MEDIAINFO_ADVANCED2
      virtual void Read_Buffer_Unsynched ()     {}; //Temp, should be in File__Base caller
      void Read_Buffer_Unsynched_OneFramePerFile ();
      virtual void Read_Buffer_Finalize ()      {}; //Temp, should be in File__Base caller
      bool Buffer_Parse();
  
      //***************************************************************************
      // BitStream init
      //***************************************************************************
  
      void BS_Begin();
      void BS_Begin_LE(); //Little Endian version
      void BS_End();
      void BS_End_LE(); //Little Endian version
  
      //***************************************************************************
      // File Header
      //***************************************************************************
  
      //File Header - Management
      bool FileHeader_Manage ();
  
      //File Header - Begin
      virtual bool FileHeader_Begin ()                                            {return true;};
  
      //File Header - Parse
      virtual void FileHeader_Parse ()                                            {Element_DoNotShow();};
  
      //***************************************************************************
      // Header
      //***************************************************************************
  
      //Header - Management
      bool Header_Manage ();
  
      //Header - Begin
      virtual bool Header_Begin ()                                                {return true;};
  
      //Header - Parse
      virtual void Header_Parse ();
  
      //Header - Info
      void Header_Fill_Code (int64u Code);
      inline void Header_Fill_Code (int64u Code, const Ztring &) {Header_Fill_Code(Code);};
      #define Header_Fill_Code2(A,B) Header_Fill_Code(A)
      void Header_Fill_Size (int64u Size);
  
      //***************************************************************************
      // Data
      //***************************************************************************
  
      //Header - Management
      bool Data_Manage ();
  
      //Data - Parse
      virtual void Data_Parse ()                                                  {};
  
      //Data - Info
      inline void Data_Info (const Ztring &)                                      {};
      inline void Data_Info_From_Milliseconds (int64u)                            {}
  
      //Data - Get info
      size_t Data_Remain ()                                                       {return (size_t)(Element_Size-(Element_Offset+BS->Offset_Get()));};
      size_t Data_BS_Remain ()                                                    {return (size_t)BS->Remain();};
  
      //Data - Detect EOF
      virtual void Detect_EOF ()                                                  {};
      bool EOF_AlreadyDetected;
  
      //Data - Helpers
      void Data_Accept        (const char*)                                       {Accept();}
      void Data_Accept        ()                                                  {Accept();}
      void Data_Reject        (const char*)                                       {Reject();}
      void Data_Reject        ()                                                  {Reject();}
      void Data_Finish        (const char*)                                       {ForceFinish();}
      void Data_Finish        ()                                                  {ForceFinish();}
      void Data_GoTo          (int64u GoTo_, const char*)                         {GoTo(GoTo_);}
      void Data_GoTo          (int64u GoTo_)                                      {GoTo(GoTo_);}
      void Data_GoToFromEnd   (int64u GoToFromEnd_, const char*)                  {GoToFromEnd(GoToFromEnd_);}
      void Data_GoToFromEnd   (int64u GoToFromEnd_)                               {GoToFromEnd(GoToFromEnd_);}
  
      //***************************************************************************
      // Elements
      //***************************************************************************
  
      //Elements - Begin
      void Element_Begin ();
      #define Element_Begin0() Element_Begin()
      #define Element_Begin1(_NAME) Element_Begin()
      #define Element_Trace_Begin0()
      #define Element_Trace_Begin1(_NAME)
  
      //Elements - Name
      #define Element_Name(_A)
  
      //Elements - Info
      #define Element_Info1(_A)
      #define Element_Info2(_A,_B)
      #define Element_Info3(_A,_B,_C)
      #define Element_Info1C(_CONDITION,_A)
      #define Element_Info_From_Milliseconds(_A)
      #define Element_Parser(_A) {}
      #define Element_Error(_A) {}
      #define Param_Error(_A) {}
  
      //Elements - End
      inline void Element_End () {Element_End_Common_Flush();}
      #define Element_End0() Element_End()
      #define Element_End1(_NAME) Element_End()
      #define Element_Trace_End0()
      #define Element_Trace_End1(_NAME)
  
      //Elements - Preparation of element from external app
      void Element_Prepare (int64u Size);
  
  protected :
      //Element - Common
      void   Element_End_Common_Flush();
  public :
  
      //***************************************************************************
      // Param
      //***************************************************************************
  
      //Param - Main
      inline void noop() {}
      #define Param1(_A) noop()
      #define Param2(_A,_B) noop()
      #define Param3(_A,_B,_C) noop()
  
      //Param - Info
      #define Param_Info1(_A) noop()
      #define Param_Info2(_A,_B) noop()
      #define Param_Info3(_A,_B,_C) noop()
      #define Param_Info1C(_CONDITION,_A) noop()
      #define Param_Info2C(_CONDITION,_A,_B) noop()
      #define Param_Info3C(_CONDITION,_A,_B,_C) noop()
      #define Param_Info_From_Milliseconds(A) noop()
  
      //***************************************************************************
      // Information
      //***************************************************************************
  
      inline void Info (const std::string&, size_t =0) {}
  
      //***************************************************************************
      // Big Endian (Integer, Float, Fixed-Point)
      //***************************************************************************
  
      void Get_B1_   (int8u   &Info);
      void Get_B2_   (int16u  &Info);
      void Get_B3_   (int32u  &Info);
      void Get_B4_   (int32u  &Info);
      void Get_B5_   (int64u  &Info);
      void Get_B6_   (int64u  &Info);
      void Get_B7_   (int64u  &Info);
      void Get_B8_   (int64u  &Info);
      void Get_B16_  (int128u &Info);
      void Get_BF2_  (float32 &Info);
      void Get_BF4_  (float32 &Info);
      void Get_BF8_  (float64 &Info);
      void Get_BF10_ (float80 &Info);
      void Get_BFP4_ (int8u  Bits, float32 &Info);
      #define Get_B1(Info, Name) Get_B1_(Info)
      #define Get_B2(Info, Name) Get_B2_(Info)
      #define Get_B3(Info, Name) Get_B3_(Info)
      #define Get_B4(Info, Name) Get_B4_(Info)
      #define Get_B5(Info, Name) Get_B5_(Info)
      #define Get_B6(Info, Name) Get_B6_(Info)
      #define Get_B7(Info, Name) Get_B7_(Info)
      #define Get_B8(Info, Name) Get_B8_(Info)
      #define Get_B16(Info, Name) Get_B16_(Info)
      #define Get_BF2(Info, Name) Get_BF2_(Info)
      #define Get_BF4(Info, Name) Get_BF4_(Info)
      #define Get_BF8(Info, Name) Get_BF8_(Info)
      #define Get_BF10(Info, Name) Get_BF10_(Info)
      #define Get_BFP4(Bits, Info, Name) Get_BFP4_(Bits, Info)
      void Peek_B1  (int8u   &Info);
      void Peek_B2  (int16u  &Info);
      void Peek_B3  (int32u  &Info);
      void Peek_B4  (int32u  &Info);
      void Peek_B5  (int64u  &Info);
      void Peek_B6  (int64u  &Info);
      void Peek_B7  (int64u  &Info);
      void Peek_B8  (int64u  &Info);
      void Peek_B16 (int128u &Info);
      void Peek_BF4 (float32 &Info);
      void Peek_BF8 (float64 &Info);
      void Peek_BF10(float64 &Info);
      void Peek_BFP4(int8u  Bits, float64 &Info);
      #define Skip_B1(Name) Element_Offset++
      #define Skip_B2(Name) Element_Offset+=2
      #define Skip_B3(Name) Element_Offset+=3
      #define Skip_B4(Name) Element_Offset+=4
      #define Skip_B5(Name) Element_Offset+=5
      #define Skip_B6(Name) Element_Offset+=6
      #define Skip_B7(Name) Element_Offset+=7
      #define Skip_B8(Name) Element_Offset+=8
      #define Skip_BF4(Name) Element_Offset+=4
      #define Skip_BF8(Name) Element_Offset+=8
      #define Skip_B16(Name) Element_Offset+=16
      #define Skip_BFP4(Size, Name) Element_Offset+=4
      #define Skip_Hexa(Bytes, Name) Element_Offset+=Bytes
      #define Info_B1(_INFO, _NAME)   Element_Offset++
      #define Info_B2(_INFO, _NAME)   Element_Offset+=2
      #define Info_B3(_INFO, _NAME)   Element_Offset+=3
      #define Info_B4(_INFO, _NAME)   Element_Offset+=4
      #define Info_B5(_INFO, _NAME)   Element_Offset+=5
      #define Info_B6(_INFO, _NAME)   Element_Offset+=6
      #define Info_B7(_INFO, _NAME)   Element_Offset+=7
      #define Info_B8(_INFO, _NAME)   Element_Offset+=8
      #define Info_B16(_INFO, _NAME)  Element_Offset+=16
      #define Info_BF4(_INFO, _NAME)  Element_Offset+=4
      #define Info_BF8(_INFO, _NAME)  Element_Offset+=8
      #define Info_BF10(_INFO, _NAME) Element_Offset+=10
      #define Info_BFP4(_BITS, _INFO, _NAME) Element_Offset+=4
  
      //***************************************************************************
      // Little Endian
      //***************************************************************************
  
      void Get_L1_   (int8u   &Info);
      void Get_L2_   (int16u  &Info);
      void Get_L3_   (int32u  &Info);
      void Get_L4_   (int32u  &Info);
      void Get_L5_   (int64u  &Info);
      void Get_L6_   (int64u  &Info);
      void Get_L7_   (int64u  &Info);
      void Get_L8_   (int64u  &Info);
      void Get_L16_  (int128u &Info);
      void Get_LF4_  (float32 &Info);
      void Get_LF8_  (float64 &Info);
      void Get_LF10_ (float80 &Info);
      void Get_LFP4_ (int8u  Bits, float32 &Info);
      #define Get_L1(Info, Name) Get_L1_(Info)
      #define Get_L2(Info, Name) Get_L2_(Info)
      #define Get_L3(Info, Name) Get_L3_(Info)
      #define Get_L4(Info, Name) Get_L4_(Info)
      #define Get_L5(Info, Name) Get_L5_(Info)
      #define Get_L6(Info, Name) Get_L6_(Info)
      #define Get_L7(Info, Name) Get_L7_(Info)
      #define Get_L8(Info, Name) Get_L8_(Info)
      #define Get_L16(Info, Name) Get_L16_(Info)
      #define Get_LF4(Info, Name) Get_LF4_(Info)
      #define Get_LF8(Info, Name) Get_LF8_(Info)
      #define Get_LF10(Info, Name) Get_LF10_(Info)
      #define Get_LFP4(Bits, Info, Name) Get_LFP4_(Bits, Info)
      void Peek_L1  (int8u   &Info);
      void Peek_L2  (int16u  &Info);
      void Peek_L3  (int32u  &Info);
      void Peek_L4  (int32u  &Info);
      void Peek_L5  (int64u  &Info);
      void Peek_L6  (int64u  &Info);
      void Peek_L7  (int64u  &Info);
      void Peek_L8  (int64u  &Info);
      void Peek_L16 (int128u &Info);
      void Peek_LF4 (float32 &Info);
      void Peek_LF8 (float64 &Info);
      void Peek_LF10(float64 &Info);
      void Peek_LFP4(int8u  Bits, float64 &Info);
      #define Skip_L1(Name) Element_Offset++
      #define Skip_L2(Name) Element_Offset+=2
      #define Skip_L3(Name) Element_Offset+=3
      #define Skip_L4(Name) Element_Offset+=4
      #define Skip_L5(Name) Element_Offset+=5
      #define Skip_L6(Name) Element_Offset+=6
      #define Skip_L7(Name) Element_Offset+=7
      #define Skip_L8(Name) Element_Offset+=8
      #define Skip_LF4(Name) Element_Offset+=4
      #define Skip_LF8(Name) Element_Offset+=8
      #define Skip_L16(Name) Element_Offset+=16
      #define Skip_LFP4(Size, Name) Element_Offset+=4
      #define Info_L1(_INFO, _NAME)   Element_Offset++
      #define Info_L2(_INFO, _NAME)   Element_Offset+=2
      #define Info_L3(_INFO, _NAME)   Element_Offset+=3
      #define Info_L4(_INFO, _NAME)   Element_Offset+=4
      #define Info_L5(_INFO, _NAME)   Element_Offset+=5
      #define Info_L6(_INFO, _NAME)   Element_Offset+=6
      #define Info_L7(_INFO, _NAME)   Element_Offset+=7
      #define Info_L8(_INFO, _NAME)   Element_Offset+=8
      #define Info_L16(_INFO, _NAME)  Element_Offset+=16
      #define Info_LF4(_INFO, _NAME)  Element_Offset+=4
      #define Info_LF8(_INFO, _NAME)  Element_Offset+=8
      #define Info_LF10(_INFO, _NAME) Element_Offset+=10
      #define Info_LFP4(_LITS, _INFO, _NAME) Element_Offset+=4
  
      //***************************************************************************
      // Little and Big Endian together
      //***************************************************************************
  
      void Get_D1_   (int8u   &Info);
      void Get_D2_   (int16u  &Info);
      void Get_D3_   (int32u  &Info);
      void Get_D4_   (int32u  &Info);
      void Get_D5_   (int64u  &Info);
      void Get_D6_   (int64u  &Info);
      void Get_D7_   (int64u  &Info);
      void Get_D8_   (int64u  &Info);
      void Get_D16_  (int128u &Info);
      void Get_DF4_  (float32 &Info);
      void Get_DF8_  (float64 &Info);
      void Get_DF10_ (float80 &Info);
      void Get_DFP4_ (int8u  Bits, float32 &Info);
      #define Get_D1(Info, Name) Get_D1_(Info)
      #define Get_D2(Info, Name) Get_D2_(Info)
      #define Get_D3(Info, Name) Get_D3_(Info)
      #define Get_D4(Info, Name) Get_D4_(Info)
      #define Get_D5(Info, Name) Get_D5_(Info)
      #define Get_D6(Info, Name) Get_D6_(Info)
      #define Get_D7(Info, Name) Get_D7_(Info)
      #define Get_D8(Info, Name) Get_D8_(Info)
      #define Get_D16(Info, Name) Get_D16_(Info)
      #define Get_DF4(Info, Name) Get_DF4_(Info)
      #define Get_DF8(Info, Name) Get_DF8_(Info)
      #define Get_DF10(Info, Name) Get_DF10_(Info)
      #define Get_DFP4(Bits, Info, Name) Get_DFP4_(Bits, Info)
      void Peek_D1  (int8u   &Info);
      void Peek_D2  (int16u  &Info);
      void Peek_D3  (int32u  &Info);
      void Peek_D4  (int32u  &Info);
      void Peek_D5  (int64u  &Info);
      void Peek_D6  (int64u  &Info);
      void Peek_D7  (int64u  &Info);
      void Peek_D8  (int64u  &Info);
      void Peek_D16 (int128u &Info);
      void Peek_DF4 (float32 &Info);
      void Peek_DF8 (float64 &Info);
      void Peek_DF10(float64 &Info);
      void Peek_DFP4(int8u  Bits, float64 &Info);
      #define Skip_D1(Name) Element_Offset++
      #define Skip_D2(Name) Element_Offset+=2
      #define Skip_D3(Name) Element_Offset+=3
      #define Skip_D4(Name) Element_Offset+=4
      #define Skip_D5(Name) Element_Offset+=5
      #define Skip_D6(Name) Element_Offset+=6
      #define Skip_D7(Name) Element_Offset+=7
      #define Skip_D8(Name) Element_Offset+=8
      #define Skip_DF4(Name) Element_Offset+=4
      #define Skip_DF8(Name) Element_Offset+=8
      #define Skip_D16(Name) Element_Offset+=16
      #define Skip_DFP4(Size, Name) Element_Offset+=4
      #define Info_D1(_INFO, _NAME)   Element_Offset++
      #define Info_D2(_INFO, _NAME)   Element_Offset+=2
      #define Info_D3(_INFO, _NAME)   Element_Offset+=3
      #define Info_D4(_INFO, _NAME)   Element_Offset+=4
      #define Info_D5(_INFO, _NAME)   Element_Offset+=5
      #define Info_D6(_INFO, _NAME)   Element_Offset+=6
      #define Info_D7(_INFO, _NAME)   Element_Offset+=7
      #define Info_D8(_INFO, _NAME)   Element_Offset+=8
      #define Info_D16(_INFO, _NAME)  Element_Offset+=16
      #define Info_DF4(_INFO, _NAME)  Element_Offset+=4
      #define Info_DF8(_INFO, _NAME)  Element_Offset+=8
      #define Info_DF10(_INFO, _NAME) Element_Offset+=10
      #define Info_DFP4(_DITS, _INFO, _NAME) Element_Offset+=4
  
      //***************************************************************************
      // GUID
      //***************************************************************************
  
      void Get_GUID (int128u &Info);
      inline void Get_GUID (int128u &Info, const char*) {Get_GUID(Info);}
      void Peek_GUID(int128u &Info);
      inline void Skip_GUID(               const char*) {if (Element_Offset+16>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=16;}
      #define Info_GUID(_INFO, _NAME) int128u _INFO; Get_GUID(_INFO, _NAME)
  
      //***************************************************************************
      // UUID
      //***************************************************************************
  
      inline void Get_UUID (int128u &Info) {Get_B16_(Info);}
      inline void Get_UUID (int128u &Info, const char*) {Get_B16_(Info);}
      inline void Peek_UUID(int128u &Info) {Peek_B16(Info);}
      inline void Skip_UUID(               const char*) {if (Element_Offset+16>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=16;}
      #define Info_UUID(_INFO, _NAME) int128u _INFO; Get_UUID(_INFO, _NAME)
  
      //***************************************************************************
      // EBML
      //***************************************************************************
  
      void Get_EB (int64u &Info);
      void Get_ES (int64s &Info);
      inline void Get_EB (int64u &Info, const char*) {Get_EB(Info);}
      inline void Get_ES (int64s &Info, const char*) {Get_ES(Info);}
      void Skip_EB();
      void Skip_ES();
      inline void Skip_EB(              const char*) {Skip_EB();}
      inline void Skip_ES(              const char*) {Skip_ES();}
      #define Info_EB(_INFO, _NAME) int64u _INFO; Get_EB(_INFO, _NAME)
      #define Info_ES(_INFO, _NAME) int64s _INFO; Get_ES(_INFO, _NAME)
  
      //***************************************************************************
      // Variable Size Value
      //***************************************************************************
  
      void Get_VS (int64u &Info);
      inline void Get_VS (int64u &Info, const char*) {Get_VS(Info);}
      void Skip_VS();
      inline void Skip_VS(              const char*) {Skip_VS();}
      #define Info_VS(_INFO, _NAME) int64u _INFO; Get_VS(_INFO, _NAME)
  
      //***************************************************************************
      // Exp-Golomb
      //***************************************************************************
  
      void Get_UE (int32u &Info);
      void Get_SE (int32s &Info);
      inline void Get_UE (int32u &Info, const char*) {Get_UE(Info);}
      inline void Get_SE (int32s &Info, const char*) {Get_SE(Info);}
      void Skip_UE();
      inline void Skip_SE() {Skip_UE();}
      inline void Skip_UE(              const char*) {Skip_UE();}
      inline void Skip_SE(              const char*) {Skip_SE();}
      #define Info_UE(_INFO, _NAME) int32u _INFO; Get_UE(_INFO, _NAME)
      #define Info_SE(_INFO, _NAME) int32s _INFO; Get_SE(_INFO, _NAME)
  
      //***************************************************************************
      // Interleaved Exp-Golomb
      //***************************************************************************
  
      void Get_UI (int32u &Info);
      void Get_SI (int32s &Info);
      inline void Get_UI (int32u &Info, const char*) {Get_UI(Info);}
      inline void Get_SI (int32s &Info, const char*) {Get_SI(Info);}
      void Skip_UI();
      void Skip_SI();
      inline void Skip_UI(              const char*) {Skip_UI();}
      inline void Skip_SI(              const char*) {Skip_SI();}
      #define Info_UI(_INFO, _NAME) int32u _INFO; Get_UI(_INFO, _NAME)
      #define Info_SI(_INFO, _NAME) int32s _INFO; Get_SI(_INFO, _NAME)
  
      //***************************************************************************
      // Variable Length Code
      //***************************************************************************
  
      struct vlc
      {
          int32u  value;
          int8u   bit_increment;
          int8s   mapped_to1;
          int8s   mapped_to2;
          int8s   mapped_to3;
      };
      struct vlc_fast
      {
          int8u*      Array;
          int8u*      BitsToSkip;
          const vlc*  Vlc;
          int8u       Size;
      };
      #define VLC_END \
          {(int32u)-1, (int8u)-1, 0, 0, 0}
      static void Get_VL_Prepare(vlc_fast &Vlc);
      void Get_VL_ (const vlc Vlc[], size_t &Info);
      void Get_VL_ (const vlc_fast &Vlc, size_t &Info);
      #define Get_VL(Vlc, Info, Name) Get_VL_(Vlc, Info);
      void Skip_VL_(const vlc Vlc[]);
      void Skip_VL_(const vlc_fast &Vlc);
      #define Skip_VL(Vlc, Name) Skip_VL_(Vlc);
      #define Info_VL(Vlc, Info, Name) Skip_VL_(Vlc)
  
      //***************************************************************************
      // Characters
      //***************************************************************************
  
      void Get_C1 (int8u  &Info);
      void Get_C2 (int16u &Info);
      void Get_C3 (int32u &Info);
      void Get_C4 (int32u &Info);
      void Get_C5 (int64u &Info);
      void Get_C6 (int64u &Info);
      void Get_C7 (int64u &Info);
      void Get_C8 (int64u &Info);
      inline void Get_C1 (int8u  &Info, const char*) {Get_C1(Info);}
      inline void Get_C2 (int16u &Info, const char*) {Get_C2(Info);}
      inline void Get_C3 (int32u &Info, const char*) {Get_C3(Info);}
      inline void Get_C4 (int32u &Info, const char*) {Get_C4(Info);}
      inline void Get_C5 (int64u &Info, const char*) {Get_C5(Info);}
      inline void Get_C6 (int64u &Info, const char*) {Get_C6(Info);}
      inline void Get_C7 (int64u &Info, const char*) {Get_C7(Info);}
      inline void Get_C8 (int64u &Info, const char*) {Get_C8(Info);}
      inline void Skip_C1(              const char*) {if (Element_Offset+1>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=1;}
      inline void Skip_C2(              const char*) {if (Element_Offset+2>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=2;}
      inline void Skip_C3(              const char*) {if (Element_Offset+3>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=3;}
      inline void Skip_C4(              const char*) {if (Element_Offset+4>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=4;}
      inline void Skip_C5(              const char*) {if (Element_Offset+5>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=5;}
      inline void Skip_C6(              const char*) {if (Element_Offset+6>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=6;}
      inline void Skip_C7(              const char*) {if (Element_Offset+7>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=7;}
      inline void Skip_C8(              const char*) {if (Element_Offset+8>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=8;}
      #define Info_C1(_INFO, _NAME) int8u  _INFO; Get_C1(_INFO, _NAME)
      #define Info_C2(_INFO, _NAME) int16u _INFO; Get_C2(_INFO, _NAME)
      #define Info_C3(_INFO, _NAME) int32u _INFO; Get_C3(_INFO, _NAME)
      #define Info_C4(_INFO, _NAME) int32u _INFO; Get_C4(_INFO, _NAME)
      #define Info_C5(_INFO, _NAME) int64u _INFO; Get_C5(_INFO, _NAME)
      #define Info_C6(_INFO, _NAME) int64u _INFO; Get_C6(_INFO, _NAME)
      #define Info_C7(_INFO, _NAME) int64u _INFO; Get_C7(_INFO, _NAME)
      #define Info_C8(_INFO, _NAME) int64u _INFO; Get_C8(_INFO, _NAME)
  
      //***************************************************************************
      // Text
      //***************************************************************************
  
      void Get_Local  (int64u Bytes, Ztring      &Info);
      void Get_ISO_6937_2 (int64u Bytes, Ztring  &Info);
      void Get_ISO_8859_1 (int64u Bytes, Ztring  &Info);
      void Get_ISO_8859_2 (int64u Bytes, Ztring  &Info);
      void Get_ISO_8859_5 (int64u Bytes, Ztring  &Info);
      void Get_MacRoman   (int64u Bytes, Ztring  &Info);
      void Get_String (int64u Bytes, std::string &Info);
      void Get_UTF8   (int64u Bytes, Ztring      &Info);
      void Get_UTF16  (int64u Bytes, Ztring      &Info);
      void Get_UTF16B (int64u Bytes, Ztring      &Info);
      void Get_UTF16L (int64u Bytes, Ztring      &Info);
      inline void Get_Local  (int64u Bytes, Ztring      &Info, const char*) {Get_Local(Bytes, Info);}
      inline void Get_ISO_6937_2 (int64u Bytes, Ztring  &Info, const char*) {Get_ISO_6937_2(Bytes, Info);}
      inline void Get_ISO_8859_1 (int64u Bytes, Ztring  &Info, const char*) {Get_ISO_8859_1(Bytes, Info);}
      inline void Get_ISO_8859_2 (int64u Bytes, Ztring  &Info, const char*) {Get_ISO_8859_2(Bytes, Info);}
      inline void Get_ISO_8859_5 (int64u Bytes, Ztring  &Info, const char*) {Get_ISO_8859_5(Bytes, Info);}
      inline void Get_MacRoman   (int64u Bytes, Ztring  &Info, const char*) {Get_MacRoman(Bytes, Info);}
      inline void Get_String (int64u Bytes, std::string &Info, const char*) {Get_String(Bytes, Info);}
      inline void Get_UTF8   (int64u Bytes, Ztring      &Info, const char*) {Get_UTF8(Bytes, Info);}
      inline void Get_UTF16  (int64u Bytes, Ztring      &Info, const char*) {Get_UTF16(Bytes, Info);}
      inline void Get_UTF16B (int64u Bytes, Ztring      &Info, const char*) {Get_UTF16B(Bytes, Info);}
      inline void Get_UTF16L (int64u Bytes, Ztring      &Info, const char*) {Get_UTF16L(Bytes, Info);}
      void Peek_Local (int64u Bytes, Ztring      &Info);
      void Peek_String(int64u Bytes, std::string &Info);
      void Skip_Local (int64u Bytes,                    const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      void Skip_ISO_6937_2(int64u Bytes,                const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      void Skip_String(int64u Bytes,                    const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      void Skip_UTF8  (int64u Bytes,                    const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      void Skip_UTF16B(int64u Bytes,                    const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      void Skip_UTF16L(int64u Bytes,                    const char*) {if (Element_Offset+Bytes>Element_Size) {Trusted_IsNot(); return;} Element_Offset+=(size_t)Bytes;}
      #define Info_Local(_BYTES, _INFO, _NAME)  Ztring _INFO; Get_Local (_BYTES, _INFO, _NAME)
      #define Info_ISO_6937_2(_BYTES, _INFO, _NAME)  Ztring _INFO; Info_ISO_6937_2(_BYTES, _INFO, _NAME)
      #define Info_UTF8(_BYTES, _INFO, _NAME)   Ztring _INFO; Get_UTF8  (_BYTES, _INFO, _NAME)
      #define Info_UTF16B(_BYTES, _INFO, _NAME) Ztring _INFO; Get_UTF16B(_BYTES, _INFO, _NAME)
      #define Info_UTF16L(_BYTES, _INFO, _NAME) Ztring _INFO; Get_UTF16L(_BYTES, _INFO, _NAME)
  
      //***************************************************************************
      // Pascal strings
      //***************************************************************************
  
      void Get_PA (std::string &Info);
      inline void Get_PA (std::string &Info, const char*) {Get_PA(Info);}
      void Peek_PA(std::string &Info);
      void Skip_PA();
      inline void Skip_PA(                   const char*) {Skip_PA();}
      #define Info_PA(_INFO, _NAME) Ztring _INFO; Get_PA (_INFO, _NAME)
  
      //***************************************************************************
      // Others, specialized
      //***************************************************************************
  
      #if defined(MEDIAINFO_HEVC_YES) || defined(MEDIAINFO_MPEG4_YES)
      void Get_MasteringDisplayColorVolume(Ztring &MasteringDisplay_ColorPrimaries, Ztring &MasteringDisplay_Luminance);
      #endif
      #if defined(MEDIAINFO_HEVC_YES) || defined(MEDIAINFO_MPEG4_YES) || defined(MEDIAINFO_MATROSKA_YES)
      struct mastering_metadata_2086
      {
          int16u Primaries[8];
          int32u Luminance[2];
      };
      void Get_MasteringDisplayColorVolume(Ztring &MasteringDisplay_ColorPrimaries, Ztring &MasteringDisplay_Luminance, mastering_metadata_2086 &Meta);
      #endif
  
      //***************************************************************************
      // Unknown
      //***************************************************************************
  
      void Skip_XX(int64u Bytes);
      inline void Skip_XX(int64u Bytes, const char*) {Skip_XX(Bytes);}
  
      //***************************************************************************
      // Flags
      //***************************************************************************
  
      void Get_Flags_ (int64u Flags, size_t Order, bool  &Info);
      void Get_FlagsM_ (int64u ValueToPut, int8u &Info); //Multiple
      #define Get_Flags(_FLAGS, _ORDER, _INFO, _NAME) Get_Flags_(_FLAGS, _ORDER, _INFO)
      #define Get_FlagsM(_VALUE, _INFO, _NAME) Get_FlagsM_(_VALUE, _INFO)
      #define Skip_Flags(_FLAGS, _ORDER, _NAME)
      #define Skip_FlagsM(_VALUE, _NAME)
      #define Info_Flags(_FLAGS, _ORDER, _INFO, _NAME)
  
      //***************************************************************************
      // BitStream
      //***************************************************************************
  
      void Get_BS_ (int8u  Bits, int32u  &Info);
      void Get_SB_ (             bool    &Info);
      bool Get_SB_ ()                                              {return BS->GetB();}
      void Get_S1_ (int8u  Bits, int8u   &Info);
      void Get_S2_ (int8u  Bits, int16u  &Info);
      void Get_S3_ (int8u  Bits, int32u  &Info);
      void Get_S4_ (int8u  Bits, int32u  &Info);
      void Get_S5_ (int8u  Bits, int64u  &Info);
      void Get_S6_ (int8u  Bits, int64u  &Info);
      void Get_S7_ (int8u  Bits, int64u  &Info);
      void Get_S8_ (int8u  Bits, int64u  &Info);
      #define Get_BS(Bits, Info, Name) Get_BS_(Bits, Info)
      #define Get_SB(      Info, Name) Get_SB_(      Info)
      #define Get_S1(Bits, Info, Name) Get_S1_(Bits, Info)
      #define Get_S2(Bits, Info, Name) Get_S2_(Bits, Info)
      #define Get_S3(Bits, Info, Name) Get_S3_(Bits, Info)
      #define Get_S4(Bits, Info, Name) Get_S4_(Bits, Info)
      #define Get_S5(Bits, Info, Name) Get_S5_(Bits, Info)
      #define Get_S6(Bits, Info, Name) Get_S6_(Bits, Info)
      #define Get_S7(Bits, Info, Name) Get_S7_(Bits, Info)
      #define Get_S8(Bits, Info, Name) Get_S8_(Bits, Info)
      void Peek_BS(int8u  Bits, int32u  &Info);
      void Peek_SB(              bool    &Info);
      bool Peek_SB()                                              {return BS->PeekB();}
      void Peek_S1(int8u  Bits, int8u   &Info);
      void Peek_S2(int8u  Bits, int16u  &Info);
      void Peek_S3(int8u  Bits, int32u  &Info);
      void Peek_S4(int8u  Bits, int32u  &Info);
      void Peek_S5(int8u  Bits, int64u  &Info);
      void Peek_S6(int8u  Bits, int64u  &Info);
      void Peek_S7(int8u  Bits, int64u  &Info);
      void Peek_S8(int8u  Bits, int64u  &Info);
      inline void Skip_BS_(size_t Bits) {BS->Skip(Bits);}
      inline void Skip_SB_(           ) {BS->Skip(1);}
      inline void Skip_S1_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S2_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S3_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S4_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S5_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S6_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S7_(int8u  Bits) {BS->Skip(Bits);}
      inline void Skip_S8_(int8u  Bits) {BS->Skip(Bits);}
      #define Skip_BS(Bits, Name) Skip_BS_(Bits)
      #define Skip_SB(      Name) Skip_SB_()
      #define Skip_S1(Bits, Name) Skip_S1_(Bits)
      #define Skip_S2(Bits, Name) Skip_S2_(Bits)
      #define Skip_S3(Bits, Name) Skip_S3_(Bits)
      #define Skip_S4(Bits, Name) Skip_S4_(Bits)
      #define Skip_S5(Bits, Name) Skip_S5_(Bits)
      #define Skip_S6(Bits, Name) Skip_S6_(Bits)
      #define Skip_S7(Bits, Name) Skip_S7_(Bits)
      #define Skip_S8(Bits, Name) Skip_S8_(Bits)
      void Mark_0 ();
      #define Mark_0_NoTrustError() Skip_SB_() //Use it for providing a warning instead of a non-trusting error
      void Mark_1 ();
      #define Mark_1_NoTrustError() Skip_SB_() //Use it for providing a warning instead of a non-trusting error
      #define Info_BS(_BITS, _INFO, _NAME) Skip_BS_(_BITS)
      #define Info_SB(_INFO, _NAME)        Skip_SB_(     )
      #define Info_S1(_BITS, _INFO, _NAME) Skip_S1_(_BITS)
      #define Info_S2(_BITS, _INFO, _NAME) Skip_S2_(_BITS)
      #define Info_S3(_BITS, _INFO, _NAME) Skip_S3_(_BITS)
      #define Info_S4(_BITS, _INFO, _NAME) Skip_S4_(_BITS)
      #define Info_S5(_BITS, _INFO, _NAME) Skip_S5_(_BITS)
      #define Info_S6(_BITS, _INFO, _NAME) Skip_S6_(_BITS)
      #define Info_S7(_BITS, _INFO, _NAME) Skip_S7_(_BITS)
      #define Info_S8(_BITS, _INFO, _NAME) Skip_S8_(_BITS)
  
      #define TEST_SB_GET(_CODE, _NAME) \
          { \
              Peek_SB(_CODE); \
              if (!_CODE) \
                  Skip_SB_(); \
              else \
              { \
                  Element_Begin0(); \
                  Skip_SB_(); \
  
      #define TEST_SB_SKIP(_NAME) \
          { \
              if (!Peek_SB()) \
                  Skip_SB_(); \
              else \
              { \
                  Element_Begin0(); \
                  Skip_SB_(); \
  
      #define TESTELSE_SB_GET(_CODE, _NAME) \
          { \
              Peek_SB(_CODE); \
              if (_CODE) \
              { \
                  Element_Begin0(); \
                  Skip_SB_(); \
  
      #define TESTELSE_SB_SKIP(_NAME) \
          { \
              if (Peek_SB()) \
              { \
                  Element_Begin0(); \
                  Skip_SB_(); \
  
      #define TESTELSE_SB_ELSE(_NAME) \
                  Element_End0(); \
              } \
              else \
              { \
                  Skip_SB_(); \
  
      #define TESTELSE_SB_END() \
              } \
          } \
  
      #define TEST_SB_END() \
                  Element_End0(); \
              } \
          } \
  
      //***************************************************************************
      // BitStream (Little Endian)
      //***************************************************************************
  
      void Get_BT_ (int8u  Bits, int32u  &Info);
      void Get_TB_ (             bool    &Info);
      bool Get_TB_ ()                                              {bool Temp; Get_TB_(Temp); return Temp;}
      void Get_T1_ (int8u  Bits, int8u   &Info);
      void Get_T2_ (int8u  Bits, int16u  &Info);
      void Get_T4_ (int8u  Bits, int32u  &Info);
      void Get_T8_ (int8u  Bits, int64u  &Info);
      #define Get_BT(Bits, Info, Name) Get_BT_(Bits, Info)
      #define Get_TB(      Info, Name) Get_TB_(      Info)
      #define Get_T1(Bits, Info, Name) Get_T1_(Bits, Info)
      #define Get_T2(Bits, Info, Name) Get_T2_(Bits, Info)
      #define Get_T4(Bits, Info, Name) Get_T4_(Bits, Info)
      #define Get_T8(Bits, Info, Name) Get_T8_(Bits, Info)
      void Peek_BT(int8u  Bits, int32u  &Info);
      void Peek_TB(              bool    &Info);
      bool Peek_TB()                                              {bool Temp; Peek_TB(Temp); return Temp;}
      void Peek_T1(int8u  Bits, int8u   &Info);
      void Peek_T2(int8u  Bits, int16u  &Info);
      void Peek_T4(int8u  Bits, int32u  &Info);
      void Peek_T8(int8u  Bits, int64u  &Info);
      inline void Skip_BT_(size_t Bits) {BT->Skip(Bits);}
      inline void Skip_TB_(           ) {BT->SkipB();}
      inline void Skip_T1_(int8u  Bits) {BT->Skip1(Bits);}
      inline void Skip_T2_(int8u  Bits) {BT->Skip2(Bits);}
      inline void Skip_T4_(int8u  Bits) {BT->Skip4(Bits);}
      inline void Skip_T8_(int8u  Bits) {BT->Skip8(Bits);}
      #define Skip_BT(Bits, Name) Skip_BT_(Bits)
      #define Skip_TB(      Name) Skip_TB_()
      #define Skip_T1(Bits, Name) Skip_T1_(Bits)
      #define Skip_T2(Bits, Name) Skip_T2_(Bits)
      #define Skip_T4(Bits, Name) Skip_T4_(Bits)
      #define Skip_T8(Bits, Name) Skip_T8_(Bits)
      #define Info_BT(_BITS, _INFO, _NAME) Skip_BT_(_BITS)
      #define Info_TB(_INFO, _NAME)        Skip_TB_(     )
      #define Info_T1(_BITS, _INFO, _NAME) Skip_T1_(_BITS)
      #define Info_T2(_BITS, _INFO, _NAME) Skip_T2_(_BITS)
      #define Info_T4(_BITS, _INFO, _NAME) Skip_T4_(_BITS)
      #define Info_T8(_BITS, _INFO, _NAME) Skip_T8_(_BITS)
  
      #define TEST_TB_GET(_CODE, _NAME) \
          { \
              Peek_TB(_CODE); \
              if (!_CODE) \
                  Skip_TB_(); \
              else \
              { \
                  Element_Begin0(); \
                  Skip_TB_(); \
  
      #define TEST_TB_TKIP(_NAME) \
          { \
              if (!Peek_TB()) \
                  Skip_TB_(); \
              else \
              { \
                  Element_Begin0(); \
                  Skip_TB_(); \
  
      #define TESTELSE_TB_GET(_CODE, _NAME) \
          { \
              Peek_TB(_CODE); \
              if (_CODE) \
              { \
                  Element_Begin0(); \
                  Skip_TB_(); \
  
      #define TESTELSE_TB_TKIP(_NAME) \
          { \
              if (Peek_TB()) \
              { \
                  Element_Begin0(); \
                  Skip_TB_(); \
  
      #define TESTELSE_TB_ELSE(_NAME) \
                  Element_End0(); \
              } \
              else \
              { \
                  Skip_TB_(); \
  
      #define TESTELSE_TB_END() \
              } \
          } \
  
      #define TEST_TB_END() \
                  Element_End0(); \
              } \
          } \
  
      //***************************************************************************
      // Next code planning
      //***************************************************************************
  
      void NextCode_Add(int64u Code);
      void NextCode_Clear();
      bool NextCode_Test();
  
      //***************************************************************************
      // Element trusting
      //***************************************************************************
  
      void Trusted_IsNot (const char*)                                            {Trusted_IsNot();}
      void Trusted_IsNot ();
      bool Trusted_Get   () {return !Element[Element_Level].UnTrusted;}
  
      //***************************************************************************
      // Stream filling
      //***************************************************************************
  
      //Elements - Preparation of element from external app
      size_t Stream_Prepare   (stream_t KindOfStream, size_t StreamPos=(size_t)-1);
      size_t Stream_Erase     (stream_t KindOfStream, size_t StreamPos);
  
      //Fill with datas (with parameter as a size_t)
      void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, const Ztring  &Value, bool Replace=false);
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, const std::string &Value, bool Utf8=true, bool Replace=false) {if (Utf8) Fill(StreamKind, StreamPos, Parameter, Ztring().From_UTF8(Value.c_str(), Value.size()), Replace); else Fill(StreamKind, StreamPos, Parameter, Ztring().From_Local(Value.c_str(), Value.size()), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, const char*    Value, size_t Value_Size=Unlimited, bool Utf8=true, bool Replace=false) {if (Utf8) Fill(StreamKind, StreamPos, Parameter, Ztring().From_UTF8(Value, Value_Size), Replace); else Fill(StreamKind, StreamPos, Parameter, Ztring().From_Local(Value, Value_Size), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, const wchar_t* Value, size_t Value_Size=Unlimited, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring().From_Unicode(Value, Value_Size), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int8u          Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int8s          Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int16u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int16s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int32u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int32s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int64u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, int64s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
             void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, float64        Value, int8u AfterComma=3, bool Replace=false);
      #ifdef SIZE_T_IS_LONG
      inline void Fill (stream_t StreamKind, size_t StreamPos, size_t Parameter, size_t         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      #endif //SIZE_T_IS_LONG
      //Fill with datas
      void Fill_Dup (stream_t StreamKind, size_t StreamPos, const char* Parameter, const Ztring  &Value, bool Replace=false);
      void Fill_Measure (stream_t StreamKind, size_t StreamPos, const char* Parameter, const Ztring  &Value, const Ztring& Measure, bool Replace=false);
      inline void Fill_Measure(stream_t StreamKind, size_t StreamPos, const char* Parameter, const string&  Value, const Ztring& Measure, bool Utf8=true, bool Replace=false) {Fill_Measure(StreamKind, StreamPos, Parameter, Ztring().From_UTF8(Value.c_str(), Value.size()), Measure, Replace);}
      inline void Fill_Measure(stream_t StreamKind, size_t StreamPos, const char* Parameter, int            Value, const Ztring& Measure, int8u Radix=10, bool Replace=false) {Fill_Measure(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Measure, Replace);}
      inline void Fill_Measure(stream_t StreamKind, size_t StreamPos, const char* Parameter, float64        Value, const Ztring& Measure, int8u AfterComma=3, bool Replace=false) {Fill_Measure(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, AfterComma), Measure, Replace);}
      void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, const Ztring  &Value, bool Replace=false);
      void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, ZtringList &Value, ZtringList& Id, bool Replace=false);
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, const std::string &Value, bool Utf8=true, bool Replace=false) {if (Utf8) Fill(StreamKind, StreamPos, Parameter, Ztring().From_UTF8(Value.c_str(), Value.size()), Replace); else Fill(StreamKind, StreamPos, Parameter, Ztring().From_Local(Value.c_str(), Value.size()), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, const char*    Value, size_t Value_Size=Unlimited, bool Utf8=true, bool Replace=false) {if (Utf8) Fill(StreamKind, StreamPos, Parameter, Ztring().From_UTF8(Value, Value_Size), Replace); else Fill(StreamKind, StreamPos, Parameter, Ztring().From_Local(Value, Value_Size), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, const wchar_t* Value, size_t Value_Size=Unlimited, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring().From_Unicode(Value, Value_Size), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int8u          Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int8s          Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int16u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int16s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int32u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int32s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int64u         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, int64s         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, float32        Value, int8u AfterComma=3, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, AfterComma), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, float64        Value, int8u AfterComma=3, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, AfterComma), Replace);}
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, float80        Value, int8u AfterComma=3, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, AfterComma), Replace);}
      #ifdef SIZE_T_IS_LONG
      inline void Fill (stream_t StreamKind, size_t StreamPos, const char* Parameter, size_t         Value, int8u Radix=10, bool Replace=false) {Fill(StreamKind, StreamPos, Parameter, Ztring::ToZtring(Value, Radix).MakeUpperCase(), Replace);}
      #endif //SIZE_T_IS_LONG
      struct fill_temp_item
      {
          Ztring Parameter;
          Ztring Value;
      };
      void Fill_SetOptions(stream_t StreamKind, size_t StreamPos, const char* Parameter, const char* Options);
      vector<fill_temp_item> Fill_Temp[Stream_Max+1]; // +1 because Fill_Temp[Stream_Max] is used when StreamKind is unknown
      map<string, string> Fill_Temp_Options[Stream_Max+1]; // +1 because Fill_Temp[Stream_Max] is used when StreamKind is unknown
      void Fill_Flush ();
      static size_t Fill_Parameter(stream_t StreamKind, generic StreamPos);
  
      const Ztring &Retrieve_Const (stream_t StreamKind, size_t StreamPos, size_t Parameter, info_t KindOfInfo=Info_Text);
      Ztring Retrieve (stream_t StreamKind, size_t StreamPos, size_t Parameter, info_t KindOfInfo=Info_Text);
      const Ztring &Retrieve_Const (stream_t StreamKind, size_t StreamPos, const char* Parameter, info_t KindOfInfo=Info_Text);
      Ztring Retrieve (stream_t StreamKind, size_t StreamPos, const char* Parameter, info_t KindOfInfo=Info_Text);
  
      void Clear (stream_t StreamKind, size_t StreamPos, size_t Parameter);
      void Clear (stream_t StreamKind, size_t StreamPos, const char* Parameter);
      void Clear (stream_t StreamKind, size_t StreamPos);
      void Clear (stream_t StreamKind);
      inline void Clear () {File__Base::Clear();}
  
      //***************************************************************************
      // Filling
      //***************************************************************************
  
      //Actions
      void Accept        (const char*)                                            {Accept();}
      void Accept        ();
      void Accept        (File__Analyze* Parser);
      void Reject        (const char*)                                            {Reject();}
      void Reject        ();
      void Reject        (File__Analyze* Parser);
      void Fill          (const char*)                                            {Fill();}
      void Fill          ();
      void Fill          (File__Analyze* Parser);
      void Update        (const char*)                                            {Fill();}
      void Update        ();
      void Update        (File__Analyze* Parser);
      void Finish        (const char*)                                            {Finish();}
      void Finish        ();
      void Finish        (File__Analyze* Parser);
      void ForceFinish   (const char*)                                            {ForceFinish();}
      void ForceFinish   ();
      void ForceFinish   (File__Analyze* Parser);
      void GoTo          (int64u GoTo_, const char*)                              {GoTo(GoTo_);}
      void GoTo          (int64u GoTo);
      void GoToFromEnd   (int64u GoToFromEnd_, const char*)                       {GoToFromEnd(GoToFromEnd_);}
      void GoToFromEnd   (int64u GoToFromEnd);
      int64u Element_Code_Get (size_t Level);
      int64u Element_TotalSize_Get (size_t LevelLess=0);
      bool Element_IsComplete_Get ();
      void Element_ThisIsAList ();
      void Element_WaitForMoreData ();
      void Element_DoNotTrust (const char*)                                       {Element_DoNotTrust();}
      void Element_DoNotTrust ();
      inline void Element_DoNotShow () {}
      inline void Element_Show () {}
      inline bool Element_Show_Get () {return false;}
      inline void Element_Show_Add (const Ztring &) {}
  
      //Status
      bool Element_IsOK ();
      bool Element_IsNotFinished ();
      bool Element_IsWaitingForMoreData ();
  
      //***************************************************************************
      // Merging
      //***************************************************************************
  
      //Utils
  public :
      size_t Merge(MediaInfo_Internal &ToAdd, bool Erase=true); //Merge 2 File_Base
      size_t Merge(MediaInfo_Internal &ToAdd, stream_t StreamKind, size_t StreamPos_From, size_t StreamPos_To, bool Erase=true); //Merge 2 streams
      size_t Merge(File__Analyze &ToAdd, bool Erase=true); //Merge 2 File_Base
      size_t Merge(File__Analyze &ToAdd, stream_t StreamKind, size_t StreamPos_From, size_t StreamPos_To, bool Erase=true); //Merge 2 streams
  
      void CodecID_Fill           (const Ztring &Value, stream_t StreamKind, size_t StreamPos, infocodecid_format_t Format, stream_t StreamKind_CodecID=Stream_Max);
      void PixelAspectRatio_Fill  (const Ztring &Value, stream_t StreamKind, size_t StreamPos, size_t Parameter_Width, size_t Parameter_Height, size_t Parameter_PixelAspectRatio, size_t Parameter_DisplayAspectRatio);
      void DisplayAspectRatio_Fill(const Ztring &Value, stream_t StreamKind, size_t StreamPos, size_t Parameter_Width, size_t Parameter_Height, size_t Parameter_PixelAspectRatio, size_t Parameter_DisplayAspectRatio);
      #if MEDIAINFO_EVENTS
      static stream_t Streamkind_Get(int8u* ParserIDs, size_t StreamIDs_Size) {if ((ParserIDs[StreamIDs_Size-1]&0xF0)==0x80) return Stream_Video; if ((ParserIDs[StreamIDs_Size-1]&0xF0)==0xA0) return Stream_Audio; return Stream_Max;}
      stream_t Streamkind_Get() {return Streamkind_Get(ParserIDs, StreamIDs_Size);}
      #endif //MEDIAINFO_EVENTS
  
      //***************************************************************************
      // Finalize
      //***************************************************************************
  
      //End
      void Streams_Finish_Global();
  
  protected :
      void Streams_Finish_StreamOnly();
      void Streams_Finish_StreamOnly(stream_t StreamKid, size_t StreamPos);
      void Streams_Finish_StreamOnly_General(size_t StreamPos);
      void Streams_Finish_StreamOnly_Video(size_t StreamPos);
      void Streams_Finish_StreamOnly_Audio(size_t StreamPos);
      void Streams_Finish_StreamOnly_Text(size_t StreamPos);
      void Streams_Finish_StreamOnly_Other(size_t StreamPos);
      void Streams_Finish_StreamOnly_Image(size_t StreamPos);
      void Streams_Finish_StreamOnly_Menu(size_t StreamPos);
      void Streams_Finish_InterStreams();
      void Streams_Finish_Cosmetic();
      void Streams_Finish_Cosmetic(stream_t StreamKid, size_t StreamPos);
      void Streams_Finish_Cosmetic_General(size_t StreamPos);
      void Streams_Finish_Cosmetic_Video(size_t StreamPos);
      void Streams_Finish_Cosmetic_Audio(size_t StreamPos);
      void Streams_Finish_Cosmetic_Text(size_t StreamPos);
      void Streams_Finish_Cosmetic_Chapters(size_t StreamPos);
      void Streams_Finish_Cosmetic_Image(size_t StreamPos);
      void Streams_Finish_Cosmetic_Menu(size_t StreamPos);
      void Streams_Finish_HumanReadable();
      void Streams_Finish_HumanReadable_PerStream(stream_t StreamKind, size_t StreamPos, size_t Parameter);
  
      void Tags ();
      void Video_FrameRate_Rounding (size_t Pos, video Parameter);
      void Video_BitRate_Rounding (size_t Pos, video Parameter);
      void Audio_BitRate_Rounding (size_t Pos, audio Parameter);
  
      //Utils - Finalize
      void Duration_Duration123   (stream_t StreamKind, size_t StreamPos, size_t Parameter);
      void FileSize_FileSize123   (stream_t StreamKind, size_t StreamPos, size_t Parameter);
      void Kilo_Kilo123           (stream_t StreamKind, size_t StreamPos, size_t Parameter);
      void Value_Value123         (stream_t StreamKind, size_t StreamPos, size_t Parameter);
      void YesNo_YesNo            (stream_t StreamKind, size_t StreamPos, size_t Parameter);
  
      //***************************************************************************
      //
      //***************************************************************************
  
  protected :
      //Save for speed improvement
      int8u           Config_Demux;
      Ztring          Config_LineSeparator;
      bool            IsSub;
      enum stream_source
      {
          IsContainer,
          IsStream,
          IsContainerExtra,
          StreamSource_Max,
      };
      stream_source   StreamSource;
  
      //Configuration
      bool DataMustAlwaysBeComplete;  //Data must always be complete, else wait for more data
      bool MustUseAlternativeParser;  //Must use the second parser (example: for Data part)
  
      //Synchro
      bool MustParseTheHeaderFile;    //There is an header part, must parse it
      size_t Trusted;
      size_t Trusted_Multiplier;
  
      //Elements
      size_t Element_Level;           //Current level
      bool   Element_WantNextLevel;   //Want to go to the next leavel instead of the same level
  
      //Element
      int64u Element_Code;            //Code filled in the file, copy of Element[Element_Level].Code
      int64u Element_Offset;          //Position in the Element (without header)
      int64u Element_Size;            //Size of the Element (without header)
  
  private :
      //***************************************************************************
      // Buffer
      //***************************************************************************
  
      void Buffer_Clear(); //Clear the buffer
  protected :
      //Buffer
      bool Open_Buffer_Continue_Loop();
      const int8u* Buffer;
  public : //TO CHANGE
      size_t Buffer_Size;
      int64u Buffer_TotalBytes;
      int64u Buffer_TotalBytes_FirstSynched;
      int64u Buffer_TotalBytes_LastSynched;
      int64u Buffer_PaddingBytes;
      int64u Buffer_JunkBytes;
      float64 Stream_BitRateFromContainer;
  protected :
      int8u* Buffer_Temp;
      size_t Buffer_Temp_Size;
      size_t Buffer_Temp_Size_Max;
      size_t Buffer_Offset; //Temporary usage in this parser
      size_t Buffer_Offset_Temp; //Temporary usage in this parser
      size_t Buffer_MinimumSize;
      size_t Buffer_MaximumSize;
      int64u Buffer_TotalBytes_FirstSynched_Max;
      int64u Buffer_TotalBytes_Fill_Max;
      friend class File__Tags_Helper;
      friend class File_Usac;
      friend class File_Mk;
      friend class File_Mpeg4;
      friend class File_Hevc;
  
      //***************************************************************************
      // Helpers
      //***************************************************************************
  
      bool FileHeader_Begin_0x000001();
      bool FileHeader_Begin_XML(tinyxml2::XMLDocument &Document);
      bool Synchronize_0x000001();
  public:
      #if defined(MEDIAINFO_FILE_YES)
      void TestContinuousFileNames(size_t CountOfFiles=24, Ztring FileExtension=Ztring(), bool SkipComputeDelay=false);
      void TestDirectory();
      #else //defined(MEDIAINFO_FILE_YES)
      void TestContinuousFileNames(size_t =24, Ztring =Ztring(), bool =false) {}
      void TestDirectory() {}
      #endif //defined(MEDIAINFO_FILE_YES)
      #if MEDIAINFO_FIXITY
      bool FixFile(int64u FileOffsetForWriting, const int8u* ToWrite, const size_t ToWrite_Size);
      #endif// MEDIAINFO_FIXITY
  
  private :
  
      //***************************************************************************
      // Elements
      //***************************************************************************
  
      //Element
  public: //TO CHANGE
      BitStream_Fast* BS;             //For conversion from bytes to bitstream
      BitStream*      BT;             //For conversion from bytes to bitstream (Little Endian)
      int64u Header_Size;             //Size of the header of the current element
  private :
  
      //Elements
      size_t Element_Level_Base;      //From other parsers
  
  public : //For very quick access, to not use except if you know what you do
      struct element_details
      {
          int64u  Code;               //Code filled in the file
          int64u  Next;               //
          bool    WaitForMoreData;    //This element is not complete, we need more data
          bool    UnTrusted;          //This element has a problem
          bool    IsComplete;         //This element is fully buffered, no need of more
      };
      std::vector<element_details> Element;
  
  private :
  
      //NextCode
      std::map<int64u, bool> NextCode;
  
      //BookMarks
      size_t              BookMark_Element_Level;
      int64u              BookMark_GoTo;
      std::vector<int64u> BookMark_Code;
      std::vector<int64u> BookMark_Next;
  
  public :
      void BookMark_Set(size_t Element_Level_ToGet=(size_t)-1);
      void BookMark_Get();
      virtual bool BookMark_Needed()                                              {return false;};
  
      //Temp
      std::bitset<32> Status;
      enum status
      {
          IsAccepted,
          IsFilled,
          IsUpdated,
          IsFinished,
          Reserved_04,
          Reserved_05,
          Reserved_06,
          Reserved_07,
          Reserved_08,
          Reserved_09,
          Reserved_10,
          Reserved_11,
          Reserved_12,
          Reserved_13,
          Reserved_14,
          Reserved_15,
          User_16,
          User_17,
          User_18,
          User_19,
          User_20,
          User_21,
          User_22,
          User_23,
          User_24,
          User_25,
          User_26,
          User_27,
          User_28,
          User_29,
          User_30,
          User_31,
      };
      bool ShouldContinueParsing;
  
      //Configuration
      bool MustSynchronize;
      bool CA_system_ID_MustSkipSlices;
      bool FillAllMergedStreams;
      class streamidentity
      {
      public:
          stream_t StreamKind;
          size_t   StreamPos;
  
          streamidentity(stream_t StreamKind_, size_t StreamPos_)
              : StreamKind(StreamKind_)
              , StreamPos(StreamPos_)
          {}
      };
      std::vector<streamidentity> MergedStreams_Last;
  
      //Demux
      enum contenttype
      {
          ContentType_MainStream,
          ContentType_SubStream,
          ContentType_Header,
          ContentType_Synchro
      };
      #if MEDIAINFO_DEMUX
          void Demux (const int8u* Buffer, size_t Buffer_Size, contenttype ContentType, const int8u* OriginalBuffer=NULL, size_t OriginalBuffer_Size=0);
          virtual bool Demux_UnpacketizeContainer_Test() {return true;}
          bool Demux_UnpacketizeContainer_Test_OneFramePerFile();
          void Demux_UnpacketizeContainer_Demux(bool random_access=true);
          void Demux_UnpacketizeContainer_Demux_Clear();
          bool Demux_EventWasSent_Accept_Specific;
      #else //MEDIAINFO_DEMUX
          #define Demux(_A, _B, _C)
      #endif //MEDIAINFO_DEMUX
      #if MEDIAINFO_DECODE
          void Decoded(const int8u* Buffer, size_t Buffer_Size);
      #endif //MEDIAINFO_DECODE
  
      //Events data
      bool    PES_FirstByte_IsAvailable;
      bool    PES_FirstByte_Value;
  
      int64u  Unsynch_Frame_Count;
  
      //AES
      #if MEDIAINFO_AES
          AESdecrypt* AES;
          int8u*      AES_IV;
          int8u*      AES_Decrypted;
          size_t      AES_Decrypted_Size;
      #endif //MEDIAINFO_AES
  
      //Hash
      #if MEDIAINFO_HASH
          HashWrapper*        Hash;
          int64u              Hash_Offset;
          int64u              Hash_ParseUpTo;
      #endif //MEDIAINFO_HASH
  
      #if MEDIAINFO_SEEK
      private:
          bool Seek_Duration_Detected;
      #endif //MEDIAINFO_SEEK
  
      #if MEDIAINFO_IBIUSAGE
      public:
          bool    Config_Ibi_Create;
          int64u  Ibi_SynchronizationOffset_Current;
          int64u  Ibi_SynchronizationOffset_BeginOfFrame;
          ibi     Ibi; //If Main only
          ibi::stream* IbiStream; //If sub only
          size_t  Ibi_Read_Buffer_Seek        (size_t Method, int64u Value, int64u ID);
          void    Ibi_Read_Buffer_Unsynched   ();
          void    Ibi_Stream_Finish           ();
          void    Ibi_Stream_Finish           (int64u Numerator, int64u Denominator); //Partial
          void    Ibi_Add                     ();
      #else //MEDIAINFO_IBIUSAGE
          size_t  Ibi_Read_Buffer_Seek        (size_t, int64u, int64u)            {return (size_t)-1;}
          void    Ibi_Read_Buffer_Unsynched   ()                                  {}
          void    Ibi_Stream_Finish           ()                                  {}
          void    Ibi_Stream_Finish           (int64u, int64u)                    {}
          void    Ibi_Add                     ()                                  {}
      #endif //MEDIAINFO_IBIUSAGE
  };
  
  //Helpers
  #define DETAILS_INFO(_DATA)
  
  #endif
  