/*
 *
 * @APPLE_LICENSE_HEADER_START@
 *
 * Copyright (c) 1999-2001 Apple Computer, Inc.  All Rights Reserved. The
 * contents of this file constitute Original Code as defined in and are
 * subject to the Apple Public Source License Version 1.2 (the 'License').
 * You may not use this file except in compliance with the License.  Please
 * obtain a copy of the License at http://www.apple.com/publicsource and
 * read it before using this file.
 *
 * This Original Code and all software distributed under the License are
 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.  Please
 * see the License for the specific language governing rights and
 * limitations under the License.
 *
 *
 * @APPLE_LICENSE_HEADER_END@
 *
 */
//
// QTHintTrack:
//   The central point of control for a hint track in a QTFile.

#ifndef QTHintTrack_H
#define QTHintTrack_H


//
// Includes
#include "QTTrack.h"
#include "QTAtom_hinf.h"
#include "QTAtom_tref.h"
#include "RTPMetaInfoPacket.h"
#include "MyAssert.h"


//
// External classes
class QTFile;
class QTAtom_stsc_SampleTableControlBlock;
class QTAtom_stts_SampleTableControlBlock;


class QTHintTrackRTPHeaderData {

	public:
		UInt16		rtpHeaderBits;
		UInt16 		rtpSequenceNumber;
		SInt32		relativePacketTransmissionTime;
		UInt16		hintFlags;
		UInt16		dataEntryCount;
		UInt32		tlvSize;
		SInt32		tlvTimestampOffset; //'rtpo' TLV which is the timestamp offset for this packet
};

//
// Class state cookie
class QTHintTrack_HintTrackControlBlock {

public:
	//
	// Constructor and destructor.
						QTHintTrack_HintTrackControlBlock(QTFile_FileControlBlock * FCB = NULL);
	virtual				~QTHintTrack_HintTrackControlBlock(void);
	
	//
	// If you are moving around randomly (seeking), you should call this to reset
	// caches
	void				Reset();

	//
	// If you want this HTCB to build RTP Meta Info packets,
	// tell it which fields to add, and also which IDs to assign, by passing
	// in an array of RTPMetaInfoPacket::kNumFields size, with all the right info
	void SetupRTPMetaInfo(RTPMetaInfoPacket::FieldID* inFieldArray, Bool16 isVideo)
		{ 	Assert(fRTPMetaInfoFieldArray == NULL); fRTPMetaInfoFieldArray = inFieldArray;
			fIsVideo = isVideo;
		}
		
	//
	// File control block
	QTFile_FileControlBlock	*fFCB;
	
	//
	// Sample Table control blocks
	QTAtom_stsc_SampleTableControlBlock  fstscSTCB;
	QTAtom_stts_SampleTableControlBlock  fsttsSTCB;
	
	//
	// Sample cache
	UInt32				fCachedSampleNumber;
	char *				fCachedSample;
	UInt32				fCachedSampleSize, fCachedSampleLength;

	//
	// Sample (description) cache
	UInt32				fCachedHintTrackSampleNumber, fCachedHintTrackSampleOffset;
	char *				fCachedHintTrackSample;
	UInt32				fCachedHintTrackSampleLength;
	UInt32				fCachedHintTrackBufferLength;

	UInt16 				fLastPacketNumberFetched;	// for optimizing Getting a packet from a cached sample
	char*				fPointerToNextPacket;		// after we get one, we point the next at this...
	
	//
	// To support RTP-Meta-Info payload
	RTPMetaInfoPacket::FieldID*			fRTPMetaInfoFieldArray;
	UInt32								fSyncSampleCursor; // Where are we in the sync sample table?
	Bool16								fIsVideo; // so that we know what to do with the frame type field
	UInt64				fCurrentPacketNumber;
	UInt64				fCurrentPacketPosition;
	
	SInt32				fMediaTrackRefIndex;
	QTAtom_stsc_SampleTableControlBlock * fMediaTrackSTSC_STCB;
 
};


//
// QTHintTrack class
class QTHintTrack : public QTTrack {

public:
	//
	// Constructors and destructor.
						QTHintTrack(QTFile * File, QTFile::AtomTOCEntry * trakAtom,
							   Bool16 Debug = false, Bool16 DeepDebug = false);
	virtual				~QTHintTrack(void);


	//
	// Initialization functions.
	virtual	ErrorCode	Initialize(void);
	
