/*
 *			GPAC - MPEG-4 Systems C Development Kit
 *
 *			Copyright (c) Jean Le Feuvre 2000-2005 
 *					All rights reserved
 *
 *  This file is part of GPAC / Object Descriptor sub-project
 *
 *  GPAC 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 2, or (at your option)
 *  any later version.
 *   
 *  GPAC 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 GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 */

#ifndef M4_DESCRIPTORS_H
#define M4_DESCRIPTORS_H

#ifdef __cplusplus
extern "C" {
#endif

#include <gpac/m4_tools.h>

/***************************************
			Descriptors Tag
***************************************/
enum
{
	ForbiddenZero_Tag					= 0x00,
	ObjectDescriptor_Tag				= 0x01,
	InitialObjectDescriptor_Tag			= 0x02,
	ESDescriptor_Tag					= 0x03,
	DecoderConfigDescriptor_Tag			= 0x04,
	DecoderSpecificInfo_Tag				= 0x05,
	SLConfigDescriptor_Tag				= 0x06,
	ContentIdentification_Tag			= 0x07,
	SuppContentIdentification_Tag		= 0x08,
	IPIPtr_Tag							= 0x09,
	IPMP_DescriptorPointer_Tag			= 0x0A,
	IPMP_Descriptor_Tag							= 0x0B,
	QoS_Tag								= 0x0C,
	RegistrationDescriptor_Tag			= 0x0D,

	/*FILE FORMAT RESERVED IDs - NEVER CREATE / USE THESE DESCRIPTORS*/
	ES_ID_IncTag						= 0x0E,
	ES_ID_RefTag						= 0x0F,
	MP4_IOD_Tag							= 0x10,
	MP4_OD_Tag							= 0x11,
	IPI_DescPtr_Tag						= 0x12,
	/*END FILE FORMAT RESERVED*/
	
	ExtensionPL_Tag						= 0x13,
	PL_IndicationIndex_Tag				= 0x14,
	
	ISO_DESC_RANGE_BEGIN				= 0x15,
	ISO_DESC_RANGE_END					= 0x3F,

	ContentClassification_Tag			= 0x40,
	KeyWordDescriptor_Tag				= 0x41,
	RatingDescriptor_Tag				= 0x42,
	LanguageDescriptor_Tag				= 0x43,
	ShortTextualDescriptor_Tag			= 0x44,
	ExpandedTextualDescriptor_Tag		= 0x45,
	ContentCreatorName_Tag				= 0x46,
	ContentCreationDate_Tag				= 0x47,
	OCI_CreatorName_Tag					= 0x48,
	OCI_CreationDate_Tag				= 0x49,
	SmpteCameraPosition_Tag				= 0x4A,

	SegmentDescriptor_Tag				= 0x4B,
	MediaTimeDescriptor_Tag				= 0x4C,

	IPMP_ToolList_Tag					= 0x60,
	IPMP_Tool_Tag						= 0x61,

	ISO_RESERVED_RANGE_BEGIN	= 0x62,
	ISO_RESERVED_RANGE_END		= 0xBF,
	
	USER_DESC_RANGE_BEGIN		= 0xC0,

	/*internal descriptor for mux input description*/
	MuxInfoDescriptor_Tag		= USER_DESC_RANGE_BEGIN,
	/*internal descriptor for bifs config input description*/
	BIFSConfig_Tag				= USER_DESC_RANGE_BEGIN + 1,
	/*internal descriptor for UI config input description*/
	UIConfig_Tag				= USER_DESC_RANGE_BEGIN + 2,
	/*internal descriptor for TextConfig description*/
	TextConfig_Tag				= USER_DESC_RANGE_BEGIN + 3,
	TextSampleDescriptor_Tag	= USER_DESC_RANGE_BEGIN + 4,


	USER_DESC_RANGE_END			= 0xFE,
	
	ForbiddenFF_Tag				= 0xFF
};

/*use to avoid rewriting the code in case ISO defines new extension desc...*/
#define ISO_EXT_RANGE_START		0x80
#define ISO_EXT_RANGE_END		0xFE

#define ISO_OCI_RANGE_START		0x40
#define ISO_OCI_RANGE_END		(ISO_RESERVED_RANGE_BEGIN - 1)

/*********************************************
	currently supported MPEG-4 stream types
*********************************************/
enum
{
	M4ST_FORBIDDEN	= 0x00,
	M4ST_OD			= 0x01,
	M4ST_OCR		= 0x02,
	M4ST_SCENE		= 0x03,
	M4ST_VISUAL		= 0x04,
	M4ST_AUDIO		= 0x05,
	M4ST_MPEG7		= 0x06,
	M4ST_IPMP		= 0x07,
	M4ST_OCI		= 0x08,
	M4ST_MPEGJ		= 0x09,
	M4ST_INTERACT	= 0x0A,
	M4ST_IPMPTool	= 0x0B,
	M4ST_FondData	= 0x0C,
	M4ST_TEXT		= 0x0D,
};

/***************************************
			Descriptors
***************************************/

#define BASE_DESCRIPTOR \
		u8 tag;

typedef struct BaseDescriptor
{
	BASE_DESCRIPTOR
} Descriptor;


/*	default descriptor. 
	NOTE: The decoderSpecificInfo is used as a default desc with tag 0x05 */
typedef struct
{
	BASE_DESCRIPTOR
	u32 dataLength;
	char *data;
} DefaultDescriptor;

/*Object Descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	Chain *ipmp_tools;
} IPMP_ToolListDescriptor;

/*Object Descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	u16 objectDescriptorID;
	char *URLString;
	Chain *ESDescriptors;
	Chain *OCIDescriptors;
	/*includes BOTH IPMP_DescriptorPointer (IPMP & IPMPX) and IPMP_Descriptor (IPMPX only)*/
	Chain *IPMP_Descriptors;
	Chain *extensionDescriptors;
} ObjectDescriptor;

/*InitialObjectDescriptor - WARNING: even though the bitstream IOD is not
a bit extension of OD, internally it is a real overclass of OD
we usually typecast IOD to OD when flags are not needed !!!*/
typedef struct
{
	BASE_DESCRIPTOR
	u16 objectDescriptorID;
	char *URLString;
	Chain *ESDescriptors;
	Chain *OCIDescriptors;
	/*includes BOTH IPMP_DescriptorPointer (IPMP & IPMPX) and IPMP_Descriptor (IPMPX only)*/
	Chain *IPMP_Descriptors;
	Chain *extensionDescriptors;

	/*IOD extensions*/
	u8 inlineProfileFlag;
	u8 OD_profileAndLevel;
	u8 scene_profileAndLevel;
	u8 audio_profileAndLevel;
	u8 visual_profileAndLevel;
	u8 graphics_profileAndLevel;

	IPMP_ToolListDescriptor *IPMPToolList;
} InitialObjectDescriptor;

