/*
 *			GPAC - MPEG-4 Systems C Development Kit
 *
 *			Copyright (c) Jean Le Feuvre 2000-2005 
 *					All rights reserved
 *
 *  This file is part of GPAC / Authoring Tools 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_AUTHORING_H_
#define __M4_AUTHORING_H_


#ifdef __cplusplus
extern "C" {
#endif

#include <gpac/m4_isomedia.h>
#include <gpac/m4_ietf.h>
#include <gpac/m4_scenegraph_vrml.h>

/*formats progress to stdout, exported for MP4Box - title IS a string, but declared as void * to avoid GCC warnings!! */
void MP4T_OnProgress(void *title, u32 done, u32 total);

/*setup interleaving for storage*/
M4Err MP4T_MakeInterleaved(M4File *mp4file, Double TimeInSec);
/*save file as fragmented movie*/
M4Err MP4T_FragmentMovie(M4File *input, char *output_file, Double MaxFragmentDuration, void (*OnProgress)(void *cbk, u32 total, u32 done), void *cbk);

/*adds chapter info contained in file - import_fps is optional (most formats don't use it), defaults to 25*/
M4Err MP4T_SetChapterFile(M4File *file, char *chap_file, Double import_fps);


/*RTP<->SL mapping*/
typedef struct 
{
	/*1 - required options*/

	/*mode, or "" if no mode ("generic" should be used instead)*/
	char mode[30];
	
	/*config of the stream if carried in SDP*/
	char *config;
	u32 configSize;
	/* Stream Type*/
	u8 StreamType;
	/* stream profile and level indication - for AVC/H264, 0xPPCCLL, with PP:profile, CC:compatibility, LL:level*/
	u32 PL_ID;


	/*2 - optional options*/
	
	/*size of AUs if constant*/
	u32 ConstantSize;
	/*duration of AUs if constant, in RTP timescale*/
	u32 ConstantDuration;

	/* Object Type Indication */
	u8 ObjectTypeIndication;
	/*audio max displacement when interleaving (eg, de-interleaving window buffer max length) in RTP timescale*/
	u32 maxDisplacement;
	/*de-interleaveBufferSize if not recomputable from maxDisplacement*/
	u32 deinterleaveBufferSize;
	
	/*The number of bits on which the AU-size field is encoded in the AU-header*/
	u32 SizeLength;
	/*The number of bits on which the AU-Index is encoded in the first AU-header*/
	u32 IndexLength;
	/*The number of bits on which the AU-Index-delta field is encoded in any non-first AU-header*/
	u32 IndexDeltaLength;

	/*The number of bits on which the DTS-delta field is encoded in the AU-header*/
	u32 DTSDeltaLength;
	/*The number of bits on which the CTS-delta field is encoded in the AU-header*/
	u32 CTSDeltaLength;
	/*random access point flag present*/
	Bool RandomAccessIndication;
	
	/*The number of bits on which the Stream-state field is encoded in the AU-header (systems only)*/
	u32 StreamStateIndication;
	/*The number of bits that is used to encode the auxiliary-data-size field 
	(no normative usage of this section)*/
	u32 AuxiliaryDataSizeLength;

	/*ISMACryp stuff*/
	u8 IV_length, IV_delta_length;
	u8 KI_length;

	/*internal stuff*/
	/*len of first AU header in an RTP payload*/
	u32 auh_first_min_len;
	u32 auh_min_len;
} RTPSLMap;
	

/*packetizer config flags - some flags are dynamically re-assigned when detecting multiSL / B-Frames / ...*/
enum
{
	/*forces MPEG-4 generic transport if MPEG-4 systems mapping is available*/
	M4HF_ForceMPEG4 =	(1),
	/*Enables AUs concatenation in an RTP packet (if payload supports it) - this forces M4HF_SignalSize for MPEG-4*/
	M4HF_UseMulti	=	(1<<1),
	/*if set, audio interleaving is used if payload supports it (forces M4HF_UseMulti flag)
		THIS IS CURRENTLY NOT IMPLEMENTED*/
	M4HF_UseInterleaving =	(1<<2),
	/*uses static RTP payloadID if any defined*/
	M4HF_UseStatic =	(1<<3),

	/*MPEG-4 generic transport option*/
	/*if flag set, RAP flag is signaled in RTP payload*/
	M4HF_SignalRAP	=	(1<<4),
	/*if flag set, AU indexes are signaled in RTP payload*/
	M4HF_SignalIDX	=	(1<<5),
	/*if flag set, AU size is signaled in RTP payload*/
	M4HF_SignalSize	=	(1<<6),
	/*if flag set, CTS is signaled in RTP payload - DTS is automatically set if needed*/
	M4HF_SignalTS	=	(1<<7),

	/*use LATML payload for AAC-LC*/
	M4HF_UseLATM	=	(1<<8),

	/*ISMACryp options*/
	/*signals that input data is selectively encrypted (eg not all input frames are encrypted) 
	- this is usually automatically set by hinter*/
	M4HF_SelectiveEncryption =	(1<<10),
	/*signals that each sample will have its own key indicator - ignored in non-multi modes
	if not set and key indicator changes, a new RTP packet will be forced*/
	M4HF_KeyIndicatorPerAU =	(1<<11),
};

