/*  Copyright (c) MediaArea.net SARL. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license that can
 *  be found in the License.html file in the root of the source tree.
 */

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

//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------

//***************************************************************************
// Constants
//***************************************************************************

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

namespace MediaInfoLib
{

#include "ZenLib/Conf.h"
using namespace ZenLib;

//---------------------------------------------------------------------------
const char* Avc_profile_idc(int8u profile_idc)
{
    switch (profile_idc)
    {
        case  44 : return "CAVLC 4:4:4 Intra";
        case  66 : return "Baseline";
        case  77 : return "Main";
        case  83 : return "Scalable Baseline";
        case  86 : return "Scalable High";
        case  88 : return "Extended";
        case 100 : return "High";
        case 110 : return "High 10";
        case 118 : return "Multiview High";
        case 122 : return "High 4:2:2";
        case 128 : return "Stereo High";
        case 138 : return "Multiview Depth High";
        case 144 : return "High 4:4:4";
        case 244 : return "High 4:4:4 Predictive";
        default  : return "";
    }
}

//---------------------------------------------------------------------------
} //NameSpace

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

//***************************************************************************
//
//***************************************************************************

//---------------------------------------------------------------------------
#if defined(MEDIAINFO_AVC_YES)
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Video/File_Avc.h"
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
    #include "MediaInfo/Text/File_DtvccTransport.h"
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
#if MEDIAINFO_ADVANCED2
    #include "ThirdParty/base64/base64.h"
#endif //MEDIAINFO_ADVANCED2
#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
#include <cstring>
#include <algorithm>
using namespace std;
using namespace ZenLib;
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

//***************************************************************************
// Infos
//***************************************************************************

//---------------------------------------------------------------------------
const size_t Avc_Errors_MaxCount=32;

//---------------------------------------------------------------------------
extern const int8u Avc_PixelAspectRatio_Size=17;
extern const float32 Avc_PixelAspectRatio[Avc_PixelAspectRatio_Size]=
{
    (float32)1, //Reserved
    (float32)1,
    (float32)12/(float32)11,
    (float32)10/(float32)11,
    (float32)16/(float32)11,
    (float32)40/(float32)33,
    (float32)24/(float32)11,
    (float32)20/(float32)11,
    (float32)32/(float32)11,
    (float32)80/(float32)33,
    (float32)18/(float32)11,
    (float32)15/(float32)11,
    (float32)64/(float32)33,
    (float32)160/(float32)99,
    (float32)4/(float32)3,
    (float32)3/(float32)2,
    (float32)2,
};

//---------------------------------------------------------------------------
const char* Avc_video_format[]=
{
    "Component",
    "PAL",
    "NTSC",
    "SECAM",
    "MAC",
    "",
    "Reserved",
    "Reserved",
};

//---------------------------------------------------------------------------
const char* Avc_video_full_range[]=
{
    "Limited",
    "Full",
};

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

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

//---------------------------------------------------------------------------
const int8u Avc_pic_struct_Size=9;
static const char* Avc_pic_struct[]=
{
    "frame",
    "top field",
    "bottom field",
    "top field, bottom field",
    "bottom field, top field",
    "top field, bottom field, top field repeated",
    "bottom field, top field, bottom field repeated",
    "frame doubling",
    "frame tripling",
};

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

//---------------------------------------------------------------------------
static const char* Avc_ct_type[]=
{
    "Progressive",
    "Interlaced",
    "Unknown",
    "Reserved",
};

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

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

//---------------------------------------------------------------------------
const char* Avc_user_data_DTG1_active_format[]=
{
    //1st value is for 4:3, 2nd is for 16:9
    "", //Undefined
    "Reserved",
    "Not recommended",
    "Not recommended",
    "Aspect ratio greater than 16:9", //Use GA94
    "Reserved",
    "Reserved",
    "Reserved",
    "4:3 full frame image / 16:9 full frame image",
    "4:3 full frame image / 4:3 pillarbox image",
    "16:9 letterbox image / 16:9 full frame image",
    "14:9 letterbox image / 14:9 pillarbox image",
    "Reserved",
    "4:3 full frame image, alternative 14:9 center / 4:3 pillarbox image, alternative 14:9 center",
    "16:9 letterbox image, alternative 14:9 center / 16:9 full frame image, alternative 14:9 center",
    "16:9 letterbox image, alternative 4:3 center / 16:9 full frame image, alternative 4:3 center",
};

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

//---------------------------------------------------------------------------
static const char* Avc_ChromaSubsampling_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* Avc_ChromaSubsampling_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 "";
    }
}

//---------------------------------------------------------------------------
const char* Avc_user_data_GA94_cc_type(int8u cc_type)
{
    switch (cc_type)
    {
        case  0 : return "CEA-608 line 21 field 1 closed captions"; //closed caption 3 if this is second field
        case  1 : return "CEA-608 line 21 field 2 closed captions"; //closed caption 4 if this is second field
        case  2 : return "DTVCC Channel Packet Data";
        case  3 : return "DTVCC Channel Packet Start";
        default : return "";
    }
}

//---------------------------------------------------------------------------
int32u Avc_MaxDpbMbs(int8u level)
{
    switch (level)
    {
        case  10 : return    1485;
        case  11 : return    3000;
        case  12 : return    6000;
        case  13 :
        case  20 : return   11880;
        case  21 : return   19800;
        case  22 : return   20250;
        case  30 : return   40500;
        case  31 : return  108000;
        case  32 : return  216000;
        case  40 :
        case  41 : return  245760;
        case  42 : return  522240;
        case  50 : return  589824;
        case  51 : return  983040;
        default  : return       0;
    }
}

//---------------------------------------------------------------------------
namespace AVC_Intra_Headers
{
    //720p50
    static const size_t __720p50__50_Size = 4 * 0x10 + 0xA;
    static const int8u  __720p50__50[__720p50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
                                                            0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD,
                                                            0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0,
                                                            0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x06,
                                                            0x48, 0x40, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
    static const size_t __720p50_100_Size = 5 * 0x10 + 0x2;
    static const int8u  __720p50_100[__720p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1,
                                                            0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85,
                                                            0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08,
                                                            0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00,
                                                            0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x64, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31,
                                                            0x12, 0x11 };
    //720p60
    static const size_t __720p60__50_Size = 4 * 0x10 + 0xB;
    static const int8u  __720p60__50[__720p60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
                                                            0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD,
                                                            0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0,
                                                            0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x3E, 0x90, 0x00, 0x1D, 0x4C, 0x08,
                                                            0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
    static const size_t __720p60_100_Size = 5 * 0x10 + 0x1;
    static const int8u  __720p60_100[__720p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1,
                                                            0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85,
                                                            0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08,
                                                            0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00,
                                                            0x00, 0x03, 0x03, 0xE9, 0x00, 0x01, 0xD4, 0xC0, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31, 0x12,
                                                            0x11 };

    //1080i50
    static const size_t _1080i50__50_Size = 5 * 0x10 + 0xE;
    static const int8u  _1080i50__50[_1080i50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
                                                            0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87,
                                                            0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D,
                                                            0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81,
                                                            0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x03, 0x00,
                                                            0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
    static const size_t _1080i50_100_Size = 5 * 0x10 + 0xF;
    static const int8u  _1080i50_100[_1080i50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
                                                            0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24,
                                                            0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B,
                                                            0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C,
                                                            0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, 0x00,
                                                            0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
    //1080i60
    static const size_t _1080i60__50_Size = 5 * 0x10 + 0xD;
    static const int8u  _1080i60__50[_1080i60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
                                                            0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87,
                                                            0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D,
                                                            0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81,
                                                            0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x7D, 0x20,
                                                            0x00, 0x1D, 0x4C, 0x10, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
    static const size_t _1080i60_100_Size = 5 * 0x10 + 0xD;
    static const int8u  _1080i60_100[_1080i60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
                                                            0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24,
                                                            0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B,
                                                            0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C,
                                                            0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x1F, 0x48,
                                                            0x00, 0x07, 0x53, 0x04, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };

    //1080p50
    static const size_t _1080p50_100_Size = 4 * 0x10 + 0xA;
    static const int8u  _1080p50_100[_1080p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
                                                            0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F,
                                                            0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70,
                                                            0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x01, 0x92, 0x10,
                                                            0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
    //1080p60
    static const size_t _1080p60_100_Size = 4 * 0x10 + 0x8;
    static const int8u  _1080p60_100[_1080p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
                                                            0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F,
                                                            0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70,
                                                            0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x0F, 0xA4, 0x00, 0x07, 0x53, 0x02, 0x10, 0x00, 0x00,
                                                            0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
};


//---------------------------------------------------------------------------
// Some DV Metadata info: http://www.freepatentsonline.com/20050076039.pdf
static const char* MDPM(int8u ID)
{
    switch (ID)
    {
        case 0x18: return "Date/Time";                          // Is "Text header" in doc?
        case 0x19: return "Date/Time (continue 1)";             // Is "Text" in doc?
        case 0x70: return "Consumer Camera 1";
        case 0x71: return "Consumer Camera 2";
        case 0x73: return "Lens";
        case 0x7F: return "Camera shutter";
        case 0xA1: return "Iris (F)";
        case 0xE0: return "Make Model";
        case 0xE1: return "Rec Info";
        case 0xE4: return "Model Name";
        case 0xE5: return "Model Name (continue 1)";
        case 0xE6: return "Model Name (continue 1)";
        default  : return "";
    }
}

//---------------------------------------------------------------------------
static const char* MDPM_MakeName(int16u Value)
{
    switch (Value)
    {
        case 0x0103: return "Panasonic";
        case 0x0108: return "Sony";
        case 0x1011: return "Canon";
        case 0x1104: return "JVC";
        default    : return "";
    }
}

//---------------------------------------------------------------------------
// From DV
extern const char*  Dv_consumer_camera_1_ae_mode[];
extern const char*  Dv_consumer_camera_1_wb_mode[];
extern const char*  Dv_consumer_camera_1_white_balance(int8u white_balance);
extern const char*  Dv_consumer_camera_1_fcm[];

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

//---------------------------------------------------------------------------
File_Avc::File_Avc()
#if MEDIAINFO_DUPLICATE
:File__Duplicate()
#endif //MEDIAINFO_DUPLICATE
{
    //Config
    #if MEDIAINFO_EVENTS
        ParserIDs[0]=MediaInfo_Parser_Avc;
        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_SPS_PPS=false;
    SizedBlocks=false;

    //Temporal references
    TemporalReferences_DelayedElement=NULL;

    //Temp
    preferred_transfer_characteristics=2;

    //Text
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        GA94_03_Parser=NULL;
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
}

//---------------------------------------------------------------------------
File_Avc::~File_Avc()
{
    Clean_Temp_References();
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        delete GA94_03_Parser; //GA94_03_Parser=NULL;
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
     Clean_Seq_Parameter();
}

//---------------------------------------------------------------------------
void File_Avc::Clean_Temp_References()
{
    for (size_t Pos = 0; Pos<TemporalReferences.size(); Pos++)
        delete TemporalReferences[Pos]; //TemporalReferences[Pos]=NULL;
    TemporalReferences.clear();
}
//---------------------------------------------------------------------------
void File_Avc::Clean_Seq_Parameter()
{
    for (size_t Pos = 0; Pos<seq_parameter_sets.size(); Pos++)
        delete seq_parameter_sets[Pos]; //TemporalReferences[Pos]=NULL;
    seq_parameter_sets.clear();
    for (size_t Pos = 0; Pos<subset_seq_parameter_sets.size(); Pos++)
        delete subset_seq_parameter_sets[Pos]; //subset_seq_parameter_sets[Pos]=NULL;
    subset_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();
}
//***************************************************************************
// AVC-Intra hardcoded headers
//***************************************************************************

//---------------------------------------------------------------------------
File_Avc::avcintra_header File_Avc::AVC_Intra_Headers_Data(int32u CodecID)
{
    switch (CodecID)
    {
        case  0x61693132: //ai12
        case  0x61693232: //ai22
                            return avcintra_header(AVC_Intra_Headers::_1080p50_100, AVC_Intra_Headers::_1080p50_100_Size);  // AVC-Intra 1080p50 class 100/200
        case  0x61693133: //ai13
        case  0x61693233: //ai23
                            return avcintra_header(AVC_Intra_Headers::_1080p60_100, AVC_Intra_Headers::_1080p60_100_Size);  // AVC-Intra 1080p60 class 100/200
        case  0x61693135: //ai15
        case  0x61693235: //ai25
                            return avcintra_header(AVC_Intra_Headers::_1080i50_100, AVC_Intra_Headers::_1080i50_100_Size);  // AVC-Intra 1080i50 class 100/200
        case  0x61693136: //ai16
        case  0x61693236: //ai26
                            return avcintra_header(AVC_Intra_Headers::_1080i60_100, AVC_Intra_Headers::_1080i60_100_Size);  // AVC-Intra 1080i60 class 100/200
        case  0x61693170: //ai1p
        case  0x61693270: //ai2p
                            return avcintra_header(AVC_Intra_Headers::__720p60_100, AVC_Intra_Headers::__720p60_100_Size);  // AVC-Intra  720p60 class 100/200
        case  0x61693171: //ai1q
        case  0x61693271: //ai2q
                            return avcintra_header(AVC_Intra_Headers::__720p50_100, AVC_Intra_Headers::__720p50_100_Size);  // AVC-Intra  720p50 class 100/200
      //case  0x61693532: //ai52
      //                    return avcintra_header(NULL, 0);                                                                // AVC-Intra 1080p25 class  50 (not supported)
      //case  0x61693533: //ai53
      //                    return avcintra_header(NULL, 0);                                                                // AVC-Intra 1080p30 class  50 (not supported)
        case  0x61693535: //ai55
                            return avcintra_header(AVC_Intra_Headers::_1080i50__50, AVC_Intra_Headers::_1080i50__50_Size);  // AVC-Intra 1080i50 class  50
        case  0x61693536: //ai56
                            return avcintra_header(AVC_Intra_Headers::_1080i60__50, AVC_Intra_Headers::_1080i60__50_Size);  // AVC-Intra 1080i60 class  50
        case  0x61693570: //ai5p
                            return avcintra_header(AVC_Intra_Headers::__720p60__50, AVC_Intra_Headers::__720p60__50_Size);  // AVC-Intra  720p60 class  50
        case  0x61693571: //ai5q
                            return avcintra_header(AVC_Intra_Headers::__720p50__50, AVC_Intra_Headers::__720p50__50_Size);  // AVC-Intra  720p50 class  50
        default       :
                            return avcintra_header(NULL, 0);
    }
}

//---------------------------------------------------------------------------
int32u File_Avc::AVC_Intra_CodecID_FromMeta(int32u Width, int32u Height, int32u Fields, int32u SampleDuration, int32u TimeScale, int32u SizePerFrame)
{
    // Computing bitrate
    int64u BitRate=SampleDuration?(((int64u)SizePerFrame)*8*TimeScale/SampleDuration):0;
    int64u SampleRate=SampleDuration?(float64_int64s(((float64)TimeScale)/SampleDuration)):0;
    int32u Class;
    switch (Width)
    {
    case 1920:
        Class=100;
        break;
    case 1440:
    case 1280:
    case 960:
        Class=50;
        break;
    default:
        if (!BitRate)
            return 0x4156696E; //AVin (neutral)
        Class=BitRate<=75000000?50:100; //Arbitrary choosen. TODO: check real maximumm bitrate, check class 200
        break;
    }
    switch (Class)
    {
        case 100 : 
                    switch (Height)
                    {
                        case 1088 :
                        case 1080 :
                                    switch (Fields)
                                    {
                                        case 1: 
                                                    switch (SampleRate)
                                                    {
                                                        case 50: return 0x61693132; //ai12
                                                        case 60: return 0x61693133; //ai13
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        case 2: 
                                                    switch (SampleRate)
                                                    {
                                                        case 25: return 0x61693135; //ai15 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 30: return 0x61693136; //ai16 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 50: return 0x61693135; //ai15 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 60: return 0x61693136; //ai16 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        default:    return 0x4156696E; //AVin (neutral)
                                    }
                        case  720 :
                                    switch (Fields)
                                    {
                                        case 1: 
                                                    switch (SampleRate)
                                                    {
                                                        case 50: return 0x61693170; //ai1p
                                                        case 60: return 0x61693171; //ai1q
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        default:    return 0x4156696E; //AVin (neutral)
                                    }
                        default   : return 0x4156696E; //AVin (neutral)
                    }
        case  50 : 
                    switch (Height)
                    {
                        case 1088 :
                        case 1080 :
                                    switch (Fields)
                                    {
                                        case 1: 
                                                    switch (SampleRate)
                                                    {
                                                        case 25: return 0x61693532; //ai52
                                                        case 30: return 0x61693533; //ai53
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        case 2: 
                                                    switch (SampleRate)
                                                    {
                                                        case 25: return 0x61693535; //ai55 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 30: return 0x61693536; //ai56 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 50: return 0x61693535; //ai55 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        case 60: return 0x61693536; //ai56 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        default:    return 0x4156696E; //AVin (neutral)
                                    }
                        case  720 :
                                    switch (Fields)
                                    {
                                        case 1: 
                                                    switch (SampleRate)
                                                    {
                                                        case 50: return 0x61693570; //ai5p
                                                        case 60: return 0x61693571; //ai5q
                                                        default: return 0x4156696E; //AVin (neutral)
                                                    }
                                        default:    return 0x4156696E; //AVin (neutral)
                                    }
                        default   : return 0x4156696E; //AVin (neutral)
                    }
        default: return 0x4156696E; //AVin (neutral)
    }
}

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

//---------------------------------------------------------------------------
void File_Avc::Streams_Fill()
{
    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);
    for (std::vector<seq_parameter_set_struct*>::iterator subset_seq_parameter_set_Item=subset_seq_parameter_sets.begin(); subset_seq_parameter_set_Item!=subset_seq_parameter_sets.end(); ++subset_seq_parameter_set_Item)
        if ((*subset_seq_parameter_set_Item))
        {
            if (seq_parameter_sets.empty())
                Streams_Fill(subset_seq_parameter_set_Item);
            else
                Streams_Fill_subset(subset_seq_parameter_set_Item);
            Fill(Stream_Video, 0, Video_MultiView_Count, (*subset_seq_parameter_set_Item)->num_views_minus1+1);
        }

    #if MEDIAINFO_ADVANCED2
        for (size_t Pos = 0; Pos<Dump_SPS.size(); Pos++)
            Fill(Stream_Video, 0, "Dump_seq_parameter_set", Dump_SPS[Pos].c_str());
        for (size_t Pos = 0; Pos<Dump_PPS.size(); Pos++)
            Fill(Stream_Video, 0, "Dump_pic_parameter_set", Dump_PPS[Pos].c_str());
    #endif //MEDIAINFO_ADVANCED2
}

//---------------------------------------------------------------------------
void File_Avc::Streams_Fill(std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item)
{
    if (Count_Get(Stream_Video))
        return;
    Stream_Prepare(Stream_Video);
    Fill(Stream_Video, 0, Video_Format, "AVC");
    Fill(Stream_Video, 0, Video_Codec, "AVC");

    //Calculating - Pixels
    int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1       +1)*16;
    int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
    int8u chromaArrayType = (*seq_parameter_set_Item)->ChromaArrayType();
    if (chromaArrayType >= 4)
        chromaArrayType = 0;
    int32u CropUnitX=Avc_SubWidthC [chromaArrayType];
    int32u CropUnitY=Avc_SubHeightC[chromaArrayType]*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
    Width -=((*seq_parameter_set_Item)->frame_crop_left_offset+(*seq_parameter_set_Item)->frame_crop_right_offset )*CropUnitX;
    Height-=((*seq_parameter_set_Item)->frame_crop_top_offset +(*seq_parameter_set_Item)->frame_crop_bottom_offset)*CropUnitY;

    //From vui_parameters
    float64 PixelAspectRatio=1;
    if ((*seq_parameter_set_Item)->vui_parameters)
    {
        if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag)
        {
            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;
        }
        if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag)
        {
            if (!(*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag)
                Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Mode, "VFR");
            else if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*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/((*seq_parameter_set_Item)->frame_mbs_only_flag?2:(((*seq_parameter_set_Item)->pic_order_cnt_type==2 && Structure_Frame/2>Structure_Field)?1:2))/FrameRate_Divider);
        }

        //Colour description
        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->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);
            }
        }

        //hrd_parameter_sets
        int64u bit_rate_value=(int64u)-1;
        bool   bit_rate_value_IsValid=true;
        bool   cbr_flag=false;
        bool   cbr_flag_IsSet=false;
        bool   cbr_flag_IsValid=true;
        seq_parameter_set_struct::vui_parameters_struct::xxl* NAL=(*seq_parameter_set_Item)->vui_parameters->NAL;
        if (NAL)
            for (size_t Pos=0; Pos<NAL->SchedSel.size(); Pos++)
            {
                if (NAL->SchedSel[Pos].cpb_size_value!=(int32u)-1)
                    Fill(Stream_Video, 0, Video_BufferSize, NAL->SchedSel[Pos].cpb_size_value);
                if (bit_rate_value!=(int64u)-1 && bit_rate_value!=NAL->SchedSel[Pos].bit_rate_value)
                    bit_rate_value_IsValid=false;
                if (bit_rate_value==(int64u)-1)
                    bit_rate_value=NAL->SchedSel[Pos].bit_rate_value;
                if (cbr_flag_IsSet==true && cbr_flag!=NAL->SchedSel[Pos].cbr_flag)
                    cbr_flag_IsValid=false;
                if (cbr_flag_IsSet==0)
                {
                    cbr_flag=NAL->SchedSel[Pos].cbr_flag;
                    cbr_flag_IsSet=true;
                }
            }
        seq_parameter_set_struct::vui_parameters_struct::xxl* VCL=(*seq_parameter_set_Item)->vui_parameters->VCL;
        if (VCL)
            for (size_t Pos=0; Pos<VCL->SchedSel.size(); Pos++)
            {
                Fill(Stream_Video, 0, Video_BufferSize, VCL->SchedSel[Pos].cpb_size_value);
                if (bit_rate_value!=(int64u)-1 && bit_rate_value!=VCL->SchedSel[Pos].bit_rate_value)
                    bit_rate_value_IsValid=false;
                if (bit_rate_value==(int64u)-1)
                    bit_rate_value=VCL->SchedSel[Pos].bit_rate_value;
                if (cbr_flag_IsSet==true && cbr_flag!=VCL->SchedSel[Pos].cbr_flag)
                    cbr_flag_IsValid=false;
                if (cbr_flag_IsSet==0)
                {
                    cbr_flag=VCL->SchedSel[Pos].cbr_flag;
                    cbr_flag_IsSet=true;
                }
            }
        if (cbr_flag_IsSet && cbr_flag_IsValid)
        {
            Fill(Stream_Video, 0, Video_BitRate_Mode, cbr_flag?"CBR":"VBR");
            if (bit_rate_value!=(int64u)-1 && bit_rate_value_IsValid)
                Fill(Stream_Video, 0, cbr_flag?Video_BitRate_Nominal:Video_BitRate_Maximum, bit_rate_value);
        }
    }

    Ztring Profile=Ztring().From_UTF8(Avc_profile_idc((*seq_parameter_set_Item)->profile_idc));
    switch ((*seq_parameter_set_Item)->profile_idc)
    {
        case  44 : // CAVLC 4:4:4 Intra
        case 100 : // High
        case 110 : // High 10
        case 122 : // High 4:2:2"
        case 244 : // High 4:4:4 Predictive
                    if ((*seq_parameter_set_Item)->constraint_set3_flag)
                        Profile+=__T(" Intra");
    }
    Profile+=__T("@L")+Ztring().From_Number(((float)(*seq_parameter_set_Item)->level_idc)/10, ((*seq_parameter_set_Item)->level_idc%10)?1:0);
    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)->frame_crop_left_offset || (*seq_parameter_set_Item)->frame_crop_right_offset)
        Fill(Stream_Video, StreamPos_Last, Video_Stored_Width, ((*seq_parameter_set_Item)->pic_width_in_mbs_minus1       +1)*16);
    if ((*seq_parameter_set_Item)->frame_crop_top_offset || (*seq_parameter_set_Item)->frame_crop_bottom_offset)
        Fill(Stream_Video, StreamPos_Last, Video_Stored_Height, ((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag));
    Fill(Stream_Video, 0, Video_PixelAspectRatio, PixelAspectRatio, 3, true);
    if(Height)
        Fill(Stream_Video, 0, Video_DisplayAspectRatio, Width*PixelAspectRatio/Height, 3, true); //More precise
    if (FrameRate_Divider==2)
    {
        Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame doubling");
        Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame doubling");
    }
    if (FrameRate_Divider==3)
    {
        Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame tripling");
        Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame tripling");
    }

    //Interlacement
    if ((*seq_parameter_set_Item)->mb_adaptive_frame_field_flag && Structure_Frame>0) //Interlaced macro-block
    {
        Fill(Stream_Video, 0, Video_ScanType, "MBAFF");
        Fill(Stream_Video, 0, Video_Interlacement, "MBAFF");
    }
    else if ((*seq_parameter_set_Item)->frame_mbs_only_flag || (Structure_Frame>0 && Structure_Field==0)) //No interlaced frame
    {
        switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected)
        {
            case  3 :
                        Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
                        Fill(Stream_Video, 0, Video_Interlacement, "TFF");
                        Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame");
                        Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields");
                        break;
            case  4 :
                        Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
                        Fill(Stream_Video, 0, Video_Interlacement, "BFF");
                        Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame");
                        Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields");
                        break;
            default :
                        Fill(Stream_Video, 0, Video_ScanType, "Progressive");
                        Fill(Stream_Video, 0, Video_Interlacement, "PPF");
        }
    }
    else if (Structure_Field>0)
    {
        Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
        Fill(Stream_Video, 0, Video_Interlacement, "Interlaced");
    }
    std::string ScanOrders, PictureTypes(PictureTypes_PreviousFrames);
    ScanOrders.reserve(TemporalReferences.size());
    for (size_t Pos=0; Pos<TemporalReferences.size(); Pos++)
        if (TemporalReferences[Pos])
        {
            ScanOrders+=TemporalReferences[Pos]->IsTop?'T':'B';
            if ((Pos%2)==0)
                PictureTypes+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
        }
        else if (!PictureTypes.empty()) //Only if stream already started
        {
            ScanOrders+=' ';
            if ((Pos%2)==0)
                PictureTypes+=' ';
        }
    Fill(Stream_Video, 0, Video_ScanOrder, ScanOrder_Detect(ScanOrders));
    { //Legacy
        string Result=ScanOrder_Detect(ScanOrders);
        if (!Result.empty())
        {
            Fill(Stream_Video, 0, Video_Interlacement, Result, true, true);
            Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
        }
        else
        {
            switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected)
            {
                case  1 :
                            Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF");
                            Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
                            break;
                case  2 :
                            Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF");
                            Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
                            break;
                case  3 :
                            Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF");
                            Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true);
                            break;
                case  4 :
                            Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF");
                            Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true);
                            break;
                default : ;
            }
        }
    }
    Fill(Stream_Video, 0, Video_Format_Settings_GOP, GOP_Detect(PictureTypes));

    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);
    if (Retrieve_Const(Stream_Video, 0, Video_BitRate_Nominal).empty()) // SPS has priority over other metadata
        Fill(Stream_Video, 0, Video_BitRate_Nominal, BitRate_Nominal);
    Fill(Stream_Video, 0, Video_MuxingMode, MuxingMode);
    for (std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item=pic_parameter_sets.begin(); pic_parameter_set_Item!=pic_parameter_sets.end(); ++pic_parameter_set_Item)
        if (*pic_parameter_set_Item && (*pic_parameter_set_Item)->seq_parameter_set_id==seq_parameter_set_Item-(seq_parameter_sets.empty()?subset_seq_parameter_sets.begin():seq_parameter_sets.begin()))
        {
            if ((*pic_parameter_set_Item)->entropy_coding_mode_flag)
            {
                Fill(Stream_Video, 0, Video_Format_Settings, "CABAC");
                Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "Yes");
                Fill(Stream_Video, 0, Video_Codec_Settings, "CABAC");
                Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "Yes");
            }
            else
            {
                Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "No");
                Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "No");
            }
            break; //TODO: currently, testing only the first pic_parameter_set
        }
    if ((*seq_parameter_set_Item)->max_num_ref_frames>0)
    {
        Fill(Stream_Video, 0, Video_Format_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames"));
        Fill(Stream_Video, 0, Video_Codec_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames"));
        Fill(Stream_Video, 0, Video_Format_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames);
        Fill(Stream_Video, 0, Video_Codec_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames);
    }
    if (Retrieve(Stream_Video, 0, Video_ColorSpace).empty())
        Fill(Stream_Video, 0, Video_ColorSpace, Avc_ChromaSubsampling_format_idc_ColorSpace((*seq_parameter_set_Item)->chroma_format_idc));
    Fill(Stream_Video, 0, Video_ChromaSubsampling, Avc_ChromaSubsampling_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);

    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;
            default:
                Ignore = false;
            }
            if (!Ignore)
                Fill(Stream_Video, 0, Item->first, Item->second);
        }
    }

    if (!maximum_content_light_level.empty())
        Fill(Stream_Video, 0, Video_MaxCLL, maximum_content_light_level);
    if (!maximum_frame_average_light_level.empty())
        Fill(Stream_Video, 0, Video_MaxFALL, maximum_frame_average_light_level);
}

