/*
* $Id$
*
* (C) 2003-2006 Gabest
* (C) 2006-2012 see Authors.txt
*
* This file is part of MPC-HC.
*
* MPC-HC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MPC-HC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*
*/
#pragma once
#include
#include
namespace MatroskaWriter
{
typedef unsigned __int64 QWORD;
class CID
{
protected:
DWORD m_id;
QWORD HeaderSize(QWORD len);
HRESULT HeaderWrite(IStream* pStream);
public:
CID(DWORD id);
DWORD GetID() const {
return m_id;
}
virtual QWORD Size(bool fWithHeader = true);
virtual HRESULT Write(IStream* pStream);
};
class CLength : public CID
{
UINT64 m_len;
public:
CLength(UINT64 len = 0) : CID(0), m_len(len) {}
operator UINT64() {
return m_len;
}
QWORD Size(bool fWithHeader = false);
HRESULT Write(IStream* pStream);
};
class CBinary : public CAtlArray, public CID
{
public:
CBinary(DWORD id) : CID(id) {}
CBinary& operator = (const CBinary& b) {
Copy(b);
return *this;
}
operator BYTE* () {
return (BYTE*)GetData();
}
CBinary& Set(CStringA str) {
SetCount(str.GetLength() + 1);
strcpy_s((char*)GetData(), str.GetLength() + 1, str);
return *this;
}
// CBinary& Set(CStringA str) {SetCount(str.GetLength()); memcpy((char*)GetData(), str, str.GetLength()); return *this;}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CANSI : public CStringA, public CID
{
public:
CANSI(DWORD id) : CID(id) {}
CANSI& Set(CStringA str) {
CStringA::operator = (str);
return *this;
}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CUTF8 : public CStringW, public CID
{
public:
CUTF8(DWORD id) : CID(id) {}
CUTF8& Set(CStringW str) {
CStringW::operator = (str);
return *this;
}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
template
class CSimpleVar : public CID
{
protected:
T m_val;
bool m_fSet;
public:
explicit CSimpleVar(DWORD id, T val = 0) : CID(id), m_val(val) {
m_fSet = !!val;
}
operator T() {
return m_val;
}
BASE& Set(T val) {
m_val = val;
m_fSet = true;
return (*(BASE*)this);
}
void UnSet() {
m_fSet = false;
}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CUInt : public CSimpleVar
{
public:
explicit CUInt(DWORD id, UINT64 val = 0) : CSimpleVar(id, val) {}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CInt : public CSimpleVar
{
public:
explicit CInt(DWORD id, INT64 val = 0) : CSimpleVar(id, val) {}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CByte : public CSimpleVar
{
public:
explicit CByte(DWORD id, BYTE val = 0) : CSimpleVar(id, val) {}
};
class CShort : public CSimpleVar
{
public:
explicit CShort(DWORD id, short val = 0) : CSimpleVar(id, val) {}
};
class CFloat : public CSimpleVar
{
public:
explicit CFloat(DWORD id, float val = 0) : CSimpleVar(id, val) {}
};
template
class CNode : public CAutoPtrList
{
public:
QWORD Size(bool fWithHeader = true) {
QWORD len = 0;
POSITION pos = GetHeadPosition();
while (pos) {
len += GetNext(pos)->Size(fWithHeader);
}
return len;
}
HRESULT Write(IStream* pStream) {
HRESULT hr;
POSITION pos = GetHeadPosition();
while (pos) if (FAILED(hr = GetNext(pos)->Write(pStream))) {
return hr;
}
return S_OK;
}
};
class EBML : public CID
{
public:
CUInt EBMLVersion, EBMLReadVersion;
CUInt EBMLMaxIDLength, EBMLMaxSizeLength;
CANSI DocType;
CUInt DocTypeVersion, DocTypeReadVersion;
EBML(DWORD id = 0x1A45DFA3);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Info : public CID
{
public:
CBinary SegmentUID, PrevUID, NextUID;
CUTF8 SegmentFilename, PrevFilename, NextFilename;
CUInt TimeCodeScale; // [ns], default: 1.000.000
CFloat Duration;
CInt DateUTC;
CUTF8 Title, MuxingApp, WritingApp;
Info(DWORD id = 0x1549A966);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Video : public CID
{
public:
CUInt FlagInterlaced, StereoMode;
CUInt PixelWidth, PixelHeight, DisplayWidth, DisplayHeight, DisplayUnit;
CUInt AspectRatioType;
CUInt ColourSpace;
CFloat GammaValue;
CFloat FramePerSec;
Video(DWORD id = 0xE0);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Audio : public CID
{
public:
CFloat SamplingFrequency;
CFloat OutputSamplingFrequency;
CUInt Channels;
CBinary ChannelPositions;
CUInt BitDepth;
Audio(DWORD id = 0xE1);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class TrackEntry : public CID
{
public:
enum {TypeVideo = 1, TypeAudio = 2, TypeComplex = 3, TypeLogo = 0x10, TypeSubtitle = 0x11, TypeControl = 0x20};
CUInt TrackNumber, TrackUID, TrackType;
CUInt FlagEnabled, FlagDefault, FlagLacing;
CUInt MinCache, MaxCache;
CUTF8 Name;
CANSI Language;
CBinary CodecID;
CBinary CodecPrivate;
CUTF8 CodecName;
CUTF8 CodecSettings;
CANSI CodecInfoURL;
CANSI CodecDownloadURL;
CUInt CodecDecodeAll;
CUInt TrackOverlay;
CUInt DefaultDuration;
enum {NoDesc = 0, DescVideo = 1, DescAudio = 2};
int DescType;
Video v;
Audio a;
TrackEntry(DWORD id = 0xAE);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Track : public CID
{
public:
CNode TrackEntries;
Track(DWORD id = 0x1654AE6B);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CBlock : public CID
{
public:
CLength TrackNumber;
REFERENCE_TIME TimeCode, TimeCodeStop;
CNode BlockData;
CBlock(DWORD id = 0xA1);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class BlockGroup : public CID
{
public:
CUInt BlockDuration;
CUInt ReferencePriority;
CInt ReferenceBlock;
CInt ReferenceVirtual;
CBinary CodecState;
CBlock Block;
// CNode TimeSlices;
BlockGroup(DWORD id = 0xA0);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Cluster : public CID
{
public:
CUInt TimeCode, Position, PrevSize;
CNode BlockGroups;
Cluster(DWORD id = 0x1F43B675);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
/* class CueReference : public CID
{
public:
CUInt CueRefTime, CueRefCluster, CueRefNumber, CueRefCodecState;
CueReference(DWORD id = 0xDB);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
*/
class CueTrackPosition : public CID
{
public:
CUInt CueTrack, CueClusterPosition, CueBlockNumber, CueCodecState;
// CNode CueReferences;
CueTrackPosition(DWORD id = 0xB7);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class CuePoint : public CID
{
public:
CUInt CueTime;
CNode CueTrackPositions;
CuePoint(DWORD id = 0xBB);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Cue : public CID
{
public:
CNode CuePoints;
Cue(DWORD id = 0x1C53BB6B);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class SeekID : public CID
{
CID m_id;
public:
SeekID(DWORD id = 0x53AB);
void Set(DWORD id) {
m_id = id;
}
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class SeekHead : public CID
{
public:
SeekID ID;
CUInt Position;
SeekHead(DWORD id = 0x4DBB);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Seek : public CID
{
public:
CNode SeekHeads;
Seek(DWORD id = 0x114D9B74);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Segment : public CID
{
public:
Segment(DWORD id = 0x18538067);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Tags : public CID
{
public:
// TODO
Tags(DWORD id = 0x1254C367);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
class Void : public CID
{
QWORD m_len;
public:
Void(QWORD len, DWORD id = 0xEC);
QWORD Size(bool fWithHeader = true);
HRESULT Write(IStream* pStream);
};
}