/*creates a new track hinter
		RTP options
	@Path_MTU: network transmission unit size
	@max_ptime: maximum packet duration in ms (only relevant for aggregated payloads)
	@default_rtp_rate: default clock rate for payloads with configurable clock rate. 
		Value 0 means default rate of 90000 Hz (default MPEG rtp rates)
	@hint_flags: rtp packetizer flags - cf above
	@PayloadID: RTP payload ID to be used (can be one of the above defined or yours cf RFC 1889)
		MP4 options
	@CopyMedia: media data is copied into hint tracks (bigger files, less server load)
	@InterleaveGroupID, InterleaveGroupPriority: cf above
		Init & callback
	@OnProgress, cbk_obj: progress callback 
	@e: return error code if failure
*/
typedef struct _tagM4RTPHinter *LPMP4RTPHINTER;
LPMP4RTPHINTER NewTrackHinter(M4File *file, u32 TrackNum, 
							u32 Path_MTU, u32 max_ptime, u32 default_rtp_rate, u32 hint_flags, u8 PayloadID, 
							Bool copy_media, u32 InterleaveGroupID, u8 InterleaveGroupPriority,
							void (*OnProgress)(void *cbk_obj, u32 done, u32 total), void *cbk_obj, M4Err *e);
/*delete the track hinter*/
void MP4T_DeleteHinter(LPMP4RTPHINTER tkHinter);
/*hints all samples in the media track*/
M4Err MP4T_ProcessTrack(LPMP4RTPHINTER tkHint);
/*returns media bandwidth in kbps*/
u32 MP4T_GetHinterBandwith(LPMP4RTPHINTER tkHinter);
/*retrieves hinter flags*/
u32 MP4T_GetHinterFlags(LPMP4RTPHINTER tkHinter);
/*retrieves rtp payload name 
	@payloadName: static buffer for retrieval, minimum 30 bytes
*/
void MP4T_GetHinterPayloadName(LPMP4RTPHINTER tkHint, char *payloadName);

/*finalizes hinting process for the track (setup flags, write SDP for RTP, ...)
	@AddSystemInfo: if non-0, systems info are duplicated in the SDP (decoder cfg, PL IDs ..)
*/
M4Err MP4T_FinalizeHintTrack(LPMP4RTPHINTER tkHint, Bool AddSystemInfo);

/*SDP IOD flag*/
enum
{
	/*no IOD included*/
	SDP_IOD_NONE = 0,
	/*base64 encoding of the regular MPEG-4 IOD*/
	SDP_IOD_REGULAR,
	/*base64 encoding of IOD containing BIFS and OD tracks (one AU only) - this is used for ISMA 1.0 profiles
	note that the "hinted" file will loose all systems info*/
	SDP_IOD_ISMA,
	/*same as ISMA but removes all clock references from IOD*/
	SDP_IOD_ISMA_STRICT,
};

/*finalizes hinting process for the file (setup flags, write SDP for RTP, ...)
	@IOD_Profile: see above
	@bandwidth: total bandwidth in kbps of all hinted tracks, 0 means no bandwidth info at session level
*/
M4Err MP4T_FinalizeHintMovie(M4File *file, u32 IOD_Profile, u32 bandwidth);


/*
		Generic packetization tools - used by track hinters and future live tools
*/

/*currently supported payload types*/
enum 
{
	/*not defined*/
	RTP_PAYT_UNKNOWN,
	/*use generic MPEG-4 transport - RFC 3016 and RFC 3640*/
	RTP_PAYT_MPEG4,
	/*use generic MPEG-1/2 audio and video transport - RFC 2250*/
	RTP_PAYT_MPEG12,
	/*use H263 transport - RFC 2429*/
	RTP_PAYT_H263,
	/*use AMR transport - RFC 3267*/
	RTP_PAYT_AMR,
	/*use AMR-WB transport - RFC 3267*/
	RTP_PAYT_AMR_WB,
	/*use QCELP transport - RFC 2658*/
	RTP_PAYT_QCELP,
	/*use EVRC/SMV transport - RFC 3558*/
	RTP_PAYT_EVRC_SMV,
	/*use 3GPP Text transport - no RFC yet, only draft*/
	RTP_PAYT_3GPP_TEXT,
	/*use H264 transport - no RFC yet, only draft*/
	RTP_PAYT_H264_AVC,
	/*use LATM for AAC-LC*/
	RTP_PAYT_LATM,
};

/*generic rtp builder (packetizer)*/
typedef struct _rtpbuilder *LPM4RTPBUILDER;

/*creates a new builder
	@hintType: hint media type, one of the above
	@flags: hint flags (cf above)
	@slc: user-given SL config to use. If none specified, default RFC config is used
	@cbk_obj: callback object passed back in functions
	@OnNewPacket: callback function starting new RTP packet
		@header: rtp hreader for new packet - note that RTP header flags are not used until PacketDone is called
	@OnPacketDone: callback function closing current RTP packet
		@header: final rtp hreader for packet
	@OnDataReference: optional, to call each time data from input buffer is added to current RTP packet. 
		If not set, data must be added through OnData
		@payload_size: size of reference data
		@offset_from_orig: start offset in input buffer
	@OnData: to call each time data is added to current RTP packet (either extra data from payload or
		data from input when not using referencing)
		@is_head: signal the data added MUST be inserted at the begining of the payload. Otherwise data
		is concatenated as recieved
*/
LPM4RTPBUILDER NewRTPBuilder(u32 hintType, 
						SLConfigDescriptor *slc, 
						u32 flags,
						void *cbk_obj, 
						void (*OnNewPacket)(void *cbk, RTPHeader *header),
						void (*OnPacketDone)(void *cbk, RTPHeader *header),
						void (*OnDataReference)(void *cbk, u32 payload_size, u32 offset_from_orig),
						void (*OnData)(void *cbk, char *data, u32 data_size, Bool is_head)
					);

