/******************************************************************************
Copyright (c) 2007 Analog Devices, Inc.  All Rights Reserved.  This software is
proprietary and confidential to Analog Devices, Inc. and its licensors.
*******************************************************************************

$Revision: 1.1 $
$Date: 2008/03/27 03:03:18 $
$LastChangedBy: sto $

Project:    MP4 Audio File Parser
Title:      MP4 Audio File Parser internal header file
Author:     CFJ

Description:
            MP4 Audio File Parser internal module header file

References:
            None

******************************************************************************/

#ifndef __ADI_MP4AD_INTERNAL_PARSER_H__
#define __ADI_MP4AD_INTERNAL_PARSER_H__

#include "adi_mp4ad_parser.h"


// Macros
#define ADI_MP4AD_FULLBOX_NUM_BYTES				(4)	// Size of the FullBox class in 4.2
#define ADI_MP4AD_MAX_HIERARCHY_LEVELS			(16)// Maximum number of hierarchy levels

// Parser function prototypes
adi_mp4ad_return_code_t parser_function_not_implemented(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_container(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_container_fullbox(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_object(adi_mp4ad_instance_t *parser);

adi_mp4ad_return_code_t parser_function_skip(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_ftyp(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_hdlr(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_stsd(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_drms(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_mp4a(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_esds(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_ilst(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_data(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_ilst_metadata(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_dref(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_stts(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_stss(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_stsc(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_stco(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_function_mdhd(adi_mp4ad_instance_t *parser);

///////////////
// Typedefs

// Pointers to the parser functions
typedef adi_mp4ad_return_code_t (*adi_mp4ad_parser_function)(adi_mp4ad_instance_t *);

// enum to identify the type of tag being parsed
typedef enum {
    TAG_STRING,     // generic string tag being parsed
    TAG_GENRE       // Genre tag being parsed
}tag_type_id_t;

// Information about each box type
typedef struct
{
	int			                id;					// 4-byte identifier (eg. 'ftyp')
	int							is_container;		// 1 if box is a container for other boxes, 0 otherwise
	adi_mp4ad_parser_function	parser_function;	// Pointer to parser function
} adi_mp4ad_boxtype_parameters;

// Enums must be in the same order as in the definition of boxtype_parameters
typedef enum
{
	ADI_MP4AD_BOXTYPE_ERROR = -1,
	ADI_MP4AD_BOXTYPE_OBJECT = 0,	// Start state
	ADI_MP4AD_BOXTYPE_FTYP,			// 4.3
	ADI_MP4AD_BOXTYPE_TRAK,			// 8.4
	ADI_MP4AD_BOXTYPE_MDIA,			// 8.7
	ADI_MP4AD_BOXTYPE_HDLR,			// 8.9
	ADI_MP4AD_BOXTYPE_MINF,			// 8.10
	ADI_MP4AD_BOXTYPE_DINF,			// 8.12
	ADI_MP4AD_BOXTYPE_STBL,			// 8.14
	ADI_MP4AD_BOXTYPE_STSD,			// 8.16
	ADI_MP4AD_BOXTYPE_DRMS,			// iTunes/Quicktime Apple DRM protected Audio Sample description box
	ADI_MP4AD_BOXTYPE_MP4A,			// ISO 14496-14:2003 sect 5.6 MPEG4 Audio Sample description box
	ADI_MP4AD_BOXTYPE_ESDS,			//
	ADI_MP4AD_BOXTYPE_UDTA,			// 8.27
	ADI_MP4AD_BOXTYPE_META,			// 8.44
	ADI_MP4AD_BOXTYPE_MOOV,			// 8.1
	ADI_MP4AD_BOXTYPE_ILST,			// iTunes/Quicktime metadata
	ADI_MP4AD_BOXTYPE_DATA,         // iTunes 'data' sub-atom for tag atoms
	ADI_MP4AD_BOXTYPE_TAG_SONGTITLE,
	ADI_MP4AD_BOXTYPE_TAG_ARTIST,
	ADI_MP4AD_BOXTYPE_TAG_ALBUM,
	ADI_MP4AD_BOXTYPE_TAG_YEAR,
	ADI_MP4AD_BOXTYPE_TAG_GENRE,
	ADI_MP4AD_BOXTYPE_TAG_GENRE_2,
	ADI_MP4AD_BOXTYPE_TAG_COMMENT,
	ADI_MP4AD_BOXTYPE_DREF,			// 8.13
	ADI_MP4AD_BOXTYPE_UUID,
	ADI_MP4AD_BOXTYPE_STTS,
	ADI_MP4AD_BOXTYPE_STSS,
	ADI_MP4AD_BOXTYPE_STSC,
	ADI_MP4AD_BOXTYPE_STCO,
	ADI_MP4AD_BOXTYPE_STSZ,
	ADI_MP4AD_BOXTYPE_MDHD,
	ADI_MP4AD_BOXTYPE_NUM_HANDLED	// The number of handled box types

} adi_mp4ad_boxtype_t;

// Array of information about each box type.
// Array elements must be in the same order as in adi_mp4ad_boxtype_t
static const adi_mp4ad_boxtype_parameters boxtype_parameters[ADI_MP4AD_BOXTYPE_NUM_HANDLED] =
{
    // box-id, is-container-flag, box-parsing-function
	{ 0x3F3F3F3F, 0, parser_function_object }, 	    // ADI_MP4AD_BOXTYPE_OBJECT , 0x3F3F3F3F is '????'
	{ 'ftyp', 0, parser_function_ftyp },
	{ 'trak', 1, parser_function_container },
	{ 'mdia', 1, parser_function_container },
	{ 'hdlr', 0, parser_function_hdlr },
	{ 'minf', 1, parser_function_container },
	{ 'dinf', 1, parser_function_container },
	{ 'stbl', 1, parser_function_container },
	{ 'stsd', 1, parser_function_stsd },
	{ 'drms', 0, parser_function_drms },
	{ 'mp4a', 1, parser_function_mp4a },
	{ 'esds', 0, parser_function_esds },
	{ 'udta', 1, parser_function_container },
	{ 'meta', 1, parser_function_container_fullbox },
	{ 'moov', 1, parser_function_container },
	{ 'ilst', 1, parser_function_container }, 			// ilst is a container
	{ 'data', 0, parser_function_data },  			// Substate to parse the data box for each metadata type
	{ '©nam', 0, parser_function_ilst_metadata },
	{ '©ART', 0, parser_function_ilst_metadata },
	{ '©alb', 0, parser_function_ilst_metadata },
	{ '©day', 0, parser_function_ilst_metadata },
	{ '©gen', 0, parser_function_ilst_metadata },
	{ 'gnre', 0, parser_function_ilst_metadata },
	{ '©cmt', 0, parser_function_ilst_metadata },
	{ 'dref', 0, parser_function_dref },
	{ 'uuid', 1, parser_function_skip },
	{ 'stts', 0, parser_function_stts },
	{ 'stss', 0, parser_function_stss },
	{ 'stsc', 0, parser_function_stsc },
	{ 'stco', 0, parser_function_stco },
	{ 'stsz', 0, parser_function_skip },        // Skip stsz box    CVN 2007Aug27
	{ 'mdhd', 0, parser_function_mdhd },
};
///////////////////
// State variables
typedef struct
{
	long int						length;					// Length of input buffer
	adi_mp4ad_bitstream_data_t		*base;					// Input buffer
	long int						first_read_index;		// Index of first read byte for this call to adi_mp4ad_parser()
	long int						first_read_bit;			// Bit number of first read bit for this call to adi_mp4ad_parser()
	long int						read_index;  			// Index of next byte to read
	long int 						read_bit;				// Bit number of next bit to read (0-7)
	long int 						write_index;			// Index of next byte to write = last valid byte + 1
	long int						is_circular;			// Is this a circular buffer?
	long int 						is_full;				// Have no bits been consumed from the buffer in this parsing loop?

} adi_mp4ad_parser_buffer;

typedef struct
{
	adi_mp4ad_boxtype_t				container;				// The container type
	int 							end_stream_index;		// Index of the last byte in the stream for this container
} adi_mp4ad_hierarchy_t;

typedef struct
{
	long int						current_chunk;			// The next chunk to be played
} adi_mp4ad_playback_t;

// iTunes metadata parsing state
typedef struct
{
	adi_mp4ad_tag_text_t*	text_to_parse;                  // pointer to current tag text struct
	tag_type_id_t           tag_type;
} adi_mp4ad_ilst_t;


typedef struct
{
	adi_mp4ad_boxtype_t 			current;				// Current state
	adi_mp4ad_parser_buffer			input_buffer;
	adi_mp4ad_metadata_t*			text_fields;			// Pointer to metadata text fields passed in adi_mp4ad_output_status_t
	int								num_mdat_boxes_found;	// The number of mdat boxes encountered by the parser
	adi_mp4ad_hierarchy_t			container_hierarchy[ADI_MP4AD_MAX_HIERARCHY_LEVELS];
															// List of containers that contain the current parsing point
	int								container_level;		// The current level within the hierarchy
	int								stream_index;			// Current index into stream when parsing, assuming zero start
	adi_mp4ad_playback_t			playback;				// State variables during playback and seeking
	int 							warning_info;			// Bitfield for warnings defined in adi_mp4ad_warning_info_bitfield_t
	void*                           index_mem_base;         // Point to the base of the indexing info buffer            // CVN 2007May12
	int                             index_mem_size;         // The allocated size of the indexing info buffer           // CVN 2007May12
	void*                           index_mem_free_point;   // Point to the free portion of the indexing info buffer    // CVN 2007May12
	int                             index_mem_unstored_bytes;   // Number of indexing info bytes that have been parsed but not been stored  // CVN 2007May12
	int								index_mem_used_bytes;	// The value going to be returned to adi_mp4ad_output_status_t.index_mem_used_bytes	// CVN 2007May23
	adi_mp4ad_ilst_t				ilst;					// iTunes metadata parsing state
    unsigned int                    audio_track_is_parsed;  // flag to indicate if an audio track has been fully parsed yet
} adi_mp4ad_parser_state;

typedef struct
{
	adi_mp4ad_uint32	size;			// in bytes. 0 if object size extends to end of file
	adi_mp4ad_uint32	type;			// Boxtype as packed ASCII
	adi_mp4ad_uint64	largesize;		// in bytes, if object size > 2^32
	adi_mp4ad_uint64	payloadsize;	// in bytes.  Size of object payload
	adi_mp4ad_uint64	headersize;		// in bytes.  Size of object header
	adi_mp4ad_boxtype_t	boxtype;		// Boxtype
	int					is_container;	// Object is a container for other objects
	adi_mp4ad_uint8		usertype[16];	// User box type if boxtype==UUID
} adi_mp4ad_object_t;

typedef struct
{
	adi_mp4ad_uint8		version;
	adi_mp4ad_uint32	flags;
} adi_mp4ad_fullbox_t;

typedef struct      // Moved from adi_mp4ad_parser.h    // CVN 2007May12
{
	adi_mp4ad_uint32	entry_count;
	adi_mp4ad_uint32*	sample_count;
	adi_mp4ad_uint32*	sample_delta;
	int					is_parsed;
} adi_mp4ad_stts_t;

typedef struct      // Moved from adi_mp4ad_parser.h    // CVN 2007May12
{
	adi_mp4ad_uint32	entry_count;
	adi_mp4ad_uint32*	sample_number;
	int					is_parsed;
} adi_mp4ad_stss_t;

typedef struct      // Moved from adi_mp4ad_parser.h    // CVN 2007May12
{
	adi_mp4ad_uint32	entry_count;
	adi_mp4ad_uint32*	first_chunk;
	adi_mp4ad_uint32*	samples_per_chunk;
	adi_mp4ad_uint32*	sample_description_index;
	int					is_parsed;
	adi_mp4ad_int32     last_chunk;     // Store the last chunk index if stsc table is not fully stored
} adi_mp4ad_stsc_t;

typedef struct      // Moved from adi_mp4ad_parser.h    // CVN 2007May12
{
	adi_mp4ad_uint32	entry_count;
	adi_mp4ad_uint32*	chunk_offset;
	int					is_parsed;
} adi_mp4ad_stco_t;

// stts, stss, stco, stsc preloops each require 64 bits, stsz preloop requires 96 bits
//#define MIN_BITS_REQ_FOR_STTS_STSS_STSC_STCO_STSZ_PRELOOP 96
#define MIN_BITS_REQ_FOR_STTS_STSS_STSC_STCO_PRELOOP 64
#define min(a,b) (int)a < (int)b ? a:b;

// substates for the parser functions stts, stss, stco, stsc, stsz
typedef enum
{
	PRELOOP,
	COUNT_LOOP,
	SKIP_LOOP
} adi_mp4ad_substate_t;

typedef struct  // Moved from adi_mp4ad_parser.h    // CVN 2007May12
{
	adi_mp4ad_stts_t							stts;
	adi_mp4ad_stss_t							stss;
	adi_mp4ad_stsc_t							stsc;
	adi_mp4ad_stco_t							stco;
	adi_mp4ad_substate_t						substate;				// added for small paser_input_buffer
	adi_mp4ad_uint32 							running_count;			// added for small paser_input_buffer
	adi_mp4ad_uint32							elements_remaining;		// added for small paser_input_buffer
} adi_mp4ad_container_indexing_info_t;

// Stream instance
struct adi_mp4ad_t
{
	adi_mp4ad_parser_state 		            state;
	adi_mp4ad_object_t						object;			// 4.2
	adi_mp4ad_fullbox_t						fullbox;		// 4.2
	adi_mp4ad_container_info_t*	            atoms;			// Parsed atoms allocated by user
	adi_mp4ad_container_indexing_info_t*	atoms_indexing;	// Parsed atoms allocated by user for indexing
};

// Memory allocation macros
#define FAST_CODE_SECTION section("adi_fast_prio0_code")

// Parser helper functions
adi_mp4ad_boxtype_t 	find_box_type(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parse_box(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parse_full_box(adi_mp4ad_instance_t *parser);
adi_mp4ad_uint64 parser_get_64_bits(adi_mp4ad_instance_t *parser);
adi_mp4ad_return_code_t parser_skip_bits(adi_mp4ad_instance_t *parser, int numBits);
adi_mp4ad_uint64 adi_mp4ad_parser_get_bits(adi_mp4ad_instance_t *parser, int numBits);

// Function prototypes
unsigned long int adi_mp4ad_parser_get_bits (
	adi_mp4ad_instance_t *parser,
	int numBits
);

int adi_mp4ad_parser_bits_remaining (
	adi_mp4ad_instance_t *parser
);

adi_mp4ad_bitstream_data_t adi_mp4ad_parser_get_byte (
	adi_mp4ad_instance_t *parser
);

void adi_mp4ad_parser_byte_align (
	adi_mp4ad_instance_t *parser
);

long int adi_mp4ad_parser_get_bit_position (
	adi_mp4ad_instance_t *parser
);

adi_mp4ad_return_code_t adi_mp4ad_parser_rewind(
	adi_mp4ad_instance_t *parser,
	int numBits
);



#endif // __ADI_MP4AD_INTERNAL_PARSER_H__


/*
**
** EOF: $HeadURL: svn://dingofiles.spd.analog.com/audio/trunk/mp4a-parser/include/adi_mp4ad_parser_internal.h $
**
*/