//---------------------------------------------------------------------------
void File_Avc::Streams_Fill_subset(const std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item)
{
    Ztring Profile=Ztring().From_UTF8(Avc_profile_idc((*seq_parameter_set_Item)->profile_idc))+__T("@L")+Ztring().From_Number(((float)(*seq_parameter_set_Item)->level_idc)/10, 1);
    Ztring Profile_Base=Retrieve(Stream_Video, 0, Video_Format_Profile);
    Fill(Stream_Video, 0, Video_Format_Profile, Profile, true);
    if (!Profile_Base.empty())
        Fill(Stream_Video, 0, Video_Format_Profile, Profile_Base);
}

//---------------------------------------------------------------------------
void File_Avc::Streams_Finish()
{
    if (PTS_End!=(int64u)-1 && (IsSub || File_Offset+Buffer_Offset+Element_Size==File_Size))
    {
        if (PTS_End>PTS_Begin)
            Fill(Stream_Video, 0, Video_Duration, float64_int64s(((float64)(PTS_End-PTS_Begin))/1000000));
    }

    //GA94 captions
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        if (GA94_03_Parser && GA94_03_Parser->Status[IsAccepted])
        {
            Clear(Stream_Text);

            Finish(GA94_03_Parser);
            Merge(*GA94_03_Parser);

            Ztring LawRating=GA94_03_Parser->Retrieve(Stream_General, 0, General_LawRating);
            if (!LawRating.empty())
                Fill(Stream_General, 0, General_LawRating, LawRating, true);
            Ztring Title=GA94_03_Parser->Retrieve(Stream_General, 0, General_Title);
            if (!Title.empty() && Retrieve(Stream_General, 0, General_Title).empty())
                Fill(Stream_General, 0, General_Title, Title);

            for (size_t Pos=0; Pos<Count_Get(Stream_Text); Pos++)
            {
                Ztring MuxingMode=Retrieve(Stream_Text, Pos, "MuxingMode");
                Fill(Stream_Text, Pos, "MuxingMode", __T("SCTE 128 / ")+MuxingMode, true);
            }
        }
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)

    #if MEDIAINFO_IBIUSAGE
        if (seq_parameter_sets.size()==1 && (*seq_parameter_sets.begin())->vui_parameters && (*seq_parameter_sets.begin())->vui_parameters->timing_info_present_flag && (*seq_parameter_sets.begin())->vui_parameters->fixed_frame_rate_flag)
            Ibi_Stream_Finish((*seq_parameter_sets.begin())->vui_parameters->time_scale, (*seq_parameter_sets.begin())->vui_parameters->num_units_in_tick);
    #endif //MEDIAINFO_IBIUSAGE
}

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

//---------------------------------------------------------------------------
bool File_Avc::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_Avc::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;

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

//---------------------------------------------------------------------------
bool File_Avc::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;

    #if MEDIAINFO_IBIUSAGE
        bool zero_byte=Buffer[Buffer_Offset+2]==0x00;
        bool RandomAccess=(Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x07 || ((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x09 && ((Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0x00 || (Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0xA0)); //seq_parameter_set or access_unit_delimiter with value=0 or 5 (3 bits)
        if (RandomAccess)
            Ibi_Add();
    #endif //MEDIAINFO_IBIUSAGE

    //We continue
    return true;
}

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

//---------------------------------------------------------------------------
#if MEDIAINFO_DEMUX
void File_Avc::Data_Parse_Iso14496()
{
    if (Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10)
    {
        if (Element_Code==0x07)
        {
            std::vector<seq_parameter_set_struct*>::iterator Data_Item=seq_parameter_sets.begin();
            if (Data_Item!=seq_parameter_sets.end() && (*Data_Item))
            {
                (*Data_Item)->Init_Iso14496_10(0x67, Buffer+Buffer_Offset, Element_Size);
            }
        }
        if (Element_Code==0x08)
        {
            std::vector<pic_parameter_set_struct*>::iterator Data_Item=pic_parameter_sets.begin();
            if (Data_Item!=pic_parameter_sets.end() && (*Data_Item))
            {
                (*Data_Item)->Init_Iso14496_10(0x68, Buffer+Buffer_Offset, Element_Size);
            }
        }
        if (Element_Code==0x0F)
        {
            std::vector<seq_parameter_set_struct*>::iterator Data_Item=subset_seq_parameter_sets.begin();
            if (Data_Item!=subset_seq_parameter_sets.end() && (*Data_Item))
            {
                SizeOfNALU_Minus1=0;
                (*Data_Item)->Init_Iso14496_10(0x6F, Buffer+Buffer_Offset, Element_Size);
            }
        }
    }
}

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

    if ((MustParse_SPS_PPS || SizedBlocks) && Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10)
    {
        if (MustParse_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+SizeOfNALU_Minus1+1+1<=Buffer_Size)
        {
            size_t Size;
            if (Buffer_Offset+SizeOfNALU_Minus1>Buffer_Size)
            {
                Size=0;
                Buffer_Offset=Buffer_Size;
            }
            else
            switch (SizeOfNALU_Minus1)
            {
                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+=SizeOfNALU_Minus1+1;

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

            //Random access check
            if (!RandomAccess && Buffer_Offset+SizeOfNALU_Minus1+1<Buffer_Size && (Buffer[Buffer_Offset+SizeOfNALU_Minus1+1]&0x1F) && (Buffer[Buffer_Offset+SizeOfNALU_Minus1+1]&0x1F)<=5) //Is a slice
            {
                int32u slice_type;
                Element_Offset=SizeOfNALU_Minus1+1+1;
                Element_Size=Size;
                BS_Begin();
                Skip_UE("first_mb_in_slice");
                Get_UE (slice_type, "slice_type");
                BS_End();
                Element_Offset=0;

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

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

        //Adding SPS/PPS sizes
        if (RandomAccess)
        {
            for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item)
                TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size;
            for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item)
                TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_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)->Iso14496_10_Buffer_Size;
        }

        //Copying
        int8u* TranscodedBuffer=new int8u[TranscodedBuffer_Size+100];
        size_t TranscodedBuffer_Pos=0;
        if (RandomAccess)
        {
            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)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size;
            }
            for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item)
            {
                std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_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)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
                TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_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 (SizeOfNALU_Minus1)
            {
                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+SizeOfNALU_Minus1+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)]&0x1B)==0x01 && (Buffer[Buffer_Offset+(zero_byte?5:4)]&0x80)!=0x80)
           || (Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x0C))
        {
            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;
                if (Demux_IntermediateItemFound)
                {
                    if (!(((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)!=0x80)
                        || (Buffer[Demux_Offset+(zero_byte?4:3)]&0x1F)==0x0C))
                        break;
                }
                else
                {
                    if ((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)==0x80)
                        Demux_IntermediateItemFound=true;
                }

                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)]&0x1F)==0x09)
            {
                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)]&0x1F)==0x07; //seq_parameter_set
        }
    }

    if (!Status[IsAccepted])
    {
        if (Config->Demux_EventWasSent)
            return false;
        File_Avc* MI=new File_Avc;
        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)
    {
        bool Frame_Count_NotParsedIncluded_PlusOne=false;
        int64u PTS_Temp=FrameInfo.PTS;
        if (!IsSub)
            FrameInfo.PTS=(int64u)-1;
        if (Frame_Count_NotParsedIncluded!=(int64u)-1 && Interlaced_Top!=Interlaced_Bottom)
        {
            Frame_Count_NotParsedIncluded--;
            Frame_Count_NotParsedIncluded_PlusOne=true;
        }
        Demux_UnpacketizeContainer_Demux(RandomAccess);
        if (!IsSub)
            FrameInfo.PTS=PTS_Temp;
        if (Frame_Count_NotParsedIncluded_PlusOne)
            Frame_Count_NotParsedIncluded++;
    }
    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_Avc::Synched_Init()
{
    if (!Frame_Count_Valid)
        Frame_Count_Valid=Config->ParseSpeed>=0.3?512:(IsSub?1:2);

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

    //Temporal references
    TemporalReferences_DelayedElement=NULL;
    TemporalReferences_Min=0;
    TemporalReferences_Max=0;
    TemporalReferences_Reserved=0;
    TemporalReferences_Offset=0;
    TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
    TemporalReferences_pic_order_cnt_Min=0;

    //Text
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        GA94_03_IsPresent=false;
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)

    //File specific
    SizeOfNALU_Minus1=(int8u)-1;

    //Status
    IFrame_Count=0;
    prevPicOrderCntMsb=0;
    prevPicOrderCntLsb=(int32u)-1;
    prevTopFieldOrderCnt=(int32u)-1;
    prevFrameNum=(int32u)-1;
    prevFrameNumOffset=(int32u)-1;

    //Count of a Packets
    Block_Count=0;
    Interlaced_Top=0;
    Interlaced_Bottom=0;
    Structure_Field=0;
    Structure_Frame=0;

    //Temp
    FrameRate_Divider=1;
    FirstPFrameInGop_IsParsed=false;
    Config_IsRepeated=false;
    tc=0;

    //Default values
    Streams.resize(0x100);
    Streams[0x06].Searching_Payload=true; //sei
    Streams[0x07].Searching_Payload=true; //seq_parameter_set
    Streams[0x09].Searching_Payload=true; //access_unit_delimiter
    Streams[0x0F].Searching_Payload=true; //subset_seq_parameter_set
    for (int8u Pos=0xFF; Pos>=0xB9; Pos--)
        Streams[Pos].Searching_Payload=true; //Testing MPEG-PS

    //Options
    Option_Manage();

    //Specific cases
    #if MEDIAINFO_EVENTS
        if (Config->ParseUndecodableFrames_Get())
        {
            Accept(); //In some case, we must accept the stream very quickly and before the sequence header is detected
            Streams[0x01].Searching_Payload=true; //slice_header
            Streams[0x05].Searching_Payload=true; //slice_header
        }
    #endif //MEDIAINFO_EVENTS
    #if MEDIAINFO_DEMUX
        Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10=Config->Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10_Get();
    #endif //MEDIAINFO_DEMUX
}

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