/*destroy builder*/
void M4RTP_DeleteBuilder(LPM4RTPBUILDER builder);

/*
		init the builder
	@PathMTU: the network transmission unit size (UDP packet size for IP, ..)
	@max_ptime: maximum packet duration IN RTP TIMESCALE
	@StreamType: MPEG-4 system stream type - MUST always be provided for payloads format specifying 
		audio or video streams
	@OTI : MPEG-4 system objectTypeIndication - may be 0 if stream is not mpeg4 systems

			*** all other params are for MultiSL draft ***
	
	  @avgSize: average size of an AU. This is not always known (real-time encoding). 
In this case you should specify a rough compute indicating how many packets could be 
stored per RTP packet. for ex AAC stereo at 44100 k / 64kbps , one AU ~= 380 bytes
so 3 AUs for 1500 MTU is ok - BE CAREFULL: MultiSL adds some SL info on top of the 12
byte RTP header so you should specify a smaller size
The packetizer will ALWAYS make sure there's no pb storing the packets so specifying 
more will result in a slight overhead in the SL mapping but the gain to singleSL 
will still be worth it.
	-Nota: at init, the packetizer can decide to switch to SingleSL if the average size 
specified is too close to the PathMTU

	@maxSize: max size of an AU. If unknown (real-time) set to 0
	@avgTS: average CTS progression (1000/FPS for video)
	@maxDTS: maximum DTS offset in case of bidirectional coding. 
	@IV_length: size (in bytes) of IV when ISMACrypted
	@KI_length: size (in bytes) of key indicator when ISMACrypted
	@pref_mode: MPEG-4 generic only, specifies the payload mode - can be NULL (mode generic)
*/

void M4RTP_InitBuilder(LPM4RTPBUILDER builder, u8 PayloadType, u32 PathMTU, u32 max_ptime,
					   u32 StreamType, u32 OTI, u32 PL_ID,
					   u32 avgSize, u32 maxSize, 
					   u32 avgTS, u32 maxDTS,
					   u8 IV_length, u8 KI_length,
					   char *pref_mode);

/*set frame crypto info*/
void M4RTP_SetCrypInfo(LPM4RTPBUILDER builder, u64 IV, char *key_indicator, Bool is_encrypted);
/*packetize input buffer
@data, @data_size: input buffer
@IsAUEnd: set to one if this buffer is the last of the AU
@FullAUSize: complete access unit size if known, 0 otherwise
@duration: sample duration in rtp timescale (only needed for 3GPP text streams)
@descIndex: sample description index (only needed for 3GPP text streams)
*/
M4Err M4RTP_ProcessData(LPM4RTPBUILDER builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex);

/*format the "fmtp: " attribute for the MPEG-4 generic packetizer. sdpline shall be at least 2000 char*/
M4Err M4RTP_FormatMPEG4_SDP(LPM4RTPBUILDER builder, char *payload_name, char *sdpLine, char *dsi, u32 dsi_size);
/*formats SDP payload name and media name - both MUST be at least 20 bytes*/
Bool M4RTP_GetPayloadName(LPM4RTPBUILDER builder, char *szPayloadName, char *szMediaName);

/*basic MPEG-4 visual object parser (DSI extraction and timing/framing)*/
typedef struct
{
	u8 VideoPL;
	u8 RAP_stream, objectType, has_shape, enh_layer;
	/*video resolution*/
	u16 width, height;
	/*pixel aspect ratio*/
	u8 par_num, par_den;

	u16 clock_rate;
	u8 NumBitsTimeIncrement;
	u32 time_increment;
} M4VDecoderSpecificInfo;


typedef struct _tagM4V_Parser *LPM4VPARSER;

LPM4VPARSER M4V_NewParser(unsigned char *data, u32 data_size);
void M4V_DeleteParser(LPM4VPARSER m4v);
M4Err M4V_ParseConfig(LPM4VPARSER m4v, M4VDecoderSpecificInfo *dsi);

/*get a frame (can contain GOP). The parser ALWAYS resync on the next object in the bitstream
thus you can seek the bitstream to copy the payload without re-seeking it */
M4Err M4V_GetFrame(LPM4VPARSER m4v, M4VDecoderSpecificInfo dsi, u8 *frame_type, u32 *time_inc, u32 *size, u32 *start, Bool *is_coded);
/*returns current object start in bitstream*/
u32 M4V_GetObjectStartPos(LPM4VPARSER m4v);
/*returns 1 if current object is a valid MPEG-4 Visual object*/
Bool M4V_IsValidObjectType(LPM4VPARSER m4v);
/*returns readable description of profile*/
const char *M4V_VideoProfileName(u8 video_pl);
/*decodes DSI*/
M4Err M4V_GetConfig(char *rawdsi, u32 rawdsi_size, M4VDecoderSpecificInfo *dsi);
/*rewrites PL code in DSI*/
void M4V_RewritePL(unsigned char **io_dsi, u32 *io_dsi_len, u8 PL);

/*MP3 tools*/
u8 MP3_GetNumChannels(u32 hdr);
u16 MP3_GetSamplingRate(u32 hdr);
u16 MP3_GetSamplesPerFrame(u32 hdr);
u16 MP3_GetBitRate(u32 hdr);
u8 MP3_GetObjectTypeIndication(u32 hdr);
u8 MP3_GetLayer(u32 hdr);
u8 MP3_GetVersion(u32 hdr);
const char *MP3_GetVersionName(u32 hdr);
u16 MP3_GetFrameSize(u32 hdr);
u32 MP3_GetNextHeader(FILE* in);
u32 MP3_GetNextHeaderMem(char *buffer, u32 size, u32 *pos);

