/*  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.
 */

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Contributor: Lionel Duchateau, kurtnoise@free.fr
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
    #pragma hdrstop
#endif
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
using namespace ZenLib;
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_MPEGPS_YES) || defined(MEDIAINFO_MPEGTS_YES) || defined(MEDIAINFO_HEVC_YES)
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//---------------------------------------------------------------------------
extern const char* Hevc_tier_flag(bool tier_flag)
{
    return tier_flag ? "High" : "Main";
}

//---------------------------------------------------------------------------
extern const char* Hevc_profile_idc(int32u profile_idc)
{
    switch (profile_idc)
    {
        case   1 : return "Main";
        case   2 : return "Main 10";
        case   3 : return "Main Still";
        case   4 : return "Format Range"; // extensions
        case   5 : return "High Throughput";
        case   6 : return "Multiview Main";
        case   7 : return "Scalable Main"; // can be "Scalable Main 10" depending on general_max_8bit_constraint_flag
        case   8 : return "3D Main";
        case   9 : return "Screen Content"; // coding extensions
        case  10 : return "Scalable Format Range"; // extensions
        default  : return "";
    }
}

} //NameSpace

//---------------------------------------------------------------------------
#endif //...
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_HEVC_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Video/File_Hevc.h"
#include <cmath>
#include <algorithm>
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if MEDIAINFO_EVENTS
    #include "MediaInfo/MediaInfo_Config_PerPackage.h"
    #include "MediaInfo/MediaInfo_Events.h"
    #include "MediaInfo/MediaInfo_Events_Internal.h"
#endif //MEDIAINFO_EVENTS
using namespace std;
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Info
//***************************************************************************

//---------------------------------------------------------------------------
static const int8u Hevc_SubWidthC[]=
{
    1,
    2,
    2,
    1,
};

//---------------------------------------------------------------------------
static const int8u Hevc_SubHeightC[]=
{
    1,
    2,
    1,
    1,
};

//---------------------------------------------------------------------------
static const char* Hevc_chroma_format_idc(int8u chroma_format_idc)
{
    switch (chroma_format_idc)
    {
        case 1: return "4:2:0";
        case 2: return "4:2:2";
        case 3: return "4:4:4";
        default: return "";
    }
}

//---------------------------------------------------------------------------
static const char* Hevc_chroma_format_idc_ColorSpace(int8u chroma_format_idc)
{
    switch (chroma_format_idc)
    {
        case 0: return "Y";
        case 1: return "YUV";
        case 2: return "YUV";
        default: return "";
    }
}

//---------------------------------------------------------------------------
static const char* Hevc_pic_type[]=
{
    "I",
    "I, P",
    "I, P, B",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
};

//---------------------------------------------------------------------------
static const char* Hevc_slice_type(int32u slice_type)
{
    switch (slice_type)
    {
        case 0 : return "P";
        case 1 : return "B";
        case 2 : return "I";
        default: return "";
    }
};

//---------------------------------------------------------------------------
extern const char* Mpegv_colour_primaries(int8u colour_primaries);
extern const char* Mpegv_transfer_characteristics(int8u transfer_characteristics);
extern const char* Mpegv_matrix_coefficients(int8u matrix_coefficients);
const char* Mpegv_matrix_coefficients_ColorSpace(int8u matrix_coefficients);

//---------------------------------------------------------------------------
extern const int8u Avc_PixelAspectRatio_Size;
extern const float32 Avc_PixelAspectRatio[];
extern const char* Avc_video_format[];
extern const char* Avc_video_full_range[];

//***************************************************************************
// Constructor/Destructor
//***************************************************************************

//---------------------------------------------------------------------------
File_Hevc::File_Hevc()
{
    //Config
    #if MEDIAINFO_EVENTS
        ParserIDs[0]=MediaInfo_Parser_Hevc;
        StreamIDs_Width[0]=0;
    #endif //MEDIAINFO_EVENTS
    #if MEDIAINFO_TRACE
        Trace_Layers_Update(8); //Stream
    #endif //MEDIAINFO_TRACE
    MustSynchronize=true;
    Buffer_TotalBytes_FirstSynched_Max=64*1024;
    PTS_DTS_Needed=true;
    StreamSource=IsStream;
    Frame_Count_NotParsedIncluded=0;

    //In
    Frame_Count_Valid=0;
    FrameIsAlwaysComplete=false;
    MustParse_VPS_SPS_PPS=false;
    MustParse_VPS_SPS_PPS_FromMatroska=false;
    MustParse_VPS_SPS_PPS_FromFlv=false;
    SizedBlocks=false;

    //File specific
    lengthSizeMinusOne=(int8u)-1;
}

//---------------------------------------------------------------------------
File_Hevc::~File_Hevc()
{
    Clean_Seq_Parameter();
}
//---------------------------------------------------------------------------
void File_Hevc::Clean_Seq_Parameter()
{
    for (size_t Pos = 0; Pos < seq_parameter_sets.size(); Pos++)
        delete seq_parameter_sets[Pos]; //seq_parameter_sets[Pos]=NULL;
    seq_parameter_sets.clear();
    for (size_t Pos = 0; Pos<pic_parameter_sets.size(); Pos++)
        delete pic_parameter_sets[Pos]; //pic_parameter_sets[Pos]=NULL;
    pic_parameter_sets.clear();
    for (size_t Pos = 0; Pos<video_parameter_sets.size(); Pos++)
        delete video_parameter_sets[Pos]; //video_parameter_sets[Pos]=NULL;
    video_parameter_sets.clear();
    
}

//***************************************************************************
// Streams management
//***************************************************************************

//---------------------------------------------------------------------------
void File_Hevc::Streams_Fill()
{
    if (MustParse_VPS_SPS_PPS_FromFlv)
        return;

    if (Count_Get(Stream_Video)==0)
        Stream_Prepare(Stream_Video);
    Fill(Stream_Video, 0, Video_Format, "HEVC");
    Fill(Stream_Video, 0, Video_Codec, "HEVC");

    for (std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item=seq_parameter_sets.begin(); seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item)
        if ((*seq_parameter_set_Item))
            Streams_Fill(seq_parameter_set_Item);

    //Library name
    Fill(Stream_General, 0, General_Encoded_Library, Encoded_Library);
    Fill(Stream_General, 0, General_Encoded_Library_Name, Encoded_Library_Name);
    Fill(Stream_General, 0, General_Encoded_Library_Version, Encoded_Library_Version);
    Fill(Stream_General, 0, General_Encoded_Library_Settings, Encoded_Library_Settings);
    Fill(Stream_Video, 0, Video_Encoded_Library, Encoded_Library);
    Fill(Stream_Video, 0, Video_Encoded_Library_Name, Encoded_Library_Name);
    Fill(Stream_Video, 0, Video_Encoded_Library_Version, Encoded_Library_Version);
    Fill(Stream_Video, 0, Video_Encoded_Library_Settings, Encoded_Library_Settings);
    hdr::iterator EtsiTs103433=HDR.find(HdrFormat_EtsiTs103433);
    if (EtsiTs103433!=HDR.end())
    {
        for (std::map<video, Ztring>::iterator Item=EtsiTs103433->second.begin(); Item!=EtsiTs103433->second.end(); ++Item)
        {
            Fill(Stream_Video, 0, Item->first, Item->second);
        }
    }
    hdr::iterator SmpteSt209440=HDR.find(HdrFormat_SmpteSt209440);
    if (SmpteSt209440!=HDR.end())
    {
        for (std::map<video, Ztring>::iterator Item=SmpteSt209440->second.begin(); Item!=SmpteSt209440->second.end(); ++Item)
        {
            switch (Item->first)
            {
                case Video_MasteringDisplay_ColorPrimaries:
                case Video_MasteringDisplay_Luminance:
                    if (Retrieve_Const(Stream_Video, 0, Item->first)==Item->second)
                        break;
                    // Fallthrough
                default:
                    Fill(Stream_Video, 0, Item->first, Item->second);
            }
        }
    }
    hdr::iterator SmpteSt2086=HDR.find(HdrFormat_SmpteSt2086);
    if (SmpteSt2086!=HDR.end())
    {
        for (std::map<video, Ztring>::iterator Item=SmpteSt2086->second.begin(); Item!=SmpteSt2086->second.end(); ++Item)
        {
            bool Ignore;
            switch (Item->first)
            {
                case Video_HDR_Format:
                    Ignore=!Retrieve_Const(Stream_Video, 0, Item->first).empty();
                    break;
                case Video_MasteringDisplay_ColorPrimaries:
                case Video_MasteringDisplay_Luminance:
                    Ignore=Retrieve_Const(Stream_Video, 0, Item->first)==Item->second;
                    break;
            }
            if (!Ignore)
                Fill(Stream_Video, 0, Item->first, Item->second);
        }
    }
    if (!EtsiTS103433.empty())
    {
        Fill(Stream_Video, 0, "EtsiTS103433", EtsiTS103433);
        Fill_SetOptions(Stream_Video, 0, "EtsiTS103433", "N NTN");
    }
    if (maximum_content_light_level)
        Fill(Stream_Video, 0, "MaxCLL", Ztring::ToZtring(maximum_content_light_level) + __T(" cd/m2"));
    if (maximum_frame_average_light_level)
        Fill(Stream_Video, 0, "MaxFALL", Ztring::ToZtring(maximum_frame_average_light_level) + __T(" cd/m2"));
    if (chroma_sample_loc_type_top_field != (int32u)-1)
    {
    Fill(Stream_Video, 0, "ChromaSubsampling_Position", __T("Type ") + Ztring::ToZtring(chroma_sample_loc_type_top_field));
    if (chroma_sample_loc_type_bottom_field != (int32u)-1 && chroma_sample_loc_type_bottom_field != chroma_sample_loc_type_top_field)
        Fill(Stream_Video, 0, "ChromaSubsampling_Position", __T("Type ") + Ztring::ToZtring(chroma_sample_loc_type_bottom_field));
    }
}

//---------------------------------------------------------------------------
void File_Hevc::Streams_Fill(std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item)
{
    int32u Width = (*seq_parameter_set_Item)->pic_width_in_luma_samples;
    int32u Height= (*seq_parameter_set_Item)->pic_height_in_luma_samples;
    int8u chromaArrayType = (*seq_parameter_set_Item)->ChromaArrayType();
    if (chromaArrayType >= 4)
        chromaArrayType = 0;
    int32u CropUnitX=Hevc_SubWidthC [chromaArrayType];
    int32u CropUnitY=Hevc_SubHeightC[chromaArrayType];
    Width -=((*seq_parameter_set_Item)->conf_win_left_offset+(*seq_parameter_set_Item)->conf_win_right_offset)*CropUnitX;
    Height-=((*seq_parameter_set_Item)->conf_win_top_offset +(*seq_parameter_set_Item)->conf_win_bottom_offset)*CropUnitY;

    Ztring Profile;
    if ((*seq_parameter_set_Item)->profile_space==0)
    {
        if ((*seq_parameter_set_Item)->profile_idc)
        {
            Profile=Ztring().From_UTF8(Hevc_profile_idc((*seq_parameter_set_Item)->profile_idc));
            if ((*seq_parameter_set_Item)->profile_idc == 7 && (*seq_parameter_set_Item)->general_max_8bit_constraint_flag)
                Profile+=__T(" 10");
        }
        if ((*seq_parameter_set_Item)->level_idc)
        {
            if ((*seq_parameter_set_Item)->profile_idc)
                Profile+=__T('@');
            Profile+=__T('L')+Ztring().From_Number(((float)(*seq_parameter_set_Item)->level_idc)/30, ((*seq_parameter_set_Item)->level_idc%10)?1:0);
            Profile+=__T('@');
            Profile+=Ztring().From_UTF8(Hevc_tier_flag((*seq_parameter_set_Item)->tier_flag));
        }
    }
    Fill(Stream_Video, 0, Video_Format_Profile, Profile);
    Fill(Stream_Video, 0, Video_Codec_Profile, Profile);
    Fill(Stream_Video, StreamPos_Last, Video_Width, Width);
    Fill(Stream_Video, StreamPos_Last, Video_Height, Height);
    if ((*seq_parameter_set_Item)->conf_win_left_offset || (*seq_parameter_set_Item)->conf_win_right_offset)
        Fill(Stream_Video, StreamPos_Last, Video_Stored_Width, (*seq_parameter_set_Item)->pic_width_in_luma_samples);
    if ((*seq_parameter_set_Item)->conf_win_top_offset || (*seq_parameter_set_Item)->conf_win_bottom_offset)
        Fill(Stream_Video, StreamPos_Last, Video_Stored_Height, (*seq_parameter_set_Item)->pic_height_in_luma_samples);

    Fill(Stream_Video, 0, Video_ColorSpace, Hevc_chroma_format_idc_ColorSpace((*seq_parameter_set_Item)->chroma_format_idc));
    Fill(Stream_Video, 0, Video_ChromaSubsampling, Hevc_chroma_format_idc((*seq_parameter_set_Item)->chroma_format_idc));
    if ((*seq_parameter_set_Item)->bit_depth_luma_minus8==(*seq_parameter_set_Item)->bit_depth_chroma_minus8)
        Fill(Stream_Video, 0, Video_BitDepth, (*seq_parameter_set_Item)->bit_depth_luma_minus8+8);

    if (preferred_transfer_characteristics!=2)
        Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics(preferred_transfer_characteristics));
    if ((*seq_parameter_set_Item)->vui_parameters)
    {
        if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag)
        {
                if ((*seq_parameter_set_Item)->vui_parameters->time_scale && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick)
                        Fill(Stream_Video, StreamPos_Last, Video_FrameRate, (float64)(*seq_parameter_set_Item)->vui_parameters->time_scale / (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick);
        }

        if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag)
        {
                float64 PixelAspectRatio = 1;
                if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc<Avc_PixelAspectRatio_Size)
                        PixelAspectRatio = Avc_PixelAspectRatio[(*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc];
                else if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc == 0xFF && (*seq_parameter_set_Item)->vui_parameters->sar_height)
                        PixelAspectRatio = ((float64) (*seq_parameter_set_Item)->vui_parameters->sar_width) / (*seq_parameter_set_Item)->vui_parameters->sar_height;

                Fill(Stream_Video, 0, Video_PixelAspectRatio, PixelAspectRatio, 3, true);
                if(Height)
                   Fill(Stream_Video, 0, Video_DisplayAspectRatio, Width*PixelAspectRatio/Height, 3, true); //More precise
        }

        //Colour description
        if ((*seq_parameter_set_Item)->vui_parameters->video_signal_type_present_flag)
        {
            Fill(Stream_Video, 0, Video_Standard, Avc_video_format[(*seq_parameter_set_Item)->vui_parameters->video_format]);
            Fill(Stream_Video, 0, Video_colour_range, Avc_video_full_range[(*seq_parameter_set_Item)->vui_parameters->video_full_range_flag]);
            if ((*seq_parameter_set_Item)->vui_parameters->colour_description_present_flag)
            {
                Fill(Stream_Video, 0, Video_colour_description_present, "Yes");
                Fill(Stream_Video, 0, Video_colour_primaries, Mpegv_colour_primaries((*seq_parameter_set_Item)->vui_parameters->colour_primaries));
                Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics((*seq_parameter_set_Item)->vui_parameters->transfer_characteristics));
                Fill(Stream_Video, 0, Video_matrix_coefficients, Mpegv_matrix_coefficients((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients));
                if ((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients!=2)
                    Fill(Stream_Video, 0, Video_ColorSpace, Mpegv_matrix_coefficients_ColorSpace((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients), Unlimited, true, true);
            }
        }
    }
}

//---------------------------------------------------------------------------
void File_Hevc::Streams_Finish()
{
}

//***************************************************************************
// Buffer - File header
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Hevc::FileHeader_Begin()
{
    if (!File__Analyze::FileHeader_Begin_0x000001())
        return false;

    if (!MustSynchronize)
    {
        Synched_Init();
        Buffer_TotalBytes_FirstSynched=0;
        File_Offset_FirstSynched=File_Offset;
    }

    //All should be OK
    return true;
}

//***************************************************************************
// Buffer - Synchro
//***************************************************************************

//---------------------------------------------------------------------------
bool File_Hevc::Synchronize()
{
    //Synchronizing
    size_t Buffer_Offset_Min=Buffer_Offset;
    while(Buffer_Offset+4<=Buffer_Size && (Buffer[Buffer_Offset  ]!=0x00
                                        || Buffer[Buffer_Offset+1]!=0x00
                                        || Buffer[Buffer_Offset+2]!=0x01))
    {
        Buffer_Offset+=2;
        while(Buffer_Offset<Buffer_Size && Buffer[Buffer_Offset]!=0x00)
            Buffer_Offset+=2;
        if (Buffer_Offset>=Buffer_Size || Buffer[Buffer_Offset-1]==0x00)
            Buffer_Offset--;
    }
    if (Buffer_Offset>Buffer_Offset_Min && Buffer[Buffer_Offset-1]==0x00)
        Buffer_Offset--;

    //Parsing last bytes if needed
    if (Buffer_Offset+4==Buffer_Size && (Buffer[Buffer_Offset  ]!=0x00
                                      || Buffer[Buffer_Offset+1]!=0x00
                                      || Buffer[Buffer_Offset+2]!=0x00
                                      || Buffer[Buffer_Offset+3]!=0x01))
        Buffer_Offset++;
    if (Buffer_Offset+3==Buffer_Size && (Buffer[Buffer_Offset  ]!=0x00
                                      || Buffer[Buffer_Offset+1]!=0x00
                                      || Buffer[Buffer_Offset+2]!=0x01))
        Buffer_Offset++;
    if (Buffer_Offset+2==Buffer_Size && (Buffer[Buffer_Offset  ]!=0x00
                                      || Buffer[Buffer_Offset+1]!=0x00))
        Buffer_Offset++;
    if (Buffer_Offset+1==Buffer_Size &&  Buffer[Buffer_Offset  ]!=0x00)
        Buffer_Offset++;

    if (Buffer_Offset+4>Buffer_Size)
        return false;

    if (File_Offset==0 && Buffer_Offset==0 && (Buffer[3]==0xE0 || Buffer[3]==0xFE))
    {
        //It is from MPEG-PS
        Reject();
        return false;
    }

    //Synched is OK
    Synched=true;
    return true;
}