//---------------------------------------------------------------------------
#if MEDIAINFO_ADVANCED2
void File_Avc::Read_Buffer_SegmentChange()
{
}
#endif //MEDIAINFO_ADVANCED2

//---------------------------------------------------------------------------
void File_Avc::Read_Buffer_Unsynched()
{
    //Temporal references
    Clean_Temp_References();
    delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=NULL;
    TemporalReferences_Min=0;
    TemporalReferences_Max=0;
    TemporalReferences_Reserved=0;
    TemporalReferences_Offset=0;
    TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
    TemporalReferences_pic_order_cnt_Min=0;

    //Text
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        if (GA94_03_Parser)
            GA94_03_Parser->Open_Buffer_Unsynch();
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)

    //parameter_sets
    if (SizedBlocks || !Config_IsRepeated) //If sized blocks, it is not a broadcasted stream so SPS/PPS are only in container header, we must not disable them.
    {
        //Rebuilding immediatly TemporalReferences
        seq_parameter_set_structs* _seq_parameter_sets=!seq_parameter_sets.empty()?&seq_parameter_sets:&subset_seq_parameter_sets; //Some MVC streams have no seq_parameter_sets. TODO: better management of temporal references
        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))
            {
                size_t MaxNumber;
                switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
                {
                    case 0 : MaxNumber=(*seq_parameter_set_Item)->MaxPicOrderCntLsb; break;
                    case 2 : MaxNumber=(*seq_parameter_set_Item)->MaxFrameNum*2; break;
                    default: Trusted_IsNot("Not supported"); return;
                }

                TemporalReferences.resize(4*MaxNumber);
                TemporalReferences_Reserved=MaxNumber;
            }
    }
    else
    {
        Clean_Seq_Parameter();
    }

    //Status
    Interlaced_Top=0;
    Interlaced_Bottom=0;
    prevPicOrderCntMsb=0;
    prevPicOrderCntLsb=(int32u)-1;
    prevTopFieldOrderCnt=(int32u)-1;
    prevFrameNum=(int32u)-1;
    prevFrameNumOffset=(int32u)-1;

    //Temp
    FrameRate_Divider=1;
    FirstPFrameInGop_IsParsed=false;
    tc=0;

    //Impossible to know TimeStamps now
    PTS_End=0;
    DTS_End=0;
}

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

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

    //Parsing
    int8u nal_unit_type;
    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 ( 2, nal_ref_idc,                                "nal_ref_idc");
        Get_S1 ( 5, nal_unit_type,                              "nal_unit_type");
        BS_End();
        if (!Header_Parser_Fill_Size())
        {
            Element_WaitForMoreData();
            return;
        }
    }
    else
    {
        int64u Size;
        switch (SizeOfNALU_Minus1)
        {
            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: {
                        int32u Size_;
                        Get_B4 (Size_,                          "size");
                        Size=Size_;
                    }
                    break;
        }
        Size+=Element_Offset;
        if (Size==Element_Offset || Buffer_Offset+Size>Buffer_Size) //If Size is 0 or Size biger than sample size, it is not normal, we skip the complete frame
            Size=Buffer_Size-Buffer_Offset;
        Header_Fill_Size(Size);
        BS_Begin();
        Mark_0 ();
        Get_S1 ( 2, nal_ref_idc,                                "nal_ref_idc");
        Get_S1 ( 5, nal_unit_type,                              "nal_unit_type");
        BS_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_Avc::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_Avc::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 start_code;
        if (Buffer[Buffer_Offset+2]==0x00)
            start_code=CC1(Buffer+Buffer_Offset+4)&0x1F;
        else
            start_code=CC1(Buffer+Buffer_Offset+3)&0x1F;

        //Searching start
        if (Streams[start_code].Searching_Payload
         || Streams[start_code].ShouldDuplicate)
            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("AVC, Synchronisation lost");
    return Synchronize();
}