/*vorbis tools*/
typedef struct
{
	u32 sample_rate, channels, version;
	s32 max_r, avg_r, low_r;
	u32 min_block, max_block;

	/*do not touch, parser private*/
	Bool is_init;
	u32 modebits;
	Bool mode_flag[64];
} VorbisParser;

/*call with vorbis header packets - you MUST initialize the structure to 0 before!!
returns 1 if success, 0 if error.*/
Bool VorbisParseHeader(VorbisParser *vp, char *data, u32 data_len);
/*returns 0 if init error or not a vorbis frame, otherwise returns the number of audio samples
in this frame*/
u32 VorbisCheckFrame(VorbisParser *vp, char *data, u32 data_length);


enum M4A_ObjectTypes
{
    M4A_AAC_Main = 1,
    M4A_AAC_LC = 2,
    M4A_AAC_SBR = 3,
    M4A_AAC_LTP = 4,
    M4A_SBR = 5,
    M4A_AAC_Scalable = 6,
    M4A_TwinVQ = 7,
    M4A_CELP = 8, 
    M4A_HVXC = 9,
    M4A_TTSI = 12,
    M4A_Main_synthetic = 13,
    M4A_Wavetable_Synthesis = 14,
    M4A_General_MIDI = 15,
    M4A_Algorithmic_Synthesis_Audio_FX = 16,
    M4A_ER_AAC_LC = 17,
    M4A_ER_AAC_LTP = 19,
    M4A_ER_AAC_scalable = 20,
    M4A_ER_TwinVQ = 21,
    M4A_ER_BSAC = 22,
    M4A_ER_AAC_LD = 23,
    M4A_ER_CELP = 24,
    M4A_ER_HVXC = 25,
    M4A_ER_HILN = 26,
    M4A_ER_Parametric = 27
};

static const u32 m4a_sample_rates[] =
{
    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 
	16000, 12000, 11025, 8000, 7350, 0, 0, 0
};

/*get Audio type from dsi. return audio codec type:*/
typedef struct
{
	u32 nb_chan;
	u32 base_object_type, base_sr, base_sr_index;
	/*SBR*/
	Bool has_sbr;
	u32 sbr_object_type, sbr_sr, sbr_sr_index;
	/*PL indication*/
	u8 audioPL;
} M4ADecoderSpecificInfo;
/*parses dsi and updates audioPL*/
M4Err M4A_GetConfig(char *dsi, u32 dsi_size, M4ADecoderSpecificInfo *cfg);
/*gets audioPL for given cfg*/
u32 M4A_GetProfile(M4ADecoderSpecificInfo *cfg);
const char *M4A_GetObjectTypeName(u32 objectType);
const char *M4A_AudioProfileName(u8 audio_pl);


typedef struct
{
	u32 bitrate;
	u32 sample_rate;
	u32 framesize;
	u32 channels;
} AC3Header;

Bool AC3_ParseHeader(u8 *buffer, u32 buffer_size, u32 *pos, AC3Header *out_hdr);


/*guess which std this file refers to. return value:
	ISO_Media_File: unrecognized std
	GPP_V5_File: 3GP file (max 1 audio, 1 video) without text track
	GPP_V6_File: 3GP file (max 1 audio, 1 video) with text track
	GPP_GEN_File: 3GP file multitrack file
	GPP2_V1_File: 3GP2 file
	H264_AVC_File: AVC file
	FCC("ISMA"): ISMA file (may overlap with 3GP)
	MP4_V2_File: any generic MP4 file (eg with BIFS/OD/MPEG-4 systems stuff)
*/
u32 MP4T_GuessSpecification(M4File *mp4file);
/*returns 1 if file is single AV (max one audio, one video, one text and basic od/bifs)*/
Bool MP4T_IsSingleAV(M4File *mp4file);

/*make the file ISMA compliant: creates ISMA BIFS / OD tracks if needed, and update audio/video IDs
the file should not contain more than one audio and one video track
@keepImage: if set, generates system info if image is found - only used for image imports
@LogMsg: redirection for message or NULL for stdout
*/
M4Err MP4T_MakeISMA(M4File *mp4file, Bool keepESIDs, Bool keepImage, Bool no_ocr, void (*LogMsg)(void *cbk, const char *szMsg), void *cbk);

/*make the file 3GP compliant && sets profile
@LogMsg: redirection for message or NULL for stdout
*/
M4Err MP4T_Make3GPP(M4File *mp4file, void (*LogMsg)(void *cbk, const char *szMsg), void *cbk);

/*returns TRUE if the encoded data fits in an ESD url - streamType os the systems stream type*/
Bool MP4T_CanEmbbedData(char *data, u32 data_size, u32 streamType);

/*creates (if needed) an ESDescriptor for the given track - THIS IS RESERVED for local playback
only, since the OTI used when emulated is not standard...*/
ESDescriptor *MP4T_MapESDescriptor(M4File *mp4, u32 track);