//---------------------------------------------------------------------------
bool File_Hevc::Synched_Test()
{
    //Must have enough buffer for having header
    if (Buffer_Offset+6>Buffer_Size)
        return false;

    //Quick test of synchro
    if (Buffer[Buffer_Offset  ]!=0x00
     || Buffer[Buffer_Offset+1]!=0x00
     || (Buffer[Buffer_Offset+2]!=0x01 && (Buffer[Buffer_Offset+2]!=0x00 || Buffer[Buffer_Offset+3]!=0x01)))
    {
        Synched=false;
        return true;
    }

    //Quick search
    if (!Header_Parser_QuickSearch())
        return false;

    //We continue
    return true;
}

//***************************************************************************
// Buffer - Demux
//***************************************************************************

//---------------------------------------------------------------------------
#if MEDIAINFO_DEMUX
bool File_Hevc::Demux_UnpacketizeContainer_Test()
{
    const int8u*    Buffer_Temp=NULL;
    size_t          Buffer_Temp_Size=0;
    bool            RandomAccess=true; //Default, in case of problem

    if ((MustParse_VPS_SPS_PPS || SizedBlocks) && Demux_Transcode_Iso14496_15_to_AnnexB)
    {
        if (MustParse_VPS_SPS_PPS)
            return true; //Wait for SPS and PPS

        //Random access check
        RandomAccess=false;

        //Computing final size
        size_t TranscodedBuffer_Size=0;
        size_t Buffer_Offset_Save=Buffer_Offset;
        while (Buffer_Offset+lengthSizeMinusOne+1+1<=Buffer_Size)
        {
            size_t Size;
            if (Buffer_Offset+lengthSizeMinusOne>Buffer_Size)
            {
                Size=0;
                Buffer_Offset=Buffer_Size;
            }
            else
            switch (lengthSizeMinusOne)
            {
                case 0: Size=Buffer[Buffer_Offset];
                        TranscodedBuffer_Size+=2;
                        break;
                case 1: Size=BigEndian2int16u(Buffer+Buffer_Offset);
                        TranscodedBuffer_Size++;
                        break;
                case 2: Size=BigEndian2int24u(Buffer+Buffer_Offset);
                        break;
                case 3: Size=BigEndian2int32u(Buffer+Buffer_Offset);
                        TranscodedBuffer_Size--;
                        break;
                default:    return true; //Problem
            }
            Size+=lengthSizeMinusOne+1;

            //Coherency checking
            if (Size==0 || Buffer_Offset+Size>Buffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+lengthSizeMinusOne+1>Buffer_Size))
                Size=Buffer_Size-Buffer_Offset;

            //Random access check
            if (!RandomAccess && Buffer_Offset+lengthSizeMinusOne+1<Buffer_Size && (Buffer[Buffer_Offset+lengthSizeMinusOne+1]&0x40)==0) //Is a slice
            {
                Element_Offset=lengthSizeMinusOne+1+2;
                Element_Size=Size;

                BS_Begin();
                Get_SB (   first_slice_segment_in_pic_flag,                 "first_slice_segment_in_pic_flag");
                if (first_slice_segment_in_pic_flag)
                {
                    Element_Code=(Buffer[Buffer_Offset+lengthSizeMinusOne+1]&0x3E)>>1; //nal_unit_type
                    RapPicFlag=Element_Code>=16 && Element_Code<=23;
                    if (RapPicFlag)
                        Skip_SB(                                                "no_output_of_prior_pics_flag");
                    Get_UE (   slice_pic_parameter_set_id,                      "slice_pic_parameter_set_id");
                    int8u num_extra_slice_header_bits=(int8u)-1;
                    std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item;
                    if (MustParse_VPS_SPS_PPS_FromFlv)
                        num_extra_slice_header_bits=0; // We bet it is old, so without num_extra_slice_header_bits
                    else if (!(slice_pic_parameter_set_id>=pic_parameter_sets.size() || (*(pic_parameter_set_Item=pic_parameter_sets.begin()+slice_pic_parameter_set_id))==NULL))
                    {
                        num_extra_slice_header_bits=(*pic_parameter_set_Item)->num_extra_slice_header_bits;
                    }
                    if (num_extra_slice_header_bits!=(int8u)-1)
                    {
                        int32u slice_type;
                        Skip_S1(num_extra_slice_header_bits,                    "slice_reserved_flags");
                        Get_UE (slice_type,                                     "slice_type");

                        switch (slice_type)
                        {
                            case 2 :
                            case 7 :
                                        RandomAccess=true;
                        }
                    }
                }
                BS_End();
            }

            TranscodedBuffer_Size+=Size;
            Buffer_Offset+=Size;
        }
        Buffer_Offset=Buffer_Offset_Save;

        //Adding VPS/SPS/PPS sizes
        if (RandomAccess)
        {
            for (video_parameter_set_structs::iterator Data_Item=video_parameter_sets.begin(); Data_Item!=video_parameter_sets.end(); ++Data_Item)
                TranscodedBuffer_Size+=(*Data_Item)->AnnexB_Buffer_Size;
            for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item)
                TranscodedBuffer_Size+=(*Data_Item)->AnnexB_Buffer_Size;
            for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item)
                TranscodedBuffer_Size+=(*Data_Item)->AnnexB_Buffer_Size;
        }

        //Copying
        int8u* TranscodedBuffer=new int8u[TranscodedBuffer_Size+100];
        size_t TranscodedBuffer_Pos=0;
        if (RandomAccess)
        {
            for (video_parameter_set_structs::iterator Data_Item=video_parameter_sets.begin(); Data_Item!=video_parameter_sets.end(); ++Data_Item)
            {
                std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->AnnexB_Buffer, (*Data_Item)->AnnexB_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->AnnexB_Buffer_Size;
            }
            for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item)
            {
                std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->AnnexB_Buffer, (*Data_Item)->AnnexB_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->AnnexB_Buffer_Size;
            }
            for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item)
            {
                std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->AnnexB_Buffer, (*Data_Item)->AnnexB_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->AnnexB_Buffer_Size;
            }
        }
        while (Buffer_Offset<Buffer_Size)
        {
            //Sync layer
            TranscodedBuffer[TranscodedBuffer_Pos]=0x00;
            TranscodedBuffer_Pos++;
            TranscodedBuffer[TranscodedBuffer_Pos]=0x00;
            TranscodedBuffer_Pos++;
            TranscodedBuffer[TranscodedBuffer_Pos]=0x01;
            TranscodedBuffer_Pos++;

            //Block
            size_t Size;
            switch (lengthSizeMinusOne)
            {
                case 0: Size=Buffer[Buffer_Offset];
                        Buffer_Offset++;
                        break;
                case 1: Size=BigEndian2int16u(Buffer+Buffer_Offset);
                        Buffer_Offset+=2;
                        break;
                case 2: Size=BigEndian2int24u(Buffer+Buffer_Offset);
                        Buffer_Offset+=3;
                        break;
                case 3: Size=BigEndian2int32u(Buffer+Buffer_Offset);
                        Buffer_Offset+=4;
                        break;
                default: //Problem
                        delete [] TranscodedBuffer;
                        return false;
            }

            //Coherency checking
            if (Size==0 || Buffer_Offset+Size>Buffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+lengthSizeMinusOne+1>Buffer_Size))
                Size=Buffer_Size-Buffer_Offset;

            std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, Buffer+Buffer_Offset, Size);
            TranscodedBuffer_Pos+=Size;
            Buffer_Offset+=Size;
        }
        Buffer_Offset=0;

        Buffer_Temp=Buffer;
        Buffer=TranscodedBuffer;
        Buffer_Temp_Size=Buffer_Size;
        Buffer_Size=TranscodedBuffer_Size;
        Demux_Offset=Buffer_Size;
    }
    else
    {
        bool zero_byte=Buffer[Buffer_Offset+2]==0x00;
        if (!(((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x40)==0 && (Buffer[Buffer_Offset+(zero_byte?6:5)]&0x80)!=0x80)
           || (Buffer[Buffer_Offset+(zero_byte?4:3)]&0x7E)==(38<<1)))
        {
            if (Demux_Offset==0)
            {
                Demux_Offset=Buffer_Offset;
                Demux_IntermediateItemFound=false;
            }
            while (Demux_Offset+6<=Buffer_Size)
            {
                //Synchronizing
                while(Demux_Offset+6<=Buffer_Size && (Buffer[Demux_Offset  ]!=0x00
                                                   || Buffer[Demux_Offset+1]!=0x00
                                                   || Buffer[Demux_Offset+2]!=0x01))
                {
                    Demux_Offset+=2;
                    while(Demux_Offset<Buffer_Size && Buffer[Buffer_Offset]!=0x00)
                        Demux_Offset+=2;
                    if (Demux_Offset>=Buffer_Size || Buffer[Demux_Offset-1]==0x00)
                        Demux_Offset--;
                }

                if (Demux_Offset+6>Buffer_Size)
                {
                    if (Config->IsFinishing)
                        Demux_Offset=Buffer_Size;
                    break;
                }

                zero_byte=Buffer[Demux_Offset+2]==0x00;
                int8u nal_unit_type=Buffer[Demux_Offset+(zero_byte?4:3)]>>1;
                bool Next;
                switch (nal_unit_type)
                {
                    case  0 :
                    case  1 :
                    case  2 :
                    case  3 :
                    case  4 :
                    case  5 :
                    case  6 :
                    case  7 :
                    case  8 :
                    case  9 :
                    case 16 :
                    case 17 :
                    case 18 :
                    case 19 :
                    case 20 :
                    case 21 :
                                if (Demux_IntermediateItemFound)
                                {
                                    if (Buffer[Demux_Offset+(zero_byte?6:5)]&0x80)
                                        Next=true;
                                    else
                                        Next=false;
                                }
                                else
                                {
                                    Next=false;
                                    Demux_IntermediateItemFound=true;
                                }
                              break;
                    case 32 :
                    case 33 :
                    case 34 :
                    case 35 :
                              if (Demux_IntermediateItemFound)
                                  Next=true;
                              else
                                  Next=false;
                              break;
                    default : Next=false;
                }

                if (Next)
                {
                    Demux_IntermediateItemFound=false;
                    break;
                }

                Demux_Offset++;
            }

            if (Demux_Offset+6>Buffer_Size && !FrameIsAlwaysComplete && !Config->IsFinishing)
                return false; //No complete frame

            if (Demux_Offset && Buffer[Demux_Offset-1]==0x00)
                Demux_Offset--;

            zero_byte=Buffer[Buffer_Offset+2]==0x00;
            size_t Buffer_Offset_Random=Buffer_Offset;
            if ((Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x7E)==(35<<1))
            {
                Buffer_Offset_Random++;
                if (zero_byte)
                    Buffer_Offset_Random++;
                while(Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random  ]!=0x00
                                                           || Buffer[Buffer_Offset_Random+1]!=0x00
                                                           || Buffer[Buffer_Offset_Random+2]!=0x01))
                    Buffer_Offset_Random++;
                zero_byte=Buffer[Buffer_Offset_Random+2]==0x00;
            }
            RandomAccess=Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x7E)==(32<<1); //video_parameter_set
        }
    }

    if (!Status[IsAccepted])
    {
        if (Config->Demux_EventWasSent)
            return false;
        File_Hevc* MI=new File_Hevc;
        Element_Code=(int64u)-1;
        Open_Buffer_Init(MI);
        #ifdef MEDIAINFO_EVENTS
            MediaInfo_Config_PerPackage* Config_PerPackage_Temp=MI->Config->Config_PerPackage;
            MI->Config->Config_PerPackage=NULL;
        #endif //MEDIAINFO_EVENTS
        Open_Buffer_Continue(MI, Buffer, Buffer_Size);
        #ifdef MEDIAINFO_EVENTS
            MI->Config->Config_PerPackage=Config_PerPackage_Temp;
        #endif //MEDIAINFO_EVENTS
        bool IsOk=MI->Status[IsAccepted];
        delete MI;
        if (!IsOk)
            return false;
    }

    if (IFrame_Count || RandomAccess)
    {
        int64u PTS_Temp=FrameInfo.PTS;
        if (!IsSub)
            FrameInfo.PTS=(int64u)-1;
        Demux_UnpacketizeContainer_Demux(RandomAccess);
        if (!IsSub)
            FrameInfo.PTS=PTS_Temp;
    }
    else
        Demux_UnpacketizeContainer_Demux_Clear();

    if (Buffer_Temp)
    {
        Demux_TotalBytes-=Buffer_Size;
        Demux_TotalBytes+=Buffer_Temp_Size;
        delete[] Buffer;
        Buffer=Buffer_Temp;
        Buffer_Size=Buffer_Temp_Size;
    }

    return true;
}
#endif //MEDIAINFO_DEMUX

//---------------------------------------------------------------------------
void File_Hevc::Synched_Init()
{
    if (!Frame_Count_Valid)
        Frame_Count_Valid=Config->ParseSpeed>=0.3?16:16; //Note: should be replaced by "512:2" when I-frame/GOP detection is OK

    //FrameInfo
    PTS_End=0;
    if (!IsSub)
        FrameInfo.DTS=0; //No DTS in container
    DTS_Begin=FrameInfo.DTS;
    DTS_End=FrameInfo.DTS;

    //Status
    IFrame_Count=0;

    //Temp
    chroma_sample_loc_type_top_field=(int32u)-1;
    chroma_sample_loc_type_bottom_field=(int32u)-1;
    maximum_content_light_level=0;
    maximum_frame_average_light_level=0;
    preferred_transfer_characteristics=2;
    chroma_format_idc=0;

    //Default values
    Streams.resize(0x100);
    Streams[32].Searching_Payload=true; //video_parameter_set
    Streams[35].Searching_Payload=true; //access_unit_delimiter
    Streams[39].Searching_Payload=true; //sei
    for (int8u Pos=0xFF; Pos>=48; Pos--)
        Streams[Pos].Searching_Payload=true; //unspecified

    #if MEDIAINFO_DEMUX
        Demux_Transcode_Iso14496_15_to_AnnexB=Config->Demux_Hevc_Transcode_Iso14496_15_to_AnnexB_Get();
    #endif //MEDIAINFO_DEMUX
}

//***************************************************************************
// Buffer - Global
//***************************************************************************

//---------------------------------------------------------------------------
void File_Hevc::Read_Buffer_Unsynched()
{
    //Impossible to know TimeStamps now
    PTS_End=0;
    DTS_End=0;
}

//***************************************************************************
// Buffer - Per element
//***************************************************************************

//---------------------------------------------------------------------------
void File_Hevc::Header_Parse()
{
    //Specific case
    if (MustParse_VPS_SPS_PPS)
    {
        Header_Fill_Size(Element_Size);
        Header_Fill_Code((int64u)-1, "Specific");
        return;
    }

    //Parsing
    int8u nal_unit_type, nuh_temporal_id_plus1;
    if (!SizedBlocks)
    {
        if (Buffer[Buffer_Offset+2]==0x00)
            Skip_B1(                                            "zero_byte");
        Skip_B3(                                                "start_code_prefix_one_3bytes");
        BS_Begin();
        Mark_0 ();
        Get_S1 (6, nal_unit_type,                               "nal_unit_type");
        Get_S1 (6, nuh_layer_id,                                "nuh_layer_id");
        Get_S1 (3, nuh_temporal_id_plus1,                       "nuh_temporal_id_plus1");
        BS_End();

        if (!Header_Parser_Fill_Size())
        {
            Element_WaitForMoreData();
            return;
        }

        //if (nuh_temporal_id_plus1==0) // Found 1 stream with nuh_temporal_id_plus1==0, lets disable this coherency test for the moment
        //    Trusted_IsNot("nuh_temporal_id_plus1");
    }
    else
    {
        int32u Size;
        switch (lengthSizeMinusOne)
        {
            case 0: {
                        int8u Size_;
                        Get_B1 (Size_,                          "size");
                        Size=Size_;
                    }
                    break;
            case 1: {
                        int16u Size_;
                        Get_B2 (Size_,                          "size");
                        Size=Size_;
                    }
                    break;
            case 2: {
                        int32u Size_;
                        Get_B3 (Size_,                          "size");
                        Size=Size_;
                    }
                    break;
            case 3:     Get_B4 (Size,                           "size");
                    break;
            default:    Trusted_IsNot("No size of NALU defined");
                        Size=(int32u)(Buffer_Size-Buffer_Offset);
        }
        BS_Begin();
        Mark_0 ();
        Get_S1 (6, nal_unit_type,                               "nal_unit_type");
        Get_S1 (6, nuh_layer_id,                                "nuh_layer_id");
        Get_S1 (3, nuh_temporal_id_plus1,                       "nuh_temporal_id_plus1");
        BS_End();

        //if (nuh_temporal_id_plus1==0) // Found 1 stream with nuh_temporal_id_plus1==0, lets disable this coherency test for the moment
        //    Trusted_IsNot("nuh_temporal_id_plus1");

        FILLING_BEGIN();
            Header_Fill_Size(Size?(Element_Offset-2+Size):(Buffer_Size-Buffer_Offset)); //If Size is 0, it is not normal, we skip the complete frame
        FILLING_END();
    }

    //Filling
    #if MEDIAINFO_TRACE
        if (Trace_Activated)
            Header_Fill_Code(nal_unit_type, Ztring().From_CC1(nal_unit_type));
        else
    #endif //MEDIAINFO_TRACE
            Header_Fill_Code(nal_unit_type);
}