/*File Format Object Descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	u16 objectDescriptorID;
	char *URLString;
	Chain *ES_ID_RefDescriptors;
	Chain *OCIDescriptors;
	Chain *IPMP_Descriptors;
	Chain *extensionDescriptors;
	Chain *ES_ID_IncDescriptors;
} M4F_ObjectDescriptor;

/*File Format Initial Object Descriptor - same remark as IOD*/
typedef struct
{
	BASE_DESCRIPTOR
	u16 objectDescriptorID;
	char *URLString;
	Chain *ES_ID_RefDescriptors;
	Chain *OCIDescriptors;
	Chain *IPMP_Descriptors;
	Chain *extensionDescriptors;
	Chain *ES_ID_IncDescriptors;

	u8 inlineProfileFlag;
	u8 OD_profileAndLevel;
	u8 scene_profileAndLevel;
	u8 audio_profileAndLevel;
	u8 visual_profileAndLevel;
	u8 graphics_profileAndLevel;

	IPMP_ToolListDescriptor *IPMPToolList;
} M4F_InitialObjectDescriptor;


/*File Format ES Descriptor for IOD*/
typedef struct {
	BASE_DESCRIPTOR
	u32 trackID;
} ES_ID_Inc;

/*File Format ES Descriptor for OD*/
typedef struct {
	BASE_DESCRIPTOR
	u16 trackRef;
} ES_ID_Ref;

/*Decoder config Descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	u8 objectTypeIndication;
	u8 streamType;
	u8 upstream;
	u32 bufferSizeDB;
	u32 maxBitrate;
	u32 avgBitrate;
	DefaultDescriptor *decoderSpecificInfo;
	Chain *profileLevelIndicationIndexDescriptor;
} DecoderConfigDescriptor;

/*the Sync Layer config descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	u8 predefined;
	u8 useAccessUnitStartFlag;
	u8 useAccessUnitEndFlag;
	u8 useRandomAccessPointFlag;
	u8 hasRandomAccessUnitsOnlyFlag;
	u8 usePaddingFlag;
	u8 useTimestampsFlag;
	u8 useIdleFlag;
	u8 durationFlag;
	u32 timestampResolution;
	u32 OCRResolution;
	u8 timestampLength;
	u8 OCRLength;
	u8 AULength;
	u8 instantBitrateLength;
	u8 degradationPriorityLength;
	u8 AUSeqNumLength;
	u8 packetSeqNumLength;
	u32 timeScale;
	u16 AUDuration;
	u16 CUDuration;
	u64 startDTS;
	u64 startCTS;
} SLConfigDescriptor;

/***************************************
			SLConfig Tag
***************************************/
enum
{
	SLPredef_Null = 0x01,
	SLPredef_MP4 = 0x02,
	/*intern to GPAC, means NO SL at all (for streams unable to handle AU reconstruction a timing)*/
	SLPredef_SkipSL = 0xF0
};

/*set SL predefined (assign all fields according to sl->predefined value)*/
M4Err SLSetPredefined(SLConfigDescriptor *sl);

/*Content Identification Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u8 compatibility;
	u8 protectedContent;
	u8 contentTypeFlag;
	u8 contentIdentifierFlag;
	u8 contentType;
	u8 contentIdentifierType;
	/*international code string*/
	unsigned char *contentIdentifier;	
} ContentIdentificationDescriptor;

/*Supplementary Content Identification Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 languageCode;
	char *supplContentIdentifierTitle;
	char *supplContentIdentifierValue;
} SupplementaryContentIdentificationDescriptor;

/*IPI (Intelectual Property Identification) Descriptor Pointer*/
typedef struct {
	BASE_DESCRIPTOR
	u16 IPI_ES_Id;
} IPI_DescrPointer;

/*IPMP Descriptor Pointer*/
typedef struct {
	BASE_DESCRIPTOR
	u8 IPMP_DescriptorID;
	u16 IPMP_DescriptorIDEx;
	u16 IPMP_ES_ID;	
} IPMP_DescrPointer;

/*IPMPX control points*/
enum
{
	/*no control point*/
	IPMP_CP_NONE = 0,
	/*control point between DB and decoder*/
	IPMP_CP_DB = 1,
	/*control point between decoder and CB*/
	IPMP_CP_CB = 2,
	/*control point between CB and render*/
	IPMP_CP_CM = 3,
	/*control point in BIFS tree (???)*/
	IPMP_CP_BIFS = 4,
	/*the rest is reserved or forbidden(0xFF)*/
};

/*IPMPX base classe*/
#define IPMPX_BASE	\
	u8 tag;	\
	u8 version;	\
	u32 dataID;	\

typedef struct 
{
	IPMPX_BASE
} IPMPX_Base;

/*IPMP descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u8 IPMP_DescriptorID;
	u16 IPMPS_Type;
	/*if IPMPS_Type=0, NULL-terminated URL, else if IPMPS_Type is not IPMPX, opaque data*/
	char *opaque_data;
	/*if IPMPS_Type=0, irrelevant (strlen(URL)), else if IPMPS_Type is not IPMPX, opaque data size*/
	u32 opaque_data_size;

	/*IPMPX specific*/
	u16 IPMP_DescriptorIDEx;
	bin128 IPMP_ToolID;
	u8 control_point;
	u8 cp_sequence_code;
	Chain *ipmpx_data;
} IPMP_Descriptor;


/*IPMPTool*/
#define MAX_IPMP_ALT_TOOLS	20
typedef struct
{
	BASE_DESCRIPTOR
	bin128 IPMP_ToolID;
	/*if set, this is an alternate tool*/
	u32 num_alternate;
	bin128 specificToolID[MAX_IPMP_ALT_TOOLS];

	struct _tagIPMPXParamDesc *toolParamDesc;
	char *tool_url;
} IPMP_Tool;


/*BIFSConfig - parsing only, STORED IN ESD:DCD:DSI*/
typedef struct {
	BASE_DESCRIPTOR
	u32 version;
	u16 nodeIDbits;
	u16 routeIDbits;
	u16 protoIDbits;
	Bool isCommandStream;
	Bool pixelMetrics;
	u16 pixelWidth, pixelHeight;
} BIFSConfigDescriptor;

/*sepcial function for authoring - convert DSI to BIFSConfig*/
M4Err OD_GetBIFSConfig(DefaultDescriptor *dsi, u8 oti, BIFSConfigDescriptor *cfg);

/*flags for style*/
enum
{
	STF_Normal = 0,
	STF_Bold = 1,
	STF_Italic = 2,
	STF_Underlined = 4
};

typedef struct
{
	u16 startCharOffset;
	u16 endCharOffset;
	u16 fontID;
	u8 style_flags;
	u8 font_size;
	/*ARGB*/
	u32 text_color;
} StyleRecord;

typedef struct
{
	u16 fontID;
	char *fontName;
} FontRecord;