enum
{
	/*no selective encryption*/
	M4_SELENC_NONE = 0,
	/*only encrypts RAP samples*/
	M4_SELENC_RAP = 1,
	/*only encrypts non-RAP samples*/
	M4_SELENC_NON_RAP = 2,
	/*selective encryption of random samples*/
	M4_SELENC_RAND = 3,
	/*selective encryption of a random sample in given range*/
	M4_SELENC_RAND_RANGE = 4,
	/*selective encryption of first sample in given range*/
	M4_SELENC_RANGE = 5
};

typedef struct
{
	u32 trackID;
	char key[16];
	char salt[8];

	/*the rest is only used for encryption*/
	char KMS_URI[5000];
	char Scheme_URI[5000];
	/*selecive encryption type*/
	u32 sel_enc_type;
	u32 sel_enc_range;
	/*IPMP signaling: 0: none, 1: IPMP, 2: IPMPX
	when IPMP signaling is enabled, the OD stream will be updated with
	IPMP Update commands*/
	u32 ipmp_type;
	/*if not set and IPMP enabled, defaults to TrackID*/
	u32 ipmp_desc_id;
} M4TrackCryptInfo;

/*encrypts track - logs, progress: info callbacks, NULL for stdout*/
M4Err MP4T_ISMACryptTrack(M4File *mp4, M4TrackCryptInfo *tci, void (*logs)(void *cbk, const char *szMsg), void (*progress)(void *cbk, u32 done, u32 total), void *cbk);

/*decrypts track - logs, progress: info callbacks, NULL for stdout*/
M4Err MP4T_ISMADecryptTrack(M4File *mp4, M4TrackCryptInfo *tci, void (*logs)(void *cbk, const char *szMsg), void (*progress)(void *cbk, u32 done, u32 total), void *cbk);

/*decrypt a track in the file 
@drm_file: location of DRM data (cf MP4Box doc).
@LogMsg: redirection for message or NULL for stdout
*/
M4Err MP4T_ISMADecrypt(M4File *mp4file, const char *drm_file, void (*LogMsg)(void *cbk, const char *szMsg), void *cbk);

/*Crypt a track in the file 
@drm_file: location of DRM data.
@LogMsg: redirection for message or NULL for stdout
*/
M4Err MP4T_ISMACrypt(M4File *mp4file, const char *drm_file, void (*LogMsg)(void *cbk, const char *szMsg), void *cbk);

/*loads key and salt from a LOCAL gpac-DRM file (cf MP4Box doc)*/
M4Err MP4T_GetISMACrypInfoForGPAC(u32 stream_id, char *drm_file, char *key, char *salt);

/*loads key and salt for MPEG4IP protected files*/
Bool MP4T_GetISMACrypInfoForMPEG4IP(u32 stream_id, char *kms_uri, char *key, char *salt);

/*			
			track importers

	All these can import a file into a dedicated track. If esd is NULL the track is blindly added 
	otherwise it is added with the requested ESID if non-0, otherwise the new trackID is stored in ESID
	if use_data_ref is set, data is only referenced in the file
	if duration is not 0, only the first duration seconds are imported
	NOTE: if an ESD is specified, its decoderSpecificInfo is also updated
*/
/*track importer flags*/
enum
{
	/*references data rather than copy, whenever possible*/
	M4TI_USE_DATAREF = 1,
	/*for AVI video: imports at constant FPS (eg imports N-Vops due to encoder drops)*/
	M4TI_NO_FRAME_DROP = 1<<1,
	/*for CMP ASP only: forces treating the input as packed bitsream and discards all n-vops*/
	M4TI_FORCE_PACKED = 1<<2,
	/*for AAC audio: forces SBR mode with implicit signaling (backward compatible)*/
	M4TI_SBR_IMPLICIT = 1<<3,
	/*for AAC audio: forces SBR mode with explicit signaling (non-backward compatible). 
	Will override M4TI_SBR_IMPLICIT flag when set*/
	M4TI_SBR_EXPLICIT = 1<<4,
	/*forces MPEG-4 import - some 3GP2 streams have both native IsoMedia sample description and MPEG-4 one possible*/
	M4TI_FORCE_MPEG4 = 1<<5,
	/*special flag for text import at run time (never set on probe), indicates to leave the text box empty
	so that we dynamically adapt to display size*/
	M4TI_SKIT_TXT_BOX = 1<<6,
	
	/*when set, only updates tracks info and return*/
	M4TI_PROBE_ONLY	= 1<<20,
	/*only set when probing, signals several frames per sample possible*/
	M4TI_3GPP_AGGREGATION = 1<<21,
	/*only set when probing, signals video FPS overridable*/
	M4TI_OVERRIDE_FPS = 1<<22,
	/*only set when probing, signals duration not usable*/
	M4TI_NO_DURATION = 1<<23,
	/*when set by user during import, will abort*/
	M4TI_DO_ABORT = 1<<31
};

#define MAX_IMPORT_TRACKS	10
struct __track_import_info
{
	u32 track_num;
	/*track type (M4_***MediaType)*/
	u32 type;
	/*possible import flags*/
	u32 flags;
};

