Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
4939 lines (4526 sloc) 219 KB
/* 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_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_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;
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());
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);
}
}
if (Temp->second.Parser)
{
//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 (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);
}
}
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);
//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_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_Size<=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_Size;
Element_ThisIsAList();
}
//---------------------------------------------------------------------------
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)
{
//Problem
Laces.clear();
Laces.push_back(Element_Size - Element_Offset);
}
else
Laces.push_back(Element_Size-Element_Offset-Element_Offset_Virtual); //last lace
}
break;
case 2 : //Fixed-size lacing - No more data
{
int64u Size=(Element_Size-Element_Offset)/(FrameCountMinus1+1);
Laces.resize(FrameCountMinus1+1, Size);
}
break;
case 3 : //EBML lacing
{
int64u Element_Offset_Virtual=0, Size;
Get_EB (Size, "Size");
Laces.push_back(Size);
Element_Offset_Virtual+=Size;
for (int8u Pos=1; Pos<FrameCountMinus1; Pos++)
{
int64s Diff;
Get_ES (Diff, "Difference");
Size+=Diff; Param_Info1(Size);
Element_Offset_Virtual+=Size;
Laces.push_back(Size);
}
if (Element_Offset+Element_Offset_Virtual>Element_Size)
{
//Problem
Laces.clear();
Laces.push_back(Element_Size - Element_Offset);
}
else
Laces.push_back(Element_Size-Element_Offset-Element_Offset_Virtual); Param_Info1(Size); //last lace
}
break;
default : ; //Should never be here
}
Element_End0();
}
else
Laces.push_back(Element_Size-Element_Offset);
}
else
{
Laces.push_back(Element_Size-Element_Offset);
}
}
else
{
Laces.push_back(Element_Size-Element_Offset);
}
if (Laces.size()==1)
{
Element_Begin1("Data");
Segment_Cluster_BlockGroup_Block_Lace();
Element_End0();
}
#if MEDIAINFO_TRACE
if (Trace_Activated && (Trace_Segment_Cluster_Count>MaxCountSameElementInTrace || streamItem.Trace_Segment_Cluster_Block_Count>MaxCountSameElementInTrace))
Element_Children_IfNoErrors();
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_BlockGroup_Block_Lace()
{
stream& streamItem=Stream[TrackNumber];
//Content compression
if (streamItem.ContentCompAlgo!=(int32u)-1 && streamItem.ContentCompAlgo!=3)
streamItem.Searching_Payload=false; //Unsupported
if (streamItem.Searching_Payload && streamItem.Parser)
{
Element_Parser(streamItem.Parser->ParserName.c_str());
Element_Code=TrackNumber;
//Content compression
/* Old method, does not support all needs e.g. 1 complete frame per demux packet
if (streamItem.ContentCompAlgo==3) //Header Stripping
{
Element_Offset-=(size_t)streamItem.ContentCompSettings_Buffer_Size; //This is an extra array, not in the stream
Open_Buffer_Continue(streamItem.Parser, streamItem.ContentCompSettings_Buffer, (size_t)streamItem.ContentCompSettings_Buffer_Size);
Element_Offset+=(size_t)streamItem.ContentCompSettings_Buffer_Size;
Demux(streamItem.ContentCompSettings_Buffer, (size_t)streamItem.ContentCompSettings_Buffer_Size, ContentType_MainStream);
}
*/
int8u* Buffer_Stripping=NULL;
const int8u* Save_Buffer=Buffer;
int64u Save_File_Offset=File_Offset;
size_t Save_Buffer_Offset=Buffer_Offset;
int64u Save_Element_Size=Element_Size;
size_t Save_Element_Offset=(size_t)Element_Offset;
if (streamItem.ContentCompAlgo==3) //Header Stripping
{
Element_Size=streamItem.ContentCompSettings_Buffer_Size+Save_Element_Size-Save_Element_Offset;
File_Offset+=Buffer_Offset+Element_Offset-streamItem.ContentCompSettings_Buffer_Size;
Buffer_Offset=0;
Element_Offset=0;
Buffer_Stripping=new int8u[(size_t)Element_Size];
std::memcpy(Buffer_Stripping, streamItem.ContentCompSettings_Buffer, streamItem.ContentCompSettings_Buffer_Size);
std::memcpy(Buffer_Stripping+streamItem.ContentCompSettings_Buffer_Size, Save_Buffer+Save_Buffer_Offset+Save_Element_Offset, Save_Element_Size-Save_Element_Offset);
Buffer=Buffer_Stripping;
}
//Parsing
if(Laces_Pos)
FrameInfo.PTS=streamItem.Parser->FrameInfo.PTS;
else
streamItem.Parser->FrameInfo.PTS=FrameInfo.PTS;
Frame_Count_NotParsedIncluded=(streamItem.PacketCount==1 && !Laces_Pos)?0:streamItem.Parser->Frame_Count_NotParsedIncluded;
#if MEDIAINFO_DEMUX
int8u Demux_Level_old=Demux_Level;
if (streamItem.Parser && streamItem.Parser->Demux_Level==2)
Demux_Level=4;
Demux(Buffer+Buffer_Offset+(size_t)Element_Offset, (size_t)(Element_Size-Element_Offset), ContentType_MainStream);
Demux_Level=Demux_Level_old;
streamItem.Parser->FrameInfo.PTS=FrameInfo.PTS;
#endif //MEDIAINFO_DEMUX
Open_Buffer_Continue(streamItem.Parser, (size_t)(Element_Size-Element_Offset));
if (streamItem.Parser->Status[IsFinished]
|| (streamItem.PacketCount>=300 && Config->ParseSpeed<1.0)
|| (streamItem.PacketCount>=3 && Config->ParseSpeed==0)
)
{
streamItem.Searching_Payload=false;
if (!streamItem.Searching_TimeStamps && !streamItem.Searching_TimeStamp_Start)
Stream_Count--;
}
FrameInfo.PTS=(int64u)-1;
Frame_Count_NotParsedIncluded=(int64u)-1;
#if MEDIAINFO_DEMUX
if (Config->Demux_EventWasSent && Config->Demux_Unpacketize_Get())
Demux_EventWasSent=Element_Code;
#endif //MEDIAINFO_DEMUX
if (Save_Buffer!=Buffer)
{
//We must change the buffer for keeping out
Element_Offset=Save_Element_Size;
Element_Size=Save_Element_Size;
File_Offset=Save_File_Offset;
Buffer_Offset=Save_Buffer_Offset;
delete[] Buffer; Buffer=Save_Buffer;
}
}
else
Skip_XX(Element_Size-Element_Offset, "Data");
//Filling
Frame_Count++;
if (!Status[IsFilled] && (Stream_Count==0 || Frame_Count>(Config->ParseSpeed?512:3)*Stream.size()))
{
Fill();
if (Config->ParseSpeed<1.0)
{
//Jumping
std::sort(Segment_Seeks.begin(), Segment_Seeks.end());
for (size_t Pos=0; Pos<Segment_Seeks.size(); Pos++)
if (Segment_Seeks[Pos].SeekPosition>File_Offset+Buffer_Offset+Element_Size)
{
JumpTo(Segment_Seeks[Pos].SeekPosition);
Open_Buffer_Unsynch();
break;
}
if (File_GoTo==(int64u)-1)
{
JumpTo(Segment_Offset_End);
Open_Buffer_Unsynch();
}
}
Laces.clear();
}
Laces_Pos++;
if (Laces_Pos>=Laces.size())
{
Laces.clear();
Laces_Pos=0;
}
Element_Show();
#if MEDIAINFO_TRACE
if (Trace_Activated && (Trace_Segment_Cluster_Count>MaxCountSameElementInTrace || streamItem.Trace_Segment_Cluster_Block_Count>MaxCountSameElementInTrace))
Element_Children_IfNoErrors();
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_BlockGroup_BlockDuration()
{
//Parsing
int64u Segment_Cluster_TimeCode_Value=UInteger_Get();
FILLING_BEGIN();
if (Segment_Cluster_BlockGroup_BlockDuration_TrackNumber!=(int64u)-1)
{
Stream[Segment_Cluster_BlockGroup_BlockDuration_TrackNumber].Segment_Cluster_BlockGroup_BlockDuration_Counts[Segment_Cluster_TimeCode_Value]++;
Segment_Cluster_BlockGroup_BlockDuration_TrackNumber=(int64u)-1;
}
else
Segment_Cluster_BlockGroup_BlockDuration_Value=Segment_Cluster_TimeCode_Value;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_SimpleBlock()
{
Segment_Cluster_BlockGroup_BlockDuration_Value=(int64u)-1;
Segment_Cluster_BlockGroup_BlockDuration_TrackNumber=(int64u)-1;
Segment_Cluster_BlockGroup_Block();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cluster_Timecode()
{
//Parsing
Segment_Cluster_TimeCode_Value=UInteger_Get();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cues()
{
//Skipping Cues, we don't need of them
TestMultipleInstances();
#if MEDIAINFO_TRACE
Trace_Segment_Cues_CuePoint_Count=0;
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Cues_CuePoint()
{
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
if (Trace_Segment_Cues_CuePoint_Count<MaxCountSameElementInTrace)
Trace_Segment_Cues_CuePoint_Count++;
else
Element_Set_Remove_Children_IfNoErrors();
}
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info()
{
TestMultipleInstances(&Segment_Info_Count);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_DateUTC()
{
//Parsing
int64u Data;
Get_B8(Data, "Data"); Element_Info1(Data/1000000000+978307200); //From Beginning of the millenium, in nanoseconds
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Fill(Stream_General, 0, "Encoded_Date", Ztring().Date_From_Seconds_1970((int32u)(Data/1000000000+978307200))); //978307200s between beginning of the millenium and 1970
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_Duration()
{
//Parsing
float64 Float=Float_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Duration=Float;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_MuxingApp()
{
//Parsing
Ztring Data=UTF8_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Fill(Stream_General, 0, "Encoded_Library", Data);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_SegmentUID()
{
//Parsing
int128u Data;
Data=UInteger16_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
string DataString=uint128toString(Data, 10);
Fill(Stream_General, 0, General_UniqueID, DataString);
Fill(Stream_General, 0, General_UniqueID_String, DataString+" (0x"+uint128toString(Data, 16)+')');
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_TimecodeScale()
{
//Parsing
int64u UInteger=UInteger_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
TimecodeScale=UInteger;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_Title()
{
//Parsing
Ztring Data=UTF8_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Fill(Stream_General, 0, "Title", Data);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Info_WritingApp()
{
//Parsing
Ztring Data=UTF8_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Fill(Stream_General, 0, "Encoded_Application", Data);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_SeekHead()
{
Segment_Seeks.clear();
#if MEDIAINFO_TRACE
Trace_Segment_SeekHead_Seek_Count=0;
#endif // MEDIAINFO_TRACE
}
//---------------------------------------------------------------------------
void File_Mk::Segment_SeekHead_Seek()
{
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
if (Trace_Segment_SeekHead_Seek_Count<MaxCountSameElementInTrace)
Trace_Segment_SeekHead_Seek_Count++;
else
Element_Set_Remove_Children_IfNoErrors();
}
#endif // MEDIAINFO_TRACE
Segment_Seeks.resize(Segment_Seeks.size()+1);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_SeekHead_Seek_SeekID()
{
//Parsing
int64u Data;
Get_EB (Data, "Data");
FILLING_BEGIN();
Segment_Seeks.back().SeekID=Data;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_SeekHead_Seek_SeekPosition()
{
//Parsing
int64u Data=UInteger_Get();
FILLING_BEGIN();
Segment_Seeks.back().SeekPosition=Segment_Offset_Begin+Data;
FILLING_END();
Element_Info1(Ztring::ToZtring(Segment_Offset_Begin+Data, 16));
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags()
{
Segment_Tag_SimpleTag_TagNames.clear();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags_Tag()
{
//Previous tags
tags::iterator Items0 = Segment_Tags_Tag_Items.find((int64u)-1);
if (Items0 != Segment_Tags_Tag_Items.end())
{
tagspertrack &Items = Segment_Tags_Tag_Items[0]; // Creates it if not yet present, else take the previous one
//Change the key of the current tag
for (tagspertrack::iterator Item=Items0->second.begin(); Item!=Items0->second.end(); ++Item)
Items[Item->first] = Item->second;
Segment_Tags_Tag_Items.erase(Items0);
}
//Init
Segment_Tags_Tag_Targets_TagTrackUID_Value=0; // Default is all tracks
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags_Tag_SimpleTag_TagLanguage()
{
//Parsing
Ztring Data=String_Get();
FILLING_BEGIN();
//Fill(StreamKind_Last, StreamPos_Last, "Language", Data);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags_Tag_SimpleTag_TagName()
{
//Parsing
Ztring TagName=UTF8_Get();
Segment_Tag_SimpleTag_TagNames.resize(Element_Level-5); //5 is the first level of a tag
Segment_Tag_SimpleTag_TagNames.push_back(TagName);
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags_Tag_SimpleTag_TagString()
{
//Parsing
Ztring TagString;
TagString=UTF8_Get();
if (Segment_Tag_SimpleTag_TagNames.empty())
return;
if (Segment_Tag_SimpleTag_TagNames[0]==__T("AERMS_OF_USE")) Segment_Tag_SimpleTag_TagNames[0]=__T("TermsOfUse"); //Typo in the source file
if (Segment_Tag_SimpleTag_TagNames[0]==__T("BITSPS")) return; //Useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("COMPATIBLE_BRANDS")) return; //QuickTime techinical info, useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("CONTENT_TYPE")) Segment_Tag_SimpleTag_TagNames[0]=__T("ContentType");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("COPYRIGHT")) Segment_Tag_SimpleTag_TagNames[0]=__T("Copyright");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("CREATION_TIME")) {Segment_Tag_SimpleTag_TagNames[0]=__T("Encoded_Date"); TagString.insert(0, __T("UTC "));}
if (Segment_Tag_SimpleTag_TagNames[0]==__T("DATE_DIGITIZED")) {Segment_Tag_SimpleTag_TagNames[0]=__T("Mastered_Date"); TagString.insert(0, __T("UTC "));}
if (Segment_Tag_SimpleTag_TagNames[0]==__T("DATE_RELEASE")) Segment_Tag_SimpleTag_TagNames[0]=__T("Released_Date");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("DATE_RELEASED")) Segment_Tag_SimpleTag_TagNames[0]=__T("Released_Date");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("DESCRIPTION")) Segment_Tag_SimpleTag_TagNames[0]=__T("Description");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("ENCODED_BY")) Segment_Tag_SimpleTag_TagNames[0]=__T("EncodedBy");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("ENCODER")) Segment_Tag_SimpleTag_TagNames[0]=__T("Encoded_Library");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("FPS")) return; //Useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("HANDLER_NAME"))
{
if (TagString.find(__T("Handler"))!=std::string::npos || TagString.find(__T("handler"))!=std::string::npos || TagString.find(__T("vide"))!=std::string::npos || TagString.find(__T("soun"))!=std::string::npos)
return; //This is not a Title
Segment_Tag_SimpleTag_TagNames[0]=__T("Title");
}
if (Segment_Tag_SimpleTag_TagNames[0]==__T("LANGUAGE")) Segment_Tag_SimpleTag_TagNames[0]=__T("Language");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("MAJOR_BRAND")) return; //QuickTime techinical info, useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("MINOR_VERSION")) return; //QuickTime techinical info, useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("PART_NUMBER")) Segment_Tag_SimpleTag_TagNames[0]=__T("Track/Position");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("ORIGINAL_MEDIA_TYPE")) Segment_Tag_SimpleTag_TagNames[0]=__T("OriginalSourceForm");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("SAMPLE") && Segment_Tag_SimpleTag_TagNames.size()==2 && Segment_Tag_SimpleTag_TagNames[1]==__T("PART_NUMBER")) return; //Useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("SAMPLE") && Segment_Tag_SimpleTag_TagNames.size()==2 && Segment_Tag_SimpleTag_TagNames[1]==__T("TITLE")) {Segment_Tag_SimpleTag_TagNames.resize(1); Segment_Tag_SimpleTag_TagNames[0]=__T("Title_More");}
if (Segment_Tag_SimpleTag_TagNames[0]==__T("STEREO_MODE")) return; //Useless
if (Segment_Tag_SimpleTag_TagNames[0]==__T("TERMS_OF_USE")) Segment_Tag_SimpleTag_TagNames[0]=__T("TermsOfUse");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("TIMECODE"))
{
if (TagString.find(__T("Handler"))!=std::string::npos || TagString.find(__T("handler"))!=std::string::npos || TagString.find(__T("vide"))!=std::string::npos || TagString.find(__T("soun"))!=std::string::npos)
return; //This is not a Title
Segment_Tag_SimpleTag_TagNames[0]=__T("TimeCode_FirstFrame");
Segment_Tags_Tag_Items[Segment_Tags_Tag_Targets_TagTrackUID_Value]["TimeCode_Source"]="Matroska tags";
}
if (Segment_Tag_SimpleTag_TagNames[0]==__T("TITLE")) Segment_Tag_SimpleTag_TagNames[0]=__T("Title");
if (Segment_Tag_SimpleTag_TagNames[0]==__T("TOTAL_PARTS")) Segment_Tag_SimpleTag_TagNames[0]=__T("Track/Position_Total");
for (size_t Pos=0; Pos<Segment_Tag_SimpleTag_TagNames.size(); Pos++)
{
if (Segment_Tag_SimpleTag_TagNames[Pos]==__T("BARCODE")) Segment_Tag_SimpleTag_TagNames[Pos]=__T("BarCode");
if (Segment_Tag_SimpleTag_TagNames[Pos]==__T("COMMENT")) Segment_Tag_SimpleTag_TagNames[Pos]=__T("Comment");
if (Segment_Tag_SimpleTag_TagNames[Pos]==__T("ORIGINAL")) Segment_Tag_SimpleTag_TagNames[Pos]=__T("Original");
if (Segment_Tag_SimpleTag_TagNames[Pos]==__T("URL")) Segment_Tag_SimpleTag_TagNames[Pos]=__T("Url");
}
Ztring TagName;
for (size_t Pos=0; Pos<Segment_Tag_SimpleTag_TagNames.size(); Pos++)
{
TagName+=Segment_Tag_SimpleTag_TagNames[Pos];
if (Pos+1<Segment_Tag_SimpleTag_TagNames.size())
TagName+=__T('/');
}
Segment_Tags_Tag_Items[Segment_Tags_Tag_Targets_TagTrackUID_Value][TagName]=TagString;
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tags_Tag_Targets_TagTrackUID()
{
//Parsing
Segment_Tags_Tag_Targets_TagTrackUID_Value=UInteger_Get();
FILLING_BEGIN();
tags::iterator Items0 = Segment_Tags_Tag_Items.find((int64u)-1);
if (Items0 != Segment_Tags_Tag_Items.end())
{
tagspertrack &Items = Segment_Tags_Tag_Items[Segment_Tags_Tag_Targets_TagTrackUID_Value]; // Creates it if not yet present, else take the previous one
//Change the key of the current tag
for (tagspertrack::iterator Item=Items0->second.begin(); Item!=Items0->second.end(); ++Item)
Items[Item->first] = Item->second;
Segment_Tags_Tag_Items.erase(Items0);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks()
{
TestMultipleInstances(&Segment_Tracks_Count);
SegmentTrack_Offset_End=File_Offset+Buffer_Offset+Element_TotalSize_Get();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry()
{
if (Segment_Info_Count>1)
return; //First element has the priority
//Clearing
CodecID.clear();
InfoCodecID_Format_Type=InfoCodecID_Format_Matroska;
TrackType=(int64u)-1;
TrackNumber=(int64u)-1;
AudioBitDepth=(int64u)-1;
TrackVideoDisplayWidth=0;
TrackVideoDisplayHeight=0;
AvgBytesPerSec=0;
//Preparing
Stream_Prepare(Stream_Max);
//Default values
Fill_Flush();
Fill(StreamKind_Last, StreamPos_Last, "Language", "eng");
Fill(StreamKind_Last, StreamPos_Last, General_StreamOrder, Stream.size());
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_Audio()
{
//Default values
if (StreamKind_Last==Stream_Max)
Stream_Prepare(Stream_Audio);
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, 1);
if (Retrieve_Const(Stream_Audio, StreamPos_Last, Audio_SamplingRate).empty())
Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, 8000);
Audio_Manage();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_Audio_BitDepth()
{
//Parsing
int64u UInteger=UInteger_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
if (UInteger)
{
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", UInteger, 10, true);
Audio_Manage();
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_Audio_Channels()
{
//Parsing
int64u UInteger=UInteger_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
if (UInteger)
{
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, UInteger, 10, true);
Audio_Manage();
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_Audio_OutputSamplingFrequency()
{
//Parsing
float64 Float=Float_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
if (Float)
{
Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, Float, 0, true);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_Audio_SamplingFrequency()
{
//Parsing
float64 Float=Float_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
if (Float)
{
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_SamplingRate)==__T("8000"))
Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, Float, 0, true);
#ifdef MEDIAINFO_AAC_YES
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_CodecID).find(__T("A_AAC/"))==0)
((File_Aac*)Stream[TrackNumber].Parser)->AudioSpecificConfig_OutOfBand(float64_int64s(Float));
#endif //MEDIAINFO_AAC_YES
Audio_Manage();
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_CodecID()
{
//Parsing
Ztring Data=String_Get();
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
CodecID=Data;
CodecID_Manage();
CodecPrivate_Manage();
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression()
{
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Stream[TrackNumber].ContentCompAlgo=0; //0 is default
Fill(StreamKind_Last, StreamPos_Last, "MuxingMode", Mk_ContentCompAlgo(0), Unlimited, true, true);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompAlgo()
{
//Parsing
int64u Algo=UInteger_Get(); Param_Info1(Mk_ContentCompAlgo(Algo));
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
Stream[TrackNumber].ContentCompAlgo=Algo;
Fill(StreamKind_Last, StreamPos_Last, "MuxingMode", Mk_ContentCompAlgo(Algo), Unlimited, true, true);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_ContentEncodings_ContentEncoding_ContentCompression_ContentCompSettings()
{
//Parsing
Skip_XX(Element_Size, "Data");
FILLING_BEGIN();
if (Segment_Info_Count>1)
return; //First element has the priority
stream& streamItem = Stream[TrackNumber];
streamItem.ContentCompSettings_Buffer=new int8u[(size_t)Element_Size];
std::memcpy(streamItem.ContentCompSettings_Buffer, Buffer+Buffer_Offset, (size_t)Element_Size);
streamItem.ContentCompSettings_Buffer_Size=(size_t)Element_Size;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_CodecPrivate()
{
if (Segment_Info_Count>1)
{
Skip_XX(Element_Size, "Data (not parsed)");
return; //First element has the priority
}
if (TrackNumber==(int64u)-1 || TrackType==(int64u)-1 || Retrieve(Stream[TrackNumber].StreamKind, Stream[TrackNumber].StreamPos, "CodecID").empty())
{
//Codec not already known, saving CodecPrivate
if (CodecPrivate)
delete[] CodecPrivate; //CodecPrivate=NULL.
CodecPrivate_Size=(size_t)Element_Size;
CodecPrivate=new int8u[CodecPrivate_Size];
std::memcpy(CodecPrivate, Buffer+Buffer_Offset, CodecPrivate_Size);
return;
}
Segment_Tracks_TrackEntry_CodecPrivate__Parse();
}
//---------------------------------------------------------------------------
void File_Mk::Segment_Tracks_TrackEntry_CodecPrivate__Parse()
{
//Creating the parser
stream& streamItem = Stream[TrackNumber];
if (streamItem.Parser==NULL)
{
if (streamItem.StreamKind==Stream_Audio && Retrieve(Stream_Audio, streamItem.StreamPos, Audio_CodecID)==__T("A_MS/ACM"))
Segment_Tracks_TrackEntry_CodecPrivate_auds();
else if (streamItem.StreamKind==Stream_Video && Retrieve(Stream_Video, streamItem.StreamPos, Video_CodecID)==__T("V_MS/VFW/FOURCC"))
Segment_Tracks_TrackEntry_CodecPrivate_vids();
else if (Element_Size>0)
Skip_XX(Element_Size, "Unknown");
return;
}
#if MEDIAINFO_DEMUX
switch (Config->Demux_InitData_Get())
{
case 0 : //In demux event
{
Demux_Level=2; //Container
int64u Element_Code_Old=Element_Code;
Element_Code=TrackNumber;
Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_Header);
Element_Code=Element_Code_Old;
}
break;
case 1 : //In field
{
std::string Data_Raw((const char*)(Buffer+Buffer_Offset), (size_t)Element_Size);
std::string Data_Base64(Base64::encode(Data_Raw));
Fill(StreamKind_Last, StreamPos_Last, "Demux_InitBytes", Data_Base64);
Fill_SetOptions(StreamKind_Last, StreamPos_Last, "Demux_InitBytes