typedef struct
{
	s16 top, left, bottom, right;
} BoxRecord;

/*scroll flags*/
enum
{
	STF_ScrollCredits = 0,
	STF_ScrollMarquee = 1,
	STF_ScrollDown = 2,
	STF_ScrollRight = 3
};

/* display flags*/
enum
{
	STF_ScrollIn = 0x00000020,
	STF_ScrollOut = 0x00000040,
	/*use one of the scroll flags, eg STF_ScrollDirection | STF_ScrollCredits*/
	STF_ScrollDirection = 0x00000180,
	STF_Karaoke	= 0x00000800,
	STF_VerticalText = 0x00020000,
	STF_FillRegion = 0x00040000,
};

typedef struct
{
	/*this is defined as a descriptor for parsing*/
	BASE_DESCRIPTOR

	u32 displayFlags;
	/*left, top: 0 -  centered: 1 - bottom, right: -1*/
	s8 horiz_justif, vert_justif;
	/*ARGB*/
	u32 back_color;
	BoxRecord default_pos;
	StyleRecord	default_style;

	u32 font_count;
	FontRecord *fonts;

	/*unused in isomedia but needed for streamingText*/
	u8 sample_index;
} TextSampleDescriptor;

typedef struct
{
	BASE_DESCRIPTOR
	/*only 0x10 shall be used for 3GP text stream*/
	u8 Base3GPPFormat;
	/*only 0x10 shall be used for StreamingText*/
	u8 MPEGExtendedFormat;
	/*only 0x10 shall be used for StreamingText (base profile, base level)*/
	u8 profileLevel;
	u32 timescale;
	/*0 forbidden, 1: out-of-band desc only, 2: in-band desc only, 3: both*/
	u8 sampleDescriptionFlags;
	/*More negative layer values are towards the viewer*/
	s16 layer;
	/*text track width & height*/
	u16 text_width;
	u16 text_height;
	/*compatible 3GP formats, same coding as 3GPPBaseFormat*/
	u8 nb_compatible_formats;
	u8 compatible_formats[20];
	/*defined in m4_isomedia.h*/
	Chain *sample_descriptions;

	/*if true info below are valid (cf 3GPP for their meaning)*/
	Bool has_vid_info;
	u16 video_width;
	u16 video_height;
	s16 horiz_offset;
	s16 vert_offset;
} TextConfigDescriptor;

/*sepcial function for authoring - convert DSI to TextConfig*/
M4Err OD_GetTextConfig(DefaultDescriptor *dsi, u8 oti, TextConfigDescriptor *cfg);


/*MuxInfo descriptor - parsing only, stored in ESD:extDescr*/
typedef struct {
	BASE_DESCRIPTOR
	/*input location*/
	char *file_name;
	/*input groupID for interleaving*/
	u32 GroupID;
	/*input stream format (not required, guessed from file_name)*/
	char *streamFormat;
	/*time offset in ms from first TS (appends an edit list in mp4)*/
	u32 startTime;

	/*media length to import in ms (from 0)*/
	u32 duration;

	/*SRT/SUB import extensions - only support for text and italic style*/
	char *textNode;
	char *fontNode;

	/*video and SUB import*/
	Double frame_rate;

	/*same as importer flags, cf m4_author.h*/
	u32 import_flags;

	/*indicates input file shall be destryed - used during SWF import*/
	Bool delete_file;
} MuxInfoDescriptor;

typedef struct
{
	BASE_DESCRIPTOR
	/*input type*/
	char *deviceName;
	/*string sensor terminaison (validation) char*/
	char termChar;
	/*string sensor deletion char*/
	char delChar;
	/*device-specific data*/
	char *ui_data;
	u32 ui_data_length;
} UIConfigDescriptor;

/*sepcial function for authoring - convert DSI to UIConfig*/
M4Err OD_GetUIConfig(DefaultDescriptor *dsi, UIConfigDescriptor *cfg);
/*converts UIConfig to dsi - does not destroy input descr but does create output one*/
M4Err OD_EncodeUIConfig(UIConfigDescriptor *cfg, DefaultDescriptor **out_dsi);


/***************************************
			QoS Tags
***************************************/
enum
{
	QoSMaxDelayTag = 0x01,
	QoSPrefMaxDelayTag = 0x02,
	QoSLossProbTag = 0x03,
	QoSMaxGapLossTag = 0x04,
	QoSMaxAUSizeTag = 0x41,
	QoSAvgAUSizeTag = 0x42,
	QoSMaxAURateTag = 0x43
};

/***************************************
			QoS Qualifiers
***************************************/
typedef struct {
	BASE_DESCRIPTOR
	u8 predefined;
	Chain *QoS_Qualifiers;
} QoS_Descriptor;


#define QOS_BASE_QUALIFIER \
	u8 tag;	\
	u32 size;

typedef struct {
	QOS_BASE_QUALIFIER
} QoS_Default;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 MaxDelay;
} QoS_MaxDelay;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 PrefMaxDelay;
} QoS_PrefMaxDelay;

typedef struct {
	QOS_BASE_QUALIFIER
	Float LossProb;
} QoS_LossProb;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 MaxGapLoss;
} QoS_MaxGapLoss;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 MaxAUSize;
} QoS_MaxAUSize;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 AvgAUSize;
} QoS_AvgAUSize;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 MaxAURate;
} QoS_MaxAURate;

typedef struct {
	QOS_BASE_QUALIFIER
	u32 DataLength;		/*max size class : 2^28 - 1*/
	unsigned char *Data;
} QoS_Private;


/*Registration Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 formatIdentifier;
	u32 dataLength;
	unsigned char *additionalIdentificationInfo;
} RegistrationDescriptor;

/*Language Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 langCode;
} LanguageDescriptor;

/*Elementary Stream Descriptor*/
typedef struct
{
	BASE_DESCRIPTOR
	u16 ESID;
	u16 OCRESID;
	u16 dependsOnESID;
	u8 streamPriority;
	char *URLString;
	DecoderConfigDescriptor *decoderConfig;
	SLConfigDescriptor *slConfig;
	IPI_DescrPointer *ipiPtr;
	QoS_Descriptor *qos;
	RegistrationDescriptor *RegDescriptor;
	/*0 or 1 lang desc*/
	LanguageDescriptor *langDesc;
	
	Chain *IPIDataSet;
	Chain *IPMPDescriptorPointers;
	Chain *extensionDescriptors;

} ESDescriptor;


/*Content Classification Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 classificationEntity;
	u16 classificationTable;
	u32 dataLength;
	unsigned char *contentClassificationData;
} ContentClassificationDescriptor;


/*this structure is used in KeyWordDescriptor*/
typedef struct {
	char *keyWord;
} KeyWordItem;