//---------------------------------------------------------------------------
bool File_Hevc::Header_Parser_Fill_Size()
{
    //Look for next Sync word
    if (Buffer_Offset_Temp==0) //Buffer_Offset_Temp is not 0 if Header_Parse_Fill_Size() has already parsed first frames
        Buffer_Offset_Temp=Buffer_Offset+4;
    while (Buffer_Offset_Temp+5<=Buffer_Size
        && CC3(Buffer+Buffer_Offset_Temp)!=0x000001)
    {
        Buffer_Offset_Temp+=2;
        while(Buffer_Offset_Temp<Buffer_Size && Buffer[Buffer_Offset_Temp]!=0x00)
            Buffer_Offset_Temp+=2;
        if (Buffer_Offset_Temp>=Buffer_Size || Buffer[Buffer_Offset_Temp-1]==0x00)
            Buffer_Offset_Temp--;
    }

    //Must wait more data?
    if (Buffer_Offset_Temp+5>Buffer_Size)
    {
        if (FrameIsAlwaysComplete || Config->IsFinishing)
            Buffer_Offset_Temp=Buffer_Size; //We are sure that the next bytes are a start
        else
            return false;
    }

    if (Buffer[Buffer_Offset_Temp-1]==0x00)
        Buffer_Offset_Temp--;

    //OK, we continue
    Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset);
    Buffer_Offset_Temp=0;
    return true;
}

//---------------------------------------------------------------------------
bool File_Hevc::Header_Parser_QuickSearch()
{
    while (       Buffer_Offset+6<=Buffer_Size
      &&   Buffer[Buffer_Offset  ]==0x00
      &&   Buffer[Buffer_Offset+1]==0x00
      &&  (Buffer[Buffer_Offset+2]==0x01
        || (Buffer[Buffer_Offset+2]==0x00 && Buffer[Buffer_Offset+3]==0x01)))
    {
        //Getting start_code
        int8u nal_unit_type;
        if (Buffer[Buffer_Offset+2]==0x00)
            nal_unit_type=(CC1(Buffer+Buffer_Offset+4)&0x7E)>>1;
        else
            nal_unit_type=(CC1(Buffer+Buffer_Offset+3)&0x7E)>>1;

        //Searching start
        if (Streams[nal_unit_type].Searching_Payload)
            return true;

        //Synchronizing
        Buffer_Offset+=4;
        Synched=false;
        if (!Synchronize())
        {
            UnSynched_IsNotJunk=true;
            return false;
        }

        if (Buffer_Offset+6>Buffer_Size)
        {
            UnSynched_IsNotJunk=true;
            return false;
        }
    }

    Trusted_IsNot("HEVC, Synchronisation lost");
    return Synchronize();
}

//---------------------------------------------------------------------------
void File_Hevc::Data_Parse()
{
    //Specific case
    if (Element_Code==(int64u)-1)
    {
        VPS_SPS_PPS();
        return;
    }

    if (nuh_layer_id)
    {
        //Skip_XX(Element_Size,                                   "(Extension)");
        //return;
    }

    //Trailing zeroes
    int64u Element_Size_SaveBeforeZeroes=Element_Size;
    if (Element_Size)
    {
        while (Element_Size && Buffer[Buffer_Offset+(size_t)Element_Size-1]==0)
            Element_Size--;
    }

    //Searching emulation_prevention_three_byte
    int8u* Buffer_3Bytes=NULL;
    const int8u* Save_Buffer=Buffer;
    int64u Save_File_Offset=File_Offset;
    size_t Save_Buffer_Offset=Buffer_Offset;
    int64u Save_Element_Size=Element_Size;
    size_t Element_Offset_3Bytes=(size_t)Element_Offset;
    std::vector<size_t> ThreeByte_List;
    while (Element_Offset_3Bytes+3<=Element_Size)
    {
        if (CC3(Buffer+Buffer_Offset+(size_t)Element_Offset_3Bytes)==0x000003)
            ThreeByte_List.push_back(Element_Offset_3Bytes+2);
        Element_Offset_3Bytes+=2;
        while(Element_Offset_3Bytes<Element_Size && Buffer[Buffer_Offset+(size_t)Element_Offset_3Bytes]!=0x00)
            Element_Offset_3Bytes+=2;
        if (Element_Offset_3Bytes>=Element_Size || Buffer[Buffer_Offset+(size_t)Element_Offset_3Bytes-1]==0x00)
            Element_Offset_3Bytes--;
    }

    if (!ThreeByte_List.empty())
    {
        //We must change the buffer for keeping out
        Element_Size=Save_Element_Size-ThreeByte_List.size();
        File_Offset+=Buffer_Offset;
        Buffer_Offset=0;
        Buffer_3Bytes=new int8u[(size_t)Element_Size];
        for (size_t Pos=0; Pos<=ThreeByte_List.size(); Pos++)
        {
            size_t Pos0=(Pos==ThreeByte_List.size())?(size_t)Save_Element_Size:(ThreeByte_List[Pos]);
            size_t Pos1=(Pos==0)?0:(ThreeByte_List[Pos-1]+1);
            size_t Buffer_3bytes_Begin=Pos1-Pos;
            size_t Save_Buffer_Begin  =Pos1;
            size_t Size=               Pos0-Pos1;
            std::memcpy(Buffer_3Bytes+Buffer_3bytes_Begin, Save_Buffer+Save_Buffer_Offset+Save_Buffer_Begin, Size);
        }
        Buffer=Buffer_3Bytes;
    }

    //Parsing
    switch (Element_Code)
    {
        case  0 :
        case  1 :
        case  2 :
        case  3 :
        case  4:
        case  5:
        case  6:
        case  7:
        case  8:
        case  9:
        case 16 :
        case 17 :
        case 18 :
        case 19 :
        case 20 :
        case 21 :
                  slice_segment_layer(); break;
        case 32 : video_parameter_set(); break;
        case 33 : seq_parameter_set(); break;
        case 34 : pic_parameter_set(); break;
        case 35 : access_unit_delimiter(); break;
        case 36 : end_of_seq(); break;
        case 37 : end_of_bitstream(); break;
        case 38 : filler_data(); break;
        case 39 :
        case 40 :
                  sei(); break;
        default :
                  Skip_XX(Element_Size-Element_Offset, "Data");
                  if (Element_Code>=48)
                      Trusted_IsNot("Unspecified");
    }

    if (!ThreeByte_List.empty())
    {
        //We must change the buffer for keeping out
        Element_Size=Save_Element_Size;
        File_Offset=Save_File_Offset;
        Buffer_Offset=Save_Buffer_Offset;
        delete[] Buffer; Buffer=Save_Buffer;
        Buffer_3Bytes=NULL; //Same as Buffer...
        Element_Offset+=ThreeByte_List.size();
    }

    #if MEDIAINFO_DEMUX
        if (Demux_Transcode_Iso14496_15_to_AnnexB)
        {
            if (Element_Code==32)
            {
                std::vector<video_parameter_set_struct*>::iterator Data_Item=video_parameter_sets.begin();
                if (Data_Item!=video_parameter_sets.end() && (*Data_Item))
                {
                    delete[] (*Data_Item)->AnnexB_Buffer;
                    (*Data_Item)->AnnexB_Buffer_Size=(size_t)(Element_Size+5);
                    (*Data_Item)->AnnexB_Buffer=new int8u[(*Data_Item)->AnnexB_Buffer_Size];
                    (*Data_Item)->AnnexB_Buffer[0]=0x00;
                    (*Data_Item)->AnnexB_Buffer[1]=0x00;
                    (*Data_Item)->AnnexB_Buffer[2]=0x01;
                    (*Data_Item)->AnnexB_Buffer[3]=Buffer[Buffer_Offset-2];
                    (*Data_Item)->AnnexB_Buffer[4]=Buffer[Buffer_Offset-1];
                    std::memcpy((*Data_Item)->AnnexB_Buffer+5, Buffer+Buffer_Offset, (size_t)Element_Size);
                }
            }
            if (Element_Code==33)
            {
                std::vector<seq_parameter_set_struct*>::iterator Data_Item=seq_parameter_sets.begin();
                if (Data_Item!=seq_parameter_sets.end() && (*Data_Item))
                {
                    delete[] (*Data_Item)->AnnexB_Buffer;
                    (*Data_Item)->AnnexB_Buffer_Size=(size_t)(Element_Size+5);
                    (*Data_Item)->AnnexB_Buffer=new int8u[(*Data_Item)->AnnexB_Buffer_Size];
                    (*Data_Item)->AnnexB_Buffer[0]=0x00;
                    (*Data_Item)->AnnexB_Buffer[1]=0x00;
                    (*Data_Item)->AnnexB_Buffer[2]=0x01;
                    (*Data_Item)->AnnexB_Buffer[3]=Buffer[Buffer_Offset-2];
                    (*Data_Item)->AnnexB_Buffer[4]=Buffer[Buffer_Offset-1];
                    std::memcpy((*Data_Item)->AnnexB_Buffer+5, Buffer+Buffer_Offset, (size_t)Element_Size);
                }
            }
            if (Element_Code==34)
            {
                std::vector<pic_parameter_set_struct*>::iterator Data_Item=pic_parameter_sets.begin();
                if (Data_Item!=pic_parameter_sets.end() && (*Data_Item))
                {
                    delete[] (*Data_Item)->AnnexB_Buffer;
                    (*Data_Item)->AnnexB_Buffer_Size=(size_t)(Element_Size+5);
                    (*Data_Item)->AnnexB_Buffer=new int8u[(*Data_Item)->AnnexB_Buffer_Size];
                    (*Data_Item)->AnnexB_Buffer[0]=0x00;
                    (*Data_Item)->AnnexB_Buffer[1]=0x00;
                    (*Data_Item)->AnnexB_Buffer[2]=0x01;
                    (*Data_Item)->AnnexB_Buffer[3]=Buffer[Buffer_Offset-2];
                    (*Data_Item)->AnnexB_Buffer[4]=Buffer[Buffer_Offset-1];
                    std::memcpy((*Data_Item)->AnnexB_Buffer+5, Buffer+Buffer_Offset, (size_t)Element_Size);
                }
            }
        }
    #endif //MEDIAINFO_DEMUX

    //Trailing zeroes
    Element_Size=Element_Size_SaveBeforeZeroes;
}

//***************************************************************************
// Elements
//***************************************************************************