//---------------------------------------------------------------------------
void File_Avc::Data_Parse()
{
    //Specific case
    if (Element_Code==(int64u)-1)
    {
        SPS_PPS();
        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--;
    }

    //Dump of the SPS/PPS - Init
    #if MEDIAINFO_ADVANCED2
        size_t spspps_Size=0;
        if (true) //TODO: add an option for activating this extra piece of information in the output
        {
            switch (Element_Code)
            {
                case 0x07 : //seq_parameter_set();
                            spspps_Size = seq_parameter_sets.size();
                            break;
                case 0x08 : //pic_parameter_set();
                            spspps_Size = pic_parameter_sets.size();
                            break;
                default: ;
            }
        }
    #endif //MEDIAINFO_ADVANCED2

    //svc_extension
    bool svc_extension_flag=false;
    if (Element_Code==0x0E || Element_Code==0x14)
    {
        BS_Begin();
        Get_SB (svc_extension_flag,                             "svc_extension_flag");
        if (svc_extension_flag)
            nal_unit_header_svc_extension();
        else
            nal_unit_header_mvc_extension();
        BS_End();
    }

    //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 0x00 : Element_Name("unspecified"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x01 : slice_layer_without_partitioning_non_IDR(); break;
        case 0x02 : Element_Name("slice_data_partition_a_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x03 : Element_Name("slice_data_partition_b_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x04 : Element_Name("slice_data_partition_c_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x05 : slice_layer_without_partitioning_IDR(); break;
        case 0x06 : sei(); break;
        case 0x07 : seq_parameter_set(); break;
        case 0x08 : pic_parameter_set(); break;
        case 0x09 : access_unit_delimiter(); break;
        case 0x0A : Element_Name("end_of_seq"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x0B : Element_Name("end_of_stream"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x0C : filler_data(); break;
        case 0x0D : Element_Name("seq_parameter_set_extension"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x0E : prefix_nal_unit(svc_extension_flag); break;
        case 0x0F : subset_seq_parameter_set(); break;
        case 0x13 : Element_Name("slice_layer_without_partitioning"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
        case 0x14 : slice_layer_extension(svc_extension_flag); break;
        default :
            if (Element_Code<0x18)
                Element_Name("reserved");
            else
                Element_Name("unspecified");
            Skip_XX(Element_Size-Element_Offset, "Data");
    }

    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();
    }

    //Duplicate
    #if MEDIAINFO_DUPLICATE
        if (!Streams.empty() && Streams[(size_t)Element_Code].ShouldDuplicate)
            File__Duplicate_Write(Element_Code);
    #endif //MEDIAINFO_DUPLICATE

    #if MEDIAINFO_DEMUX
        Data_Parse_Iso14496();
    #endif //MEDIAINFO_DEMUX

    //Dump of the SPS/PPS - Fill
    #if MEDIAINFO_ADVANCED2
        if (false) //TODO: add an option for activating this extra piece of information in the output
        {
            switch (Element_Code)
            {
                case 0x07 : //seq_parameter_set();
                            if (spspps_Size != seq_parameter_sets.size() && !Status[IsFilled])
                            {
                                std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header
                                Dump_SPS.push_back(Base64::encode(Data_Raw));
                            }
                            break;
                case 0x08 : //pic_parameter_set();
                            if (spspps_Size != pic_parameter_sets.size() && !Status[IsFilled])
                            {
                                std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header
                                Dump_PPS.push_back(Base64::encode(Data_Raw));
                            }
                            break;
                default: ;
            }
        }
    #endif //MEDIAINFO_ADVANCED2

    #if MEDIAINFO_DEMUX
        Data_Parse_Iso14496();
    #endif //MEDIAINFO_DEMUX

    //Trailing zeroes
    Element_Size=Element_Size_SaveBeforeZeroes;
}

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

//---------------------------------------------------------------------------
// Packet "01"
void File_Avc::slice_layer_without_partitioning_non_IDR()
{
    Element_Name("slice_layer_without_partitioning (non-IDR)");

    //Parsing
    BS_Begin();
    slice_header();
    slice_data(true);
    BS_End();
}

//---------------------------------------------------------------------------
// Packet "05"
void File_Avc::slice_layer_without_partitioning_IDR()
{
    Element_Name("slice_layer_without_partitioning (IDR)");

    //Parsing
    BS_Begin();
    slice_header();
    slice_data(true);
    BS_End();

    FILLING_BEGIN_PRECISE();
        //NextCode
        for (int8u Pos=0x01; Pos<=0x05; Pos++)
            NextCode_Add(Pos);
    FILLING_END();
}

//---------------------------------------------------------------------------
//
void File_Avc::slice_header()
{
    //Encryption management
    if (CA_system_ID_MustSkipSlices)
    {
        //Is not decodable
        Skip_BS(Data_BS_Remain(),                               "Data");
        Finish("AVC");
        return;
    }

    Element_Begin1("slice_header");

    //Parsing
    int32u  slice_type, pic_order_cnt_lsb=(int32u)-1;
    int32u  first_mb_in_slice, pic_parameter_set_id, frame_num, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, disable_deblocking_filter_idc;

    int32s  delta_pic_order_cnt_bottom=0;
    bool    field_pic_flag=false, bottom_field_flag=false;
    Get_UE (first_mb_in_slice,                                  "first_mb_in_slice");
    Get_UE (slice_type,                                         "slice_type"); Param_Info1C((slice_type<10), Avc_slice_type[slice_type]);
    #if MEDIAINFO_EVENTS
        if (!first_mb_in_slice)
        {
            switch(Element_Code)
            {
                case 5 :    // This is an IDR frame
                            if (Config->Config_PerPackage) // 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
            }

            EVENT_BEGIN (Video, SliceInfo, 0)
                Event.FieldPosition=Field_Count;
                Event.SlicePosition=Element_IsOK()?first_mb_in_slice:(int64u)-1;
                switch (slice_type)
                {
                    case 0 :
                    case 3 :
                    case 5 :
                    case 8 :
                                Event.SliceType=1; break;
                    case 1 :
                    case 6 :
                                Event.SliceType=2; break;
                    case 2 :
                    case 4 :
                    case 7 :
                    case 9 :
                                Event.SliceType=0; break;
                    default:
                                Event.SliceType=(int8u)-1;
                }
                Event.Flags=0;
            EVENT_END   ()
        }
    #endif //MEDIAINFO_EVENTS
    if (slice_type>=10)
    {
        Skip_BS(Data_BS_Remain(),                               "Data");
        Element_End0();
        return;
    }
    Get_UE (pic_parameter_set_id,                               "pic_parameter_set_id");
    std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item;
    if (pic_parameter_set_id>=pic_parameter_sets.size() || (*(pic_parameter_set_Item=pic_parameter_sets.begin()+pic_parameter_set_id))==NULL)
    {
        //Not yet present
        Skip_BS(Data_BS_Remain(),                               "Data (pic_parameter_set is missing)");
        Element_End0();
        return;
    }
    std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
    if ((*pic_parameter_set_Item)->seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL)
    {
        if ((*pic_parameter_set_Item)->seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL)
        {
            //Not yet present
            Skip_BS(Data_BS_Remain(),                           "Data (seq_parameter_set is missing)");
            Element_End0();
            return;
        }
    }
    if ((*seq_parameter_set_Item)->separate_colour_plane_flag==1)
        Skip_S1(2,                                              "color_plane_id");
    num_ref_idx_l0_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l0_default_active_minus1; //Default
    num_ref_idx_l1_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l1_default_active_minus1; //Default
    Get_BS ((*seq_parameter_set_Item)->log2_max_frame_num_minus4+4, frame_num, "frame_num");
    if (!(*seq_parameter_set_Item)->frame_mbs_only_flag)
    {
        TEST_SB_GET(field_pic_flag,                             "field_pic_flag");
            Get_SB (bottom_field_flag,                          "bottom_field_flag");
        TEST_SB_END();
    }
    if (Element_Code==5) //IdrPicFlag
        Skip_UE(                                                "idr_pic_id");
    if ((*seq_parameter_set_Item)->pic_order_cnt_type==0)
    {
        Get_BS ((*seq_parameter_set_Item)->log2_max_pic_order_cnt_lsb_minus4+4, pic_order_cnt_lsb, "pic_order_cnt_lsb");
        if ((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag)
            Get_SE (delta_pic_order_cnt_bottom,                 "delta_pic_order_cnt_bottom");
    }
    if ((*seq_parameter_set_Item)->pic_order_cnt_type==1 && !(*seq_parameter_set_Item)->delta_pic_order_always_zero_flag )
    {
        Skip_SE(                                                "delta_pic_order_cnt[0]");
        if((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag)
            Skip_SE(                                            "delta_pic_order_cnt[1]");
    }
    if((*pic_parameter_set_Item)->redundant_pic_cnt_present_flag)
        Skip_UE(                                                "redundant_pic_cnt");
    if (slice_type==1 || slice_type==6) //B-Frame
        Skip_SB(                                                "direct_spatial_mv_pred_flag");
    switch (slice_type)
    {
        case 0 : //P-Frame
        case 1 : //B-Frame
        case 3 : //SP-Frame
        case 5 : //P-Frame
        case 6 : //B-Frame
        case 8 : //SP-Frame
                    TEST_SB_SKIP(                               "num_ref_idx_active_override_flag");
                        Get_UE (num_ref_idx_l0_active_minus1,   "num_ref_idx_l0_active_minus1");
                        switch (slice_type)
                        {
                            case 1 : //B-Frame
                            case 6 : //B-Frame
                                        Get_UE (num_ref_idx_l1_active_minus1, "num_ref_idx_l1_active_minus1");
                                        break;
                            default:    ;
                        }
                    TEST_SB_END();
                    break;
        default:    ;
    }
    ref_pic_list_modification(slice_type, Element_Code==20); //nal_unit_type==20 --> ref_pic_list_mvc_modification()
    if (((*pic_parameter_set_Item)->weighted_pred_flag && (slice_type==0 || slice_type==3 || slice_type==5 || slice_type==8))
     || ((*pic_parameter_set_Item)->weighted_bipred_idc==1 && (slice_type==1 || slice_type==6)))
        pred_weight_table(slice_type, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, (*seq_parameter_set_Item)->ChromaArrayType());
    std::vector<int8u> memory_management_control_operations;
    if (nal_ref_idc)
        dec_ref_pic_marking(memory_management_control_operations);

    if ((*pic_parameter_set_Item)->entropy_coding_mode_flag &&
        (slice_type!=2 && slice_type!=7 && //I-Frames
         slice_type!=4 && slice_type!=9))  //SI-Frames
        Skip_UE(                                               "cabac_init_idc");
    Skip_SE(                                                   "slice_qp_delta");
    switch (slice_type)
    {
        case 3 : //SP-Frame
        case 4 : //SI-Frame
        case 8 : //SP-Frame
        case 9 : //SI-Frame
                switch (slice_type)
                {
                    case 3 : //SP-Frame
                    case 8 : //SP-Frame
                            Skip_SB(                           "sp_for_switch_flag");
                            break;
                    default:    ;
                }
                Skip_SE (                                      "slice_qs_delta");
                break;
        default:    ;
    }
    if ((*pic_parameter_set_Item)->deblocking_filter_control_present_flag)
    {
        Get_UE(disable_deblocking_filter_idc,                  "disable_deblocking_filter_idc");
        if (disable_deblocking_filter_idc!=1)
        {
            Skip_SE(                                           "slice_alpha_c0_offset_div2");
            Skip_SE(                                           "slice_beta_offset_div2");
        }
    }

    Element_End0();

    FILLING_BEGIN();
        //Count of I-Frames
        if (first_mb_in_slice==0 && Element_Code!=20 && (slice_type==2 || slice_type==7)) //Not slice_layer_extension, I-Frame
            IFrame_Count++;

        //pic_struct
        if (field_pic_flag && (*seq_parameter_set_Item)->pic_struct_FirstDetected==(int8u)-1)
            (*seq_parameter_set_Item)->pic_struct_FirstDetected=bottom_field_flag?2:1; //2=BFF, 1=TFF

        //Saving some info
        int32s TemporalReferences_Offset_pic_order_cnt_lsb_Diff=0;
        if ((*seq_parameter_set_Item)->pic_order_cnt_type!=1 && first_mb_in_slice==0 && (Element_Code!=0x14 || seq_parameter_sets.empty()) && TemporalReferences_Reserved) //Not slice_layer_extension except if MVC only
        {
            if (field_pic_flag)
            {
                Structure_Field++;
                if (bottom_field_flag)
                    Interlaced_Bottom++;
                else
                    Interlaced_Top++;
            }
            else
                Structure_Frame++;

            //Frame order detection
            int64s pic_order_cnt=0;
            switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
            {
                case 0 :
                            {
                            if (Element_Code==5) //IDR
                            {
                                prevPicOrderCntMsb=0;
                                prevPicOrderCntLsb=0;
                                TemporalReferences_Offset=TemporalReferences_Max;
                                if (TemporalReferences_Offset%2)
                                    TemporalReferences_Offset++;
                                TemporalReferences_pic_order_cnt_Min=0;
                            }
                            else
                            {
                                const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(), 5) != memory_management_control_operations.end();
                                if (Has5)
                                {
                                    prevPicOrderCntMsb=0;
                                    if (bottom_field_flag)
                                        prevPicOrderCntLsb=0;
                                    else
                                        prevPicOrderCntLsb=prevTopFieldOrderCnt;
                                }
                            }
                            int32s PicOrderCntMsb;
                            if (prevPicOrderCntLsb==(int32u)-1)
                            {
                                PicOrderCntMsb=0;
                                if ((int32u)(2*((*seq_parameter_set_Item)->max_num_ref_frames+3))<pic_order_cnt_lsb)
                                    TemporalReferences_Min=pic_order_cnt_lsb-2*((*seq_parameter_set_Item)->max_num_ref_frames+3);
                            }
                            else if (pic_order_cnt_lsb<prevPicOrderCntLsb && prevPicOrderCntLsb-pic_order_cnt_lsb>=(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2)
                                PicOrderCntMsb=prevPicOrderCntMsb+(*seq_parameter_set_Item)->MaxPicOrderCntLsb;
                            else if (pic_order_cnt_lsb>prevPicOrderCntLsb && pic_order_cnt_lsb-prevPicOrderCntLsb>(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2)
                                PicOrderCntMsb=prevPicOrderCntMsb-(*seq_parameter_set_Item)->MaxPicOrderCntLsb;
                            else
                                PicOrderCntMsb=prevPicOrderCntMsb;

                            int32s TopFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb;
                            int32s BottomFieldOrderCnt;
                            if (field_pic_flag)
                                BottomFieldOrderCnt=TopFieldOrderCnt+delta_pic_order_cnt_bottom;
                            else
                                BottomFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb;

                            prevPicOrderCntMsb=PicOrderCntMsb;
                            prevPicOrderCntLsb=pic_order_cnt_lsb;
                            prevTopFieldOrderCnt=TopFieldOrderCnt;

                            pic_order_cnt=bottom_field_flag?BottomFieldOrderCnt:TopFieldOrderCnt;
                            }
                            break;
                case 2 :
                            {
                            const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(),5) != memory_management_control_operations.end();
                            if (Has5)
                                prevFrameNumOffset=0;
                            int32u FrameNumOffset;

                            if (Element_Code==5) //IdrPicFlag
                            {
                                TemporalReferences_Offset=TemporalReferences_Max;
                                if (TemporalReferences_Offset%2)
                                    TemporalReferences_Offset++;
                                FrameNumOffset=0;
                            }
                            else if (prevFrameNumOffset==(int32u)-1)
                                FrameNumOffset=0;
                            else if (prevFrameNum>frame_num)
                                FrameNumOffset=prevFrameNumOffset+(*seq_parameter_set_Item)->MaxFrameNum;
                            else
                                FrameNumOffset=prevFrameNumOffset;

                            int32u tempPicOrderCnt;
                            if (Element_Code==5) //IdrPicFlag
                                tempPicOrderCnt=0;
                            else
                            {
                                tempPicOrderCnt=2*(FrameNumOffset+frame_num);
                                if (!nal_ref_idc && tempPicOrderCnt) //Note: if nal_ref_idc is 0, tempPicOrderCnt is not expected to be 0 but it may be the case with invalid streams
                                    tempPicOrderCnt--;
                            }

                            pic_order_cnt=tempPicOrderCnt;

                            prevFrameNum=frame_num;
                            prevFrameNumOffset=FrameNumOffset;

                            pic_order_cnt_lsb=frame_num;
                            }
                            break;
                default:    ;
            }

            if (pic_order_cnt<TemporalReferences_pic_order_cnt_Min)
            {
                if (pic_order_cnt<0)
                {
                    size_t Base=(size_t)(TemporalReferences_Offset+TemporalReferences_pic_order_cnt_Min);
                    size_t ToInsert=(size_t)(TemporalReferences_pic_order_cnt_Min-pic_order_cnt);
                    if (Base+ToInsert>=4*TemporalReferences_Reserved || Base>=4*TemporalReferences_Reserved || ToInsert+TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max-Base>=4*TemporalReferences_Reserved)
                    {
                        Trusted_IsNot("Problem in temporal references");
                        return;
                    }
                    Element_Info1(__T("Offset of ")+Ztring::ToZtring(ToInsert));
                    TemporalReferences.insert(TemporalReferences.begin()+Base, ToInsert, NULL);
                    TemporalReferences_Offset+=ToInsert;
                    TemporalReferences_Offset_pic_order_cnt_lsb_Last += ToInsert;
                    TemporalReferences_Max+=ToInsert;
                    TemporalReferences_pic_order_cnt_Min=pic_order_cnt;
                }
                else if (TemporalReferences_Min>(size_t)(TemporalReferences_Offset+pic_order_cnt))
                    TemporalReferences_Min=(size_t)(TemporalReferences_Offset+pic_order_cnt);
            }

            if (pic_order_cnt<0 && TemporalReferences_Offset<(size_t)(-pic_order_cnt)) //Found in playreadyEncryptedBlowUp.ts without encryption test
            {
                Trusted_IsNot("Problem in temporal references");
                return;
            }

            if ((size_t)(TemporalReferences_Offset+pic_order_cnt)>=3*TemporalReferences_Reserved)
            {
                size_t Offset=TemporalReferences_Max-TemporalReferences_Offset;
                if (Offset%2)
                    Offset++;
                if (Offset>=TemporalReferences_Reserved && pic_order_cnt>=(int64s)TemporalReferences_Reserved)
                {
                    TemporalReferences_Offset+=TemporalReferences_Reserved;
                    pic_order_cnt-=TemporalReferences_Reserved;
                    TemporalReferences_pic_order_cnt_Min-=TemporalReferences_Reserved/2;
                    switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
                    {
                        case 0 :
                                prevPicOrderCntMsb-=(int32u)TemporalReferences_Reserved;
                                break;
                        case 2 :
                                prevFrameNumOffset-=(int32u)TemporalReferences_Reserved/2;
                                break;
                        default:;
                    }
                }
                while (TemporalReferences_Offset+pic_order_cnt>=3*TemporalReferences_Reserved)
                {
                    for (size_t Pos=0; Pos<TemporalReferences_Reserved; Pos++)
                    {
                        if (TemporalReferences[Pos])
                        {
                            if ((Pos%2)==0)
                                PictureTypes_PreviousFrames+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
                            delete TemporalReferences[Pos];
                            TemporalReferences[Pos] = NULL;
                        }
                        else if (!PictureTypes_PreviousFrames.empty()) //Only if stream already started
                        {
                            if ((Pos%2)==0)
                                PictureTypes_PreviousFrames+=' ';
                        }
                    }
                    if (PictureTypes_PreviousFrames.size()>=8*TemporalReferences.size())
                        PictureTypes_PreviousFrames.erase(PictureTypes_PreviousFrames.begin(), PictureTypes_PreviousFrames.begin()+PictureTypes_PreviousFrames.size()-TemporalReferences.size());
                    TemporalReferences.erase(TemporalReferences.begin(), TemporalReferences.begin()+TemporalReferences_Reserved);
                    TemporalReferences.resize(4*TemporalReferences_Reserved);
                    if (TemporalReferences_Reserved<TemporalReferences_Offset)
                        TemporalReferences_Offset-=TemporalReferences_Reserved;
                    else
                        TemporalReferences_Offset=0;
                    if (TemporalReferences_Reserved<TemporalReferences_Min)
                        TemporalReferences_Min-=TemporalReferences_Reserved;
                    else
                        TemporalReferences_Min=0;
                    if (TemporalReferences_Reserved<TemporalReferences_Max)
                        TemporalReferences_Max-=TemporalReferences_Reserved;
                    else
                        TemporalReferences_Max=0;
                    if (TemporalReferences_Reserved<TemporalReferences_Offset_pic_order_cnt_lsb_Last)
                        TemporalReferences_Offset_pic_order_cnt_lsb_Last-=TemporalReferences_Reserved;
                    else
                        TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
                }
            }

            TemporalReferences_Offset_pic_order_cnt_lsb_Diff=(int32s)((int32s)(TemporalReferences_Offset+pic_order_cnt)-TemporalReferences_Offset_pic_order_cnt_lsb_Last);
            TemporalReferences_Offset_pic_order_cnt_lsb_Last=(size_t)(TemporalReferences_Offset+pic_order_cnt);
            if (field_pic_flag && (*seq_parameter_set_Item)->pic_order_cnt_type==2 && TemporalReferences_Offset_pic_order_cnt_lsb_Last<TemporalReferences.size() && TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last])
                TemporalReferences_Offset_pic_order_cnt_lsb_Last++;
            if (TemporalReferences_Max<=TemporalReferences_Offset_pic_order_cnt_lsb_Last)
                TemporalReferences_Max=TemporalReferences_Offset_pic_order_cnt_lsb_Last+((*seq_parameter_set_Item)->frame_mbs_only_flag?2:1);
            if (TemporalReferences_Min>TemporalReferences_Offset_pic_order_cnt_lsb_Last)
                TemporalReferences_Min=TemporalReferences_Offset_pic_order_cnt_lsb_Last;
            if (TemporalReferences_DelayedElement)
            {
                delete TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=TemporalReferences_DelayedElement;
            }
            if (TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]==NULL)
                TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=new temporal_reference();
            TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->frame_num=frame_num;
            TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->slice_type=(int8u)slice_type;
            TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsTop=!bottom_field_flag;
            TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsField=field_pic_flag;
            if (TemporalReferences_DelayedElement)
            {
                TemporalReferences_DelayedElement=NULL;
                sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed((*pic_parameter_set_Item)->seq_parameter_set_id);
            }
        }

        if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick)
            tc=float64_int64s(((float64)1000000000)/((float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->pic_order_cnt_type==2?1:2)/FrameRate_Divider)/((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?2:1));
        if (first_mb_in_slice==0)
        {
            if (Frame_Count==0)
            {
                if (FrameInfo.PTS==(int64u)-1)
                    FrameInfo.PTS=FrameInfo.DTS+tc*(TemporalReferences_Offset_pic_order_cnt_lsb_Diff?2:1)*((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?2:1); //No PTS in container
                PTS_Begin=FrameInfo.PTS;
            }
            #if MEDIAINFO_ADVANCED2
                if (PTS_Begin_Segment==(int64u)-1 && File_Offset>=Config->File_Current_Offset)
                {
                    PTS_Begin_Segment=FrameInfo.PTS;
                }
            #endif //MEDIAINFO_ADVANCED2
            if (slice_type==2 || slice_type==7) //IFrame
                FirstPFrameInGop_IsParsed=false;
        }
        else
        {
            if (FrameInfo.PTS!=(int64u)-1)
                FrameInfo.PTS-=tc;
            if (FrameInfo.DTS!=(int64u)-1)
                FrameInfo.DTS-=tc;
        }

        //Frame pos
        if (Frame_Count!=(int64u)-1 && Frame_Count && ((!(*seq_parameter_set_Item)->frame_mbs_only_flag && Interlaced_Top==Interlaced_Bottom && field_pic_flag) || first_mb_in_slice!=0 || (Element_Code==0x14 && !seq_parameter_sets.empty())))
        {
            Frame_Count--;
            if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1)
                Frame_Count_NotParsedIncluded--;
            Frame_Count_InThisBlock--;
        }
        else if (first_mb_in_slice==0)
        {
            if ((*seq_parameter_set_Item)->pic_order_cnt_type!=1 && (Element_Code!=0x14 || seq_parameter_sets.empty())) //Not slice_layer_extension except if MVC only
            {
                if ((!IsSub || Frame_Count_InThisBlock) && TemporalReferences_Offset_pic_order_cnt_lsb_Diff && TemporalReferences_Offset_pic_order_cnt_lsb_Diff!=2)
                    FrameInfo.PTS+=(TemporalReferences_Offset_pic_order_cnt_lsb_Diff-(field_pic_flag?1:2))/((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?1:2)*(int64s)tc;
            }

            if (!FirstPFrameInGop_IsParsed && (slice_type==0 || slice_type==5)) //P-Frame
            {
                FirstPFrameInGop_IsParsed=true;

                //Testing if we have enough to test GOP
                if (Frame_Count<=Frame_Count_Valid)
                {
                    std::string PictureTypes(PictureTypes_PreviousFrames);
                    PictureTypes.reserve(TemporalReferences.size());
                    for (size_t Pos=0; Pos<TemporalReferences.size(); Pos++)
                        if (TemporalReferences[Pos])
                        {
                            if ((Pos%2)==0)
                                PictureTypes+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
                        }
                        else if (!PictureTypes.empty()) //Only if stream already started
                        {
                            if ((Pos%2)==0)
                                PictureTypes+=' ';
                        }
                        #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
                            if (!GOP_Detect(PictureTypes).empty() && !GA94_03_IsPresent)
                                Frame_Count_Valid=Frame_Count; //We have enough frames
                        #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
                }
            }
        }

        #if MEDIAINFO_TRACE
            if (Trace_Activated)
            {
                Element_Info1(TemporalReferences_Offset_pic_order_cnt_lsb_Last);
                Element_Info1((((*seq_parameter_set_Item)->frame_mbs_only_flag || !field_pic_flag)?__T("Frame "):(bottom_field_flag?__T("Field (Bottom) "):__T("Field (Top) ")))+Ztring::ToZtring(Frame_Count));
                if (slice_type<9)
                    Element_Info1(__T("slice_type ")+Ztring().From_UTF8(Avc_slice_type[slice_type]));
                Element_Info1(__T("frame_num ")+Ztring::ToZtring(frame_num));
                if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag)
                {
                    if (FrameInfo.PCR!=(int64u)-1)
                        Element_Info1(__T("PCR ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PCR)/1000000)));
                    if (FrameInfo.DTS!=(int64u)-1)
                        Element_Info1(__T("DTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.DTS)/1000000)));
                    if (FrameInfo.PTS!=(int64u)-1)
                        Element_Info1(__T("PTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PTS)/1000000)));
                }
                if ((*seq_parameter_set_Item)->pic_order_cnt_type==0)
                    Element_Info1(__T("pic_order_cnt_lsb ")+Ztring::ToZtring(pic_order_cnt_lsb));
                if (first_mb_in_slice)
                    Element_Info1(__T("first_mb_in_slice ")+Ztring::ToZtring(first_mb_in_slice));
            }
        #endif //MEDIAINFO_TRACE

        //Counting
        if (Frame_Count!=(int64u)-1)
        {
            if (File_Offset+Buffer_Offset+Element_Size==File_Size)
                Frame_Count_Valid=Frame_Count; //Finish frames in case of there are less than Frame_Count_Valid frames
            Frame_Count++;
            if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1)
                Frame_Count_NotParsedIncluded++;
            Frame_Count_InThisBlock++;
        }
        if ((*seq_parameter_set_Item)->pic_order_cnt_type==0 && field_pic_flag)
        {
            Field_Count++;
            Field_Count_InThisBlock++;
        }
        if (FrameInfo.PTS!=(int64u)-1)
            FrameInfo.PTS+=tc;
        if (FrameInfo.DTS!=(int64u)-1)
            FrameInfo.DTS+=tc;
        if (FrameInfo.PTS!=(int64u)-1 && (FrameInfo.PTS>PTS_End || (PTS_End>1000000000 && FrameInfo.PTS<=PTS_End-1000000000))) //More than current PTS_End or less than current PTS_End minus 1 second (there is a problem?)
            PTS_End=FrameInfo.PTS;

        #if MEDIAINFO_DUPLICATE
            if (Streams[(size_t)Element_Code].ShouldDuplicate)
                File__Duplicate_Write(Element_Code, (*seq_parameter_set_Item)->pic_order_cnt_type==0?pic_order_cnt_lsb:frame_num);
        #endif //MEDIAINFO_DUPLICATE

        //Filling only if not already done
        if (Frame_Count==1 && !Status[IsAccepted])
            Accept("AVC");
        if (!Status[IsFilled])
        {
            #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
                if (!GA94_03_IsPresent && IFrame_Count>=8)
                    Frame_Count_Valid=Frame_Count; //We have enough frames
            #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
            if (Frame_Count>=Frame_Count_Valid)
            {
                Fill("AVC");
                if (!IsSub && !Streams[(size_t)Element_Code].ShouldDuplicate && Config->ParseSpeed<1.0)
                    Finish("AVC");
            }
        }
    FILLING_END();
}

//---------------------------------------------------------------------------
//
void File_Avc::slice_data(bool AllCategories)
{
    Element_Begin1("slice_data");

    Skip_BS(Data_BS_Remain(),                                   "(ToDo)");

    Element_End0();
}

//---------------------------------------------------------------------------
//
void File_Avc::ref_pic_list_modification(int32u slice_type, bool mvc)
{
    if ((slice_type%5)!=2 && (slice_type%5)!=4)
    {
        TEST_SB_SKIP(                                           "ref_pic_list_modification_flag_l0");
            int32u modification_of_pic_nums_idc;
            do
            {
                Get_UE (modification_of_pic_nums_idc,           "modification_of_pic_nums_idc");
                if (modification_of_pic_nums_idc<2)
                    Skip_UE(                                    "abs_diff_pic_num_minus1");
                else if (modification_of_pic_nums_idc==2)
                    Skip_UE(                                    "long_term_pic_num");
                else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only
                    Skip_UE(                                    "abs_diff_view_idx_minus1");
                else if (modification_of_pic_nums_idc!=3)
                {
                    Trusted_IsNot("ref_pic_list_modification_flag_l0");
                    Skip_BS(Data_BS_Remain(),                   "(Remaining bits)");
                }
            }
            while (modification_of_pic_nums_idc!=3 && Data_BS_Remain());
        TEST_SB_END();
    }
    if ((slice_type%5)==1)
    {
        TEST_SB_SKIP(                                           "ref_pic_list_modification_flag_l1");
            int32u modification_of_pic_nums_idc;
            do
            {
                Get_UE (modification_of_pic_nums_idc,           "modification_of_pic_nums_idc");
                if (modification_of_pic_nums_idc<2)
                    Skip_UE(                                    "abs_diff_pic_num_minus1");
                else if (modification_of_pic_nums_idc==2)
                    Skip_UE(                                    "long_term_pic_num");
                else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only
                    Skip_UE(                                    "abs_diff_view_idx_minus1");
                else if (modification_of_pic_nums_idc!=3)
                {
                    Trusted_IsNot("ref_pic_list_modification_flag_l1");
                    Skip_BS(Data_BS_Remain(),                   "(Remaining bits)");
                }
            }
            while (modification_of_pic_nums_idc!=3 && Data_BS_Remain());
        TEST_SB_END();
    }
}

//---------------------------------------------------------------------------
//
void File_Avc::pred_weight_table(int32u  slice_type, int32u num_ref_idx_l0_active_minus1, int32u num_ref_idx_l1_active_minus1, int8u ChromaArrayType)
{
    // 7.3.3.2 Prediction weight table syntax
    Skip_UE(                                                    "luma_log2_weight_denom");
    if (ChromaArrayType)
        Skip_UE(                                                "chroma_log2_weight_denom");
    for(int32u i=0; i<=num_ref_idx_l0_active_minus1; i++)
    {
        TEST_SB_SKIP(                                           "luma_weight_l0_flag");
            Skip_SE(                                            "luma_weight_l0");
            Skip_SE(                                            "luma_offset_l0");
        TEST_SB_END();
		if (ChromaArrayType)
		{
			TEST_SB_SKIP(                                       "chroma_weight_l0_flag");
				Skip_SE(                                        "chroma_weight_l0");
				Skip_SE(                                        "chroma_offset_l0");
				Skip_SE(                                        "chroma_weight_l0");
				Skip_SE(                                        "chroma_offset_l0");
			TEST_SB_END();
		}
    }
    if (slice_type % 5 == 1)
    {
        for (int32u i = 0; i <= num_ref_idx_l1_active_minus1; i++)
        {
            TEST_SB_SKIP("luma_weight_l1_flag");
            Skip_SE("luma_weight_l1");
            Skip_SE("luma_offset_l1");
            TEST_SB_END();
            if (ChromaArrayType)
            {
                TEST_SB_SKIP("chroma_weight_l1_flag");
                Skip_SE("chroma_weight_l1");
                Skip_SE("chroma_offset_l1");
                Skip_SE("chroma_weight_l1");
                Skip_SE("chroma_offset_l1");
                TEST_SB_END();
            }
        }
    }
}

//---------------------------------------------------------------------------
//
void File_Avc::dec_ref_pic_marking(std::vector<int8u> &memory_management_control_operations)
{
    if (Element_Code==5) //IdrPicFlag
    {
        Skip_SB(                                                "no_output_of_prior_pics_flag");
        Skip_SB(                                                "long_term_reference_flag");
    }
    else
    {
        TEST_SB_SKIP(                                           "adaptive_ref_pic_marking_mode_flag");
            int32u memory_management_control_operation;
            do
            {
                Get_UE (memory_management_control_operation,    "memory_management_control_operation");
                switch (memory_management_control_operation)
                {
                    case 1 :
                                Skip_UE(                        "difference_of_pic_nums_minus1");
                                break;
                    case 2 :
                                Skip_UE(                        "long_term_pic_num");
                                break;
                    case 3 :
                                Skip_UE(                        "difference_of_pic_nums_minus1");
                                //break; 3 --> difference_of_pic_nums_minus1 then long_term_frame_idx
                    case 6 :
                                Skip_UE(                        "long_term_frame_idx");
                                break;
                    case 4 :
                                Skip_UE(                        "max_long_term_frame_idx_plus1");
                                break;
                }
                memory_management_control_operations.push_back((int8u)memory_management_control_operation);
            }
            while (Data_BS_Remain() && memory_management_control_operation);
        TEST_SB_END()
    }
}

//---------------------------------------------------------------------------
// Packet "06"
void File_Avc::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();
    Mark_1(                                                     );
    BS_End();
}

//---------------------------------------------------------------------------
void File_Avc::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();

    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); break;
        case  1 :   sei_message_pic_timing(payloadSize, seq_parameter_set_id); 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 147:   sei_alternative_transfer_characteristics(); break;
        case 137:   sei_message_mastering_display_colour_volume(); break;
        case 144:   sei_message_light_level(); 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.
}

//---------------------------------------------------------------------------
// SEI - 0
void File_Avc::sei_message_buffering_period(int32u &seq_parameter_set_id)
{
    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;
    }
    if ((*seq_parameter_set_Item)->NalHrdBpPresentFlag())
        sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->NAL);
    if ((*seq_parameter_set_Item)->VclHrdBpPresentFlag())
        sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->VCL);
    BS_End();
}

void File_Avc::sei_message_buffering_period_xxl(seq_parameter_set_struct::vui_parameters_struct::xxl* xxl)
{
    if (xxl==NULL)
        return;
    for (int32u SchedSelIdx=0; SchedSelIdx<xxl->SchedSel.size(); SchedSelIdx++)
    {
        //Get_S4 (xxl->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->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->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->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");
    }
}

//---------------------------------------------------------------------------
// SEI - 1
void File_Avc::sei_message_pic_timing(int32u /*payloadSize*/, int32u seq_parameter_set_id)
{
    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
    int8u   pic_struct=(int8u)-1;
    BS_Begin();
    if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag())
    {
        int8u cpb_removal_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->cpb_removal_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->cpb_removal_delay_length_minus1; //Spec is not precise, I am not sure
        int8u dpb_output_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->dpb_output_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->dpb_output_delay_length_minus1; //Spec is not precise, I am not sure
        Skip_S4(cpb_removal_delay_length_minus1+1,              "cpb_removal_delay");
        Skip_S4(dpb_output_delay_length_minus1+1,               "dpb_output_delay");
    }
    if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag)
    {
        Get_S1 (4, pic_struct,                                  "pic_struct");
        switch (pic_struct)
        {
            case  0 :
            case  1 :
            case  2 :
            case  3 :
            case  4 :
            case  5 :
            case  6 : FrameRate_Divider=1; break;
            case  7 : FrameRate_Divider=2; break;
            case  8 : FrameRate_Divider=3; break;
            default : Param_Info1("Reserved"); return; //NumClockTS is unknown
        }
        Param_Info1(Avc_pic_struct[pic_struct]);
        int8u NumClockTS=Avc_NumClockTS[pic_struct];
        int8u seconds_value=0, minutes_value=0, hours_value=0; //Here because theses values can be reused in later ClockTSs.
        for (int8u i=0; i<NumClockTS; i++)
        {
            Element_Begin1("ClockTS");
            TEST_SB_SKIP(                                       "clock_timestamp_flag");
                Ztring TimeStamp;
                int32u time_offset=0;
                int8u n_frames;
                bool full_timestamp_flag, nuit_field_based_flag;
                Info_S1(2, ct_type,                             "ct_type"); Param_Info1(Avc_ct_type[ct_type]);
                Get_SB (   nuit_field_based_flag,               "nuit_field_based_flag");
                Skip_S1(5,                                      "counting_type");
                Get_SB (   full_timestamp_flag,                 "full_timestamp_flag");
                Skip_SB(                                        "discontinuity_flag");
                Skip_SB(                                        "cnt_dropped_flag");
                Get_S1 (8, n_frames,                            "n_frames");
                if (full_timestamp_flag)
                {
                    Get_S1 (6, seconds_value,                    "seconds_value");
                    Get_S1 (6, minutes_value,                    "minutes_value");
                    Get_S1 (5, hours_value,                      "hours_value");
                }
                else
                {
                    TEST_SB_SKIP(                               "seconds_flag");
                        Get_S1 (6, seconds_value,               "seconds_value");
                        TEST_SB_SKIP(                           "minutes_flag");
                            Get_S1 (6, minutes_value,           "minutes_value");
                            TEST_SB_SKIP(                       "hours_flag");
                                Get_S1 (5, hours_value,         "hours_value");
                            TEST_SB_END();
                        TEST_SB_END();
                    TEST_SB_END();
                }
                TimeStamp=Ztring::ToZtring(hours_value)+__T(':')+Ztring::ToZtring(minutes_value)+__T(':')+Ztring::ToZtring(seconds_value);
                if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag())
                {
                    int8u time_offset_length=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->time_offset_length:(*seq_parameter_set_Item)->vui_parameters->VCL->time_offset_length; //Spec is not precise, I am not sure
                    if (time_offset_length)
                        Get_S4 (time_offset_length, time_offset,    "time_offset");
                }
                if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->time_scale)
                {
                    float32 Milliseconds=((float32)(n_frames*((*seq_parameter_set_Item)->vui_parameters->num_units_in_tick*(1+(nuit_field_based_flag?1:0)))+time_offset))/(*seq_parameter_set_Item)->vui_parameters->time_scale;
                    TimeStamp+=__T('.');
                    TimeStamp+=Ztring::ToZtring(Milliseconds);
                }
                Element_Info1(TimeStamp);
            TEST_SB_END();
            Element_End0();
        }
    }
    BS_End();

    FILLING_BEGIN_PRECISE();
        if ((*seq_parameter_set_Item)->pic_struct_FirstDetected==(int8u)-1 && (*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag)
            (*seq_parameter_set_Item)->pic_struct_FirstDetected=pic_struct;
    FILLING_END();
}