/*Key Word Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 languageCode;
	u8 isUTF8;
	Chain *keyWordsList;
} KeyWordDescriptor;

/*Rating Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 ratingEntity;
	u16 ratingCriteria;
	u32 infoLength;
	unsigned char *ratingInfo;
} RatingDescriptor;


/*Short Textual Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 langCode;
	u8 isUTF8;
	char *eventName;
	char *eventText;
} ShortTextualDescriptor;


/*this structure is used in ExpandedTextualDescriptor*/
typedef struct {
	char *text;
} ETD_ItemText;

/*Expanded Textual Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u32 langCode;
	u8 isUTF8;
	Chain *itemDescriptionList;
	Chain *itemTextList;
	unsigned char *NonItemText;
} ExpandedTextualDescriptor;

/*this structure is used in ContentCreatorNameDescriptor*/
typedef struct {
	u32 langCode;
	u8 isUTF8;
	char *contentCreatorName;
} contentCreatorInfo;

/*Content Creator Name Descriptor
NOTE: the desctructor will delete all the items in the list
(contentCreatorInfo items) */
typedef struct {
	BASE_DESCRIPTOR
	Chain *ContentCreators;
} ContentCreatorNameDescriptor;

/*Content Creation Date Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	unsigned char contentCreationDate[5];
} ContentCreationDateDescriptor;


/*this structure is used in OCICreatorNameDescriptor*/
typedef struct {
	u32 langCode;
	u8 isUTF8;
	char *OCICreatorName;
} OCICreator;

/*OCI Creator Name Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	Chain *OCICreators;
} OCICreatorNameDescriptor;

/*OCI Creation Date Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	unsigned char OCICreationDate[5];
} OCICreationDateDescriptor;


/*this structure is used in SmpteCameraPositionDescriptor*/
typedef struct {
	u8 paramID;
	u32 param;
} SmpteParam;

/*Smpte Camera Position Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u8 cameraID;
	Chain *ParamList;
} SmpteCameraPositionDescriptor;


/*Extension Profile Level Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u8 profileLevelIndicationIndex;
	u8 ODProfileLevelIndication;
	u8 SceneProfileLevelIndication;
	u8 AudioProfileLevelIndication;
	u8 VisualProfileLevelIndication;
	u8 GraphicsProfileLevelIndication;
	u8 MPEGJProfileLevelIndication;
} ExtensionProfileLevelDescriptor;

/*Profile Level Indication Index Descriptor*/
typedef struct {
	BASE_DESCRIPTOR
	u8 profileLevelIndicationIndex;
} ProfileLevelIndicationIndexDescriptor;


/*AVC config descriptor - not a real MPEG-4 descriptor */
/*used for sequenceParameterSetNALUnit and pictureParameterSetNALUnit*/
typedef struct
{
	u16 size;
	char *data;
} AVCConfigSlot;

typedef struct 
{
	u8 configurationVersion;
	u8 AVCProfileIndication;
	u8 profile_compatibility;
	u8 AVCLevelIndication; 
	u8 nal_unit_size;
	
	Chain *sequenceParameterSets;
	Chain *pictureParameterSets;
} AVCConfig;

/*simple constructor/destructor*/
AVCConfig *AVC_NewConfig();
void AVC_DeleteConfig(AVCConfig *cfg);
/*gets AVCConfig from MPEG-4 DSI*/
AVCConfig *AVC_ReadDSI(char *dsi, u32 dsi_size);
/*writes AVCConfig as MPEG-4 DSI*/
M4Err AVC_WriteDSI(AVCConfig *cfg, char **outData, u32 *outSize);

/****************************************************************************

			MPEG-4 SYSTEM - OBJECT DESCRIPTORS COMMANDS DECLARATION

****************************************************************************/


/***************************************
			Commands Tags
***************************************/
enum
{
	ODUpdate_Tag					= 0x01,
	ODRemove_Tag					= 0x02,
	ESDUpdate_Tag					= 0x03,
	ESDRemove_Tag					= 0x04,
	IPMPDUpdate_Tag					= 0x05,
	IPMPDRemove_Tag					= 0x06,

	/*file format reserved*/
	ESDRemove_Ref_Tag				= 0x07,

	ODExecute_Tag					= 0x08,

	IPMPToolDescUpdate_Tag			= 0x09,
	IPMPToolDescRemove_Tag			= 0x0A,
	IPMPToolDescLink_Tag			= 0x0B,
	IPMPToolDescUnlink_Tag			= 0x0C,

	ISO_RESERVED_COMMANDS_BEGIN		= 0x0D,
	ISO_RESERVED_COMMANDS_END		= 0xBF,
	
	USER_RESERVED_COMMANDS_BEGIN	= 0xC0,
	USER_RESERVED_COMMANDS_END		= 0xFE
};

/***************************************
			OD commands
***************************************/
#define BASE_OD_COMMAND \
	u8 tag;

/*the (abstract) base command. */
typedef struct {
	BASE_OD_COMMAND
} ODCommand;

/*the default bcommand*/
typedef struct {
	BASE_OD_COMMAND
	u32 dataSize;
	char *data;
} BaseODCommand;

/*Object Descriptor Update
NB: the list can contain OD or IOD, except internally in the File Format (only MP4_OD)*/
typedef struct
{
	BASE_OD_COMMAND
	Chain *objectDescriptors;
} ObjectDescriptorUpdate;

/*Object Descriptor Remove*/
typedef struct
{
	BASE_OD_COMMAND
	u32 NbODs;
	u16 *OD_ID;
} ObjectDescriptorRemove;

/*Object Descriptor Execute*/
typedef struct
{
	BASE_OD_COMMAND
	u32 NbODs;
	u16 *OD_ID;
} ObjectDescriptorExecute;

/*Elementary Stream Descriptor Update*/
typedef struct
{
	BASE_OD_COMMAND
	u16 ODID;
	Chain *ESDescriptors;
} ESDescriptorUpdate;

/*Elementary Stream Descriptor Remove*/
typedef struct {
	BASE_OD_COMMAND
	u16 ODID;
	u32 NbESDs;
	u16 *ES_ID;
} ESDescriptorRemove;

/*IPMP Descriptor Update*/
typedef struct {
	BASE_OD_COMMAND
	Chain *IPMPDescList;
} IPMPDescriptorUpdate;

/*IPMP Descriptor Remove*/
typedef struct {
	BASE_OD_COMMAND
	u32 NbIPMPDs;
	/*now this is bad: only IPMPv1 descriptors can be removed at run tim...*/
	u8 *IPMPDescID;
} IPMPDescriptorRemove;


/************************************************************
				Media Control Extensions
************************************************************/
typedef struct
{
	BASE_DESCRIPTOR
	Double startTime;
	Double Duration;
	unsigned char *SegmentName;
} SegmentDescriptor;

typedef struct
{
	BASE_DESCRIPTOR
	Double mediaTimeStamp;
} MediaTimeDescriptor;




/********************************************************************
	OD Exports
********************************************************************/

/*OD CODEC object - just a simple reader/writer*/
typedef struct tagODCoDec
{
	BitStream *bs;
	Chain *CommandList;
} ODCoDec;
typedef struct tagODCoDec * LPODCODEC;

