Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can
* be found in the License.html file in the root of the source tree.
*/
//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_MK_YES)
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Mk.h"
#if defined(MEDIAINFO_OGG_YES)
#include "MediaInfo/Multiple/File_Ogg.h"
#endif
#if defined(MEDIAINFO_RM_YES)
#include "MediaInfo/Multiple/File_Rm.h"
#endif
#if defined(MEDIAINFO_MPEG4V_YES)
#include "MediaInfo/Video/File_Mpeg4v.h"
#endif
#if defined(MEDIAINFO_AV1_YES)
#include "MediaInfo/Video/File_Av1.h"
#endif
#if defined(MEDIAINFO_AVC_YES)
#include "MediaInfo/Video/File_Avc.h"
#endif
#if defined(MEDIAINFO_DVDIF_YES)
#include "MediaInfo/Multiple/File_DvDif.h"
#endif
#if defined(MEDIAINFO_HEVC_YES)
#include "MediaInfo/Video/File_Hevc.h"
#endif
#if defined(MEDIAINFO_FFV1_YES)
#include "MediaInfo/Video/File_Ffv1.h"
#endif
#if defined(MEDIAINFO_HUFFYUV_YES)
#include "MediaInfo/Video/File_HuffYuv.h"
#endif
#if defined(MEDIAINFO_VC1_YES)
#include "MediaInfo/Video/File_Vc1.h"
#endif
#if defined(MEDIAINFO_DIRAC_YES)
#include "MediaInfo/Video/File_Dirac.h"
#endif
#if defined(MEDIAINFO_MPEGV_YES)
#include "MediaInfo/Video/File_Mpegv.h"
#endif
#if defined(MEDIAINFO_PRORES_YES)
#include "MediaInfo/Video/File_ProRes.h"
#endif
#if defined(MEDIAINFO_VP8_YES)
#include "MediaInfo/Video/File_Vp8.h"
#endif
#if defined(MEDIAINFO_AAC_YES)
#include "MediaInfo/Audio/File_Aac.h"
#endif
#if defined(MEDIAINFO_AC3_YES)
#include "MediaInfo/Audio/File_Ac3.h"
#endif
#if defined(MEDIAINFO_DTS_YES)
#include "MediaInfo/Audio/File_Dts.h"
#endif
#if defined(MEDIAINFO_MPEGA_YES)
#include "MediaInfo/Audio/File_Mpega.h"
#endif
#if defined(MEDIAINFO_FLAC_YES)
#include "MediaInfo/Audio/File_Flac.h"
#endif
#if defined(MEDIAINFO_OPUS_YES)
#include "MediaInfo/Audio/File_Opus.h"
#endif
#if defined(MEDIAINFO_WVPK_YES)
#include "MediaInfo/Audio/File_Wvpk.h"
#endif
#if defined(MEDIAINFO_TTA_YES)
#include "MediaInfo/Audio/File_Tta.h"
#endif
#if defined(MEDIAINFO_PCM_YES)
#include "MediaInfo/Audio/File_Pcm.h"
#endif
#if MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Events.h"
#endif //MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#include <cstring>
#include <cmath>
#include <algorithm>
#include <zlib.h>
#include "ThirdParty/base64/base64.h"
#if MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Events_Internal.h"
#endif //MEDIAINFO_EVENTS
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//***************************************************************************
// Constants
//***************************************************************************
//---------------------------------------------------------------------------
#if MEDIAINFO_TRACE
static const size_t MaxCountSameElementInTrace=10;
#endif // MEDIAINFO_TRACE
//---------------------------------------------------------------------------
namespace Elements
{
//Common
const int64u Zero=(int32u)-1; //Should be (int64u)-1 but Borland C++ does not like this
const int64u CRC32=0x3F;
const int64u Void=0x6C;
//EBML
const int64u Ebml=0xA45DFA3;
const int64u Ebml_Version=0x286;
const int64u Ebml_ReadVersion=0x2F7;
const int64u Ebml_MaxIDLength=0x2F2;
const int64u Ebml_MaxSizeLength=0x2F3;
const int64u Ebml_DocType=0x282;
const int64u Ebml_DocTypeVersion=0x287;
const int64u Ebml_DocTypeReadVersion=0x285;
//RAWcooked
const int64u RawcookedBlock=0x7262;
const int64u RawcookedBlock_AfterData=0x02;
const int64u RawcookedBlock_BeforeData=0x01;
const int64u RawcookedBlock_FileName=0x10;
const int64u RawcookedBlock_FileHash=0x20;
const int64u RawcookedBlock_MaskAdditionAfterData=0x04;
const int64u RawcookedBlock_MaskAdditionBeforeData=0x03;
const int64u RawcookedBlock_MaskAdditionFileName=0x11;
const int64u RawcookedSegment=0x7273;
const int64u RawcookedSegment_LibraryName=0x70;
const int64u RawcookedSegment_LibraryVersion=0x71;
const int64u RawcookedTrack=0x7274;
const int64u RawcookedTrack_AfterData=0x02;
const int64u RawcookedTrack_BeforeData=0x01;
const int64u RawcookedTrack_FileName=0x10;
const int64u RawcookedTrack_FileHash=0x20;
const int64u RawcookedTrack_MaskBaseAfterData=0x04;
const int64u RawcookedTrack_MaskBaseBeforeData=0x03;
const int64u RawcookedTrack_MaskBaseFileName=0x11;
//Segment
const int64u Segment=0x8538067;
const int64u Segment_SeekHead=0x14D9B74;
const int64u Segment_SeekHead_Seek=0xDBB;
const int64u Segment_SeekHead_Seek_SeekID=0x13AB;
const int64u Segment_SeekHead_Seek_SeekPosition=0x13AC;
const int64u Segment_Info=0x549A966;
const int64u Segment_Info_SegmentUID=0x33A4;
const int64u Segment_Info_SegmentFilename=0x3384;
const int64u Segment_Info_PrevUID=0x1CB923;
const int64u Segment_Info_PrevFilename=0x1C83AB;
const int64u Segment_Info_NextUID=0x1EB923;
const int64u Segment_Info_NextFilename=0x1E83BB;
const int64u Segment_Info_SegmentFamily=0x444;
const int64u Segment_Info_ChapterTranslate=0x2924;
const int64u Segment_Info_ChapterTranslate_ChapterTranslateEditionUID=0x29FC;
const int64u Segment_Info_ChapterTranslate_ChapterTranslateCodec=0x29BF;
const int64u Segment_Info_ChapterTranslate_ChapterTranslateID=0x29A5;
const int64u Segment_Info_TimecodeScale=0xAD7B1;
const int64u Segment_Info_Duration=0x489;
const int64u Segment_Info_DateUTC=0x461;
const int64u Segment_Info_Title=0x3BA9;
const int64u Segment_Info_MuxingApp=0xD80;
const int64u Segment_Info_WritingApp=0x1741;
const int64u Segment_Cluster=0xF43B675;
const int64u Segment_Cluster_Timecode=0x67;
const int64u Segment_Cluster_SilentTracks=0x1854;
const int64u Segment_Cluster_SilentTracks_SilentTrackNumber=0x18D7;
const int64u Segment_Cluster_Position=0x27;
const int64u Segment_Cluster_PrevSize=0x2B;
const int64u Segment_Cluster_SimpleBlock=0x23;
const int64u Segment_Cluster_BlockGroup=0x20;
const int64u Segment_Cluster_BlockGroup_Block=0x21;
const int64u Segment_Cluster_BlockGroup_Block_Lace=0xFFFFFFFFFFFFFFFELL; //Fake one
const int64u Segment_Cluster_BlockGroup_BlockVirtual=0x22;
const int64u Segment_Cluster_BlockGroup_BlockAdditions=0x35A1;
const int64u Segment_Cluster_BlockGroup_BlockAdditions_BlockMore=0x26;
const int64u Segment_Cluster_BlockGroup_BlockAdditions_BlockMore_BlockAddID=0x6E;
const int64u Segment_Cluster_BlockGroup_BlockAdditions_BlockMore_BlockAdditional=0x25;
const int64u Segment_Cluster_BlockGroup_BlockDuration=0x1B;
const int64u Segment_Cluster_BlockGroup_ReferencePriority=0x7A;
const int64u Segment_Cluster_BlockGroup_ReferenceBlock=0x7B;
const int64u Segment_Cluster_BlockGroup_ReferenceVirtual=0x7D;
const int64u Segment_Cluster_BlockGroup_CodecState=0x24;
const int64u Segment_Cluster_BlockGroup_DiscardPadding=0x35A2;
const int64u Segment_Cluster_BlockGroup_Slices=0xE;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice=0x68;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice_LaceNumber=0x4C;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice_FrameNumber=0x4D;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice_BlockAdditionID=0x4B;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice_Delay=0x4E;
const int64u Segment_Cluster_BlockGroup_Slices_TimeSlice_SliceDuration=0x4F;
const int64u Segment_Cluster_BlockGroup_ReferenceFrame=0x48;
const int64u Segment_Cluster_BlockGroup_ReferenceFrame_ReferenceOffset=0x49;
const int64u Segment_Cluster_BlockGroup_ReferenceFrame_ReferenceTimeCode=0x4A;
const int64u Segment_Cluster_EncryptedBlock=0x2F;
const int64u Segment_Tracks=0x654AE6B;
const int64u Segment_Tracks_TrackEntry=0x2E;
const int64u Segment_Tracks_TrackEntry_TrackNumber=0x57;
const int64u Segment_Tracks_TrackEntry_TrackUID=0x33C5;
const int64u Segment_Tracks_TrackEntry_TrackType=0x3;
const int64u Segment_Tracks_TrackEntry_FlagEnabled=0x39;
const int64u Segment_Tracks_TrackEntry_FlagDefault=0x8;
const int64u Segment_Tracks_TrackEntry_FlagForced=0x15AA;
const int64u Segment_Tracks_TrackEntry_FlagLacing=0x1C;
const int64u Segment_Tracks_TrackEntry_MinCache=0x2DE7;
const int64u Segment_Tracks_TrackEntry_MaxCache=0x2DF8;
const int64u Segment_Tracks_TrackEntry_DefaultDuration=0x3E383;
const int64u Segment_Tracks_TrackEntry_DefaultDecodedFieldDuration=0x34E7A;
const int64u Segment_Tracks_TrackEntry_TrackTimecodeScale=0x3314F;
const int64u Segment_Tracks_TrackEntry_TrackOffset=0x137F;
const int64u Segment_Tracks_TrackEntry_MaxBlockAdditionID=0x15EE;
const int64u Segment_Tracks_TrackEntry_Name=0x136E;
const int64u Segment_Tracks_TrackEntry_Language=0x2B59C;
const int64u Segment_Tracks_TrackEntry_LanguageIETF=0x2B59D;
const int64u Segment_Tracks_TrackEntry_CodecID=0x6;
const int64u Segment_Tracks_TrackEntry_CodecPrivate=0x23A2;
const int64u Segment_Tracks_TrackEntry_CodecName=0x58688;
const int64u Segment_Tracks_TrackEntry_AttachmentLink=0x3446;
const int64u Segment_Tracks_TrackEntry_CodecSettings=0x1A9697;
const int64u Segment_Tracks_TrackEntry_CodecInfoURL=0x1B4040;
const int64u Segment_Tracks_TrackEntry_CodecDownloadURL=0x6B240;
const int64u Segment_Tracks_TrackEntry_CodecDecodeAll=0x2A;
const int64u Segment_Tracks_TrackEntry_TrackOverlay=0x2FAB;
const int64u Segment_Tracks_TrackEntry_CodecDelay=0x16AA;
const int64u Segment_Tracks_TrackEntry_SeekPreRoll=0x16BB;
const int64u Segment_Tracks_TrackEntry_TrackTranslate=0x2624;
const int64u Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateEditionUID=0x26FC;
const int64u Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateCodec=0x26BF;
const int64u Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateTrackID=0x26A5;
const int64u Segment_Tracks_TrackEntry_Video=0x60;
const int64u Segment_Tracks_TrackEntry_Video_FlagInterlaced=0x1A;
const int64u Segment_Tracks_TrackEntry_Video_FieldOrder=0x1D;
const int64u Segment_Tracks_TrackEntry_Video_StereoMode=0x13B8;
const int64u Segment_Tracks_TrackEntry_Video_AlphaMode=0x13C0;
const int64u Segment_Tracks_TrackEntry_Video_OldStereoMode=0x13B9;
const int64u Segment_Tracks_TrackEntry_Video_PixelWidth=0x30;
const int64u Segment_Tracks_TrackEntry_Video_PixelHeight=0x3A;
const int64u Segment_Tracks_TrackEntry_Video_PixelCropBottom=0x14AA;
const int64u Segment_Tracks_TrackEntry_Video_PixelCropTop=0x14BB;
const int64u Segment_Tracks_TrackEntry_Video_PixelCropLeft=0x14CC;
const int64u Segment_Tracks_TrackEntry_Video_PixelCropRight=0x14DD;
const int64u Segment_Tracks_TrackEntry_Video_DisplayWidth=0x14B0;
const int64u Segment_Tracks_TrackEntry_Video_DisplayHeight=0x14BA;
const int64u Segment_Tracks_TrackEntry_Video_DisplayUnit=0x14B2;
const int64u Segment_Tracks_TrackEntry_Video_AspectRatioType=0x14B3;
const int64u Segment_Tracks_TrackEntry_Video_ColourSpace=0xEB524;
const int64u Segment_Tracks_TrackEntry_Video_GammaValue=0xFB523;
const int64u Segment_Tracks_TrackEntry_Video_FrameRate=0x383E3;
const int64u Segment_Tracks_TrackEntry_Video_Colour=0x15B0;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MatrixCoefficients=0x15B1;
const int64u Segment_Tracks_TrackEntry_Video_Colour_BitsPerChannel=0x15B2;
const int64u Segment_Tracks_TrackEntry_Video_Colour_ChromaSubsamplingHorz=0x15B3;
const int64u Segment_Tracks_TrackEntry_Video_Colour_ChromaSubsamplingVert=0x15B4;
const int64u Segment_Tracks_TrackEntry_Video_Colour_CbSubsamplingHorz=0x15B5;
const int64u Segment_Tracks_TrackEntry_Video_Colour_CbSubsamplingVert=0x15B6;
const int64u Segment_Tracks_TrackEntry_Video_Colour_ChromaSitingHorz=0x15B7;
const int64u Segment_Tracks_TrackEntry_Video_Colour_ChromaSitingVert=0x15B8;
const int64u Segment_Tracks_TrackEntry_Video_Colour_Range=0x15B9;
const int64u Segment_Tracks_TrackEntry_Video_Colour_TransferCharacteristics=0x15BA;
const int64u Segment_Tracks_TrackEntry_Video_Colour_Primaries=0x15BB;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MaxCLL=0x15BC;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MaxFALL=0x15BD;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata=0x15D0;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryRChromaticityX=0x15D1;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryRChromaticityY=0x15D2;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryGChromaticityX=0x15D3;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryGChromaticityY=0x15D4;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryBChromaticityX=0x15D5;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryBChromaticityY=0x15D6;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_WhitePointChromaticityX=0x15D7;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_WhitePointChromaticityY=0x15D8;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_LuminanceMax=0x15D9;
const int64u Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_LuminanceMin=0x15DA;
const int64u Segment_Tracks_TrackEntry_Video_Projection=0x3670;
const int64u Segment_Tracks_TrackEntry_Video_Projection_ProjectionType=0x3671;
const int64u Segment_Tracks_TrackEntry_Video_Projection_ProjectionPrivate=0x3672;
const int64u Segment_Tracks_TrackEntry_Video_Projection_ProjectionPoseYaw=0x3673;
const int64u Segment_Tracks_TrackEntry_Video_Projection_ProjectionPosePitch=0x3674;
const int64u Segment_Tracks_TrackEntry_Video_Projection_ProjectionPoseRoll=0x3675;
const int64u Segment_Tracks_TrackEntry_Audio=0x61;
const int64u Segment_Tracks_TrackEntry_Audio_SamplingFrequency=0x35;
const int64u Segment_Tracks_TrackEntry_Audio_OutputSamplingFrequency=0x38B5;
const int64u Segment_Tracks_TrackEntry_Audio_Channels=0x1F;
const int64u Segment_Tracks_TrackEntry_Audio_ChannelPositions=0x3D7B;
const int64u Segment_Tracks_TrackEntry_Audio_BitDepth=0x2264;
const int64u Segment_Tracks_TrackEntry_TrackOperation=0x62;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes=0x63;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane=0x64;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane_TrackPlaneUID=0x65;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane_TrackPlaneType=0x66;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackJoinBlocks=0x69;
const int64u Segment_Tracks_TrackEntry_TrackOperation_TrackJoinBlocks_TrackJoinUID=0x6D;
const int64u Segment_Tracks_TrackEntry_TrickTrackUID=0x40;
const int64u Segment_Tracks_TrackEntry_TrickTrackSegmentUID=0x41;
const int64u Segment_Tracks_TrackEntry_TrickTrackFlag=0x46;
const int64u Segment_Tracks_TrackEntry_TrickMasterTrackUID=0x47;
const int64u Segment_Tracks_TrackEntry_TrickMasterTrackSegmentUID=0x44;
const int64u Segment_Tracks_TrackEntry_BlockAdditionMapping=0x1E4;
const int64u Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDName=0x1A4;
const int64u Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDType=0x1E7;
const int64u Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDExtraData=0x1ED;
const int64u Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDValue=0x1F0;
const int64u Segment_Tracks_TrackEntry_ContentEncodings=0x2D80;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding=0x2240;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingOrder=0x1031;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingScope=0x1032;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingType=0x1033;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression=0x1034;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompAlgo=0x254;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompSettings=0x255;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption=0x1035;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentEncAlgo=0x7E1;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentEncKeyID=0x7E2;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSignature=0x7E3;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigKeyID=0x7E4;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigAlgo=0x7E5;
const int64u Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigHashAlgo=0x7E6;
const int64u Segment_Cues=0xC53BB6B;
const int64u Segment_Cues_CuePoint=0x3B;
const int64u Segment_Cues_CuePoint_CueTime=0x33;
const int64u Segment_Cues_CuePoint_CueTrackPositions=0x37;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueTrack=0x77;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueClusterPosition=0x71;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueRelativePosition=0x70;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueDuration=0x32;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueBlockNumber=0x1378;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueCodecState=0x6A;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueReference=0x5B;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefTime=0x16;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefCluster=0x17;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefNumber=0x135F;
const int64u Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefCodecState=0x6B;
const int64u Segment_Attachments=0x941A469;
const int64u Segment_Attachments_AttachedFile=0x21A7;
const int64u Segment_Attachments_AttachedFile_FileDescription=0x67E;
const int64u Segment_Attachments_AttachedFile_FileName=0x66E;
const int64u Segment_Attachments_AttachedFile_FileMimeType=0x660;
const int64u Segment_Attachments_AttachedFile_FileData=0x65C;
const int64u Segment_Attachments_AttachedFile_FileUID=0x6AE;
const int64u Segment_Attachments_AttachedFile_FileReferral=0x675;
const int64u Segment_Attachments_AttachedFile_FileUsedStartTime=0x661;
const int64u Segment_Attachments_AttachedFile_FileUsedEndTime=0x662;
const int64u Segment_Chapters=0x43A770;
const int64u Segment_Chapters_EditionEntry=0x5B9;
const int64u Segment_Chapters_EditionEntry_EditionUID=0x5BC;
const int64u Segment_Chapters_EditionEntry_EditionFlagHidden=0x5BD;
const int64u Segment_Chapters_EditionEntry_EditionFlagDefault=0x5DB;
const int64u Segment_Chapters_EditionEntry_EditionFlagOrdered=0x5DD;
const int64u Segment_Chapters_EditionEntry_ChapterAtom=0x36;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterUID=0x33C4;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterStringUID=0x1654;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeStart=0x11;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeEnd=0x12;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagHidden=0x18;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagEnabled=0x598;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentUID=0x2E67;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentEditionUID=0x2EBC;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterPhysicalEquiv=0x23C3;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack=0xF;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack_ChapterTrackNumber=0x9;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay=0x0;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapString=0x5;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguage=0x37C;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguageIETF=0x37D;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapCountry=0x37E;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess=0x2944;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCodecID=0x2955;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessPrivate=0x50D;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand=0x2911;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessTime=0x2922;
const int64u Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessData=0x2933;
const int64u Segment_Tags=0x254C367;
const int64u Segment_Tags_Tag=0x3373;
const int64u Segment_Tags_Tag_Targets=0x23C0;
const int64u Segment_Tags_Tag_Targets_TargetTypeValue=0x28CA;
const int64u Segment_Tags_Tag_Targets_TargetType=0x23CA;
const int64u Segment_Tags_Tag_Targets_TagTrackUID=0x23C5;
const int64u Segment_Tags_Tag_Targets_TagEditionUID=0x23C9;
const int64u Segment_Tags_Tag_Targets_TagChapterUID=0x23C4;
const int64u Segment_Tags_Tag_Targets_TagAttachmentUID=0x23C6;
const int64u Segment_Tags_Tag_SimpleTag=0x27C8;
const int64u Segment_Tags_Tag_SimpleTag_TagName=0x5A3;
const int64u Segment_Tags_Tag_SimpleTag_TagLanguage=0x47A;
const int64u Segment_Tags_Tag_SimpleTag_TagLanguageIETF=0x47B;
const int64u Segment_Tags_Tag_SimpleTag_TagDefault=0x484;
const int64u Segment_Tags_Tag_SimpleTag_TagString=0x487;
const int64u Segment_Tags_Tag_SimpleTag_TagBinary=0x485;
}
//---------------------------------------------------------------------------
// CRC_32_Table (Little Endian bitstream, )
// The CRC in use is the IEEE-CRC-32 algorithm as used in the ISO 3309 standard and in section 8.1.1.6.2 of ITU-T recommendation V.42, with initial value of 0xFFFFFFFF. The CRC value MUST be computed on a little endian bitstream and MUST use little endian storage.
// A CRC is computed like this:
// Init: int32u CRC32 ^= 0;
// for each data byte do
// CRC32=(CRC32>>8) ^ Mk_CRC32_Table[(CRC32&0xFF)^*Buffer_Current++];
// End: CRC32 ^= 0;
static const int32u Mk_CRC32_Table[256] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02Ef8D,
};
//---------------------------------------------------------------------------
static void Matroska_CRC32_Compute(int32u &CRC32, const int8u* Buffer_Current, const int8u* Buffer_End)
{
while (Buffer_Current<Buffer_End)
CRC32 = (CRC32 >> 8) ^ Mk_CRC32_Table[(CRC32 & 0xFF) ^ *Buffer_Current++];
}
//---------------------------------------------------------------------------
#if MEDIAINFO_FIXITY
static size_t Matroska_TryToFixCRC(int8u* Buffer, size_t Buffer_Size, int32u CRCExpected, int8u& Modified)
{
//looking for a bit flip
vector<size_t> BitPositions;
size_t BitPosition_Max=Buffer_Size*8;
for (size_t BitPosition=0; BitPosition<BitPosition_Max; BitPosition++)
{
size_t BytePosition=BitPosition>>3;
size_t BitInBytePosition=BitPosition&0x7;
Buffer[BytePosition]^=1<<BitInBytePosition;
int32u CRC32Computed=0xFFFFFFFF;
Matroska_CRC32_Compute(CRC32Computed, Buffer, Buffer+Buffer_Size);
CRC32Computed ^= 0xFFFFFFFF;
if (CRC32Computed==CRCExpected)
{
BitPositions.push_back(BitPosition);
}
Buffer[BytePosition]^=1<<BitInBytePosition;
}
if (BitPositions.size()!=1)
return (size_t)-1;
Modified=Buffer[BitPositions[0]>>3]; //Save the byte here as we already have the content
return BitPositions[0];
}
#endif //MEDIAINFO_FIXITY
//---------------------------------------------------------------------------
static const char* Mk_ContentCompAlgo(int64u Algo)
{
switch (Algo)
{
case 0x00 : return "zlib";
case 0x01 : return "bzlib";
case 0x02 : return "lzo1x";
case 0x03 : return "Header stripping";
default : return "";
}
}
//---------------------------------------------------------------------------
static const char* Mk_StereoMode(int64u StereoMode)
{
switch (StereoMode)
{
case 0x00 : return ""; //Mono (default)
case 0x01 : return "Side by Side (left eye first)";
case 0x02 : return "Top-Bottom (right eye first)";
case 0x03 : return "Top-Bottom (left eye first)";
case 0x04 : return "Checkboard (right eye first)";
case 0x05 : return "Checkboard (left eye first)";
case 0x06 : return "Row Interleaved (right eye first)";
case 0x07 : return "Row Interleaved (left eye first)";
case 0x08 : return "Column Interleaved (right eye first)";
case 0x09 : return "Column Interleaved (left eye first)";
case 0x0A : return "Anaglyph (cyan/red)";
case 0x0B : return "Side by Side (right eye first)";
case 0x0C : return "Anaglyph (green/magenta)";
case 0x0D : return "Both Eyes laced in one block (left eye first)";
case 0x0E : return "Both Eyes laced in one block (right eye first)";
default : return "";
}
}
//---------------------------------------------------------------------------
static const char* Mk_OriginalSourceMedium_From_Source_ID (const Ztring &Value)
{
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('0'))
return "Blu-ray";
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('1'))
return "DVD-Video";
return "";
}
//---------------------------------------------------------------------------
static Ztring Mk_ID_From_Source_ID (const Ztring &Value)
{
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('0'))
{
// Blu-ray
int16u ValueI=0;
for (size_t Pos=2; Pos<Value.size(); Pos++)
{
ValueI*=16;
if (Value[Pos]>=__T('0') && Value[Pos]<=__T('9'))
ValueI+=Value[Pos]-__T('0');
else if (Value[Pos]>=__T('A') && Value[Pos]<=__T('F'))
ValueI+=10+Value[Pos]-__T('A');
else if (Value[Pos]>=__T('a') && Value[Pos]<=__T('f'))
ValueI+=10+Value[Pos]-__T('a');
else
return Value;
}
return Ztring::ToZtring(ValueI);
}
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('1'))
{
// DVD-Video
int16u ValueI=0;
for (size_t Pos=2; Pos<Value.size(); Pos++)
{
ValueI*=16;
if (Value[Pos]>=__T('0') && Value[Pos]<=__T('9'))
ValueI+=Value[Pos]-__T('0');
else if (Value[Pos]>=__T('A') && Value[Pos]<=__T('F'))
ValueI+=10+Value[Pos]-__T('A');
else if (Value[Pos]>=__T('a') && Value[Pos]<=__T('f'))
ValueI+=10+Value[Pos]-__T('a');
else
return Value;
}
int8u ID1 = ValueI&0xFF;
int8u ID2 = 0;
ValueI-=ID1;
if (ValueI)
ID2=ValueI>>8;
return Ztring::ToZtring(ID1) + (ID2?(__T('-') + Ztring::ToZtring(ID2)):Ztring());
}
return Value;
}
//---------------------------------------------------------------------------
static Ztring Mk_ID_String_From_Source_ID (const Ztring &Value)
{
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('0'))
{
// Blu-ray
int16u ValueI=0;
for (size_t Pos=2; Pos<Value.size(); Pos++)
{
ValueI*=16;
if (Value[Pos]>=__T('0') && Value[Pos]<=__T('9'))
ValueI+=Value[Pos]-__T('0');
else if (Value[Pos]>=__T('A') && Value[Pos]<=__T('F'))
ValueI+=10+Value[Pos]-__T('A');
else if (Value[Pos]>=__T('a') && Value[Pos]<=__T('f'))
ValueI+=10+Value[Pos]-__T('a');
else
return Value;
}
return Get_Hex_ID(ValueI);
}
if (Value.size()==6 && Value[0] == __T('0') && Value[1] == __T('1'))
{
// DVD-Video
int16u ValueI=0;
for (size_t Pos=2; Pos<Value.size(); Pos++)
{
ValueI*=16;
if (Value[Pos]>=__T('0') && Value[Pos]<=__T('9'))
ValueI+=Value[Pos]-__T('0');
else if (Value[Pos]>=__T('A') && Value[Pos]<=__T('F'))
ValueI+=10+Value[Pos]-__T('A');
else if (Value[Pos]>=__T('a') && Value[Pos]<=__T('f'))
ValueI+=10+Value[Pos]-__T('a');
else
return Value;
}
int8u ID1 = ValueI&0xFF;
int8u ID2 = 0;
ValueI-=ID1;
if (ValueI)
ID2=ValueI>>8;
return Get_Hex_ID(ID1) + (ID2? Get_Hex_ID(ID2):Ztring());
}
return Value;
}
//***************************************************************************
// Infos
//***************************************************************************
//---------------------------------------------------------------------------
extern std::string ExtensibleWave_ChannelMask (int32u ChannelMask);
extern std::string ExtensibleWave_ChannelMask2 (int32u ChannelMask);
extern std::string ExtensibleWave_ChannelMask_ChannelLayout(int32u ChannelMask);
//---------------------------------------------------------------------------
const char* Mpegv_colour_primaries(int8u colour_primaries);
const char* Mpegv_transfer_characteristics(int8u transfer_characteristics);
const char* Mpegv_matrix_coefficients(int8u matrix_coefficients);
const char* Mpegv_matrix_coefficients_ColorSpace(int8u matrix_coefficients);
const char* Mk_Video_Colour_Range(int8u range)
{
switch (range)
{
case 1: return "Limited";
case 2: return "Full";
default: return "";
}
}
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
//---------------------------------------------------------------------------
File_Mk::File_Mk()
:File__Analyze()
{
//Configuration
#if MEDIAINFO_EVENTS
ParserIDs[0]=MediaInfo_Parser_Matroska;
StreamIDs_Width[0]=16;
#endif //MEDIAINFO_EVENTS
#if MEDIAINFO_DEMUX
Demux_Level=2; //Container
#endif //MEDIAINFO_DEMUX
#if MEDIAINFO_TRACE
Trace_Layers_Update(0); //Container1
#endif //MEDIAINFO_TRACE
DataMustAlwaysBeComplete=false;
MustSynchronize=true;
//Temp
InvalidByteMax=0; //Default is max size of 8 bytes
Format_Version=0;
TimecodeScale=1000000; //Default value
Duration=0;
Segment_Info_Count=0;
Segment_Tracks_Count=0;
Segment_Cluster_Count=0;
CurrentAttachmentIsCover=false;
CoverIsSetFromAttachment=false;
BlockAddIDType=0;
Laces_Pos=0;
IsParsingSegmentTrack_SeekBackTo=0;
SegmentTrack_Offset_End=0;
#if MEDIAINFO_DEMUX
Demux_EventWasSent=(int64u)-1;
#endif //MEDIAINFO_DEMUX
CRC32Compute_SkipUpTo=0;
Stream_Count=0;
#if MEDIAINFO_TRACE
Trace_Activated_Save=false;
#endif //MEDIAINFO_TRACE
//Hints
File_Buffer_Size_Hint_Pointer=NULL;
//Helpers
CodecPrivate=NULL;
}
//---------------------------------------------------------------------------
File_Mk::~File_Mk()
{
delete[] CodecPrivate; //CodecPrivate=NULL;
}
//***************************************************************************
// Streams management
//***************************************************************************
//---------------------------------------------------------------------------
void File_Mk::Streams_Finish()
{
if (Duration!=0 && TimecodeScale!=0)
Fill(Stream_General, 0, General_Duration, Duration*int64u_float64(TimecodeScale)/1000000.0, 0);
if (Retrieve(Stream_General, 0, General_IsStreamable).empty())
Fill(Stream_General, 0, General_IsStreamable, "Yes");
//Tags (General)
for (tags::iterator Item=Segment_Tags_Tag_Items.begin(); Item!=Segment_Tags_Tag_Items.end(); ++Item)
if (!Item->first || Item->first == (int64u)-1)
{
for (tagspertrack::iterator Tag=Item->second.begin(); Tag!=Item->second.end(); ++Tag)
if ((Tag->first!=__T("Encoded_Library") || Retrieve(Stream_General, 0, "Encoded_Library")!=Tag->second) // Avoid repetition if Info block is same as tags
&& (Tag->first!=__T("Encoded_Date") || Retrieve(StreamKind_Last, StreamPos_Last, "Encoded_Date")!=Tag->second)
&& (Tag->first!=__T("Title") || Retrieve(StreamKind_Last, StreamPos_Last, "Title")!=Tag->second))
Fill(Stream_General, 0, Tag->first.To_UTF8().c_str(), Tag->second);
}
for (std::map<int64u, stream>::iterator Temp=Stream.begin(); Temp!=Stream.end(); ++Temp)
{
StreamKind_Last=Temp->second.StreamKind;
StreamPos_Last=Temp->second.StreamPos;
float64 FrameRate_FromTags = 0.0;
bool HasStats=false;
//Tags (per track)
if (Temp->second.TrackUID && Temp->second.TrackUID!=(int64u)-1)
{
//Technical info
for (std::map<std::string, Ztring>::iterator Info=Temp->second.Infos.begin(); Info!=Temp->second.Infos.end(); ++Info)
Fill(StreamKind_Last, StreamPos_Last, Info->first.c_str(), Info->second);
tags::iterator Item=Segment_Tags_Tag_Items.find(Temp->second.TrackUID);
if (Item != Segment_Tags_Tag_Items.end())
{
//Statistic Tags
tagspertrack::iterator Item2=Item->second.find(__T("_STATISTICS_TAGS"));
HasStats=Item2!=Item->second.end();
if (HasStats)
{
Ztring TagsList=Item2->second;
Item->second.erase(Item2);
bool Tags_Verified=false;
{
Ztring Hutc = Retrieve(Stream_General, 0, "Encoded_Date");
Hutc.FindAndReplace(__T("UTC "), Ztring());
Hutc = Hutc.substr(0, Hutc.find(__T(" / "), 0)); // leave only the first date in a "UTC date1 / UTC date2" field
Ztring App, Utc;
Item2=Item->second.find(__T("_STATISTICS_WRITING_APP"));
if (Item2!=Item->second.end())
{
App=Item2->second;
Item->second.erase(Item2);
}
Item2=Item->second.find(__T("_STATISTICS_WRITING_DATE_UTC"));
if (Item2!=Item->second.end())
{
Utc=Item2->second;
Item->second.erase(Item2);
}
if (Utc>=Hutc)
Tags_Verified=true;
else
Fill(StreamKind_Last, StreamPos_Last, "Statistics Tags Issue", App + __T(' ') + Utc + __T(" / ") + Retrieve(Stream_General, 0, "Encoded_Application") + __T(' ') + Hutc);
}
Ztring TempTag;
float64 Statistics_Duration=0;
float64 Statistics_FrameCount=0;
for (Ztring::iterator Back = TagsList.begin();;++Back)
{
if ((Back == TagsList.end()) || (*Back == ' ') || (*Back == '\0'))
{
if (!TempTag.empty())
{
Item2=Item->second.find(TempTag);
if (Item2!=Item->second.end())
{
TempTag=Item2->first;
const Ztring& TagValue=Item2->second;
bool Set=false;
if (TempTag==__T("BPS"))
{
if (Tags_Verified)
{ Item->second["BitRate"]=TagValue; Set=true; }
else
TempTag="BitRate";
}
else if (TempTag==__T("DURATION"))
{
if (Tags_Verified)
{
ZtringList Parts;
Parts.Separator_Set(0, ":");
Parts.Write(TagValue);
Statistics_Duration=0;
if (Parts.size()>=1)
Statistics_Duration += Parts[0].To_float64()*60*60;
if (Parts.size()>=2)
Statistics_Duration += Parts[1].To_float64()*60;
int8u Rounding=0; //Default is rounding to milliseconds, TODO: rounding to less than millisecond when "Duration" field is changed to seconds.
if (Parts.size()>=3)
{
Statistics_Duration += Parts[2].To_float64();
if (Parts[2].size()>6) //More than milliseconds
Rounding=Parts[2].size()-6;
}
Item->second["Duration"].From_Number(Statistics_Duration*1000, Rounding);
Set=true;
}
if (!Set) TempTag="Duration";
}
else if (TempTag==__T("NUMBER_OF_FRAMES"))
{
if (Tags_Verified)
{
Statistics_FrameCount=TagValue.To_float64();
Item->second["FrameCount"]=TagValue;
if (StreamKind_Last==Stream_Text)
{
const Ztring &Format=Retrieve(Stream_Text, StreamPos_Last, "Format");
if (Format.find(__T("608"))==string::npos && Format.find(__T("708"))==string::npos)
Item->second["ElementCount"]=TagValue; // if not 608 or 708, this is used to be also the count of elements
}
Set=true;
}
else
TempTag="FrameCount";
}
else if (TempTag==__T("NUMBER_OF_BYTES"))
{
if (Tags_Verified)
{
Item->second["StreamSize"]=TagValue;
Set=true;
}
else
TempTag="StreamSize";
}
else if (TempTag==__T("NUMBER_OF_BYTES_UNCOMPRESSED"))
{
if (Tags_Verified)
{
Item->second["StreamSize_Demuxed"]=TagValue;
Set=true;
}
else
TempTag="Stream Size (Uncompressed)";
}
else if (TempTag==__T("SOURCE_ID"))
{
if (Tags_Verified)
{
Item->second["OriginalSourceMedium_ID"]=Mk_ID_From_Source_ID(TagValue);
Item->second["OriginalSourceMedium_ID/String"]=Mk_ID_String_From_Source_ID(TagValue);
Item->second["OriginalSourceMedium"]=Mk_OriginalSourceMedium_From_Source_ID(TagValue);
Set=true;
}
else
TempTag="OriginalSourceMedium_ID";
}
if (!Set)
{
TempTag.insert(0, __T("FromStats_"));
Item->second[TempTag]=TagValue;
}
Item->second.erase(Item2);
}
if (Back == TagsList.end())
break;
TempTag.clear();
}
}
else
TempTag+=*Back;
}
if (Statistics_Duration && Statistics_FrameCount)
{
FrameRate_FromTags = Statistics_FrameCount/Statistics_Duration;
if (float64_int64s(FrameRate_FromTags) - FrameRate_FromTags*1.001 > -0.0001
&& float64_int64s(FrameRate_FromTags) - FrameRate_FromTags*1.001 < +0.0001)
{
// Checking 1.001 frame rates, Statistics_Duration is has often only a 1 ms precision so we test between -1ms and +1ms
float64 Duration_1001 = Statistics_FrameCount / float64_int64s(FrameRate_FromTags) * 1.001000;
float64 Duration_1000 = Statistics_FrameCount / float64_int64s(FrameRate_FromTags) * 1.001001;
bool CanBe1001 = false;
bool CanBe1000 = false;
if (std::fabs((Duration_1000 - Duration_1001) * 10000) >= 15)
{
Ztring DurationS; DurationS.From_Number(Statistics_Duration, 3);
Ztring DurationS_1001; DurationS_1001.From_Number(Duration_1001, 3);
Ztring DurationS_1000; DurationS_1000.From_Number(Duration_1000, 3);
CanBe1001=DurationS==DurationS_1001?true:false;
CanBe1000=DurationS==DurationS_1000?true:false;
if (CanBe1001 && !CanBe1000)
FrameRate_FromTags = float64_int64s(FrameRate_FromTags) / 1.001;
if (CanBe1000 && !CanBe1001)
FrameRate_FromTags = float64_int64s(FrameRate_FromTags) / 1.001001;
}
// Duration from tags not reliable, checking TrackDefaultDuration
if (CanBe1000 == CanBe1001 && Temp->second.TrackDefaultDuration)
{
const float64 Duration_Default=((float64)1000000000)/Temp->second.TrackDefaultDuration;
if (float64_int64s(Duration_Default) - Duration_Default*1.001000 > -0.000002
&& float64_int64s(Duration_Default) - Duration_Default*1.001000 < +0.000002) // Detection of precise 1.001 (e.g. 24000/1001) taking into account precision of 32-bit float
{
FrameRate_FromTags = float64_int64s(FrameRate_FromTags) / 1.001;
}
if (float64_int64s(Duration_Default) - Duration_Default*1.001001 > -0.000002
&& float64_int64s(Duration_Default) - Duration_Default*1.001001 < +0.000002) // Detection of rounded 1.001 (e.g. 23976/1000) taking into account precision of 32-bit float
{
FrameRate_FromTags = float64_int64s(FrameRate_FromTags) / 1.001001;
}
}
}
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_FrameRate), FrameRate_FromTags, 3, true);
}
}
//Filling
for (tagspertrack::iterator Tag=Item->second.begin(); Tag!=Item->second.end(); ++Tag)
{
if (!HasStats && Tag->first==__T("DURATION"))
{
//If this field is present but there is no stats tag, let's hope that the field was not copied as is after an edit of the file...
const string& s=Tag->second.To_UTF8();
if ( s.size()>=12
&& s[ 0]>='0' && s[ 0]<='9'
&& s[ 1]>='0' && s[ 1]<='9'
&& s[ 2]==':'
&& s[ 3]>='0' && s[ 3]<='9'
&& s[ 4]>='0' && s[ 4]<='9'
&& s[ 5]==':'
&& s[ 6]>='0' && s[ 6]<='9'
&& s[ 7]>='0' && s[ 7]<='9'
&& s[ 8]=='.')
{
bool IsNok=false;
size_t s_size=s.size();
for (size_t i=9; i<s_size; i++)
if (s[i]<'0' || s[i]>'9')
IsNok=true;
if (!IsNok)
{
float64 d=(s[ 0]-'0')*10*60*60
+ (s[ 1]-'0') *60*60
+ (s[ 3]-'0') *10*60
+ (s[ 4]-'0') *60
+ (s[ 6]-'0') *10
+ (s[ 7]-'0') ;
for (size_t i=9; i<s_size; i++)
d+=(s[i]-'0')/std::pow(10.0, double(i)-8);
Fill(StreamKind_Last, StreamPos_Last, "Duration", d*1000, s.size()-12);
continue;
}
}
}
if ((Tag->first!=__T("Language") || Retrieve(StreamKind_Last, StreamPos_Last, "Language").empty())) // Prioritize Tracks block over tags
Fill(StreamKind_Last, StreamPos_Last, Tag->first.To_UTF8().c_str(), Tag->second);
}
}
}
if (Temp->second.DisplayAspectRatio!=0)
{
//Corrections
if (Temp->second.DisplayAspectRatio>=1.777 && Temp->second.DisplayAspectRatio<=1.778)
Temp->second.DisplayAspectRatio=((float32)16)/9;
if (Temp->second.DisplayAspectRatio>=1.333 && Temp->second.DisplayAspectRatio<=1.334)
Temp->second.DisplayAspectRatio=((float32)4)/3;
Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, Temp->second.DisplayAspectRatio, 3, true);
int64u Width=Retrieve(Stream_Video, StreamPos_Last, Video_Width).To_int64u();
int64u Height=Retrieve(Stream_Video, StreamPos_Last, Video_Height).To_int64u();
if (Width)
Fill(Stream_Video, StreamPos_Last, Video_PixelAspectRatio, Temp->second.DisplayAspectRatio*Height/Width, 3, true);
}
if (Temp->second.Parser)
{
Fill(Temp->second.Parser);
if (Config->ParseSpeed<=1.0)
Temp->second.Parser->Open_Buffer_Unsynch();
}
//Video specific
if (StreamKind_Last==Stream_Video)
{
//FrameRate
bool IsVfr=false;
bool RelyOnParser=false;
if (Temp->second.Segment_Cluster_BlockGroup_BlockDuration_Counts.size()>2)
IsVfr=true;
else if (Temp->second.TimeCodes.size()>1)
{
//Trying to detect VFR
std::vector<int64s> FrameRate_Between;
std::sort(Temp->second.TimeCodes.begin(), Temp->second.TimeCodes.end()); //This is PTS, no DTS --> Some frames are out of order
size_t FramesToAdd=0;
for (size_t Pos=1; Pos<Temp->second.TimeCodes.size(); Pos++)
{
int64u Duration=Temp->second.TimeCodes[Pos]-Temp->second.TimeCodes[Pos-1];
if (Duration)
FrameRate_Between.push_back(Duration);
else
FramesToAdd++;
}
if (FrameRate_Between.size()>=60+32) //Minimal 1 seconds (@60 fps)
FrameRate_Between.resize(FrameRate_Between.size()-16); //We remove the last ones, because this is PTS, no DTS --> Some frames are out of order
std::sort(FrameRate_Between.begin(), FrameRate_Between.end());
if (FrameRate_Between.size()>2)
{
//Looking for 3 consecutive same values, in order to remove some missing frames from stats
size_t i=FrameRate_Between.size()-1;
int64s Previous = FrameRate_Between[i];
do
{
i--;
if (FrameRate_Between[i]==Previous && FrameRate_Between[i-1]==Previous)
break;
Previous=FrameRate_Between[i];
}
while (i>2);
if (i>FrameRate_Between.size()/2)
FrameRate_Between.resize(i+2);
}
if (FrameRate_Between.size()>=40)
FrameRate_Between.resize(FrameRate_Between.size()-FrameRate_Between.size()/10); //We remove the last ones, in order to ignore skipped frames (bug of the muxer?)
else if (FrameRate_Between.size()>=7)
FrameRate_Between.resize(FrameRate_Between.size()-4); //We remove the last ones, in order to ignore skipped frames (bug of the muxer?)
if (FrameRate_Between.size()>2
&& FrameRate_Between[0]*0.9<FrameRate_Between[FrameRate_Between.size()-1]
&& FrameRate_Between[0]*1.1>FrameRate_Between[FrameRate_Between.size()-1]
&& TimecodeScale)
{
float Time=0;
for (size_t i=0; i<FrameRate_Between.size(); i++)
Time += FrameRate_Between[i];
Time /= FrameRate_Between.size();
if (Temp->second.TrackDefaultDuration && Time>=Temp->second.TrackDefaultDuration/TimecodeScale*0.95 && Time<=Temp->second.TrackDefaultDuration/TimecodeScale*1.05)
Time=(float)Temp->second.TrackDefaultDuration/TimecodeScale; //TrackDefaultDuration is maybe more precise than the time code
if (Time)
{
float32 FrameRate_FromCluster=1000000000/Time/TimecodeScale;
if (Temp->second.Parser)
{
float32 FrameRate_FromParser=Temp->second.Parser->Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate).To_float32();
if (FrameRate_FromParser
&& FrameRate_FromParser*2>FrameRate_FromCluster*0.9
&& FrameRate_FromParser*2<FrameRate_FromCluster*1.1) //TODO: awfull method to detect interlaced content with one field per block
FrameRate_FromCluster/=2;
if (FrameRate_FromParser
&& FrameRate_FromParser>FrameRate_FromCluster*0.99
&& FrameRate_FromParser<FrameRate_FromCluster*1.01)
RelyOnParser=true; //Disabling frame rate guess, relying on parser precision
}
if (FrameRate_FromTags)
{
if (FrameRate_FromCluster < FrameRate_FromTags - (FrameRate_FromTags*(TimecodeScale*0.0000000010021)) || FrameRate_FromCluster > FrameRate_FromTags + (FrameRate_FromTags*(TimecodeScale*0.0000000010021)))
IsVfr=true;
}
else if (!RelyOnParser)
Fill(Stream_Video, StreamPos_Last, Video_FrameRate, FrameRate_FromCluster);
}
}
else if (FrameRate_Between.size()>2)
IsVfr=true;
}
// In case there are not enough frames for computing frame rate, trying to rely on TrackDefaultDuration as a fallback
if (!IsVfr && !RelyOnParser && Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate).empty() && Temp->second.TrackDefaultDuration
&& Temp->second.TrackDefaultDuration!=32999999 // Seen in some 30 fps stream, not the one for all frames
&& Temp->second.TrackDefaultDuration!=41999998 // Seen in some 24 fps stream, not the one for all frames
&& Temp->second.TrackDefaultDuration!=41999999 // Seen in some 24 fps stream, not the one for all frames
)
{
float32 FrameRate_FromCluster=1000000000/(float32)Temp->second.TrackDefaultDuration;
if (Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate).empty())
Fill(Stream_Video, StreamPos_Last, Video_FrameRate, FrameRate_FromCluster);
}
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Mode, IsVfr?"VFR":"CFR");
//MasteringDisplay
Ztring MasteringDisplay_ColorPrimaries, MasteringDisplay_Luminance;
Get_MasteringDisplayColorVolume(MasteringDisplay_ColorPrimaries, MasteringDisplay_Luminance, Temp->second.MasteringMetadata);
if (!MasteringDisplay_ColorPrimaries.empty() || !MasteringDisplay_Luminance.empty())
{
Fill(StreamKind_Last, StreamPos_Last, "HDR_Format", "SMPTE ST 2086");
Fill(StreamKind_Last, StreamPos_Last, "HDR_Format_Compatibility", "HDR10");
Fill(StreamKind_Last, StreamPos_Last, "MasteringDisplay_ColorPrimaries", MasteringDisplay_ColorPrimaries);
Fill(StreamKind_Last, StreamPos_Last, "MasteringDisplay_Luminance", MasteringDisplay_Luminance);
}
}
//Delay
if (Temp->second.TimeCode_Start!=(int64u)-1 && TimecodeScale)
{
//From TimeCode
float64 Delay=Temp->second.TimeCode_Start*int64u_float64(TimecodeScale)/1000000.0;
//From stream format
if (Temp->second.Parser && StreamKind_Last==Stream_Audio && Count_Get(Stream_Video)==1 && Temp->second.Parser->Count_Get(Stream_General)>0)
{
if (Temp->second.Parser->Buffer_TotalBytes_FirstSynched==0)
;
else if (Temp->second.AvgBytesPerSec!=0)
Delay+=((float64)Temp->second.Parser->Buffer_TotalBytes_FirstSynched)*1000/Temp->second.AvgBytesPerSec;
else
{
int64u BitRate = Temp->second.Parser->Retrieve(Stream_Audio, 0, Audio_BitRate).To_int64u();
if (BitRate == 0)
BitRate = Temp->second.Parser->Retrieve(Stream_Audio, 0, Audio_BitRate_Nominal).To_int64u();
if (BitRate)
Delay += ((float64)Temp->second.Parser->Buffer_TotalBytes_FirstSynched) * 1000 / BitRate;
}
}
//Filling
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Delay), Delay, 0, true);
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Delay_Source), "Container");
const Ztring &DurationS=Retrieve(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Duration));
float64 Duration=DurationS.To_float64();
if (!HasStats && Duration && Duration>=Delay) //Not sure about when tats are present, so for the moment we remove delay from duration only if there is no stats, Duration looks like more lie timestamp of the end of the last frame with the example we got
{
Duration-=Delay;
size_t DotPos=DurationS.find(__T('.'));
if (DotPos == (size_t)-1)
DotPos = DurationS.size();
else
DotPos++;
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Duration), Duration, DurationS.size()-DotPos, true);
}
}
if (Temp->second.Parser)
{
Ztring Codec_Temp=Retrieve(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec)); //We want to keep the 4CC;
//if (Duration_Temp.empty()) Duration_Temp=Retrieve(StreamKind_Last, Temp->second.StreamPos, Fill_Parameter(StreamKind_Last, Generic_Duration)); //Duration from stream is sometimes false
//else Duration_Temp.clear();
#ifdef MEDIAINFO_PCM_YES
if (Temp->second.Parser && Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("PCM"))
{
Temp->second.Parser->Accept();
Temp->second.Parser->Fill(); // No need of any content for filling, so filling it even if very quick pass
}
#endif //MEDIAINFO_PCM_YES
Finish(Temp->second.Parser);
Merge(*Temp->second.Parser, StreamKind_Last, 0, StreamPos_Last);
//if (!Duration_Temp.empty()) Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Duration), Duration_Temp, true);
if (Temp->second.StreamKind==Stream_Video && !Codec_Temp.empty())
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec), Codec_Temp, true);
//Format specific
#if defined(MEDIAINFO_DVDIF_YES)
if (StreamKind_Last==Stream_Video && Retrieve(Stream_Video, StreamPos_Last, Video_Format)==__T("DV"))
{
if (Retrieve(Stream_General, 0, General_Recorded_Date).empty())
Fill(Stream_General, 0, General_Recorded_Date, Temp->second.Parser->Retrieve(Stream_General, 0, General_Recorded_Date));
//Video and Audio are together
size_t Audio_Count=Temp->second.Parser->Count_Get(Stream_Audio);
for (size_t Audio_Pos=0; Audio_Pos<Audio_Count; Audio_Pos++)
{
Fill_Flush();
Stream_Prepare(Stream_Audio); // TODO: merge code with the one from RIFF/AVI parser and put this audio streams in the ID order instead of after pure Matroska audio streams
size_t Pos=Count_Get(Stream_Audio)-1;
Merge(*Temp->second.Parser, Stream_Audio, Audio_Pos, StreamPos_Last);
Fill(Stream_Audio, Pos, Audio_MuxingMode, "DV");
Fill(Stream_Audio, Pos, Audio_Duration, Retrieve(Stream_Video, Temp->second.StreamPos, Video_Duration));
Fill(Stream_Audio, Pos, "MuxingMode_MoreInfo", __T("Muxed in Video #")+Ztring().From_Number(Temp->second.StreamPos+1));
Fill(Stream_Audio, Pos, Audio_StreamSize_Encoded, 0); //Included in the DV stream size
Ztring ID=Retrieve(Stream_Audio, Pos, Audio_ID);
Fill(Stream_Audio, Pos, Audio_ID, Retrieve(Stream_Video, Temp->second.StreamPos, Video_ID)+__T("-")+ID, true);
}
StreamKind_Last=Stream_Video;
StreamPos_Last=Temp->second.StreamPos;
}
#endif
//Special case: AAC
if (StreamKind_Last==Stream_Audio
&& (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("AAC")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("MPEG Audio")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("Vorbis")))
Clear(Stream_Audio, StreamPos_Last, Audio_BitDepth); //Resolution is not valid for AAC / MPEG Audio / Vorbis
//Special case: 5.1
if (StreamKind_Last==Stream_Audio
&& (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("AC-3")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("E-AC-3")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("DTS"))
&& Retrieve(Stream_Audio, StreamPos_Last, Audio_Channel_s__Original)==__T("6")
&& Retrieve(Stream_Audio, StreamPos_Last, Audio_Channel_s_)==__T("5"))
{
Clear(Stream_Audio, StreamPos_Last, Audio_Channel_s__Original);
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, 6, 10, true); //Some muxers do not count LFE in the channel count, let's say it is normal
}
//VFR
if (Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate_Mode)==__T("VFR") && Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate_Original).empty())
{
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Original, Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate));
Clear(Stream_Video, StreamPos_Last, Video_FrameRate);
}
//Crop
if (Temp->second.PixelCropLeft || Temp->second.PixelCropRight)
{
Fill(Stream_Video, StreamPos_Last, Video_Width_Original, Retrieve(Stream_Video, StreamPos_Last, Video_Width), true);
Fill(Stream_Video, StreamPos_Last, Video_Width, Retrieve(Stream_Video, StreamPos_Last, Video_Width).To_int64u()-Temp->second.PixelCropLeft-Temp->second.PixelCropRight, 10, true);
Fill(Stream_Video, StreamPos_Last, Video_Width_Offset, Temp->second.PixelCropLeft, 10, true);
}
if (Temp->second.PixelCropTop || Temp->second.PixelCropBottom)
{
Fill(Stream_Video, StreamPos_Last, Video_Height_Original, Retrieve(Stream_Video, StreamPos_Last, Video_Height), true);
Fill(Stream_Video, StreamPos_Last, Video_Height, Retrieve(Stream_Video, StreamPos_Last, Video_Height).To_int64u()-Temp->second.PixelCropTop-Temp->second.PixelCropBottom, 10, true);
Fill(Stream_Video, StreamPos_Last, Video_Height_Offset, Temp->second.PixelCropTop, 10, true);
}
}
if (Temp->second.FrameRate!=0 && Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate).empty())
Fill(Stream_Video, StreamPos_Last, Video_FrameRate, Temp->second.FrameRate, 3);
//Flags
Fill(StreamKind_Last, StreamPos_Last, "Default", Temp->second.Default?"Yes":"No");
Fill(StreamKind_Last, StreamPos_Last, "Forced", Temp->second.Forced?"Yes":"No");
}
//Chapters
if (TimecodeScale)
{
for (EditionEntries_Pos=0; EditionEntries_Pos<EditionEntries.size(); EditionEntries_Pos++)
{
Stream_Prepare(Stream_Menu);
Fill(Stream_Menu, StreamPos_Last, Menu_Chapters_Pos_Begin, Count_Get(Stream_Menu, StreamPos_Last), 10, true);
for (ChapterAtoms_Pos=0; ChapterAtoms_Pos<EditionEntries[EditionEntries_Pos].ChapterAtoms.size(); ChapterAtoms_Pos++)
{
if (EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterTimeStart!=(int64u)-1)
{
Ztring Text;
for (ChapterDisplays_Pos=0; ChapterDisplays_Pos<EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays.size(); ChapterDisplays_Pos++)
{
Ztring PerLanguage;
if (!EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays[ChapterDisplays_Pos].ChapLanguage.empty())
PerLanguage=MediaInfoLib::Config.Iso639_1_Get(EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays[ChapterDisplays_Pos].ChapLanguage)+__T(':');
PerLanguage+=EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays[ChapterDisplays_Pos].ChapString;
Text+=PerLanguage+__T(" - ");
}
Ztring Time=Ztring().Duration_From_Milliseconds(EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterTimeStart/1000000).To_UTF8().c_str();
if (Text.size())
Text.resize(Text.size()-3);
else
Text = Time;
Fill(Stream_Menu, StreamPos_Last, Time.To_UTF8().c_str(), Text);
}
}
Fill(Stream_Menu, StreamPos_Last, Menu_Chapters_Pos_End, Count_Get(Stream_Menu, StreamPos_Last), 10, true);
}
}
//Purge what is not needed anymore
if (!File_Name.empty()) //Only if this is not a buffer, with buffer we can have more data
Stream.clear();
}
//***************************************************************************
// Buffer - Global
//***************************************************************************
//---------------------------------------------------------------------------
void File_Mk::Read_Buffer_Unsynched()
{
Laces_Pos=0;
Laces.clear();
if (!File_GoTo)
Element_Level=0;
for (std::map<int64u, stream>::iterator streamItem=Stream.begin(); streamItem!=Stream.end(); streamItem++)
{
if (!File_GoTo)
streamItem->second.PacketCount=0;
if (streamItem->second.Parser)
streamItem->second.Parser->Open_Buffer_Unsynch();
}
}
//---------------------------------------------------------------------------
#if MEDIAINFO_SEEK
size_t File_Mk::Read_Buffer_Seek(size_t Method, int64u Value, int64u ID)
{
//Currently stupidely go back to 0 //TODO:
GoTo(Buffer_TotalBytes_FirstSynched);
Open_Buffer_Unsynch();
return 1;
}
#endif //MEDIAINFO_SEEK
//***************************************************************************
// Buffer - Synchro
//***************************************************************************
//---------------------------------------------------------------------------
bool File_Mk::Synchronize()
{
//Synchronizing
while (Buffer_Offset+4<=Buffer_Size && (Buffer[Buffer_Offset ]!=0x1A
|| Buffer[Buffer_Offset+1]!=0x45
|| Buffer[Buffer_Offset+2]!=0xDF
|| Buffer[Buffer_Offset+3]!=0xA3))
{
Buffer_Offset++;
while (Buffer_Offset<Buffer_Size && Buffer[Buffer_Offset]!=0x1A)
Buffer_Offset++;
}
//Parsing last bytes if needed
if (Buffer_Offset+4>Buffer_Size)
{
if (Buffer_Offset+3==Buffer_Size && CC3(Buffer+Buffer_Offset)!=0x1A45DF)
Buffer_Offset++;
if (Buffer_Offset+2==Buffer_Size && CC2(Buffer+Buffer_Offset)!=0x1A45)
Buffer_Offset++;
if (Buffer_Offset+1==Buffer_Size && CC1(Buffer+Buffer_Offset)!=0x1A)
Buffer_Offset++;
return false;
}
//Synched is OK
MustSynchronize=false; //We need synchro only once (at the beginning, in case of junk bytes before EBML)
return true;
}
//***************************************************************************
// Buffer - Global
//***************************************************************************
//---------------------------------------------------------------------------
void File_Mk::Read_Buffer_Continue()
{
//Handling CRC32 computing when there is no need of the data (data not parsed, only needed for CRC32)
if (CRC32Compute_SkipUpTo>File_Offset)
{
int64u Size=CRC32Compute_SkipUpTo-File_Offset;
if (Element_Size>Size)
Element_Size=Size;
Element_Offset=Element_Size;
CRC32_Check();
}
}
//***************************************************************************
// Buffer
//***************************************************************************
//---------------------------------------------------------------------------
bool File_Mk::Header_Begin()
{
#if MEDIAINFO_DEMUX
//Handling of multiple frames in one block
if (Config->Demux_Unpacketize_Get() && Demux_EventWasSent!=(int64u)-1)
{
stream &Stream_Temp=Stream[Demux_EventWasSent];
Frame_Count_NotParsedIncluded=Stream_Temp.Parser->Frame_Count_NotParsedIncluded;
FrameInfo.PTS=Stream_Temp.Parser->FrameInfo.PTS;
Open_Buffer_Continue(Stream_Temp.Parser, Buffer + Buffer_Offset, 0);
if (Config->Demux_EventWasSent)
return false;
Demux_EventWasSent=(int64u)-1;
}
#endif //MEDIAINFO_DEMUX
#if MEDIAINFO_TRACE
if (Trace_Activated_Save && Element_Level==0)
{
Trace_Activated=true;
Trace_Activated_Save=false;
}
#endif //MEDIAINFO_TRACE
return true;
}
//---------------------------------------------------------------------------
void File_Mk::Header_Parse()
{
//Handling of laces
if (!Laces.empty())
{
Header_Fill_Code(Elements::Segment_Cluster_BlockGroup_Block_Lace, "Data");
Header_Fill_Size(Laces[Laces_Pos]);
return;
}
//Test of zero padding
int8u Null;
Peek_B1(Null);
if (Null<=InvalidByteMax)
{
if (Buffer_Offset_Temp==0)
Buffer_Offset_Temp=Buffer_Offset+1;
while (Buffer_Offset_Temp<Buffer_Size)
{
if (Buffer[Buffer_Offset_Temp]>InvalidByteMax)
break;
Buffer_Offset_Temp++;
}
if (Buffer_Offset_Temp>=Buffer_Size)
{
Element_WaitForMoreData();
return;
}
Header_Fill_Code((int32u)-1); //Should be (int64u)-1 but Borland C++ does not like this
Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset);
Buffer_Offset_Temp=0;
return;
}
//Parsing
int64u Name = 0, Size = 0;
bool NameIsValid=true;
if (Element_Offset+1<Element_Size)
{
int8u NamePeek;
Peek_B1(NamePeek);
if (NamePeek<0x10)
{
Skip_B1( "Invalid");
#if MEDIAINFO_TRACE
Element_Level--;
Element_Info("NOK");
Element_Level++;
#endif //MEDIAINFO_TRACE
NameIsValid=false;
Header_Fill_Code(0, "Junk");
Header_Fill_Size(1);
}
}
if (NameIsValid)
{
Get_EB (Name, "Name");
Get_EB (Size, "Size");
//Detection of 0-sized Segment expected to be -1-sized (unlimited)
if (Name==Elements::Segment && Size==0)
{
Param_Info1("Incoherent, changed to unlimited");
Size=0xFFFFFFFFFFFFFFLL; //Unlimited
Fill(Stream_General, 0, "SegmentSizeIsZero", "Yes");
#if MEDIAINFO_FIXITY
if (Config->TryToFix_Get())
{
size_t Pos=(size_t)(Element_Offset-1);
while (!Buffer[Buffer_Offset+Pos])
Pos--;
size_t ToWrite_Size=Element_Offset-Pos;
if (ToWrite_Size<=8)
{
int8u ToWrite[8];
int64u2BigEndian(ToWrite, ((int64u)-1)>>(ToWrite_Size-1));
FixFile(File_Offset+Buffer_Offset+Pos, ToWrite, ToWrite_Size)?Param_Info1("Fixed"):Param_Info1("Not fixed");
}
}
#endif //MEDIAINFO_FIXITY
}
//Filling
Header_Fill_Code(Name, Ztring().From_Number(Name, 16));
Header_Fill_Size(Element_Offset+Size);
}
if ((Name==Elements::Segment_Cluster_BlockGroup_Block || Name==Elements::Segment_Cluster_SimpleBlock) && Buffer_Offset+Element_Offset+Size>Buffer_Size && File_Buffer_Size_Hint_Pointer)
{
int64u Buffer_Size_Target = (size_t)(Buffer_Offset + Element_Offset + Size - Buffer_Size + Element_Offset); //+Element_Offset for next packet header
if (Buffer_Size_Target<128 * 1024)
Buffer_Size_Target = 128 * 1024;
(*File_Buffer_Size_Hint_Pointer) = (size_t)Buffer_Size_Target;
Element_WaitForMoreData();
return;
}
//Incoherencies
if (Element_Offset+Size>Element_TotalSize_Get())
{
Param_Error("TRUNCATED-ELEMENT:1");
if (Element_Level<=2)
Fill(Stream_General, 0, "IsTruncated", "Yes");
}
//Should we parse Cluster?
if (Element_Level==3 && Name==Elements::Segment_Cluster && !Segment_Tracks_Count)
{
//Jumping
for (size_t Pos=0; Pos<Segment_Seeks.size(); Pos++)
if (Segment_Seeks[Pos].SeekID==Elements::Segment_Tracks)
{
Fill(Stream_General, 0, General_IsStreamable, "No");
Element_DoNotShow();
IsParsingSegmentTrack_SeekBackTo=File_Offset+Buffer_Offset;
JumpTo(Segment_Seeks[Pos].SeekPosition);
break;
}
if (File_GoTo==(int64u)-1)
JumpTo(Segment_Offset_End);
return;
}
//Is Tracks already parsed?
if (Element_Level==3 && Name==Elements::Segment_Tracks && SegmentTrack_Offset_End==File_Offset+Buffer_Offset+Element_Offset+Size)
{
//This element was already parsed, skipping it
JumpTo(SegmentTrack_Offset_End);
Element_DoNotShow();
SegmentTrack_Offset_End=0;
return;
}
}
//---------------------------------------------------------------------------
void File_Mk::Data_Parse()
{
#define LIS2(_ATOM, _NAME) \
case Elements::_ATOM : \
if (Level==Element_Level) \
{ \
Element_Name(_NAME); \
_ATOM(); \
Element_ThisIsAList(); \
} \
#define ATO2(_ATOM, _NAME) \
case Elements::_ATOM : \
if (Level==Element_Level) \
{ \
if (Element_IsComplete_Get()) \
{ \
Element_Name(_NAME); \
_ATOM(); \
} \
else \
{ \
Element_WaitForMoreData(); \
return; \
} \
} \
break; \
#define ATOM_END_MK \
ATOM(Zero) \
ATOM(CRC32) \
ATOM(Void) \
ATOM_END
//Parsing
DATA_BEGIN
LIS2(Ebml, "EBML")
ATOM_BEGIN
ATO2(Ebml_Version, "EBMLVersion")
ATO2(Ebml_ReadVersion, "EBMLReadVersion")
ATO2(Ebml_MaxIDLength, "EBMLMaxIDLength")
ATO2(Ebml_MaxSizeLength, "EBMLMaxSizeLength")
ATO2(Ebml_DocType, "DocType")
ATO2(Ebml_DocTypeVersion, "DocTypeVersion")
ATO2(Ebml_DocTypeReadVersion, "DocTypeReadVersion")
ATOM_END_MK
#if MEDIAINFO_TRACE
LIS2(RawcookedBlock, "RawcookedBlock")
ATOM_BEGIN
ATO2(RawcookedBlock_AfterData, "AfterData")
ATO2(RawcookedBlock_BeforeData, "BeforeData")
ATO2(RawcookedBlock_FileName, "FileName")
ATO2(RawcookedBlock_FileHash, "FileHash")
ATO2(RawcookedBlock_MaskAdditionBeforeData, "MaskAdditionBeforeData")
ATO2(RawcookedBlock_MaskAdditionAfterData, "MaskAdditionAfterData")
ATO2(RawcookedBlock_MaskAdditionFileName, "MaskAdditionFileName")
ATOM_END_MK
LIS2(RawcookedSegment, "RawcookedSegment")
ATOM_BEGIN
ATO2(RawcookedSegment_LibraryName, "LibraryName")
ATO2(RawcookedSegment_LibraryVersion, "LibraryVersion")
ATOM_END_MK
LIS2(RawcookedTrack, "RawcookedTrack")
ATOM_BEGIN
ATO2(RawcookedTrack_BeforeData, "BeforeData")
ATO2(RawcookedTrack_AfterData, "AfterData")
ATO2(RawcookedTrack_FileName, "FileName")
ATO2(RawcookedTrack_FileHash, "FileHash")
ATO2(RawcookedTrack_MaskBaseAfterData, "MaskBaseAfterData")
ATO2(RawcookedTrack_MaskBaseBeforeData, "MaskBaseBeforeData")
ATO2(RawcookedTrack_MaskBaseFileName, "MaskBaseFileName")
ATOM_END_MK
#endif //MEDIAINFO_TRACE
LIS2(Segment, "Segment")
ATOM_BEGIN
LIS2(Segment_SeekHead, "SeekHead")
ATOM_BEGIN
LIS2(Segment_SeekHead_Seek, "Seek")
ATOM_BEGIN
ATO2(Segment_SeekHead_Seek_SeekID, "SeekID")
ATO2(Segment_SeekHead_Seek_SeekPosition, "SeekPosition")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Info, "Info")
ATOM_BEGIN
ATO2(Segment_Info_SegmentUID, "SegmentUID")
ATO2(Segment_Info_SegmentFilename, "SegmentFilename")
ATO2(Segment_Info_PrevUID, "PrevUID")
ATO2(Segment_Info_PrevFilename, "PrevFilename")
ATO2(Segment_Info_NextUID, "NextUID")
ATO2(Segment_Info_NextFilename, "NextFilename")
ATO2(Segment_Info_SegmentFamily, "SegmentFamily")
LIS2(Segment_Info_ChapterTranslate, "ChapterTranslate")
ATOM_BEGIN
ATO2(Segment_Info_ChapterTranslate_ChapterTranslateEditionUID, "ChapterTranslateEditionUID")
ATO2(Segment_Info_ChapterTranslate_ChapterTranslateCodec, "ChapterTranslateCodec")
ATO2(Segment_Info_ChapterTranslate_ChapterTranslateID, "ChapterTranslateID")
ATOM_END_MK
ATO2(Segment_Info_TimecodeScale, "TimecodeScale")
ATO2(Segment_Info_Duration, "Duration")
ATO2(Segment_Info_DateUTC, "DateUTC")
ATO2(Segment_Info_Title, "Title")
ATO2(Segment_Info_MuxingApp, "MuxingApp")
ATO2(Segment_Info_WritingApp, "WritingApp")
ATOM_END_MK
LIS2(Segment_Cluster, "Cluster")
ATOM_BEGIN
ATO2(Segment_Cluster_Timecode, "Timecode")
LIS2(Segment_Cluster_SilentTracks, "SilentTracks")
ATOM_BEGIN
ATO2(Segment_Cluster_SilentTracks_SilentTrackNumber, "SilentTrackNumber")
ATOM_END_MK
ATO2(Segment_Cluster_Position, "Position")
ATO2(Segment_Cluster_PrevSize, "PrevSize")
LIS2(Segment_Cluster_SimpleBlock, "SimpleBlock")
ATOM_BEGIN
ATO2(Segment_Cluster_BlockGroup_Block_Lace, "Lace")
ATOM_END_MK
LIS2(Segment_Cluster_BlockGroup, "BlockGroup")
ATOM_BEGIN
LIS2(Segment_Cluster_BlockGroup_Block, "Block")
ATOM_BEGIN
ATO2(Segment_Cluster_BlockGroup_Block_Lace, "Lace")
ATOM_END_MK
ATO2(Segment_Cluster_BlockGroup_BlockVirtual, "BlockVirtual")
LIS2(Segment_Cluster_BlockGroup_BlockAdditions, "BlockAdditions")
ATOM_BEGIN
LIS2(Segment_Cluster_BlockGroup_BlockAdditions_BlockMore, "BlockMore")
ATOM_BEGIN
ATO2(Segment_Cluster_BlockGroup_BlockAdditions_BlockMore_BlockAddID, "BlockAddID")
ATO2(Segment_Cluster_BlockGroup_BlockAdditions_BlockMore_BlockAdditional, "BlockAdditional")
ATOM_END_MK
ATOM_END_MK
ATO2(Segment_Cluster_BlockGroup_BlockDuration, "BlockDuration")
ATO2(Segment_Cluster_BlockGroup_ReferencePriority, "ReferencePriority")
ATO2(Segment_Cluster_BlockGroup_ReferenceBlock, "ReferenceBlock")
ATO2(Segment_Cluster_BlockGroup_ReferenceVirtual, "ReferenceVirtual")
ATO2(Segment_Cluster_BlockGroup_CodecState, "CodecState")
ATO2(Segment_Cluster_BlockGroup_DiscardPadding, "DiscardPadding")
LIS2(Segment_Cluster_BlockGroup_Slices, "Slices")
ATOM_BEGIN
LIS2(Segment_Cluster_BlockGroup_Slices_TimeSlice, "TimeSlice")
ATOM_BEGIN
ATO2(Segment_Cluster_BlockGroup_Slices_TimeSlice_LaceNumber, "LaceNumber")
ATO2(Segment_Cluster_BlockGroup_Slices_TimeSlice_FrameNumber, "FrameNumber")
ATO2(Segment_Cluster_BlockGroup_Slices_TimeSlice_BlockAdditionID, "BlockAdditionID")
ATO2(Segment_Cluster_BlockGroup_Slices_TimeSlice_Delay, "Delay")
ATO2(Segment_Cluster_BlockGroup_Slices_TimeSlice_SliceDuration, "SliceDuration")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Cluster_BlockGroup_ReferenceFrame, "ReferenceFrame")
ATOM_BEGIN
ATO2(Segment_Cluster_BlockGroup_ReferenceFrame_ReferenceOffset, "ReferenceOffset")
ATO2(Segment_Cluster_BlockGroup_ReferenceFrame_ReferenceTimeCode, "ReferenceTimeCode")
ATOM_END_MK
ATOM_END_MK
ATO2(Segment_Cluster_EncryptedBlock, "EncryptedBlock")
ATOM_END_MK
LIS2(Segment_Tracks, "Tracks")
ATOM_BEGIN
LIS2(Segment_Tracks_TrackEntry, "TrackEntry")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_TrackNumber, "TrackNumber")
ATO2(Segment_Tracks_TrackEntry_TrackUID, "TrackUID")
ATO2(Segment_Tracks_TrackEntry_TrackType, "TrackType")
ATO2(Segment_Tracks_TrackEntry_FlagEnabled, "FlagEnabled")
ATO2(Segment_Tracks_TrackEntry_FlagDefault, "FlagDefault")
ATO2(Segment_Tracks_TrackEntry_FlagForced, "FlagForced")
ATO2(Segment_Tracks_TrackEntry_FlagLacing, "FlagLacing")
ATO2(Segment_Tracks_TrackEntry_MinCache, "MinCache")
ATO2(Segment_Tracks_TrackEntry_MaxCache, "MaxCache")
ATO2(Segment_Tracks_TrackEntry_DefaultDuration, "DefaultDuration")
ATO2(Segment_Tracks_TrackEntry_DefaultDecodedFieldDuration, "DefaultDecodedFieldDuration")
ATO2(Segment_Tracks_TrackEntry_TrackTimecodeScale, "TrackTimecodeScale")
ATO2(Segment_Tracks_TrackEntry_TrackOffset, "TrackOffset")
ATO2(Segment_Tracks_TrackEntry_MaxBlockAdditionID, "MaxBlockAdditionID")
ATO2(Segment_Tracks_TrackEntry_Name, "Name")
ATO2(Segment_Tracks_TrackEntry_Language, "Language")
ATO2(Segment_Tracks_TrackEntry_LanguageIETF, "LanguageIETF")
ATO2(Segment_Tracks_TrackEntry_CodecID, "CodecID")
ATO2(Segment_Tracks_TrackEntry_CodecPrivate, "CodecPrivate")
ATO2(Segment_Tracks_TrackEntry_CodecName, "CodecName")
ATO2(Segment_Tracks_TrackEntry_AttachmentLink, "AttachmentLink")
ATO2(Segment_Tracks_TrackEntry_CodecSettings, "CodecSettings")
ATO2(Segment_Tracks_TrackEntry_CodecInfoURL, "CodecInfoURL")
ATO2(Segment_Tracks_TrackEntry_CodecDownloadURL, "CodecDownloadURL")
ATO2(Segment_Tracks_TrackEntry_CodecDecodeAll, "CodecDecodeAll")
ATO2(Segment_Tracks_TrackEntry_TrackOverlay, "TrackOverlay")
ATO2(Segment_Tracks_TrackEntry_CodecDelay, "CodecDelay")
ATO2(Segment_Tracks_TrackEntry_SeekPreRoll, "SeekPreRoll")
LIS2(Segment_Tracks_TrackEntry_TrackTranslate, "TrackTranslate")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateEditionUID, "TrackTranslateEditionUID")
ATO2(Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateCodec, "TrackTranslateCodec")
ATO2(Segment_Tracks_TrackEntry_TrackTranslate_TrackTranslateTrackID, "TrackTranslateTrackID")
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_Video, "Video")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_Video_FlagInterlaced, "FlagInterlaced")
ATO2(Segment_Tracks_TrackEntry_Video_FieldOrder, "FieldOrder")
ATO2(Segment_Tracks_TrackEntry_Video_StereoMode, "StereoMode")
ATO2(Segment_Tracks_TrackEntry_Video_AlphaMode, "AlphaMode")
ATO2(Segment_Tracks_TrackEntry_Video_OldStereoMode, "OldStereoMode")
ATO2(Segment_Tracks_TrackEntry_Video_PixelWidth, "PixelWidth")
ATO2(Segment_Tracks_TrackEntry_Video_PixelHeight, "PixelHeight")
ATO2(Segment_Tracks_TrackEntry_Video_PixelCropBottom, "PixelCropBottom")
ATO2(Segment_Tracks_TrackEntry_Video_PixelCropTop, "PixelCropTop")
ATO2(Segment_Tracks_TrackEntry_Video_PixelCropLeft, "PixelCropLeft")
ATO2(Segment_Tracks_TrackEntry_Video_PixelCropRight, "PixelCropRight")
ATO2(Segment_Tracks_TrackEntry_Video_DisplayWidth, "DisplayWidth")
ATO2(Segment_Tracks_TrackEntry_Video_DisplayHeight, "DisplayHeight")
ATO2(Segment_Tracks_TrackEntry_Video_DisplayUnit, "DisplayUnit")
ATO2(Segment_Tracks_TrackEntry_Video_AspectRatioType, "AspectRatioType")
ATO2(Segment_Tracks_TrackEntry_Video_ColourSpace, "ColourSpace")
ATO2(Segment_Tracks_TrackEntry_Video_GammaValue, "GammaValue")
ATO2(Segment_Tracks_TrackEntry_Video_FrameRate, "FrameRate")
LIS2(Segment_Tracks_TrackEntry_Video_Colour, "Colour")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MatrixCoefficients, "MatrixCoefficients")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_BitsPerChannel, "BitsPerChannel")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_ChromaSubsamplingHorz, "ChromaSubsamplingHorz")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_ChromaSubsamplingVert, "ChromaSubsamplingVert")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_CbSubsamplingHorz, "CbSubsamplingHorz")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_CbSubsamplingVert, "CbSubsamplingVert")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_ChromaSitingHorz, "ChromaSitingHorz")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_ChromaSitingVert, "ChromaSitingVert")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_Range, "Range")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_TransferCharacteristics, "TransferCharacteristics")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_Primaries, "Primaries")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MaxCLL, "MaxCLL")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MaxFALL, "MaxFALL")
LIS2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata, "MasteringMetadata")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryRChromaticityX, "PrimaryRChromaticityX")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryRChromaticityY, "PrimaryRChromaticityY")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryGChromaticityX, "PrimaryGChromaticityX")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryGChromaticityY, "PrimaryGChromaticityY")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryBChromaticityX, "PrimaryBChromaticityX")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_PrimaryBChromaticityY, "PrimaryBChromaticityY")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_WhitePointChromaticityX, "WhitePointChromaticityX")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_WhitePointChromaticityY, "WhitePointChromaticityY")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_LuminanceMax, "LuminanceMax")
ATO2(Segment_Tracks_TrackEntry_Video_Colour_MasteringMetadata_LuminanceMin, "LuminanceMin")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_Video_Projection, "Projection")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_Video_Projection_ProjectionType, "ProjectionType")
ATO2(Segment_Tracks_TrackEntry_Video_Projection_ProjectionPrivate, "ProjectionPrivate")
ATO2(Segment_Tracks_TrackEntry_Video_Projection_ProjectionPoseYaw, "ProjectionPoseYaw")
ATO2(Segment_Tracks_TrackEntry_Video_Projection_ProjectionPosePitch, "ProjectionPosePitch")
ATO2(Segment_Tracks_TrackEntry_Video_Projection_ProjectionPoseRoll, "ProjectionPoseRoll")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_Audio, "Audio")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_Audio_SamplingFrequency, "SamplingFrequency")
ATO2(Segment_Tracks_TrackEntry_Audio_OutputSamplingFrequency, "OutputSamplingFrequency")
ATO2(Segment_Tracks_TrackEntry_Audio_Channels, "Channels")
ATO2(Segment_Tracks_TrackEntry_Audio_ChannelPositions, "ChannelPositions")
ATO2(Segment_Tracks_TrackEntry_Audio_BitDepth, "BitDepth")
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_TrackOperation, "TrackOperation")
ATOM_BEGIN
LIS2(Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes, "TrackCombinePlanes")
ATOM_BEGIN
LIS2(Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane, "TrackPlane")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane_TrackPlaneUID, "TrackPlaneUID")
ATO2(Segment_Tracks_TrackEntry_TrackOperation_TrackCombinePlanes_TrackPlane_TrackPlaneType, "TrackPlaneType")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_TrackOperation_TrackJoinBlocks, "TrackJoinBlocks")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_TrackOperation_TrackJoinBlocks_TrackJoinUID, "TrackJoinUID")
ATOM_END_MK
ATOM_END_MK
ATO2(Segment_Tracks_TrackEntry_TrickTrackUID, "TrickTrackUID")
ATO2(Segment_Tracks_TrackEntry_TrickTrackSegmentUID, "TrickTrackSegmentUID")
ATO2(Segment_Tracks_TrackEntry_TrickTrackFlag, "TrickTrackFlag")
ATO2(Segment_Tracks_TrackEntry_TrickMasterTrackUID, "TrickMasterTrackUID")
ATO2(Segment_Tracks_TrackEntry_TrickMasterTrackSegmentUID, "TrickMasterTrackSegmentUID")
LIS2(Segment_Tracks_TrackEntry_BlockAdditionMapping, "BlockAdditionMapping")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDName, "BlockAddIDName")
ATO2(Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDType, "BlockAddIDType")
ATO2(Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDExtraData, "BlockAddIDExtraData")
ATO2(Segment_Tracks_TrackEntry_BlockAdditionMapping_BlockAddIDValue, "BlockAddIDValue")
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_ContentEncodings, "ContentEncodings")
ATOM_BEGIN
LIS2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding, "ContentEncoding")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingOrder, "ContentEncodingOrder")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingScope, "ContentEncodingScope")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncodingType, "ContentEncodingType")
LIS2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression, "ContentCompression")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompAlgo, "ContentCompAlgo")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompSettings, "ContentCompSettings")
ATOM_END_MK
LIS2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption, "ContentEncryption")
ATOM_BEGIN
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentEncAlgo, "ContentEncAlgo")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentEncKeyID, "ContentEncKeyID")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSignature, "ContentSignature")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigKeyID, "ContentSigKeyID")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigAlgo, "ContentSigAlgo")
ATO2(Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentEncryption_ContentSigHashAlgo, "ContentSigHashAlgo")
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Cues, "Cues")
ATOM_BEGIN
LIS2(Segment_Cues_CuePoint, "CuePoint")
ATOM_BEGIN
ATO2(Segment_Cues_CuePoint_CueTime, "CueTime")
LIS2(Segment_Cues_CuePoint_CueTrackPositions, "CueTrackPositions")
ATOM_BEGIN
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueTrack, "CueTrack")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueClusterPosition, "CueClusterPosition")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueRelativePosition, "CueRelativePosition")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueDuration, "CueDuration")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueBlockNumber, "CueBlockNumber")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueCodecState, "CueCodecState")
LIS2(Segment_Cues_CuePoint_CueTrackPositions_CueReference, "CueReference")
ATOM_BEGIN
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefTime, "CueRefTime")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefCluster, "CueRefCluster")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefNumber, "CueRefNumber")
ATO2(Segment_Cues_CuePoint_CueTrackPositions_CueReference_CueRefCodecState, "CueRefCodecState")
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Attachments, "Attachments")
ATOM_BEGIN
LIS2(Segment_Attachments_AttachedFile, "AttachedFile")
ATOM_BEGIN
ATO2(Segment_Attachments_AttachedFile_FileDescription, "FileDescription")
ATO2(Segment_Attachments_AttachedFile_FileName, "FileName")
ATO2(Segment_Attachments_AttachedFile_FileMimeType, "FileMimeType")
LIS2(Segment_Attachments_AttachedFile_FileData, "FileData") //This is ATOM, but some ATOMs are too big
ATOM_BEGIN
ATOM_END_MK
ATO2(Segment_Attachments_AttachedFile_FileUID, "FileUID")
ATO2(Segment_Attachments_AttachedFile_FileReferral, "FileReferral")
ATO2(Segment_Attachments_AttachedFile_FileUsedStartTime, "FileUsedStartTime")
ATO2(Segment_Attachments_AttachedFile_FileUsedEndTime, "FileUsedEndTime")
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Chapters, "Chapters")
ATOM_BEGIN
LIS2(Segment_Chapters_EditionEntry, "EditionEntry")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_EditionUID, "EditionUID")
ATO2(Segment_Chapters_EditionEntry_EditionFlagHidden, "EditionFlagHidden")
ATO2(Segment_Chapters_EditionEntry_EditionFlagDefault, "EditionFlagDefault")
ATO2(Segment_Chapters_EditionEntry_EditionFlagOrdered, "EditionFlagOrdered")
LIS2(Segment_Chapters_EditionEntry_ChapterAtom, "ChapterAtom")
ATOM_BEGIN
LIS2(Segment_Chapters_EditionEntry_ChapterAtom, "ChapterAtom")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterUID, "ChapterUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterStringUID, "ChapterStringUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeStart, "ChapterTimeStart")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeEnd, "ChapterTimeEnd")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagHidden, "ChapterFlagHidden")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagEnabled, "ChapterFlagEnabled")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentUID, "ChapterSegmentUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentEditionUID, "ChapterSegmentEditionUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterPhysicalEquiv, "ChapterPhysicalEquiv")
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack, "ChapterTrack")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack_ChapterTrackNumber, "ChapterTrackNumber")
ATOM_END_MK
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay, "ChapterDisplay")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapString, "ChapString")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguage, "ChapLanguage")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguageIETF, "ChapLanguageIETF")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapCountry, "ChapCountry")
ATOM_END_MK
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess, "ChapProcess")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCodecID, "ChapProcessCodecID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessPrivate, "ChapProcessPrivate")
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand, "ChapProcessCommand")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessTime, "ChapProcessTime")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessData, "ChapProcessData")
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterUID, "ChapterUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterStringUID, "ChapterStringUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeStart, "ChapterTimeStart")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeEnd, "ChapterTimeEnd")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagHidden, "ChapterFlagHidden")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterFlagEnabled, "ChapterFlagEnabled")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentUID, "ChapterSegmentUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterSegmentEditionUID, "ChapterSegmentEditionUID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterPhysicalEquiv, "ChapterPhysicalEquiv")
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack, "ChapterTrack")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterTrack_ChapterTrackNumber, "ChapterTrackNumber")
ATOM_END_MK
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay, "ChapterDisplay")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapString, "ChapString")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguage, "ChapLanguage")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguageIETF, "ChapLanguageIETF")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapCountry, "ChapCountry")
ATOM_END_MK
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess, "ChapProcess")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCodecID, "ChapProcessCodecID")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessPrivate, "ChapProcessPrivate")
LIS2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand, "ChapProcessCommand")
ATOM_BEGIN
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessTime, "ChapProcessTime")
ATO2(Segment_Chapters_EditionEntry_ChapterAtom_ChapProcess_ChapProcessCommand_ChapProcessData, "ChapProcessData")
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
LIS2(Segment_Tags, "Tags")
ATOM_BEGIN
LIS2(Segment_Tags_Tag, "Tag")
ATOM_BEGIN
LIS2(Segment_Tags_Tag_Targets, "Targets")
ATOM_BEGIN
ATO2(Segment_Tags_Tag_Targets_TargetTypeValue, "TargetTypeValue")
ATO2(Segment_Tags_Tag_Targets_TargetType, "TargetType")
ATO2(Segment_Tags_Tag_Targets_TagTrackUID, "TagTrackUID")
ATO2(Segment_Tags_Tag_Targets_TagEditionUID, "TagEditionUID")
ATO2(Segment_Tags_Tag_Targets_TagChapterUID, "TagChapterUID")
ATO2(Segment_Tags_Tag_Targets_TagAttachmentUID, "TagAttachmentUID")
ATOM_END_MK
LIS2(Segment_Tags_Tag_SimpleTag, "SimpleTag")
ATOM_BEGIN
LIS2(Segment_Tags_Tag_SimpleTag, "SimpleTag")
ATOM_BEGIN
ATO2(Segment_Tags_Tag_SimpleTag_TagName, "TagName")
ATO2(Segment_Tags_Tag_SimpleTag_TagLanguage, "TagLanguage")
ATO2(Segment_Tags_Tag_SimpleTag_TagLanguageIETF, "TagLanguageIETF")
ATO2(Segment_Tags_Tag_SimpleTag_TagDefault, "TagDefault")
ATO2(Segment_Tags_Tag_SimpleTag_TagString, "TagString")
ATO2(Segment_Tags_Tag_SimpleTag_TagBinary, "TagBinary")
ATOM_END_MK
ATO2(Segment_Tags_Tag_SimpleTag_TagName, "TagName")
ATO2(Segment_Tags_Tag_SimpleTag_TagLanguage, "TagLanguage")
ATO2(Segment_Tags_Tag_SimpleTag_TagLanguageIETF, "TagLanguageIETF")
ATO2(Segment_Tags_Tag_SimpleTag_TagDefault, "TagDefault")
ATO2(Segment_Tags_Tag_SimpleTag_TagString, "TagString")
ATO2(Segment_Tags_Tag_SimpleTag_TagBinary, "TagBinary")
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
ATOM_END_MK
DATA_END
if (!Element_IsWaitingForMoreData() && !CRC32Compute.empty())
CRC32_Check();
if (IsParsingSegmentTrack_SeekBackTo && File_Offset+Buffer_Offset+Element_Offset==SegmentTrack_Offset_End) //TODO: implement check at end of an element
{
while (Element_Level>(Element_Offset==Element_Size?2:1))
Element_End0();
GoTo(IsParsingSegmentTrack_SeekBackTo);
IsParsingSegmentTrack_SeekBackTo=0;
}
}
//***************************************************************************
// Elements
//***************************************************************************
//---------------------------------------------------------------------------
void File_Mk::Zero()
{
Element_Name("Junk");
Skip_XX(Element_Size, "Junk");
}
//---------------------------------------------------------------------------
void File_Mk::CRC32()
{
Element_Name("CRC-32");
//Parsing
if (Element_Size!=4)
UInteger_Info(); //Something is wrong, 4-byte integer is expected
else
{
if (CRC32Compute.empty())
Fill(Stream_General, 0, "ErrorDetectionType", Element_Level==3?"Per level 1":"Custom", Unlimited, true, true);
if (CRC32Compute.size()<Element_Level)
CRC32Compute.resize(Element_Level);
Get_L4(CRC32Compute[Element_Level-1].Expected, "Value");
{
Param_Info1(__T("Not tested ")+Ztring::ToZtring(Element_Level-1)+__T(' ')+Ztring::ToZtring(CRC32Compute[Element_Level-1].Expected));
CRC32Compute[Element_Level-1].Computed=0xFFFFFFFF;
CRC32Compute[Element_Level-1].Pos = File_Offset + Buffer_Offset;
CRC32Compute[Element_Level-1].From = File_Offset + Buffer_Offset + Element_Size;
CRC32Compute[Element_Level-1].UpTo = File_Offset + Buffer_Offset + Element_TotalSize_Get(1);
}
}
}
//---------------------------------------------------------------------------
void File_Mk::Void()
{
Element_Name("Void");
//Parsing
UInteger_Info();
}
//---------------------------------------------------------------------------
void File_Mk::Ebml_ReadVersion()
{
//Parsing
UInteger_Info();
}
//---------------------------------------------------------------------------
void File_Mk::Ebml_MaxSizeLength()
{
//Parsing
int64u Value = UInteger_Get();
//Filling
FILLING_BEGIN();
if (Value > 8)
Value = 8; //Not expected, considerating it as if it is 8 for the moment
InvalidByteMax = (int8u)((1 << (8-Value))-1);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Ebml_DocType()
{
//Parsing
Ztring Data=String_Get();
//Filling
FILLING_BEGIN();
if (Data==__T("matroska"))
{
Accept("Matroska");
Fill(Stream_General, 0, General_Format, "Matroska");
Buffer_MaximumSize = 64 * 1024 * 1024; //Testing with huge lossless 4K frames
File_Buffer_Size_Hint_Pointer = Config->File_Buffer_Size_Hint_Pointer_Get();
}
else if (Data==__T("webm"))
{
Accept("Matroska");
Fill(Stream_General, 0, General_Format, "WebM");
}
else if (Data==__T("rawcooked"))
{
Accept("RAWcooked");
Fill(Stream_General, 0, General_Format, "RAWcooked");
}
else
{
Reject("Matroska");
return;
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Ebml_DocTypeVersion()
{
//Parsing
Format_Version=UInteger_Get();
//Filling
FILLING_BEGIN();
Fill(Stream_General, 0, General_Format_Version, __T("Version ")+Ztring::ToZtring(Format_Version));
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Ebml_DocTypeReadVersion()
{
//Parsing
int64u UInteger=UInteger_Get();
//Filling
FILLING_BEGIN();
if (UInteger!=Format_Version && MediaInfoLib::Config.LegacyStreamDisplay_Get())
Fill(Stream_General, 0, General_Format_Version, __T("Version ")+Ztring::ToZtring(UInteger)); //Adding compatible version for info about legacy decoders
FILLING_END();
}
//---------------------------------------------------------------------------
#if MEDIAINFO_TRACE
bool File_Mk::Rawcooked_Compressed_Start(rawcookedtrack::mask* Mask, bool UseMask)
{
if (!Trace_Activated) // Currently used only for trace
{
int64u Size;
Get_EB(Size, "Size");
Skip_XX(Element_Size-Element_Offset, "Data");
return false;
}
Get_EB(Rawcooked_Compressed_Save_Element_Size, "Size");
if (Rawcooked_Compressed_Save_Element_Size && Element_Offset!=Element_Size)
{
int64u Element_Offset_Save=Element_Offset;
Skip_XX(Element_Size-Element_Offset, "Compressed data");
Element_Offset=Element_Offset_Save;
//Sizes
unsigned long Source_Size=(unsigned long)(Element_Size-Element_Offset);
unsigned long Dest_Size=(unsigned long)Rawcooked_Compressed_Save_Element_Size;
//Uncompressing
int8u* Dest=new int8u[(Mask && UseMask && Mask->Size>Dest_Size)?Mask->Size:Dest_Size];
if (uncompress((Bytef*)Dest, &Dest_Size, (const Bytef*)Buffer+Buffer_Offset+(size_t)Element_Offset, Source_Size)<0)
{
delete[] Dest; //Dest=NULL;
Param_Info("Problem during the decompression");
return false;
}
//Store or apply mask
if (Mask)
{
if (UseMask && Mask->Buffer)
{
size_t i=0;
for (; i<Dest_Size && i<Mask->Size; i++)
Dest[i]+=Mask->Buffer[i];
for (; i<Mask->Size; i++)
Dest[i]=Mask->Buffer[i];
}
if (!UseMask)
{
Mask->Buffer=Dest;
Mask->Size=Dest_Size;
}
}
File_Offset+=Buffer_Offset+Element_Offset;
Rawcooked_Compressed_Save_Buffer_Offset=Buffer_Offset;
Buffer_Offset=0;
Rawcooked_Compressed_Save_Buffer=Buffer;
Buffer=Dest;
Rawcooked_Compressed_Save_Element_Size=Element_Size;
Element_Size=Dest_Size;
Rawcooked_Compressed_Save_Element_Offset=Element_Offset;
Element_Offset=0;
}
else
{
Rawcooked_Compressed_Save_Buffer=Buffer;
}
return true;
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_Compressed_End(rawcookedtrack::mask* Mask, bool UseMask)
{
if (Buffer==Rawcooked_Compressed_Save_Buffer)
return; // No buffer created, nothing to do
if (!Mask || !Mask->Buffer || UseMask)
delete[] Buffer; //Buffer=NULL;
Buffer=Rawcooked_Compressed_Save_Buffer;
Buffer_Offset=Rawcooked_Compressed_Save_Buffer_Offset;
Element_Size=Rawcooked_Compressed_Save_Element_Size;
Element_Offset=Element_Size;
File_Offset-=Buffer_Offset+Rawcooked_Compressed_Save_Element_Offset;
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_BeforeData()
{
//Parsing
MediaInfo_Internal MI;
MI.Option(__T("File_IsReferenced"), __T("1"));
MI.Option(__T("File_KeepInfo"), __T("1"));
MI.Open_Buffer_Init(Element_Size-Element_Offset);
MI.Open_Buffer_Continue(Buffer+Buffer_Offset+(size_t)Element_Offset, (size_t)(Element_Size-Element_Offset));
MI.Open_Buffer_Finalize();
Element[Element_Level].TraceNode.TakeChilrenFrom(MI.Info->Element[0].TraceNode);
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_BeforeData(bool HasMask, bool UseMask)
{
if (!Rawcooked_Compressed_Start(HasMask?&RawcookedTrack_Data.MaskBaseBeforeData:NULL, UseMask))
return;
Rawcooked_BeforeData();
Rawcooked_Compressed_End(HasMask?&RawcookedTrack_Data.MaskBaseBeforeData:NULL, UseMask);
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_AfterData()
{
//Parsing
Skip_XX(Element_Size-Element_Offset, "Data");
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_AfterData(bool, bool UseMask)
{
if (!Rawcooked_Compressed_Start(NULL, UseMask))
return;
Rawcooked_AfterData();
Rawcooked_Compressed_End(NULL, UseMask);
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_FileName()
{
//Parsing
Skip_String(Element_Size-Element_Offset, "Data");
}
//---------------------------------------------------------------------------
void File_Mk::Rawcooked_FileName(bool HasMask, bool UseMask)
{
if (!Rawcooked_Compressed_Start(HasMask?&RawcookedTrack_Data.MaskBaseFileName:NULL, UseMask))
return;
Rawcooked_FileName();
Rawcooked_Compressed_End(HasMask?&RawcookedTrack_Data.MaskBaseFileName:NULL, UseMask);
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedBlock()
{
if (Trace_Activated)
{
Element_Info1(Ztring().From_Number(RawcookedTrack_Data.FramePos));
RawcookedTrack_Data.FramePos++;
if (RawcookedTrack_Data.FramePos>10)
{
Trace_Activated_Save=true;
Trace_Activated=false;
Skip_XX(Element_Size, "");
}
}
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedBlock_FileHash()
{
//Parsing
int64u Type;
Get_EB(Type, "Type");
switch (Type)
{
case 0 : Param_Info("MD5"); Skip_Hexa(16, "Data"); break;
default: Skip_XX(Element_Size-Element_Offset, "Data");
}
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedSegment()
{
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedSegment_LibraryName()
{
Skip_Local(Element_Size, "LibraryName");
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedSegment_LibraryVersion()
{
Skip_Local(Element_Size, "LibraryVersion");
}
//---------------------------------------------------------------------------
void File_Mk::RawcookedTrack()
{
if (RawcookedTrack_Data.FramePos>10)
{
Element_Level--;
Param("RawcookedBlock", Ztring::ToZtring(RawcookedTrack_Data.FramePos-10)+__T(" other blocks"));
Element_Level++;
}
RawcookedTrack_Data=rawcookedtrack();
}
#endif //MEDIAINFO_TRACE
//---------------------------------------------------------------------------
void File_Mk::Segment()
{
if (!Status[IsAccepted])
{
Accept("Matroska");
Fill(Stream_General, 0, General_Format, "Matroska"); //Default is Matroska
}
Segment_Offset_Begin=File_Offset+Buffer_Offset;
Segment_Offset_End=File_Offset+Buffer_Offset+Element_TotalSize_Get();
#if MEDIAINFO_TRACE
Trace_Segment_Cluster_Count=0;
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Attachments_AttachedFile()
{
AttachedFile_FileName.clear();
AttachedFile_FileMimeType.clear();
AttachedFile_FileDescription.clear();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Attachments_AttachedFile_FileDescription()
{
//Parsing
Ztring Data=UTF8_Get();
AttachedFile_FileDescription=Data.To_UTF8();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Attachments_AttachedFile_FileName()
{
//Parsing
Ztring Data=UTF8_Get();
Fill(Stream_General, 0, "Attachments", Data);
//Cover is in the first file which name contains "cover"
if (!CoverIsSetFromAttachment && Data.MakeLowerCase().find(__T("cover")) != string::npos)
CurrentAttachmentIsCover=true;
AttachedFile_FileName=Data.To_UTF8();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Attachments_AttachedFile_FileMimeType()
{
//Parsing
Ztring Data=String_Get();
AttachedFile_FileMimeType=Data.To_UTF8();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Attachments_AttachedFile_FileData()
{
Element_Name("FileData");
bool Attachments_Demux=true;
//Parsing
if ((Attachments_Demux || !CoverIsSetFromAttachment && CurrentAttachmentIsCover) && Element_TotalSize_Get()<=16*1024*1024) //TODO: option for setting the acceptable maximum size of the attachment
{
if (!Element_IsComplete_Get())
{
Element_WaitForMoreData();
return;
}
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
//Parsing
MediaInfo_Internal MI;
MI.Option(__T("File_IsReferenced"), __T("1"));
MI.Option(__T("File_KeepInfo"), __T("1"));
MI.Open_Buffer_Init(Element_Size-Element_Offset);
MI.Open_Buffer_Continue(Buffer+Buffer_Offset+(size_t)Element_Offset, (size_t)(Element_Size-Element_Offset));
MI.Open_Buffer_Finalize();
Element[Element_Level].TraceNode.TakeChilrenFrom(MI.Info->Element[0].TraceNode);
}
#endif //MEDIAINFO_TRACE
std::string Data_Raw;
Peek_String(Element_TotalSize_Get(), Data_Raw);
if (!CoverIsSetFromAttachment && CurrentAttachmentIsCover)
{
//Filling
#if MEDIAINFO_ADVANCED
if (MediaInfoLib::Config.Flags1_Get(Flags_Cover_Data_base64))
{
std::string Data_Base64(Base64::encode(Data_Raw));
Fill(Stream_General, 0, General_Cover_Data, Data_Base64);
}
#endif //MEDIAINFO_ADVANCED
Fill(Stream_General, 0, General_Cover, "Yes");
CoverIsSetFromAttachment=true;
}
#if MEDIAINFO_EVENTS
if (Attachments_Demux)
{
EVENT_BEGIN(Global, AttachedFile, 0)
Event.Content_Size=Data_Raw.size();
Event.Content=(const int8u*)Data_Raw.c_str();
Event.Flags=0;
Event.Name=AttachedFile_FileName.c_str();
Event.MimeType=AttachedFile_FileMimeType.c_str();
Event.Description=AttachedFile_FileDescription.c_str();
EVENT_END()
}
#endif //MEDIAINFO_EVENTS
}
Element_Offset=Element_TotalSize_Get();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry()
{
//Filling
EditionEntries_Pos=EditionEntries.size();
EditionEntries.resize(EditionEntries_Pos+1);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry_ChapterAtom()
{
//Filling
ChapterAtoms_Pos=EditionEntries[EditionEntries_Pos].ChapterAtoms.size();
EditionEntries[EditionEntries_Pos].ChapterAtoms.resize(ChapterAtoms_Pos+1);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay()
{
//Filling
ChapterDisplays_Pos=EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays.size();
EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays.resize(ChapterDisplays_Pos+1);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapLanguage()
{
//Parsing
Ztring Data=String_Get();
FILLING_BEGIN();
EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays[ChapterDisplays_Pos].ChapLanguage=Data;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry_ChapterAtom_ChapterDisplay_ChapString()
{
//Parsing
Ztring Data=UTF8_Get();
FILLING_BEGIN();
EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterDisplays[ChapterDisplays_Pos].ChapString=Data;
//if (TimecodeScale!=0 && ChapterTimeStart!=(int64u)-1)
// Fill(StreamKind_Last, StreamPos_Last, Ztring::ToZtring(Chapter_Pos).To_Local().c_str(), Ztring().Duration_From_Milliseconds(ChapterTimeStart/TimecodeScale)+__T(" - ")+ChapterString, true);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Chapters_EditionEntry_ChapterAtom_ChapterTimeStart()
{
//Parsing
int64u Data=UInteger_Get();
FILLING_BEGIN();
EditionEntries[EditionEntries_Pos].ChapterAtoms[ChapterAtoms_Pos].ChapterTimeStart=Data;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster()
{
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
if (Trace_Segment_Cluster_Count<MaxCountSameElementInTrace)
Trace_Segment_Cluster_Count++;
else
Element_Set_Remove_Children_IfNoErrors();
}
#endif // MEDIAINFO_TRACE
//For each stream
if (!Segment_Cluster_Count)
{
for (std::map<int64u, stream>::iterator Temp=Stream.begin(); Temp!=Stream.end(); ++Temp)
{
if (!Temp->second.Parser)
Temp->second.Searching_Payload=false;
if (Temp->second.StreamKind==Stream_Video || Temp->second.StreamKind==Stream_Audio)
Temp->second.Searching_TimeStamp_Start=true;
if (Temp->second.StreamKind==Stream_Video)
Temp->second.Searching_TimeStamps=true;
if (Temp->second.Searching_Payload
|| Temp->second.Searching_TimeStamp_Start
|| Temp->second.Searching_TimeStamps)
Stream_Count++;
//Specific cases
#ifdef MEDIAINFO_AAC_YES
if (Retrieve(Temp->second.StreamKind, Temp->second.StreamPos, Audio_CodecID).find(__T("A_AAC/"))==0)
((File_Aac*)Stream[Temp->first].Parser)->Mode=File_Aac::Mode_raw_data_block; //In case AudioSpecificConfig is not present
#endif //MEDIAINFO_AAC_YES
}
}
Segment_Cluster_Count++;
Segment_Cluster_TimeCode_Value=0; //Default
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_BlockGroup()
{
Segment_Cluster_BlockGroup_BlockDuration_Value=(int64u)-1;
Segment_Cluster_BlockGroup_BlockDuration_TrackNumber=(int64u)-1;
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_BlockGroup_Block()
{
if (!Element_IsComplete_Get())
{
Element_WaitForMoreData();
return;
}
//Parsing
Get_EB (TrackNumber, "TrackNumber"); Element_Info1(TrackNumber);
//Finished?
stream& streamItem = Stream[TrackNumber];
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
if (streamItem.Trace_Segment_Cluster_Block_Count<=MaxCountSameElementInTrace)
streamItem.Trace_Segment_Cluster_Block_Count++;
//else
// Element_Set_Remove_Children_IfNoErrors();
}
#endif // MEDIAINFO_TRACE
streamItem.PacketCount++;
if (streamItem.Searching_Payload || streamItem.Searching_TimeStamps || streamItem.Searching_TimeStamp_Start)
{
//Parsing
int16u TimeCodeU;
Get_B2 (TimeCodeU, "TimeCode"); // Should be signed, but we don't have signed integer reader
int16s TimeCode = (int16s)TimeCodeU;
Element_Info1(TimeCodeU);
#if MEDIAINFO_DEMUX
FrameInfo.PTS=(Segment_Cluster_TimeCode_Value+TimeCode)*1000000;
#endif //MEDIAINFO_DEMUX
FILLING_BEGIN();
if (Segment_Cluster_TimeCode_Value+TimeCode<streamItem.TimeCode_Start) //Does not work well: streamItem.Searching_TimeStamp_Start)
{
FILLING_BEGIN();
streamItem.TimeCode_Start=Segment_Cluster_TimeCode_Value+TimeCode;
//streamItem.Searching_TimeStamp_Start=false;
FILLING_END();
}
if (streamItem.Searching_TimeStamps)
{
streamItem.TimeCodes.push_back(Segment_Cluster_TimeCode_Value+TimeCode);
if (streamItem.TimeCodes.size()>128)
streamItem.Searching_TimeStamps=false;
}
if (Segment_Cluster_BlockGroup_BlockDuration_Value!=(int64u)-1)
{
streamItem.Segment_Cluster_BlockGroup_BlockDuration_Counts[Segment_Cluster_BlockGroup_BlockDuration_Value]++;
Segment_Cluster_BlockGroup_BlockDuration_Value=(int64u)-1;
}
FILLING_END();
if (streamItem.Searching_Payload)
{
int32u Lacing;
Element_Begin1("Flags");
BS_Begin();
Skip_BS(1, "KeyFrame");
Skip_BS(3, "Reserved");
Skip_BS(1, "Invisible");
Get_BS (2, Lacing, "Lacing");
Skip_BS(1, "Discardable");
BS_End();
Element_End0();
if (Lacing>0)
{
Element_Begin1("Lacing");
int8u FrameCountMinus1;
Get_B1(FrameCountMinus1, "Frame count minus 1");
switch (Lacing)
{
case 1 : //Xiph lacing
{
int64u Element_Offset_Virtual=0;
for (int8u Pos=0; Pos<FrameCountMinus1; Pos++)
{
int32u Size=0;
int8u Size8;
do
{
Get_B1 (Size8, "Size");
Size+=Size8;
}
while (Size8==0xFF);
Param_Info1(Size);
Element_Offset_Virtual+=Size;
Laces.push_back(Size);
}
if (Element_Offset+Element_Offset_Virtual>Element_Size)