/*track dumper*/
typedef struct __track_import
{
	M4File *dest;
	/*media to import:
		MP4/ISO media: trackID
		AVI files: 
			0: first video and first audio,
			1: video track
			2->any: audio track(s)
		MPEG-PS files with N video streams: 
			0: first video and first audio
			1->N: video track
			N+1->any: audio track
	TrackNums can be obtain with probing
	*/
	u32 trackID;
	/*media source - selects importer type based on extension*/
	char *in_name;
	/*progress notif - if NULL dumps to stdout*/
	void (*import_progress)(struct __track_import*, u32 cur_sample, u32 sample_count);
	/*messages notif - if NULL dumps to stdout*/
	void (*import_message)(struct __track_import*, M4Err e, const char *message);
	/*import duration if any*/
	u32 duration;
	/*importer flags*/
	u32 flags;
	/*if non 0, force video FPS (CMP, AVI, OGG, H264) - also used by SUB import*/
	Double video_fps;
	/*optional ESD*/
	ESDescriptor *esd;
	/*frame per sample cumulation (3GP media only) - MAX 15, ignored in data ref*/
	u32 frames_per_sample;
	/*track ID of imported media in destination file*/
	u32 final_trackID;
	
	/*opaque user handle*/
	void *user_data;

	/*for MP4 import only*/
	M4File *orig;

	/*number of tracks after probing - may be set to 0, in which case no track 
	selection can be performed. It may also be inaccurate if probing doesn't
	detect all available tracks (cf ogg import)*/
	u32 nb_tracks;
	/*track info after probing (M4TI_PROBE_ONLY set).*/
	struct __track_import_info tk_info[MAX_IMPORT_TRACKS];
} M4TrackImporter;

M4Err MP4T_ImportMedia(M4TrackImporter *importer);

enum
{
	/*track dumper types areformatted as flags for conveniency for 
	authoring tools, but never used as a OR'ed set*/
	/*native format (JPG, PNG, MP3, raw aac or raw cmp) if supported*/
	M4TD_NATIVE = 1,
	/*raw samples (all except OD)*/
	M4TD_RAW_SAMPLES = (1<<1),
	/*NHNT format (any MPEG-4 media)*/
	M4TD_NHNT = (1<<2),
	/*AVI (MPEG4 video and AVC tracks only)*/
	M4TD_AVI = (1<<3),
	/*MP4 (all except OD)*/
	M4TD_MP4 = (1<<4),
	/*AVI->RAW to dump video (trackID=1) or audio (trackID>=2)*/
	M4TD_AVI_NATIVE = (1<<5),

	/*following ones are real flags*/
	/*used bfor MP4 extraction, indicates track should be added to dest file if any*/
	M4TD_MERGE_TRACKS = (1<<10),
	/*indicates QCP file format possible as well as native (EVRC and SMV audio only)*/
	M4TD_USE_QCP = (1<<11),
	/*ony probes extraction format*/
	M4TD_PROBE_ONLY = (1<<30),
	/*when set by user during export, will abort*/
	M4TD_DO_ABORT = (1<<31),
};

/*track dumper*/
typedef struct __track_dumper
{
	M4File *file;
	u32 trackID;
	/*sample number to dump for M4TD_RAW_SAMPLES only*/
	u32 sample_num;
	/*out name WITHOUT extension*/
	char *out_name;
	/*progress notif - if NULL dumps to stdout*/
	void (*dump_progress)(struct __track_dumper*, u32 cur_sample, u32 sample_count);
	/*messages notif - if NULL dumps to stdout*/
	void (*dump_message)(struct __track_dumper*, M4Err e, const char *message);
	/*dump type*/
	u32 flags;
	/*non-IsoMedia file (AVI)*/
	char *in_name;

	/*opaque user handle*/
	void *user_data;
} M4TrackDumper;

/*if error returns same value as error signaled in message*/
M4Err MP4T_DumpTrack(M4TrackDumper *dump);

/*gets image size (bs must contain the whole image) - OTI is image type (JPEG=0x6C, PNG=0x6D)*/
void MP4T_GetImageSize(BitStream *bs, u8 OTI, u32 *width, u32 *height);


/*
		Memory scene management

*/

/*NDT check - return 1 if node belongs to given NDT. Handles proto, and assumes undefined nodes
always belong to the desired NDT*/
Bool Node_IsInTable(SFNode *node, u32 NDTType);

/*generic systems access unit context*/
typedef struct
{	
	/*AU timing in TimeStampResolution*/
	u32 timing;
	/*timing in sec - used if timing isn't set*/
	Double timing_sec;
	/*random access indication - may be overriden by encoder*/
	Bool is_rap;
	/*opaque command list per stream type*/
	Chain *commands;

	/*pointer to owner stream*/
	struct _stream_context *owner;
} M4AUContext;

/*generic stream context*/
typedef struct _stream_context
{
	/*ESID of stream, or 0 if unknown in which case it is automatically updated at encode stage*/
	u16 ESID;
	/*stream type - used as a hint, the encoder(s) may override it*/
	u8 streamType;
	u8 objectType;
	u32 timeScale;
	Chain *AUs;

	/*last stream AU time, when playing the context directly*/
	u32 last_au_time;
} M4StreamContext;

/*generic presentation context*/
typedef struct 
{
	/*the one and only scene graph used by the scene manager.*/
	LPSCENEGRAPH scene_graph;

	/*all systems streams used in presentation*/
	Chain *streams;
	/*(initial) object descriptor if any - if not set the encoder will generate it*/
	ObjectDescriptor *root_od;

	/*scene resolution*/
	u32 scene_width, scene_height;
	Bool is_pixel_metrics;

	/*BIFS encoding - these is needed for:
	- protos in protos which define subscene graph, hence seperate namespace, but are coded with the same IDs
	- route insertions which are not tracked by the scene graph
	we could do this by hand (counting protos & route insert) but let's be lazy
	*/
	u32 max_node_id, max_route_id, max_proto_id;
} M4SceneManager;

