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

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Elements part
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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

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

//---------------------------------------------------------------------------
#ifdef MEDIAINFO_WM_YES
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Wm.h"
#if defined(MEDIAINFO_VC1_YES)
    #include "MediaInfo/Video/File_Vc1.h"
#endif
#if defined(MEDIAINFO_MPEGV_YES)
    #include "MediaInfo/Video/File_Mpegv.h"
#endif
#if defined(MEDIAINFO_AC3_YES)
    #include "MediaInfo/Audio/File_Ac3.h"
#endif
#if defined(MEDIAINFO_MPEGA_YES)
    #include "MediaInfo/Audio/File_Mpega.h"
#endif
#if defined(MEDIAINFO_AAC_YES)
    #include "MediaInfo/Audio/File_Aac.h"
#endif
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if MEDIAINFO_DEMUX
    #include "ThirdParty/base64/base64.h"
#endif //MEDIAINFO_DEMUX
#include "ZenLib/Utils.h"
using namespace ZenLib;
//---------------------------------------------------------------------------

namespace MediaInfoLib
{

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

extern std::string Id3v2_PictureType(int8u Type);

static const char* Wm_CodecList_Kind(int32u Kind)
{
    switch (Kind)
    {
        case 0x01 : return "Video";
        case 0x02 : return "Audio";
        default   : return "";
    }
}

static const char* Wm_BannerImageData_Type(int32u Type)
{
    switch (Type)
    {
    case 0x00 : return "";
        case 0x01 : return "Bitmap";
        case 0x02 : return "JPEG";
        case 0x03 : return "GIF";
        default   : return "";
    }
}

#define UUID(NAME, PART1, PART2, PART3, PART4, PART5) \
    const int64u NAME   =((int64u(0x##PART1))&0xFF)<<56 | ((int64u(0x##PART1)>>8)&0xFF)<<48 | ((int64u(0x##PART1)>>16)&0xFF)<<40 | ((int64u(0x##PART1)>>24)&0xFF)<<32 | ((int64u(0x##PART2))&0xFF)<<24 | ((int64u(0x##PART2)>>8)&0xFF)<<16 | ((int64u(0x##PART3))&0xFF)<<8 | ((int64u(0x##PART3)>>8)&0xFF); \
    const int64u NAME##2=0x##PART4##PART5##ULL; \

namespace Elements
{
    UUID(Header,                                                75B22630, 668E, 11CF, A6D9, 00AA0062CE6C)
    UUID(Header_FileProperties,                                 8CABDCA1, A947, 11CF, 8EE4, 00C00C205365)
    UUID(Header_StreamProperties,                               B7DC0791, A9B7, 11CF, 8EE6, 00C00C205365)
    UUID(Header_StreamProperties_Audio,                         F8699E40, 5B4D, 11CF, A8FD, 00805F5C442B)
    UUID(Header_StreamProperties_Video,                         BC19EFC0, 5B4D, 11CF, A8FD, 00805F5C442B)
    UUID(Header_StreamProperties_Command,                       59DACFC0, 59E6, 11D0, A3AC, 00A0C90348F6)
    UUID(Header_StreamProperties_JFIF,                          B61BE100, 5B4E, 11CF, A8FD, 00805F5C442B)
    UUID(Header_StreamProperties_DegradableJPEG,                35907DE0, E415, 11CF, A917, 00805F5C442B)
    UUID(Header_StreamProperties_FileTransfer,                  91BD222C, F21C, 497A, 8B6D, 5AA86BFC0185)
    UUID(Header_StreamProperties_Binary,                        3AFB65E2, 47EF, 40F2, AC2C, 70A90D71D343)
    UUID(Header_StreamProperties_Binary_WebStreamMediaSubType,  776257D4, C627, 41CB, 8F81, 7AC7FF1C40CC)
    UUID(Header_StreamProperties_Binary_WebStreamFormat,        DA1E6B13, 8359, 4050, B398, 388E965BF00C)
    UUID(Header_HeaderExtension,                                5FBF03B5, A92E, 11CF, 8EE3, 00C00C205365)
    UUID(Header_HeaderExtension_ExtendedStreamProperties,       14E6A5CB, C672, 4332, 8399, A96952065B5A)
    UUID(Header_HeaderExtension_AdvancedMutualExclusion,        A08649CF, 4775, 4670, 8A16, 6E35357566CD)
    UUID(Header_HeaderExtension_GroupMutualExclusion,           D1465A40, 5A79, 4338, B71B, E36B8FD6C249)
    UUID(Header_HeaderExtension_StreamPrioritization,           D4FED15B, 88D3, 454F, 81F0, ED5C45999E24)
    UUID(Header_HeaderExtension_BandwidthSharing,               A69609E6, 517B, 11D2, B6AF, 00C04FD908E9)
    UUID(Header_HeaderExtension_LanguageList,                   7C4346A9, EFE0, 4BFC, B229, 393EDE415C85)
    UUID(Header_HeaderExtension_Metadata,                       C5F8CBEA, 5BAF, 4877, 8467, AA8C44FA4CCA)
    UUID(Header_HeaderExtension_MetadataLibrary,                44231C94, 9498, 49D1, A141, 1D134E457054)
    UUID(Header_HeaderExtension_IndexParameters,                D6E229DF, 35DA, 11D1, 9034, 00A0C90349BE)
    UUID(Header_HeaderExtension_MediaIndexParameters,           6B203BAD, 3F11, 48E4, ACA8, D7613DE2CFA7)
    UUID(Header_HeaderExtension_TimecodeIndexParameters,        F55E496D, 9797, 4B5D, 8C8B, 604DFE9BFB24)
    UUID(Header_HeaderExtension_Compatibility,                  26F18B5D, 4584, 47EC, 9F5F, 0E651F0452C9)
    UUID(Header_HeaderExtension_AdvancedContentEncryption,      43058533, 6981, 49E6, 9B74, AD12CB86D58C)
    UUID(Header_HeaderExtension_IndexPlaceholder,               D9AADE20, 7C17, 4F9C, BC28, 8555DD98E2A2)
    UUID(Header_CodecList,                                      86D15240, 311D, 11D0, A3A4, 00ACC90348F6)
    UUID(Header_ScriptCommand,                                  1EFB1A30, 0B62, 11D0, A39B, 00A0C90348F6)
    UUID(Header_Marker,                                         F487CD01, A951, 11CF, 8EE6, 00C00C205365)
    UUID(Header_BitRateMutualExclusion,                         D6E229DC, 35DA, 11D1, 9034, 00A0C90349BE)
    UUID(Header_ErrorCorrection,                                75B22635, 668E, 11CF, A6D9, 00AA0062CE6C)
    UUID(Header_ContentDescription,                             75B22633, 668E, 11CF, A6D9, 00AA0062CE6C)
    UUID(Header_ExtendedContentDescription,                     D2D0A440, E307, 11D2, 97F0, 00A0C95EA850)
    UUID(Header_StreamBitRate,                                  7BF875CE, 468D, 11D1, 8D82, 006097C9A2B2)
    UUID(Header_ContentBranding,                                2211B3FA, BD23, 11D2, B4B7, 00A0C955FC6E)
    UUID(Header_ContentEncryption,                              2211B3FB, BD23, 11D2, B4B7, 00A0C955FC6E)
    UUID(Header_ExtendedContentEncryption,                      298AE614, 2622, 4C17, B935, DAE07EE9289C)
    UUID(Header_DigitalSignature,                               2211B3FC, BD23, 11D2, B4B7, 00A0C955FC6E)
    UUID(Header_Padding,                                        1806D474, CADF, 4509, A4BA, 9AABCB96AAE8)
    UUID(Data,                                                  75B22636, 668E, 11CF, A6D9, 00AA0062CE6C)
    UUID(SimpleIndex,                                           33000890, E5B1, 11CF, 89F4, 00A0C90349CB)
    UUID(Index,                                                 D6E229D3, 35DA, 11D1, 9034, 00A0C90349BE)
    UUID(MediaIndex,                                            FEB103F8, 12AD, 4C64, 840F, 2A1D2F7AD48C)
    UUID(TimecodeIndex,                                         3CB73FD0, 0C4A, 4803, 953D, EDF7B6228F0C)

    UUID(Payload_Extension_System_TimeStamp,                    1135BEB7, 3A39, 478A, 98D9, 15C76B00EB69);
    UUID(Mutex_Language,                                        D6E22A00, 35DA, 11D1, 9034, 00A0C90349BE);
    UUID(Mutex_Bitrate,                                         D6E22A01, 35DA, 11D1, 9034, 00A0C90349BE);
}

static const char* Wm_StreamType(const int128u& Kind)
{
    switch (Kind.hi)
    {
        case Elements::Header_StreamProperties_Audio :          return "Audio";
        case Elements::Header_StreamProperties_Video :          return "Video";
        case Elements::Header_StreamProperties_Command :        return "Command";
        case Elements::Header_StreamProperties_JFIF :           return "JFIF";
        case Elements::Header_StreamProperties_DegradableJPEG : return "Degradable JPEG";
        case Elements::Header_StreamProperties_FileTransfer :   return "File Transfer";
        case Elements::Header_StreamProperties_Binary :         return "Binary";
        default :                                               return "";
    }
}

static const char* Wm_ExclusionType(const int128u& ExclusionType)
{
    switch (ExclusionType.hi)
    {
        case Elements::Header_StreamProperties_Audio :          return "Language";
        case Elements::Header_StreamProperties_Video :          return "Bitrate";
        default :                                               return "";
    }
}

//***************************************************************************
// Format
//***************************************************************************

//---------------------------------------------------------------------------
// Element parse
//
void File_Wm::Data_Parse()
{
    //Parsing
    DATA_BEGIN
    LIST(Header)
        ATOM_BEGIN
        ATOM(Header_FileProperties)
        ATOM(Header_StreamProperties)
        LIST(Header_HeaderExtension)
            ATOM_BEGIN
            ATOM(Header_HeaderExtension_ExtendedStreamProperties)
            ATOM(Header_HeaderExtension_AdvancedMutualExclusion)
            ATOM(Header_HeaderExtension_GroupMutualExclusion)
            ATOM(Header_HeaderExtension_StreamPrioritization)
            ATOM(Header_HeaderExtension_BandwidthSharing)
            ATOM(Header_HeaderExtension_LanguageList)
            ATOM(Header_HeaderExtension_Metadata)
            ATOM(Header_HeaderExtension_MetadataLibrary)
            ATOM(Header_HeaderExtension_IndexParameters)
            ATOM(Header_HeaderExtension_MediaIndexParameters)
            ATOM(Header_HeaderExtension_TimecodeIndexParameters)
            ATOM(Header_HeaderExtension_Compatibility)
            ATOM(Header_HeaderExtension_AdvancedContentEncryption)
            ATOM(Header_HeaderExtension_IndexPlaceholder)
            ATOM(Header_Padding)
            ATOM_END
        ATOM(Header_CodecList)
        ATOM(Header_ScriptCommand)
        ATOM(Header_Marker)
        ATOM(Header_BitRateMutualExclusion)
        ATOM(Header_ErrorCorrection)
        ATOM(Header_ContentDescription)
        ATOM(Header_ExtendedContentDescription)
        ATOM(Header_StreamBitRate)
        ATOM(Header_ContentBranding)
        ATOM(Header_ContentEncryption)
        ATOM(Header_ExtendedContentEncryption)
        ATOM(Header_DigitalSignature)
        ATOM(Header_Padding)
        ATOM_END
    LIST(Data)
        ATOM_DEFAULT_ALONE(Data_Packet)
    LIST_SKIP(SimpleIndex)
    LIST_SKIP(Index)
    ATOM(MediaIndex)
    ATOM(TimecodeIndex)
    DATA_END
}

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

//---------------------------------------------------------------------------
void File_Wm::Header()
{
    Data_Accept("Windows Media");
    Element_Name("Header");

    //Parsing
    Skip_L4(                                                    "Number of Header Objects");
    Skip_L1(                                                    "Alignment");
    Skip_L1(                                                    "Architecture");

    FILLING_BEGIN();
        Fill(Stream_General, 0, General_Format, "Windows Media");
        Header_StreamProperties_StreamOrder=0;
    FILLING_END();
}

//---------------------------------------------------------------------------
void File_Wm::Header_FileProperties()
{
    Element_Name("File Properties");

    //Parsing
    int64u CreationDate, PlayDuration, SendDuration, Preroll;
    int32u Flags, MaximumBitRate;
    Skip_GUID(                                                  "File ID");
    Skip_L8(                                                    "File Size");
    Get_L8 (CreationDate,                                       "Creation Date"); Param_Info1(Ztring().Date_From_Milliseconds_1601(CreationDate/10000));
    Skip_L8(                                                    "Data Packets Count");
    Get_L8 (PlayDuration,                                       "Play Duration"); Param_Info_From_Milliseconds(PlayDuration/10000);
    Get_L8 (SendDuration,                                       "Send Duration"); Param_Info_From_Milliseconds(SendDuration/10000);
    Get_L8 (Preroll,                                            "Preroll"); Param_Info_From_Milliseconds(Preroll);
    Get_L4 (Flags,                                              "Flags");
        Skip_Flags(Flags, 0,                                    "Broadcast");
        Skip_Flags(Flags, 1,                                    "Seekable");
        Skip_Flags(Flags, 2,                                    "Use Packet Template");
        Skip_Flags(Flags, 3,                                    "Live");
        Skip_Flags(Flags, 4,                                    "Recordable");
        Skip_Flags(Flags, 5,                                    "Unknown Data Size");
    Skip_L4(                                                    "Minimum Data Packet Size");
    Get_L4 (MaximumDataPacketSize,                              "Maximum Data Packet Size");
    Get_L4 (MaximumBitRate,                                     "Maximum Bitrate");

    //Filling
    if (MaximumBitRate)
        Fill(Stream_General, 0, General_OverallBitRate_Maximum, MaximumBitRate);
    Ztring Encoded_Date_New=Ztring().Date_From_Seconds_1601(CreationDate/10000000);
    const Ztring& Encoded_Date_Old=Retrieve_Const(Stream_General, 0, General_Encoded_Date);
    if (Encoded_Date_Old.empty() || Encoded_Date_New!=Encoded_Date_Old)
        Fill(Stream_General, 0, General_Encoded_Date, Encoded_Date_New);
    if (PlayDuration/1000>Preroll)
        Fill(Stream_General, 0, General_Duration, PlayDuration/10000-Preroll);
    FileProperties_Preroll=(int32u)(Preroll);
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties ()
{
    Element_Name("Stream Properties");

    //Parsing
    int128u StreamType;
    int32u StreamTypeLength, ErrorCorrectionTypeLength;
    Get_GUID(StreamType,                                        "StreamType"); Param_Info1(Wm_StreamType(StreamType)); Element_Info1(Wm_StreamType(StreamType));
    Skip_GUID(                                                  "Error Correction Type");
    Skip_L8(                                                    "Time Offset");
    Get_L4 (StreamTypeLength,                                   "Type-Specific Data Length");
    Get_L4 (ErrorCorrectionTypeLength,                          "Error Correction Data Length");
    Get_L2 (Stream_Number,                                      "Stream Number");
    if (Stream_Number&0x8000)
    {
        Param_Info1("Encrypted Content");
        Stream[Stream_Number&0x007F].Info["Encryption"]=__T("Encrypted");
    }
    Stream_Number&=0x007F; //Only 7bits
    Element_Info1(Stream_Number);
    Skip_L4(                                                    "Reserved");
    switch (StreamType.hi)
    {
        case Elements::Header_StreamProperties_Audio :          Element_Begin0(); //size is StreamTypeLength
                                                                Header_StreamProperties_Audio();
                                                                Element_End0(); break;
        case Elements::Header_StreamProperties_Video :          Element_Begin0(); //size is StreamTypeLength
                                                                Header_StreamProperties_Video();
                                                                Element_End0(); break;
        case Elements::Header_StreamProperties_JFIF :           Element_Begin0(); //size is StreamTypeLength
                                                                Header_StreamProperties_JFIF();
                                                                Element_End0(); break;
        case Elements::Header_StreamProperties_DegradableJPEG : Element_Begin0(); //size is StreamTypeLength
                                                                Header_StreamProperties_DegradableJPEG();
                                                                Element_End0(); break;
        case Elements::Header_StreamProperties_FileTransfer :
        case Elements::Header_StreamProperties_Binary :         Element_Begin0(); //size is StreamTypeLength
                                                                Header_StreamProperties_Binary();
                                                                StreamKind_Last=Stream_Max; StreamPos_Last=(size_t)-1;
                                                                Element_End0(); break;
        default :                                               if (StreamTypeLength>0)
                                                                    Skip_XX(StreamTypeLength, "Type-Specific Data");
                                                                StreamKind_Last=Stream_Max; StreamPos_Last=(size_t)-1;
    }
    if (ErrorCorrectionTypeLength)
        Skip_XX(ErrorCorrectionTypeLength,                      "Error Correction Data");

    //Filling
    stream& StreamItem = Stream[Stream_Number];
    StreamItem.StreamKind=StreamKind_Last;
    StreamItem.StreamPos=StreamPos_Last;
    StreamItem.Info["ID"].From_Number(Stream_Number);
    StreamItem.Info["StreamOrder"].From_Number(Header_StreamProperties_StreamOrder);
    Header_StreamProperties_StreamOrder++;
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Audio ()
{
    Element_Name("Audio");

    //Parsing
    int32u SamplingRate, BytesPerSec;
    int16u CodecID, Channels, Data_Size, Resolution;
    Get_L2 (CodecID,                                            "Codec ID");
    Get_L2 (Channels,                                           "Number of Channels");
    Get_L4 (SamplingRate,                                       "Samples Per Second");
    Get_L4 (BytesPerSec,                                        "Average Number of Bytes Per Second");
    Skip_L2(                                                    "Block Alignment");
    Get_L2 (Resolution,                                         "Bits / Sample");
    Get_L2 (Data_Size,                                          "Codec Specific Data Size");

    //Filling
    Stream_Prepare(Stream_Audio);
    Stream[Stream_Number].IsCreated=true;
    Ztring Codec; Codec.From_Number(CodecID, 16);
    Codec.MakeUpperCase();
    CodecID_Fill(Codec, Stream_Audio, StreamPos_Last, InfoCodecID_Format_Riff);
    Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Codec); //May be replaced by codec parser
    Fill(Stream_Audio, StreamPos_Last, Audio_Codec_CC, Codec);
    if (Channels)
        Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, Channels);
    if (SamplingRate)
        Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, SamplingRate);
    if (BytesPerSec)
        Fill(Stream_Audio, StreamPos_Last, Audio_BitRate, BytesPerSec*8);
    if (Resolution)
        Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, Resolution);

    FILLING_BEGIN();
        //Creating the parser
             if (0);
        #if defined(MEDIAINFO_MPEGA_YES)
        else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Ztring::ToZtring(CodecID, 16))==__T("MPEG Audio"))
        {
            stream& StreamItem = Stream[Stream_Number];
            File_Mpega* Parser = new File_Mpega;
            StreamItem.Parser= Parser;
            Parser->Frame_Count_Valid=8;
            StreamItem.Parser->ShouldContinueParsing=true;
        }
        #endif
        Open_Buffer_Init(Stream[Stream_Number].Parser);
    FILLING_END();