/*construction / destruction*/
LPODCODEC OD_NewCodec();
void OD_DeleteCodec(LPODCODEC codec);
/* add a command to the codec command list. */
M4Err OD_AddCommand(LPODCODEC codec, ODCommand *command);
/*encode the current coimmand list - once called the commands are destroyed*/
M4Err OD_EncodeAU(LPODCODEC codec);
/*get the encoded AU. user is responsible of allocated space*/
M4Err OD_GetEncodedAU(LPODCODEC codec, char **outAU, u32 *au_length);
/* set the encoded AU to the codec*/
M4Err OD_SetBuffer(LPODCODEC codec, char *au, u32 au_length);
/*decode the previously set-up AU*/
M4Err OD_DecodeAU(LPODCODEC codec);
/*get the first OD command in the list. Once called, the command is removed 
from the command list. Return NULL when commandList is empty*/
ODCommand *OD_GetCommand(LPODCODEC codec);


/************************************************************
		ODCommand Functions
************************************************************/

/*Commands Creation / Destruction*/
ODCommand *OD_NewCommand(u8 tag);
M4Err OD_DeleteCommand(ODCommand **com);


/************************************************************
		Descriptors Functions
************************************************************/

/*Descriptors Creation / Destruction*/
Descriptor *OD_NewDescriptor(u8 tag);
M4Err OD_DeleteDescriptor(Descriptor **desc);

/*use this function to decode a standalone descriptor
the raw descriptor MUST be formatted with tag and size field!!!
a new desc is created and you must delete it when done*/
M4Err OD_ReadDesc(char *raw_desc, u32 descSize, Descriptor * *outDesc);

/*use this function to encode a standalone descriptor
the desc will be formatted with tag and size field
the output buffer is allocated and you must delete it when done*/
M4Err OD_EncDesc(Descriptor *desc, char **outEncDesc, u32 *outSize);

/*use this function to get the size of a standalone descriptor (including tag and size fields)
return 0 if error*/
u32 OD_GetDescSize(Descriptor *desc);

/*this is usefull to duplicate on the fly a descriptor*/
M4Err OD_DuplicateDescriptor(Descriptor *inDesc, Descriptor **outDesc);


/*This functions handles internally what desc can be added to another desc
and adds it. NO DUPLICATION of the descriptor, so
once a desc is added to its parent, destroying the parent WILL DESTROY 
this descriptor*/
M4Err OD_AddDescToDesc(Descriptor *parentDesc, Descriptor *newDesc);


/*this is a helper for building a preformatted ESDescriptor with decoderConfig, decoderSpecificInfo with no data and 
SLConfig descriptor with predefined*/
ESDescriptor *OD_NewESDescriptor(u32 sl_predefined);


/*Since IPMP V2, we introduce a new set of functions to read / write a list of descriptors
that have no containers (a bit like an OD command, but for descriptors)
This is usefull for IPMPv2 DecoderSpecificInfo which contains a set of IPMP_Declarators
As it could be used for other purposes we keep it generic
you must create the list yourself, the functions just encode/decode from/to the list*/

/*uncompress an encoded list of descriptors. You must pass an empty Chain structure
to know exactly what was in the buffer*/
M4Err OD_ReadDescList(char *raw_list, u32 raw_size, Chain *descList);
/*compress all descriptors in the list into a single buffer. The buffer is allocated
by the lib and must be destroyed by your app
you must pass (outEncList != NULL  && *outEncList == NULL)*/
M4Err OD_EncDescList(Chain *descList, char **outEncList, u32 *outSize);
/*returns size of encoded desc list*/
M4Err OD_SizeDescList(Chain *descList, u32 *outSize);
/*destroy the descriptors in a list but not the list*/
M4Err OD_DeleteDescList(Chain *descList);

/*retuns NULL if unknown, otherwise value*/
const char *OD_GetStreamTypeName(u32 streamType);
u32 OD_GetStreamTypeByName(const char *streamType);

/************************************************************
		QoS Qualifiers Functions
************************************************************/

/*QoS Qualifiers Creation / Destruction*/
QoS_Default *OD_NewQoSQualifier(u8 tag);
M4Err OD_DeleteQoSQualifier(QoS_Default **qos);

/*READ/WRITE functions: QoS qualifiers are special descriptors but follow the same rules as descriptors.
therefore, use OD_ReadDesc and OD_EncDesc for QoS*/

/*same function, but for QoS, as a Qualifier IS NOT a descriptor*/
M4Err OD_AddQualifToQoS(QoS_Descriptor *desc, QoS_Default *qualif);



/*
	OCI Stream AU is a list of OCI event (like OD AU is a list of OD commands)
*/

typedef struct tagOCIEvent *LPOCIEVENT;

LPOCIEVENT NewOCIEvent(u16 EventID);
void DeleteOCIEvent(LPOCIEVENT event);

M4Err OCIEvent_SetStartTime(LPOCIEVENT event, u8 Hours, u8 Minutes, u8 Seconds, u8 HundredSeconds, u8 IsAbsoluteTime);
M4Err OCIEvent_SetDuration(LPOCIEVENT event, u8 Hours, u8 Minutes, u8 Seconds, u8 HundredSeconds);
M4Err OCIEvent_AddDescriptor(LPOCIEVENT event, Descriptor *oci_desc);

M4Err OCIEvent_GetEventID(LPOCIEVENT event, u16 *ID);
M4Err OCIEvent_GetStartTime(LPOCIEVENT event, u8 *Hours, u8 *Minutes, u8 *Seconds, u8 *HundredSeconds, u8 *IsAbsoluteTime);
M4Err OCIEvent_GetDuration(LPOCIEVENT event, u8 *Hours, u8 *Minutes, u8 *Seconds, u8 *HundredSeconds);
u32 OCIEvent_GetDescriptorCount(LPOCIEVENT event);
Descriptor *OCIEvent_GetDescriptor(LPOCIEVENT event, u32 DescIndex);
M4Err OCIEvent_RemoveDescriptor(LPOCIEVENT event, u32 DescIndex);



typedef struct tagOCICodec *LPOCICODEC;

/*construction / destruction
IsEncoder specifies an OCI Event encoder
version is for future extensions, and only 0x01 is valid for now*/
LPOCICODEC OCI_NewCodec(u8 IsEncoder, u8 Version);
void OCI_DeleteCodec(LPOCICODEC codec);

/*				ENCODER FUNCTIONS
add a command to the codec event list. 
The event WILL BE DESTROYED BY THE CODEC after encoding*/
M4Err OCI_AddEvent(LPOCICODEC codec, LPOCIEVENT event);

/*encode AU. The memory allocation is done in place
WARNING: once this function called, the codec event List is empty 
and events destroyed
you must set *outAU = NULL*/
M4Err OCI_EncodeAU(LPOCICODEC codec, char **outAU, u32 *au_length);



