00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #pragma once
00023
00024 #include <atlbase.h>
00025 #include <atlcoll.h>
00026 #include <afxtempl.h>
00027 #include "..\BaseSplitter\BaseSplitter.h"
00028
00029 namespace MatroskaReader
00030 {
00031 class CMatroskaNode;
00032
00033 typedef unsigned __int64 QWORD;
00034
00035 class CANSI : public CStringA {public: HRESULT Parse(CMatroskaNode* pMN);};
00036 class CUTF8 : public CStringW {public: HRESULT Parse(CMatroskaNode* pMN);};
00037
00038 template<class T, class BASE>
00039 class CSimpleVar
00040 {
00041 protected:
00042 T m_val;
00043 bool m_fValid;
00044 public:
00045 CSimpleVar(T val = 0) : m_val(val), m_fValid(false) {}
00046 BASE& operator = (const BASE& v) {m_val = v.m_val; m_fValid = true; return(*this);}
00047 BASE& operator = (T val) {m_val = val; m_fValid = true; return(*this);}
00048 operator T() {return m_val;}
00049 BASE& Set(T val) {m_val = val; m_fValid = true; return(*(BASE*)this);}
00050 bool IsValid() {return m_fValid;}
00051 virtual HRESULT Parse(CMatroskaNode* pMN);
00052 };
00053
00054 class CUInt : public CSimpleVar<UINT64, CUInt> {public: HRESULT Parse(CMatroskaNode* pMN);};
00055 class CInt : public CSimpleVar<INT64, CInt> {public: HRESULT Parse(CMatroskaNode* pMN);};
00056 class CByte : public CSimpleVar<BYTE, CByte> {};
00057 class CShort : public CSimpleVar<short, CShort> {};
00058 class CFloat : public CSimpleVar<double, CFloat> {public: HRESULT Parse(CMatroskaNode* pMN);};
00059 class CID : public CSimpleVar<DWORD, CID> {public: HRESULT Parse(CMatroskaNode* pMN);};
00060 class CLength : public CSimpleVar<UINT64, CLength> {bool m_fSigned; public: CLength(bool fSigned = false) : m_fSigned(fSigned) {} HRESULT Parse(CMatroskaNode* pMN);};
00061 class CSignedLength : public CLength {public: CSignedLength() : CLength(true) {}};
00062
00063 class ContentCompression;
00064
00065 class CBinary : public CArray<BYTE>
00066 {
00067 public:
00068 CBinary& operator = (const CBinary& b) {Copy(b); return(*this);}
00069 operator BYTE*() {return (BYTE*)GetData();}
00070 CStringA ToString() {return CStringA((LPCSTR)GetData(), GetCount());}
00071 bool Compress(ContentCompression& cc), Decompress(ContentCompression& cc);
00072 HRESULT Parse(CMatroskaNode* pMN);
00073 };
00074
00075 template<class T>
00076 class CNode : public CAutoPtrList<T> {public: HRESULT Parse(CMatroskaNode* pMN);};
00077
00078 class EBML
00079 {
00080 public:
00081 CUInt EBMLVersion, EBMLReadVersion;
00082 CUInt EBMLMaxIDLength, EBMLMaxSizeLength;
00083 CANSI DocType;
00084 CUInt DocTypeVersion, DocTypeReadVersion;
00085
00086 HRESULT Parse(CMatroskaNode* pMN);
00087 };
00088
00089 class Info
00090 {
00091 public:
00092 CBinary SegmentUID, PrevUID, NextUID;
00093 CUTF8 SegmentFilename, PrevFilename, NextFilename;
00094 CUInt TimeCodeScale;
00095 CFloat Duration;
00096 CInt DateUTC;
00097 CUTF8 Title, MuxingApp, WritingApp;
00098
00099 Info() {TimeCodeScale.Set(1000000ui64);}
00100 HRESULT Parse(CMatroskaNode* pMN);
00101 };
00102
00103 class SeekHead
00104 {
00105 public:
00106 CID SeekID;
00107 CUInt SeekPosition;
00108
00109 HRESULT Parse(CMatroskaNode* pMN);
00110 };
00111
00112 class Seek
00113 {
00114 public:
00115 CNode<SeekHead> SeekHeads;
00116
00117 HRESULT Parse(CMatroskaNode* pMN);
00118 };
00119
00120 class TimeSlice
00121 {
00122 public:
00123 CUInt LaceNumber, FrameNumber;
00124 CUInt Delay, Duration;
00125
00126 HRESULT Parse(CMatroskaNode* pMN);
00127 };
00128
00129 class SimpleBlock
00130 {
00131 public:
00132 CLength TrackNumber;
00133 CInt TimeCode;
00134 CByte Lacing;
00135 CAutoPtrList<CBinary> BlockData;
00136
00137 HRESULT Parse(CMatroskaNode* pMN, bool fFull);
00138 };
00139
00140 class BlockGroup
00141 {
00142 public:
00143 SimpleBlock Block;
00144
00145 CUInt BlockDuration;
00146 CUInt ReferencePriority;
00147 CInt ReferenceBlock;
00148 CInt ReferenceVirtual;
00149 CBinary CodecState;
00150 CNode<TimeSlice> TimeSlices;
00151
00152 HRESULT Parse(CMatroskaNode* pMN, bool fFull);
00153 };
00154
00155 class CBlockGroupNode : public CNode<BlockGroup>
00156 {
00157 public:
00158 HRESULT Parse(CMatroskaNode* pMN, bool fFull);
00159 };
00160
00161 class CSimpleBlockNode : public CNode<SimpleBlock>
00162 {
00163 public:
00164 HRESULT Parse(CMatroskaNode* pMN, bool fFull);
00165 };
00166
00167 class Cluster
00168 {
00169 public:
00170 CUInt TimeCode, Position, PrevSize;
00171 CBlockGroupNode BlockGroups;
00172 CSimpleBlockNode SimpleBlocks;
00173
00174 HRESULT Parse(CMatroskaNode* pMN);
00175 HRESULT ParseTimeCode(CMatroskaNode* pMN);
00176 };
00177
00178 class Video
00179 {
00180 public:
00181 CUInt FlagInterlaced, StereoMode;
00182 CUInt PixelWidth, PixelHeight, DisplayWidth, DisplayHeight, DisplayUnit;
00183 CUInt AspectRatioType;
00184 CUInt ColourSpace;
00185 CFloat GammaValue;
00186 CFloat FramePerSec;
00187
00188 HRESULT Parse(CMatroskaNode* pMN);
00189 };
00190
00191 class Audio
00192 {
00193 public:
00194 CFloat SamplingFrequency;
00195 CFloat OutputSamplingFrequency;
00196 CUInt Channels;
00197 CBinary ChannelPositions;
00198 CUInt BitDepth;
00199
00200 Audio() {SamplingFrequency.Set(8000.0); Channels.Set(1);}
00201 HRESULT Parse(CMatroskaNode* pMN);
00202 };
00203
00204 class ContentCompression
00205 {
00206 public:
00207 CUInt ContentCompAlgo; enum {ZLIB, BZLIB, LZO1X, HDRSTRIP};
00208 CBinary ContentCompSettings;
00209
00210 ContentCompression() {ContentCompAlgo.Set(ZLIB);}
00211 HRESULT Parse(CMatroskaNode* pMN);
00212 };
00213
00214 class ContentEncryption
00215 {
00216 public:
00217 CUInt ContentEncAlgo; enum {UNKE, DES, THREEDES, TWOFISH, BLOWFISH, AES};
00218 CBinary ContentEncKeyID, ContentSignature, ContentSigKeyID;
00219 CUInt ContentSigAlgo; enum {UNKS, RSA};
00220 CUInt ContentSigHashAlgo; enum {UNKSH, SHA1_160, MD5};
00221
00222 ContentEncryption() {ContentEncAlgo.Set(0); ContentSigAlgo.Set(0); ContentSigHashAlgo.Set(0);}
00223 HRESULT Parse(CMatroskaNode* pMN);
00224 };
00225
00226 class ContentEncoding
00227 {
00228 public:
00229 CUInt ContentEncodingOrder;
00230 CUInt ContentEncodingScope; enum {AllFrameContents = 1, TracksPrivateData = 2};
00231 CUInt ContentEncodingType; enum {Compression, Encryption};
00232 ContentCompression cc;
00233 ContentEncryption ce;
00234
00235 ContentEncoding() {ContentEncodingOrder.Set(0); ContentEncodingScope.Set(AllFrameContents); ContentEncodingType.Set(Compression);}
00236 HRESULT Parse(CMatroskaNode* pMN);
00237 };
00238
00239 class ContentEncodings
00240 {
00241 public:
00242 CNode<ContentEncoding> ce;
00243
00244 ContentEncodings() {}
00245 HRESULT Parse(CMatroskaNode* pMN);
00246 };
00247
00248 class TrackEntry
00249 {
00250 public:
00251 enum {TypeVideo = 1, TypeAudio = 2, TypeComplex = 3, TypeLogo = 0x10, TypeSubtitle = 0x11, TypeControl = 0x20};
00252 CUInt TrackNumber, TrackUID, TrackType;
00253 CUInt FlagEnabled, FlagDefault, FlagLacing;
00254 CUInt MinCache, MaxCache;
00255 CUTF8 Name;
00256 CANSI Language;
00257 CBinary CodecID;
00258 CBinary CodecPrivate;
00259 CUTF8 CodecName;
00260 CUTF8 CodecSettings;
00261 CANSI CodecInfoURL;
00262 CANSI CodecDownloadURL;
00263 CUInt CodecDecodeAll;
00264 CUInt TrackOverlay;
00265 CUInt DefaultDuration;
00266 CFloat TrackTimecodeScale;
00267 enum {NoDesc = 0, DescVideo = 1, DescAudio = 2};
00268 int DescType;
00269 Video v;
00270 Audio a;
00271 ContentEncodings ces;
00272 TrackEntry() {DescType = NoDesc; FlagEnabled.Set(1); FlagDefault.Set(1); FlagLacing.Set(1); }
00273 HRESULT Parse(CMatroskaNode* pMN);
00274
00275 bool Expand(CBinary& data, UINT64 Scope);
00276 };
00277
00278 class Track
00279 {
00280 public:
00281 CNode<TrackEntry> TrackEntries;
00282
00283 HRESULT Parse(CMatroskaNode* pMN);
00284 };
00285
00286 class CueReference
00287 {
00288 public:
00289 CUInt CueRefTime, CueRefCluster, CueRefNumber, CueRefCodecState;
00290
00291 HRESULT Parse(CMatroskaNode* pMN);
00292 };
00293
00294 class CueTrackPosition
00295 {
00296 public:
00297 CUInt CueTrack, CueClusterPosition, CueBlockNumber, CueCodecState;
00298 CNode<CueReference> CueReferences;
00299
00300 HRESULT Parse(CMatroskaNode* pMN);
00301 };
00302
00303 class CuePoint
00304 {
00305 public:
00306 CUInt CueTime;
00307 CNode<CueTrackPosition> CueTrackPositions;
00308
00309 HRESULT Parse(CMatroskaNode* pMN);
00310 };
00311
00312 class Cue
00313 {
00314 public:
00315 CNode<CuePoint> CuePoints;
00316
00317 HRESULT Parse(CMatroskaNode* pMN);
00318 };
00319
00320 class AttachedFile
00321 {
00322 public:
00323 CUTF8 FileDescription;
00324 CUTF8 FileName;
00325 CANSI FileMimeType;
00326 QWORD FileDataPos, FileDataLen;
00327 CUInt FileUID;
00328
00329 AttachedFile() {FileDataPos = FileDataLen = 0;}
00330 HRESULT Parse(CMatroskaNode* pMN);
00331 };
00332
00333 class Attachment
00334 {
00335 public:
00336 CNode<AttachedFile> AttachedFiles;
00337
00338 HRESULT Parse(CMatroskaNode* pMN);
00339 };
00340
00341 class ChapterDisplay
00342 {
00343 public:
00344 CUTF8 ChapString;
00345 CANSI ChapLanguage;
00346 CANSI ChapCountry;
00347
00348 ChapterDisplay() {ChapLanguage.CStringA::operator = ("eng");}
00349 HRESULT Parse(CMatroskaNode* pMN);
00350 };
00351
00352 class ChapterAtom
00353 {
00354 public:
00355 CUInt ChapterUID;
00356 CUInt ChapterTimeStart, ChapterTimeEnd, ChapterFlagHidden, ChapterFlagEnabled;
00357
00358 CNode<ChapterDisplay> ChapterDisplays;
00359 CNode<ChapterAtom> ChapterAtoms;
00360
00361 ChapterAtom() {ChapterUID.Set(rand());ChapterFlagHidden.Set(0);ChapterFlagEnabled.Set(1);}
00362 HRESULT Parse(CMatroskaNode* pMN);
00363 ChapterAtom* FindChapterAtom(UINT64 id);
00364 };
00365
00366 class EditionEntry : public ChapterAtom
00367 {
00368 public:
00369 HRESULT Parse(CMatroskaNode* pMN);
00370 };
00371
00372 class Chapter
00373 {
00374 public:
00375 CNode<EditionEntry> EditionEntries;
00376
00377 HRESULT Parse(CMatroskaNode* pMN);
00378 };
00379
00380 class Segment
00381 {
00382 public:
00383 QWORD pos, len;
00384 Info SegmentInfo;
00385 CNode<Seek> MetaSeekInfo;
00386 CNode<Cluster> Clusters;
00387 CNode<Track> Tracks;
00388 CNode<Cue> Cues;
00389 CNode<Attachment> Attachments;
00390 CNode<Chapter> Chapters;
00391
00392
00393
00394 HRESULT Parse(CMatroskaNode* pMN);
00395 HRESULT ParseMinimal(CMatroskaNode* pMN);
00396
00397 UINT64 GetMasterTrack();
00398
00399 REFERENCE_TIME GetRefTime(INT64 t) {return t*(REFERENCE_TIME)(SegmentInfo.TimeCodeScale)/100;}
00400 ChapterAtom* FindChapterAtom(UINT64 id, int nEditionEntry = 0);
00401 };
00402
00403 class CMatroskaFile : public CBaseSplitterFile
00404 {
00405 public:
00406 CMatroskaFile(IAsyncReader* pAsyncReader, HRESULT& hr);
00407 virtual ~CMatroskaFile() {}
00408
00409 HRESULT Init();
00410
00411 using CBaseSplitterFile::Read;
00412 template <class T> HRESULT Read(T& var);
00413
00414 EBML m_ebml;
00415 Segment m_segment;
00416 REFERENCE_TIME m_rtOffset;
00417
00418 HRESULT Parse(CMatroskaNode* pMN);
00419 };
00420
00421 class CMatroskaNode
00422 {
00423 CMatroskaNode* m_pParent;
00424 CMatroskaFile* m_pMF;
00425
00426 bool Resync();
00427
00428 public:
00429 CID m_id;
00430 CLength m_len;
00431 QWORD m_filepos, m_start;
00432
00433 HRESULT Parse();
00434
00435 public:
00436 CMatroskaNode(CMatroskaFile* pMF);
00437 CMatroskaNode(CMatroskaNode* pParent);
00438
00439 CMatroskaNode* Parent() {return m_pParent;}
00440 CAutoPtr<CMatroskaNode> Child(DWORD id = 0, bool fSearch = true);
00441 bool Next(bool fSame = false);
00442 bool Find(DWORD id, bool fSearch = true);
00443
00444 QWORD FindPos(DWORD id, QWORD start = 0);
00445
00446 void SeekTo(QWORD pos);
00447 QWORD GetPos(), GetLength();
00448 template <class T> HRESULT Read(T& var);
00449 HRESULT Read(BYTE* pData, QWORD len);
00450
00451 CAutoPtr<CMatroskaNode> Copy();
00452
00453 CAutoPtr<CMatroskaNode> GetFirstBlock();
00454 bool NextBlock();
00455 };
00456 }