    //Parsing
    if (Data_Size>0)
    {
        Element_Begin1("Codec Specific Data");
        switch (CodecID)
        {
            case 0x0161 :
            case 0x0162 :
            case 0x0163 : Header_StreamProperties_Audio_WMA(); break;
            case 0x1610 : Header_StreamProperties_Audio_HEAac(); break;
            case 0x7A21 :
            case 0x7A22 : Header_StreamProperties_Audio_AMR(); break;
            default     : Skip_XX(Data_Size,                    "Unknown");
        }
        Element_End0();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Audio_WMA ()
{
    Element_Info1("WMA");

            //Demux
            #if MEDIAINFO_DEMUX
                switch (Config->Demux_InitData_Get())
                {
                    case 0 :    //In demux event
                                Demux_Level=2; //Container
                                Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_Header);
                                break;
                    case 1 :    //In field
                                {
                                std::string Data_Raw((const char*)(Buffer+Buffer_Offset+Element_Offset), (size_t)10);//Element_Size-(Element_Offset));
                                std::string Data_Base64(Base64::encode(Data_Raw));
                                Fill(Stream_Audio, StreamPos_Last, "Demux_InitBytes", Data_Base64);
                                Fill_SetOptions(Stream_Audio, StreamPos_Last, "Demux_InitBytes", "N NT");
                                }
                                break;
                    default :   ;
                }
            #endif //MEDIAINFO_DEMUX

    //Parsing
    Skip_L4(                                                    "SamplesPerBlock");
    Skip_L2(                                                    "EncodeOptions");
    Skip_L4(                                                    "SuperBlockAlign");
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Audio_HEAac()
{
    //Parsing
    #if defined(MEDIAINFO_AAC_YES)
        File_Aac* MI=new File_Aac();
        MI->Mode=File_Aac::Mode_HEAACWAVEFORMAT;
        Open_Buffer_Init(MI);
        Open_Buffer_Continue(MI);
        Stream[Stream_Number].Parser=MI;
    #else //MEDIAINFO_AAC_YES
        Skip_XX(Element_Size-Element_Offset,                    "HEAACWAVEFORMAT");
    #endif
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Audio_AMR ()
{
    Element_Info1("AMR");

    //Parsing
    int32u Flags;
    bool   VBR;
    Get_L4 (Flags,                                              "Flags");
        Skip_Flags(Flags, 0,                                    "SID is used");
        Get_Flags (Flags, 1, VBR,                               "Varying bitrate");

    //Filling
    Fill(Stream_Audio, StreamPos_Last, Audio_BitRate_Mode, VBR?"VBR":"CBR");
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Video ()
{
    Element_Name("Video");

    //Parsing
    int32u Width, Height, Compression;
    int16u Data_Size, Resolution;
    Get_L4 (Width,                                              "Width");
    Get_L4 (Height,                                             "Height");
    Skip_L1(                                                    "Flags");
    Get_L2 (Data_Size,                                          "Format Data Size");
    Skip_L4(                                                    "Size");
    Get_L4 (Width,                                              "Width");
    Get_L4 (Height,                                             "Height");
    Skip_L2(                                                    "Planes");
    Get_L2 (Resolution,                                         "BitCount");
    Get_C4 (Compression,                                        "Compression");
    Skip_L4(                                                    "SizeImage");
    Skip_L4(                                                    "XPelsPerMeter");
    Skip_L4(                                                    "YPelsPerMeter");
    Skip_L4(                                                    "ClrUsed");
    Skip_L4(                                                    "ClrImportant");

    //Filling
    Stream_Prepare(Stream_Video);
    Stream[Stream_Number].IsCreated=true;
    CodecID_Fill(Ztring().From_CC4(Compression), Stream_Video, StreamPos_Last, InfoCodecID_Format_Riff);
    Fill(Stream_Video, StreamPos_Last, Video_Codec, Ztring().From_CC4(Compression)); //May be replaced by codec parser
    Fill(Stream_Video, StreamPos_Last, Video_Codec_CC, Ztring().From_CC4(Compression));
    Fill(Stream_Video, StreamPos_Last, Video_Width, Width);
    Fill(Stream_Video, StreamPos_Last, Video_Height, Height);
    if (Resolution>0)
        Fill(Stream_Video, StreamPos_Last, Video_BitDepth, (Resolution%3)?Resolution:(Resolution/3)); //If not a multiple of 3, the total resolution is filled
    if (Compression==CC4("DVR "))
        IsDvrMs=true;

    //From Content description (we imagine that data is for all video streams...)
    if (Header_ExtendedContentDescription_AspectRatioX && Header_ExtendedContentDescription_AspectRatioY)
    {
        if (Header_ExtendedContentDescription_AspectRatioX==16 && Header_ExtendedContentDescription_AspectRatioY==9)
            Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, ((float32)16)/9, 3);
        else if (Header_ExtendedContentDescription_AspectRatioX==4 && Header_ExtendedContentDescription_AspectRatioY==3)
            Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, ((float32)4)/3, 3);
        else
            Fill(Stream_Video, StreamPos_Last, Video_PixelAspectRatio, ((float32)Header_ExtendedContentDescription_AspectRatioX)/Header_ExtendedContentDescription_AspectRatioY, 3, true);
    }

    //Creating the parser
         if (0);
    #if defined(MEDIAINFO_VC1_YES)
    else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("VC-1"))
    {
        stream& StreamItem = Stream[Stream_Number];
        File_Vc1* Parser = new File_Vc1;
        StreamItem.Parser= Parser;
        if (Compression==CC4("WMV3"))
        {
            Parser->From_WMV3=true;
            Parser->MustSynchronize=false;
        }
        Parser->FrameIsAlwaysComplete=true; //Warning: this is not always the case, see data parsing
        Open_Buffer_Init(StreamItem.Parser);
        if (Data_Size>40)
        {

            //Demux
            #if MEDIAINFO_DEMUX
                switch (Config->Demux_InitData_Get())
                {
                    case 0 :    //In demux event
                                Element_Code=Stream_Number;
                                Demux_Level=2; //Container
                                Demux(Buffer+(size_t)Element_Offset, (size_t)(Data_Size-40), ContentType_Header);
                                break;
                    case 1 :    //In field
                                {
                                std::string Data_Raw((const char*)(Buffer+(size_t)Element_Offset), (size_t)(Data_Size-40));
                                std::string Data_Base64(Base64::encode(Data_Raw));
                                Fill(Stream_Video, StreamPos_Last, "Demux_InitBytes", Data_Base64);
                                Fill_SetOptions(Stream_Video, StreamPos_Last, "Demux_InitBytes", "N NT");
                                }
                                break;
                    default :   ;
                }
            #endif //MEDIAINFO_DEMUX
            stream& StreamItem = Stream[Stream_Number];
            Open_Buffer_Continue(StreamItem.Parser, (size_t)(Data_Size-40));
            if (StreamItem.Parser->Status[IsFinished])
            {
                Finish(StreamItem.Parser);
                Merge(*StreamItem.Parser, Stream_Video, 0, StreamPos_Last);
                delete StreamItem.Parser; StreamItem.Parser=NULL;
            }
            else
            {
                ((File_Vc1*)StreamItem.Parser)->Only_0D=true;
                ((File_Vc1*)StreamItem.Parser)->MustSynchronize=false;
            }
        }
    }
    #endif
    #if defined(MEDIAINFO_MPEGV_YES)
    else if (MediaInfoLib::Config.Codec_Get(Ztring().From_CC4(Compression), InfoCodec_KindofCodec).find(__T("MPEG-2"))==0)
    {
        stream& StreamItem = Stream[Stream_Number];
        File_Mpegv* Parser = new File_Mpegv;
        StreamItem.Parser  = Parser;
        Parser->Frame_Count_Valid=30; //For searching Pulldown
        Open_Buffer_Init(StreamItem.Parser);
    }
    #endif
    else if (Data_Size>40) //TODO: see "The Mummy_e"
        Skip_XX(Data_Size-40,                                   "Codec Specific Data");
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_JFIF ()
{
    Element_Name("JFIF");

    //Parsing
    int32u Width, Height;
    Get_L4 (Width,                                              "Width");
    Get_L4 (Height,                                             "Height");
    Skip_L4(                                                    "Reserved");

    //Filling
    Stream_Prepare(Stream_Image);
    Fill(Stream_Video, StreamPos_Last, Video_Format, "JPEG");
    Fill(Stream_Video, StreamPos_Last, Video_Codec, "JPEG");
    Fill(Stream_Video, StreamPos_Last, Video_Width, Width);
    Fill(Stream_Video, StreamPos_Last, Video_Height, Height);
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_DegradableJPEG ()
{
    Element_Name("Degradable JPEG");

    int32u Width, Height;
    int16u InterchangeDataLength;
    Get_L4 (Width,                                              "Width");
    Get_L4 (Height,                                             "Height");
    Skip_L2(                                                    "Reserved");
    Skip_L2(                                                    "Reserved");
    Skip_L2(                                                    "Reserved");
    Get_L2 (InterchangeDataLength,                              "Interchange data length");
    if (InterchangeDataLength>0)
        Skip_XX(InterchangeDataLength,                          "Interchange data");
    else
        Skip_L1(                                                "Zero");

    //Filling
    Stream_Prepare(Stream_Image);
    Fill(Stream_Video, StreamPos_Last, Video_Format, "JPEG");
    Fill(Stream_Video, StreamPos_Last, Video_Codec, "JPEG");
    Fill(Stream_Video, StreamPos_Last, Video_Width, Width);
    Fill(Stream_Video, StreamPos_Last, Video_Height, Height);
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamProperties_Binary ()
{
    Element_Name("Binary");

    //Parsing
    int32u FormatDataLength;
    Skip_GUID(                                                  "Major media type");
    Skip_GUID(                                                  "Media subtype");
    Skip_L4(                                                    "Fixed-size samples");
    Skip_L4(                                                    "Temporal compression");
    Skip_L4(                                                    "Sample size");
    Skip_GUID(                                                  "Format type");
    Get_L4 (FormatDataLength,                                   "Format data size");
    if (FormatDataLength>0)
        Skip_XX(FormatDataLength,                               "Format data");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension()
{
    Element_Name("Header Extension");

    //Parsing
    int32u Size;
    Skip_GUID(                                                  "ClockType");
    Skip_L2(                                                    "ClockSize");
    Get_L4 (Size,                                               "Extension Data Size");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_ExtendedStreamProperties()
{
    Element_Name("Extended Stream Properties");

    //Parsing
    int64u AverageTimePerFrame;
    int32u DataBitrate, Flags;
    int16u StreamNumber, LanguageID, StreamNameCount, PayloadExtensionSystemCount;
    Info_L8(StartTime,                                          "Start Time"); Param_Info_From_Milliseconds(StartTime);
    Info_L8(EndTime,                                            "End Time"); Param_Info_From_Milliseconds(EndTime);
    Get_L4 (DataBitrate,                                        "Data Bitrate");
    Skip_L4(                                                    "Buffer Size");
    Skip_L4(                                                    "Initial Buffer Fullness");
    Skip_L4(                                                    "Alternate Data Bitrate");
    Skip_L4(                                                    "Alternate Buffer Size");
    Skip_L4(                                                    "Alternate Initial Buffer Fullness");
    Skip_L4(                                                    "Maximum Object Size");
    Get_L4 (Flags,                                              "Flags");
        Skip_Flags(Flags, 0,                                    "Reliable");
        Skip_Flags(Flags, 1,                                    "Seekable");
        Skip_Flags(Flags, 2,                                    "No Cleanpoints");
        Skip_Flags(Flags, 3,                                    "Resend Live Cleanpoints");
    Get_L2 (StreamNumber,                                       "Stream Number"); Element_Info1(StreamNumber);
    Get_L2 (LanguageID,                                         "Stream Language ID Index");
    Get_L8 (AverageTimePerFrame,                                "Average Time Per Frame");
    Get_L2 (StreamNameCount,                                    "Stream Name Count");
    Get_L2 (PayloadExtensionSystemCount,                        "Payload Extension System Count");
    for (int16u Pos=0; Pos<StreamNameCount; Pos++)
    {
        Element_Begin1("Stream Name");
        int16u StreamNameLength;
        Skip_L2(                                                "Language ID Index");
        Get_L2 (StreamNameLength,                               "Stream Name Length");
        Skip_UTF16L(StreamNameLength,                           "Stream Name");
        Element_End0();
    }
    for (int16u Pos=0; Pos<PayloadExtensionSystemCount; Pos++)
    {
        Element_Begin1("Payload Extension System");
        stream::payload_extension_system Payload_Extension_System;
        int32u ExtensionSystemInfoLength;
        Get_GUID(Payload_Extension_System.ID,                   "Extension System ID");
        Get_L2 (Payload_Extension_System.Size,                  "Extension Data Size");
        Get_L4 (ExtensionSystemInfoLength,                      "Extension System Info Length");
        if (ExtensionSystemInfoLength>0)
            Skip_XX(ExtensionSystemInfoLength,                  "Extension System Info");
        Element_End0();

        //Filling
        Stream[StreamNumber].Payload_Extension_Systems.push_back(Payload_Extension_System);
    }

    //Header_StreamProperties
    if (Element_Offset<Element_Size)
    {
        //This could be everything, but in theory this is only Header_StreamProperties
        int128u Name;
        int64u Size;
        Element_Begin1("Stream Properties Object");
        Element_Begin1("Header");
            Get_GUID(Name,                                      "Name");
            Get_L8 (Size,                                       "Size");
        Element_End0();
        if (Size>=24 && Element_Offset+Size-24==Element_Size)
        {
            switch (Name.hi)
            {
                case Elements::Header_StreamProperties :    Header_StreamProperties(); break;
                default :                                   Skip_XX(Size-24, "Unknown");
            }
        }
        else
            Skip_XX(Element_Size-Element_Offset,                "Problem");
        Element_End0();
    }

    //Filling
    stream& StreamItem = Stream[StreamNumber];
    StreamItem.LanguageID=LanguageID;
    StreamItem.AverageBitRate=DataBitrate;
    StreamItem.AverageTimePerFrame=AverageTimePerFrame;
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_AdvancedMutualExclusion()
{
    Element_Name("Advanced Mutual Exclusion");

    //Parsing
    int16u Count;
    Info_GUID(ExclusionType,                                    "Exclusion Type"); Param_Info1(Wm_ExclusionType(ExclusionType));
    Get_L2 (Count,                                              "Stream Numbers Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Info_L2(StreamNumber,                                   "Stream Number"); Element_Info1(StreamNumber);
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_GroupMutualExclusion()
{
    Element_Name("Group Mutual Exclusion");

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

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_StreamPrioritization()
{
    Element_Name("Stream Prioritization");

    //Parsing
    int16u Count;
    Get_L2 (Count,                                              "Stream Numbers Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        int16u Flags;
        Element_Begin1("Stream");
        Info_L2(StreamNumber,                                   "Stream Number"); Element_Info1(StreamNumber);
        Get_L2 (Flags,                                          "Flags");
            Skip_Flags(Flags, 0,                                "Mandatory");
        Element_End0();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_BandwidthSharing()
{
    Element_Name("Bandwidth Sharing");

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

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_LanguageList()
{
    Element_Name("Language List");

    //Parsing
    Ztring LanguageID;
    int16u Count;
    int8u  LanguageID_Length;
    Get_L2 (Count,                                              "Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Language ID");
        Get_L1 (LanguageID_Length,                              "Language ID Length");
        if (LanguageID_Length>0)
        {
            Get_UTF16L(LanguageID_Length, LanguageID,           "Language ID");
            Element_Info1(LanguageID);
        }
        Element_End0();

        //Filling
        Languages.push_back(LanguageID);
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_MetadataLibrary()
{
    Element_Name("Metadata Library");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_Metadata()
{
    Element_Name("Metadata");

    //Parsing
    float32 AspectRatioX=0, AspectRatioY=0;
    int16u Count;
    Get_L2 (Count,                                              "Description Records Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Description Record");
        Ztring Name, Data;
        int64u Data_Int64=0;
        int32u Data_Length;
        int16u StreamNumber, Name_Length, Data_Type;
        Skip_L2(                                                "Reserved");
        Get_L2 (StreamNumber,                                   "Stream Number");
        Get_L2 (Name_Length,                                    "Name Length");
        Get_L2 (Data_Type,                                      "Data Type");
        Get_L4 (Data_Length,                                    "Data Length");
        Get_UTF16L(Name_Length, Name,                           "Name Length");
        switch (Data_Type)
        {
            case 0x00 : Get_UTF16L(Data_Length, Data,           "Data"); break;
            case 0x01 : Skip_XX(Data_Length,                    "Data"); Data=__T("(Binary)"); break;
            case 0x02 : {int16u Data_Int; Get_L2 (Data_Int,     "Data"); Data=(Data_Int==0)?__T("No"):__T("Yes"); Data_Int64=Data_Int;} break;
            case 0x03 : {int32u Data_Int; Get_L4 (Data_Int,     "Data"); Data.From_Number(Data_Int); Data_Int64=Data_Int;} break;
            case 0x04 : {int64u Data_Int; Get_L8 (Data_Int,     "Data"); Data.From_Number(Data_Int); Data_Int64=Data_Int;} break;
            case 0x05 : {int16u Data_Int; Get_L2 (Data_Int,     "Data"); Data.From_Number(Data_Int); Data_Int64=Data_Int;} break;
            default   : Skip_XX(Data_Length,                    "Data"); Data=__T("(Unknown)"); break;
        }
        Element_Info1(Name);
        Element_Info1(Data);
        Element_End0();

        if (Name==__T("IsVBR"))
            Stream[StreamNumber].Info["BitRate_Mode"]=(Data_Int64==0)?"CBR":"VBR";
        else if (Name==__T("AspectRatioX"))
        {
            AspectRatioX=Data.To_float32();
            if (AspectRatioX && AspectRatioY)
                Stream[StreamNumber].Info["PixelAspectRatio"].From_Number(AspectRatioX/AspectRatioY, 3);
        }
        else if (Name==__T("AspectRatioY"))
        {
            AspectRatioY=Data.To_float32();
            if (AspectRatioX && AspectRatioY)
                Stream[StreamNumber].Info["PixelAspectRatio"].From_Number(AspectRatioX/AspectRatioY, 3);
        }
        else if (Name==__T("DeviceConformanceTemplate"))
        {
            if (Data!=__T("@") && Data.find(__T('@'))!=std::string::npos)
                Stream[StreamNumber].Info["Format_Profile"]=Data;
        }
        else if (Name==__T("WM/WMADRCPeakReference")) {}
        else if (Name==__T("WM/WMADRCAverageReference")) {}
        else if (Name==__T("WM/WMADRCAverageTarget")) {}
        else if (Name==__T("WM/WMADRCPeakTarget")) {}
        else
            Stream[StreamNumber].Info[Name.To_Local()]=Data;
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_IndexParameters()
{
    Element_Name("Index Parameters");

    //Parsing
    int16u Count;
    Skip_L4(                                                    "Index Entry Time Interval");
    Get_L2 (Count,                                              "Index Specifiers Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Index Specifier");
        int16u IndexType;
        Skip_L2(                                                "Stream Number");
        Get_L2 (IndexType,                                      "Index Type");
        Element_Info1(IndexType);
        Element_End0();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_MediaIndexParameters()
{
    Header_HeaderExtension_IndexParameters();

    Element_Name("MediaIndex Parameters");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_TimecodeIndexParameters()
{
    Header_HeaderExtension_IndexParameters();

    Element_Name("Timecode Index Parameters");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_Compatibility()
{
    Element_Name("Compatibility");

    //Parsing
    Skip_L1(                                                    "Profile");
    Skip_L1(                                                    "Mode");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_AdvancedContentEncryption()
{
    Element_Name("Advanced Content Encryption");
}

//---------------------------------------------------------------------------
void File_Wm::Header_HeaderExtension_IndexPlaceholder()
{
    Element_Name("Index Placeholder");
}

//---------------------------------------------------------------------------
void File_Wm::Header_CodecList()
{
    Element_Name("Codec List");

    //Parsing
    Ztring CodecName, CodecDescription;
    int32u Count32;
    int16u Count, Type, CodecNameLength, CodecDescriptionLength, CodecInformationLength;
    Skip_GUID(                                                  "Reserved");
    Get_L4 (Count32,                                            "Codec Entries Count");
    Count=(int16u)Count32;
    CodecInfos.resize(Count);
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Codec Entry");
        Get_L2 (Type,                                           "Type"); Param_Info1(Wm_CodecList_Kind(Type));
        Get_L2 (CodecNameLength,                                "Codec Name Length");
        Get_UTF16L(CodecNameLength*2, CodecName,                "Codec Name");
        Get_L2 (CodecDescriptionLength,                         "Codec Description Length");
        Get_UTF16L(CodecDescriptionLength*2, CodecDescription,  "Codec Description");
        Get_L2 (CodecInformationLength,                         "Codec Information Length");
        if (Type==2 && CodecInformationLength==2) //Audio and 2CC
            Skip_L2(                                            "2CC"); //Not used, we have it elsewhere
        else if (Type==1 && CodecInformationLength==4) //Video and 4CC
            Skip_C4(                                            "4CC"); //Not used, we have it elsewhere
        else
            Skip_XX(CodecInformationLength,                     "Codec Information");
        Element_End0();

        FILLING_BEGIN();
            CodecInfos[Pos].Type=Type;
            CodecInfos[Pos].Info=CodecName;
            if (!CodecDescription.empty())
            {
                CodecInfos[Pos].Info+=__T(" - ");
                CodecInfos[Pos].Info+=CodecDescription;
            }

            Codec_Description_Count++;
        FILLING_END();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_ScriptCommand()
{
    Element_Name("Script Command");

    //Parsing
    Skip_GUID(                                                  "Reserved");
    int16u Commands_Count, CommandTypes_Count;
    Get_L2 (Commands_Count,                                     "Commands Count");
    Get_L2 (CommandTypes_Count,                                 "Command Types Count");
    for (int16u Pos=0; Pos<CommandTypes_Count; Pos++)
    {
        Element_Begin1("Command Type");
        int16u Length;
        Get_L2 (Length,                                         "Command Type Length");
        if (Length>0)
            Skip_UTF16L(Length*2,                               "Command Type");
        Element_End0();
    }
    for (int16u Pos=0; Pos<Commands_Count; Pos++)
    {
        Element_Begin1("Command");
        int16u Length;
        Skip_L2(                                                "Type Index");
        Get_L2 (Length,                                         "Command Length");
        if (Length>0)
            Skip_UTF16L(Length*2,                               "Command");
        Element_End0();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_Marker()
{
    Element_Name("Markers");

    //Parsing
    Skip_GUID(                                                  "Reserved");
    int32u Markers_Count;
    int16u Name_Length;
    Get_L4 (Markers_Count,                                      "Markers Count");
    Skip_L2(                                                    "Reserved");
    Get_L2 (Name_Length,                                        "Name Length");
    if (Name_Length>0)
        Skip_UTF16L(Name_Length,                                "Name");

    //Filling
    if (Markers_Count>0)
        Stream_Prepare(Stream_Menu);

    //Parsing
    for (int32u Pos=0; Pos<Markers_Count; Pos++)
    {
        Element_Begin1("Marker");
        Ztring Marker;
        int32u Marker_Length;
        Skip_L8(                                                "Offset");
        Info_L8(PresentationTime,                               "Presentation Time"); Param_Info_From_Milliseconds(PresentationTime/10000);
        Skip_L2(                                                "Entry Length");
        Info_L4(SendTime,                                       "Send Time"); Param_Info_From_Milliseconds(SendTime);
        Skip_L4(                                                "Flags");
        Get_L4 (Marker_Length,                                  "Marker Description Length");
        if (Marker_Length>0)
            Get_UTF16L(Marker_Length*2, Marker,                 "Marker Description");
        Element_End0();
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_BitRateMutualExclusion()
{
    Element_Name("BitRate Mutual Exclusion");

    //Parsing
    int16u Count;
    Skip_GUID(                                                  "Exclusion Type");
    Get_L2 (Count,                                              "Stream Numbers Count");
    for (int16u Pos=0; Pos<Count; Pos++)
        Skip_L2(                                                "Stream Number");
}

//---------------------------------------------------------------------------
void File_Wm::Header_ErrorCorrection()
{
    Element_Name("Error Correction");
}

//---------------------------------------------------------------------------
void File_Wm::Header_ContentDescription()
{
    Element_Name("Content Description");

    //Parsing
    Ztring Title, Author, Copyright, Description, Rating;
    int16u TitleLength, AuthorLength, CopyrightLength, DescriptionLength, RatingLength;
    Get_L2 (TitleLength,                                        "TitleLength");
    Get_L2 (AuthorLength,                                       "AuthorLength");
    Get_L2 (CopyrightLength,                                    "CopyrightLength");
    Get_L2 (DescriptionLength,                                  "DescriptionLength");
    Get_L2 (RatingLength,                                       "RatingLength");
    if (TitleLength>0)
        Get_UTF16L(TitleLength, Title,                          "Title");
    if (AuthorLength>0)
        Get_UTF16L(AuthorLength, Author,                        "Author");
    if (CopyrightLength>0)
        Get_UTF16L(CopyrightLength, Copyright,                  "Copyright");
    if (DescriptionLength>0)
        Get_UTF16L(DescriptionLength, Description,              "Description");
    if (RatingLength>0)
        Get_UTF16L(RatingLength, Rating,                        "Rating");

    //Filling
    Fill(Stream_General, 0, General_Title, Title);
    Fill(Stream_General, 0, General_Performer, Author);
    Fill(Stream_General, 0, General_Copyright, Copyright);
    Fill(Stream_General, 0, General_Comment, Description);
    Fill(Stream_General, 0, General_Rating, Rating);
}

//---------------------------------------------------------------------------
void File_Wm::Header_ExtendedContentDescription()
{
    Element_Name("Extended Content Description");

    //Parsing
    int16u Count;
    Get_L2 (Count,                                              "Content Descriptors Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Content Descriptor");
        Ztring Name, Value;
        int64u Value_Int64=0;
        int16u Name_Length, Value_Type, Value_Length;
        Get_L2 (Name_Length,                                    "Name Length");
        Get_UTF16L(Name_Length, Name,                           "Name");
        Get_L2 (Value_Type,                                     "Value Data Type");
        Get_L2 (Value_Length,                                   "Value Length");
        switch (Value_Type)
        {
            case 0x00 : Get_UTF16L(Value_Length, Value,         "Value"); break;
            case 0x01 :
                        if (Name==__T("ASFLeakyBucketPairs")) Header_ExtendedContentDescription_ASFLeakyBucketPairs(Value_Length);
                        else if (Name==__T("WM/Picture")) {
                            Ztring Mime, Description;
                            int32u Data_Size;
                            int8u PictureType;
                            Get_L1 (PictureType,                                    "Picture Ttype"); Element_Info1(Id3v2_PictureType(PictureType));
                            Get_L4 (Data_Size,                                      "Data size");
                            if (Value_Length<5 || Data_Size>Value_Length-5U)
                                return; //There is a problem
                            int64u End = Element_Offset;
                            while (End + 1 < Element_Size && *(int16u*)(Buffer + Buffer_Offset + End)) {
                                End += 2;
                            }
                            Get_UTF16L (End-Element_Offset, Mime,                   "Mime Type");
                            Skip_L2(                                                "Zero");
                            End = Element_Offset;
                            while (End + 1 < Element_Size && *(int16u*)(Buffer + Buffer_Offset + End)) {
                                End += 2;
                            }
                            Get_UTF16L (End-Element_Offset, Description,            "Description");
                            Skip_L2(                                                "Zero");
                            auto Element_Size_Save = Element_Size;
                            Element_Size = Element_Offset + Data_Size;
                            Attachment("WM/Picture", Description, Id3v2_PictureType(PictureType).c_str(), Mime, true);
                            Element_Size = Element_Size_Save;
                        }
                        else {Skip_XX(Value_Length,             "Value"); Value=__T("(Binary)");} break;
            case 0x02 : {int32u Value_Int; Get_L4 (Value_Int,   "Value"); Value=(Value_Int==0)?__T("No"):__T("Yes"); Value_Int64=Value_Int;} break;
            case 0x03 : {int32u Value_Int; Get_L4 (Value_Int,   "Value"); Value.From_Number(Value_Int); Value_Int64=Value_Int;} break;
            case 0x04 : {int64u Value_Int; Get_L8 (Value_Int,   "Value"); Value.From_Number(Value_Int); Value_Int64=Value_Int;} break;
            case 0x05 : {int16u Value_Int; Get_L2 (Value_Int,   "Value"); Value.From_Number(Value_Int); Value_Int64=Value_Int;} break;
            default   : Skip_XX(Value_Length,                   "Value"); Value=__T("(Unknown)"); break;
        }
        Element_Info1(Name);
        Element_Info1(Value);
        Element_End0();

        //Filling
        if (!Value.empty())
        {
                 if (Name==__T("Agility FPS")) {}
            else if (Name==__T("ASFLeakyBucketPairs")) {} //Already done elsewhere
            else if (Name==__T("AspectRatioX")) Header_ExtendedContentDescription_AspectRatioX=Value_Int64;
            else if (Name==__T("AspectRatioY")) Header_ExtendedContentDescription_AspectRatioY=Value_Int64;
            else if (Name==__T("Buffer Average")) {}
            else if (Name==__T("DVR Index Granularity")) {}
            else if (Name==__T("DVR File Version")) {}
            else if (Name==__T("IsVBR"))
                Fill(Stream_General, 0, General_OverallBitRate_Mode, Value_Int64==0?"CBR":"VBR");
            else if (Name==__T("VBR Peak")) {} //Already in "Stream Bitrate" chunk
            else if (Name==__T("WMFSDKVersion")) {}
            else if (Name==__T("WMFSDKNeeded")) {}
            else if (Name==__T("WM/AlbumTitle"))
                Fill(Stream_General, 0, General_Album, Value);
            else if (Name==__T("WM/AlbumArtist"))
            {
                const Ztring& Previous=Retrieve(Stream_General, 0, General_Performer);
                if (!Previous.empty() && Previous != Value)
                    Fill(Stream_General, 0, General_Accompaniment, Previous); // Microsoft "Contributing artists"
                Fill(Stream_General, 0, General_Performer, Value, true);
            }
            else if (Name==__T("WM/ArtistSortOrder"))
                Fill(Stream_General, 0, General_Performer_Sort, Value);
            else if (Name==__T("WM/AuthorURL"))
                Fill(Stream_General, 0, "Author/Url", Value);
            else if (Name==__T("WM/BeatsPerMinute"))
                Fill(Stream_General, 0, General_BPM, Value);
            else if (Name==__T("WM/Binary"))
                Fill(Stream_General, 0, General_Cover, "Y");
            else if (Name==__T("WM/Comments"))
                Fill(Stream_General, 0, General_Comment, Value, true); //Clear last value
            else if (Name==__T("WM/Composer"))
                Fill(Stream_General, 0, General_Composer, Value);
            else if (Name==__T("WM/Conductor"))
                Fill(Stream_General, 0, General_Conductor, Value);
            else if (Name==__T("WM/EncodedBy"))
                Fill(Stream_General, 0, General_EncodedBy, Value);
            else if (Name==__T("WM/EncoderSettings"))
                Fill(Stream_General, 0, General_Encoded_Library_Settings, Value);
            else if (Name==__T("WM/EncodingTime"))
            {
                 Ztring Encoded_Date_New=Ztring().Date_From_Seconds_1601(Value_Int64/10000000);
                 const Ztring& Encoded_Date_Old=Retrieve_Const(Stream_General, 0, General_Encoded_Date);
                 if (Encoded_Date_Old.empty() || Encoded_Date_New!=Encoded_Date_Old)
                    Fill(Stream_General, 0, General_Encoded_Date, Encoded_Date_New);
            }
            else if (Name==__T("WM/Genre"))
                Fill(Stream_General, 0, General_Genre, Value, true); //Clear last value
            else if (Name==__T("WM/GenreID"))
            {
                if (Retrieve(Stream_General, 0, General_Genre).empty())
                    Fill(Stream_General, 0, General_Genre, Value);
            }
            else if (Name==__T("WM/Language"))
                Language_ForAll=Value;
            else if (Name==__T("WM/MediaCredits"))
                Fill(Stream_General, 0, General_ThanksTo, Value);
            else if (Name==__T("WM/MediaPrimaryClassID")) {}
            else if (Name==__T("WM/MCDI")) {}
            else if (Name==__T("WM/ModifiedBy"))
                Fill(Stream_General, 0, General_RemixedBy, Value);
            else if (Name==__T("WM/OriginalAlbumTitle"))
                Fill(Stream_General, 0, "Original/Album", Value);
            else if (Name==__T("WM/OriginalReleaseTime"))
            {
                 if (Value.size()<10 || Value.rfind(__T("0001-01-01"), 0)==string::npos)
                     Fill(Stream_General, 0, "Original/Released_Date", Value);
            }
            else if (Name==__T("WM/ParentalRating"))
                Fill(Stream_General, 0, General_LawRating, Value);
            else if (Name==__T("WM/ParentalRatingReason"))
                Fill(Stream_General, 0, General_LawRating_Reason, Value);
            else if (Name==__T("WM/Provider"))
                Fill(Stream_General, 0, "Provider", Value);
            else if (Name==__T("WM/Publisher"))
                Fill(Stream_General, 0, General_Publisher, Value);
            else if (Name==__T("WM/RadioStationName"))
                Fill(Stream_General, 0, General_ServiceName, Value);
            else if (Name==__T("WM/RadioStationOwner"))
                Fill(Stream_General, 0, General_ServiceProvider, Value);
            else if (Name==__T("WM/SubTitle"))
                Fill(Stream_General, 0, General_Title_More, Value);
            else if (Name==__T("WM/SubTitleDescription"))
                Fill(Stream_General, 0, General_Title_More, Value);
            else if (Name==__T("WM/ToolName"))
                Fill(Stream_General, 0, General_Encoded_Application, Value);
            else if (Name==__T("WM/ToolVersion"))
                Fill(Stream_General, 0, General_Encoded_Application, Retrieve(Stream_General, 0, General_Encoded_Application)+__T(" ")+Value, true);
            else if (Name==__T("WM/TrackNumber"))
                Fill(Stream_General, 0, General_Track_Position, Value, true); //Clear last value, like WM/Track
            else if (Name==__T("WM/Track"))
            {
                if (Retrieve(Stream_General, 0, General_Track_Position).empty())
                    Fill(Stream_General, 0, General_Track_Position, Value.To_int32u()+1);
            }
            else if (Name==__T("WM/UniqueFileIdentifier"))
            {
                if (Value.empty() || Value[0]!=__T(';')) //Test if there is only the separator
                {
                    Value.FindAndReplace(__T(";"), MediaInfoLib::Config.TagSeparator_Get());
                    Fill(Stream_General, 0, General_UniqueID, Value);
                }
            }
            else if (Name==__T("WM/Writer"))
                Fill(Stream_General, 0, General_WrittenBy, Value);
            else if (Name==__T("WM/Year"))
                Fill(Stream_General, 0, General_Recorded_Date, Value);
            else
                Fill(Stream_General, 0, Name.To_Local().c_str(), Value);
        }
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_ExtendedContentDescription_ASFLeakyBucketPairs(int16u Value_Length)
{
    Element_Begin1("ASFLeakyBucketPairs");
    Skip_L2(                                                    "Reserved");
    for (int16u Pos=2; Pos<Value_Length; Pos+=8)
    {
        Element_Begin1("Bucket");
        Skip_L4(                                                "BitRate");
        Skip_L4(                                                "msBufferWindow");
        Element_End0();
    }
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Wm::Header_StreamBitRate()
{
    Element_Name("Stream Bitrate");

    //Parsing
    int16u Count;
    Get_L2 (Count,                                              "Count");
    for (int16u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Stream");
        int32u AverageBitRate;
        int16u StreamNumber;
        Get_L2 (StreamNumber,                                   "Stream Number"); Element_Info1(StreamNumber);
        Get_L4 (AverageBitRate,                                 "Average Bitrate"); Element_Info1(AverageBitRate);
        Element_End0();

        //Filling
        stream& StreamItem = Stream[StreamNumber];
        if (StreamItem.AverageBitRate==0) //Prefere Average bitrate of Extended Stream Properties if present
            StreamItem.AverageBitRate=AverageBitRate;
    }
}

//---------------------------------------------------------------------------
void File_Wm::Header_ContentBranding()
{
    Element_Name("Content Branding");

    //Parsing
    Ztring CopyrightURL, BannerImageURL;
    int32u BannerImageData_Type, BannerImageData_Length, BannerImageURL_Length, CopyrightURL_Length;
    Get_L4 (BannerImageData_Type,                               "Banner Image Data Type"); Param_Info1(Wm_BannerImageData_Type(BannerImageData_Type));
    Get_L4 (BannerImageData_Length,                             "Banner Image Data Length");
    if (BannerImageData_Length>0)
        Skip_XX(BannerImageData_Length,                         "Banner Image Data");
    Get_L4 (BannerImageURL_Length,                              "Banner Image URL Length");
    if (BannerImageURL_Length>0)
    Get_Local(BannerImageURL_Length, BannerImageURL,            "Banner Image URL");
        Get_L4 (CopyrightURL_Length,                            "Copyright URL Length");
    if (CopyrightURL_Length>0)
        Get_Local(CopyrightURL_Length, CopyrightURL,            "Copyright URL");
}

//---------------------------------------------------------------------------
void File_Wm::Header_ContentEncryption()
{
    Element_Name("Content Encryption");

    //Parsing
    Ztring LicenseURL;
    int32u SecretDataLength, ProtectionTypeLength, KeyIDLength, LicenseURLLength;
    Get_L4 (SecretDataLength,                                   "Secret Data Length");
    Skip_XX(SecretDataLength,                                   "Secret Data");
    Get_L4 (ProtectionTypeLength,                               "Protection Type Length");
    Skip_Local(ProtectionTypeLength,                            "Protection Type");
    Get_L4 (KeyIDLength,                                        "Key ID Length");
    Skip_Local(KeyIDLength,                                     "Key ID Type");
    Get_L4 (LicenseURLLength,                                   "License URL Length");
    Get_Local(LicenseURLLength, LicenseURL,                     "License URL");

    //Filling
    Fill(Stream_General, 0, "Encryption", LicenseURL);
}

//---------------------------------------------------------------------------
void File_Wm::Header_ExtendedContentEncryption()
{
    Element_Name("Extended Content Encryption");

    //Parsing
    int32u DataLength;
    Get_L4 (DataLength,                                         "Data Length");
    Skip_XX(DataLength,                                         "Data");
}

//---------------------------------------------------------------------------
void File_Wm::Header_DigitalSignature()
{
    Element_Name("Digital Signature");

    //Parsing
    int32u DataLength;
    Skip_L4(                                                    "Signature Type");
    Get_L4 (DataLength,                                         "Signature Data Length");
    Skip_XX(DataLength,                                         "Signature Data");
}

//---------------------------------------------------------------------------
void File_Wm::Header_Padding()
{
    Element_Name("Padding");

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

//---------------------------------------------------------------------------
void File_Wm::Data()
{
    Element_Name("Data");

    //Parsing
    Skip_GUID(                                                  "File ID");
    Skip_L8(                                                    "Total Data Packets");
    Skip_L1(                                                    "Alignment");
    Skip_L1(                                                    "Packet Alignment");

    //Filling
    Fill(Stream_General, 0, General_HeaderSize, File_Offset+Buffer_Offset-24);
    Fill(Stream_General, 0, General_DataSize, Element_TotalSize_Get()+24);

    //For each stream
    Streams_Count=0;
    std::map<int16u, stream>::iterator Temp=Stream.begin();
    while (Temp!=Stream.end())
    {
        #if defined(MEDIAINFO_MPEGA_YES)
        if (IsDvrMs && !Temp->second.Parser && Temp->second.AverageBitRate>=32768)
        {
            Temp->second.Parser=new File_Mpega; //No stream properties, trying to detect it in datas...
            ((File_Mpega*)Temp->second.Parser)->Frame_Count_Valid=8;
            Open_Buffer_Init(Temp->second.Parser);
        }
        #endif
        if (Temp->second.Parser || Temp->second.StreamKind==Stream_Video) //We need Stream_Video for Frame_Rate computing
        {
            Temp->second.SearchingPayload=true;
            Streams_Count++;
        }
        ++Temp;
    }

    //Enabling the alternative parser
    MustUseAlternativeParser=true;
    Data_AfterTheDataChunk=File_Offset+Buffer_Offset+Element_TotalSize_Get();
}

//---------------------------------------------------------------------------
void File_Wm::Data_Packet()
{
    //Counting
    Packet_Count++;
    Element_Info1(Packet_Count);
    size_t Element_Show_Count=0;

    //Parsing
    int32u PacketLength=0, SizeOfMediaObject=0;
    int8u  Flags, ErrorCorrectionData_Length, ErrorCorrectionLengthType, SequenceType, PaddingLengthType, PacketLengthType;
    bool   ErrorCorrectionPresent;
    Element_Begin1("Error Correction");
        Get_L1 (Flags,                                          "Flags");
            Get_FlagsM(Flags&0x0F, ErrorCorrectionData_Length,  "Error Correction Data Length"); //4 lowest bits
            Skip_Flags(Flags, 4,                                "Opaque Data Present");
            Get_FlagsM((Flags>>5)&0x03, ErrorCorrectionLengthType, "Error Correction Length Type"); //bits 6 and 7
            Get_Flags (Flags, 7, ErrorCorrectionPresent,        "Error Correction Present");
        if (ErrorCorrectionPresent && ErrorCorrectionLengthType==0 && ErrorCorrectionData_Length==2)
        {
            int8u  TypeNumber;
            Get_L1 (TypeNumber,                                 "Type/Number");
                Skip_FlagsM((TypeNumber>>4)&0x0F, "Type");
                Skip_FlagsM( TypeNumber    &0x0F, "Number");
            Skip_L1(                                            "Cycle");
        }
    Element_End0();

    Element_Begin1("Payload Parsing Information");
        Get_L1 (Flags,                                          "Length Type Flags");
            Get_Flags (Flags, 0, MultiplePayloadsPresent,       "Multiple Payloads Present");
            Get_FlagsM((Flags>>1)&0x3, SequenceType,            "Sequence Type");
            Get_FlagsM((Flags>>3)&0x3, PaddingLengthType,       "Padding Length Type");
            Get_FlagsM((Flags>>5)&0x3, PacketLengthType,        "Packet Length Type");
            Skip_Flags(Flags, 7,                                "Error Correction Present");
        Get_L1 (Flags,                                          "Property Flags");
            Get_FlagsM( Flags    &0x3, ReplicatedDataLengthType, "Replicated Data Length Type");
            Get_FlagsM((Flags>>2)&0x3, OffsetIntoMediaObjectLengthType, "Offset Into Media Object Length Type");
            Get_FlagsM((Flags>>4)&0x3, MediaObjectNumberLengthType, "Media Object Number Length Type");
            Get_FlagsM((Flags>>6)&0x3, StreamNumberLengthType,  "Stream Number Length Type");
        switch (PacketLengthType)
        {
            case 1 : {int8u  Data; Get_L1(Data,                 "Packet Length"); PacketLength=Data;} break;
            case 2 : {int16u Data; Get_L2(Data,                 "Packet Length"); PacketLength=Data;} break;
            case 3 :               Get_L4(PacketLength,         "Packet Length");                     break;
            default: ;
        }
        switch (SequenceType)
        {
            case 1 : Skip_L1(                                   "Sequence"); break;
            case 2 : Skip_L2(                                   "Sequence"); break;
            case 3 : Skip_L4(                                   "Sequence"); break;
            default: ;
        }
        switch (PaddingLengthType)
        {
            case 1 : {int8u  Data; Get_L1(Data,                 "Padding Length"); Data_Parse_Padding=Data;} break;
            case 2 : {int16u Data; Get_L2(Data,                 "Padding Length"); Data_Parse_Padding=Data;} break;
            case 3 :               Get_L4(Data_Parse_Padding,   "Padding Length");                           break;
            default: Data_Parse_Padding=0;
        }
        Skip_L4(                                                "Send Time");
        Skip_L2(                                                "Duration");
    Element_End0();

    if (MultiplePayloadsPresent)
    {
        //Parsing
        Element_Begin1("Multiple Payloads additional flags");
            int8u AdditionalFlags;
            Get_L1 (AdditionalFlags,                                     "Flags");
                Get_FlagsM( AdditionalFlags    &0x3F, NumberPayloads,    "Number of Payloads"); //6 bits
                Get_FlagsM((AdditionalFlags>>6)&0x03, PayloadLengthType, "Payload Length Type"); //bits 6 and 7
        Element_End0();
    }
    else
    {
        SizeOfMediaObject=(int32u)(Element_Size-Element_Offset-Data_Parse_Padding);
        NumberPayloads=1;
    }

    for (NumberPayloads_Pos=0; NumberPayloads_Pos<NumberPayloads; NumberPayloads_Pos++)
    {
        Element_Begin1("Payload");
        int32u ReplicatedDataLength=0, PayloadLength=0;
        int8u  StreamNumber;
        Get_L1 (StreamNumber,                                   "Stream Number");
        Stream_Number=StreamNumber&0x7F; //For KeyFrame
        Element_Info1(Stream_Number);
        switch (MediaObjectNumberLengthType)
        {
            case 1 : Skip_L1(                                   "Media Object Number"); break;
            case 2 : Skip_L2(                                   "Media Object Number"); break;
            case 3 : Skip_L4(                                   "Media Object Number"); break;
            default: Trusted_IsNot("Media Object Number"); return; //Problem
        }
        switch (OffsetIntoMediaObjectLengthType)
        {
            case 1 : Skip_L1(                                   "Offset Into Media Object"); break;
            case 2 : Skip_L2(                                   "Offset Into Media Object"); break;
            case 3 : Skip_L4(                                   "Offset Into Media Object"); break;
            default: Trusted_IsNot("Offset Into Media Object"); return; //Problem
        }
        switch (ReplicatedDataLengthType)
        {
            case 1 : {int8u  Data; Get_L1(Data,                 "Replicated Data Length"); ReplicatedDataLength=Data;} break;
            case 2 : {int16u Data; Get_L2(Data,                 "Replicated Data Length"); ReplicatedDataLength=Data;} break;
            case 3 :               Get_L4(ReplicatedDataLength, "Replicated Data Length");                             break;
            default: Trusted_IsNot("Replicated Data Length"); return; //Problem
        }
        if (ReplicatedDataLengthType!=0 && ReplicatedDataLength>0)
        {
            if (ReplicatedDataLength>=8)
            {
                int32u PresentationTime;
                Get_L4 (SizeOfMediaObject,                      "Size Of Media Object");
                Get_L4 (PresentationTime,                       "Presentation Time");
                if (ReplicatedDataLength>8)
                    Data_Packet_ReplicatedData(ReplicatedDataLength-8);

                //Presentation time delta
                std::map<int16u, stream>::iterator Strea=Stream.find(Stream_Number);
                if (Strea!=Stream.end() && Strea->second.StreamKind==Stream_Video)
                {
                    Strea->second.PresentationTimes.insert(PresentationTime);
                }
            }
            else if (ReplicatedDataLength==1)
            {
                Skip_L1(                                        "Presentation Time Delta");
                //TODO
            }
            else
            {
                Skip_XX(ReplicatedDataLength,                   "Replicated Data");
            }
        }

        if (MultiplePayloadsPresent)
        {
            switch (PayloadLengthType)
            {
                case 1 : {int8u  Data; Get_L1(Data,             "Payload Length"); PayloadLength=Data;} break;
                case 2 : {int16u Data; Get_L2(Data,             "Payload Length"); PayloadLength=Data;} break;
                case 3 :               Get_L4(PayloadLength,    "Payload Length");                      break;
                default: Trusted_IsNot("Payload Length"); return; //Problem
            }
        }
        else if (Element_Size-Element_Offset>Data_Parse_Padding)
            PayloadLength=(int32u)(Element_Size-(Element_Offset+Data_Parse_Padding));
        else
        {
            Trusted_IsNot("Padding size problem");
        }
        if (Element_Offset+PayloadLength+Data_Parse_Padding>Element_Size)
        {
            Trusted_IsNot("Payload Length problem");
        }
        else
        {
            //Demux
            Element_Code=Stream_Number;
            Demux(Buffer+(size_t)Element_Offset, (size_t)PayloadLength, ContentType_MainStream);

            //Analyzing
            stream& StreamItem = Stream[Stream_Number];
            if (StreamItem.Parser && StreamItem.SearchingPayload)
            {
                //Handling of spanned on multiple chunks
                #if defined(MEDIAINFO_VC1_YES)
                    bool FrameIsAlwaysComplete=true;
                #endif
                if (PayloadLength!=SizeOfMediaObject)
                {
                    if (SizeOfMediaObject_BytesAlreadyParsed==0)
                        SizeOfMediaObject_BytesAlreadyParsed=SizeOfMediaObject-PayloadLength;
                    else
                        SizeOfMediaObject_BytesAlreadyParsed-=PayloadLength;
                    if (SizeOfMediaObject_BytesAlreadyParsed==0)
                        Element_Show_Count++;
                    #if defined(MEDIAINFO_VC1_YES)
                    else
                        FrameIsAlwaysComplete=false;
                    #endif
                }
                else
                    Element_Show_Count++;

                //Codec specific
                #if defined(MEDIAINFO_VC1_YES)
                if (Retrieve(StreamItem.StreamKind, StreamItem.StreamPos, Fill_Parameter(StreamItem.StreamKind, Generic_Format))==__T("VC-1"))
                    ((File_Vc1*)StreamItem.Parser)->FrameIsAlwaysComplete=FrameIsAlwaysComplete;
                #endif

                Open_Buffer_Continue(StreamItem.Parser, (size_t)PayloadLength);
                if (StreamItem.Parser->Status[IsFinished]
                 || (StreamItem.PresentationTimes.size()>=300 && Config->ParseSpeed<1.0))
                {
                    StreamItem.Parser->Open_Buffer_Unsynch();
                    StreamItem.SearchingPayload=false;
                    Streams_Count--;
                }

                Element_Show();
            }
            else
            {
                Skip_XX(PayloadLength,                              "Data");
                if (StreamItem.SearchingPayload
                 && (StreamItem.StreamKind==Stream_Video && StreamItem.PresentationTimes.size()>=300))
                {
                    StreamItem.SearchingPayload=false;
                    Streams_Count--;
                }
            }
        }
        Element_End0();
    }

    if (Data_Parse_Padding)
        Skip_XX(Data_Parse_Padding,                             "Padding");

    //Jumping if needed
    if (Streams_Count==0 || (Packet_Count>=1000 && Config->ParseSpeed<1.0))
    {
        Info("Data, Jumping to end of chunk");
        GoTo(Data_AfterTheDataChunk, "Windows Media");
    }

    if (Element_Show_Count>0)
        Element_Show();
}

//---------------------------------------------------------------------------
void File_Wm::Data_Packet_ReplicatedData(int32u Size)
{
    Element_Begin1("Replicated Data");
    int64u Element_Offset_Final=Element_Offset+Size;
    stream& StreamItem = Stream[Stream_Number];
    for (size_t Pos=0; Pos<StreamItem.Payload_Extension_Systems.size(); Pos++)
    {
        Element_Begin0();
        switch (StreamItem.Payload_Extension_Systems[Pos].ID.hi)
        {
            case Elements::Payload_Extension_System_TimeStamp :     Data_Packet_ReplicatedData_TimeStamp(); break;
            default :                                               //Not enough info to validate this algorithm
                                                                    //if (StreamItem.Payload_Extension_Systems[Pos].Size!=(int16u)-1)
                                                                    //{
                                                                    //    Element_Name("Unknown");
                                                                    //    Skip_XX(StreamItem.Payload_Extension_Systems[Pos].Size, "Unknown");
                                                                    //}
                                                                    //else
                                                                        Pos=StreamItem.Payload_Extension_Systems.size(); //Disabling the rest, all is unknown
        }
        Element_End0();
    }

    if (Element_Offset<Element_Offset_Final)
    {
        Element_Begin1("Other chunks");
        Skip_XX(Element_Offset_Final-Element_Offset, "Unknown");
        Element_End0();
    }
    Element_End0();
}

//---------------------------------------------------------------------------
void File_Wm::Data_Packet_ReplicatedData_TimeStamp()
{
    Element_Name("TimeStamp");

    //Parsing
    int64u TS0;
    Skip_L2(                                                    "Unknown");
    Skip_L4(                                                    "Unknown");
    Skip_L4(                                                    "Unknown");
    Get_L8 (TS0,                                                "TS0");
    #if MEDIAINFO_TRACE
        if (TS0!=(int64u)-1) Param_Info1(TS0/10000);
    #endif //MEDIAINFO_TRACE
    Info_L8(TS1,                                                "TS1");
    #if MEDIAINFO_TRACE
        if (TS1!=(int64u)-1) Param_Info1(TS1/10000);
    #endif //MEDIAINFO_TRACE
    Skip_L4(                                                    "Unknown");
    Skip_L4(                                                    "Unknown");
    Skip_L4(                                                    "Unknown");
    Skip_L4(                                                    "Unknown");
    stream& StreamItem = Stream[Stream_Number];
    if (StreamItem.TimeCode_First==(int64u)-1 && TS0!=(int64u)-1)
        StreamItem.TimeCode_First=TS0/10000;
}

//---------------------------------------------------------------------------
void File_Wm::SimpleIndex()
{
    Element_Name("Simple Index");

    //Parsing
    /*
    int32u Count;
    Skip_GUID(                                                  "File ID");
    Skip_L8(                                                    "Index Entry Time Interval");
    Skip_L4(                                                    "Maximum Packet Count");
    Get_L4 (Count,                                              "Index Entries Count");
    for (int32u Pos=0; Pos<Count; Pos++)
    {
        Element_Begin1("Index Entry", 6);
        int32u PacketNumber;
        int16u PacketCount;
        Get_L4 (PacketNumber,                                   "Packet Number");
        Get_L2 (PacketCount,                                    "Packet Count");
        Element_End0();
    }
    */
    Skip_XX(Element_TotalSize_Get()-Element_Offset,             "Indexes");
}

//---------------------------------------------------------------------------
void File_Wm::Index()
{
    Element_Name("Index");

    //Parsing
    /*
    int32u Blocks_Count;
    int16u Specifiers_Count;
    Skip_L4(                                                    "Index Entry Time Interval");
    Get_L2 (Specifiers_Count,                                   "Index Specifiers Count");
    Get_L4 (Blocks_Count,                                       "Index Blocks Count");
    for (int16u Pos=0; Pos<Specifiers_Count; Pos++)
    {
        Element_Begin1("Specifier");
            Skip_L2(                                            "Stream Number");
            Skip_L2(                                            "Index Type");
        Element_End0();
    }
    for (int32u Pos=0; Pos<Blocks_Count; Pos++)
    {
        Element_Begin1("Block");
        int32u Entry_Count;
        Get_L4 (Entry_Count,                                    "Index Entry Count");
        Element_Begin1("Block Positions");
            for (int16u Pos=0; Pos<Specifiers_Count; Pos++)
                Skip_L4(                                        "Position");
        Element_End0();
        for (int32u Pos=0; Pos<Entry_Count; Pos++)
        {
            Element_Begin1("Entry");
            for (int16u Pos=0; Pos<Specifiers_Count; Pos++)
                Skip_L4(                                        "Offset");
            Element_End0();
        }
        Element_End0();
    }
    */
    Skip_XX(Element_TotalSize_Get()-Element_Offset,             "Indexes");
}

//---------------------------------------------------------------------------
void File_Wm::MediaIndex()
{
    Element_Name("MediaIndex");
}

//---------------------------------------------------------------------------
void File_Wm::TimecodeIndex()
{
    Element_Name("Timecode Index");

    //Parsing
    int32u TimeCode_First=(int32u)-1;
    int32u IndexBlocksCount;
    int16u IndexSpecifiersCount;
    Skip_L4(                                                    "Reserved");
    Get_L2 (IndexSpecifiersCount,                               "Index Specifiers Count");
    Get_L4 (IndexBlocksCount,                                   "Index Blocks Count");
    Element_Begin1("Index Specifiers");
        for (int16u Pos=0; Pos<IndexSpecifiersCount; ++Pos)
        {
            Element_Begin1("Index Specifier");
            Skip_L2(                                                "Stream Number");
            Info_L2(IndexType,                                      "Index Type");
            Element_Info1(IndexType);
            Element_End0();
        }
    Element_End0();
    Element_Begin1("Index Blocks");
        for (int16u Pos=0; Pos<IndexBlocksCount; ++Pos)
        {
            Element_Begin1("Index Block");
            int32u IndexEntryCount;
            Get_L4 (IndexEntryCount,                                "Index Entry Count");
            Skip_L2(                                                "Timecode Range");
            Element_Begin1("Block Positions");
                for (int16u Pos=0; Pos<IndexSpecifiersCount; ++Pos)
                    Skip_L8(                                        "Block Position");
            Element_End0();
            Element_Begin1("Index Entries");
                for (int32u Pos=0; Pos<IndexEntryCount; ++Pos)
                {
                    Element_Begin1("Index Entry");
                    if (TimeCode_First==(int32u)-1)
                        Get_L4 (TimeCode_First,                     "Timecode");
                    else
                        Skip_L4(                                    "Timecode");
                    for (int16u Pos=0; Pos<IndexSpecifiersCount; ++Pos)
                        Skip_L4(                                    "Offsets");
                    Element_End0();
                }
            Element_End0();
            Element_End0();
        }
    Element_End0();

    FILLING_BEGIN();
        Stream_Prepare(Stream_Other);
        Fill(Stream_Other, StreamPos_Last, Other_Type, "Time code");
        Fill(Stream_Other, StreamPos_Last, Other_Format, "WM TC");
        if (TimeCode_First!=(int32u)-1)
        {
            int8u H1= TimeCode_First>>28;
            int8u H2=(TimeCode_First>>24)&0xF;
            int8u M1=(TimeCode_First>>20)&0xF;
            int8u M2=(TimeCode_First>>16)&0xF;
            int8u S1=(TimeCode_First>>12)&0xF;
            int8u S2=(TimeCode_First>> 8)&0xF;
            int8u F1=(TimeCode_First>> 4)&0xF;
            int8u F2= TimeCode_First     &0xF;
            if (H1<10 && H2<10 && M1<10 && M2<10 && S1<10 && S2<10 && F1<10 && F2<10)
            {
                string TC;
                TC+='0'+H1;
                TC+='0'+H2;
                TC+=':';
                TC+='0'+M1;
                TC+='0'+M2;
                TC+=':';
                TC+='0'+S1;
                TC+='0'+S2;
                TC+=':';
                TC+='0'+F1;
                TC+='0'+F2;
                Fill(Stream_Other, StreamPos_Last, Other_TimeCode_FirstFrame, TC.c_str());
            }
        }
    FILLING_END();
}

//***************************************************************************
// C++
//***************************************************************************

} //NameSpace

#endif //MEDIAINFO_WM_YES