//---------------------------------------------------------------------------
// SEI - 5
void File_Avc::sei_message_user_data_registered_itu_t_t35()
{
    Element_Info1("user_data_registered_itu_t_t35");

    //Parsing
    int8u itu_t_t35_country_code;
    Get_B1 (itu_t_t35_country_code,                             "itu_t_t35_country_code");
    if (itu_t_t35_country_code==0xFF)
        Skip_B1(                                                "itu_t_t35_country_code_extension_byte");
    if (itu_t_t35_country_code!=0xB5 || Element_Offset+2>=Element_Size)
    {
        if (Element_Size-Element_Offset)
            Skip_XX(Element_Size-Element_Offset,                "Unknown");
        return;
    }

    //United-States
    int16u id;
    Get_B2 (id,                                                 "id?");
    if (id!=0x0031 || Element_Offset+4>=Element_Size)
    {
        if (Element_Size-Element_Offset)
            Skip_XX(Element_Size-Element_Offset,                "Unknown");
        return;
    }

    int32u Identifier;
    Peek_B4(Identifier);
    switch (Identifier)
    {
        case 0x44544731 :   sei_message_user_data_registered_itu_t_t35_DTG1(); return;
        case 0x47413934 :   sei_message_user_data_registered_itu_t_t35_GA94(); return;
        default         :   if (Element_Size-Element_Offset)
                                Skip_XX(Element_Size-Element_Offset, "Unknown");
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - DTG1
void File_Avc::sei_message_user_data_registered_itu_t_t35_DTG1()
{
    Element_Info1("Active Format Description");

    //Parsing
    bool active_format_flag;
    Skip_C4(                                                    "afd_identifier");
    BS_Begin();
    Mark_0();
    Get_SB (active_format_flag,                                 "active_format_flag");
    Mark_0_NoTrustError();
    Mark_0_NoTrustError();
    Mark_0_NoTrustError();
    Mark_0_NoTrustError();
    Mark_0_NoTrustError();
    Mark_1_NoTrustError();
    if (active_format_flag)
    {
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Mark_1_NoTrustError();
        Info_S1(4, active_format,                               "active_format"); Param_Info1(Avc_user_data_DTG1_active_format[active_format]);
    }
    BS_End();
}

//---------------------------------------------------------------------------
// SEI - 5 - GA94
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94()
{
    //Parsing
    int8u user_data_type_code;
    Skip_B4(                                                    "GA94_identifier");
    Get_B1 (user_data_type_code,                                "user_data_type_code");
    switch (user_data_type_code)
    {
        case 0x03 : sei_message_user_data_registered_itu_t_t35_GA94_03(); break;
        case 0x06 : sei_message_user_data_registered_itu_t_t35_GA94_06(); break;
        default   : Skip_XX(Element_Size-Element_Offset,        "GA94_reserved_user_data");
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - GA94 - 0x03
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03()
{
    #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        GA94_03_IsPresent=true;
        MustExtendParsingDuration=true;
        Buffer_TotalBytes_Fill_Max=(int64u)-1; //Disabling this feature for this format, this is done in the parser

        Element_Info1("DTVCC Transport");

        //Coherency
        delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=new temporal_reference();

        TemporalReferences_DelayedElement->GA94_03=new buffer_data(Buffer+Buffer_Offset+(size_t)Element_Offset,(size_t)(Element_Size-Element_Offset));

        //Parsing
        Skip_XX(Element_Size-Element_Offset,                    "CC data");
    #else //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
        Skip_XX(Element_Size-Element_Offset,                    "DTVCC Transport data");
    #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
}

void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed(int32u seq_parameter_set_id)
{
    // Skipping missing frames
    if (TemporalReferences_Max-TemporalReferences_Min>(size_t)(4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3))) // max_num_ref_frames ref frame maximum
    {
        size_t TemporalReferences_Min_New=TemporalReferences_Max-4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3);
        while (TemporalReferences_Min_New>TemporalReferences_Min && TemporalReferences[TemporalReferences_Min_New-1])
            TemporalReferences_Min_New--;
        TemporalReferences_Min=TemporalReferences_Min_New;
        while (TemporalReferences[TemporalReferences_Min]==NULL)
            TemporalReferences_Min++;
    }

    // Parsing captions
    while (TemporalReferences[TemporalReferences_Min] && TemporalReferences_Min+2*seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames<TemporalReferences_Max)
    {
        #if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
            Element_Begin1("Reordered DTVCC Transport");

            //Parsing
            #if MEDIAINFO_DEMUX
                int64u Element_Code_Old=Element_Code;
                Element_Code=0x4741393400000003LL;
            #endif //MEDIAINFO_DEMUX
            if (GA94_03_Parser==NULL)
            {
                GA94_03_Parser=new File_DtvccTransport;
                Open_Buffer_Init(GA94_03_Parser);
                ((File_DtvccTransport*)GA94_03_Parser)->Format=File_DtvccTransport::Format_A53_4_GA94_03;
            }
            if (((File_DtvccTransport*)GA94_03_Parser)->AspectRatio==0)
            {
                float64 PixelAspectRatio=1;
                std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item=seq_parameter_sets.begin();
                for (; seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item)
                    if ((*seq_parameter_set_Item))
                        break;
                if (seq_parameter_set_Item!=seq_parameter_sets.end())
                {
                    if (((*seq_parameter_set_Item)->vui_parameters) && ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag))
                    {
                        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;
                    }
                    const int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1       +1)*16;
                    const int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
                    if(Height)
                        ((File_DtvccTransport*)GA94_03_Parser)->AspectRatio=Width*PixelAspectRatio/Height;
                }
            }
            if (GA94_03_Parser->PTS_DTS_Needed)
            {
                GA94_03_Parser->FrameInfo.PCR=FrameInfo.PCR;
                GA94_03_Parser->FrameInfo.PTS=FrameInfo.PTS;
                GA94_03_Parser->FrameInfo.DTS=FrameInfo.DTS;
            }
            #if MEDIAINFO_DEMUX
                if (TemporalReferences[TemporalReferences_Min]->GA94_03)
                {
                    int8u Demux_Level_Save=Demux_Level;
                    Demux_Level=8; //Ancillary
                    Demux(TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size, ContentType_MainStream);
                    Demux_Level=Demux_Level_Save;
                }
                Element_Code=Element_Code_Old;
            #endif //MEDIAINFO_DEMUX
            if (TemporalReferences[TemporalReferences_Min]->GA94_03)
            {
                #if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
                    GA94_03_Parser->ServiceDescriptors=ServiceDescriptors;
                #endif
                Open_Buffer_Continue(GA94_03_Parser, TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size);
            }

            Element_End0();
        #endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)

        TemporalReferences_Min+=((seq_parameter_sets[seq_parameter_set_id]->frame_mbs_only_flag | !TemporalReferences[TemporalReferences_Min]->IsField)?2:1);
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - GA94 - 0x03
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_06()
{
    Element_Info1("Bar data");

    //Parsing
    bool   top_bar_flag, bottom_bar_flag, left_bar_flag, right_bar_flag;
    BS_Begin();
    Get_SB (top_bar_flag,                                       "top_bar_flag");
    Get_SB (bottom_bar_flag,                                    "bottom_bar_flag");
    Get_SB (left_bar_flag,                                      "left_bar_flag");
    Get_SB (right_bar_flag,                                     "right_bar_flag");
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    BS_End();
    if (top_bar_flag)
    {
        Mark_1();
        Mark_1();
        Skip_S2(14,                                             "line_number_end_of_top_bar");
    }
    if (bottom_bar_flag)
    {
        Mark_1();
        Mark_1();
        Skip_S2(14,                                             "line_number_start_of_bottom_bar");
    }
    if (left_bar_flag)
    {
        Mark_1();
        Mark_1();
        Skip_S2(14,                                             "pixel_number_end_of_left_bar");
    }
    if (right_bar_flag)
    {
        Mark_1();
        Mark_1();
        Skip_S2(14,                                             "pixel_number_start_of_right_bar");
    }
    Mark_1();
    Mark_1();
    Mark_1();
    Mark_1();
    Mark_1();
    Mark_1();
    Mark_1();
    Mark_1();
    BS_End();

    if (Element_Size-Element_Offset)
        Skip_XX(Element_Size-Element_Offset,                    "additional_bar_data");
}

//---------------------------------------------------------------------------
// SEI - 5
void File_Avc::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 0xDC45E9BDE6D948B7LL : Element_Info1("x264");
                                     sei_message_user_data_unregistered_x264(payloadSize-16); break;
        case 0xFB574A60AC924E68LL : Element_Info1("eavc");
                                     sei_message_user_data_unregistered_x264(payloadSize-16); break;
        case 0x17EE8C60F84D11D9LL : Element_Info1("Blu-ray");
                                    sei_message_user_data_unregistered_bluray(payloadSize-16); break;
        default :
                    Element_Info1("unknown");
                    Skip_XX(payloadSize-16,                     "data");
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - x264
void File_Avc::sei_message_user_data_unregistered_x264(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();
            do
            {
                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;
                do
                {
                    string Separator;
                    Peek_String(1, Separator);
                    if (Separator==" ")
                    {
                        Skip_UTF8(1,                                "separator");
                        Options_Pos_Before+=1;
                    }
                    else
                        break;
                }
                while (Options_Pos_Before!=Data.size());

                //Filling
                if (option!="options:")
                {
                    if (!Encoded_Library_Settings.empty())
                        Encoded_Library_Settings+=__T(" / ");
                    Encoded_Library_Settings+=Ztring().From_UTF8(option.c_str());
                    if (option.find("bitrate=")==0)
                        BitRate_Nominal.From_UTF8(option.substr(8)+"000"); //After "bitrate="
                }
            }
            while (Options_Pos_Before!=Data.size());
            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);
                Encoded_Library.From_UTF8(Value.c_str());
            }
            if (Loop==1 && Encoded_Library.find(__T("x264"))==0)
            {
                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("eavc "))==0)
    {
        Encoded_Library_Name=__T("eavc");
        Encoded_Library_Version=Encoded_Library.SubString(__T("eavc "), __T(""));
    }
    else if (Encoded_Library.find(__T("x264 - "))==0)
    {
        Encoded_Library_Name=__T("x264");
        Encoded_Library_Version=Encoded_Library.SubString(__T("x264 - "), __T(""));
    }
    else if (Encoded_Library.find(__T("SUPER(C) by eRightSoft "))==0)
    {
        Encoded_Library_Name=__T("SUPER(C) by eRightSoft");
        Encoded_Library_Date=Ztring(__T("UTC "))+Encoded_Library.SubString(__T("2000-"), __T(" "));
    }
    else
        Encoded_Library_Name=Encoded_Library;
}