/*Decoder: decode the previously set-up AU
the input buffer is cleared once decoded*/
M4Err OCI_DecodeAU(LPOCICODEC codec, char *au, u32 au_length);

/*get the first OCI Event in the list. Once called, the event is removed 
from the event list. Return NULL when the event List is empty
you MUST delete events */
LPOCIEVENT OCI_GetEvent(LPOCICODEC codec);


/*OD dump tools*/
M4Err OD_DumpAU(char *data, u32 dataLength, FILE *trace, u32 indent, Bool XMTDump);
M4Err OD_DumpCommand(void *p, FILE *trace, u32 indent, Bool XMTDump);
M4Err OD_DumpDescriptor(void *ptr, FILE *trace, u32 indent, Bool XMTDump);
M4Err OD_DumpCommandList(Chain *commandList, FILE *trace, u32 indent, Bool XMTDump);

/*OCI dump tools*/
M4Err OCI_DumpEvent(LPOCIEVENT ev, FILE *trace, u32 indent, Bool XMTDump);
M4Err OCI_DumpAU(u8 version, char *au, u32 au_length, FILE *trace, u32 indent, Bool XMTDump);


/*OD parsing tools (XMT/BT)*/
/*returns desc tag based on name*/
u32 OD_GetTagByName(char *descName);
/*field type for OD/QoS/IPMPX/etc*/
enum
{
	/*regular type*/
	DFT_DEFAULT = 0,
	/*single descriptor type*/
	DFT_OD = 1,
	/*descriptor list type*/
	DFT_OD_LIST = 2,
	/*IPMP Data type*/
	DFT_IPMPX = 3,
	/*IPMP Data list type*/
	DFT_IPMPX_LIST = 4,
	/*IPMP ByteArray type*/
	DFT_IPMPX_BA = 5,
	/*IPMP ByteArray list type*/
	DFT_IPMPX_BA_LIST = 6,
};
u32 OD_GetFieldType(Descriptor *desc, char *fieldName);
/*set non-descriptor field value - value string shall be presented without ' or " characters*/
M4Err OD_SetField(Descriptor *desc, char *fieldName, char *val);


/*
	Although this is not really part of the OD framework, it's so related to SLConfig that we keep it here
*/
typedef struct tagSLHeader
{
	u8 accessUnitStartFlag;
	u8 accessUnitEndFlag;
	u8 paddingFlag;
	u8 randomAccessPointFlag;
	u8 OCRflag;
	u8 idleFlag;
	u8 decodingTimeStampFlag;
	u8 compositionTimeStampFlag;
	u8 instantBitrateFlag;
	u8 degradationPriorityFlag;

	u8 paddingBits;
	u16 packetSequenceNumber;
	u64 objectClockReference;
	u16 AU_sequenceNumber;
	u64 decodingTimeStamp;
	u64 compositionTimeStamp;
	u16 accessUnitLength;
	u32 instantBitrate;
	u16 degradationPriority;

	/*this is NOT part of standard SL, only used internally: signals duration of access unit if known
	this is usefull for streams with very random updates, to prevent buffering for instance a subtitle stream
	which is likely to have no updates during the first minutes... expressed in media timescale*/
	u32 au_duration;
	/*ISMACryp extensions*/
	u8 isma_encrypted;
	u64 isma_BSO;
} SLHeader, LPSLHDR;

/*packetize SL-PDU*/
void SL_Packetize(SLConfigDescriptor* slConfig, SLHeader *Header, char *PDU, u32 size, char **outPacket, u32 *OutSize);
/*depacketize SL-PDU*/
void SL_Depacketize(SLConfigDescriptor *slConfig, SLHeader *Header, char *PDU, u32 PDULength, u32 *HeaderLen);




/*
	IPMPX extensions - IPMP Data only (messages are not supported yet)
*/

typedef struct
{
	u32 length;
	char *data;
} IPMPX_ByteArray;

/*IPMPX authentication descriptors*/
#define IPMPX_AUTH_DESC	\
	u8 tag;	\

typedef struct
{
	IPMPX_AUTH_DESC
} IPMPX_Authentication;

enum
{
	IPMPX_AUTH_Forbidden_Tag = 0x00,
	IPMPX_AUTH_AlgorithmDescr_Tag = 0x01,
	IPMPX_AUTH_KeyDescr_Tag = 0x02,
};

typedef struct
{
	IPMPX_AUTH_DESC
	char *keyBody;
	u32 keyBodyLength;
} IPMPX_AUTH_KeyDescriptor;

typedef struct
{
	IPMPX_AUTH_DESC
	/*used if no specAlgoID*/
	u16 regAlgoID;
	IPMPX_ByteArray *specAlgoID;
	IPMPX_ByteArray *OpaqueData;
} IPMPX_AUTH_AlgorithmDescriptor;


/*IPMP data messages*/
enum 
{
	IPMPX_Forbidden_Tag = 0x00,
	IPMPX_OpaqueData_Tag = 0x01,
	IPMPX_AudioWatermarkingInit_Tag = 0x02,
	IPMPX_VideoWatermarkingInit_Tag = 0x03,
	IPMPX_SelectiveDecryptionInit_Tag = 0x04,
	IPMPX_KeyData_Tag = 0x05,
	IPMPX_SendAudioWatermark_Tag = 0x06,
	IPMPX_SendVideoWatermark_Tag = 0x07,
	IPMPX_RightsData_Tag = 0x08,
	IPMPX_SecureContainer_Tag = 0x09,
	IPMPX_AddToolNotificationListener_Tag = 0x0A,
	IPMPX_RemoveToolNotificationListener_Tag = 0x0B,
	IPMPX_InitAuthentication_Tag = 0x0C,
	IPMPX_MutualAuthentication_Tag = 0x0D,
	IPMPX_UserQuery_Tag = 0x0E,
	IPMPX_UserQueryResponse_Tag = 0x0F,
	IPMPX_ParametricDescription_Tag = 0x10,
	IPMPX_ToolParamCapabilitiesQuery_Tag = 0x11,
	IPMPX_ToolParamCapabilitiesResponse_Tag = 0x12,
	/*NO ASSOCIATED STRUCTURE*/
	IPMPX_GetTools_Tag = 0x13,
	IPMPX_GetToolsResponse_Tag = 0x14,
	IPMPX_GetToolContext_Tag = 0x15,
	IPMPX_GetToolContextResponse_Tag = 0x16,
	IPMPX_ConnectTool_Tag = 0x17,
	IPMPX_DisconnectTool_Tag = 0x18,
	IPMPX_NotifyToolEvent_Tag = 0x19,
	IPMPX_CanProcess_Tag = 0x1A,
	IPMPX_TrustSecurityMetadata_Tag = 0x1B,
	IPMPX_ToolAPI_Config_Tag = 0x1C,