	Bool16				IsHintTrackInitialized() { return fHintTrackInitialized; }

	//
	// Accessors.
			ErrorCode	GetSDPFileLength(int * Length);
			char *		GetSDPFile(int * Length);
			
	inline	UInt64		GetTotalRTPBytes(void) { return fHintInfoAtom ? fHintInfoAtom->GetTotalRTPBytes() : 0; }
	inline	UInt64		GetTotalRTPPackets(void) { return fHintInfoAtom ? fHintInfoAtom->GetTotalRTPPackets() : 0; }

	inline	UInt32		GetFirstRTPTimestamp(void) { return fFirstRTPTimestamp; }
	
	//
	// Sample functions
	Bool16		GetSamplePtr(UInt32 SampleNumber, char ** Buffer, UInt32 * Length,
									 QTHintTrack_HintTrackControlBlock * HTCB);

	//
	// Packet functions
	inline	UInt32		GetRTPTimescale(void) { return fRTPTimescale; }
	
	inline	UInt32		GetRTPTimestampRandomOffset(void) { return fTimestampRandomOffset; }
	
	inline	UInt16		GetRTPSequenceNumberRandomOffset(void) { return fSequenceNumberRandomOffset; }
	
	ErrorCode	GetNumPackets(UInt32 SampleNumber, UInt16 * NumPackets,
									  QTHintTrack_HintTrackControlBlock * HTCB = NULL);

	//
	// This function will build an RTP-Meta-Info packet if the last argument
	// is non-NULL. Some caveats apply to maximize performance of this operation:
	//
	// 1. 	If the "md" (media data) field is desired, please put it at the end.
	//
	// 2.	If you want to use compressed fields, pass in the field ID in the first
	// 		byte of the TwoCharConst. Also set the high bit to indicate that this
	//		is a compressed field ID.
	//
	// Supported fields: tt, md, ft, pp, pn, sq
	ErrorCode	GetPacket(UInt32 SampleNumber, UInt16 PacketNumber,
								  char * Buffer, UInt32 * Length,
								  Float64 * TransmitTime,
								  Bool16 dropBFrames,
								  Bool16 dropRepeatPackets = false,
								  UInt32 SSRC = 0,
								  QTHintTrack_HintTrackControlBlock * HTCB = NULL);

	inline ErrorCode 	GetSampleData( QTHintTrack_HintTrackControlBlock * htcb, char **buffPtr, char **ppPacketBufOut, UInt32 sampleNumber, UInt16 packetNumber, UInt32 buffOutLen ); 

	//
	// Debugging functions.
	virtual	void		DumpTrack(void);
	
	// only reliable after all of the packets have been played
	// any hint packet may reference another media track and we don't know until all have been played.
	inline SInt16 GetHintTrackType(void) { return fHintType; }

protected:

	enum
	{
		kRepeatPacketMask = 0x0001,
		kBFrameBitMask = 0x0002
	};
	
	enum
	{
		kUnknown = 0,
		kOptimized = -1,
		kUnoptimized = 1
	};
	//
	// Protected member variables.
	QTAtom_hinf			*fHintInfoAtom;
	QTAtom_tref			*fHintTrackReferenceAtom;
	
	QTTrack				**fTrackRefs;
	
	UInt32				fMaxPacketSize;
	UInt32				fRTPTimescale, fFirstRTPTimestamp;
	UInt32				fTimestampRandomOffset;
	UInt16				fSequenceNumberRandomOffset;	
	Bool16				fHintTrackInitialized;
	SInt16				fHintType;
	//
	// Used by GetPacket for RTP-Meta-Info payload stuff
	void 				WriteMetaInfoField(	RTPMetaInfoPacket::FieldIndex inFieldIndex,
											RTPMetaInfoPacket::FieldID inFieldID,
											void* inFieldData, UInt32 inFieldLen, char** ioBuffer);

	inline QTTrack::ErrorCode	GetSamplePacketPtr( char ** samplePacketPtr, UInt32 sampleNumber, UInt16 packetNumber, QTHintTrackRTPHeaderData	&hdrData,  QTHintTrack_HintTrackControlBlock & htcb);
	inline void			GetSamplePacketHeaderVars( char *samplePacketPtr,char *maxBuffPtr, QTHintTrackRTPHeaderData &hdrData );
};

#endif // QTHintTrack_H