//---------------------------------------------------------------------------
// Packets
void File_Hevc::slice_segment_layer()
{
    #if MEDIAINFO_TRACE
        Element_Name("slice_segment_layer");
        switch (Element_Code)
        {
            case 0 :
            case 1 : break;
            case 2 :
            case 3 : Element_Info("TSA"); break;
            case 4:
            case 5: Element_Info("STSA"); break;
            case 6:
            case 7: Element_Info("RADL"); break;
            case 8:
            case 9: Element_Info("RASL"); break;
            case 16 :
            case 17 :
            case 18 : Element_Info("BLA"); break;
            case 19 :
            case 20 : Element_Info("IDR"); break;
            case 21 : Element_Info("CRA"); break;
            default: ;
        }
    #endif //MEDIAINFO_TRACE

    //Parsing
    RapPicFlag=Element_Code>=16 && Element_Code<=23;
    BS_Begin();
    slice_segment_header();
    BS_End();
    Skip_XX(Element_Size-Element_Offset,                        "(ToDo)");

    FILLING_BEGIN();
        if (slice_pic_parameter_set_id==(int32u)-1)
            return;

        //Count of I-Frames
        if (first_slice_segment_in_pic_flag && (Element_Code==19 || Element_Code==20))
            IFrame_Count++;

        if (first_slice_segment_in_pic_flag)
        {
            //Frame_Count
            Frame_Count++;
            if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1)
                Frame_Count_NotParsedIncluded++;
            Frame_Count_InThisBlock++;

            //Filling only if not already done
            if (Frame_Count==1 && !Status[IsAccepted])
                Accept("HEVC");
            if (!Status[IsFilled])
            {
                if (IFrame_Count>=8)
                    Frame_Count_Valid=Frame_Count; //We have enough frames
                if (Frame_Count>=Frame_Count_Valid)
                {
                    Fill("HEVC");
                    if (!IsSub && Config->ParseSpeed<1.0)
                        Finish("HEVC");
                }
            }
        }
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "32"
void File_Hevc::video_parameter_set()
{
    Element_Name("video_parameter_set");

    //Parsing
    int32u  vps_num_layer_sets_minus1;
    int8u   vps_video_parameter_set_id, vps_max_sub_layers_minus1, vps_max_layer_id;
    bool    vps_temporal_id_nesting_flag, vps_sub_layer_ordering_info_present_flag;
    BS_Begin();
    Get_S1 (4,  vps_video_parameter_set_id,                     "vps_video_parameter_set_id");
    if (MustParse_VPS_SPS_PPS_FromFlv)
    {
        BS_End();
        Skip_XX(Element_Size-Element_Offset,                     "Data");

        //Creating Data
        if (vps_video_parameter_set_id>=video_parameter_sets.size())
            video_parameter_sets.resize(vps_video_parameter_set_id+1);
        std::vector<video_parameter_set_struct*>::iterator Data_Item=video_parameter_sets.begin()+vps_video_parameter_set_id;
        delete *Data_Item; *Data_Item=new video_parameter_set_struct(
                                                                        0 //TODO: check which code is intended here
                                                                    );

        //NextCode
        NextCode_Clear();
        NextCode_Add(33);

        //Autorisation of other streams
        Streams[33].Searching_Payload=true; //seq_parameter_set
        Streams[36].Searching_Payload=true; //end_of_seq
        Streams[37].Searching_Payload=true; //end_of_bitstream
        Streams[38].Searching_Payload=true; //filler_data

        return;
    }
    Skip_S1(2,                                                  "vps_reserved_three_2bits");
    Skip_S1(6,                                                  "vps_reserved_zero_6bits");
    Get_S1 (3,  vps_max_sub_layers_minus1,                      "vps_max_sub_layers_minus1");
    if (vps_max_sub_layers_minus1>6)
    {
        Trusted_IsNot("vps_max_sub_layers_minus1 not valid");
        BS_End();
        return; //Problem, not valid
    }
    Get_SB (    vps_temporal_id_nesting_flag,                   "vps_temporal_id_nesting_flag");
    //if (vps_max_sub_layers_minus1==0 && !vps_temporal_id_nesting_flag)
    //{
    //    Trusted_IsNot("vps_temporal_id_nesting_flag not valid");
    //    BS_End();
    //    return; //Problem, not valid
    //}
    Skip_S2(16,                                                 "vps_reserved_0xffff_16bits");
    profile_tier_level(vps_max_sub_layers_minus1);
    Get_SB (   vps_sub_layer_ordering_info_present_flag,        "vps_sub_layer_ordering_info_present_flag");
    for (int32u SubLayerPos=(vps_sub_layer_ordering_info_present_flag?0:vps_max_sub_layers_minus1); SubLayerPos<=vps_max_sub_layers_minus1; SubLayerPos++)
    {
        Element_Begin1("SubLayer");
        Skip_UE(                                                "vps_max_dec_pic_buffering_minus1");
        Skip_UE(                                                "vps_max_num_reorder_pics");
        Skip_UE(                                                "vps_max_latency_increase_plus1");
        Element_End0();
    }
    Get_S1 ( 6, vps_max_layer_id,                               "vps_max_layer_id");
    Get_UE (    vps_num_layer_sets_minus1,                      "vps_num_layer_sets_minus1");
    if (vps_num_layer_sets_minus1>=1024)
    {
        Trusted_IsNot("vps_num_layer_sets_minus1 not valid");
        BS_End();
        return; //Problem, not valid
    }
    for (int32u LayerSetPos=1; LayerSetPos<=vps_num_layer_sets_minus1; LayerSetPos++)
        for (int8u LayerId=0; LayerId<=vps_max_layer_id; LayerId++)
            Skip_SB(                                            "layer_id_included_flag");
    TEST_SB_SKIP(                                               "vps_timing_info_present_flag");
        int32u vps_time_scale, vps_num_hrd_parameters;
        Skip_S4(32,                                             "vps_num_units_in_tick");
        Get_S4 (32, vps_time_scale,                             "vps_time_scale");
        if (vps_time_scale==0)
        {
            Trusted_IsNot("vps_time_scale not valid");
            Element_End0();
            BS_End();
            return; //Problem, not valid
        }
        TEST_SB_SKIP(                                           "vps_poc_proportional_to_timing_flag");
            Skip_UE(                                            "vps_num_ticks_poc_diff_one_minus1");
        TEST_SB_END();
        Get_UE (    vps_num_hrd_parameters,                     "vps_num_hrd_parameters");
        if (vps_num_hrd_parameters>1024)
        {
            Trusted_IsNot("vps_num_hrd_parameters not valid");
            vps_num_hrd_parameters=0;
        }
        for (int32u HrdPos=0; HrdPos<vps_num_hrd_parameters; HrdPos++)
        {
            seq_parameter_set_struct::vui_parameters_struct::xxl_common *xxL_Common=NULL;
            seq_parameter_set_struct::vui_parameters_struct::xxl *NAL=NULL, *VCL=NULL;
            int32u hrd_layer_set_idx;
            bool   cprms_present_flag;
            Get_UE (   hrd_layer_set_idx,                       "hrd_layer_set_idx");
            if (hrd_layer_set_idx>=1024)
                Trusted_IsNot("hrd_layer_set_idx not valid");
            if (HrdPos)
                Get_SB (cprms_present_flag,                     "cprms_present_flag");
            else
                cprms_present_flag=true;
            hrd_parameters(cprms_present_flag, vps_max_sub_layers_minus1, xxL_Common, NAL, VCL);
            delete xxL_Common; xxL_Common=NULL; //TODO: keep VPS hrd_parameters
            delete NAL; NAL=NULL;
            delete VCL; VCL=NULL;
        }
    TEST_SB_END();
    TESTELSE_SB_SKIP(                                           "vps_extension_flag");
        Skip_BS(Data_BS_Remain(),                               "vps_extension_data");
        Trusted_IsNot("(Not supported)"); // Should be skipped, but the detection is too sensible in that case, do not remove it until the detection is adapted
    TESTELSE_SB_ELSE(                                           "vps_extension_flag");
        Mark_1();
        while (Data_BS_Remain())
            Mark_0();
    TESTELSE_SB_END();
    BS_End();

    FILLING_BEGIN_PRECISE();
        //Creating Data
        if (vps_video_parameter_set_id>=video_parameter_sets.size())
            video_parameter_sets.resize(vps_video_parameter_set_id+1);
        std::vector<video_parameter_set_struct*>::iterator Data_Item=video_parameter_sets.begin()+vps_video_parameter_set_id;
        delete *Data_Item; *Data_Item=new video_parameter_set_struct(
                                                                        vps_max_sub_layers_minus1
                                                                    );

        //NextCode
        NextCode_Clear();
        NextCode_Add(33);

        //Autorisation of other streams
        Streams[33].Searching_Payload=true; //seq_parameter_set
        Streams[36].Searching_Payload=true; //end_of_seq
        Streams[37].Searching_Payload=true; //end_of_bitstream
        Streams[38].Searching_Payload=true; //filler_data
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "33"
void File_Hevc::seq_parameter_set()
{
    Element_Name("seq_parameter_set");

    //Parsing
    seq_parameter_set_struct::vui_parameters_struct* vui_parameters_Item=NULL;
    int32u  sps_seq_parameter_set_id, chroma_format_idc, pic_width_in_luma_samples, pic_height_in_luma_samples, bit_depth_luma_minus8, bit_depth_chroma_minus8, log2_max_pic_order_cnt_lsb_minus4, num_short_term_ref_pic_sets;
    int32u  conf_win_left_offset=0, conf_win_right_offset=0, conf_win_top_offset=0, conf_win_bottom_offset=0;
    int8u   video_parameter_set_id, max_sub_layers_minus1;
    bool    separate_colour_plane_flag=false, sps_sub_layer_ordering_info_present_flag;
    BS_Begin();
    Get_S1 (4, video_parameter_set_id,                          "sps_video_parameter_set_id");
    std::vector<video_parameter_set_struct*>::iterator video_parameter_set_Item;
    if (video_parameter_set_id >= video_parameter_sets.size() || (*(video_parameter_set_Item = video_parameter_sets.begin() + video_parameter_set_id)) == NULL)
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (video_parameter_set is missing)");
        BS_End();
        return;
    }
    Get_S1 (3, max_sub_layers_minus1,                           "sps_max_sub_layers_minus1");
    Skip_SB(                                                    "sps_temporal_id_nesting_flag");
    profile_tier_level(max_sub_layers_minus1);
    Get_UE (   sps_seq_parameter_set_id,                        "sps_seq_parameter_set_id");
    if (MustParse_VPS_SPS_PPS_FromFlv)
    {
        BS_End();
        Skip_XX(Element_Size-Element_Offset,                     "Data");

        //Creating Data
        if (sps_seq_parameter_set_id>=seq_parameter_sets.size())
            seq_parameter_sets.resize(sps_seq_parameter_set_id+1);
        std::vector<seq_parameter_set_struct*>::iterator Data_Item=seq_parameter_sets.begin()+sps_seq_parameter_set_id;
        delete *Data_Item; *Data_Item=new seq_parameter_set_struct(
                                                                    NULL, //TODO: check which code is intended here
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    0,
                                                                    false,
                                                                    false,
                                                                    false,
                                                                    false
                                                                    );

        //NextCode
        NextCode_Clear();
        NextCode_Add(34);

        //Autorisation of other streams
        Streams[34].Searching_Payload=true; //pic_parameter_set

        return;
    }
    Get_UE (   chroma_format_idc,                               "chroma_format_idc"); Param_Info1(Hevc_chroma_format_idc((int8u)chroma_format_idc));
    if (chroma_format_idc>=4)
    {
        Trusted_IsNot("chroma_format_idc not valid");
        BS_End();
        return; //Problem, not valid
    }
    if (chroma_format_idc==3)
        Get_SB (separate_colour_plane_flag,                     "separate_colour_plane_flag");
    Get_UE (    pic_width_in_luma_samples,                      "pic_width_in_luma_samples");
    Get_UE (    pic_height_in_luma_samples,                     "pic_height_in_luma_samples");
    TEST_SB_SKIP(                                               "conformance_window_flag");
        Get_UE (conf_win_left_offset,                           "conf_win_left_offset");
        Get_UE (conf_win_right_offset,                          "conf_win_right_offset");
        Get_UE (conf_win_top_offset,                            "conf_win_top_offset");
        Get_UE (conf_win_bottom_offset,                         "conf_win_bottom_offset");
    TEST_SB_END();
    Get_UE (   bit_depth_luma_minus8,                           "bit_depth_luma_minus8");
    if (bit_depth_luma_minus8>6)
    {
        Trusted_IsNot("bit_depth_luma_minus8 not valid");
        return; //Problem, not valid
    }
    Get_UE (   bit_depth_chroma_minus8,                         "bit_depth_chroma_minus8");
    if (bit_depth_chroma_minus8>6)
    {
        Trusted_IsNot("bit_depth_chroma_minus8 not valid");
        return; //Problem, not valid
    }
    Get_UE (   log2_max_pic_order_cnt_lsb_minus4,               "log2_max_pic_order_cnt_lsb_minus4");
    if (log2_max_pic_order_cnt_lsb_minus4>12)
    {
        Trusted_IsNot("log2_max_pic_order_cnt_lsb_minus4 not valid");
        return; //Problem, not valid
    }
    Get_SB (   sps_sub_layer_ordering_info_present_flag,        "sps_sub_layer_ordering_info_present_flag");
    for (int32u SubLayerPos = (sps_sub_layer_ordering_info_present_flag ? 0 : max_sub_layers_minus1); SubLayerPos <= max_sub_layers_minus1; SubLayerPos++)
    {
        Element_Begin1("SubLayer");
        Skip_UE(                                                "sps_max_dec_pic_buffering_minus1");
        Skip_UE(                                                "sps_max_num_reorder_pics");
        Skip_UE(                                                "sps_max_latency_increase_plus1");
        Element_End0();
    }
    Skip_UE(                                                    "log2_min_luma_coding_block_size_minus3");
    Skip_UE(                                                    "log2_diff_max_min_luma_coding_block_size");
    Skip_UE(                                                    "log2_min_transform_block_size_minus2");
    Skip_UE(                                                    "log2_diff_max_min_transform_block_size");
    Skip_UE(                                                    "max_transform_hierarchy_depth_inter");
    Skip_UE(                                                    "max_transform_hierarchy_depth_intra");
    TEST_SB_SKIP(                                               "scaling_list_enabled_flag");
        TEST_SB_SKIP(                                           "sps_scaling_list_data_present_flag");
            scaling_list_data();
        TEST_SB_END();
    TEST_SB_END();
    Skip_SB(                                                    "amp_enabled_flag");
    Skip_SB(                                                    "sample_adaptive_offset_enabled_flag");
    TEST_SB_SKIP(                                               "pcm_enabled_flag");
        Element_Begin1("pcm");
        Skip_S1(4,                                              "pcm_sample_bit_depth_luma_minus1");
        Skip_S1(4,                                              "pcm_sample_bit_depth_chroma_minus1");
        Skip_UE(                                                "log2_min_pcm_luma_coding_block_size_minus3");
        Skip_UE(                                                "log2_diff_max_min_pcm_luma_coding_block_size");
        Skip_SB(                                                "pcm_loop_filter_disabled_flag");
        Element_End0();
    TEST_SB_END();
    Get_UE (   num_short_term_ref_pic_sets,                     "num_short_term_ref_pic_sets");
    if (num_short_term_ref_pic_sets>64)
    {
        BS_End();
        Trusted_IsNot("num_short_term_ref_pic_sets not valid");
        return; //Problem, not valid
    }
    short_term_ref_pic_sets((int8u)num_short_term_ref_pic_sets);
    TEST_SB_SKIP(                                               "long_term_ref_pics_present_flag");
        Element_Begin1("long_term_ref_pics");
        int32u num_long_term_ref_pics_sps;
        Get_UE (num_long_term_ref_pics_sps,                     "num_long_term_ref_pics_sps");
        for (int32u long_term_ref_pics_sps_pos=0; long_term_ref_pics_sps_pos<num_long_term_ref_pics_sps; long_term_ref_pics_sps_pos++)
        {
            Skip_BS(log2_max_pic_order_cnt_lsb_minus4+4,        "lt_ref_pic_poc_lsb_sps");
            Skip_SB(                                            "used_by_curr_pic_lt_sps_flag");
        }
        Element_End0();
    TEST_SB_END();
    Skip_SB(                                                    "sps_temporal_mvp_enabled_flag");
    Skip_SB(                                                    "strong_intra_smoothing_enabled_flag");
    TEST_SB_SKIP(                                               "vui_parameters_present_flag");
        vui_parameters(video_parameter_set_Item, vui_parameters_Item);
    TEST_SB_END();
    TESTELSE_SB_SKIP(                                           "sps_extension_flag");
        Skip_BS(Data_BS_Remain(),                               "sps_extension_data");
        Trusted_IsNot("(Not supported)"); // Should be skipped, but the detection is too sensible in that case, do not remove it until the detection is adapted
    TESTELSE_SB_ELSE(                                           "sps_extension_flag");
        Mark_1();
        while (Data_BS_Remain())
            Mark_0();
    TESTELSE_SB_END();
    BS_End();

    FILLING_BEGIN_PRECISE();
        //Creating Data
        if (sps_seq_parameter_set_id>=seq_parameter_sets.size())
            seq_parameter_sets.resize(sps_seq_parameter_set_id+1);
        std::vector<seq_parameter_set_struct*>::iterator Data_Item=seq_parameter_sets.begin()+sps_seq_parameter_set_id;
        delete *Data_Item; *Data_Item=new seq_parameter_set_struct(
                                                                    vui_parameters_Item,
                                                                    profile_space,
                                                                    tier_flag,
                                                                    profile_idc,
                                                                    level_idc,
                                                                    pic_width_in_luma_samples,
                                                                    pic_height_in_luma_samples,
                                                                    conf_win_left_offset,
                                                                    conf_win_right_offset,
                                                                    conf_win_top_offset,
                                                                    conf_win_bottom_offset,
                                                                    (int8u)video_parameter_set_id,
                                                                    (int8u)chroma_format_idc,
                                                                    separate_colour_plane_flag,
                                                                    (int8u)log2_max_pic_order_cnt_lsb_minus4,
                                                                    (int8u)bit_depth_luma_minus8,
                                                                    (int8u)bit_depth_chroma_minus8,
                                                                    general_progressive_source_flag,
                                                                    general_interlaced_source_flag,
                                                                    general_frame_only_constraint_flag,
                                                                    general_max_8bit_constraint_flag
                                                                  );

        //NextCode
        NextCode_Clear();
        NextCode_Add(34);

        //Autorisation of other streams
        Streams[34].Searching_Payload=true; //pic_parameter_set
    FILLING_ELSE();
        delete vui_parameters_Item; //vui_parameters_Item=NULL;
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "34"
void File_Hevc::pic_parameter_set()
{
    Element_Name("pic_parameter_set");

    //Parsing
    int32u  pps_pic_parameter_set_id, pps_seq_parameter_set_id, num_ref_idx_l0_default_active_minus1, num_ref_idx_l1_default_active_minus1;
    int8u   num_extra_slice_header_bits;
    bool    tiles_enabled_flag, dependent_slice_segments_enabled_flag;
    BS_Begin();
    Get_UE (    pps_pic_parameter_set_id,                       "pps_pic_parameter_set_id");
    if (pps_pic_parameter_set_id>=64)
    {
        Trusted_IsNot("pic_parameter_set_id not valid");
        BS_End();
        return; //Problem, not valid
    }
    Get_UE (    pps_seq_parameter_set_id,                       "pps_seq_parameter_set_id");
    if (pps_seq_parameter_set_id>=16)
    {
        Trusted_IsNot("seq_parameter_set_id not valid");
        return; //Problem, not valid
    }
    //std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
    if (pps_seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_sets.begin()+pps_seq_parameter_set_id))==NULL) //(seq_parameter_set_Item=seq_parameter_sets.begin()+pps_seq_parameter_set_id) not usd for the moment
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (seq_parameter_set is missing)");
        BS_End();
        return;
    }
    if (MustParse_VPS_SPS_PPS_FromFlv)
    {
        BS_End();
        Skip_XX(Element_Size-Element_Offset,                     "Data");

        //Filling
        if (pps_pic_parameter_set_id>=pic_parameter_sets.size())
            pic_parameter_sets.resize(pps_pic_parameter_set_id+1);
        std::vector<pic_parameter_set_struct*>::iterator pic_parameter_sets_Item=pic_parameter_sets.begin()+pps_pic_parameter_set_id;
        delete *pic_parameter_sets_Item; *pic_parameter_sets_Item=new pic_parameter_set_struct(
                                                                                                    0,
                                                                                                    0,
                                                                                                    0,
                                                                                                    0,
                                                                                                    false
                                                                                              );

        //NextCode
        NextCode_Clear();

        //Autorisation of other streams
        Streams[ 0].Searching_Payload=true; //slice_segment_layer
        Streams[ 1].Searching_Payload=true; //slice_segment_layer
        Streams[ 2].Searching_Payload=true; //slice_segment_layer
        Streams[ 3].Searching_Payload=true; //slice_segment_layer
        Streams[ 4].Searching_Payload=true; //slice_layer
        Streams[ 5].Searching_Payload=true; //slice_layer
        Streams[ 6].Searching_Payload=true; //slice_layer
        Streams[ 7].Searching_Payload=true; //slice_layer
        Streams[ 8].Searching_Payload=true; //slice_layer
        Streams[ 9].Searching_Payload=true; //slice_layer
        Streams[16].Searching_Payload=true; //slice_segment_layer
        Streams[17].Searching_Payload=true; //slice_segment_layer
        Streams[18].Searching_Payload=true; //slice_segment_layer
        Streams[19].Searching_Payload=true; //slice_segment_layer
        Streams[20].Searching_Payload=true; //slice_segment_layer
        Streams[21].Searching_Payload=true; //slice_segment_layer

        return;
    }
    Get_SB (    dependent_slice_segments_enabled_flag,          "dependent_slice_segments_enabled_flag");
    Skip_SB(                                                    "output_flag_present_flag");
    Get_S1 (3,  num_extra_slice_header_bits,                    "num_extra_slice_header_bits");
    Skip_SB(                                                    "sign_data_hiding_flag");
    Skip_SB(                                                    "cabac_init_present_flag");
    Get_UE (    num_ref_idx_l0_default_active_minus1,           "num_ref_idx_l0_default_active_minus1");
    Get_UE (    num_ref_idx_l1_default_active_minus1,           "num_ref_idx_l1_default_active_minus1");
    Skip_SE(                                                    "init_qp_minus26");
    Skip_SB(                                                    "constrained_intra_pred_flag");
    Skip_SB(                                                    "transform_skip_enabled_flag");
    TEST_SB_SKIP(                                               "cu_qp_delta_enabled_flag");
        Skip_UE(                                                "diff_cu_qp_delta_depth");
    TEST_SB_END();
    Skip_SE(                                                    "pps_cb_qp_offset");
    Skip_SE(                                                    "pps_cr_qp_offset");
    Skip_SB(                                                    "pps_slice_chroma_qp_offsets_present_flag");
    Skip_SB(                                                    "weighted_pred_flag");
    Skip_SB(                                                    "weighted_bipred_flag");
    Skip_SB(                                                    "transquant_bypass_enable_flag");
    Get_SB (    tiles_enabled_flag,                             "tiles_enabled_flag");
    Skip_SB(                                                    "entropy_coding_sync_enabled_flag");
    if (tiles_enabled_flag)
    {
        Element_Begin1("tiles");
        int32u  num_tile_columns_minus1, num_tile_rows_minus1;
        bool    uniform_spacing_flag;
        Get_UE (    num_tile_columns_minus1,                    "num_tile_columns_minus1");
        Get_UE (    num_tile_rows_minus1,                       "num_tile_rows_minus1");
        Get_SB (    uniform_spacing_flag,                       "uniform_spacing_flag");
        if (!uniform_spacing_flag)
        {
            for (int32u tile_pos=0; tile_pos<num_tile_columns_minus1; tile_pos++)
               Skip_UE(                                         "column_width_minus1");
            for (int32u tile_pos=0; tile_pos<num_tile_rows_minus1; tile_pos++)
               Skip_UE(                                         "row_height_minus1");
        }
        Skip_SB(                                                "loop_filter_across_tiles_enabled_flag");
        Element_End0();
    }
    Skip_SB(                                                    "pps_loop_filter_across_slices_enabled_flag");
    TEST_SB_SKIP(                                               "deblocking_filter_control_present_flag");
        bool pps_disable_deblocking_filter_flag;
        Skip_SB(                                                "deblocking_filter_override_enabled_flag");
        Get_SB (    pps_disable_deblocking_filter_flag,         "pps_disable_deblocking_filter_flag");
        if (!pps_disable_deblocking_filter_flag)
        {
           Skip_SE(                                             "pps_beta_offset_div2");
           Skip_SE(                                             "pps_tc_offset_div2");
        }
    TEST_SB_END();
    TEST_SB_SKIP(                                               "pps_scaling_list_data_present_flag ");
        scaling_list_data();
    TEST_SB_END();
    Skip_SB(                                                    "lists_modification_present_flag");
    Skip_UE(                                                    "log2_parallel_merge_level_minus2");
    Skip_SB(                                                    "slice_segment_header_extension_present_flag");
    TESTELSE_SB_SKIP(                                           "pps_extension_flag");
        Skip_BS(Data_BS_Remain(),                               "pps_extension_data");
        Trusted_IsNot("(Not supported)"); // Should be skipped, but the detection is too sensible in that case, do not remove it until the detection is adapted
    TESTELSE_SB_ELSE(                                           "pps_extension_flag");
        Mark_1();
        while (Data_BS_Remain())
            Mark_0();
    TESTELSE_SB_END();
    BS_End();

    FILLING_BEGIN_PRECISE();
        //NextCode
        //NextCode_Clear();
        //NextCode_Add(0x05);
        //NextCode_Add(0x06);

        //Filling
        if (pps_pic_parameter_set_id>=pic_parameter_sets.size())
            pic_parameter_sets.resize(pps_pic_parameter_set_id+1);
        std::vector<pic_parameter_set_struct*>::iterator pic_parameter_sets_Item=pic_parameter_sets.begin()+pps_pic_parameter_set_id;
        delete *pic_parameter_sets_Item; *pic_parameter_sets_Item = new pic_parameter_set_struct(
                                                                                                    (int8u)pps_seq_parameter_set_id,
                                                                                                    (int8u)num_ref_idx_l0_default_active_minus1,
                                                                                                    (int8u)num_ref_idx_l1_default_active_minus1,
                                                                                                    num_extra_slice_header_bits,
                                                                                                    dependent_slice_segments_enabled_flag
                                                                                                );
        //Autorisation of other streams
        //if (!seq_parameter_sets.empty())
        //{
        //    for (int8u Pos=0x01; Pos<=0x06; Pos++)
        //    {
        //        Streams[Pos].Searching_Payload=true; //Coded slice...
        //        if (Streams[0x08].ShouldDuplicate)
        //            Streams[Pos].ShouldDuplicate=true;
        //    }
        //}

        //NextCode
        NextCode_Clear();

        //Autorisation of other streams
        Streams[ 0].Searching_Payload=true; //slice_segment_layer
        Streams[ 1].Searching_Payload=true; //slice_segment_layer
        Streams[ 2].Searching_Payload=true; //slice_segment_layer
        Streams[ 3].Searching_Payload=true; //slice_segment_layer
        Streams[ 4].Searching_Payload=true; //slice_layer
        Streams[ 5].Searching_Payload=true; //slice_layer
        Streams[ 6].Searching_Payload=true; //slice_layer
        Streams[ 7].Searching_Payload=true; //slice_layer
        Streams[ 8].Searching_Payload=true; //slice_layer
        Streams[ 9].Searching_Payload=true; //slice_layer
        Streams[16].Searching_Payload=true; //slice_segment_layer
        Streams[17].Searching_Payload=true; //slice_segment_layer
        Streams[18].Searching_Payload=true; //slice_segment_layer
        Streams[19].Searching_Payload=true; //slice_segment_layer
        Streams[20].Searching_Payload=true; //slice_segment_layer
        Streams[21].Searching_Payload=true; //slice_segment_layer
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "35"
void File_Hevc::access_unit_delimiter()
{
    Element_Name("access_unit_delimiter");

    //Parsing
    BS_Begin();
    Info_S1( 3, pic_type,                                   "pic_type"); Param_Info1(Hevc_pic_type[pic_type]);
    BS_End();
}