//---------------------------------------------------------------------------
// SEI - 5 - x264
void File_Avc::sei_message_user_data_unregistered_bluray(int32u payloadSize)
{
    if (payloadSize<4)
    {
        Skip_XX(payloadSize,                                    "Unknown");
        return;
    }
    int32u Identifier;
    Get_B4 (Identifier,                                         "Identifier");
    switch (Identifier)
    {
        case 0x47413934 :   sei_message_user_data_registered_itu_t_t35_GA94_03(); return;
        case 0x4D44504D :   sei_message_user_data_unregistered_bluray_MDPM(Element_Size-Element_Offset); return;
        default         :   Skip_XX(Element_Size-Element_Offset, "Unknown");
    }
}

//---------------------------------------------------------------------------
// SEI - 5 - bluray - MDPM
void File_Avc::sei_message_user_data_unregistered_bluray_MDPM(int32u payloadSize)
{
    if (payloadSize<1)
    {
        Skip_XX(payloadSize, "Unknown");
        return;
    }

    Element_Info1("Modified Digital Video Pack Metadata");

    Skip_B1(                                                    "Count");
    payloadSize--;
    string DateTime0, DateTime1, DateTime2, Model0, Model1, Model2;
    int16u MakeName=(int16u)-1;
    Ztring IrisFNumber;
    while (payloadSize >= 5)
    {
        Element_Begin0();
        int8u  ID;
        Get_B1(ID,                                              "ID"); Element_Name(MDPM(ID));
        switch (ID)
        {
            case 0x18:
                        {
                        int16u Year;
                        int8u  MM, Zone_Hours;
                        bool   Zone_Sign, Zone_Minutes;
                        BS_Begin();
                        Mark_0();
                        Skip_SB(                                "DST flag");
                        Get_SB (Zone_Sign,                      "Time zone sign");
                        Get_S1 (4, Zone_Hours,                  "Time zone hours");
                        Get_SB (Zone_Minutes,                   "Time zone half-hour flag");
                        BS_End();
                        Get_B2 (Year,                           "Year");
                        Get_B1 (MM,                             "Month");
                        DateTime0+='0'+(Year>>12);
                        DateTime0+='0'+((Year&0xF00)>>8);
                        DateTime0+='0'+((Year&0xF0)>>4);
                        DateTime0+='0'+(Year&0xF);
                        DateTime0+='-';
                        DateTime0+='0'+((MM&0xF0)>>4);
                        DateTime0+='0'+(MM&0xF);
                        DateTime0+='-';
                        Element_Info1(DateTime0);
                        DateTime2+=Zone_Sign?'-':'+';
                        DateTime2+='0'+Zone_Hours/10;
                        DateTime2+='0'+Zone_Hours%10;
                        DateTime2+=':';
                        DateTime2+=Zone_Minutes?'3':'0';
                        DateTime2+='0';
                        Element_Info1(DateTime2);
                        }
                        break;
            case 0x19:
                        {
                        int8u  DD, hh, mm, ss;
                        Get_B1 (DD,                             "Day");
                        Get_B1 (hh,                             "Hour");
                        Get_B1 (mm,                             "Minute");
                        Get_B1 (ss,                             "Second");
                        DateTime1+='0'+(DD>>4);
                        DateTime1+='0'+(DD&0xF);
                        DateTime1+=' ';
                        DateTime1+='0'+(hh>>4);
                        DateTime1+='0'+(hh&0xF);
                        DateTime1+=':';
                        DateTime1+='0'+(mm>>4);
                        DateTime1+='0'+(mm&0xF);
                        DateTime1+=':';
                        DateTime1+='0'+(ss>>4);
                        DateTime1+='0'+(ss&0xF);
                        Element_Info1(DateTime1);
                        }
                        break;
            case 0x70:
                        consumer_camera_1();
                        break;
            case 0x71:
                        consumer_camera_2();
                        break;
            case 0xA1:
                        {
                        int16u D, N;
                        Get_B2 (D,                              "D");
                        Get_B2 (N,                              "N");
                        IrisFNumber.From_Number(((float64)D)/N, 6);
                        Element_Info1(IrisFNumber);
                        }
                        break;
            case 0xE0:
                        {
                        Get_B2 (MakeName,                       "Name");
                        Skip_B2(                                "Category");
                        Element_Info1(MDPM_MakeName(MakeName));
                        }
                        break;
            case 0xE4:
                        Get_String(4, Model0,                   "Data"); Element_Info1(Model0);
                        break;
            case 0xE5:
                        Get_String(4, Model1,                   "Data"); Element_Info1(Model1);
                        break;
            case 0xE6:
                        Get_String(4, Model2,                   "Data");
                        Model2.erase(Model2.find_last_not_of('\0')+1);
                        Element_Info1(Model2);
                        break;
            default: Skip_B4("Data");
        }
        Element_End0();
        payloadSize -= 5;
    }
    if (payloadSize)
        Skip_XX(payloadSize, "Unknown");

    FILLING_BEGIN();
        if (!Frame_Count && !seq_parameter_sets.empty() && !pic_parameter_sets.empty())
        {
            if (!DateTime0.empty() && !DateTime1.empty())
                Fill(Stream_General, 0, General_Recorded_Date, DateTime0+DateTime1+DateTime2);
            if (MDPM_MakeName(MakeName)[0] || !Model0.empty())
            {
                string Model;
                if (MDPM_MakeName(MakeName)[0])
                {
                    Model=MDPM_MakeName(MakeName);
                    Fill(Stream_General, 0, General_Encoded_Application_CompanyName, Model);
                    if (!Model0.empty())
                        Model+=' ';
                }
                Fill(Stream_General, 0, General_Encoded_Application, Model+Model0+Model1+Model2);
                Fill(Stream_General, 0, General_Encoded_Application_Name, Model0+Model1+Model2);
            }
            Fill(Stream_Video, 0, "IrisFNumber", IrisFNumber);
        }
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Avc::consumer_camera_1()
{
    //Parsing
    BS_Begin();
    int8u ae_mode, wb_mode, white_balance, fcm;
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Skip_S1(6,                                                  "iris");
    Get_S1 (4, ae_mode,                                         "ae mode"); Param_Info1(Dv_consumer_camera_1_ae_mode[ae_mode]);
    Skip_S1(4,                                                  "agc(Automatic Gain Control)");
    Get_S1 (3, wb_mode,                                         "wb mode (white balance mode)"); Param_Info1(Dv_consumer_camera_1_wb_mode[wb_mode]);
    Get_S1 (5, white_balance,                                   "white balance"); Param_Info1(Dv_consumer_camera_1_white_balance(white_balance));
    Get_S1 (1, fcm,                                             "fcm (Focus mode)"); Param_Info1(Dv_consumer_camera_1_fcm[fcm]);
    Skip_S1(7,                                                  "focus (focal point)");
    BS_End();

    /* TODO: need some tweaking
    FILLING_BEGIN();
        if (!Frame_Count)
        {
            Ztring Settings;
            if (ae_mode<0x0F) Settings+=__T("ae mode=")+Ztring(Dv_consumer_camera_1_ae_mode[ae_mode])+__T(", ");
            if (wb_mode<0x08) Settings+=__T("wb mode=")+Ztring(Dv_consumer_camera_1_wb_mode[wb_mode])+__T(", ");
            if (wb_mode<0x1F) Settings+=__T("white balance=")+Ztring(Dv_consumer_camera_1_white_balance(white_balance))+__T(", ");
            Settings+=__T("fcm=")+Ztring(Dv_consumer_camera_1_fcm[fcm]);
            Fill(Stream_Video, 0, "Camera_Settings", Settings);
        }
    FILLING_END();
    */
}

//---------------------------------------------------------------------------
void File_Avc::consumer_camera_2()
{
    //Parsing
    BS_Begin();
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Skip_S1(1,                                                  "vpd");
    Skip_S1(5,                                                  "vertical panning speed");
    Skip_S1(1,                                                  "is");
    Skip_S1(1,                                                  "hpd");
    Skip_S1(6,                                                  "horizontal panning speed");
    Skip_S1(8,                                                  "focal length");
    Skip_S1(1,                                                  "zen");
    Info_S1(3, zoom_U,                                          "units of e-zoom");
    Info_S1(4, zoom_D,                                          "1/10 of e-zoom"); /*if (zoom_D!=0xF)*/ Param_Info1(__T("zoom=")+Ztring().From_Number(zoom_U+((float32)zoom_U)/10, 2));
    BS_End();
}

//---------------------------------------------------------------------------
void File_Avc::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_Avc::sei_message_light_level()
{
    Element_Info1("light_level");

    //Parsing
    Get_LightLevel(maximum_content_light_level, maximum_frame_average_light_level);
}

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

    //Parsing
    BS_Begin();
    Skip_UE(                                                    "recovery_frame_cnt");
    Skip_SB(                                                    "exact_match_flag");
    Skip_SB(                                                    "broken_link_flag");
    Skip_S1(2,                                                  "changing_slice_group_idc");
    BS_End();
}

//---------------------------------------------------------------------------
// SEI - 32
void File_Avc::sei_message_mainconcept(int32u payloadSize)
{
    Element_Info1("MainConcept text");

    //Parsing
    string Text;
    Get_String(payloadSize, Text,                               "text");

    if (Text.find("produced by MainConcept H.264/AVC Codec v")!=std::string::npos)
    {
        Encoded_Library=Ztring().From_UTF8(Text).SubString(__T("produced by "), __T(" MainConcept AG"));
        Encoded_Library_Name=__T("MainConcept H.264/AVC Codec");
        Encoded_Library_Version= Ztring().From_UTF8(Text).SubString(__T("produced by MainConcept H.264/AVC Codec v"), __T(" (c) "));
        Encoded_Library_Date=MediaInfoLib::Config.Library_Get(InfoLibrary_Format_MainConcept_Avc, Encoded_Library_Version, InfoLibrary_Date);
    }
}

//---------------------------------------------------------------------------
void File_Avc::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));
}

//---------------------------------------------------------------------------
// Packet "07"
void File_Avc::seq_parameter_set()
{
    Element_Name("seq_parameter_set");

    //parsing
    int32u seq_parameter_set_id;
    seq_parameter_set_struct* Data_Item_New=seq_parameter_set_data(seq_parameter_set_id);
    if (!Data_Item_New)
        return;
    Mark_1(                                                     );
    size_t BS_bits=Data_BS_Remain()%8;
    while (BS_bits)
    {
        Mark_0(                                                 );
        BS_bits--;
    }
    BS_End();

    //Hack for 00003.m2ts: There is a trailing 0x89, why?
    if (Element_Offset+1==Element_Size)
    {
        int8u ToTest;
        Peek_B1(ToTest);
        if (ToTest==0x98)
            Skip_B1(                                            "Unknown");

    }

    //Hack for : There is a trailing data, why?
    if (Element_Offset+4==Element_Size)
    {
        int32u ToTest;
        Peek_B4(ToTest);
        if (ToTest==0xE30633C0)
            Skip_B4(                                            "Unknown");
    }

    //NULL bytes
    while (Element_Offset<Element_Size)
    {
        int8u Null;
        Get_B1 (Null,                                           "NULL byte");
        if (Null)
            Trusted_IsNot("Should be NULL byte");
    }

    FILLING_BEGIN_PRECISE();
        //NextCode
        NextCode_Clear();
        NextCode_Add(0x08);

        //Add
        seq_parameter_set_data_Add(seq_parameter_sets, seq_parameter_set_id, Data_Item_New);

        //Autorisation of other streams
        Streams[0x08].Searching_Payload=true; //pic_parameter_set
        if (Streams[0x07].ShouldDuplicate)
            Streams[0x08].ShouldDuplicate=true; //pic_parameter_set
        Streams[0x0A].Searching_Payload=true; //end_of_seq
        if (Streams[0x07].ShouldDuplicate)
            Streams[0x0A].ShouldDuplicate=true; //end_of_seq
        Streams[0x0B].Searching_Payload=true; //end_of_stream
        if (Streams[0x07].ShouldDuplicate)
            Streams[0x0B].ShouldDuplicate=true; //end_of_stream
    FILLING_ELSE();
        delete Data_Item_New;
    FILLING_END();
}

void File_Avc::seq_parameter_set_data_Add(std::vector<seq_parameter_set_struct*> &Data, const int32u Data_id, seq_parameter_set_struct* Data_Item_New)
{
    //Creating Data
    if (Data_id>=Data.size())
        Data.resize(Data_id+1);
    else
        FirstPFrameInGop_IsParsed=true;
    std::vector<seq_parameter_set_struct*>::iterator Data_Item=Data.begin()+Data_id;
    delete *Data_Item; *Data_Item=Data_Item_New;

    //Computing values (for speed)
    size_t MaxNumber;
    switch (Data_Item_New->pic_order_cnt_type)
    {
        case 0 :
                    MaxNumber=Data_Item_New->MaxPicOrderCntLsb;
                    break;
        case 1 :
        case 2 :
                    MaxNumber=Data_Item_New->MaxFrameNum*2;
                    break;
        default:
                    MaxNumber = 0;
    }

    if (MaxNumber>TemporalReferences_Reserved)
    {
        TemporalReferences.resize(4*MaxNumber);
        TemporalReferences_Reserved=MaxNumber;
    }
}