/*scene manager constructor - @scene_graph: scene graph used by the manager. */
M4SceneManager *NewSceneManager(LPSCENEGRAPH scene_graph);
/*scene manager destructor - does not destroy the attached scene graph*/
void M4SM_Delete(M4SceneManager *ctx);
/*retrive or create a stream context in the presentation context
WARNING: if a stream with the same streamType and no ESID already exists in the context, 
it is assigned the requested ES_ID - this is needed to solve base layer*/
M4StreamContext *M4SM_NewStream(M4SceneManager *ctx, u16 ES_ID, u8 streamType, u8 objectType);
/*removes and destroy stream context from presentation context*/
void M4SM_RemoveStream(M4SceneManager *ctx, M4StreamContext *sc);
/*create a new AU context in the given stream context*/
M4AUContext *M4SM_NewAU(M4StreamContext *stream, u32 timing, Double time_ms, Bool isRap);



/*SWF to MPEG-4 flags*/
enum
{
	/*all data in dictionary is in first frame*/
	M4SWF_StaticDictionary = 1,
	/*remove all text*/
	M4SWF_NoText = (1<<1),
	/*remove embedded fonts (force device font usage)*/
	M4SWF_NoFonts = (1<<2),
	/*forces XCurve2D which supports quadratic bezier*/
	M4SWF_UseXCurve = (1<<3),
	/*forces line remove*/
	M4SWF_NoStrike = (1<<4),
	/*forces XLineProperties (supports scalable lines)*/
	M4SWF_UseXLineProps = (1<<5),
	/*forces gradient remove (using center color) */
	M4SWF_NoGradient = (1<<6),
	/*use a dedicated BIFS stream to control display list. This allows positioning in the movie
	(jump to frame, etc..) as well as looping from inside the movie (set by default)*/
	M4SWF_SplitTimeline = (1<<7),
	/*when using SplitTimeline, this flag will prevent generating an AnimationStream in the scene (this is used
	by direct playback only)*/
	M4SWF_NoAnimationStream = (1<<8),
};

/*general loader flags*/
enum
{
	/*if set, always load MPEG-4 nodes, otherwise X3D versions are used for vrml/x3d*/
	M4CL_MPEG4_STRICT = 1,
	/*signal loading is done for playback:	
		scrips will be queued in their parent command for later loading
		SFTime (MPEG-4 only) fields will be handled correctly when inserting/creating nodes based on AU timing
	*/
	M4CL_FOR_PLAYBACK = 2,

	/*special flag indicating that the context is already loaded & valid (eg no default stream creations & co)
	this is used when performing diff encoding (eg the file to load only has updates).
	When set, M4SM_LoaderInit will NOT attempt to parse first frame*/
	M4CL_CTX_IS_LOADED = 4,
};

/*loader type, usually detected based on file ext*/
enum
{	
	M4CL_BT = 1, /*BT loader*/
	M4CL_VRML, /*VRML97 loader*/
	M4CL_X3DV, /*X3D VRML loader*/
	M4CL_XMTA, /*XMT-A loader*/
	M4CL_X3D, /*X3D XML loader*/
	M4CL_SWF, /*SWF->MPEG-4 converter*/
	M4CL_MP4 /*MP4 memory loader*/
};

typedef struct _m4_context_loader
{
	/*scene graph worked on - may be NULL if ctx is present*/
	LPSCENEGRAPH scene_graph;
	/*context manager to load (MUST BE RESETED BEFORE if needed) - may be NULL for loaders not using commands, 
	in which case the graph will be directly updated*/
	M4SceneManager *ctx;
	/*file to import except IsoMedia files*/
	const char *fileName;
	/*IsoMedia file to import (we need to be able to load from an opened file for scene stats)*/
	M4File *isom;
	/*message reporter*/
	void (*OnMessage)(void *cbk, char *msg, M4Err e);
	/*progress callback - can be frames, bytes etc.. depending on file being loaded*/
	void (*OnProgress)(void *cbk, u32 done, u32 to_do);
	/*user callback*/
	void *cbk;
	/*swf import flags*/
	u32 swf_import_flags;
	/*swf flatten limit: angle limit below which 2 lines are considered as aligned, 
	in which case the lines are merged as one. If 0, no flattening happens*/
	Float swf_flatten_limit;
	/*swf extraction path: if set, swf media (mp3, jpeg) are extracted to this path. If not set
	media are extracted to original file directory*/
	const char *localPath;

	/*loader flags*/
	u32 flags;

	/*private to loader*/
	void *loader_priv;
	/*loader type, one of the above value. If not set, detected based on file extension*/
	u32 type;
} M4ContextLoader;

/*initializes the context loader - this will load any IOD and the first frame of the main scene*/
M4Err M4SM_LoaderInit(M4ContextLoader *load);
/*completely loads context*/
M4Err M4SM_LoaderRun(M4ContextLoader *load);
/*terminates the context loader*/
void M4SM_LoaderDone(M4ContextLoader *load);

/*applies all commands in all streams (only BIFS for now): the context manager will only have one command per
stream, this command being a random access*/
M4Err M4SM_MakeRandomAccess(M4SceneManager *ctx);

/*translates SRT/SUB (TTXT not supported) source into BIFS command stream source
	@src: ESDescriptor of new stream (MUST be created before to store TS resolution)
	@mux: MuxInfoDescriptor of src stream - shall contain a valid file, and at least the textNode member set
*/
M4Err M4SM_ImportBIFSText(M4SceneManager *ctx, ESDescriptor *src, MuxInfoDescriptor *mux);

