//================================================================================
// lib2D library
//
// "Matroska" movie container support header file
//
// AUTHOR:  Gabor Nagy
// DATE:    2026-May-03 20:46:24
//
// Copyright (C) 2014-2026 by Gabor Nagy. All rights reserved.
//================================================================================
#ifndef _EpMKV_h
#define _EpMKV_h

#include <stdio.h>

#ifndef _EClass_h
#include <EClass.h>
#endif

#include <EUndo.h>
#include <Color/Color.h>


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
extern "C" {
#endif


typedef struct EEBMLElement_S   EEBMLElement;
typedef struct EEBMLElement_S*  EEBMLElementPtr;
EListA_t(EEBMLElementPtr);


enum
{
	EEBMLTypeSINT = 1,
	EEBMLTypeUINT,
	EEBMLTypeFLOAT,
	EEBMLTypeSTRING,
	EEBMLTypeUTF8,
	EEBMLTypeDATE,
	EEBMLTypeMASTER,
	EEBMLTypeBINARY
} EEBMLType;

#define EFourCC(a, b, c, d)  ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))

enum
{
	EpCodecMJPEG = EFourCC('M', 'J', 'P', 'G'),
	EpCodecH264  = EFourCC('A', 'V', 'C', '1')
};

#define EEBMLTypeREADCONTENT  0x1000  // Read content, even if it's an EEBMLTypeBINARY
#define EEBMLTypeUNSUPPORTED  0x2000  // Flag added to EEBMLType to indicate that this element should be skipped
#define EEBMLTypeFLAGS        (EEBMLTypeUNSUPPORTED)
#define EEBMLTypeENUMBITS     0x00FF

struct EEBMLElement_S
{
	const char*     Name;
	const uint8_t*  ID;uint16_t  IDLength;
	int             Type;  // EEBMLTypeSInT, EEBMLTypeUINT etc.
	EBool           Supported;
	EListA_s(, EEBMLElementPtr, AcceptedChildren);
};

typedef struct
{
	ETime     TimeCode;
	EIndex    StartOffset, Size;
} EpMKVBlock;

typedef struct
{
	int       RefCnt;
	int       TrackNumber;
	uint32_t  CodecID;
	EBool     VFWCodecID;  // Codec ID is V_MS/VFW/FOURCC. Need to look in the <CodecPrivate> Element for details (PITA)

	EIndex2   PixelSize;

	EListA(, EpMKVBlock, Blocks);  // E.g. frames for video
} EpMKVTrack;


typedef struct
{
	EIndex  TimeCodeScale;  // Nanoseconds
	EList(, EpMKVTrack*, VideoTracks);
} EpMKVSegment;

#define EEBML_HIERARCHY_MAX_DEPTH  64

typedef struct
{
// Reading
//
	EIndex               ReadStack_EndPositions[EEBML_HIERARCHY_MAX_DEPTH];  // End positions of the Elements on the stack. This is how we know when to pop
	const EEBMLElement*  ReadStack[EEBML_HIERARCHY_MAX_DEPTH];
	int                  Level;                                              // Current level in the hierarchy during reading


	EList(, EpMKVSegment*, Segments);

// Writing
//
	EIndex    FramesPerCluster;    // To reduce the number of fwrite() calls and the file size, save this many frames per mkv cluster
	ETime     ClusterTimeCode_us;
	EIndex    ClusterFrameC;       // Number of frames accumulated so far for the current cluster
	uint8_t*  ClusterBuffer;EIndex  ClusterBufferPtr, ClusterBufferSizeAllocated;
	uint32_t  CodecID;
} EpMKV;


#if defined (__cplusplus) && (!(defined (__CPLUSLIBS)))
}	// Close scope of 'extern "C"' declaration
#endif


#endif // _EpMKV_h