//---------------------------------------------------------------------------
// Packet "36"
void File_Hevc::end_of_seq()
{
    Element_Name("end_of_seq");
}

//---------------------------------------------------------------------------
// Packet "37"
void File_Hevc::end_of_bitstream()
{
    Element_Name("end_of_bitstream");
}

//---------------------------------------------------------------------------
// Packet "38"
void File_Hevc::filler_data()
{
    Element_Name("filler_data");

    //Parsing
    Skip_XX(Element_Size,                                       "ff_bytes");
}

//---------------------------------------------------------------------------
// Packet "39" or "40
void File_Hevc::sei()
{
    Element_Name("sei");

    //Parsing
    int32u seq_parameter_set_id=(int32u)-1;
    while(Element_Offset+1<Element_Size)
    {
        Element_Begin1("sei message");
            sei_message(seq_parameter_set_id);
        Element_End0();
    }
    BS_Begin();
    if (!Peek_SB())
        Fill(Stream_Video, 0, "SEI_rbsp_stop_one_bit", "Missing", Unlimited, true, true);
    Mark_1(                                                     );
    BS_End();
}

//---------------------------------------------------------------------------
void File_Hevc::sei_message(int32u &seq_parameter_set_id)
{
    //Parsing
    int32u  payloadType=0, payloadSize=0;
    int8u   payload_type_byte, payload_size_byte;
    Element_Begin1("sei message header");
        do
        {
            Get_B1 (payload_type_byte,                          "payload_type_byte");
            payloadType+=payload_type_byte;
        }
        while(payload_type_byte==0xFF);
        do
        {
            Get_B1 (payload_size_byte,                          "payload_size_byte");
            payloadSize+=payload_size_byte;
        }
        while(payload_size_byte==0xFF);
    Element_End0();

    //Manage buggy files not having final bit stop
    const int8u* Buffer_Buggy;
    int64u Buffer_Offset_Buggy, Element_Size_Buggy;
    if (Element_Offset+payloadSize>Element_Size)
    {
        Buffer_Buggy=Buffer;
        Buffer_Offset_Buggy=Buffer_Offset;
        Element_Size_Buggy=Element_Size;
        Element_Size=Element_Offset+payloadSize;
        Buffer=new int8u[(size_t)Element_Size];
        Buffer_Offset=0;
        memcpy((void*)Buffer, Buffer_Buggy+Buffer_Offset, (size_t)Element_Size_Buggy);
        memset((void*)(Buffer+(size_t)Element_Size_Buggy), 0x00, (size_t)(Element_Size-Element_Size_Buggy)); //Last 0x00 bytes are discarded, we recreate them
    }
    else
        Buffer_Buggy=NULL;

    int64u Element_Offset_Save=Element_Offset+payloadSize;
    if (Element_Offset_Save>Element_Size)
    {
        Trusted_IsNot("Wrong size");
        Skip_XX(Element_Size-Element_Offset,                    "unknown");
        return;
    }
    int64u Element_Size_Save=Element_Size;
    Element_Size=Element_Offset_Save;
    switch (payloadType)
    {
        case   0 :   sei_message_buffering_period(seq_parameter_set_id, payloadSize); break;
        case   1 :   sei_message_pic_timing(seq_parameter_set_id, payloadSize); break;
        case   4 :   sei_message_user_data_registered_itu_t_t35(); break;
        case   5 :   sei_message_user_data_unregistered(payloadSize); break;
        case   6 :   sei_message_recovery_point(); break;
        //case  32 :   sei_message_mainconcept(payloadSize); break;
        case 129 :   sei_message_active_parameter_sets(); break;
        case 132 :   sei_message_decoded_picture_hash(payloadSize); break;
        case 137 :   sei_message_mastering_display_colour_volume(); break;
        case 144 :   sei_message_light_level(); break;
        case 147 :   sei_alternative_transfer_characteristics(); break;
        default :
                    Element_Info1("unknown");
                    Skip_XX(payloadSize,                        "data");
    }
    Element_Offset=Element_Offset_Save; //Positionning in the right place.
    Element_Size=Element_Size_Save; //Positionning in the right place.

    //Manage buggy files not having final bit stop
    if (Buffer_Buggy)
    {
        delete[] Buffer;
        Buffer=Buffer_Buggy;
        Buffer_Offset=Buffer_Offset_Buggy;
        Element_Size=Element_Size_Buggy;
    }
}

//---------------------------------------------------------------------------
// SEI - 0
void File_Hevc::sei_message_buffering_period(int32u &seq_parameter_set_id, int32u payloadSize)
{
    Element_Info1("buffering_period");

    //Parsing
    if (Element_Offset==Element_Size)
        return; //Nothing to do
    BS_Begin();
    Get_UE (seq_parameter_set_id,                               "seq_parameter_set_id");
    std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
    if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (seq_parameter_set is missing)");
        BS_End();
        return;
    }
    bool sub_pic_hrd_params_present_flag=false; //Default
    bool irap_cpb_params_present_flag=((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->xxL_Common)?(*seq_parameter_set_Item)->vui_parameters->xxL_Common->sub_pic_hrd_params_present_flag:false;
    if (!sub_pic_hrd_params_present_flag)
        Get_SB (irap_cpb_params_present_flag,                   "irap_cpb_params_present_flag");
    int8u au_cpb_removal_delay_length_minus1=((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->xxL_Common)?(*seq_parameter_set_Item)->vui_parameters->xxL_Common->au_cpb_removal_delay_length_minus1:23;
    int8u dpb_output_delay_length_minus1=((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->xxL_Common)?(*seq_parameter_set_Item)->vui_parameters->xxL_Common->dpb_output_delay_length_minus1:23;
    if (irap_cpb_params_present_flag)
    {
         Skip_S4(au_cpb_removal_delay_length_minus1+1,          "cpb_delay_offset");
         Skip_S4(dpb_output_delay_length_minus1+1,              "dpb_delay_offset");
    }
    Skip_SB(                                                    "concatenation_flag");
    Skip_S4(au_cpb_removal_delay_length_minus1+1,               "au_cpb_removal_delay_delta_minus1");
    if ((*seq_parameter_set_Item)->NalHrdBpPresentFlag())
        sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters?(*seq_parameter_set_Item)->vui_parameters->xxL_Common:NULL, irap_cpb_params_present_flag, (*seq_parameter_set_Item)->vui_parameters->NAL);
    if ((*seq_parameter_set_Item)->VclHrdBpPresentFlag())
        sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters?(*seq_parameter_set_Item)->vui_parameters->xxL_Common:NULL, irap_cpb_params_present_flag, (*seq_parameter_set_Item)->vui_parameters->VCL);
    BS_End();
}

void File_Hevc::sei_message_buffering_period_xxl(seq_parameter_set_struct::vui_parameters_struct::xxl_common* xxL_Common, bool irap_cpb_params_present_flag, seq_parameter_set_struct::vui_parameters_struct::xxl* xxl)
{
    if (xxL_Common==NULL || xxl==NULL)
    {
        //Problem?
        Skip_BS(Data_BS_Remain(),                               "Problem?");
        return;
    }
    for (int32u SchedSelIdx=0; SchedSelIdx<xxl->SchedSel.size(); SchedSelIdx++)
    {
        //Get_S4 (xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay/90, " ms");
        //Get_S4 (xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset/90, " ms");
        Info_S4 (xxL_Common->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(initial_cpb_removal_delay/90, " ms");
        Info_S4 (xxL_Common->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(initial_cpb_removal_delay_offset/90, " ms");
        if (xxL_Common->sub_pic_hrd_params_present_flag || irap_cpb_params_present_flag)
        {
            Info_S4 (xxL_Common->initial_cpb_removal_delay_length_minus1+1, initial_alt_cpb_removal_delay, "initial_alt_cpb_removal_delay"); Param_Info2(initial_alt_cpb_removal_delay/90, " ms");
            Info_S4 (xxL_Common->initial_cpb_removal_delay_length_minus1+1, initial_alt_cpb_removal_delay_offset, "initial_alt_cpb_removal_delay_offset"); Param_Info2(initial_alt_cpb_removal_delay_offset/90, " ms");
        }
    }
}

//---------------------------------------------------------------------------
// SEI - 1
void File_Hevc::sei_message_pic_timing(int32u &seq_parameter_set_id, int32u payloadSize)
{
    Element_Info1("pic_timing");

    //Testing if we can parsing it now. TODO: handle case seq_parameter_set_id is unknown (buffering of message, decoding in slice parsing)
    if (seq_parameter_set_id==(int32u)-1 && seq_parameter_sets.size()==1)
        seq_parameter_set_id=0;
    std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
    if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (seq_parameter_set is missing)");
        return;
    }

    //Parsing
    BS_Begin();
    if ((*seq_parameter_set_Item)->vui_parameters?(*seq_parameter_set_Item)->vui_parameters->frame_field_info_present_flag:((*seq_parameter_set_Item)->general_progressive_source_flag && (*seq_parameter_set_Item)->general_interlaced_source_flag))
    {
        Skip_S1(4,                                              "pic_struct");
        Skip_S1(2,                                              "source_scan_type");
        Skip_SB(                                                "duplicate_flag");
    }
    if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag())
    {
        int8u au_cpb_removal_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->xxL_Common->au_cpb_removal_delay_length_minus1;
        int8u dpb_output_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->xxL_Common->dpb_output_delay_length_minus1;
        bool  sub_pic_hrd_params_present_flag=(*seq_parameter_set_Item)->vui_parameters->xxL_Common->sub_pic_hrd_params_present_flag;
        Skip_S4(au_cpb_removal_delay_length_minus1+1,           "au_cpb_removal_delay_minus1");
        Skip_S4(dpb_output_delay_length_minus1+1,               "pic_dpb_output_delay");
        if (sub_pic_hrd_params_present_flag)
        {
            int8u dpb_output_delay_du_length_minus1=(*seq_parameter_set_Item)->vui_parameters->xxL_Common->dpb_output_delay_du_length_minus1;
            Skip_S4(dpb_output_delay_du_length_minus1+1,        "pic_dpb_output_du_delay");
        }
    }
    BS_End();
}

//---------------------------------------------------------------------------
// SEI - 4
void File_Hevc::sei_message_user_data_registered_itu_t_t35()
{
    Element_Info1("user_data_registered_itu_t_t35");

    int8u itu_t_t35_country_code;
    Get_B1(itu_t_t35_country_code,                              "itu_t_t35_country_code");

    switch (itu_t_t35_country_code)
    {
        case 0xB5:  sei_message_user_data_registered_itu_t_t35_B5(); break; // USA
    }
}