//---------------------------------------------------------------------------
// Packet "08"
void File_Avc::pic_parameter_set()
{
    Element_Name("pic_parameter_set");

    //Parsing
    int32u  pic_parameter_set_id, seq_parameter_set_id, num_slice_groups_minus1, num_ref_idx_l0_default_active_minus1, num_ref_idx_l1_default_active_minus1, slice_group_map_type=0;
    int8u   weighted_bipred_idc=0;
    bool    entropy_coding_mode_flag,bottom_field_pic_order_in_frame_present_flag, redundant_pic_cnt_present_flag, weighted_pred_flag, deblocking_filter_control_present_flag;
    BS_Begin();
    Get_UE (pic_parameter_set_id,                               "pic_parameter_set_id");
    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)
    {
        if (seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
        {
            //Not yet present
            Skip_BS(Data_BS_Remain(),                               "Data (seq_parameter_set is missing)");
            return;
        }
    }
    Get_SB (entropy_coding_mode_flag,                           "entropy_coding_mode_flag");
    Get_SB (bottom_field_pic_order_in_frame_present_flag,       "bottom_field_pic_order_in_frame_present_flag");
    Get_UE (num_slice_groups_minus1,                            "num_slice_groups_minus1");
    if (num_slice_groups_minus1>7)
    {
        Trusted_IsNot("num_slice_groups_minus1 too high");
        num_slice_groups_minus1=0;
    }
    if (num_slice_groups_minus1>0)
    {
        Get_UE (slice_group_map_type,                           "slice_group_map_type");
        if (slice_group_map_type==0)
        {
            for (int32u Pos=0; Pos<=num_slice_groups_minus1; Pos++)
                Skip_UE(                                        "run_length_minus1");
        }
        else if (slice_group_map_type==2)
        {
            for (int32u Pos=0; Pos<num_slice_groups_minus1; Pos++)
            {
                Skip_UE(                                        "top_left");
                Skip_UE(                                        "bottom_right");
            }
        }
        else if (slice_group_map_type==3
              || slice_group_map_type==4
              || slice_group_map_type==5)
        {
            Skip_SB(                                            "slice_group_change_direction_flag");
            Skip_UE(                                            "slice_group_change_rate_minus1");
        }
        else if (slice_group_map_type==6)
        {
            int32u pic_size_in_map_units_minus1;
            Get_UE (pic_size_in_map_units_minus1,               "pic_size_in_map_units_minus1");
            if(pic_size_in_map_units_minus1>((*seq_parameter_set_Item)->pic_width_in_mbs_minus1+1)*((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1))
            {
                Trusted_IsNot("pic_size_in_map_units_minus1 too high");
                return;
            }
            #if defined (__mips__)       || defined (__mipsel__)
                int32u slice_group_id_Size=(int32u)(std::ceil(std::log((double)(num_slice_groups_minus1+1))/std::log((double)10))); //std::log is natural logarithm
            #else
                int32u slice_group_id_Size=(int32u)(std::ceil(std::log((float32)(num_slice_groups_minus1+1))/std::log((float32)10))); //std::log is natural logarithm
            #endif
            for (int32u Pos=0; Pos<=pic_size_in_map_units_minus1; Pos++)
                Skip_BS(slice_group_id_Size,                    "slice_group_id");
        }
    }
    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");
    Get_SB (weighted_pred_flag,                                 "weighted_pred_flag");
    Get_S1 (2, weighted_bipred_idc,                             "weighted_bipred_idc");
    Skip_SE(                                                    "pic_init_qp_minus26");
    Skip_SE(                                                    "pic_init_qs_minus26");
    Skip_SE(                                                    "chroma_qp_index_offset");
    Get_SB (deblocking_filter_control_present_flag,             "deblocking_filter_control_present_flag");
    Skip_SB(                                                    "constrained_intra_pred_flag");
    Get_SB (redundant_pic_cnt_present_flag,                     "redundant_pic_cnt_present_flag");
    bool more_rbsp_data=false;
    if (Element_Size)
    {
        int64u Offset=Element_Size-1;
        while (Offset && Buffer[Buffer_Offset+(size_t)Offset]==0x00) //Searching if there are NULL bytes at the end of the data
            Offset--;
        size_t Bit_Pos=7;
        while (Bit_Pos && !(Buffer[Buffer_Offset+(size_t)Offset]&(1<<(7-Bit_Pos))))
            Bit_Pos--;
        if (Data_BS_Remain()>1+(7-Bit_Pos)+(Element_Size-Offset-1)*8)
            more_rbsp_data=true;
    }
    if (more_rbsp_data)
    {
        bool transform_8x8_mode_flag;
        Get_SB (transform_8x8_mode_flag,                        "transform_8x8_mode_flag");
        TEST_SB_SKIP(                                           "pic_scaling_matrix_present_flag");
        for (int8u Pos=0; Pos<6+(transform_8x8_mode_flag?((*seq_parameter_set_Item)->chroma_format_idc!=3?2:6):0); Pos++ )
            {
                TEST_SB_SKIP(                                   "pic_scaling_list_present_flag");
                    scaling_list(Pos<6?16:64);
                TEST_SB_END();
            }
        TEST_SB_END();
        Skip_SE(                                                "second_chroma_qp_index_offset");
    }
    Mark_1(                                                     );
    BS_End();

    while (Element_Offset<Element_Size) //Not always removed from the stream, ie in MPEG-4
    {
        int8u Padding;
        Peek_B1(Padding);
        if (!Padding)
            Skip_B1(                                            "Padding");
        else
            break;
    }

    FILLING_BEGIN_PRECISE();
        //Integrity
        if (pic_parameter_set_id>=256)
        {
            Trusted_IsNot("pic_parameter_set_id not valid");
            return; //Problem, not valid
        }
        if (seq_parameter_set_id>=32)
        {
            Trusted_IsNot("seq_parameter_set_id not valid");
            return; //Problem, not valid
        }

        //NextCode
        NextCode_Clear();
        NextCode_Add(0x05);
        NextCode_Add(0x06);
        if (!subset_seq_parameter_sets.empty())
            NextCode_Add(0x14); //slice_layer_extension

        //Filling
        if (pic_parameter_set_id>=pic_parameter_sets.size())
            pic_parameter_sets.resize(pic_parameter_set_id+1);
        std::vector<pic_parameter_set_struct*>::iterator pic_parameter_sets_Item=pic_parameter_sets.begin()+pic_parameter_set_id;
        delete *pic_parameter_sets_Item; *pic_parameter_sets_Item = new pic_parameter_set_struct(
                                                                                                    (int8u)seq_parameter_set_id,
                                                                                                    (int8u)num_ref_idx_l0_default_active_minus1,
                                                                                                    (int8u)num_ref_idx_l1_default_active_minus1,
                                                                                                    weighted_bipred_idc,
                                                                                                    num_slice_groups_minus1,
                                                                                                    slice_group_map_type,
                                                                                                    entropy_coding_mode_flag,
                                                                                                    bottom_field_pic_order_in_frame_present_flag,
                                                                                                    weighted_pred_flag,
                                                                                                    redundant_pic_cnt_present_flag,
                                                                                                    deblocking_filter_control_present_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;
            }
        }
        if (!subset_seq_parameter_sets.empty())
        {
            Streams[0x14].Searching_Payload=true; //slice_layer_extension
            if (Streams[0x08].ShouldDuplicate)
                Streams[0x14].ShouldDuplicate=true; //slice_layer_extension
        }

        //Setting as OK
        if (!Status[IsAccepted])
            Accept("AVC");
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "09"
void File_Avc::access_unit_delimiter()
{
    Element_Name("access_unit_delimiter");

    int8u primary_pic_type;
    BS_Begin();
    Get_S1 ( 3, primary_pic_type,                               "primary_pic_type"); Param_Info1(Avc_primary_pic_type[primary_pic_type]);
    Mark_1_NoTrustError(                                        ); //Found 1 file without this bit
    BS_End();
}

//---------------------------------------------------------------------------
// Packet "09"
void File_Avc::filler_data()
{
    Element_Name("filler_data");

    while (Element_Offset<Element_Size)
    {
        int8u FF;
        Peek_B1(FF);
        if (FF!=0xFF)
            break;
        Element_Offset++;
    }
    BS_Begin();
    Mark_1(                                                     );
    BS_End();
}

//---------------------------------------------------------------------------
// Packet "0E"
void File_Avc::prefix_nal_unit(bool svc_extension_flag)
{
    Element_Name("prefix_nal_unit");

    //Parsing
    if (svc_extension_flag)
    {
        Skip_XX(Element_Size-Element_Offset,                    "prefix_nal_unit_svc");
    }
}

//---------------------------------------------------------------------------
// Packet "0F"
void File_Avc::subset_seq_parameter_set()
{
    Element_Name("subset_seq_parameter_set");

    //Parsing
    int32u subset_seq_parameter_set_id;
    seq_parameter_set_struct* Data_Item_New=seq_parameter_set_data(subset_seq_parameter_set_id);
    if (!Data_Item_New)
        return;
    if (Data_Item_New->profile_idc==83 || Data_Item_New->profile_idc==86)
    {
        //bool svc_vui_parameters_present_flag;
        seq_parameter_set_svc_extension();
        /* The rest is not yet implemented
        Get_SB (svc_vui_parameters_present_flag,                "svc_vui_parameters_present_flag");
        if (svc_vui_parameters_present_flag)
            svc_vui_parameters_extension();
        */
    }
    else if (Data_Item_New->profile_idc==118 || Data_Item_New->profile_idc==128)
    {
        //bool mvc_vui_parameters_present_flag, additional_extension2_flag;
        Mark_1();
        seq_parameter_set_mvc_extension(Data_Item_New);
        /* The rest is not yet implemented
        Get_SB (mvc_vui_parameters_present_flag,                "mvc_vui_parameters_present_flag");
        if (mvc_vui_parameters_present_flag)
            mvc_vui_parameters_extension();
        Get_SB (additional_extension2_flag,                     "additional_extension2_flag");
        if (additional_extension2_flag)
        {
            //Not handled, should skip all bits except 1
            BS_End();
            return;
        }
        */
    }
    /* The rest is not yet implemented
    Mark_1(                                                     );
    */
    BS_End();

    FILLING_BEGIN();
        //NextCode
        NextCode_Clear();
        NextCode_Add(0x08);

        //Add
        seq_parameter_set_data_Add(subset_seq_parameter_sets, subset_seq_parameter_set_id, Data_Item_New);

        //Autorisation of other streams
        Streams[0x08].Searching_Payload=true; //pic_parameter_set
        if (Streams[0x0F].ShouldDuplicate)
            Streams[0x08].ShouldDuplicate=true; //pic_parameter_set
        Streams[0x0A].Searching_Payload=true; //end_of_seq
        if (Streams[0x0F].ShouldDuplicate)
            Streams[0x0A].ShouldDuplicate=true; //end_of_seq
        Streams[0x0B].Searching_Payload=true; //end_of_stream
        if (Streams[0x0F].ShouldDuplicate)
            Streams[0x0B].ShouldDuplicate=true; //end_of_stream
    FILLING_END();
}

//---------------------------------------------------------------------------
// Packet "14"
void File_Avc::slice_layer_extension(bool svc_extension_flag)
{
    Element_Name("slice_layer_extension");

    //Parsing
    if (svc_extension_flag)
    {
        Skip_XX(Element_Size-Element_Offset,                    "slice_header_in_scalable_extension + slice_data_in_scalable_extension");
    }
    else
    {
        BS_Begin();
        slice_header();
        slice_data(true);
        BS_End();
    }
}

//***************************************************************************
// SubElements
//***************************************************************************

//---------------------------------------------------------------------------
File_Avc::seq_parameter_set_struct* File_Avc::seq_parameter_set_data(int32u &Data_id)
{
    //Parsing
    seq_parameter_set_struct::vui_parameters_struct* vui_parameters_Item=NULL;
    int32u  chroma_format_idc=1, bit_depth_luma_minus8=0, bit_depth_chroma_minus8=0, log2_max_frame_num_minus4, pic_order_cnt_type, log2_max_pic_order_cnt_lsb_minus4=(int32u)-1, max_num_ref_frames, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1, frame_crop_left_offset=0, frame_crop_right_offset=0, frame_crop_top_offset=0, frame_crop_bottom_offset=0;
    int8u   profile_idc, level_idc;
    bool    constraint_set3_flag, separate_colour_plane_flag=false, delta_pic_order_always_zero_flag=false, frame_mbs_only_flag, mb_adaptive_frame_field_flag=false;
    Get_B1 (profile_idc,                                        "profile_idc");
    BS_Begin();
    Element_Begin1("constraints");
        Skip_SB(                                                "constraint_set0_flag");
        Skip_SB(                                                "constraint_set1_flag");
        Skip_SB(                                                "constraint_set2_flag");
        Get_SB (constraint_set3_flag,                           "constraint_set3_flag");
        Skip_SB(                                                "constraint_set4_flag");
        Skip_SB(                                                "constraint_set5_flag");
        Skip_BS(2,                                              "reserved_zero_2bits");
    Element_End0();
    Get_S1 ( 8, level_idc,                                      "level_idc");
    Get_UE (    Data_id,                                        "seq_parameter_set_id");
    switch (profile_idc)
    {
        case 100 :
        case 110 :
        case 122 :
        case 244 :
        case  44 :
        case  83 :
        case  86 :
        case 118 :
        case 128 :  //High profiles
        case 138 :
                    Element_Begin1("high profile specific");
                    Get_UE (chroma_format_idc,                  "chroma_format_idc"); Param_Info1C((chroma_format_idc<3), Avc_ChromaSubsampling_format_idc(chroma_format_idc));
                    if (chroma_format_idc==3)
                        Get_SB (separate_colour_plane_flag,     "separate_colour_plane_flag");
                    Get_UE (bit_depth_luma_minus8,              "bit_depth_luma_minus8");
                    Get_UE (bit_depth_chroma_minus8,            "bit_depth_chroma_minus8");
                    Skip_SB(                                    "qpprime_y_zero_transform_bypass_flag");
                    TEST_SB_SKIP(                               "seq_scaling_matrix_present_flag");
                        for (int32u Pos=0; Pos<(int32u)((chroma_format_idc!=3) ? 8 : 12); Pos++)
                        {
                            TEST_SB_SKIP(                       "seq_scaling_list_present_flag");
                                scaling_list(Pos<6?16:64);
                            TEST_SB_END();
                        }
                    TEST_SB_END();
                    Element_End0();
                    break;
        default  :  ;
    }
    Get_UE (log2_max_frame_num_minus4,                          "log2_max_frame_num_minus4");
    Get_UE (pic_order_cnt_type,                                 "pic_order_cnt_type");
    if (pic_order_cnt_type==0)
        Get_UE (log2_max_pic_order_cnt_lsb_minus4,              "log2_max_pic_order_cnt_lsb_minus4");
    else if (pic_order_cnt_type==1)
    {
        int32u num_ref_frames_in_pic_order_cnt_cycle;
        Get_SB (delta_pic_order_always_zero_flag,               "delta_pic_order_always_zero_flag");
        Skip_SE(                                                "offset_for_non_ref_pic");
        Skip_SE(                                                "offset_for_top_to_bottom_field");
        Get_UE (num_ref_frames_in_pic_order_cnt_cycle,          "num_ref_frames_in_pic_order_cnt_cycle");
        if (num_ref_frames_in_pic_order_cnt_cycle>=256)
        {
            Trusted_IsNot("num_ref_frames_in_pic_order_cnt_cycle too high");
            return NULL;
        }
        for(int32u Pos=0; Pos<num_ref_frames_in_pic_order_cnt_cycle; Pos++)
            Skip_SE(                                            "offset_for_ref_frame");
    }
    else if (pic_order_cnt_type > 2)
    {
        Trusted_IsNot("pic_order_cnt_type not supported");
        return NULL;
    }
    Get_UE (max_num_ref_frames,                                 "max_num_ref_frames");
    Skip_SB(                                                    "gaps_in_frame_num_value_allowed_flag");
    Get_UE (pic_width_in_mbs_minus1,                            "pic_width_in_mbs_minus1");
    Get_UE (pic_height_in_map_units_minus1,                     "pic_height_in_map_units_minus1");
    Get_SB (frame_mbs_only_flag,                                "frame_mbs_only_flag");
    if (!frame_mbs_only_flag)
        Get_SB (mb_adaptive_frame_field_flag,                   "mb_adaptive_frame_field_flag");
    Skip_SB(                                                    "direct_8x8_inference_flag");
    TEST_SB_SKIP(                                               "frame_cropping_flag");
        Get_UE (frame_crop_left_offset,                         "frame_crop_left_offset");
        Get_UE (frame_crop_right_offset,                        "frame_crop_right_offset");
        Get_UE (frame_crop_top_offset,                          "frame_crop_top_offset");
        Get_UE (frame_crop_bottom_offset,                       "frame_crop_bottom_offset");
    TEST_SB_END();
    TEST_SB_SKIP(                                               "vui_parameters_present_flag");
        vui_parameters(vui_parameters_Item);
    TEST_SB_END();

    FILLING_BEGIN();
        //Integrity
        if (Data_id>=32)
        {
            Trusted_IsNot("seq_parameter_set_id not valid");
            delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
            return NULL; //Problem, not valid
        }
        if (pic_order_cnt_type==0 && log2_max_pic_order_cnt_lsb_minus4>12)
        {
            Trusted_IsNot("log2_max_pic_order_cnt_lsb_minus4 not valid");
            delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
            return NULL; //Problem, not valid
        }
        if (log2_max_frame_num_minus4>12)
        {
            Trusted_IsNot("log2_max_frame_num_minus4 not valid");
            delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
            return NULL; //Problem, not valid
        }

        //Creating Data
        return new seq_parameter_set_struct(
                                                                    vui_parameters_Item,
                                                                    pic_width_in_mbs_minus1,
                                                                    pic_height_in_map_units_minus1,
                                                                    frame_crop_left_offset,
                                                                    frame_crop_right_offset,
                                                                    frame_crop_top_offset,
                                                                    frame_crop_bottom_offset,
                                                                    (int8u)chroma_format_idc,
                                                                    profile_idc,
                                                                    level_idc,
                                                                    (int8u)bit_depth_luma_minus8,
                                                                    (int8u)bit_depth_chroma_minus8,
                                                                    (int8u)log2_max_frame_num_minus4,
                                                                    (int8u)pic_order_cnt_type,
                                                                    (int8u)log2_max_pic_order_cnt_lsb_minus4,
                                                                    (int8u)max_num_ref_frames,
                                                                    constraint_set3_flag,
                                                                    separate_colour_plane_flag,
                                                                    delta_pic_order_always_zero_flag,
                                                                    frame_mbs_only_flag,
                                                                    mb_adaptive_frame_field_flag
                                                                  );
    FILLING_ELSE();
        delete vui_parameters_Item; //vui_parameters_Item=NULL;
        return NULL;
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Avc::scaling_list(int32u ScalingList_Size)
{
    //From http://mpeg4ip.cvs.sourceforge.net/mpeg4ip/mpeg4ip/util/h264/main.cpp?revision=1.17&view=markup
    int32u lastScale=8, nextScale=8;
    for (int32u Pos=0; Pos<ScalingList_Size; Pos++)
    {
        if (nextScale!=0)
        {
            int32s delta_scale;
            Get_SE (delta_scale,                                "scale_delta");
            nextScale=(lastScale+delta_scale+256)%256;
        }
        if (nextScale)
            lastScale=nextScale;
    }
}

//---------------------------------------------------------------------------
void File_Avc::vui_parameters(seq_parameter_set_struct::vui_parameters_struct* &vui_parameters_Item_)
{
    //Parsing
    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, colour_description_present_flag=false, timing_info_present_flag, fixed_frame_rate_flag=false, nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag, pic_struct_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");
        Skip_UE(                                                "chroma_sample_loc_type_top_field");
        Skip_UE(                                                "chroma_sample_loc_type_bottom_field");
    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");
        Get_SB (    fixed_frame_rate_flag,                      "fixed_frame_rate_flag");
    TEST_SB_END();
    TEST_SB_GET (nal_hrd_parameters_present_flag,               "nal_hrd_parameters_present_flag");
        hrd_parameters(NAL);
    TEST_SB_END();
    TEST_SB_GET (vcl_hrd_parameters_present_flag,               "vcl_hrd_parameters_present_flag");
        hrd_parameters(VCL);
    TEST_SB_END();
    if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
        Skip_SB(                                                "low_delay_hrd_flag");
    Get_SB (   pic_struct_present_flag,                         "pic_struct_present_flag");
    TEST_SB_SKIP(                                               "bitstream_restriction_flag");
        int32u  max_num_reorder_frames;
        Skip_SB(                                                "motion_vectors_over_pic_boundaries_flag");
        Skip_UE(                                                "max_bytes_per_pic_denom");
        Skip_UE(                                                "max_bits_per_mb_denom");
        Skip_UE(                                                "log2_max_mv_length_horizontal");
        Skip_UE(                                                "log2_max_mv_length_vertical");
        Get_UE (max_num_reorder_frames,                         "max_num_reorder_frames");
        Skip_UE(                                                "max_dec_frame_buffering");
    TEST_SB_END();

    FILLING_BEGIN();
        vui_parameters_Item_=new seq_parameter_set_struct::vui_parameters_struct(
                                                                                    NAL,
                                                                                    VCL,
                                                                                    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,
                                                                                    colour_description_present_flag,
                                                                                    timing_info_present_flag,
                                                                                    fixed_frame_rate_flag,
                                                                                    pic_struct_present_flag
                                                                                );
    FILLING_ELSE();
        delete NAL; NAL=NULL;
        delete VCL; VCL=NULL;
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Avc::hrd_parameters(seq_parameter_set_struct::vui_parameters_struct::xxl* &hrd_parameters_Item_)
{
    //Parsing
    int32u cpb_cnt_minus1;
    int8u  bit_rate_scale, cpb_size_scale, initial_cpb_removal_delay_length_minus1, cpb_removal_delay_length_minus1, dpb_output_delay_length_minus1, time_offset_length;
    Get_UE (   cpb_cnt_minus1,                                  "cpb_cnt_minus1");
    Get_S1 (4, bit_rate_scale,                                  "bit_rate_scale");
    Get_S1 (4, cpb_size_scale,                                  "cpb_size_scale");
    if (cpb_cnt_minus1>31)
    {
        Trusted_IsNot("cpb_cnt_minus1 too high");
        cpb_cnt_minus1=0;
    }
    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");
        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();
    }
    Get_S1 (5, initial_cpb_removal_delay_length_minus1,         "initial_cpb_removal_delay_length_minus1");
    Get_S1 (5, cpb_removal_delay_length_minus1,                 "cpb_removal_delay_length_minus1");
    Get_S1 (5, dpb_output_delay_length_minus1,                  "dpb_output_delay_length_minus1");
    Get_S1 (5, time_offset_length,                              "time_offset_length");

    //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,
                                                                                    initial_cpb_removal_delay_length_minus1,
                                                                                    cpb_removal_delay_length_minus1,
                                                                                    dpb_output_delay_length_minus1,
                                                                                    time_offset_length
                                                                                 );
}

//---------------------------------------------------------------------------
void File_Avc::nal_unit_header_svc_extension()
{
    //Parsing
    Element_Begin1("nal_unit_header_svc_extension");
    Skip_SB(                                                    "idr_flag");
    Skip_S1( 6,                                                 "priority_id");
    Skip_SB(                                                    "no_inter_layer_pred_flag");
    Skip_S1( 3,                                                 "dependency_id");
    Skip_S1( 4,                                                 "quality_id");
    Skip_S1( 3,                                                 "temporal_id");
    Skip_SB(                                                    "use_ref_base_pic_flag");
    Skip_SB(                                                    "discardable_flag");
    Skip_SB(                                                    "output_flag");
    Skip_S1( 2,                                                 "reserved_three_2bits");
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Avc::nal_unit_header_mvc_extension()
{
    //Parsing
    Element_Begin1("nal_unit_header_mvc_extension");
    Skip_SB(                                                    "non_idr_flag");
    Skip_S1( 6,                                                 "priority_id");
    Skip_S1(10,                                                 "view_id");
    Skip_S1( 3,                                                 "temporal_id");
    Skip_SB(                                                    "anchor_pic_flag");
    Skip_SB(                                                    "inter_view_flag");
    Skip_SB(                                                    "reserved_one_bit");
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Avc::seq_parameter_set_svc_extension()
{
    //Parsing
    Element_Begin1("seq_parameter_set_svc_extension");
    //Skip_SB(                                                    "");
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Avc::svc_vui_parameters_extension()
{
    //Parsing
    Element_Begin1("svc_vui_parameters_extension");
    //Skip_SB(                                                    "");
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Avc::seq_parameter_set_mvc_extension(seq_parameter_set_struct* Data_Item)
{
    //Parsing
    Element_Begin1("seq_parameter_set_mvc_extension");
    int32u num_views_minus1;
    Get_UE (num_views_minus1,                                   "num_views_minus1");
    //(Not implemented)
    Element_End0();

    FILLING_BEGIN();
        Data_Item->num_views_minus1 = (int16u)num_views_minus1;
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Avc::mvc_vui_parameters_extension()
{
    //Parsing
    Element_Begin1("mvc_vui_parameters_extension");
    Skip_SB(                                                    "");
    Element_End0();
}

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

//---------------------------------------------------------------------------
void File_Avc::SPS_PPS()
{
    //Parsing
    int8u Profile, Level, seq_parameter_set_count, pic_parameter_set_count;
    if (SizedBlocks)
        Skip_B1(                                                "configurationVersion");
    Get_B1 (Profile,                                            "AVCProfileIndication");
    Skip_B1(                                                    "profile_compatibility");
    Get_B1 (Level,                                              "AVCLevelIndication");
    BS_Begin();
    Skip_S1(6,                                                  "reserved");
    Get_S1 (2, SizeOfNALU_Minus1,                               "lengthSizeMinusOne");
    Skip_S1(3,                                                  "reserved");
    Get_S1 (5, seq_parameter_set_count,                         "numOfSequenceParameterSets");
    BS_End();
    for (int8u Pos=0; Pos<seq_parameter_set_count; Pos++)
    {
        Element_Begin1("seq_parameter_set");
        int16u Size;
        Get_B2 (Size,                                           "sequenceParameterSetLength");
        if (!Size || Size>Element_Size-Element_Offset)
        {
            Trusted_IsNot("Size is wrong");
            break; //There is an error
        }
        BS_Begin();
        Mark_0 ();
        Skip_S1( 2,                                             "nal_ref_idc");
        Skip_S1( 5,                                             "nal_unit_type");
        BS_End();
        if (!Trusted_Get())
            break;
        int64u Element_Offset_Save=Element_Offset;
        int64u Element_Size_Save=Element_Size;
        Buffer_Offset+=(size_t)Element_Offset_Save;
        Element_Offset=0;
        Element_Size=Size-(Size?1:0);
        Element_Code=0x07; //seq_parameter_set
        Data_Parse();
        Buffer_Offset-=(size_t)Element_Offset_Save;
        Element_Offset=Element_Offset_Save+Size-1;
        Element_Size=Element_Size_Save;
        Element_End0();
    }
    Get_B1 (pic_parameter_set_count,                            "numOfPictureParameterSets");
    for (int8u Pos=0; Pos<pic_parameter_set_count; Pos++)
    {
        Element_Begin1("pic_parameter_set");
        int16u Size;
        Get_B2 (Size,                                           "pictureParameterSetLength");
        if (!Size || Size>Element_Size-Element_Offset)
        {
            Trusted_IsNot("Size is wrong");
            break; //There is an error
        }
        BS_Begin();
        Mark_0 ();
        Skip_S1( 2,                                             "nal_ref_idc");
        Skip_S1( 5,                                             "nal_unit_type");
        BS_End();
        if (!Trusted_Get())
            break;
        int64u Element_Offset_Save=Element_Offset;
        int64u Element_Size_Save=Element_Size;
        Buffer_Offset+=(size_t)Element_Offset_Save;
        Element_Offset=0;
        Element_Size=Size-1;
        Element_Code=0x08; //pic_parameter_set
        Data_Parse();
        Buffer_Offset-=(size_t)Element_Offset_Save;
        Element_Offset=Element_Offset_Save+Size-1;
        Element_Size=Element_Size_Save;
        Element_End0();
    }
    if (Element_Offset<Element_Size)
    {
        switch (Profile)
        {
            case 100:
            case 110:
            case 122:
            case 144:
                        {
                        int8u numOfSequenceParameterSetExt;
                        BS_Begin();
                        Skip_S1( 6,                             "reserved");
                        Skip_S1( 2,                             "chroma_format");
                        Skip_S1( 5,                             "reserved");
                        Skip_S1( 3,                             "bit_depth_luma_minus8");
                        Skip_S1( 5,                             "reserved");
                        Skip_S1( 3,                             "bit_depth_chroma_minus8");
                        BS_End();
                        Get_B1 (numOfSequenceParameterSetExt,   "numOfSequenceParameterSetExt");
                        for (int8u Pos=0; Pos<numOfSequenceParameterSetExt; Pos++)
                        {
                            Element_Begin1("sequenceParameterSetExtNALUnit");
                            int16u Size;
                            Get_B2 (Size,                       "sequenceParameterSetExtLength");
                            BS_Begin();
                            Mark_0 ();
                            Skip_S1( 2,                         "nal_ref_idc");
                            Skip_S1( 5,                         "nal_unit_type");
                            BS_End();
                            int64u Element_Offset_Save=Element_Offset;
                            int64u Element_Size_Save=Element_Size;
                            Buffer_Offset+=(size_t)Element_Offset_Save;
                            Element_Offset=0;
                            Element_Size=Size-1;
                            if (Element_Size>Element_Size_Save-Element_Offset_Save)
                                break; //There is an error
                            Element_Code=0x0F; //subset_seq_parameter_set
                            Data_Parse();
                            Buffer_Offset-=(size_t)Element_Offset_Save;
                            Element_Offset=Element_Offset_Save+Size-1;
                            Element_Size=Element_Size_Save;
                            Element_End0();
                        }
                        }
            default:;
        }
    }
    if (Element_Offset<Element_Size)
        Skip_XX(Element_Size-Element_Offset,                        "Padding?");

    //Filling
    FILLING_BEGIN_PRECISE();
        //Detection of some bugs in the file
        if (!seq_parameter_sets.empty() && seq_parameter_sets[0] && (Profile!=seq_parameter_sets[0]->profile_idc || Level!=seq_parameter_sets[0]->level_idc))
            MuxingMode=Ztring("Container profile=")+Ztring().From_UTF8(Avc_profile_idc(Profile))+__T("@")+Ztring().From_Number(((float)Level)/10, 1);

        MustParse_SPS_PPS=false;
        if (!Status[IsAccepted])
            Accept("AVC");
    FILLING_END();
}

//***************************************************************************
// Helpers
//***************************************************************************

//---------------------------------------------------------------------------
std::string File_Avc::GOP_Detect (std::string PictureTypes)
{
    //Finding a string without blanks
    size_t PictureTypes_Limit=PictureTypes.find(' ');
    if (PictureTypes_Limit!=string::npos)
    {
        if (PictureTypes_Limit>PictureTypes.size()/2)
            PictureTypes.resize(PictureTypes_Limit);
        else
        {
            //Trim
            size_t TrimPos;
            TrimPos=PictureTypes.find_first_not_of(' ');
            if (TrimPos!=string::npos)
                PictureTypes.erase(0, TrimPos);
            TrimPos=PictureTypes.find_last_not_of(' ');
            if (TrimPos!=string::npos)
                PictureTypes.erase(TrimPos+1);

            //Finding the longest string
            ZtringList List; List.Separator_Set(0, __T(" "));
            List.Write(Ztring().From_UTF8(PictureTypes));
            size_t MaxLength=0;
            size_t MaxLength_Pos=0;
            for (size_t Pos=0; Pos<List.size(); Pos++)
                if (List[Pos].size()>MaxLength)
                {
                    MaxLength=List[Pos].size();
                    MaxLength_Pos=Pos;
                }
            PictureTypes=List[MaxLength_Pos].To_UTF8();

        }
    }

    //Creating all GOP values
    std::vector<Ztring> GOPs;
    size_t GOP_Frame_Count=0;
    size_t GOP_BFrames_Max=0;
    size_t I_Pos1=PictureTypes.find('I');
    while (I_Pos1!=std::string::npos)
    {
        size_t I_Pos2=PictureTypes.find('I', I_Pos1+1);
        if (I_Pos2!=std::string::npos)
        {
            std::vector<size_t> P_Positions;
            size_t P_Position=I_Pos1;
            do
            {
                P_Position=PictureTypes.find('P', P_Position+1);
                if (P_Position<I_Pos2)
                    P_Positions.push_back(P_Position);
            }
            while (P_Position<I_Pos2);
            if (P_Positions.size()>1 && P_Positions[0]>I_Pos1+1 && P_Positions[P_Positions.size()-1]==I_Pos2-1)
                P_Positions.resize(P_Positions.size()-1); //Removing last P-Frame for next test, this is often a terminating P-Frame replacing a B-Frame
            Ztring GOP;
            bool IsOK=true;
            if (!P_Positions.empty())
            {
                size_t Delta=P_Positions[0]-I_Pos1;
                for (size_t Pos=1; Pos<P_Positions.size(); Pos++)
                    if (P_Positions[Pos]-P_Positions[Pos-1]!=Delta)
                    {
                        IsOK=false;
                        break;
                    }
                if (IsOK)
                {
                    GOP+=__T("M=")+Ztring::ToZtring(P_Positions[0]-I_Pos1)+__T(", ");
                    if (P_Positions[0]-I_Pos1>GOP_BFrames_Max)
                        GOP_BFrames_Max=P_Positions[0]-I_Pos1;
                }
            }
            if (IsOK)
            {
                GOP+=__T("N=")+Ztring::ToZtring(I_Pos2-I_Pos1);
                GOPs.push_back(GOP);
            }
            else
                GOPs.push_back(Ztring()); //There is a problem, blank
            GOP_Frame_Count+=I_Pos2-I_Pos1;
        }
        I_Pos1=I_Pos2;
    }

    //Some clean up
    if (GOP_Frame_Count+GOP_BFrames_Max>Frame_Count && !GOPs.empty())
        GOPs.resize(GOPs.size()-1); //Removing the last one, there may have uncomplete B-frame filling
    if (GOPs.size()>4)
        GOPs.erase(GOPs.begin()); //Removing the first one, it is sometime different and we have enough to deal with

    //Filling
    if (GOPs.size()>=4)
    {
        bool IsOK=true;
        for (size_t Pos=1; Pos<GOPs.size(); Pos++)
            if (GOPs[Pos]!=GOPs[0])
            {
                IsOK=false;
                break;
            }
        if (IsOK)
            return GOPs[0].To_UTF8();
    }

    return string();
}

//---------------------------------------------------------------------------
std::string File_Avc::ScanOrder_Detect (std::string ScanOrders)
{
    //Finding a string without blanks
    size_t ScanOrders_Limit=ScanOrders.find(' ');
    if (ScanOrders_Limit!=string::npos)
    {
        if (ScanOrders_Limit>ScanOrders.size()/2)
            ScanOrders.resize(ScanOrders_Limit);
        else
        {
            //Trim
            size_t TrimPos;
            TrimPos=ScanOrders.find_first_not_of(' ');
            if (TrimPos!=string::npos)
                ScanOrders.erase(0, TrimPos);
            TrimPos=ScanOrders.find_last_not_of(' ');
            if (TrimPos!=string::npos)
                ScanOrders.erase(TrimPos+1);

            //Finding the longest string
            ZtringList List; List.Separator_Set(0, __T(" "));
            List.Write(Ztring().From_UTF8(ScanOrders));
            size_t MaxLength=0;
            size_t MaxLength_Pos=0;
            for (size_t Pos=0; Pos<List.size(); Pos++)
                if (List[Pos].size()>MaxLength)
                {
                    MaxLength=List[Pos].size();
                    MaxLength_Pos=Pos;
                }
            ScanOrders=List[MaxLength_Pos].To_UTF8();

        }
    }

    //Filling
    if (ScanOrders.find("TBTBTBTB")==0)
        return ("TFF");
    if (ScanOrders.find("BTBTBTBT")==0)
        return ("BFF");
    return string();
}

} //NameSpace

#endif //MEDIAINFO_AVC_YES