	/*ISMA*/
	IPMPX_ISMACryp_Tag = 0xD0, 

	/*intern ones for parsing (not real datas)*/
	IPMPX_TrustedTool_Tag = 0xA1,
	IPMPX_TrustSpecification_Tag = 0xA2,
	/*emulate algo descriptors as base IPMP classes for parsing...*/
	IPMPX_AlgorithmDescr_Tag = 0xA3,
	IPMPX_KeyDescr_Tag = 0xA4,
	IPMPX_ParamDescrItem_Tag = 0xA5,
	IPMPX_SelEncBuffer_Tag = 0xA6,
	IPMPX_SelEncField_Tag = 0xA7,
};

typedef u8 IPMPX_Date[5];


#define IPMPX_DATA_BASE	\
	u8 tag;	\
	u8 Version;	\
	u8 dataID;	\

typedef struct
{
	IPMPX_DATA_BASE
} IPMPX_Data;

typedef struct
{
	IPMPX_DATA_BASE
	u32 Context;
	u8 AuthType;
} IPMPX_InitAuthentication;

/*NOT a real DATA, only used as data for parsing*/
typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_Date startDate;
	u8 attackerProfile;
	u32 trustedDuration;
	IPMPX_ByteArray	*CCTrustMetadata;
} IPMPX_TrustSpecification;

/*NOT a real DATA, only used as data for parsing*/
typedef struct
{
	IPMPX_DATA_BASE
	bin128 toolID;	
	IPMPX_Date AuditDate;
	Chain *trustSpecifications;
} IPMPX_TrustedTool;

typedef struct _ipmpx_TrustSecurityMetadata
{
	IPMPX_DATA_BASE
	Chain *TrustedTools;
} IPMPX_TrustSecurityMetadata;


typedef struct
{
	IPMPX_DATA_BASE
	Bool failedNegotiation;

	Chain *candidateAlgorithms;
	Chain *agreedAlgorithms;
	IPMPX_ByteArray *AuthenticationData;

	/*inclAuthCodes will be set if any of the members is set (cf spec...)*/
	u32 certType;
	/*IPMPX_ByteArray list*/
	Chain *certificates;
	IPMPX_AUTH_KeyDescriptor *publicKey;
	IPMPX_ByteArray *opaque;
	IPMPX_TrustSecurityMetadata *trustData;
	IPMPX_ByteArray *authCodes;
} IPMPX_MutualAuthentication;

typedef struct
{
	IPMPX_DATA_BASE
	/*if set MAC is part of the encrypted data*/
	Bool isMACEncrypted;

	IPMPX_ByteArray *encryptedData;
	IPMPX_Data *protectedMsg;
	IPMPX_ByteArray *MAC;
} IPMPX_SecureContainer;

/*IPMP_Tool is defined in m4_descriptors.h*/
typedef struct
{
	Chain *ipmp_tools;
} IPMPX_GetToolsResponse;

typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_ByteArray	*main_class;
	IPMPX_ByteArray	*subClass;
	IPMPX_ByteArray	*typeData;
	IPMPX_ByteArray	*type;
	IPMPX_ByteArray	*addedData;
} IPMPX_ParametricDescriptionItem;

typedef struct _tagIPMPXParamDesc
{
	IPMPX_DATA_BASE
	IPMPX_ByteArray *descriptionComment;
	u8 majorVersion;
	u8 minorVersion;
	/*list of IPMPX_ParametricDescriptionItem*/
	Chain *descriptions;
} IPMPX_ParametricDescription;

typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_ParametricDescription *description;
} IPMPX_ToolParamCapabilitiesQuery;

typedef struct
{
	IPMPX_DATA_BASE
	Bool capabilitiesSupported;
} IPMPX_ToolParamCapabilitiesResponse;


typedef struct
{
	IPMPX_DATA_BASE
	IPMP_Descriptor *toolDescriptor;
} IPMPX_ConnectTool;

typedef struct
{
	IPMPX_DATA_BASE
	u32 IPMP_ToolContextID;
} IPMPX_DisconnectTool;


typedef struct
{
	IPMPX_DATA_BASE
    u8 scope;
	u16 IPMP_DescriptorIDEx;
} IPMPX_GetToolContext;


typedef struct
{
	IPMPX_DATA_BASE
    u16 OD_ID;
	u16 ESD_ID;
    u32 IPMP_ToolContextID;
} IPMPX_GetToolContextResponse;

/*IPMPX_LISTEN_Types*/
enum
{
	IPMPX_LISTEN_CONNECTED = 0x00,
	IPMPX_LISTEN_CONNECTIONFAILED = 0x01,
	IPMPX_LISTEN_DISCONNECTED = 0x02,
	IPMPX_LISTEN_DISCONNECTIONFAILED = 0x03,
	IPMPX_LISTEN_WATERMARKDETECTED = 0x04,
};

typedef struct
{
	IPMPX_DATA_BASE
	u8 scope;
	/*events to listen to*/
	u8 eventTypeCount;
	u8 eventType[10];
} IPMPX_AddToolNotificationListener;

typedef struct
{
	IPMPX_DATA_BASE
	u8 eventTypeCount;
	u8 eventType[10];
} IPMPX_RemoveToolNotificationListener;

typedef struct
{
	IPMPX_DATA_BASE
	u16 OD_ID;
	u16 ESD_ID;
	u8 eventType;
	u32 IPMP_ToolContextID;
} IPMPX_NotifyToolEvent;

typedef struct
{
	IPMPX_DATA_BASE
	Bool canProcess;
} IPMPX_CanProcess;

typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_ByteArray *opaqueData;
} IPMPX_OpaqueData;


typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_ByteArray *keyBody;
	/*flags meaning
	hasStartDTS = 1;
	hasStartPacketID = 1<<1;
	hasExpireDTS = 1<<2;
	hasExpirePacketID = 1<<3
	*/
	u32 flags;

	u64 startDTS;
	u32 startPacketID;
	u64 expireDTS;
	u32 expirePacketID;
	IPMPX_ByteArray *OpaqueData;
} IPMPX_KeyData;

typedef struct
{
	IPMPX_DATA_BASE
	IPMPX_ByteArray *rightsInfo;	
} IPMPX_RightsData;


/*not a real IPMPX_Data in spec, but emulated as if for parsing*/
typedef struct
{
	IPMPX_DATA_BASE
	bin128 cipher_Id; 
	u8 syncBoundary;
	/*block mode if stream cypher info is NULL*/
	u8 mode;  
	u16 blockSize;
	u16 keySize;
	IPMPX_ByteArray *Stream_Cipher_Specific_Init_Info; 
} IPMPX_SelEncBuffer;

/*not a real IPMPX_Data in spec, but emulated as if for parsing*/
typedef struct
{
	IPMPX_DATA_BASE
	u8 field_Id; 
	u8 field_Scope;
	u8 buf; 

	u16 mappingTableSize;
	u16 *mappingTable;
	IPMPX_ByteArray *shuffleSpecificInfo;
} IPMPX_SelEncField;