//---------------------------------------------------------------------------
// SEI - 4 - USA
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5()
{
    int16u itu_t_t35_terminal_provider_code;
    Get_B2 (itu_t_t35_terminal_provider_code,                   "itu_t_t35_terminal_provider_code");

    switch (itu_t_t35_terminal_provider_code)
    {
        case 0x003A: sei_message_user_data_registered_itu_t_t35_B5_003A(); break;
        case 0x003C: sei_message_user_data_registered_itu_t_t35_B5_003C(); break;
    }
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003A
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003A()
{
    int8u itu_t_t35_terminal_provider_oriented_code;
    Get_B1 (itu_t_t35_terminal_provider_oriented_code,          "itu_t_t35_terminal_provider_oriented_code");

    switch (itu_t_t35_terminal_provider_oriented_code)
    {
        case 0x00: sei_message_user_data_registered_itu_t_t35_B5_003A_00(); break;
        case 0x02: sei_message_user_data_registered_itu_t_t35_B5_003A_02(); break;
    }
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003A - ETSI 103-433-1
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003A_00()
{
    Element_Info1("SL-HDR message");
    BS_Begin();
    int8u sl_hdr_mode_value_minus1, sl_hdr_spec_major_version_idc, sl_hdr_spec_minor_version_idc;
    bool sl_hdr_cancel_flag;
    Get_S1 (4, sl_hdr_mode_value_minus1,                        "sl_hdr_mode_value_minus1");
    Get_S1 (4, sl_hdr_spec_major_version_idc,                   "sl_hdr_spec_major_version_idc");
    Get_S1 (7, sl_hdr_spec_minor_version_idc,                   "sl_hdr_spec_minor_version_idc");
    Get_SB (sl_hdr_cancel_flag,                                 "sl_hdr_cancel_flag");
    int8u sl_hdr_payload_mode;
    int8u k_coefficient_value[3];
    if (!sl_hdr_cancel_flag)
    {
        mastering_metadata_2086 Meta;
        bool coded_picture_info_present_flag, target_picture_info_present_flag, src_mdcv_info_present_flag;
        Skip_SB(                                                "sl_hdr_persistence_flag");
        Get_SB (coded_picture_info_present_flag,                "coded_picture_info_present_flag");
        Get_SB (target_picture_info_present_flag,               "target_picture_info_present_flag");
        Get_SB (src_mdcv_info_present_flag,                     "src_mdcv_info_present_flag");
        Skip_SB(                                                "sl_hdr_extension_present_flag");
        Get_S1 (3, sl_hdr_payload_mode,                         "sl_hdr_payload_mode");
        BS_End();
        if (coded_picture_info_present_flag)
        {
            Skip_B1(                                            "coded_picture_primaries");
            Skip_B2(                                            "coded_picture_max_luminance");
            Skip_B2(                                            "coded_picture_min_luminance");
        }
        if (target_picture_info_present_flag)
        {
            Skip_B1(                                            "target_picture_primaries");
            Skip_B2(                                            "target_picture_max_luminance");
            Skip_B2(                                            "target_picture_min_luminance");
        }
        if (src_mdcv_info_present_flag)
        {
            int16u max, min;
            for (int8u i = 0; i < 3; i++)
            {
                Get_B2 (Meta.Primaries[i*2  ],                  "src_mdcv_primaries_x");
                Get_B2 (Meta.Primaries[i*2+1],                  "src_mdcv_primaries_y");
            }
            Get_B2 (Meta.Primaries[3*2  ],                      "src_mdcv_ref_white_x");
            Get_B2 (Meta.Primaries[3*2+1],                      "src_mdcv_ref_white_y");
            Get_B2 (max,                                        "src_mdcv_max_mastering_luminance");
            Get_B2 (min,                                        "src_mdcv_min_mastering_luminance");
            Meta.Luminance[0]=min;
            Meta.Luminance[1]=((int32u)max)*10000;
        }
        for (int8u i = 0; i < 4; i++)
            Skip_B2(                                            "matrix_coefficient_value");
        for (int8u i = 0; i < 2; i++)
            Skip_B2(                                            "chroma_to_luma_injection");
        for (int8u i = 0; i < 3; i++)
            Get_B1 (k_coefficient_value[i],                     "k_coefficient_value");

        FILLING_BEGIN()
            std::map<video, Ztring>& EtsiTs103433=HDR[HdrFormat_EtsiTs103433];
            Ztring& HDR_Format=EtsiTs103433[Video_HDR_Format];
            if (HDR_Format.empty())
            {
                HDR_Format=__T("SL-HDR")+Ztring().From_Number(sl_hdr_mode_value_minus1+1);
                EtsiTs103433[Video_HDR_Format_Version]=Ztring().From_Number(sl_hdr_spec_major_version_idc)+__T('.')+Ztring().From_Number(sl_hdr_spec_minor_version_idc);
                Get_MasteringDisplayColorVolume(EtsiTs103433[Video_MasteringDisplay_ColorPrimaries], EtsiTs103433[Video_MasteringDisplay_Luminance], Meta);
                if (sl_hdr_payload_mode<2)
                    EtsiTs103433[Video_HDR_Format_Settings]=sl_hdr_payload_mode?__T("Table-based"):__T("Parameter-based");
                else
                    EtsiTs103433[Video_HDR_Format_Settings]=__T("Payload Mode ") + Ztring().From_Number(sl_hdr_payload_mode);
                if (!sl_hdr_mode_value_minus1)
                    EtsiTs103433[Video_HDR_Format_Settings]+=k_coefficient_value[0]==0 && k_coefficient_value[1]==0 && k_coefficient_value[2]==0?__T(", non-constant"):__T(", constant");

                EtsiTS103433 = __T("SL-HDR") + Ztring().From_Number(sl_hdr_mode_value_minus1 + 1);
                if (!sl_hdr_mode_value_minus1)
                    EtsiTS103433 += k_coefficient_value[0] == 0 && k_coefficient_value[1] == 0 && k_coefficient_value[2] == 0 ? __T(" NCL") : __T(" CL");
                EtsiTS103433 += __T(" specVersion=") + Ztring().From_Number(sl_hdr_spec_major_version_idc) + __T(".") + Ztring().From_Number(sl_hdr_spec_minor_version_idc);
                EtsiTS103433 += __T(" payloadMode=") + Ztring().From_Number(sl_hdr_payload_mode);
            }
        FILLING_END();
    }
    else
        BS_End();
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003A - ETSI 103-433
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003A_02()
{
    Element_Info1("SL-HDR information");
    int8u ts_103_433_spec_version;
    BS_Begin();
    Get_S1 (4, ts_103_433_spec_version,                         "ts_103_433_spec_version");
    if (ts_103_433_spec_version==0)
    {
        Skip_S1 (4,                                             "ts_103_433_payload_mode");
    }
    else if (ts_103_433_spec_version==1)
    {
        Skip_S1 (3,                                             "sl_hdr_mode_support");
    }
    else
        Skip_S1 (Data_BS_Remain(),                              "Unknown");
    BS_End();
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003C
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003C()
{
    int16u itu_t_t35_terminal_provider_oriented_code;
    Get_B2 (itu_t_t35_terminal_provider_oriented_code,          "itu_t_t35_terminal_provider_oriented_code");

    switch (itu_t_t35_terminal_provider_oriented_code)
    {
        case 0x0001: sei_message_user_data_registered_itu_t_t35_B5_003C_0001(); break;
    }
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003C - 0001
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003C_0001()
{
    int8u application_identifier;
    Get_B1 (application_identifier,                             "application_identifier");

    switch (application_identifier)
    {
        case 0x04: sei_message_user_data_registered_itu_t_t35_B5_003C_0001_04(); break;
    }
}

//---------------------------------------------------------------------------
// SEI - 4 - USA - 003C - 0001 - SMPTE ST 2094-40 (HDR10+)
void File_Hevc::sei_message_user_data_registered_itu_t_t35_B5_003C_0001_04()
{
    Element_Info1("SMPTE ST 2094 App 4");
    int8u application_version;
    bool IsHDRplus=false, tone_mapping_flag;
    Get_B1 (application_version,                                "application_version");
    if (application_version==1)
    {
        int32u targeted_system_display_maximum_luminance, maxscl[4], distribution_maxrgb_percentiles[16];
        int16u fraction_bright_pixels;
        int8u num_distribution_maxrgb_percentiles, distribution_maxrgb_percentages[16], num_windows, num_bezier_curve_anchors;
        bool targeted_system_display_actual_peak_luminance_flag, mastering_display_actual_peak_luminance_flag, color_saturation_mapping_flag;
        BS_Begin();
        Get_S1 ( 2, num_windows,                                "num_windows");

        for (int8u w=1; w<num_windows; w++)
        {
            Element_Begin1("window");
            Skip_S2(16,                                         "window_upper_left_corner_x");
            Skip_S2(16,                                         "window_upper_left_corner_y");
            Skip_S2(16,                                         "window_lower_right_corner_x");
            Skip_S2(16,                                         "window_lower_right_corner_y");
            Skip_S2(16,                                         "center_of_ellipse_x");
            Skip_S2(16,                                         "center_of_ellipse_y");
            Skip_S1( 8,                                         "rotation_angle");
            Skip_S2(16,                                         "semimajor_axis_internal_ellipse");
            Skip_S2(16,                                         "semimajor_axis_external_ellipse");
            Skip_S2(16,                                         "semiminor_axis_external_ellipse");
            Skip_SB(                                            "overlap_process_option");
            Element_End0();
        }

        Get_S4 (27, targeted_system_display_maximum_luminance,  "targeted_system_display_maximum_luminance");
        TEST_SB_GET (targeted_system_display_actual_peak_luminance_flag, "targeted_system_display_actual_peak_luminance_flag");
            int8u num_rows_targeted_system_display_actual_peak_luminance, num_cols_targeted_system_display_actual_peak_luminance;
            Get_S1(5, num_rows_targeted_system_display_actual_peak_luminance, "num_rows_targeted_system_display_actual_peak_luminance");
            Get_S1(5, num_cols_targeted_system_display_actual_peak_luminance, "num_cols_targeted_system_display_actual_peak_luminance");
            for(int8u i=0; i<num_rows_targeted_system_display_actual_peak_luminance; i++)
                for(int8u j=0; j<num_cols_targeted_system_display_actual_peak_luminance; j++)
                    Skip_S1(4,                                   "targeted_system_display_actual_peak_luminance");
        TEST_SB_END();

        for (int8u w=0; w<num_windows; w++)
        {
            Element_Begin1("window");
            for(int8u i=0; i<3; i++)
            {
                Get_S3 (17, maxscl[i],                          "maxscl"); Param_Info2(Ztring::ToZtring(((float)maxscl[i])/100000, 5), " cd/m2");
            }
            Get_S3 (17, maxscl[3],                              "average_maxrgb");   Param_Info2(Ztring::ToZtring(((float)maxscl[3])/100000, 5), " cd/m2");

            Get_S1(4, num_distribution_maxrgb_percentiles,      "num_distribution_maxrgb_percentiles");
            for (int8u i=0; i< num_distribution_maxrgb_percentiles; i++)
            {
                Element_Begin1(                                 "distribution_maxrgb");
                Get_S1 ( 7, distribution_maxrgb_percentages[i], "distribution_maxrgb_percentages");
                Get_S3 (17, distribution_maxrgb_percentiles[i], "distribution_maxrgb_percentiles");
                Element_Info1(distribution_maxrgb_percentages[i]);
                Element_Info1(distribution_maxrgb_percentiles[i]);
                Element_End0();
            }
            Get_S2 (10, fraction_bright_pixels,                 "fraction_bright_pixels");
            Element_End0();
        }

        TEST_SB_GET (mastering_display_actual_peak_luminance_flag, "mastering_display_actual_peak_luminance_flag");
            int8u num_rows_mastering_display_actual_peak_luminance, num_cols_mastering_display_actual_peak_luminance;
            Get_S1(5, num_rows_mastering_display_actual_peak_luminance, "num_rows_mastering_display_actual_peak_luminance");
            Get_S1(5, num_cols_mastering_display_actual_peak_luminance, "num_cols_mastering_display_actual_peak_luminance");
            for(int8u i=0; i< num_rows_mastering_display_actual_peak_luminance; i++)
                for(int8u j=0; j< num_cols_mastering_display_actual_peak_luminance; j++)
                    Skip_S1(4,                                   "mastering_display_actual_peak_luminance");
        TEST_SB_END();

        for (int8u w=0; w<num_windows; w++)
        {
            Element_Begin1("window");
            TEST_SB_GET (tone_mapping_flag,                     "tone_mapping_flag");
                Skip_S2(12,                                     "knee_point_x");
                Skip_S2(12,                                     "knee_point_y");
                Get_S1(4, num_bezier_curve_anchors,             "num_bezier_curve_anchors");
                for (int8u i = 0; i < num_bezier_curve_anchors; i++)
                    Skip_S2(10,                                 "bezier_curve_anchor");
            TEST_SB_END();
            Element_End0();
        }
        TEST_SB_GET (color_saturation_mapping_flag,             "color_saturation_mapping_flag");
            Info_S1(6, color_saturation_weight,                 "color_saturation_weight"); Param_Info1(((float)color_saturation_weight)/8);
        TEST_SB_END();
        BS_End();

        FILLING_BEGIN();
            IsHDRplus=true;
            if (num_windows!=1 || targeted_system_display_actual_peak_luminance_flag || num_distribution_maxrgb_percentiles!=9 || fraction_bright_pixels || mastering_display_actual_peak_luminance_flag || (distribution_maxrgb_percentages[2]>100 && distribution_maxrgb_percentages[2]!=0xFF) || (!tone_mapping_flag && targeted_system_display_maximum_luminance) || (tone_mapping_flag && num_bezier_curve_anchors>9) || color_saturation_mapping_flag)
                IsHDRplus=false;
            for(int8u i=0; i<4; i++)
                if (maxscl[i]>100000)
                    IsHDRplus=false;
            if (IsHDRplus)
                for(int8u i=0; i<9; i++)
                {
                    static const int8u distribution_maxrgb_percentages_List[9]={1, 5, 10, 25, 50, 75, 90, 95, 99};
                    if (distribution_maxrgb_percentages[i]!=distribution_maxrgb_percentages_List[i])
                        IsHDRplus=false;
                    if (distribution_maxrgb_percentiles[i]>100000)
                        IsHDRplus=false;
                }
        FILLING_END();
    }

    FILLING_BEGIN();
        std::map<video, Ztring>& SmpteSt209440=HDR[HdrFormat_SmpteSt209440];
        Ztring& HDR_Format=SmpteSt209440[Video_HDR_Format];
        if (HDR_Format.empty())
        {
            HDR_Format=__T("SMPTE ST 2094 App 4");
            SmpteSt209440[Video_HDR_Format_Version].From_Number(application_version);
            if (IsHDRplus)
                SmpteSt209440[Video_HDR_Format_Compatibility]=tone_mapping_flag?__T("HDR10+ Profile B"):__T("HDR10+ Profile A");
        }
    FILLING_END();
}

//---------------------------------------------------------------------------
// SEI - 5
void File_Hevc::sei_message_user_data_unregistered(int32u payloadSize)
{
    Element_Info1("user_data_unregistered");

    //Parsing
    int128u uuid_iso_iec_11578;
    Get_UUID(uuid_iso_iec_11578,                                "uuid_iso_iec_11578");

    switch (uuid_iso_iec_11578.hi)
    {
        case 0x427FCC9BB8924821LL : Element_Info1("Ateme");
                                     sei_message_user_data_unregistered_Ateme(payloadSize-16); break;
        case 0x2CA2DE09B51747DBLL : Element_Info1("x265");
                                     sei_message_user_data_unregistered_x265(payloadSize-16); break;
        default :
                    Element_Info1("unknown");
                    Skip_XX(payloadSize-16,                     "data");
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - Ateme
void File_Hevc::sei_message_user_data_unregistered_Ateme(int32u payloadSize)
{
    //Parsing
    Get_UTF8 (payloadSize, Encoded_Library,                     "Library name");

    //Encoded_Library
    if (Encoded_Library.find(__T("ATEME "))==0)
    {
        size_t Pos=Encoded_Library.find_first_of(__T("0123456789"));
        if (Pos && Encoded_Library[Pos-1]==__T(' '))
        {
            Encoded_Library_Name=Encoded_Library.substr(0, Pos-1);
            Encoded_Library_Version=Encoded_Library.substr(Pos);
        }
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - x265
void File_Hevc::sei_message_user_data_unregistered_x265(int32u payloadSize)
{
    //Parsing
    string Data;
    Peek_String(payloadSize, Data);
    if (Data.size()!=payloadSize && Data.size()+1!=payloadSize)
    {
        Skip_XX(payloadSize,                                    "Unknown");
        return; //This is not a text string
    }
    size_t Data_Pos_Before=0;
    size_t Loop=0;
    do
    {
        size_t Data_Pos=Data.find(" - ", Data_Pos_Before);
        if (Data_Pos==std::string::npos)
            Data_Pos=Data.size();
        if (Data.find("options: ", Data_Pos_Before)==Data_Pos_Before)
        {
            Element_Begin1("options");
            size_t Options_Pos_Before=Data_Pos_Before;
            Encoded_Library_Settings.clear();
            while (Options_Pos_Before!=Data.size())
            {
                size_t Options_Pos=Data.find(__T(' '), Options_Pos_Before);
                if (Options_Pos==std::string::npos)
                    Options_Pos=Data.size();
                string option;
                Get_String (Options_Pos-Options_Pos_Before, option, "option");
                Options_Pos_Before=Options_Pos;
                while (Options_Pos_Before!=Data.size())
                {
                    string Separator;
                    Peek_String(1, Separator);
                    if (Separator==" ")
                    {
                        Skip_UTF8(1,                                "separator");
                        Options_Pos_Before+=1;
                    }
                    else
                        break;
                }

                //Filling
                if (option!="options:" && !(!option.empty() && option[0]>='0' && option[0]<='9') && option.find("fps=")!=0 && option.find("bitdepth=")!=0) //Ignoring redundant information e.g. width, height, frame rate, bit depth
                {
                    if (!Encoded_Library_Settings.empty())
                        Encoded_Library_Settings+=__T(" / ");
                    Encoded_Library_Settings+=Ztring().From_UTF8(option.c_str());
                }
            }
            Element_End0();
        }
        else
        {
            string Value;
            Get_String(Data_Pos-Data_Pos_Before, Value,          "data");

            //Saving
            if (Loop==0)
            {
                //Cleaning a little the value
                while (!Value.empty() && Value[0]<0x30)
                    Value.erase(Value.begin());
                while (!Value.empty() && Value[Value.size()-1]<0x30)
                    Value.erase(Value.end()-1);
                size_t Value_Pos=Value.find(__T(' '));
                if (Value_Pos!=string::npos)
                    Value.resize(Value_Pos);
                Encoded_Library.From_UTF8(Value.c_str());
            }
            if (Loop==1 && Encoded_Library.find(__T("x265"))==0)
            {
                size_t Value_Pos=Value.find(" 8bpp");
                if (Value_Pos!=string::npos)
                    Value.resize(Value_Pos);

                Encoded_Library+=__T(" - ");
                Encoded_Library+=Ztring().From_UTF8(Value.c_str());
            }
        }
        Data_Pos_Before=Data_Pos;
        if (Data_Pos_Before+3<=Data.size())
        {
            Skip_UTF8(3,                                        "separator");
            Data_Pos_Before+=3;
        }

        Loop++;
    }
    while (Data_Pos_Before!=Data.size());

    //Encoded_Library
    if (Encoded_Library.find(__T("x265 - "))==0)
    {
        Encoded_Library_Name=__T("x265");
        Encoded_Library_Version=Encoded_Library.SubString(__T("x265 - "), Ztring());
    }
    else
        Encoded_Library_Name=Encoded_Library;
}

//---------------------------------------------------------------------------
// SEI - 6
void File_Hevc::sei_message_recovery_point()
{
    Element_Info1("recovery_point");

    //Parsing
    BS_Begin();
    Skip_SE(                                                    "recovery_poc_cnt");
    Skip_SB(                                                    "exact_match_flag");
    Skip_SB(                                                    "broken_link_flag");
    BS_End();
}

//---------------------------------------------------------------------------
void File_Hevc::sei_message_active_parameter_sets()
{
    Element_Info1("active_parameter_sets");

    //Parsing
    int32u num_sps_ids_minus1;
    BS_Begin();
    Skip_S1(4,                                                  "active_video_parameter_set_id");
    Skip_SB(                                                    "self_contained_cvs_flag");
    Skip_SB(                                                    "no_parameter_set_update_flag");
    Get_UE (   num_sps_ids_minus1,                              "num_sps_ids_minus1");
    for (int32u i=0; i<=num_sps_ids_minus1; ++i)
    {
        Skip_UE(                                                "active_seq_parameter_set_id");
    }
    BS_End();
}

//---------------------------------------------------------------------------
void File_Hevc::sei_message_decoded_picture_hash(int32u payloadSize)
{
    Element_Info1("decoded_picture_hash");

    //Parsing
    int8u hash_type;
    Get_B1 (hash_type,                                          "hash_type");
    for (int8u cIdx=0; cIdx<(chroma_format_idc?3:1); cIdx++)
        switch (hash_type)
        {
            case 0 :    // md5
                        Skip_XX(16,                             "md5");
                        break;
            case 1 :    // crc
                        Skip_XX( 2,                             "crc");
                        break;
            case 2 :    // checksum
                        Skip_XX( 4,                             "checksum");
                        break;
            default :   //
                        Skip_XX((Element_Size-1)/(chroma_format_idc?1:3), "unknown");
                        break;
        }
}

//---------------------------------------------------------------------------
void File_Hevc::sei_message_mastering_display_colour_volume()
{
    Element_Info1("mastering_display_colour_volume");

    std::map<video, Ztring>& SmpteSt2086=HDR[HdrFormat_SmpteSt2086];
    Ztring& HDR_Format=SmpteSt2086[Video_HDR_Format];
    if (HDR_Format.empty())
    {
        HDR_Format=__T("SMPTE ST 2086");
        SmpteSt2086[Video_HDR_Format_Compatibility]="HDR10";
    }
    Get_MasteringDisplayColorVolume(SmpteSt2086[Video_MasteringDisplay_ColorPrimaries], SmpteSt2086[Video_MasteringDisplay_Luminance]);
}

//---------------------------------------------------------------------------
void File_Hevc::sei_message_light_level()
{
    Element_Info1("light_level");

    //Parsing
    Get_B2(maximum_content_light_level,                         "maximum_content_light_level");
    Get_B2(maximum_frame_average_light_level,                   "maximum_frame_average_light_level");
}

//---------------------------------------------------------------------------
void File_Hevc::sei_alternative_transfer_characteristics()
{
    Element_Info1("alternative_transfer_characteristics");

    //Parsing
    Get_B1(preferred_transfer_characteristics,                  "preferred_transfer_characteristics"); Param_Info1(Mpegv_transfer_characteristics(preferred_transfer_characteristics));
}

//***************************************************************************
// Sub-elements
//***************************************************************************

//---------------------------------------------------------------------------
void File_Hevc::slice_segment_header()
{
    Element_Begin1("slice_segment_header");

    //Parsing
    bool    dependent_slice_segment_flag=false;
    Get_SB (   first_slice_segment_in_pic_flag,                 "first_slice_segment_in_pic_flag");
    if (RapPicFlag)
        Skip_SB(                                                "no_output_of_prior_pics_flag");
    Get_UE (   slice_pic_parameter_set_id,                      "slice_pic_parameter_set_id");
    std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item;
    if (slice_pic_parameter_set_id>=pic_parameter_sets.size() || (*(pic_parameter_set_Item=pic_parameter_sets.begin()+slice_pic_parameter_set_id))==NULL)
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (pic_parameter_set is missing)");
        Element_End0();
        slice_pic_parameter_set_id=(int32u)-1;
        slice_type=(int32u)-1;
        return;
    }
    if (!first_slice_segment_in_pic_flag)
    {
        if (!MustParse_VPS_SPS_PPS_FromFlv && (*pic_parameter_set_Item)->dependent_slice_segments_enabled_flag)
            Get_SB (dependent_slice_segment_flag,               "dependent_slice_segment_flag");
        //Skip_BS(Ceil( Log2( PicSizeInCtbsY ) ),               "slice_segment_address");
        Skip_BS(Data_BS_Remain(),                               "(ToDo)");
        Element_End0();
        slice_type=(int32u)-1;
        return;
    }
    if (!dependent_slice_segment_flag)
    {
        if (!MustParse_VPS_SPS_PPS_FromFlv)
            Skip_S1((*pic_parameter_set_Item)->num_extra_slice_header_bits, "slice_reserved_flags");
        Get_UE (slice_type,                                     "slice_type"); Param_Info1(Hevc_slice_type(slice_type));
    }
    //TODO...
    Skip_BS(Data_BS_Remain(),                                   "(ToDo)");

    Element_End0();

    #if MEDIAINFO_EVENTS
        if (first_slice_segment_in_pic_flag)
        {
            switch(Element_Code)
            {
                case 19 :
                case 20 :   // This is an IDR frame
                            if (Config->Config_PerPackage && Element_Code==0x05) // First slice of an IDR frame
                            {
                                // IDR
                                Config->Config_PerPackage->FrameForAlignment(this, true);
                                Config->Config_PerPackage->IsClosedGOP(this);
                            }
                            break;
                default:    ; // This is not an IDR frame
            }
        }
    #endif //MEDIAINFO_EVENTS
}

//---------------------------------------------------------------------------
void File_Hevc::profile_tier_level(int8u maxNumSubLayersMinus1)
{
    Element_Begin1("profile_tier_level");

    //Parsing
    std::vector<bool>sub_layer_profile_present_flags, sub_layer_level_present_flags;
    Get_S1 (2,  profile_space,                                  "general_profile_space");
    Get_SB (    tier_flag,                                      "general_tier_flag");
    Get_S1 (5,  profile_idc,                                    "general_profile_idc");
    Element_Begin1("general_profile_compatibility_flags");
        for (int8u profile_pos=0; profile_pos<32; profile_pos++)
            if (profile_pos==profile_idc)
            {
                bool general_profile_compatibility_flag;
                Get_SB (    general_profile_compatibility_flag, "general_profile_compatibility_flag");
                //if (!general_profile_compatibility_flag && !profile_space)  //found some files without this flag, ignoring the test for the moment (not really important)
                //    Trusted_IsNot("general_profile_compatibility_flag not valid");
            }
            else
                Skip_SB(                                        "general_profile_compatibility_flag");
    Element_End0();
    Element_Begin1("general_profile_compatibility_flags");
        Get_SB (    general_progressive_source_flag,            "general_progressive_source_flag");
        Get_SB (    general_interlaced_source_flag,             "general_interlaced_source_flag");
        Skip_SB(                                                "general_non_packed_constraint_flag");
        Get_SB (    general_frame_only_constraint_flag,         "general_frame_only_constraint_flag");
        Skip_SB(                                                "general_max_12bit_constraint_flag");
        Skip_SB(                                                "general_max_10bit_constraint_flag");
        Get_SB (    general_max_8bit_constraint_flag,           "general_max_8bit_constraint_flag");
        Skip_SB(                                                "general_max_422chroma_constraint_flag");
        Skip_SB(                                                "general_max_420chroma_constraint_flag");
        Skip_SB(                                                "general_max_monochrome_constraint_flag");
        Skip_SB(                                                "general_intra_constraint_flag");
        Skip_SB(                                                "general_one_picture_only_constraint_flag");
        Skip_SB(                                                "general_lower_bit_rate_constraint_flag");
        Skip_SB(                                                "general_max_14bit_constraint_flag");
        for (int8u constraint_pos=0; constraint_pos<33; constraint_pos++)
            Skip_SB(                                            "general_reserved");
        Skip_SB(                                                "general_inbld_flag");
    Element_End0();
    Get_S1 (8,  level_idc,                                      "general_level_idc");
    for (int32u SubLayerPos=0; SubLayerPos<maxNumSubLayersMinus1; SubLayerPos++)
    {
        Element_Begin1("SubLayer");
        bool sub_layer_profile_present_flag, sub_layer_level_present_flag;
        Get_SB (   sub_layer_profile_present_flag,              "sub_layer_profile_present_flag");
        Get_SB (   sub_layer_level_present_flag,                "sub_layer_level_present_flag");
        sub_layer_profile_present_flags.push_back(sub_layer_profile_present_flag);
        sub_layer_level_present_flags.push_back(sub_layer_level_present_flag);
        Element_End0();
    }
    if (maxNumSubLayersMinus1)
        for(int32u SubLayerPos=maxNumSubLayersMinus1; SubLayerPos<8; SubLayerPos++)
            Skip_S1(2,                                          "reserved_zero_2bits");
    for (int32u SubLayerPos=0; SubLayerPos<maxNumSubLayersMinus1; SubLayerPos++)
    {
        Element_Begin1("SubLayer");
        if (sub_layer_profile_present_flags[SubLayerPos])
        {
            Skip_S1(2,                                          "sub_layer_profile_space");
            Skip_SB(                                            "sub_layer_tier_flag");
            Skip_S1(5,                                          "sub_layer_profile_idc");
            Skip_S4(32,                                         "sub_layer_profile_compatibility_flags");
            Skip_SB(                                            "sub_layer_progressive_source_flag");
            Skip_SB(                                            "sub_layer_interlaced_source_flag");
            Skip_SB(                                            "sub_layer_non_packed_constraint_flag");
            Skip_SB(                                            "sub_layer_frame_only_constraint_flag");
            Skip_S8(44,                                         "sub_layer_reserved_zero_44bits");
        }
        if (sub_layer_level_present_flags[SubLayerPos])
        {
            Skip_S1(8,                                          "sub_layer_level_idc");
        }
        Element_End0();
    }

    Element_End0();
}

//---------------------------------------------------------------------------
void File_Hevc::short_term_ref_pic_sets(int8u num_short_term_ref_pic_sets)
{
    Element_Begin1("short_term_ref_pic_sets");
    int32u num_pics=0;

    for (int32u stRpsIdx=0; stRpsIdx<num_short_term_ref_pic_sets; stRpsIdx++)
    {
        Element_Begin1("short_term_ref_pic_set");
        bool inter_ref_pic_set_prediction_flag=false;
        if (stRpsIdx)
            Get_SB (inter_ref_pic_set_prediction_flag,              "inter_ref_pic_set_prediction_flag");
        if (inter_ref_pic_set_prediction_flag)
        {
            int32u  delta_idx_minus1=0, abs_delta_rps_minus1;
            bool    delta_rps_sign;
            if (stRpsIdx==num_short_term_ref_pic_sets)
                Get_UE (delta_idx_minus1,                           "delta_idx_minus1");
            if (delta_idx_minus1+1>stRpsIdx)
            {
                Skip_BS(Data_BS_Remain(),                           "(Problem)");
                Element_End0();
                Element_End0();
                return;
            }
            Get_SB (   delta_rps_sign,                              "delta_rps_sign");
            Get_UE (   abs_delta_rps_minus1,                        "abs_delta_rps_minus1");
            int32u num_pics_new=0;
            for(int32u pic_pos=0 ; pic_pos<=num_pics; pic_pos++)
            {
                TESTELSE_SB_SKIP(                                   "used_by_curr_pic_flag");
                    num_pics_new++;
                TESTELSE_SB_ELSE(                                   "used_by_curr_pic_flag");
                    bool use_delta_flag;
                    Get_SB (use_delta_flag,                         "use_delta_flag");
                    if (use_delta_flag)
                        num_pics_new++;
                TESTELSE_SB_END();
            }
            num_pics=num_pics_new;
        }
        else
        {
            int32u num_negative_pics, num_positive_pics;
            Get_UE (num_negative_pics,                              "num_negative_pics");
            Get_UE (num_positive_pics,                              "num_positive_pics");
            num_pics=num_negative_pics+num_positive_pics;
            for (int32u i=0; i<num_negative_pics; i++)
            {
                Skip_UE(                                            "delta_poc_s0_minus1");
                Skip_SB(                                            "used_by_curr_pic_s0_flag");
            }
            for (int32u i=0; i<num_positive_pics; i++)
            {
                Skip_UE(                                            "delta_poc_s1_minus1");
                Skip_SB(                                            "used_by_curr_pic_s1_flag");
            }
        }
        Element_End0();
    }

    Element_End0();
}

//---------------------------------------------------------------------------
void File_Hevc::vui_parameters(std::vector<video_parameter_set_struct*>::iterator video_parameter_set_Item, seq_parameter_set_struct::vui_parameters_struct* &vui_parameters_Item_)
{
    //Parsing
    seq_parameter_set_struct::vui_parameters_struct::xxl_common *xxL_Common=NULL;
    seq_parameter_set_struct::vui_parameters_struct::xxl *NAL = NULL, *VCL = NULL;
    int32u  num_units_in_tick = (int32u)-1, time_scale = (int32u)-1;
    int16u  sar_width=(int16u)-1, sar_height=(int16u)-1;
    int8u   aspect_ratio_idc=0, video_format=5, video_full_range_flag=0, colour_primaries=2, transfer_characteristics=2, matrix_coefficients=2;
    bool    aspect_ratio_info_present_flag, video_signal_type_present_flag, frame_field_info_present_flag, colour_description_present_flag=false, timing_info_present_flag;
    TEST_SB_GET (aspect_ratio_info_present_flag,                "aspect_ratio_info_present_flag");
        Get_S1 (8, aspect_ratio_idc,                            "aspect_ratio_idc"); Param_Info1C((aspect_ratio_idc<Avc_PixelAspectRatio_Size), Avc_PixelAspectRatio[aspect_ratio_idc]);
        if (aspect_ratio_idc==0xFF)
        {
            Get_S2 (16, sar_width,                              "sar_width");
            Get_S2 (16, sar_height,                             "sar_height");
        }
    TEST_SB_END();
    TEST_SB_SKIP(                                               "overscan_info_present_flag");
        Skip_SB(                                                "overscan_appropriate_flag");
    TEST_SB_END();
    TEST_SB_GET (video_signal_type_present_flag,                "video_signal_type_present_flag");
        Get_S1 (3, video_format,                                "video_format"); Param_Info1(Avc_video_format[video_format]);
        Get_S1 (1, video_full_range_flag,                       "video_full_range_flag"); Param_Info1(Avc_video_full_range[video_full_range_flag]);
        TEST_SB_GET (colour_description_present_flag,           "colour_description_present_flag");
            Get_S1 (8, colour_primaries,                        "colour_primaries"); Param_Info1(Mpegv_colour_primaries(colour_primaries));
            Get_S1 (8, transfer_characteristics,                "transfer_characteristics"); Param_Info1(Mpegv_transfer_characteristics(transfer_characteristics));
            Get_S1 (8, matrix_coefficients,                     "matrix_coefficients"); Param_Info1(Mpegv_matrix_coefficients(matrix_coefficients));
        TEST_SB_END();
    TEST_SB_END();
    TEST_SB_SKIP(                                               "chroma_loc_info_present_flag");
        Get_UE (chroma_sample_loc_type_top_field,               "chroma_sample_loc_type_top_field");
        Get_UE (chroma_sample_loc_type_bottom_field,            "chroma_sample_loc_type_bottom_field");
    TEST_SB_END();
    Skip_SB(                                                    "neutral_chroma_indication_flag");
    Skip_SB(                                                    "field_seq_flag");
    Get_SB (   frame_field_info_present_flag,                   "frame_field_info_present_flag");
    TEST_SB_SKIP(                                               "default_display_window_flag ");
        Skip_UE(                                                "def_disp_win_left_offset");
        Skip_UE(                                                "def_disp_win_right_offset");
        Skip_UE(                                                "def_disp_win_top_offset");
        Skip_UE(                                                "def_disp_win_bottom_offset");
    TEST_SB_END();
    TEST_SB_GET (timing_info_present_flag,                      "timing_info_present_flag");
        Get_S4 (32, num_units_in_tick,                          "num_units_in_tick");
        Get_S4 (32, time_scale,                                 "time_scale");
        TEST_SB_SKIP(                                           "vui_poc_proportional_to_timing_flag");
            Skip_UE(                                            "vui_num_ticks_poc_diff_one_minus1");
        TEST_SB_END();
        TEST_SB_SKIP(                                           "hrd_parameters_present_flag");
            hrd_parameters(true, (*video_parameter_set_Item)->vps_max_sub_layers_minus1, xxL_Common, NAL, VCL);
        TEST_SB_END();
    TEST_SB_END();
    TEST_SB_SKIP(                                               "bitstream_restriction_flag");
        Skip_SB(                                                "tiles_fixed_structure_flag");
        Skip_SB(                                                "motion_vectors_over_pic_boundaries_flag");
        Skip_SB(                                                "restricted_ref_pic_lists_flag");
        Skip_UE(                                                "min_spatial_segmentation_idc");
        Skip_UE(                                                "max_bytes_per_pic_denom");
        Skip_UE(                                                "max_bits_per_min_cu_denom");
        Skip_UE(                                                "log2_max_mv_length_horizontal");
        Skip_UE(                                                "log2_max_mv_length_vertical");
    TEST_SB_END();

    FILLING_BEGIN();
        vui_parameters_Item_ = new seq_parameter_set_struct::vui_parameters_struct(
                                                                                    NAL,
                                                                                    VCL,
                                                                                    xxL_Common,
                                                                                    num_units_in_tick,
                                                                                    time_scale,
                                                                                    sar_width,
                                                                                    sar_height,
                                                                                    aspect_ratio_idc,
                                                                                    video_format,
                                                                                    video_full_range_flag,
                                                                                    colour_primaries,
                                                                                    transfer_characteristics,
                                                                                    matrix_coefficients,
                                                                                    aspect_ratio_info_present_flag,
                                                                                    video_signal_type_present_flag,
                                                                                    frame_field_info_present_flag,
                                                                                    colour_description_present_flag,
                                                                                    timing_info_present_flag
                                                                                  );
    FILLING_ELSE();
    delete xxL_Common; xxL_Common=NULL;
    delete NAL; NAL=NULL;
    delete VCL; VCL=NULL;
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Hevc::hrd_parameters(bool commonInfPresentFlag, int8u maxNumSubLayersMinus1, seq_parameter_set_struct::vui_parameters_struct::xxl_common* &xxL_Common, seq_parameter_set_struct::vui_parameters_struct::xxl* &NAL, seq_parameter_set_struct::vui_parameters_struct::xxl* &VCL)
{
    //Parsing
    int8u bit_rate_scale=0, cpb_size_scale=0, du_cpb_removal_delay_increment_length_minus1=0, dpb_output_delay_du_length_minus1=0, initial_cpb_removal_delay_length_minus1=0, au_cpb_removal_delay_length_minus1=0, dpb_output_delay_length_minus1=0;
    bool nal_hrd_parameters_present_flag=false, vcl_hrd_parameters_present_flag=false, sub_pic_hrd_params_present_flag=false;
    if (commonInfPresentFlag)
    {
        Get_SB (nal_hrd_parameters_present_flag,                "nal_hrd_parameters_present_flag");
        Get_SB (vcl_hrd_parameters_present_flag,                "vcl_hrd_parameters_present_flag");
        if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
        {
            TEST_SB_GET (sub_pic_hrd_params_present_flag,       "sub_pic_hrd_params_present_flag");
                Skip_S1(8,                                      "tick_divisor_minus2");
                Get_S1 (5, du_cpb_removal_delay_increment_length_minus1,  "du_cpb_removal_delay_increment_length_minus1");
                Skip_SB(                                        "sub_pic_cpb_params_in_pic_timing_sei_flag");
                Get_S1 (5, dpb_output_delay_du_length_minus1,   "dpb_output_delay_du_length_minus1");
            TEST_SB_END();
            Get_S1 (4, bit_rate_scale,                          "bit_rate_scale");
            Get_S1 (4, cpb_size_scale,                          "cpb_size_scale");
            if (sub_pic_hrd_params_present_flag)
                Skip_S1(4,                                      "cpb_size_du_scale");
            Get_S1 (5, initial_cpb_removal_delay_length_minus1, "initial_cpb_removal_delay_length_minus1");
            Get_S1 (5, au_cpb_removal_delay_length_minus1,      "au_cpb_removal_delay_length_minus1");
            Get_S1 (5, dpb_output_delay_length_minus1,          "dpb_output_delay_length_minus1");
        }
    }

    for (int8u NumSubLayer=0; NumSubLayer<=maxNumSubLayersMinus1; NumSubLayer++)
    {
        int32u cpb_cnt_minus1=0;
        bool fixed_pic_rate_general_flag, fixed_pic_rate_within_cvs_flag=true, low_delay_hrd_flag=false;
        Get_SB (fixed_pic_rate_general_flag,                   "fixed_pic_rate_general_flag");
        if (!fixed_pic_rate_general_flag)
            Get_SB (fixed_pic_rate_within_cvs_flag,            "fixed_pic_rate_within_cvs_flag");
        if (fixed_pic_rate_within_cvs_flag)
            Skip_UE(                                           "elemental_duration_in_tc_minus1");
        else
            Get_SB (low_delay_hrd_flag,                        "low_delay_hrd_flag");
        if (!low_delay_hrd_flag)
        {
            Get_UE (cpb_cnt_minus1,                            "cpb_cnt_minus1");
            if (cpb_cnt_minus1>31)
            {
                Trusted_IsNot("cpb_cnt_minus1 too high");
                cpb_cnt_minus1=0;
                return;
            }
        }
        if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
            xxL_Common=new seq_parameter_set_struct::vui_parameters_struct::xxl_common(
                                                                                        sub_pic_hrd_params_present_flag,
                                                                                        du_cpb_removal_delay_increment_length_minus1,
                                                                                        dpb_output_delay_du_length_minus1,
                                                                                        initial_cpb_removal_delay_length_minus1,
                                                                                        au_cpb_removal_delay_length_minus1,
                                                                                        dpb_output_delay_length_minus1
                                                                                      );
        if (nal_hrd_parameters_present_flag)
            sub_layer_hrd_parameters(xxL_Common, bit_rate_scale, cpb_size_scale, cpb_cnt_minus1, NAL); //TODO: save HRD per NumSubLayer
        if (vcl_hrd_parameters_present_flag)
            sub_layer_hrd_parameters(xxL_Common, bit_rate_scale, cpb_size_scale, cpb_cnt_minus1, VCL); //TODO: save HRD per NumSubLayer
    }
}

//---------------------------------------------------------------------------
void File_Hevc::sub_layer_hrd_parameters(seq_parameter_set_struct::vui_parameters_struct::xxl_common* xxL_Common, int8u bit_rate_scale, int8u cpb_size_scale, int32u cpb_cnt_minus1, seq_parameter_set_struct::vui_parameters_struct::xxl* &hrd_parameters_Item_)
{
    //Parsing
    vector<seq_parameter_set_struct::vui_parameters_struct::xxl::xxl_data>  SchedSel;
    SchedSel.reserve(cpb_cnt_minus1 + 1);
    for (int8u SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; ++SchedSelIdx)
    {
        Element_Begin1("ShedSel");
        int64u bit_rate_value, cpb_size_value;
        int32u bit_rate_value_minus1, cpb_size_value_minus1;
        bool cbr_flag;
        Get_UE (bit_rate_value_minus1,                          "bit_rate_value_minus1");
        bit_rate_value = (int64u)((bit_rate_value_minus1 + 1)*pow(2.0, 6 + bit_rate_scale)); Param_Info2(bit_rate_value, " bps");
        Get_UE (cpb_size_value_minus1,                          "cpb_size_value_minus1");
        cpb_size_value = (int64u)((cpb_size_value_minus1 + 1)*pow(2.0, 4 + cpb_size_scale)); Param_Info2(cpb_size_value, " bits");
        if (xxL_Common->sub_pic_hrd_params_present_flag)
        {
            Skip_UE(                                            "cpb_size_du_value_minus1");
            Skip_UE(                                            "bit_rate_du_value_minus1");
        }
        Get_SB (cbr_flag,                                       "cbr_flag");
        Element_End0();

        FILLING_BEGIN();
        SchedSel.push_back(seq_parameter_set_struct::vui_parameters_struct::xxl::xxl_data(
                                                                                            bit_rate_value,
                                                                                            cpb_size_value,
                                                                                            cbr_flag
                                                                                         ));
        FILLING_END();
    }

    //Validity test
    if (!Element_IsOK() || (SchedSel.size() == 1 && SchedSel[0].bit_rate_value == 64))
    {
        return; //We do not trust this kind of data
    }

    //Filling
    hrd_parameters_Item_=new seq_parameter_set_struct::vui_parameters_struct::xxl(
                                                                                    SchedSel
                                                                                 );
}

//---------------------------------------------------------------------------
void File_Hevc::scaling_list_data()
{
    for(int8u sizeId=0; sizeId<4; sizeId++)
        for (int8u matrixId = 0; matrixId<((sizeId == 3) ? 2 : 6); matrixId++)
        {
            bool scaling_list_pred_mode_flag;
            Get_SB (scaling_list_pred_mode_flag,                "scaling_list_pred_mode_flag");
            if(!scaling_list_pred_mode_flag)
                Skip_UE(                                        "scaling_list_pred_matrix_id_delta");
            else
            {
                //nextCoef = 8
                size_t coefNum=std::min(64, (1<<(4+(sizeId<<1))));
                if( sizeId > 1 )
                {
                    Skip_SE(                                    "scaling_list_dc_coef_minus8"); //[ sizeId ? 2 ][ matrixId ] se(v)
                    //nextCoef = scaling_list_dc_coef_minus8[ sizeId ? 2 ][ matrixId ] + 8
                }
                for(size_t i=0; i<coefNum; i++)
                {
                    Skip_SE(                                    "scaling_list_delta_coef");
                    //nextCoef = ( nextCoef + scaling_list_delta_coef + 256 ) % 256
                    //ScalingList[ sizeId ][ matrixId ][ i ] = nextCoef
                }
            }
        }
}

//***************************************************************************
// Specific
//***************************************************************************

//---------------------------------------------------------------------------
void File_Hevc::VPS_SPS_PPS()
{
    if (MustParse_VPS_SPS_PPS_FromMatroska || MustParse_VPS_SPS_PPS_FromFlv)
    {
        if (Element_Size>=5
         && Buffer[Buffer_Offset  ]==0x01
         && Buffer[Buffer_Offset+1]==0x00
         && Buffer[Buffer_Offset+2]==0x00
         && Buffer[Buffer_Offset+3]==0x00
         && Buffer[Buffer_Offset+4]==0xFF) //Trying to detect old proposal of the form of Matroska implementation
            return VPS_SPS_PPS_FromMatroska();

        MustParse_VPS_SPS_PPS_FromMatroska=false;
        MustParse_VPS_SPS_PPS_FromFlv=false;
    }

    //Parsing
    int64u general_constraint_indicator_flags;
    int32u general_profile_compatibility_flags;
    int8u  configurationVersion;
    int8u  chromaFormat, bitDepthLumaMinus8, bitDepthChromaMinus8;
    int8u  general_profile_space, general_profile_idc, general_level_idc;
    int8u  numOfArrays, constantFrameRate, numTemporalLayers;
    bool   general_tier_flag, temporalIdNested;
    Get_B1 (configurationVersion,                               "configurationVersion");
    BS_Begin();
        Get_S1 (2, general_profile_space,                       "general_profile_space");
        Get_SB (   general_tier_flag,                           "general_tier_flag");
        Get_S1 (5, general_profile_idc,                         "general_profile_idc");
    BS_End();
    Get_B4 (general_profile_compatibility_flags,                "general_profile_compatibility_flags");
    Get_B6 (general_constraint_indicator_flags,                 "general_constraint_indicator_flags");
    Get_B1 (general_level_idc,                                  "general_level_idc");
    BS_Begin();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Skip_S2(12,                                             "min_spatial_segmentation_idc");
    BS_End();
    BS_Begin();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Skip_S1(2,                                              "parallelismType");
    BS_End();
    BS_Begin();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Get_S1 (2, chromaFormat,                                "chromaFormat");
    BS_End();
    BS_Begin();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Get_S1 (3, bitDepthLumaMinus8,                          "bitDepthLumaMinus8");
    BS_End();
    BS_Begin();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Get_S1 (3, bitDepthChromaMinus8,                        "bitDepthChromaMinus8");
    BS_End();
    Skip_B2(                                                    "avgFrameRate");
    BS_Begin();
        Get_S1 (2, constantFrameRate,                           "constantFrameRate");
        Get_S1 (3, numTemporalLayers,                           "numTemporalLayers");
        Get_SB (   temporalIdNested,                            "temporalIdNested");
        Get_S1 (2, lengthSizeMinusOne,                          "lengthSizeMinusOne");
    BS_End();
    Get_B1 (numOfArrays,                                        "numOfArrays");
    for (size_t ArrayPos=0; ArrayPos<numOfArrays; ArrayPos++)
    {
        Element_Begin1("Array");
        int16u numNalus;
        int8u NAL_unit_type;
        BS_Begin();
            Skip_SB(                                            "array_completeness");
            Mark_0_NoTrustError();
            Get_S1 (6, NAL_unit_type,                           "NAL_unit_type");
        BS_End();
        Get_B2 (numNalus,                                       "numNalus");
        for (size_t NaluPos=0; NaluPos<numNalus; NaluPos++)
        {
            Element_Begin1("nalUnit");
            int16u nalUnitLength;
            Get_B2 (nalUnitLength,                              "nalUnitLength");
            if (nalUnitLength<2 || Element_Offset+nalUnitLength>Element_Size)
            {
                Trusted_IsNot("Size is wrong");
                break; //There is an error
            }

            //Header
            int8u nal_unit_type, nuh_temporal_id_plus1;
            BS_Begin();
            Mark_0 ();
            Get_S1 (6, nal_unit_type,                           "nal_unit_type");
            Get_S1 (6, nuh_layer_id,                            "nuh_layer_id");
            Get_S1 (3, nuh_temporal_id_plus1,                   "nuh_temporal_id_plus1");
            if (nuh_temporal_id_plus1==0)
                Trusted_IsNot("nuh_temporal_id_plus1 is invalid");
            BS_End();

            //Data
            int64u Element_Offset_Save=Element_Offset;
            int64u Element_Size_Save=Element_Size;
            Buffer_Offset+=(size_t)Element_Offset_Save;
            Element_Offset=0;
            Element_Size=nalUnitLength-2;
            Element_Code=nal_unit_type;
            Data_Parse();
            Buffer_Offset-=(size_t)Element_Offset_Save;
            Element_Offset=Element_Offset_Save+nalUnitLength-2;
            Element_Size=Element_Size_Save;

            Element_End0();
        }
        Element_End0();
    }

    MustParse_VPS_SPS_PPS=false;
    FILLING_BEGIN_PRECISE();
        Accept("HEVC");
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Hevc::VPS_SPS_PPS_FromMatroska()
{
    //Parsing
    int8u Profile, Level, vid_parameter_set_count, seq_parameter_set_count, pic_parameter_set_count;
    if (SizedBlocks)
        Skip_B1(                                                "Version");
    Get_B1 (Profile,                                            "Profile");
    Skip_B1(                                                    "Compatible profile");
    Get_B1 (Level,                                              "Level");
    BS_Begin();
    Skip_S1(6,                                                  "Reserved");
    Get_S1 (2, lengthSizeMinusOne,                              "Size of NALU length minus 1");
    Skip_S1(3,                                                  "Reserved");
    Get_S1 (5, vid_parameter_set_count,                         MustParse_VPS_SPS_PPS_FromFlv?"vid_parameter_set+seq_parameter_set count":"vid_parameter_set count");
    BS_End();
    for (int8u Pos=0; Pos<vid_parameter_set_count; Pos++)
    {
        Element_Begin1("nalUnit");
        int16u nalUnitLength;
        Get_B2 (nalUnitLength,                              "nalUnitLength");
        if (nalUnitLength<2 || Element_Offset+nalUnitLength>Element_Size)
        {
            Trusted_IsNot("Size is wrong");
            break; //There is an error
        }

        //Header
        int8u nal_unit_type, nuh_temporal_id_plus1;
        BS_Begin();
        Mark_0 ();
        Get_S1 (6, nal_unit_type,                           "nal_unit_type");
        Get_S1 (6, nuh_layer_id,                            "nuh_layer_id");
        Get_S1 (3, nuh_temporal_id_plus1,                   "nuh_temporal_id_plus1");
        if (nuh_temporal_id_plus1==0)
            Trusted_IsNot("nuh_temporal_id_plus1 is invalid");
        BS_End();

        //Data
        int64u Element_Offset_Save=Element_Offset;
        int64u Element_Size_Save=Element_Size;
        Buffer_Offset+=(size_t)Element_Offset_Save;
        Element_Offset=0;
        Element_Size=nalUnitLength-2;
        Element_Code=nal_unit_type;
        Data_Parse();
        Buffer_Offset-=(size_t)Element_Offset_Save;
        Element_Offset=Element_Offset_Save+nalUnitLength-2;
        Element_Size=Element_Size_Save;

        Element_End0();
    }
    if (MustParse_VPS_SPS_PPS_FromFlv)
        seq_parameter_set_count=0;
    else
    {
        BS_Begin();
        Skip_S1(3,                                              "Reserved");
        Get_S1 (5, seq_parameter_set_count,                     "seq_parameter_set count");
        BS_End();
    }
    for (int8u Pos=0; Pos<seq_parameter_set_count; Pos++)
    {
        Element_Begin1("nalUnit");
        int16u nalUnitLength;
        Get_B2 (nalUnitLength,                              "nalUnitLength");
        if (nalUnitLength<2 || Element_Offset+nalUnitLength>Element_Size)
        {
            Trusted_IsNot("Size is wrong");
            break; //There is an error
        }

        //Header
        int8u nal_unit_type, nuh_temporal_id_plus1;
        BS_Begin();
        Mark_0 ();
        Get_S1 (6, nal_unit_type,                           "nal_unit_type");
        Get_S1 (6, nuh_layer_id,                            "nuh_layer_id");
        Get_S1 (3, nuh_temporal_id_plus1,                   "nuh_temporal_id_plus1");
        if (nuh_temporal_id_plus1==0)
            Trusted_IsNot("nuh_temporal_id_plus1 is invalid");
        BS_End();

        //Data
        int64u Element_Offset_Save=Element_Offset;
        int64u Element_Size_Save=Element_Size;
        Buffer_Offset+=(size_t)Element_Offset_Save;
        Element_Offset=0;
        Element_Size=nalUnitLength-2;
        Element_Code=nal_unit_type;
        Data_Parse();
        Buffer_Offset-=(size_t)Element_Offset_Save;
        Element_Offset=Element_Offset_Save+nalUnitLength-2;
        Element_Size=Element_Size_Save;

        Element_End0();
    }
    Get_B1 (pic_parameter_set_count,                            "pic_parameter_set count");
    for (int8u Pos=0; Pos<pic_parameter_set_count; Pos++)
    {
        Element_Begin1("nalUnit");
        int16u nalUnitLength;
        Get_B2 (nalUnitLength,                              "nalUnitLength");
        if (nalUnitLength<2 || Element_Offset+nalUnitLength>Element_Size)
        {
            Trusted_IsNot("Size is wrong");
            break; //There is an error
        }

        //Header
        int8u nal_unit_type, nuh_temporal_id_plus1;
        BS_Begin();
        Mark_0 ();
        Get_S1 (6, nal_unit_type,                           "nal_unit_type");
        Get_S1 (6, nuh_layer_id,                            "nuh_layer_id");
        Get_S1 (3, nuh_temporal_id_plus1,                   "nuh_temporal_id_plus1");
        if (nuh_temporal_id_plus1==0)
            Trusted_IsNot("nuh_temporal_id_plus1 is invalid");
        BS_End();

        //Data
        int64u Element_Offset_Save=Element_Offset;
        int64u Element_Size_Save=Element_Size;
        Buffer_Offset+=(size_t)Element_Offset_Save;
        Element_Offset=0;
        Element_Size=nalUnitLength-2;
        Element_Code=nal_unit_type;
        Data_Parse();
        Buffer_Offset-=(size_t)Element_Offset_Save;
        Element_Offset=Element_Offset_Save+nalUnitLength-2;
        Element_Size=Element_Size_Save;

        Element_End0();
    }
    if (Element_Offset<Element_Size)
        Skip_XX(Element_Size-Element_Offset,                    "Padding?");

    //Filling
    MustParse_VPS_SPS_PPS=false;
    FILLING_BEGIN_PRECISE();
        Accept("HEVC");
    FILLING_END();
}

} //NameSpace

#endif //MEDIAINFO_HEVC_YES