/*scene dump mode*/
enum
{
	/*BT*/
	M4SM_DUMP_BT = 0,
	/*XMT-A*/
	M4SM_DUMP_XMTA,
	/*VRML Text (WRL)*/
	M4SM_DUMP_VRML,
	/*X3D Text (x3dv)*/
	M4SM_DUMP_X3D_VRML,
	/*X3D XML*/
	M4SM_DUMP_X3D_XML,
	/*automatic selection of MPEG4 vs X3D, text mode*/
	M4SM_DUMP_AUTO_TXT,
	/*automatic selection of MPEG4 vs X3D, xml mode*/
	M4SM_DUMP_AUTO_XML
};

/*dumps scene context to BT or XMT
@rad_name: file name & loc without extension - if NULL dump will happen in stdout
@dump_mode: one of the above*/
M4Err M4SM_DumpToText(M4SceneManager *ctx, char *rad_name, u32 dump_mode);


/*encoding flags*/
enum
{
	/*if flag set, DEF names are encoded*/
	M4SM_EncodeNames =	1,
	/*if flag set, RAP are generated inband rather than as sync shadow*/
	M4SM_RAPInBand = 2,
};

/*
encodes scene context into @mp4.
if @log is set, generates BIFS encoder log file
if @mediaSource is set, any unknown stream in the scene will be looked for in @mediaSource (MP4 only)
@flags: encoding flags
@rap_freq: delay between 2 RAP in ms. If 0 RAPs are not forced - BIFS only
*/
M4Err M4SM_EncodeFile(M4SceneManager *ctx, M4File *mp4, char *logFile, char *mediaSource, u32 flags, u32 rap_freq);


/*Dumping tools*/
typedef struct _scenedump *LPSCENEDUMPER;
/*create a scene dumper 
@graph: scene graph being dumped
@rad_name: file radical (NULL for stdout) - if not NULL MUST BE M4_MAX_PATH length
@indent_char: indent format
@XMLDump: if set, dumps in XML format otherwise regular text
returns NULL if can't create a file
*/
LPSCENEDUMPER NewSceneDumper(LPSCENEGRAPH graph, char *rad_name, char indent_char, Bool XMLDump);
void DeleteSceneDumper(LPSCENEDUMPER bd);

/*dumps commands list
@indent: indent to use
@skip_replace_scene_header: if set and dumping in BT mode, the initial REPLACE SCENE header is skipped
*/
M4Err SD_DumpCommandList(LPSCENEDUMPER sdump, Chain *comList, u32 indent, Bool skip_first_replace);

/*dumps complete graph - 
@skip_proto: proto declarations are skipped
@skip_routes: routes are not dumped
*/
M4Err SD_DumpGraph(LPSCENEDUMPER sdump, Bool skip_proto, Bool skip_routes);

/*stat object - to refine :)*/

/*store nodes or proto stats*/
typedef struct
{
	/*node type or protoID*/
	u32 tag;
	const char *name;
	/*number of created nodes*/
	u32 nb_created;
	/*number of used nodes*/
	u32 nb_used;
	/*number of used nodes*/
	u32 nb_del;
} NodeStats;

typedef struct _scenestat
{
	Chain *node_stats;
	Chain *proto_stats;
	
	/*ranges of all SFVec2fs for points only (MFVec2fs)*/
	SFVec2f max_2d, min_2d;
	/*number of parsed 2D points*/
	u32 count_2d;
	/*number of deleted 2D points*/
	u32 rem_2d;

	/*ranges of all SFVec3fs for points only (MFVec3fs)*/
	SFVec3f max_3d, min_3d;
	u32 count_3d;
	/*number of deleted 3D points*/
	u32 rem_3d;

	u32 count_float, rem_float;
	u32 count_color, rem_color;
	/*all SFVec2f other than MFVec2fs elements*/
	u32 count_2f;
	/*all SFVec3f other than MFVec3fs elements*/
	u32 count_3f;
} M4SceneStatistics;

typedef struct _statman *LPSTATMAN;

/*creates new stat handler*/
LPSTATMAN M4SM_NewStatisitics();
/*deletes stat handler*/
void M4SM_DeleteStatisitics(LPSTATMAN stat);
/*reset statistics*/
void M4SM_ResetStatisitics(LPSTATMAN stat);

/*get statistics - do NOT modify the returned structure*/
M4SceneStatistics *M4SM_GetStatisitics(LPSTATMAN stat);

/*produces stat report for a complete graph*/
M4Err M4SM_GetGraphStatistics(LPSTATMAN stat, LPSCENEGRAPH sg);

/*produces stat report for the full scene*/
M4Err M4SM_GetStatistics(LPSTATMAN stat, M4SceneManager *sm);

/*produces stat report for the given command*/
M4Err M4SM_GetCommandStatistics(LPSTATMAN stat, SGCommand *com);

/*rate sizes - note that these sizes INCLUDE the rate_type header byte*/
static const u32 qcelp_rates_to_sizes [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
static const u32 nb_qcelp_rates_to_sizes = 7;
static const u32 smv_evrc_rates_to_sizes [] = {0, 1, 1, 3, 2, 6, 3, 11, 4, 23, 5, 1};
static const u32 nb_smv_evrc_rates_to_sizes = 6;
static const u32 amr_nb_frame_size[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 };
static const u32 amr_wb_frame_size[16] = { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0 };

typedef struct
{
	u8 rate_idx;
	u8 pck_size;
} QCPRateTable;


#ifdef __cplusplus
}
#endif


#endif 

