/* 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
#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
//***************************************************************************
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 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_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 {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"))
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/Picture"))
Fill(Stream_General, 0, General_Cover, "Y");
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
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 1487, 1476.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 1494, 1476.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 1501, 1476.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 1538, 1476.
↑ V524 It is odd that the body of 'Header_HeaderExtension_BandwidthSharing' function is fully equivalent to the body of 'Header_HeaderExtension_GroupMutualExclusion' function.
↑ V524 It is odd that the body of 'Header_HeaderExtension_TimecodeIndexParameters' function is fully equivalent to the body of 'Header_HeaderExtension_MediaIndexParameters' function.
↑ V524 It is odd that the body of 'Index' function is fully equivalent to the body of 'SimpleIndex' function.
↑ V525 The code contains the collection of similar blocks. Check items '4', '2', '4' in lines 426, 427, 428.
↑ V525 The code contains the collection of similar blocks. Check items '2', '4', '4' in lines 1666, 1667, 1668.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'Temp->second' expression repeatedly.