/*mediaTypeExtension*/
enum
{
	IPMPX_SE_MT_ISO_IEC = 0x00,
	IPMPX_SE_MT_ITU = 0x01
	/*the rest is reserved or forbidden*/
};

/*compliance*/
enum
{
	IPMPX_SE_COMP_FULLY = 0x00,
	IPMPX_SE_COMP_VIDEO_PACKETS = 0x01,
	IPMPX_SE_COMP_VIDEO_VOP = 0x02,
	IPMPX_SE_COMP_VIDEO_NONE = 0x03,
	IPMPX_SE_COMP_VIDEO_GOB = 0x04,
	/*0x05-2F	ISO Reserved for video*/
	IPMPX_SE_COMP_AAC_DF = 0x30,
	IPMPX_SE_COMP_AAC_NONE = 0x31,
	/*
	0x32 -  0x5F	ISO Reserved for audio
	0x60 - 0xCF	ISO Reserved
	0xD0 - 0xFE	User Defined
	0xFF	Forbidden
	*/
};

/*syncBoundary*/
enum
{
	IPMPX_SE_SYNC_VID7EO_PACKETS = 0x00,
	IPMPX_SE_SYNC_VIDEO_VOP = 0x01,
	IPMPX_SE_SYNC_VIDEO_GOV = 0x02,
	/*0x03-2F	ISO Reserved for video,*/
	IPMPX_SE_SYNC_AAC_DF = 0x30,
	/*0x31 -  0x5F	ISO Reserved for audio
	0x60 - 0xCF	ISO Reserved
	0xD0 - 0xFE	User Defined
	0xFF	Forbidden
	*/
};

/*field_Id*/
enum
{
	IPMPX_SE_FID_VIDEO_MV = 0x00,
	IPMPX_SE_FID_VIDEO_DC = 0x01,
	IPMPX_SE_FID_VIDEO_DCT_SIGN = 0x02,
	IPMPX_SE_FID_VIDEO_DQUANT = 0x03,
	IPMPX_SE_FID_VIDEO_DCT_COEF = 0x04,
	IPMPX_SE_FID_VIDEO_ALL = 0x05,
	/*0x06-2F	ISO Reserved for video*/
	IPMPX_SE_FID_AAC_SIGN = 0x30,
	IPMPX_SE_FID_AAC_CODEWORDS = 0x31,
	IPMPX_SE_FID_AAC_SCALE = 0x32,
	/*0x32 -  0x5F	ISO Reserved for audio
	0x60 - 0xCF	ISO Reserved
	0xD0 - 0xFE	User Defined
	0xFF	Forbidden*/
};


typedef struct
{
	IPMPX_DATA_BASE
	u8 mediaTypeExtension; 
	u8 mediaTypeIndication;
	u8 profileLevelIndication; 
	u8 compliance;

	Chain *SelEncBuffer;

	Chain *SelEncFields;

	u16 RLE_DataLength;
	u16 *RLE_Data;
} IPMPX_SelectiveDecryptionInit;


/*watermark init ops*/
enum
{
	WM_INSERT = 0,
	WM_EXTRACT = 1,
	WM_REMARK = 2,
	WM_DETECT_COMPRESSION = 3,
};

/*used for both audio and video WM init*/
typedef struct
{
	IPMPX_DATA_BASE
	/*
	for audio: PCM defined (0x01) and all audio objectTypeIndications
	for video: YUV defined (0x01) and all visual objectTypeIndications
	*/
	u8 inputFormat;
	u8 requiredOp;

	/*valid for audio WM, inputFormat=0x01*/
	u8 nChannels;
	u8 bitPerSample;
	u32 frequency;

	/*valid for video WM, inputFormat=0x01*/
	u16 frame_horizontal_size;
	u16 frame_vertical_size;
	u8 chroma_format;

	u32 wmPayloadLen;
	char *wmPayload;

	u16 wmRecipientId;
	
	u32 opaqueDataSize;
	char *opaqueData;
} IPMPX_WatermarkingInit;



/*WM status*/
enum
{
	WM_PAYLOAD = 0,
	WM_NOPAYLOAD = 1,
	WM_NONE = 2,
	WM_UNKNOWN = 3
};

/*compression status*/
enum
{
	WM_COMPRESSION = 0,
	WM_NO_COMPRESSION = 1,
	WM_COMPRESSION_UNKNOWN = 2,
};

typedef struct
{
	IPMPX_DATA_BASE
	u8 wm_status;
	u8 compression_status;
	/*if payload is set, status is FORCED to AUDIO_WM_PAYLOAD*/
	IPMPX_ByteArray *payload;
	IPMPX_ByteArray *opaqueData;
} IPMPX_SendWatermark;


typedef struct
{
	IPMPX_DATA_BASE
	/*GPAC only supports non-0 IDs*/
	u32 Instantiation_API_ID;
	u32 Messaging_API_ID;
	IPMPX_ByteArray *opaqueData;
} IPMPX_ToolAPI_Config;

typedef struct
{
	IPMPX_DATA_BASE
	u8 cryptoSuite;
	u8 IV_length;
	Bool use_selective_encryption;
	u8 key_indicator_length;
} IPMPX_ISMACryp;


/*constructor/destructor*/
IPMPX_Data *IPMPX_NewData(u8 tag);
void IPMPX_DeleteData(IPMPX_Data *p);

/*parse from bitstream*/
M4Err IPMPX_ParseData(BitStream *bs, IPMPX_Data **out_data);
/*get IPMP_Data contained size (eg without tag & sizeofinstance)*/
u32 IPMPX_GetDataSize(IPMPX_Data *p);
/*get fulml IPMP_Data encoded size (eg with tag & sizeofinstance)*/
u32 IPMPX_GetDataFullSize(IPMPX_Data *p);
/*writes IPMP_Data to buffer*/
M4Err IPMPX_WriteData(BitStream *bs, IPMPX_Data *_p);

/*returns IPMPX_Tag based on name*/
u8 IPMPX_GetTagByName(char *dataName);
/*return values: cf m4_descriptors.h */
u32 IPMPX_GetFieldType(IPMPX_Data *p, char *fieldName);
M4Err IPMPX_SetField(IPMPX_Data *desc, char *fieldName, char *val);
/*assign subdata*/
M4Err IPMPX_SetSubData(IPMPX_Data *desc, char *fieldName, IPMPX_Data *subdesc);
/*assign bytearray*/
M4Err IPMPX_SetByteArray(IPMPX_Data *p, char *field, char *str);

/*ipmpx dumper*/
M4Err IPMPX_DumpData(IPMPX_Data *_p, FILE *trace, u32 indent, Bool XMTDump);



#ifdef __cplusplus
}
#endif

#endif	/*M4_DESCRIPTORS_H*/
