Add even more of the source

This should be about everything needed to build so far?
This commit is contained in:
Darren VanBuren 2017-03-07 17:14:16 -08:00
parent af3619d4fa
commit 849723c9cf
547 changed files with 149239 additions and 0 deletions

269
QTFileLib/QTAtom.cpp Normal file
View file

@ -0,0 +1,269 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom:
// The base-class for atoms in a QuickTime file.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom::QTAtom(QTFile * File, QTFile::AtomTOCEntry * Atom, Bool16 Debug, Bool16 DeepDebug)
: fDebug(Debug), fDeepDebug(DeepDebug),
fFile(File)
{
//
// Make a copy of the TOC entry.
memcpy(&fTOCEntry, Atom, sizeof(QTFile::AtomTOCEntry));
}
QTAtom::~QTAtom(void)
{
}
// -------------------------------------
// Read functions
//
Bool16 QTAtom::ReadBytes(UInt64 Offset, char * Buffer, UInt32 Length)
{
//
// Validate the arguments.
if( (Offset + Length) > fTOCEntry.AtomDataLength )
return false;
//
// Read and return this data.
return fFile->Read(fTOCEntry.AtomDataPos + Offset, Buffer, Length);
}
char *QTAtom::MemMap(UInt64 Offset, UInt32 Length)
{
//
// Validate the arguments.
if( (Offset + Length) > fTOCEntry.AtomDataLength )
return NULL;
//
// Read and return this data.
return fFile->MapFileToMem(fTOCEntry.AtomDataPos + Offset, Length);
}
Bool16 QTAtom::UnMap(char *memPtr, UInt32 Length)
{
if (-1 == fFile->UnmapMem(memPtr, Length))
return false;
return true;
}
Bool16 QTAtom::ReadInt8(UInt64 Offset, UInt8 * Datum)
{
//
// Read and return.
return ReadBytes(Offset, (char *)Datum, 1);
}
Bool16 QTAtom::ReadInt16(UInt64 Offset, UInt16 * Datum)
{
// General vars
UInt16 tempDatum;
//
// Read and flip.
if( !ReadBytes(Offset, (char *)&tempDatum, 2) )
return false;
*Datum = ntohs(tempDatum);
return true;
}
Bool16 QTAtom::ReadInt32(UInt64 Offset, UInt32 * Datum)
{
// General vars
UInt32 tempDatum;
//
// Read and flip.
if( !ReadBytes(Offset, (char *)&tempDatum, 4) )
return false;
*Datum = ntohl(tempDatum);
return true;
}
Bool16 QTAtom::ReadInt32To64(UInt64 Offset, UInt64 * Datum)
{
// General vars
UInt32 tempDatum;
//
// Read and flip.
if( !ReadBytes(Offset, (char *)&tempDatum, 4) )
return false;
tempDatum = ntohl(tempDatum);
*Datum = (UInt64) tempDatum;
return true;
}
Bool16 QTAtom::ReadInt32To64Signed(UInt64 Offset, SInt64 * Datum)
{
// General vars
UInt32 tempDatum;
//
// Read and flip.
if( !ReadBytes(Offset, (char *)&tempDatum, 4) )
return false;
tempDatum = ntohl(tempDatum);
*Datum = (SInt64) (SInt32) tempDatum;
return true;
}
Bool16 QTAtom::ReadInt64(UInt64 Offset, UInt64 * Datum)
{
// General vars
UInt64 tempDatum;
//
// Read and flip.
if( !ReadBytes(Offset, (char *)&tempDatum, 8) )
return false;
*Datum = (UInt64) QTAtom::NTOH64(tempDatum);
return true;
}
Bool16 QTAtom::ReadSubAtomBytes(const char * AtomPath, char * Buffer, UInt32 Length)
{
// General vars
QTFile::AtomTOCEntry *atomTOCEntry;
//
// Find the TOC entry for this sub-atom.
if( !fFile->FindTOCEntry(AtomPath, &atomTOCEntry, &fTOCEntry) )
return false;
//
// Validate the arguments.
if( (atomTOCEntry->AtomDataPos <= fTOCEntry.AtomDataPos) || ((atomTOCEntry->AtomDataPos + Length) > (fTOCEntry.AtomDataPos + fTOCEntry.AtomDataLength)) )
return false;
//
// Read and return this data.
return fFile->Read(atomTOCEntry->AtomDataPos, Buffer, Length);
}
Bool16 QTAtom::ReadSubAtomInt8(const char * AtomPath, UInt8 * Datum)
{
//
// Read and return.
return ReadSubAtomBytes(AtomPath, (char *)Datum, 1);
}
Bool16 QTAtom::ReadSubAtomInt16(const char * AtomPath, UInt16 * Datum)
{
// General vars
UInt16 tempDatum;
//
// Read and flip.
if( !ReadSubAtomBytes(AtomPath, (char *)&tempDatum, 2) )
return false;
*Datum = ntohs(tempDatum);
return true;
}
Bool16 QTAtom::ReadSubAtomInt32(const char * AtomPath, UInt32 * Datum)
{
// General vars
UInt32 tempDatum;
//
// Read and flip.
if( !ReadSubAtomBytes(AtomPath, (char *)&tempDatum, 4) )
return false;
*Datum = ntohl(tempDatum);
return true;
}
Bool16 QTAtom::ReadSubAtomInt64(const char * AtomPath, UInt64 * Datum)
{
// General vars
UInt64 tempDatum;
//
// Read and flip.
if( !ReadSubAtomBytes(AtomPath, (char *)&tempDatum, 8) )
return false;
*Datum = (UInt64) QTAtom::NTOH64(tempDatum);
return true;
}

100
QTFileLib/QTAtom.h Normal file
View file

@ -0,0 +1,100 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom:
// The base-class for atoms in a QuickTime file.
#ifndef QTAtom_H
#define QTAtom_H
//
// Includes
#include "OSHeaders.h"
#include "QTFile.h"
//
// QTAtom class
class QTAtom {
public:
//
// Constructors and destructor.
QTAtom(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom(void);
//
// Initialization functions.
virtual Bool16 Initialize(void) { return true; }
static SInt64 NTOH64(SInt64 networkOrdered)
{
#if BIGENDIAN
return networkOrdered;
#else
return (SInt64) ( (UInt64) (networkOrdered << 56) | (UInt64) (((UInt64) 0x00ff0000 << 32) & (networkOrdered << 40))
| (UInt64) ( ((UInt64) 0x0000ff00 << 32) & (networkOrdered << 24)) | (UInt64) (((UInt64) 0x000000ff << 32) & (networkOrdered << 8))
| (UInt64) ( ((UInt64) 0x00ff0000 << 8) & (networkOrdered >> 8)) | (UInt64) ((UInt64) 0x00ff0000 & (networkOrdered >> 24))
| (UInt64) ( (UInt64) 0x0000ff00 & (networkOrdered >> 40)) | (UInt64) ((UInt64) 0x00ff & (networkOrdered >> 56)) );
#endif
}
//
// Read functions.
Bool16 ReadBytes(UInt64 Offset, char * Buffer, UInt32 Length);
Bool16 ReadInt8(UInt64 Offset, UInt8 * Datum);
Bool16 ReadInt16(UInt64 Offset, UInt16 * Datum);
Bool16 ReadInt32(UInt64 Offset, UInt32 * Datum);
Bool16 ReadInt64(UInt64 Offset, UInt64 * Datum);
Bool16 ReadInt32To64(UInt64 Offset, UInt64 * Datum);
Bool16 ReadInt32To64Signed(UInt64 Offset, SInt64 * Datum);
Bool16 ReadSubAtomBytes(const char * AtomPath, char * Buffer, UInt32 Length);
Bool16 ReadSubAtomInt8(const char * AtomPath, UInt8 * Datum);
Bool16 ReadSubAtomInt16(const char * AtomPath, UInt16 * Datum);
Bool16 ReadSubAtomInt32(const char * AtomPath, UInt32 * Datum);
Bool16 ReadSubAtomInt64(const char * AtomPath, UInt64 * Datum);
char* MemMap(UInt64 Offset, UInt32 Length);
Bool16 UnMap(char *memPtr, UInt32 Length);
//
// Debugging functions.
virtual void DumpAtom(void) {}
protected:
//
// Protected member variables.
Bool16 fDebug, fDeepDebug;
QTFile *fFile;
QTFile::AtomTOCEntry fTOCEntry;
};
#endif // QTAtom_H

381
QTFileLib/QTAtom_dref.cpp Normal file
View file

@ -0,0 +1,381 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_dref:
// The 'dref' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_dref.h"
#include "OSMemory.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constants
//
const int drefPos_VersionFlags = 0;
const int drefPos_NumRefs = 4;
const int drefPos_RefTable = 8;
const int drefRefPos_Size = 0;
const int drefRefPos_Type = 4;
const int drefRefPos_VersionFlags = 8;
const int drefRefPos_Data = 12;
// -------------------------------------
// Mac alias constants and typedefs
//
enum {
kEndMark =-1, /* -1 end of variable info */
kAbsPath = 2, /* 2 absolute path name */
kMaxMark = 10 /* End Marker */
};
typedef struct
{
short what; /* what kind of information */
short len; /* length of variable data */
char data[1]; /* actual data */
} varInfo;
typedef struct
{
char private1[130];
short nlvlFrom; /* # of levels from fromFile/toFile until a common */
short nlvlTo; /* ancestor directory is found */
char private2[16];
varInfo vdata[1]; /* variable length info */
} AliasRecordPriv;
// -------------------------------------
// Constructors and destructors
//
QTAtom_dref::QTAtom_dref(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumRefs(0), fRefs(NULL)
{
}
QTAtom_dref::~QTAtom_dref(void)
{
//+ 6.16.1999 rt fix memory leak
for( UInt32 curRef = 0; curRef < fNumRefs; curRef++ )
{
delete [] fRefs[curRef].Data;
delete fRefs[curRef].FCB;
}
//-end
//
// Free our variables.
delete[] fRefs;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_dref::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
// General vars
UInt64 refPos;
//
// Parse this atom's fields.
ReadInt32(drefPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(drefPos_NumRefs, &fNumRefs);
//
// Read in all of the refs.
if( fNumRefs > 0 ) {
//
// Allocate our ref table.
fRefs = NEW DataRefEntry[fNumRefs];
if( fRefs == NULL )
return false;
//
// Read them all in..
refPos = drefPos_RefTable;
for( UInt32 CurRef = 0; CurRef < fNumRefs; CurRef++ ) {
//
// Set up the entry.
fRefs[CurRef].Flags = 0x0;
fRefs[CurRef].ReferenceType = FOUR_CHARS_TO_INT('N', 'U', 'L', 'L'); // NULL
fRefs[CurRef].DataLength = 0;
fRefs[CurRef].Data = NULL;
fRefs[CurRef].IsEntryInitialized = false;
fRefs[CurRef].IsFileOpen = false;
fRefs[CurRef].FCB = NULL;
//
// Get the flags and type.
ReadInt32(refPos + drefRefPos_VersionFlags, &tempInt32);
fRefs[CurRef].Flags = tempInt32 & 0x00ffffff;
ReadInt32(refPos + drefRefPos_Type, &tempInt32);
fRefs[CurRef].ReferenceType = tempInt32;
//
// We're done if this is a self-referencing atom.
if( fRefs[CurRef].Flags & flagSelfRef ) {
fRefs[CurRef].IsEntryInitialized = true;
continue;
}
//
// Get all of the data.
ReadInt32(refPos + drefRefPos_Size, &tempInt32);
fRefs[CurRef].DataLength = tempInt32 - 12 /* skip the header */;
fRefs[CurRef].Data = NEW char[fRefs[CurRef].DataLength];
if( fRefs[CurRef].Data == NULL ) {
//
// De-initialize this entry.
fRefs[CurRef].DataLength = 0;
fRefs[CurRef].IsEntryInitialized = false;
} else {
//
// Read the entry data.
ReadBytes(refPos + drefRefPos_Data, fRefs[CurRef].Data, fRefs[CurRef].DataLength);
//
// Configure the rest of the entry.
fRefs[CurRef].FCB = NEW QTFile_FileControlBlock();
if( fRefs[CurRef].FCB == NULL )
fRefs[CurRef].IsEntryInitialized = false;
else
fRefs[CurRef].IsEntryInitialized = true;
fRefs[CurRef].IsFileOpen = false;
}
//
// Skip over this mini-atom.
refPos += fRefs[CurRef].DataLength + 12 /* account for the header */;
}
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Read functions.
//
Bool16 QTAtom_dref::Read(UInt32 RefID, UInt64 Offset, char * const Buffer, UInt32 Length, QTFile_FileControlBlock * FCB)
{
// General vars
DataRefEntry *Entry;
//
// Validate that this ref exists.
if( (RefID == 0) || (RefID > fNumRefs) )
return false;
// qtss_printf("QTAtom_dref::Read Offset = %qd, Length = %"_S32BITARG_" \n", Offset, Length);
//
// If this data reference is in the movie file itself, then we can forward
// the request directly to QTFile.
if( IsRefInThisFile(RefID) )
return fFile->Read(Offset, Buffer, Length, FCB);
//
// The ref is not in this file; see if we have already opened an FCB for
// the file and use that, otherwise we need to process the ref.
Entry = &fRefs[RefID - 1];
//
// Abort if the entry was not initialized.
if( !Entry->IsEntryInitialized )
return false;
//
// Open the file (after parsing the data reference) if it is not open
// already.
if( !Entry->IsFileOpen ) {
// General vars
char *AliasPath;
//
// We only support parsing alias types.
if( Entry->ReferenceType != FOUR_CHARS_TO_INT('a', 'l', 'i', 's') ) //alis
return false;
//
// Parse the alias.
if( (AliasPath = ResolveAlias(Entry->Data, Entry->DataLength)) == NULL )
return false;
//
// Create a path which does *not* contain the current movie's name.
char * p;
char * MoviePath = fFile->GetMoviePath();
char * NewPath = NEW char[strlen(MoviePath) + strlen(AliasPath) + 1];
//char * NewPath = (char *)calloc(1, strlen(MoviePath) + strlen(AliasPath));
if( (p = strrchr(MoviePath, QT_PATH_SEPARATOR)) == NULL ) {
memcpy(NewPath, AliasPath, strlen(AliasPath) + 1);
} else {
int MoviePathClippedLength = (p - MoviePath) + 1;
memcpy(NewPath, MoviePath, MoviePathClippedLength);
memcpy(NewPath + MoviePathClippedLength, AliasPath, strlen(AliasPath) + 1);
}
//
// Do the open.
Entry->FCB->Set(NewPath);
if(!Entry->FCB->IsValid()) {
delete [] NewPath;
//free(NewPath);
return false;
}
Entry->IsFileOpen = true;
delete [] NewPath;
//free(NewPath);
}
//
// Do the read.
return fFile->Read(Offset, Buffer, Length, Entry->FCB);
}
// -------------------------------------
// Debugging functions
//
void QTAtom_dref::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_dref::DumpAtom - Dumping atom.\n"));
for( UInt32 CurRef = 1; CurRef <= fNumRefs; CurRef++ )
DEBUG_PRINT(("QTAtom_dref::DumpAtom - ..Ref #%"_U32BITARG_" is in file: %s\n", CurRef, IsRefInThisFile(CurRef) ? "yes" : "no"));
}
// -------------------------------------
// Protected member functions.
//
char * QTAtom_dref::ResolveAlias(char * const AliasData, UInt32 /* AliasDataLength */)
{
// General vars
AliasRecordPriv *Alias = (AliasRecordPriv *)AliasData;
varInfo *AliasVarInfo;
char *path, *pathStart;
int pathLength;
//
// Verify that we have a relative path.
if( (Alias->nlvlTo == -1) || (Alias->nlvlFrom == -1) )
return NULL;
//
// Search for the absolute pathname in this alias.
AliasVarInfo = Alias->vdata;
for( int loopCount = kMaxMark - 1; loopCount >= 0; loopCount--) {
//
// Break out of the loop if this is a match/the end of the alias.
if( ((short)ntohs(AliasVarInfo->what) == kAbsPath) || ((short)ntohs(AliasVarInfo->what) == kEndMark) )
break;
//
// Otherwise we need to move to the next data unit.
AliasVarInfo = (varInfo *)((char *)AliasVarInfo + ((ntohs(AliasVarInfo->len) + 1) & ~1) + 4 /* header size */);
}
//
// Now that we have the path, we need to strip off the absolute portions
// of it so that we can get at it from our current (relative) root.
AliasVarInfo->data[ntohs(AliasVarInfo->len)] = '\0';
pathStart = path = AliasVarInfo->data;
path += ntohs(AliasVarInfo->len);
int i = ntohs(Alias->nlvlTo);
pathLength = -1;
while( i && (path > pathStart) ) {
if( *path-- == ':' )
i--;
pathLength++;
}
if( i == 1 )
pathLength += 2; // fell out of loop; we're relative to root
else
path += 2; // points past separator character
//
// Return the alias.
return path;
}

113
QTFileLib/QTAtom_dref.h Normal file
View file

@ -0,0 +1,113 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_dref:
// The 'dref' QTAtom class.
#ifndef QTAtom_dref_H
#define QTAtom_dref_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// External classes
class QTFile_FileControlBlock;
//
// QTAtom class
class QTAtom_dref : public QTAtom {
//
// Class constants
enum {
flagSelfRef = 0x00000001
};
//
// Class typedefs.
struct DataRefEntry {
// Data ref information
UInt32 Flags;
OSType ReferenceType;
UInt32 DataLength;
char *Data;
// Tracking information
Bool16 IsEntryInitialized, IsFileOpen;
QTFile_FileControlBlock *FCB;
};
public:
//
// Constructors and destructor.
QTAtom_dref(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_dref(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
Bool16 IsRefInThisFile(UInt32 RefID) { if(RefID && (RefID<=fNumRefs)) \
return ((fRefs[RefID-1].Flags & flagSelfRef) != 0); \
return false; }
//
// Read functions.
Bool16 Read(UInt32 RefID, UInt64 Offset, char * const Buffer, UInt32 Length,
QTFile_FileControlBlock * FCB = NULL);
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member functions.
char * ResolveAlias(char * const AliasData, UInt32 AliasDataLength);
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumRefs;
DataRefEntry *fRefs;
};
#endif // QTAtom_dref_H

174
QTFileLib/QTAtom_elst.cpp Normal file
View file

@ -0,0 +1,174 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_elst:
// The 'elst' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_elst.h"
#include "OSMemory.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constants
//
const int elstPos_VersionFlags = 0;
const int elstPos_NumEdits = 4;
const int elstPos_EditList = 8;
const int elstEntryPos_Duration = 0;
const int elstEntryPos_MediaTime = 4;
const int elstEntryPos_MediaRate = 8;
const int elstEntryPosV1_Duration = 0;
const int elstEntryPosV1_MediaTime = 8;
const int elstEntryPosV1_MediaRate = 16;
// -------------------------------------
// Constructors and destructors
//
QTAtom_elst::QTAtom_elst(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEdits(0), fEdits(NULL),
fFirstEditMovieTime(0)
{
}
QTAtom_elst::~QTAtom_elst(void)
{
//
// Free our variables.
if( fEdits != NULL )
delete[] fEdits;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_elst::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(elstPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
if (fVersion > 1)
{
DEEP_DEBUG_PRINT(("QTAtom_elst::Initialize failed. Version unsupported: %d\n",fVersion));
return false;
}
ReadInt32(elstPos_NumEdits, &fNumEdits);
//
// Read in all of the edits.
if( fNumEdits > 0 ) {
DEEP_DEBUG_PRINT(("QTAtom_elst::Initialize ..%"_U32BITARG_" edits found.\n", fNumEdits));
//
// Allocate our ref table.
fEdits = NEW EditListEntry[fNumEdits];
if( fEdits == NULL )
return false;
//
// Read them all in..
for( UInt32 CurEdit = 0; CurEdit < fNumEdits; CurEdit++ )
{
if (0 == fVersion)
{
//
// Get all of the data in this edit list entry.
ReadInt32To64(elstPos_EditList + (CurEdit * 12) + elstEntryPos_Duration, &fEdits[CurEdit].EditDuration);
ReadInt32To64Signed(elstPos_EditList + (CurEdit * 12) + elstEntryPos_MediaTime, &fEdits[CurEdit].StartingMediaTime);
ReadInt32(elstPos_EditList + (CurEdit * 12) + elstEntryPos_MediaRate, &fEdits[CurEdit].EditMediaRate);
}
else if (1 == fVersion)
{
// Get all of the data in this edit list entry.
ReadInt64(elstPos_EditList + (CurEdit * 20) + elstEntryPosV1_Duration, &fEdits[CurEdit].EditDuration);
ReadInt64(elstPos_EditList + (CurEdit * 20) + elstEntryPosV1_MediaTime, (UInt64*) &fEdits[CurEdit].StartingMediaTime );
ReadInt32(elstPos_EditList + (CurEdit * 20) + elstEntryPosV1_MediaRate, &fEdits[CurEdit].EditMediaRate);
}
DEEP_DEBUG_PRINT(("QTAtom_elst::Initialize ..Edit #%"_U32BITARG_": Duration=%"_64BITARG_"u; MediaTime=%"_64BITARG_"d\n", CurEdit, fEdits[CurEdit].EditDuration, fEdits[CurEdit].StartingMediaTime));
//
// Adjust our starting media time.
if( fEdits[CurEdit].StartingMediaTime == -1 )
fFirstEditMovieTime = fEdits[CurEdit].EditDuration;
}
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_elst::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_elst::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_elst::DumpAtom - ..Version: %d.\n", (int) fVersion));
DEBUG_PRINT(("QTAtom_elst::DumpAtom - ..Number of edits: %"_S32BITARG_"\n", fNumEdits));
}

91
QTFileLib/QTAtom_elst.h Normal file
View file

@ -0,0 +1,91 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_elst:
// The 'elst' QTAtom class.
#ifndef QTAtom_elst_H
#define QTAtom_elst_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// External classes
class QTFile_FileControlBlock;
//
// QTAtom class
class QTAtom_elst : public QTAtom {
//
// Class typedefs.
struct EditListEntry {
// Edit information
UInt64 EditDuration;
SInt64 StartingMediaTime;
UInt32 EditMediaRate;
};
public:
//
// Constructors and destructor.
QTAtom_elst(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_elst(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline UInt64 FirstEditMovieTime(void) { return fFirstEditMovieTime; }
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEdits;
EditListEntry *fEdits;
UInt64 fFirstEditMovieTime;
};
#endif // QTAtom_elst_H

212
QTFileLib/QTAtom_hinf.cpp Normal file
View file

@ -0,0 +1,212 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_hinf:
// The 'hinf' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <time.h>
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_hinf.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constants
//
const char * hinfAtom_TotalRTPBytes64 = ":trpy";
const char * hinfAtom_TotalRTPBytes32 = ":totl";
const char * hinfAtom_TotalRTPPackets64 = ":nump";
const char * hinfAtom_TotalRTPPackets32 = ":npck";
const char * hinfAtom_TotalPayloadBytes64 = ":tpyl";
const char * hinfAtom_TotalPayloadBytes32 = ":tpay";
const char * hinfAtom_MaxDataRate64 = ":maxr";
const char * hinfAtom_TotalMediaBytes64 = ":dmed";
const char * hinfAtom_TotalImmedBytes64 = ":dimm";
const char * hinfAtom_TotalRepeatBytes64 = ":drep";
const char * hinfAtom_MinTransTime32 = ":tmin";
const char * hinfAtom_MaxTransTime32 = ":tmax";
const char * hinfAtom_MaxPacketSize32 = ":pmax";
const char * hinfAtom_MaxPacketDuration32 = ":dmax";
const char * hinfAtom_PayloadType = ":payt";
/*
'trpy' 8 bytes The total number of bytes that will be sent,
including 12-byte RTP headers, but not including
any network headers.
'totl' 4 bytes 4-byte version of 'trpy'
'nump' 8 bytes The total number of network packets that will be
sent (if the application knows there is a 28-byte
network header, it can multiply 28 by this number
and add it to the ÔtrpyÕ value to get the true
number of bytes sent.
'npck' 4 bytes 4-byte version of 'nump'
'tpyl' 8 bytes The total number of bytes that will be sent, not
including 12-byte RTP headers.
'tpay' 4 bytes 4-byte version of 'tpyl'
'maxr' 8 bytes The maximum data rate. This atom contains two
numbers: g, followed by m (both 32-bit values). g
is the granularity, in milliseconds. m is the
maximum data rate given that granularity. For
example, if g is 1 second, then m is the maximum
data rate over any 1 second. There may be
multiple 'maxr' atoms, with different values for g.
The maximum data rate calculation does not
include any network headers (but does include
12-byte RTP headers).
'dmed' 8 bytes The number of bytes from the media track to be
sent.
'dimm' 8 bytes The number of bytes of immediate data to be sent.
'drep' 8 bytes The number of bytes of repeated data to be sent.
'tmin' 4 bytes The smallest relative transmission time, in
milliseconds.
'tmax' 4 bytes The largest relative transmission time, in
milliseconds.
'pmax' 4 bytes The largest packet, in bytes; includes 12-byte RTP
header.
'dmax' 4 bytes The largest packet duration, in milliseconds.
'payt' variable The payload type, which includes payload
number (32-bits) followed by rtpmap payload
string (Pascal string).
*/
// -------------------------------------
// Constructors and destructors
//
QTAtom_hinf::QTAtom_hinf(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fTotalRTPBytes32(0), //totl
fTotalRTPBytes64(0), //trpy
fTotalRTPPackets32(0), //nump
fTotalRTPPackets64(0), //npck
fTotalPayLoadBytes32(0), //tpay
fTotalPayLoadBytes64(0), //tpyl
fMaxDataRate64(0), //maxr
fTotalMediaBytes64(0), //dmed
fTotalImmediateBytes64(0), //dimm
fTotalRepeatBytes64(0), //drep
fMinTransTime32(0), //tmin
fMaxTransTime32(0), //tmax
fMaxPacketSizeBytes32(0), //pmax
fMaxPacketDuration32(0), //dmax
fPayloadID(0)//payt
{
fPayloadStr[0] = 0;//payt
}
QTAtom_hinf::~QTAtom_hinf(void)
{
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_hinf::Initialize(void)
{
//
// Parse this atom's sub-atoms.
ReadSubAtomInt32(hinfAtom_TotalRTPBytes32, &fTotalRTPBytes32);
ReadSubAtomInt32(hinfAtom_TotalRTPPackets32, &fTotalRTPPackets32);
ReadSubAtomInt32(hinfAtom_TotalPayloadBytes32, &fTotalPayLoadBytes32);
ReadSubAtomInt64(hinfAtom_TotalRTPBytes64, &fTotalRTPBytes64);
ReadSubAtomInt64(hinfAtom_TotalRTPPackets64, &fTotalRTPPackets64);
ReadSubAtomInt64(hinfAtom_TotalPayloadBytes64, &fTotalPayLoadBytes64);
ReadSubAtomInt64(hinfAtom_MaxDataRate64, &fMaxDataRate64);
ReadSubAtomInt64(hinfAtom_TotalMediaBytes64, &fTotalMediaBytes64);
ReadSubAtomInt64(hinfAtom_TotalImmedBytes64, &fTotalImmediateBytes64);
ReadSubAtomInt64(hinfAtom_TotalRepeatBytes64, &fTotalRepeatBytes64);
ReadSubAtomInt32(hinfAtom_MinTransTime32, &fMinTransTime32);
ReadSubAtomInt32(hinfAtom_MaxTransTime32, &fMaxTransTime32);
ReadSubAtomInt32(hinfAtom_MaxPacketSize32, &fMaxPacketSizeBytes32);
ReadSubAtomInt32(hinfAtom_MaxPacketDuration32, &fMaxPacketDuration32);
ReadSubAtomInt32(hinfAtom_PayloadType, &fPayloadID);
if (fPayloadID != 0)
{ SInt8 len = 0;
ReadSubAtomBytes(hinfAtom_PayloadType, (char*)fPayloadStr, 5);
len = fPayloadStr[4];
if (len > 0)
{ ReadSubAtomBytes(hinfAtom_PayloadType, (char*)fPayloadStr, len+5);
::memmove(fPayloadStr,&fPayloadStr[5],len);
fPayloadStr[len] = 0;
}
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_hinf::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total RTP bytes: %"_64BITARG_"u\n", this->GetTotalRTPBytes()));
#ifndef __Win32__
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ....Average bitrate: %.2f Kbps\n", ((this->GetTotalRTPBytes() << 3) / fFile->GetDurationInSeconds()) / 1024));
#endif
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total RTP packets: %"_64BITARG_"u\n", this->GetTotalRTPPackets()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ....Average packet size: %"_64BITARG_"u\n", this->GetTotalRTPBytes() / this->GetTotalRTPPackets()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total Payload bytes: %"_64BITARG_"u\n", this->GetTotalPayLoadBytes()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Maximum Data Rate: %"_64BITARG_"u\n", this->GetMaxDataRate()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total Media Track bytes: %"_64BITARG_"u\n", this->GetTotalMediaBytes()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total Repeat Packet bytes: %"_64BITARG_"u\n", this->GetRepeatBytes()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Total Immediate Bytes: %"_64BITARG_"u\n", this->GetTotalImmediateBytes()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Minimum Transmission Time: %"_U32BITARG_"\n", this->GetMinTransTime()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Maximum Transmission Time: %"_U32BITARG_"\n", this->GetMaxTransTime()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Maximum Packet Size bytes: %"_U32BITARG_"\n", this->GetMaxPacketSizeBytes()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Maximum Maximum Packet Duration: %"_U32BITARG_"\n", this->GetMaxPacketDuration()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Payload ID: %"_U32BITARG_"\n", this->GetPayLoadID()));
DEBUG_PRINT(("QTAtom_hinf::DumpAtom - ..Payload string: %s\n", this->GetPayLoadStr()));
}

103
QTFileLib/QTAtom_hinf.h Normal file
View file

@ -0,0 +1,103 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_hinf:
// The 'hinf' QTAtom class.
#ifndef QTAtom_hinf_H
#define QTAtom_hinf_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_hinf : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_hinf(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_hinf(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline UInt64 GetTotalRTPBytes(void) { return fTotalRTPBytes32 ? (UInt64) fTotalRTPBytes32 : fTotalRTPBytes64 ; }
inline UInt64 GetTotalRTPPackets(void) { return fTotalRTPPackets32 ? (UInt64) fTotalRTPPackets32 : fTotalRTPPackets64; }
inline UInt64 GetTotalPayLoadBytes(void) { return fTotalPayLoadBytes32 ? (UInt64) fTotalPayLoadBytes32 : fTotalPayLoadBytes64; }
inline UInt64 GetMaxDataRate(void) { return fMaxDataRate64; }
inline UInt64 GetTotalMediaBytes(void) { return fTotalMediaBytes64; }
inline UInt64 GetTotalImmediateBytes(void) { return fTotalImmediateBytes64; }
inline UInt64 GetRepeatBytes(void) { return fTotalRepeatBytes64; }
inline UInt32 GetMinTransTime(void) { return fMinTransTime32; }
inline UInt32 GetMaxTransTime(void) { return fMaxTransTime32; }
inline UInt32 GetMaxPacketSizeBytes(void) { return fMaxPacketSizeBytes32; }
inline UInt32 GetMaxPacketDuration(void) { return fMaxPacketDuration32; }
inline UInt32 GetPayLoadID(void) { return fPayloadID;}
inline char* GetPayLoadStr(void) { return (char*) fPayloadStr;}
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt32 fTotalRTPBytes32; //totl
UInt64 fTotalRTPBytes64; //trpy
UInt32 fTotalRTPPackets32; //nump
UInt64 fTotalRTPPackets64; //npck
UInt32 fTotalPayLoadBytes32; //tpay
UInt64 fTotalPayLoadBytes64; //tpyl
UInt64 fMaxDataRate64; //maxr
UInt64 fTotalMediaBytes64; //dmed
UInt64 fTotalImmediateBytes64; //dimm
UInt64 fTotalRepeatBytes64; //drep
UInt32 fMinTransTime32; //tmin
UInt32 fMaxTransTime32; //tmax
UInt32 fMaxPacketSizeBytes32; //pmax
UInt32 fMaxPacketDuration32; //dmax
UInt32 fPayloadID;//payt
char fPayloadStr[262];//payt
};
#endif // QTAtom_hinf_H

161
QTFileLib/QTAtom_mdhd.cpp Normal file
View file

@ -0,0 +1,161 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_mdhd:
// The 'mdhd' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <time.h>
#include "SafeStdLib.h"
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_mdhd.h"
// -------------------------------------
// Constants
//
const int mdhdPos_VersionFlags = 0;
const int mdhdPos_CreationTime = 4;
const int mdhdPos_ModificationTime = 8;
const int mdhdPos_TimeScale = 12;
const int mdhdPos_Duration = 16;
const int mdhdPos_Language = 20;
const int mdhdPos_Quality = 22;
const int mdhdPosV1_CreationTime = 4;
const int mdhdPosV1_ModificationTime = 12;
const int mdhdPosV1_TimeScale = 20;
const int mdhdPosV1_Duration = 24;
const int mdhdPosV1_Language = 20 + 12;
const int mdhdPosV1_Quality = 22 + 12;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_mdhd::QTAtom_mdhd(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug)
{
}
QTAtom_mdhd::~QTAtom_mdhd(void)
{
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_mdhd::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(mdhdPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
if (0 == fVersion)
{
// Verify that this atom is the correct length.
if( fTOCEntry.AtomDataLength != 24 )
{
DEEP_DEBUG_PRINT(("QTAtom_mdhd::Initialize failed. Expected AtomDataLength == 24 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt32To64(mdhdPos_CreationTime, &fCreationTime);
ReadInt32To64(mdhdPos_ModificationTime, &fModificationTime);
ReadInt32(mdhdPos_TimeScale, &fTimeScale);
ReadInt32To64(mdhdPos_Duration, &fDuration);
ReadInt16(mdhdPos_Language, &fLanguage);
ReadInt16(mdhdPos_Quality, &fQuality);
}
else if (1 == fVersion)
{
// Verify that this atom is the correct length.
if( fTOCEntry.AtomDataLength != 36 )
{
DEEP_DEBUG_PRINT(("QTAtom_mdhd::Initialize failed. Expected AtomDataLength == 36 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt64(mdhdPosV1_CreationTime, &fCreationTime);
ReadInt64(mdhdPosV1_ModificationTime, &fModificationTime);
ReadInt32(mdhdPosV1_TimeScale, &fTimeScale);
ReadInt64(mdhdPosV1_Duration, &fDuration);
ReadInt16(mdhdPosV1_Language, &fLanguage);
ReadInt16(mdhdPosV1_Quality, &fQuality);
}
else
{
DEEP_DEBUG_PRINT(("QTAtom_mdhd::Initialize failed. Version unsupported: %d\n",fVersion));
return false;
}
//
// Compute the reciprocal of the timescale.
fTimeScaleRecip = 1 / (Float64)fTimeScale;
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_mdhd::DumpAtom(void)
{
// Temporary vars
time_t unixCreationTime = (time_t)fCreationTime + (time_t)QT_TIME_TO_LOCAL_TIME;
char buffer[kTimeStrSize];
struct tm timeResult;
DEBUG_PRINT(("QTAtom_mdhd::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_mdhd::DumpAtom - ..Version: %d.\n", (int) fVersion));
DEBUG_PRINT(("QTAtom_mdhd::DumpAtom - ..Creation date: %s", qtss_asctime(qtss_gmtime(&unixCreationTime, &timeResult),buffer,sizeof(buffer))));
}

83
QTFileLib/QTAtom_mdhd.h Normal file
View file

@ -0,0 +1,83 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_mdhd:
// The 'mdhd' QTAtom class.
#ifndef QTAtom_mdhd_H
#define QTAtom_mdhd_H
//
// Includes
#include "OSHeaders.h"
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_mdhd : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_mdhd(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_mdhd(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline Float64 GetTimeScale(void) { return (Float64)fTimeScale; }
inline Float64 GetTimeScaleRecip(void) { return fTimeScaleRecip; }
inline UInt64 GetDuration(void) { return fDuration; }
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt64 fCreationTime, fModificationTime;
UInt32 fTimeScale;
UInt64 fDuration;
UInt16 fLanguage;
UInt16 fQuality;
Float64 fTimeScaleRecip;
};
#endif // QTAtom_mdhd_H

229
QTFileLib/QTAtom_mvhd.cpp Normal file
View file

@ -0,0 +1,229 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_mvhd:
// The 'mvhd' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <time.h>
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_mvhd.h"
// -------------------------------------
// Constants
//
const int mvhdPos_VersionFlags = 0;
const int mvhdPos_CreationTime = 4;
const int mvhdPos_ModificationTime = 8;
const int mvhdPos_TimeScale = 12;
const int mvhdPos_Duration = 16;
const int mvhdPos_PreferredRate = 20;
const int mvhdPos_PreferredVolume = 24;
const int mvhdPos_a = 36;
const int mvhdPos_b = 40;
const int mvhdPos_u = 44;
const int mvhdPos_c = 48;
const int mvhdPos_d = 52;
const int mvhdPos_v = 56;
const int mvhdPos_x = 60;
const int mvhdPos_y = 64;
const int mvhdPos_w = 68;
const int mvhdPos_PreviewTime = 72;
const int mvhdPos_PreviewDuration = 76;
const int mvhdPos_PosterTime = 80;
const int mvhdPos_SelectionTime = 84;
const int mvhdPos_SelectionDuration = 88;
const int mvhdPos_CurrentTime = 92;
const int mvhdPos_NextTrackID = 96;
const int mvhdPosV1_CreationTime = 4; //+4 bytes
const int mvhdPosV1_ModificationTime = 12; //+4 bytes
const int mvhdPosV1_TimeScale = 20;
const int mvhdPosV1_Duration = 24; //+4 bytes
const int mvhdPosV1_PreferredRate = 20 + 12;
const int mvhdPosV1_PreferredVolume = 24 + 12;
const int mvhdPosV1_a = 36 + 12;
const int mvhdPosV1_b = 40 + 12;
const int mvhdPosV1_u = 44 + 12;
const int mvhdPosV1_c = 48 + 12;
const int mvhdPosV1_d = 52 + 12;
const int mvhdPosV1_v = 56 + 12;
const int mvhdPosV1_x = 60 + 12;
const int mvhdPosV1_y = 64 + 12;
const int mvhdPosV1_w = 68 + 12;
const int mvhdPosV1_PreviewTime = 72 + 12;
const int mvhdPosV1_PreviewDuration = 76 + 12;
const int mvhdPosV1_PosterTime = 80 + 12;
const int mvhdPosV1_SelectionTime = 84 + 12;
const int mvhdPosV1_SelectionDuration = 88 + 12;
const int mvhdPosV1_CurrentTime = 92 + 12;
const int mvhdPosV1_NextTrackID = 96 + 12;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_mvhd::QTAtom_mvhd(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug)
{
}
QTAtom_mvhd::~QTAtom_mvhd(void)
{
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_mvhd::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(mvhdPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
if (0 == fVersion)
{
// Verify that this atom is the correct length.
if( fTOCEntry.AtomDataLength != 100 )
{
DEEP_DEBUG_PRINT(("QTAtom_mvhd::Initialize failed. Expected AtomDataLength == 100 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt32To64(mvhdPos_CreationTime, &fCreationTime);
ReadInt32To64(mvhdPos_ModificationTime, &fModificationTime);
ReadInt32(mvhdPos_TimeScale, &fTimeScale);
ReadInt32To64(mvhdPos_Duration, &fDuration);
ReadInt32(mvhdPos_PreferredRate, &fPreferredRate);
ReadInt16(mvhdPos_PreferredVolume, &fPreferredVolume);
ReadInt32(mvhdPos_a, &fa);
ReadInt32(mvhdPos_b, &fb);
ReadInt32(mvhdPos_u, &fu);
ReadInt32(mvhdPos_c, &fc);
ReadInt32(mvhdPos_d, &fd);
ReadInt32(mvhdPos_v, &fv);
ReadInt32(mvhdPos_x, &fx);
ReadInt32(mvhdPos_y, &fy);
ReadInt32(mvhdPos_w, &fw);
ReadInt32(mvhdPos_PreviewTime, &fPreviewTime);
ReadInt32(mvhdPos_PreviewDuration, &fPreviewDuration);
ReadInt32(mvhdPos_PosterTime, &fPosterTime);
ReadInt32(mvhdPos_SelectionTime, &fSelectionTime);
ReadInt32(mvhdPos_SelectionDuration, &fSelectionDuration);
ReadInt32(mvhdPos_CurrentTime, &fCurrentTime);
ReadInt32(mvhdPos_NextTrackID, &fNextTrackID);
}
else if (1 == fVersion)
{
// Verify that this atom is the correct length.
if( fTOCEntry.AtomDataLength != 112 )
{
DEEP_DEBUG_PRINT(("QTAtom_mvhd::Initialize failed. Expected AtomDataLength = 112 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt64(mvhdPosV1_CreationTime, &fCreationTime);
ReadInt64(mvhdPosV1_ModificationTime, &fModificationTime);
ReadInt32(mvhdPosV1_TimeScale, &fTimeScale);
ReadInt64(mvhdPosV1_Duration, &fDuration);
ReadInt32(mvhdPosV1_PreferredRate, &fPreferredRate);
ReadInt16(mvhdPosV1_PreferredVolume, &fPreferredVolume);
ReadInt32(mvhdPosV1_a, &fa);
ReadInt32(mvhdPosV1_b, &fb);
ReadInt32(mvhdPosV1_u, &fu);
ReadInt32(mvhdPosV1_c, &fc);
ReadInt32(mvhdPosV1_d, &fd);
ReadInt32(mvhdPosV1_v, &fv);
ReadInt32(mvhdPosV1_x, &fx);
ReadInt32(mvhdPosV1_y, &fy);
ReadInt32(mvhdPosV1_w, &fw);
ReadInt32(mvhdPosV1_PreviewTime, &fPreviewTime);
ReadInt32(mvhdPosV1_PreviewDuration, &fPreviewDuration);
ReadInt32(mvhdPosV1_PosterTime, &fPosterTime);
ReadInt32(mvhdPosV1_SelectionTime, &fSelectionTime);
ReadInt32(mvhdPosV1_SelectionDuration, &fSelectionDuration);
ReadInt32(mvhdPosV1_CurrentTime, &fCurrentTime);
ReadInt32(mvhdPosV1_NextTrackID, &fNextTrackID);
}
else
{
DEEP_DEBUG_PRINT(("QTAtom_mvhd::Initialize failed. Version unsupported: %d\n",fVersion));
return false;
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_mvhd::DumpAtom(void)
{
// Temporary vars
time_t unixCreationTime = (time_t)fCreationTime + (time_t)QT_TIME_TO_LOCAL_TIME;
char buffer[kTimeStrSize];
struct tm timeResult;
DEBUG_PRINT(("QTAtom_mvhd::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_mvhd::DumpAtom - ..Version: %d.\n", (int) fVersion));
DEBUG_PRINT(("QTAtom_mvhd::DumpAtom - ..Creation date: %s", qtss_asctime(qtss_gmtime(&unixCreationTime, &timeResult),buffer,sizeof(buffer))));
DEBUG_PRINT(("QTAtom_mvhd::DumpAtom - ..Movie duration: %.2f seconds\n", GetDurationInSeconds()));
}

91
QTFileLib/QTAtom_mvhd.h Normal file
View file

@ -0,0 +1,91 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_mvhd:
// The 'mvhd' QTAtom class.
#ifndef QTAtom_mvhd_H
#define QTAtom_mvhd_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_mvhd : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_mvhd(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_mvhd(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline Float64 GetTimeScale(void) { return (Float64)fTimeScale; }
#if __Win32__
// Win compiler can't convert UInt64 to Float64. It does support SInt64 to Float64 though.
inline Float64 GetDurationInSeconds(void) { if (fTimeScale != 0){return (Float64)((SInt64)fDuration) / (Float64) ((SInt64)fTimeScale); } else {return (Float64) 0.0;} }
#else
inline Float64 GetDurationInSeconds(void) { if (fTimeScale != 0){ return fDuration / (Float64)fTimeScale; } else {return (Float64) 0.0;} }
#endif
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt64 fCreationTime, fModificationTime;
UInt32 fTimeScale;
UInt64 fDuration;
UInt32 fPreferredRate;
UInt16 fPreferredVolume;
UInt32 fa, fb, fu, fc, fd, fv, fx, fy, fw;
UInt32 fPreviewTime, fPreviewDuration, fPosterTime;
UInt32 fSelectionTime, fSelectionDuration;
UInt32 fCurrentTime;
UInt32 fNextTrackID;
};
#endif // QTAtom_mvhd_H

149
QTFileLib/QTAtom_stco.cpp Normal file
View file

@ -0,0 +1,149 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_stco:
// The 'stco' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stco.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int stcoPos_VersionFlags = 0;
const int stcoPos_NumEntries = 4;
const int stcoPos_SampleTable = 8;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_stco::QTAtom_stco(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, UInt16 offSetSize, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0),fOffSetSize(offSetSize), fChunkOffsetTable(NULL), fTable(NULL)
{
}
QTAtom_stco::~QTAtom_stco(void)
{
//
// Free our variables.
if( fChunkOffsetTable != NULL )
delete[] fChunkOffsetTable;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stco::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(stcoPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(stcoPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * fOffSetSize) != (fTOCEntry.AtomDataLength - 8) )
return false;
//
// Read in the chunk offset table.
fChunkOffsetTable = NEW char[(fNumEntries * fOffSetSize) + 1];
if( fChunkOffsetTable == NULL )
return false;
if( ((PointerSizedInt)fChunkOffsetTable & (PointerSizedInt)0x3) == 0)
fTable = (void *)fChunkOffsetTable;
else
fTable = (void *)(((PointerSizedInt)fChunkOffsetTable + 4) & ~((PointerSizedInt)0x3));
ReadBytes(stcoPos_SampleTable, (char *)fTable, fNumEntries * fOffSetSize);
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stco::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stco::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stco::DumpAtom - ..Number of chunk offset entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_stco::DumpTable(void)
{
//
// Print out a header.
qtss_printf("-- Chunk Offset table ----------------------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Chunk Num. Offset\n");
qtss_printf(" ---------- ----------\n");
//
// Print the table.
UInt64 offset = 0;
for( UInt32 CurEntry = 1; CurEntry <= fNumEntries; CurEntry++ )
{
if (ChunkOffset(CurEntry, &offset))
qtss_printf(" %10"_U32BITARG_": %"_64BITARG_"u\n", CurEntry, offset);
else
qtss_printf(" %10"_U32BITARG_": QTAtom_stco::DumpTable ChunkOffset error\n", CurEntry);
}
}

95
QTFileLib/QTAtom_stco.h Normal file
View file

@ -0,0 +1,95 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_stco:
// The 'stco' QTAtom class.
#ifndef QTAtom_stco_H
#define QTAtom_stco_H
//
// Includes
#ifndef __Win32__
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_stco : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stco(QTFile * File, QTFile::AtomTOCEntry * Atom,
UInt16 offSetSize = 4, Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stco(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline Bool16 ChunkOffset(UInt32 ChunkNumber, UInt64 *Offset = NULL)
{
if (Offset && ChunkNumber && (ChunkNumber<=fNumEntries))
{
if (4 == fOffSetSize)
*Offset = (UInt64) ntohl( ( (UInt32 *) fTable)[ChunkNumber-1]);
else
*Offset = (UInt64) QTAtom::NTOH64( ( (UInt64 *) fTable)[ChunkNumber-1]);
return true;
}
return false;
}
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
UInt16 fOffSetSize;
char *fChunkOffsetTable;
void *fTable; // longword-aligned version of the above
};
#endif // QTAtom_stco_H

619
QTFileLib/QTAtom_stsc.cpp Normal file
View file

@ -0,0 +1,619 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTAtom_stsc:
// The 'stsc' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stsc.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int stscPos_VersionFlags = 0;
const int stscPos_NumEntries = 4;
const int stscPos_SampleTable = 8;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Class state cookie
//
QTAtom_stsc_SampleTableControlBlock::QTAtom_stsc_SampleTableControlBlock(void)
{
Reset();
}
QTAtom_stsc_SampleTableControlBlock::~QTAtom_stsc_SampleTableControlBlock(void)
{
}
void QTAtom_stsc_SampleTableControlBlock::Reset(void)
{
fCurEntry = 0;
fCurSample = 1;
fLastFirstChunk = 1;
fLastSamplesPerChunk = 1;
fLastSampleDescription = 0;
fLastFirstChunk_GetChunkFirstLastSample = 1;
fLastSamplesPerChunk_GetChunkFirstLastSample = 1;
fLastTotalSamples_GetChunkFirstLastSample = 0;
fCurEntry_GetChunkFirstLastSample = 0;
chunkNumber_GetChunkFirstLastSample = 0;
firstSample_GetChunkFirstLastSample = 0;
lastSample_GetChunkFirstLastSample = 0;
fCurEntry_SampleToChunkInfo = 0;
fCurSample_SampleToChunkInfo = 1;
fLastFirstChunk_SampleToChunkInfo = 1;
fLastSamplesPerChunk_SampleToChunkInfo = 1;
fLastSampleDescription_SampleToChunkInfo = 0;
fFirstSampleNumber_SampleToChunkInfo = 0;
fFirstSamplesPerChunk_SampleToChunkInfo = 0;
fFirstChunkNumber_SampleToChunkInfo = 0;
fFirstSampleDescriptionIndex_SampleToChunkInfo = 0;
fFirstSampleOffsetInChunk_SampleToChunkInfo = 0;
fGetSampleInfo_SampleNumber = 0;
fGetSampleInfo_Length = 0;
fGetSampleInfo_SampleDescriptionIndex = 0;
fGetSampleInfo_Offset = 0;
fGetSampleInfo_LastChunk = 0;
fGetSampleInfo_LastChunkOffset = 0;
fGetSizeOfSamplesInChunk_chunkNumber = 0;
fGetSizeOfSamplesInChunk_firstSample = 0;
fGetSizeOfSamplesInChunk_lastSample = 0;
fGetSizeOfSamplesInChunk_size = 0;
}
// -------------------------------------
// Constructors and destructors
//
QTAtom_stsc::QTAtom_stsc(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fSampleToChunkTable(NULL), fTableSize(0)
{
}
QTAtom_stsc::~QTAtom_stsc(void)
{
//
// Free our variables.
#if MMAP_TABLES
if( fSampleToChunkTable != NULL )
this->UnMap(fSampleToChunkTable, fTableSize);
#else
if( fSampleToChunkTable != NULL )
delete[] fSampleToChunkTable;
#endif
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stsc::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(stscPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(stscPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * 12) != (fTOCEntry.AtomDataLength - 8) )
return false;
//
// Read in the sample-to-chunk table.
#if MMAP_TABLES
fTableSize = fNumEntries * 12;
fSampleToChunkTable = this->MemMap(stscPos_SampleTable, fTableSize);
if( fSampleToChunkTable == NULL )
return false;
#else
fSampleToChunkTable = NEW char[fNumEntries * 12];
if( fSampleToChunkTable == NULL )
return false;
ReadBytes(stscPos_SampleTable, fSampleToChunkTable, fNumEntries * 12);
#endif
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Accessors
//
Bool16 QTAtom_stsc::GetChunkFirstLastSample(UInt32 chunkNumber, UInt32 *firstSample, UInt32 *lastSample, QTAtom_stsc_SampleTableControlBlock *STCB)
{
// Temporary state var
QTAtom_stsc_SampleTableControlBlock *tempSTCB = NULL;
// General vars
UInt32 prevFirstChunk = 0, thisFirstChunk = 0;
UInt32 totalSamples = 0;
UInt32 numChunks = 0;
UInt32 numSamplesInChunks = 0;
UInt32 prevSamplesPerChunk = 0;
UInt32 samplesPerChunk = 0;
// qtss_printf("GetChunkFirstLastSample chunk = %d STCB->chunkNumber_GetChunkFirstLastSample= %d \n",chunkNumber,STCB->chunkNumber_GetChunkFirstLastSample);
if( STCB == NULL )
{
// qtss_printf(" QTAtom_stsc::GetChunkFirstLastSample (NULL == STCB) \n");
tempSTCB = NEW QTAtom_stsc_SampleTableControlBlock;
STCB = tempSTCB;
}
if ( (STCB->chunkNumber_GetChunkFirstLastSample == chunkNumber) && (STCB->lastSample_GetChunkFirstLastSample > 0) )
{
// qtss_printf("GetChunkFirstLastSample cache hit chunk = %d\n",chunkNumber);
if (firstSample) *firstSample = STCB->firstSample_GetChunkFirstLastSample;
if (lastSample) *lastSample = STCB->lastSample_GetChunkFirstLastSample;
goto GetChunkFirstLastSample_Done;
}
if (STCB->fCurEntry_GetChunkFirstLastSample > chunkNumber)
{
// qtss_printf(" QTAtom_stsc::GetChunkFirstLastSample missed Cache Loop \n");
STCB->fLastFirstChunk_GetChunkFirstLastSample = 1;
STCB->fLastSamplesPerChunk_GetChunkFirstLastSample = 1;
STCB->fLastTotalSamples_GetChunkFirstLastSample = 0;
STCB->fCurEntry_GetChunkFirstLastSample = 0;
STCB->chunkNumber_GetChunkFirstLastSample = 0;
STCB->firstSample_GetChunkFirstLastSample = 0;
STCB->lastSample_GetChunkFirstLastSample = 0;
}
if (STCB->fCurEntry_GetChunkFirstLastSample > 0)
{
// qtss_printf("GetChunkFirstLastSample cached loop chunk start = %d look for chunk = %"_S32BITARG_"\n",STCB->fLastFirstChunk_GetChunkFirstLastSample,chunkNumber);
samplesPerChunk = STCB->fLastSamplesPerChunk_GetChunkFirstLastSample;
totalSamples = STCB->fLastTotalSamples_GetChunkFirstLastSample;
thisFirstChunk = STCB->fLastFirstChunk_GetChunkFirstLastSample;
}
//
// Linearly search through the sample table until we find the chunk
// which contains the given sample.
if (fNumEntries == 1)
{
memcpy(&samplesPerChunk, fSampleToChunkTable + (STCB->fCurEntry_GetChunkFirstLastSample * 12) + 4, 4);
samplesPerChunk = ntohl(samplesPerChunk);
prevSamplesPerChunk = ((chunkNumber -1 ) * samplesPerChunk);
totalSamples = chunkNumber * samplesPerChunk;
}
else
for( ; STCB->fCurEntry_GetChunkFirstLastSample < fNumEntries; STCB->fCurEntry_GetChunkFirstLastSample++ )
{
// Copy this entry's fields.
prevSamplesPerChunk = samplesPerChunk;
prevFirstChunk = thisFirstChunk;
memcpy(&thisFirstChunk, fSampleToChunkTable + (STCB->fCurEntry_GetChunkFirstLastSample * 12) + 0, 4);
thisFirstChunk = ntohl(thisFirstChunk);
memcpy(&samplesPerChunk, fSampleToChunkTable + (STCB->fCurEntry_GetChunkFirstLastSample * 12) + 4, 4);
samplesPerChunk = ntohl(samplesPerChunk);
if (prevSamplesPerChunk == 0)
prevSamplesPerChunk = samplesPerChunk;
if ( chunkNumber < thisFirstChunk ) // found chunk in group
{
// qtss_printf("found chunk in group numEntries = %"_S32BITARG_" this chunk = %"_S32BITARG_" \n",fNumEntries, chunkNumber);
numSamplesInChunks = (chunkNumber - prevFirstChunk) * prevSamplesPerChunk;
totalSamples += numSamplesInChunks;
prevSamplesPerChunk = totalSamples - prevSamplesPerChunk;
break;
}
if ( chunkNumber == thisFirstChunk ) // found chunk
{
numSamplesInChunks = samplesPerChunk;
totalSamples += numSamplesInChunks;
prevSamplesPerChunk = totalSamples - samplesPerChunk;
break;
}
numChunks = chunkNumber - prevFirstChunk;
numSamplesInChunks = numChunks * samplesPerChunk;
totalSamples += numSamplesInChunks;
//
// We have yet to find the sample; update our CurSample counter
// and move on.
STCB->fLastFirstChunk_GetChunkFirstLastSample = thisFirstChunk;
STCB->fLastSamplesPerChunk_GetChunkFirstLastSample = samplesPerChunk;
STCB->fLastTotalSamples_GetChunkFirstLastSample = totalSamples;
}
if (firstSample) *firstSample = prevSamplesPerChunk + 1;
if (lastSample) *lastSample = totalSamples;
// qtss_printf("Get Chunk %"_S32BITARG_" First %"_S32BITARG_" Last %"_S32BITARG_" prevSamplesPerChunk %"_S32BITARG_" samplesPerChunk %"_S32BITARG_"\n",chunkNumber,*firstSample,*lastSample,prevSamplesPerChunk,samplesPerChunk);
STCB->chunkNumber_GetChunkFirstLastSample = chunkNumber;
STCB->firstSample_GetChunkFirstLastSample = prevSamplesPerChunk + 1;
STCB->lastSample_GetChunkFirstLastSample = totalSamples;
GetChunkFirstLastSample_Done:
delete tempSTCB;
return true;
}
UInt32 QTAtom_stsc::GetChunkFirstSample(UInt32 chunkNumber)
{
// Temporary state var
QTAtom_stsc_SampleTableControlBlock localSTCB;
QTAtom_stsc_SampleTableControlBlock *STCB = &localSTCB;
// General vars
UInt32 prevFirstChunk = 0, thisFirstChunk = 0, sampleDescription = 0;
UInt32 totalSamples = 1;
UInt32 numChunks = 0;
UInt32 numSamplesInChunks = 0;
UInt32 thisChunk = 0;
UInt32 prevSamplesPerChunk = 0;
UInt32 samplesPerChunk = 0;
//
// Linearly search through the sample table until we find the chunk
// which contains the given sample.
for( ; STCB->fCurEntry < fNumEntries; STCB->fCurEntry++ )
{
// Copy this entry's fields.
prevSamplesPerChunk = samplesPerChunk;
prevFirstChunk = thisFirstChunk;
memcpy(&thisFirstChunk, fSampleToChunkTable + (STCB->fCurEntry * 12) + 0, 4);
thisFirstChunk = ntohl(thisFirstChunk);
memcpy(&samplesPerChunk, fSampleToChunkTable + (STCB->fCurEntry * 12) + 4, 4);
samplesPerChunk = ntohl(samplesPerChunk);
memcpy(&sampleDescription, fSampleToChunkTable + (STCB->fCurEntry * 12) + 8, 4);
sampleDescription = ntohl(sampleDescription);
thisChunk = thisFirstChunk;
numChunks = thisFirstChunk - prevFirstChunk;
if ( chunkNumber <= thisFirstChunk ) // found chunk in group
{
numChunks = chunkNumber - prevFirstChunk;
numSamplesInChunks = numChunks * prevSamplesPerChunk;
totalSamples += numSamplesInChunks;
break;
}
numChunks = thisFirstChunk - prevFirstChunk;
numSamplesInChunks = numChunks * prevSamplesPerChunk;
totalSamples += numSamplesInChunks;
//
// We have yet to find the sample; update our CurSample counter
// and move on.
STCB->fLastFirstChunk = thisFirstChunk;
STCB->fLastSampleDescription = sampleDescription;
STCB->fLastSamplesPerChunk = samplesPerChunk;
}
return totalSamples;
}
//UInt32 gstscCacheCount = 0;
//UInt32 gstscCallCount = 0;
Bool16 QTAtom_stsc::SampleToChunkInfo(UInt32 SampleNumber, UInt32 *samplesPerChunk, UInt32 *ChunkNumber, UInt32 *SampleDescriptionIndex, UInt32 *SampleOffsetInChunk, QTAtom_stsc_SampleTableControlBlock * STCB)
{
// Temporary state var
QTAtom_stsc_SampleTableControlBlock *tempSTCB = NULL;
// General vars
UInt32 NewCurSample;
UInt32 FirstChunk = 0, SamplesPerChunk = 0, SampleDescription = 0;
Bool16 missedCache = false;
if (STCB == NULL )
{
// qtss_printf(" QTAtom_stsc::SampleToChunkInfo (NULL == STCB) \n");
tempSTCB = NEW QTAtom_stsc_SampleTableControlBlock;
STCB = tempSTCB;
}
UInt32 aChunkNumber = 0;
UInt32 aSampleDescriptionIndex = 0;
UInt32 aSampleOffsetInChunk = 0;
UInt32 aSamplesPerChunk = 0;
/*
gstscCallCount ++;
if (gstscCallCount == 1000)
{
qtss_printf("QTAtom_stsc::SampleToChunkInfo #calls = %"_S32BITARG_", cache hits = %"_S32BITARG_" \n",gstscCallCount, gstscCacheCount);
gstscCacheCount = 0;
gstscCallCount = 0;
}
*/
//
// Use a temporary STCB if we weren't given one. We cannot use a default
// STCB as we would have no way to know when we are seeking around in the
// movie.
// qtss_printf("------ QTAtom_stsc::SampleToChunkInfo SampleNumber = %"_S32BITARG_"\n",SampleNumber);
if (STCB->fFirstSampleNumber_SampleToChunkInfo == SampleNumber)
{
// qtss_printf("------ QTAtom_stsc::SampleToChunkInfo cache hit SampleNumber = %"_S32BITARG_"\n",SampleNumber);
// gstscCacheCount ++;
aChunkNumber = STCB->fFirstChunkNumber_SampleToChunkInfo;
aSampleDescriptionIndex = STCB->fFirstSampleDescriptionIndex_SampleToChunkInfo;
aSamplesPerChunk = STCB->fFirstSamplesPerChunk_SampleToChunkInfo;
aSampleOffsetInChunk = STCB->fFirstSampleOffsetInChunk_SampleToChunkInfo;
if( ChunkNumber != NULL )
*ChunkNumber = aChunkNumber;
if( SampleDescriptionIndex != NULL )
*SampleDescriptionIndex = aSampleDescriptionIndex;
if( SampleOffsetInChunk != NULL )
*SampleOffsetInChunk = aSampleOffsetInChunk;
if (NULL != samplesPerChunk)
*samplesPerChunk = aSamplesPerChunk;
goto done;
}
// qtss_printf("QTAtom_stsc::SampleToChunkInfo missed cache SampleNumber = %"_S32BITARG_"\n",SampleNumber);
//
// Assume that this sample came out of the last chunk.
aChunkNumber = STCB->fLastFirstChunk_SampleToChunkInfo + ((SampleNumber - STCB->fCurSample_SampleToChunkInfo) / STCB->fLastSamplesPerChunk_SampleToChunkInfo) ;
aSampleDescriptionIndex = STCB->fLastSampleDescription_SampleToChunkInfo;
aSampleOffsetInChunk = SampleNumber - (STCB->fCurSample_SampleToChunkInfo + ((aChunkNumber - STCB->fLastFirstChunk_SampleToChunkInfo) * STCB->fLastSamplesPerChunk_SampleToChunkInfo));
aSamplesPerChunk = STCB->fLastSamplesPerChunk_SampleToChunkInfo;
if( ChunkNumber != NULL )
*ChunkNumber = aChunkNumber;
if( SampleDescriptionIndex != NULL )
*SampleDescriptionIndex = aSampleDescriptionIndex;
if( SampleOffsetInChunk != NULL )
*SampleOffsetInChunk = aSampleOffsetInChunk;
if (NULL != samplesPerChunk)
*samplesPerChunk = aSamplesPerChunk;
//
// Linear search through the sample table until we find the chunk
// which contains the given sample.
if (STCB->fCurSample_SampleToChunkInfo > SampleNumber) // we missed the cache start over
{
missedCache = true;
// qtss_printf("missed loop Cache!! STCB = %"_S32BITARG_" STCB->fCurSample_SampleToChunkInfo = %"_S32BITARG_" > SampleNumber = %"_S32BITARG_" \n",STCB, STCB->fCurSample_SampleToChunkInfo, SampleNumber);
STCB->fCurEntry_SampleToChunkInfo = 0;
STCB->fCurSample_SampleToChunkInfo = 1;
STCB->fLastFirstChunk_SampleToChunkInfo = 1;
STCB->fLastSamplesPerChunk_SampleToChunkInfo = 1;
STCB->fLastSampleDescription_SampleToChunkInfo = 0;
}
for(; STCB->fCurEntry_SampleToChunkInfo < fNumEntries; STCB->fCurEntry_SampleToChunkInfo++ ) {
//
// Copy this entry's fields.
memcpy(&FirstChunk, fSampleToChunkTable + (STCB->fCurEntry_SampleToChunkInfo * 12) + 0, 4);
FirstChunk = ntohl(FirstChunk);
memcpy(&SamplesPerChunk, fSampleToChunkTable + (STCB->fCurEntry_SampleToChunkInfo * 12) + 4, 4);
SamplesPerChunk = ntohl(SamplesPerChunk);
memcpy(&SampleDescription, fSampleToChunkTable + (STCB->fCurEntry_SampleToChunkInfo * 12) + 8, 4);
SampleDescription = ntohl(SampleDescription);
//
// Check to see if the sample was actually in the last chunk and
// return if it was.
NewCurSample = STCB->fCurSample_SampleToChunkInfo + (FirstChunk - STCB->fLastFirstChunk_SampleToChunkInfo) * STCB->fLastSamplesPerChunk_SampleToChunkInfo ;
if( SampleNumber < NewCurSample )
{
if( ChunkNumber != NULL )
*ChunkNumber = aChunkNumber;
if( SampleDescriptionIndex != NULL )
*SampleDescriptionIndex = aSampleDescriptionIndex;
if( SampleOffsetInChunk != NULL )
*SampleOffsetInChunk = aSampleOffsetInChunk;
if (NULL != samplesPerChunk)
*samplesPerChunk = aSamplesPerChunk;
if (SampleNumber == 1 || missedCache)
{
// qtss_printf("QTAtom_stsc::SampleToChunkInfo (SampleNumber == %"_S32BITARG_") \n",SampleNumber);
STCB->fFirstChunkNumber_SampleToChunkInfo = aChunkNumber;
STCB->fFirstSampleDescriptionIndex_SampleToChunkInfo = aSampleDescriptionIndex;
STCB->fFirstSamplesPerChunk_SampleToChunkInfo = aSamplesPerChunk;
STCB->fFirstSampleOffsetInChunk_SampleToChunkInfo = aSampleOffsetInChunk;
STCB->fFirstSampleNumber_SampleToChunkInfo = SampleNumber;
}
// qtss_printf("GetSample Info in for loop returning offset %"_S32BITARG_" \n",aSampleOffsetInChunk);
goto done;
}
STCB->fCurSample_SampleToChunkInfo = NewCurSample;
//
// Assume that the sample will be in this chunk.
aChunkNumber = FirstChunk + ((SampleNumber - STCB->fCurSample_SampleToChunkInfo) / SamplesPerChunk) ;
aSampleDescriptionIndex = SampleDescription;
aSampleOffsetInChunk = SampleNumber - (STCB->fCurSample_SampleToChunkInfo + ((aChunkNumber - FirstChunk) * SamplesPerChunk));
aSamplesPerChunk = SamplesPerChunk;
//
// We have yet to find the sample; update our CurSample counter
// and move on.
STCB->fLastFirstChunk_SampleToChunkInfo = FirstChunk;
STCB->fLastSampleDescription_SampleToChunkInfo = SampleDescription;
STCB->fLastSamplesPerChunk_SampleToChunkInfo = SamplesPerChunk;
}
// qtss_printf("GetSample Info fall out of loop returning offset%"_S32BITARG_" \n",aSampleOffsetInChunk);
//
// Falling out of the loop means that the sample is in the last chunk of
// the table.
if( ChunkNumber != NULL )
*ChunkNumber = aChunkNumber;
if( SampleDescriptionIndex != NULL )
*SampleDescriptionIndex = aSampleDescriptionIndex;
if( SampleOffsetInChunk != NULL )
*SampleOffsetInChunk = aSampleOffsetInChunk;
if (NULL != samplesPerChunk)
*samplesPerChunk = aSamplesPerChunk;
if (SampleNumber == 1 || missedCache)
{
STCB->fFirstChunkNumber_SampleToChunkInfo = aChunkNumber;
STCB->fFirstSampleDescriptionIndex_SampleToChunkInfo = aSampleDescriptionIndex;
STCB->fFirstSamplesPerChunk_SampleToChunkInfo = aSamplesPerChunk;
STCB->fFirstSampleOffsetInChunk_SampleToChunkInfo = aSampleOffsetInChunk;
STCB->fFirstSampleNumber_SampleToChunkInfo = SampleNumber;
}
done:
delete tempSTCB;
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stsc::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stsc::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stsc::DumpAtom - ..Number of STC entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_stsc::DumpTable(void)
{
// General vars
UInt32 FirstChunk = 0, SamplesPerChunk = 0, SampleDescription = 0;
//
// Print out a header.
qtss_printf("-- Sample-to-Chunk table -------------------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Sample Num FirstChunk Samples/Chunk Sample Description\n");
qtss_printf(" ---------- ---------- ------------- ------------------\n");
//
// Print the table.
for( UInt32 CurEntry = 0; CurEntry < fNumEntries; CurEntry++ ) {
//
// Copy this entry's fields.
memcpy(&FirstChunk, fSampleToChunkTable + (CurEntry * 12) + 0, 4);
FirstChunk = ntohl(FirstChunk);
memcpy(&SamplesPerChunk, fSampleToChunkTable + (CurEntry * 12) + 4, 4);
SamplesPerChunk = ntohl(SamplesPerChunk);
memcpy(&SampleDescription, fSampleToChunkTable + (CurEntry * 12) + 8, 4);
SampleDescription = ntohl(SampleDescription);
//
// Print out a listing.
qtss_printf(" %10"_U32BITARG_" : %10"_U32BITARG_" %10"_U32BITARG_" %10"_U32BITARG_"\n",
CurEntry+1, FirstChunk, SamplesPerChunk, SampleDescription);
}
}

150
QTFileLib/QTAtom_stsc.h Normal file
View file

@ -0,0 +1,150 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stsc.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stsc:
// The 'stsc' QTAtom class.
#ifndef QTAtom_stsc_H
#define QTAtom_stsc_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// Class state cookie
class QTAtom_stsc_SampleTableControlBlock {
public:
//
// Constructor and destructor.
QTAtom_stsc_SampleTableControlBlock(void);
virtual ~QTAtom_stsc_SampleTableControlBlock(void);
//
// Reset function
void Reset(void);
//
// Sample table cache
UInt32 fCurEntry;
UInt32 fCurSample;
UInt32 fLastFirstChunk, fLastSamplesPerChunk, fLastSampleDescription;
UInt32 fLastFirstChunk_GetChunkFirstLastSample;
UInt32 fLastSamplesPerChunk_GetChunkFirstLastSample;
UInt32 fLastTotalSamples_GetChunkFirstLastSample;
UInt32 fCurEntry_GetChunkFirstLastSample;
UInt32 chunkNumber_GetChunkFirstLastSample;
UInt32 firstSample_GetChunkFirstLastSample;
UInt32 lastSample_GetChunkFirstLastSample;
UInt32 fFirstSampleNumber_SampleToChunkInfo;
UInt32 fFirstSamplesPerChunk_SampleToChunkInfo;
UInt32 fFirstChunkNumber_SampleToChunkInfo;
UInt32 fFirstSampleDescriptionIndex_SampleToChunkInfo;
UInt32 fFirstSampleOffsetInChunk_SampleToChunkInfo;
UInt32 fCurEntry_SampleToChunkInfo;
UInt32 fCurSample_SampleToChunkInfo;
UInt32 fLastFirstChunk_SampleToChunkInfo;
UInt32 fLastSamplesPerChunk_SampleToChunkInfo;
UInt32 fLastSampleDescription_SampleToChunkInfo;
UInt32 fGetSampleInfo_SampleNumber;
UInt32 fGetSampleInfo_Length;
UInt32 fGetSampleInfo_SampleDescriptionIndex;
UInt64 fGetSampleInfo_Offset;
UInt32 fGetSampleInfo_LastChunk;
UInt32 fGetSampleInfo_LastChunkOffset;
UInt32 fGetSizeOfSamplesInChunk_chunkNumber;
UInt32 fGetSizeOfSamplesInChunk_firstSample;
UInt32 fGetSizeOfSamplesInChunk_lastSample;
UInt32 fGetSizeOfSamplesInChunk_size;
};
//
// QTAtom class
class QTAtom_stsc : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stsc(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stsc(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
Bool16 GetChunkFirstLastSample(UInt32 chunkNumber, UInt32 *firstSample, UInt32 *lastSample, QTAtom_stsc_SampleTableControlBlock *STCB);
Bool16 SampleToChunkInfo(UInt32 SampleNumber,
UInt32 *samplesPerChunk = NULL,
UInt32 *ChunkNumber = NULL,
UInt32 *SampleDescriptionIndex = NULL,
UInt32 *SampleOffsetInChunk = NULL,
QTAtom_stsc_SampleTableControlBlock * STCB = NULL);
inline Bool16 SampleNumberToChunkNumber(UInt32 SampleNumber, UInt32 *ChunkNumber = NULL, UInt32 *SampleDescriptionIndex = NULL, UInt32 *SampleOffsetInChunk = NULL,
QTAtom_stsc_SampleTableControlBlock * STCB = NULL)
{ return SampleToChunkInfo(SampleNumber,NULL /*samplesPerChunk*/, ChunkNumber, SampleDescriptionIndex, SampleOffsetInChunk, STCB); }
UInt32 GetChunkFirstSample(UInt32 chunkNumber);
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
char *fSampleToChunkTable;
UInt32 fTableSize;
};
#endif // QTAtom_stsc_H

222
QTFileLib/QTAtom_stsd.cpp Normal file
View file

@ -0,0 +1,222 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stsd.cpp,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stsd:
// The 'stsd' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stsd.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int stsdPos_VersionFlags = 0;
const int stsdPos_NumEntries = 4;
const int stsdPos_SampleTable = 8;
const int stsdDescPos_Size = 0;
const int stsdDescPos_DataFormat = 4;
const int stsdDescPos_Index = 14;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_stsd::QTAtom_stsd(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fSampleDescriptionTable(NULL), fTable(NULL)
{
}
QTAtom_stsd::~QTAtom_stsd(void)
{
//
// Free our variables.
if( fSampleDescriptionTable != NULL )
delete[] fSampleDescriptionTable;
if( fTable != NULL )
delete[] fTable;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stsd::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
// General vars
char *pSampleDescriptionTable;
//
// Parse this atom's fields.
ReadInt32(stsdPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(stsdPos_NumEntries, &fNumEntries);
//
// Read in all of the sample descriptions.
if( fNumEntries > 0 ) {
//
// Allocate our description tables.
UInt64 tableSize = fTOCEntry.AtomDataLength - 8;
Assert(tableSize < kSInt32_Max);
fSampleDescriptionTable = NEW char[ (SInt32) tableSize];
if( fSampleDescriptionTable == NULL )
return false;
fTable = NEW char *[fNumEntries];
if( fTable == NULL )
return false;
//
// Read in the sample description table.
ReadBytes(stsdPos_SampleTable, fSampleDescriptionTable, (UInt32) tableSize);
//
// Read them all in..
pSampleDescriptionTable = fSampleDescriptionTable;
char *maxSampleDescriptionPtr = pSampleDescriptionTable + tableSize;
for( UInt32 CurDesc = 0; CurDesc < fNumEntries; CurDesc++ ) {
//
// Associate this entry in our Table with the actual location of
// this sample description.
fTable[CurDesc] = pSampleDescriptionTable;
//
// Skip over this mini-atom.
memcpy(&tempInt32, pSampleDescriptionTable, 4);
pSampleDescriptionTable += ntohl(tempInt32);
if (pSampleDescriptionTable > maxSampleDescriptionPtr)
{ return false;
}
}
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Accessors
//
Bool16 QTAtom_stsd::FindSampleDescription(OSType DataFormat, char ** Buffer, UInt32 * Length)
{
// Temporary vars
UInt32 tempInt32;
//
// Go through all of the sample descriptions, looking for the requested
// entry.
for( UInt32 CurDesc = 0; CurDesc < fNumEntries; CurDesc++ ) {
//
// Get this entry's data format.
memcpy(&tempInt32, fTable[CurDesc] + stsdDescPos_DataFormat, 4);
tempInt32 = ntohl(tempInt32);
//
// Skip this entry if it does not match.
if( DataFormat != tempInt32 )
continue;
//
// We found a match; return it.
*Buffer = fTable[CurDesc];
memcpy(&tempInt32, fTable[CurDesc] + stsdDescPos_Size, 4);
*Length = ntohl(tempInt32);
return true;
}
//
// No match was found.
return false;
}
UInt16 QTAtom_stsd::SampleDescriptionToDataReference(UInt32 SampleDescriptionID)
{
// Temporary vars
UInt16 tempInt16;
//
// Validate our arguments.
if( SampleDescriptionID > fNumEntries )
return 1;
//
// Find and return the given sample's data reference index.
memcpy(&tempInt16, fTable[SampleDescriptionID - 1] + stsdDescPos_Index, 2);
return ntohs(tempInt16);
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stsd::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stsd::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stsd::DumpAtom - ..Number of sample description entries: %"_S32BITARG_"\n", fNumEntries));
}

79
QTFileLib/QTAtom_stsd.h Normal file
View file

@ -0,0 +1,79 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stsd.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stsd:
// The 'stsd' QTAtom class.
#ifndef QTAtom_stsd_H
#define QTAtom_stsd_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_stsd : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stsd(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stsd(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
Bool16 FindSampleDescription(OSType DataFormat, char ** Buffer, UInt32 * Length);
UInt16 SampleDescriptionToDataReference(UInt32 SampleDescriptionID);
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
char *fSampleDescriptionTable;
char **fTable; // each entry points to the start of a sample
// description entry in the above memory area
};
#endif // QTAtom_stsd_H

231
QTFileLib/QTAtom_stss.cpp Normal file
View file

@ -0,0 +1,231 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stss.cpp,v 1.2 2006/03/29 00:47:00 murata Exp $
//
// QTAtom_stss:
// The 'stss' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stss.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int stssPos_VersionFlags = 0;
const int stssPos_NumEntries = 4;
const int stssPos_SampleTable = 8;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_stss::QTAtom_stss(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fSyncSampleTable(NULL), fTable(NULL), fTableSize(0)
{
}
QTAtom_stss::~QTAtom_stss(void)
{
//
// Free our variables.
#if MMAP_TABLES
if( fSyncSampleTable != NULL )
this->UnMap(fSyncSampleTable, fTableSize);
#else
if( fSyncSampleTable != NULL )
delete[] fSyncSampleTable;
#endif
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stss::Initialize(void)
{
Bool16 initSucceeds = false;
UInt32 tempInt32;
//
// Parse this atom's fields.
initSucceeds = ReadInt32(stssPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
if ( initSucceeds )
{
initSucceeds = ReadInt32(stssPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * 4) != (fTOCEntry.AtomDataLength - 8) )
return false;
#if 0// MMAP_TABLES needs fixing should be page aligned and maybe on a 64bit system the whole file should be mapped.
fTableSize = (fNumEntries * 4);
fSyncSampleTable = this->MemMap(stssPos_SampleTable, fTableSize);
fTable = (UInt32 *) fSyncSampleTable;
if (fSyncSampleTable == NULL)
return false;
#else
//
// Read in the sync sample table.
fSyncSampleTable = NEW char[(fNumEntries * 4) + 1];
if( fSyncSampleTable == NULL )
return false;
if( ((PointerSizedInt)fSyncSampleTable & (PointerSizedInt)0x3) == 0)
fTable = (UInt32 *)fSyncSampleTable;
else
fTable = (UInt32 *)(((PointerSizedInt)fSyncSampleTable + 4) & ~((PointerSizedInt)0x3));
initSucceeds = ReadBytes(stssPos_SampleTable, (char *)fTable, fNumEntries * 4);
#endif
if ( initSucceeds )
{
// This atom has been successfully read in.
// sample offsets are in network byte order on disk, convert them to host order
UInt32 sampleIndex = 0;
// convert each sample to host order
// NOTE - most other Atoms handle byte order conversions in
// the accessor function. For efficiency reasons it's converted
// to host order here for sync samples.
for ( sampleIndex = 0; sampleIndex < fNumEntries; sampleIndex++ )
{
fTable[sampleIndex] = ntohl( fTable[sampleIndex] );
}
}
}
return initSucceeds;
}
// -------------------------------------
// Accessors
//
void QTAtom_stss::PreviousSyncSample(UInt32 SampleNumber, UInt32 *SyncSampleNumber)
{
//
// We assume that we won't find an answer
*SyncSampleNumber = SampleNumber;
//
// Scan the table until we find a sample number greater than our current
// sample number; then return that.
for( UInt32 CurEntry = 0; CurEntry < fNumEntries; CurEntry++ ) {
//
// Take this entry if it is before (or equal to) our current entry.
if( fTable[CurEntry] <= SampleNumber )
*SyncSampleNumber = fTable[CurEntry];
}
}
void QTAtom_stss::NextSyncSample(UInt32 SampleNumber, UInt32 *SyncSampleNumber)
{
//
// We assume that we won't find an answer
*SyncSampleNumber = SampleNumber + 1;
//
// Scan the table until we find a sample number greater than our current
// sample number; then return that.
for( UInt32 CurEntry = 0; CurEntry < fNumEntries; CurEntry++ ) {
//
// Take this entry if it is greater than our current entry.
if( fTable[CurEntry] > SampleNumber ) {
*SyncSampleNumber = fTable[CurEntry];
break;
}
}
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stss::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stss::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stss::DumpAtom - ..Number of sync sample entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_stss::DumpTable(void)
{
//
// Print out a header.
qtss_printf("-- Sync Sample table -----------------------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Entry Num. Sample Num\n");
qtss_printf(" ---------- ----------\n");
//
// Print the table.
for( UInt32 CurEntry = 1; CurEntry <= fNumEntries; CurEntry++ ) {
//
// Print out a listing.
qtss_printf(" %10"_U32BITARG_" : %10"_U32BITARG_"\n", CurEntry, fTable[CurEntry-1]);
}
}

93
QTFileLib/QTAtom_stss.h Normal file
View file

@ -0,0 +1,93 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stss.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stss:
// The 'stss' QTAtom class.
#ifndef QTAtom_stss_H
#define QTAtom_stss_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
#include "MyAssert.h"
//
// QTAtom class
class QTAtom_stss : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stss(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stss(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
void PreviousSyncSample(UInt32 SampleNumber, UInt32 *SyncSampleNumber);
void NextSyncSample(UInt32 SampleNumber, UInt32 *SyncSampleNumber);
inline Bool16 IsSyncSample(UInt32 SampleNumber, UInt32 inCursor)
{
Assert(inCursor <= fNumEntries);
for (UInt32 curEntry = inCursor; curEntry < fNumEntries; curEntry++)
{
if (fTable[curEntry] == SampleNumber)
return true;
else if (fTable[curEntry] > SampleNumber)
return false;
}
return false;
}
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
char *fSyncSampleTable;
UInt32 *fTable; // longword-aligned version of the above
UInt32 fTableSize;
};
#endif // QTAtom_stss_H

205
QTFileLib/QTAtom_stsz.cpp Normal file
View file

@ -0,0 +1,205 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stsz.cpp,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stsz:
// The 'stsz' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stsz.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int stszPos_VersionFlags = 0;
const int stszPos_SampleSize = 4;
const int stszPos_NumEntries = 8;
const int stszPos_SampleTable = 12;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_stsz::QTAtom_stsz(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fCommonSampleSize(0),
fNumEntries(0), fSampleSizeTable(NULL), fTable(NULL)
{
}
QTAtom_stsz::~QTAtom_stsz(void)
{
//
// Free our variables.
if( fSampleSizeTable != NULL )
delete[] fSampleSizeTable;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stsz::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(stszPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(stszPos_SampleSize, &fCommonSampleSize);
//
// We don't need to read in the table (it doesn't exist anyway) if the
// SampleSize field is non-zero.
if( fCommonSampleSize != 0 )
return true;
//
// Build the table..
ReadInt32(stszPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * 4) != (fTOCEntry.AtomDataLength - 12) )
return false;
//
// Read in the sample size table.
fSampleSizeTable = NEW char[(fNumEntries * 4) + 1];
if( fSampleSizeTable == NULL )
return false;
if( ((PointerSizedInt)fSampleSizeTable & (PointerSizedInt)0x3) == 0)
fTable = (UInt32 *)fSampleSizeTable;
else
fTable = (UInt32 *)(((PointerSizedInt)fSampleSizeTable + 4) & ~((PointerSizedInt)0x3));
ReadBytes(stszPos_SampleTable, (char *)fTable, fNumEntries * 4);
//
// This atom has been successfully read in.
return true;
}
Bool16 QTAtom_stsz::SampleRangeSize(UInt32 firstSampleNumber, UInt32 lastSampleNumber, UInt32 *sizePtr)
{
Bool16 result = false;
do
{
if (lastSampleNumber < firstSampleNumber)
{
// qtss_printf("QTAtom_stsz::SampleRangeSize (lastSampleNumber %"_S32BITARG_" < firstSampleNumber %"_S32BITARG_") \n",lastSampleNumber, firstSampleNumber);
break;
}
if(fCommonSampleSize)
{
// qtss_printf("QTAtom_stsz::SampleRangeSize fCommonSampleSize %"_S32BITARG_" firstSampleNumber %"_S32BITARG_" lastSampleNumber %"_S32BITARG_" *sizePtr %"_S32BITARG_"\n",fCommonSampleSize,firstSampleNumber,lastSampleNumber,*sizePtr);
if( sizePtr != NULL )
*sizePtr = fCommonSampleSize * (lastSampleNumber - firstSampleNumber + 1) ;
result = true;
break;
}
if(firstSampleNumber && lastSampleNumber && (lastSampleNumber<=fNumEntries) && (firstSampleNumber <= fNumEntries) )
{
if( sizePtr != NULL )
{ *sizePtr = 0;
for (UInt32 sampleNumber = firstSampleNumber; sampleNumber <= lastSampleNumber; sampleNumber++ )
*sizePtr += ntohl(fTable[sampleNumber-1]);
}
result = true;
break;
}
}
while (false);
return result;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stsz::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stsz::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stsz::DumpAtom - ..Number of sample size entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_stsz::DumpTable(void)
{
//
// Print out a header.
qtss_printf("-- Sample Size table -----------------------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Sample Num SampleSize\n");
qtss_printf(" ---------- ----------\n");
//
// Print the table.
for( UInt32 CurEntry = 1; CurEntry <= fNumEntries; CurEntry++ ) {
//
// Print out a listing.
qtss_printf(" %10"_U32BITARG_" : %10"_U32BITARG_"\n", CurEntry, fTable[CurEntry-1]);
}
}

92
QTFileLib/QTAtom_stsz.h Normal file
View file

@ -0,0 +1,92 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stsz.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stsz:
// The 'stsz' QTAtom class.
#ifndef QTAtom_stsz_H
#define QTAtom_stsz_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_stsz : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stsz(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stsz(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline Bool16 SampleSize(UInt32 SampleNumber, UInt32 *Size = NULL) \
{ if(fCommonSampleSize) { \
if( Size != NULL ) \
*Size = fCommonSampleSize; \
return true; \
} else if(SampleNumber && (SampleNumber<=fNumEntries)) { \
if( Size != NULL ) \
*Size = ntohl(fTable[SampleNumber-1]); \
return true; \
} else \
return false; \
};
Bool16 SampleRangeSize(UInt32 firstSampleNumber, UInt32 lastSampleNumber, UInt32 *sizePtr);
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
inline UInt32 GetNumEntries() {return fNumEntries;}
inline UInt32 GetCommonSampleSize() {return fCommonSampleSize;}
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fCommonSampleSize;
UInt32 fNumEntries;
char *fSampleSizeTable;
UInt32 *fTable; // longword-aligned version of the above
};
#endif // QTAtom_stsz_H

581
QTFileLib/QTAtom_stts.cpp Normal file
View file

@ -0,0 +1,581 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stts.cpp,v 1.2 2006/03/29 00:47:00 murata Exp $
//
// QTAtom_stts:
// The 'stts' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <sys/types.h>
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_stts.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int sttsPos_VersionFlags = 0;
const int sttsPos_NumEntries = 4;
const int sttsPos_SampleTable = 8;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Class state cookie
//
QTAtom_stts_SampleTableControlBlock::QTAtom_stts_SampleTableControlBlock(void)
{
Reset();
}
QTAtom_stts_SampleTableControlBlock::~QTAtom_stts_SampleTableControlBlock(void)
{
}
void QTAtom_stts_SampleTableControlBlock::Reset(void)
{
fMTtSN_CurEntry = 0;
fMTtSN_CurMediaTime = 0;
fMTtSN_CurSample = 1;
fSNtMT_CurEntry = 0;
fSNtMT_CurMediaTime = 0;
fSNtMT_CurSample = 1;
fGetSampleMediaTime_SampleNumber = 0;
fGetSampleMediaTime_MediaTime = 0;
}
// -------------------------------------
// Constructors and destructors
//
QTAtom_stts::QTAtom_stts(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fTimeToSampleTable(NULL), fTableSize(0)
{
}
QTAtom_stts::~QTAtom_stts(void)
{
//
// Free our variables.
#if MMAP_TABLES
if( fTimeToSampleTable != NULL )
this->UnMap(fTimeToSampleTable, fTableSize);
#else
if( fTimeToSampleTable != NULL )
delete[] fTimeToSampleTable;
#endif
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_stts::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(sttsPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(sttsPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * 8) != (fTOCEntry.AtomDataLength - 8) )
return false;
//
// Read in the time-to-sample table.
#if MMAP_TABLES
fTableSize = (fNumEntries * 8);
fTimeToSampleTable = this->MemMap(sttsPos_SampleTable, fTableSize);
if( fTimeToSampleTable == NULL )
return false;
#else
fTimeToSampleTable = NEW char[fNumEntries * 8];
if( fTimeToSampleTable == NULL )
return false;
ReadBytes(sttsPos_SampleTable, fTimeToSampleTable, fNumEntries * 8);
#endif
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Accessors
//
Bool16 QTAtom_stts::MediaTimeToSampleNumber(UInt32 MediaTime, UInt32 * SampleNumber, QTAtom_stts_SampleTableControlBlock * STCB)
{
// General vars
UInt32 SampleCount, SampleDuration;
QTAtom_stts_SampleTableControlBlock *tempSTCB = NULL;
Bool16 result = false;
//
// Use the default STCB if one was not passed in to us.
if( STCB == NULL )
{
// qtss_printf("QTAtom_stts::MediaTimeToSampleNumber ( STCB == NULL ) \n");
tempSTCB = NEW QTAtom_stts_SampleTableControlBlock;
STCB = tempSTCB;
}
//
// Reconfigure the STCB if necessary.
if( MediaTime < STCB->fMTtSN_CurMediaTime )
{
// qtss_printf(" QTAtom_stts::MediaTimeToSampleNumber RESET \n");
STCB->Reset();
}
//
// Linearly search through the sample table until we find the sample
// which fits inside the given media time.
for( ; STCB->fMTtSN_CurEntry < fNumEntries; STCB->fMTtSN_CurEntry++ ) {
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (STCB->fMTtSN_CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleDuration, fTimeToSampleTable + (STCB->fMTtSN_CurEntry * 8) + 4, 4);
SampleDuration = ntohl(SampleDuration);
//
// Can we skip over this entry?
if( STCB->fMTtSN_CurMediaTime + (SampleCount * SampleDuration) < MediaTime ) {
STCB->fMTtSN_CurMediaTime += SampleCount * SampleDuration;
STCB->fMTtSN_CurSample += SampleCount;
continue;
}
//
// Locate and return the sample which is/begins right before the
// given media time.
if( SampleNumber != NULL )
{
*SampleNumber = STCB->fMTtSN_CurSample;
if (SampleDuration > 0)
*SampleNumber += (MediaTime - STCB->fMTtSN_CurMediaTime) / SampleDuration;
result = true;
break;
}
}
delete tempSTCB;
return result;
}
Bool16 QTAtom_stts::SampleNumberToMediaTime(UInt32 SampleNumber, UInt32 * MediaTime, QTAtom_stts_SampleTableControlBlock * STCB)
{
// General vars
UInt32 SampleCount, SampleDuration;
//
// Use the default STCB if one was not passed in to us.
Assert(STCB != NULL);
if ( STCB->fGetSampleMediaTime_SampleNumber == SampleNumber)
{
// qtss_printf("QTTrack::GetSampleMediaTime cache hit SampleNumber %"_S32BITARG_" \n", SampleNumber);
*MediaTime = STCB->fGetSampleMediaTime_MediaTime;
return true;
}
//
// Reconfigure the STCB if necessary.
if( SampleNumber < STCB->fSNtMT_CurSample )
{
// qtss_printf(" QTAtom_stts::SampleNumberToMediaTime reset \n");
STCB->Reset();
}
//
// Linearly search through the sample table until we find the sample
// which fits inside the given media time.
for( ; STCB->fSNtMT_CurEntry < fNumEntries; STCB->fSNtMT_CurEntry++ ) {
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (STCB->fSNtMT_CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleDuration, fTimeToSampleTable + (STCB->fSNtMT_CurEntry * 8) + 4, 4);
SampleDuration = ntohl(SampleDuration);
//
// Can we skip over this entry?
if( STCB->fSNtMT_CurSample + SampleCount < SampleNumber ) {
STCB->fSNtMT_CurMediaTime += SampleCount * SampleDuration;
STCB->fSNtMT_CurSample += SampleCount;
continue;
}
//
// Return the sample time at the beginning of this sample.
if( MediaTime != NULL )
*MediaTime = STCB->fSNtMT_CurMediaTime + ((SampleNumber - STCB->fSNtMT_CurSample) * SampleDuration);
STCB->fGetSampleMediaTime_SampleNumber = SampleNumber;
STCB->fGetSampleMediaTime_MediaTime = *MediaTime;
return true;
}
//
// No match; return false.
return false;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_stts::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_stts::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_stts::DumpAtom - ..Number of TTS entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_stts::DumpTable(void)
{
//
// Print out a header.
qtss_printf("-- Time To Sample table -----------------------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Entry Num. Sample Count Sample Duration\n");
qtss_printf(" ---------- ------------ ---------------\n");
//
// Print the table.
UInt32 SampleCount = 0;
UInt32 SampleDuration = 0;
for( UInt32 CurEntry = 0; CurEntry < fNumEntries; CurEntry++ )
{
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleDuration, fTimeToSampleTable + (CurEntry* 8) + 4, 4);
SampleDuration = ntohl(SampleDuration);
// Print out a listing.
qtss_printf(" %10"_U32BITARG_" : %10"_U32BITARG_" %10"_U32BITARG_"\n", CurEntry, SampleCount, SampleDuration);
}
}
// -------------------------------------
// Constants
//
const int cttsPos_VersionFlags = 0;
const int cttsPos_NumEntries = 4;
const int cttsPos_SampleTable = 8;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Class state cookie
//
QTAtom_ctts_SampleTableControlBlock::QTAtom_ctts_SampleTableControlBlock(void)
{
Reset();
}
QTAtom_ctts_SampleTableControlBlock::~QTAtom_ctts_SampleTableControlBlock(void)
{
}
void QTAtom_ctts_SampleTableControlBlock::Reset(void)
{
fMTtSN_CurEntry = 0;
fMTtSN_CurMediaTime = 0;
fMTtSN_CurSample = 1;
fSNtMT_CurEntry = 0;
fSNtMT_CurMediaTime = 0;
fSNtMT_CurSample = 1;
fGetSampleMediaTime_SampleNumber = 0;
fGetSampleMediaTime_MediaTime = 0;
}
// -------------------------------------
// Constructors and destructors
//
QTAtom_ctts::QTAtom_ctts(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fTimeToSampleTable(NULL)
{
}
QTAtom_ctts::~QTAtom_ctts(void)
{
//
// Free our variables.
if( fTimeToSampleTable != NULL )
delete[] fTimeToSampleTable;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_ctts::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(cttsPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
ReadInt32(cttsPos_NumEntries, &fNumEntries);
//
// Validate the size of the sample table.
if( (UInt32)(fNumEntries * 8) != (fTOCEntry.AtomDataLength - 8) )
return false;
//
// Read in the time-to-sample table.
fTimeToSampleTable = NEW char[fNumEntries * 8];
if( fTimeToSampleTable == NULL )
return false;
ReadBytes(cttsPos_SampleTable, fTimeToSampleTable, fNumEntries * 8);
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Accessors
//
Bool16 QTAtom_ctts::MediaTimeToSampleNumber(UInt32 MediaTime, UInt32 * SampleNumber, QTAtom_ctts_SampleTableControlBlock * STCB)
{
// General vars
UInt32 SampleCount, SampleDuration;
QTAtom_ctts_SampleTableControlBlock *tempSTCB = NULL;
Bool16 result = false;
//
// Use the default STCB if one was not passed in to us.
if( STCB == NULL )
{
// qtss_printf("QTAtom_ctts::MediaTimeToSampleNumber ( STCB == NULL ) \n");
tempSTCB = NEW QTAtom_ctts_SampleTableControlBlock;
STCB = tempSTCB;
}
//
// Reconfigure the STCB if necessary.
if( MediaTime < STCB->fMTtSN_CurMediaTime )
{
// qtss_printf(" QTAtom_ctts::MediaTimeToSampleNumber RESET \n");
STCB->Reset();
}
//
// Linearly search through the sample table until we find the sample
// which fits inside the given media time.
for( ; STCB->fMTtSN_CurEntry < fNumEntries; STCB->fMTtSN_CurEntry++ ) {
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (STCB->fMTtSN_CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleDuration, fTimeToSampleTable + (STCB->fMTtSN_CurEntry * 8) + 4, 4);
SampleDuration = ntohl(SampleDuration);
//
// Can we skip over this entry?
if( STCB->fMTtSN_CurMediaTime + (SampleCount * SampleDuration) < MediaTime ) {
STCB->fMTtSN_CurMediaTime += SampleCount * SampleDuration;
STCB->fMTtSN_CurSample += SampleCount;
continue;
}
//
// Locate and return the sample which is/begins right before the
// given media time.
if( SampleNumber != NULL )
{
*SampleNumber = STCB->fMTtSN_CurSample;
if (SampleDuration > 0)
*SampleNumber += (MediaTime - STCB->fMTtSN_CurMediaTime) / SampleDuration;
result = true;
break;
}
}
delete tempSTCB;
return result;
}
Bool16 QTAtom_ctts::SampleNumberToMediaTimeOffset(UInt32 SampleNumber, UInt32 * MediaTimeOffset, QTAtom_ctts_SampleTableControlBlock * STCB)
{
// General vars
UInt32 SampleCount, SampleOffset;
//
// Use the default STCB if one was not passed in to us.
Assert(STCB != NULL);
if ( STCB->fGetSampleMediaTime_SampleNumber == SampleNumber)
{
// qtss_printf("QTTrack::GetSampleMediaTime cache hit SampleNumber %"_S32BITARG_" \n", SampleNumber);
*MediaTimeOffset = STCB->fGetSampleMediaTime_MediaTime;
return true;
}
//
// Reconfigure the STCB if necessary.
if( SampleNumber < STCB->fSNtMT_CurSample )
{
// qtss_printf(" QTAtom_ctts::SampleNumberToMediaTime reset \n");
STCB->Reset();
}
//
// Linearly search through the sample table until we find the sample
// which fits inside the given media time.
for( ; STCB->fSNtMT_CurEntry < fNumEntries; STCB->fSNtMT_CurEntry++ ) {
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (STCB->fSNtMT_CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleOffset, fTimeToSampleTable + (STCB->fSNtMT_CurEntry * 8) + 4, 4);
SampleOffset = ntohl(SampleOffset);
//
// Can we skip over this entry?
if( STCB->fSNtMT_CurSample + SampleCount < SampleNumber ) {
STCB->fSNtMT_CurMediaTime += SampleCount * SampleOffset;
STCB->fSNtMT_CurSample += SampleCount;
continue;
}
//
// Return the sample time at the beginning of this sample.
if( MediaTimeOffset != NULL )
*MediaTimeOffset = SampleOffset;
STCB->fGetSampleMediaTime_SampleNumber = SampleNumber;
STCB->fGetSampleMediaTime_MediaTime = *MediaTimeOffset;
return true;
}
//
// No match; return false.
return false;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_ctts::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_ctts::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_ctts::DumpAtom - ..Number of CTTS entries: %"_S32BITARG_"\n", fNumEntries));
}
void QTAtom_ctts::DumpTable(void)
{
//
// Print out a header.
qtss_printf("-- Composition Time To Sample table ----------------------------------------------\n");
qtss_printf("\n");
qtss_printf(" Entry Num. Sample Count Sample Offset\n");
qtss_printf(" ---------- ------------ ---------------\n");
//
// Print the table.
UInt32 SampleCount = 0;
UInt32 SampleOffset = 0;
for( UInt32 CurEntry = 0; CurEntry < fNumEntries; CurEntry++ )
{
//
// Copy this sample count and duration.
memcpy(&SampleCount, fTimeToSampleTable + (CurEntry * 8), 4);
SampleCount = ntohl(SampleCount);
memcpy(&SampleOffset, fTimeToSampleTable + (CurEntry* 8) + 4, 4);
SampleOffset = ntohl(SampleOffset);
// Print out a listing.
qtss_printf(" %10"_U32BITARG_" : %10"_U32BITARG_" %10"_U32BITARG_"\n", CurEntry, SampleCount, SampleOffset);
}
}

181
QTFileLib/QTAtom_stts.h Normal file
View file

@ -0,0 +1,181 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_stts.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_stts:
// The 'stts' QTAtom class.
#ifndef QTAtom_stts_H
#define QTAtom_stts_H
//
// Includes
#include "QTFile.h"
#include "QTAtom.h"
//
// Class state cookie
class QTAtom_stts_SampleTableControlBlock {
public:
//
// Constructor and destructor.
QTAtom_stts_SampleTableControlBlock(void);
virtual ~QTAtom_stts_SampleTableControlBlock(void);
//
// Reset function
void Reset(void);
//
// MT->SN Sample table cache
UInt32 fMTtSN_CurEntry;
UInt32 fMTtSN_CurMediaTime, fMTtSN_CurSample;
//
/// SN->MT Sample table cache
UInt32 fSNtMT_CurEntry;
UInt32 fSNtMT_CurMediaTime, fSNtMT_CurSample;
UInt32 fGetSampleMediaTime_SampleNumber;
UInt32 fGetSampleMediaTime_MediaTime;
};
//
// QTAtom class
class QTAtom_stts : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_stts(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_stts(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
Bool16 MediaTimeToSampleNumber(UInt32 MediaTime, UInt32 * SampleNumber,
QTAtom_stts_SampleTableControlBlock * STCB);
Bool16 SampleNumberToMediaTime(UInt32 SampleNumber, UInt32 * MediaTime,
QTAtom_stts_SampleTableControlBlock * STCB);
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
char *fTimeToSampleTable;
UInt32 fTableSize;
};
//
// Class state cookie
class QTAtom_ctts_SampleTableControlBlock {
public:
//
// Constructor and destructor.
QTAtom_ctts_SampleTableControlBlock(void);
virtual ~QTAtom_ctts_SampleTableControlBlock(void);
//
// Reset function
void Reset(void);
//
// MT->SN Sample table cache
UInt32 fMTtSN_CurEntry;
UInt32 fMTtSN_CurMediaTime, fMTtSN_CurSample;
//
/// SN->MT Sample table cache
UInt32 fSNtMT_CurEntry;
UInt32 fSNtMT_CurMediaTime, fSNtMT_CurSample;
UInt32 fGetSampleMediaTime_SampleNumber;
UInt32 fGetSampleMediaTime_MediaTime;
};
//
// QTAtom class
class QTAtom_ctts : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_ctts(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_ctts(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
Bool16 MediaTimeToSampleNumber(UInt32 MediaTime, UInt32 * SampleNumber,
QTAtom_ctts_SampleTableControlBlock * STCB);
Bool16 SampleNumberToMediaTimeOffset(UInt32 SampleNumber, UInt32 * MediaTimeOffset,
QTAtom_ctts_SampleTableControlBlock * STCB);
//
// Debugging functions.
virtual void DumpAtom(void);
virtual void DumpTable(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt32 fNumEntries;
char *fTimeToSampleTable;
};
#endif // QTAtom_stts_H

210
QTFileLib/QTAtom_tkhd.cpp Normal file
View file

@ -0,0 +1,210 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_tkhd.cpp,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_tkhd:
// The 'tkhd' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <time.h>
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_tkhd.h"
// -------------------------------------
// Constants
//
const int tkhdPos_VersionFlags = 0;
const int tkhdPos_CreationTime = 4;
const int tkhdPos_ModificationTime = 8;
const int tkhdPos_TrackID = 12;
const int tkhdPos_Duration = 20;
const int tkhdPos_Layer = 32;
const int tkhdPos_AlternateGroup = 34;
const int tkhdPos_Volume = 36;
const int tkhdPos_a = 40;
const int tkhdPos_b = 44;
const int tkhdPos_u = 48;
const int tkhdPos_c = 52;
const int tkhdPos_d = 56;
const int tkhdPos_v = 60;
const int tkhdPos_x = 64;
const int tkhdPos_y = 68;
const int tkhdPos_w = 72;
const int tkhdPos_TrackWidth = 76;
const int tkhdPos_TrackHeight = 80;
const int tkhdPosV1_CreationTime = 4;
const int tkhdPosV1_ModificationTime = 12;
const int tkhdPosV1_TrackID = 20;
const int tkhdPosV1_Duration = 28;
const int tkhdPosV1_Layer = 44;
const int tkhdPosV1_AlternateGroup = 34 + 12;
const int tkhdPosV1_Volume = 36 + 12;
const int tkhdPosV1_a = 40 + 12;
const int tkhdPosV1_b = 44 + 12;
const int tkhdPosV1_u = 48 + 12;
const int tkhdPosV1_c = 52 + 12;
const int tkhdPosV1_d = 56 + 12;
const int tkhdPosV1_v = 60 + 12;
const int tkhdPosV1_x = 64 + 12;
const int tkhdPosV1_y = 68 + 12;
const int tkhdPosV1_w = 72 + 12;
const int tkhdPosV1_TrackWidth = 76 + 12;
const int tkhdPosV1_TrackHeight = 80 + 12;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_tkhd::QTAtom_tkhd(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug)
{
}
QTAtom_tkhd::~QTAtom_tkhd(void)
{
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_tkhd::Initialize(void)
{
// Temporary vars
UInt32 tempInt32;
//
// Parse this atom's fields.
ReadInt32(tkhdPos_VersionFlags, &tempInt32);
fVersion = (UInt8)((tempInt32 >> 24) & 0x000000ff);
fFlags = tempInt32 & 0x00ffffff;
if (0 == fVersion)
{
// Verify that this atom is the correct length.
if( fTOCEntry.AtomDataLength != 84 )
{
DEEP_DEBUG_PRINT(("QTAtom_tkhd::Initialize failed. Expected AtomDataLength == 84 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt32To64(tkhdPos_CreationTime, &fCreationTime);
ReadInt32To64(tkhdPos_ModificationTime, &fModificationTime);
ReadInt32(tkhdPos_TrackID, &fTrackID);
ReadInt32To64(tkhdPos_Duration, &fDuration);
ReadInt16(tkhdPos_AlternateGroup, &fAlternateGroup);
ReadInt16(tkhdPos_Volume, &fVolume);
ReadInt32(tkhdPos_a, &fa);
ReadInt32(tkhdPos_b, &fb);
ReadInt32(tkhdPos_u, &fu);
ReadInt32(tkhdPos_c, &fc);
ReadInt32(tkhdPos_d, &fd);
ReadInt32(tkhdPos_v, &fv);
ReadInt32(tkhdPos_x, &fx);
ReadInt32(tkhdPos_y, &fy);
ReadInt32(tkhdPos_w, &fw);
ReadInt32(tkhdPos_TrackWidth, &fTrackWidth);
ReadInt32(tkhdPos_TrackHeight, &fTrackHeight);
}
else if (1 == fVersion)
{
// Verify that this atom is the correct length.
if (fTOCEntry.AtomDataLength != 96)
{
DEEP_DEBUG_PRINT(("QTAtom_tkhd::Initialize failed. Expected AtomDataLength == 96 version: %d AtomDataLength: %"_64BITARG_"u\n",fVersion, fTOCEntry.AtomDataLength));
return false;
}
ReadInt64(tkhdPosV1_CreationTime, &fCreationTime);
ReadInt64(tkhdPosV1_ModificationTime, &fModificationTime);
ReadInt32(tkhdPosV1_TrackID, &fTrackID);
ReadInt64(tkhdPosV1_Duration, &fDuration);
ReadInt16(tkhdPosV1_AlternateGroup, &fAlternateGroup);
ReadInt16(tkhdPosV1_Volume, &fVolume);
ReadInt32(tkhdPosV1_a, &fa);
ReadInt32(tkhdPosV1_b, &fb);
ReadInt32(tkhdPosV1_u, &fu);
ReadInt32(tkhdPosV1_c, &fc);
ReadInt32(tkhdPosV1_d, &fd);
ReadInt32(tkhdPosV1_v, &fv);
ReadInt32(tkhdPosV1_x, &fx);
ReadInt32(tkhdPosV1_y, &fy);
ReadInt32(tkhdPosV1_w, &fw);
ReadInt32(tkhdPosV1_TrackWidth, &fTrackWidth);
ReadInt32(tkhdPosV1_TrackHeight, &fTrackHeight);
}
else
{
DEEP_DEBUG_PRINT(("QTAtom_tkhd::Initialize failed. Version unsupported: %d",fVersion));
return false;
}
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_tkhd::DumpAtom(void)
{
// Temporary vars
time_t unixCreationTime = (time_t)fCreationTime + (time_t)QT_TIME_TO_LOCAL_TIME;
char buffer[kTimeStrSize];
struct tm timeResult;
DEBUG_PRINT(("QTAtom_tkhd::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_tkhd::DumpAtom - ..Version: %d.\n", (int) fVersion));
DEBUG_PRINT(("QTAtom_tkhd::DumpAtom - ..Track ID: %"_S32BITARG_"\n", fTrackID));
DEBUG_PRINT(("QTAtom_tkhd::DumpAtom - ..Flags:%s%s%s%s\n", (fFlags & flagEnabled) ? " Enabled" : "", (fFlags & flagInMovie) ? " InMovie" : "", (fFlags & flagInPreview) ? " InPreview" : "", (fFlags & flagInPoster) ? " InPoster" : ""));
DEBUG_PRINT(("QTAtom_tkhd::DumpAtom - ..Creation date: %s", qtss_asctime(qtss_gmtime(&unixCreationTime, &timeResult),buffer,sizeof(buffer))));
}

98
QTFileLib/QTAtom_tkhd.h Normal file
View file

@ -0,0 +1,98 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_tkhd.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_tkhd:
// The 'tkhd' QTAtom class.
#ifndef QTAtom_tkhd_H
#define QTAtom_tkhd_H
//
// Includes
#include "OSHeaders.h"
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_tkhd : public QTAtom {
//
// Class constants
enum {
flagEnabled = 0x00000001,
flagInMovie = 0x00000002,
flagInPreview = 0x00000004,
flagInPoster = 0x00000008
};
public:
//
// Constructors and destructor.
QTAtom_tkhd(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_tkhd(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline UInt32 GetTrackID(void) { return fTrackID; }
inline UInt32 GetFlags(void) { return fFlags; }
inline UInt64 GetCreationTime(void) { return fCreationTime; }
inline UInt64 GetModificationTime(void) { return fModificationTime; }
inline UInt64 GetDuration(void) { return fDuration; }
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt8 fVersion;
UInt32 fFlags; // 24 bits in the low 3 bytes
UInt64 fCreationTime, fModificationTime;
UInt32 fTrackID;
UInt32 freserved1;
UInt64 fDuration;
UInt32 freserved2, freserved3;
UInt16 fLayer, fAlternateGroup;
UInt16 fVolume;
UInt16 freserved4;
UInt32 fa, fb, fu, fc, fd, fv, fx, fy, fw;
UInt32 fTrackWidth, fTrackHeight;
};
#endif // QTAtom_tkhd_H

114
QTFileLib/QTAtom_tref.cpp Normal file
View file

@ -0,0 +1,114 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_tref.cpp,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_tref:
// The 'tref' QTAtom class.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_tref.h"
#include "OSMemory.h"
// -------------------------------------
// Constants
//
const int trefPos_SampleTable = 0;
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTAtom_tref::QTAtom_tref(QTFile * File, QTFile::AtomTOCEntry * TOCEntry, Bool16 Debug, Bool16 DeepDebug)
: QTAtom(File, TOCEntry, Debug, DeepDebug),
fNumEntries(0), fTrackReferenceTable(NULL), fTable(NULL)
{
}
QTAtom_tref::~QTAtom_tref(void)
{
//
// Free our variables.
if( fTrackReferenceTable != NULL )
delete[] fTrackReferenceTable;
}
// -------------------------------------
// Initialization functions
//
Bool16 QTAtom_tref::Initialize(void)
{
//
// Compute the size of the sample table.
fNumEntries = fTOCEntry.AtomDataLength / 4;
//
// Read in the track reference table.
fTrackReferenceTable = NEW char[ (SInt32) ((fNumEntries * 4) + 1)];
if( fTrackReferenceTable == NULL )
return false;
if( ((PointerSizedInt)fTrackReferenceTable & (PointerSizedInt)0x3) == 0)
fTable = (UInt32 *)fTrackReferenceTable;
else
fTable = (UInt32 *)(((PointerSizedInt)fTrackReferenceTable + 4) & ~((PointerSizedInt)0x3));
ReadBytes(trefPos_SampleTable, (char *)fTable, (UInt32) (fNumEntries * 4) );
//
// This atom has been successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTAtom_tref::DumpAtom(void)
{
DEBUG_PRINT(("QTAtom_tref::DumpAtom - Dumping atom.\n"));
DEBUG_PRINT(("QTAtom_tref::DumpAtom - ..Number of track reference entries: %"_U32BITARG_"\n", (UInt32) fNumEntries));
}

85
QTFileLib/QTAtom_tref.h Normal file
View file

@ -0,0 +1,85 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTAtom_tref.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTAtom_tref:
// The 'tref' QTAtom class.
#ifndef QTAtom_tref_H
#define QTAtom_tref_H
//
// Includes
#ifndef __Win32__
#include <netinet/in.h>
#endif
#include "QTFile.h"
#include "QTAtom.h"
//
// QTAtom class
class QTAtom_tref : public QTAtom {
public:
//
// Constructors and destructor.
QTAtom_tref(QTFile * File, QTFile::AtomTOCEntry * Atom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTAtom_tref(void);
//
// Initialization functions.
virtual Bool16 Initialize(void);
//
// Accessors.
inline UInt32 GetNumReferences(void) { return (UInt32) fNumEntries; }
inline Bool16 TrackReferenceToTrackID(UInt32 TrackReference, UInt32 * TrackID = NULL) \
{ if(TrackReference < fNumEntries) { \
if( TrackID != NULL ) \
*TrackID = ntohl(fTable[TrackReference]); \
return true; \
} else \
return false; \
}
//
// Debugging functions.
virtual void DumpAtom(void);
protected:
//
// Protected member variables.
UInt64 fNumEntries;
char *fTrackReferenceTable;
UInt32 *fTable; // longword-aligned version of the above
};
#endif // QTAtom_tref_H

988
QTFileLib/QTFile.cpp Normal file
View file

@ -0,0 +1,988 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTFile:
// The central point of control for a file in the QuickTime File Format.
// -------------------------------------
// Includes
//
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#ifndef __Win32__
#include <netinet/in.h>
#endif
#include "OSMutex.h"
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_mvhd.h"
#include "QTAtom_tkhd.h"
#include "QTTrack.h"
#include "QTHintTrack.h"
#include "OSMemory.h"
#if MMAP_TABLES
#include <sys/mman.h>
#endif
#if DSS_USE_API_CALLBACKS
#include "QTSS.h" // When inside the server, we need to use the QTSS API file system callbacks
#endif
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTFile::QTFile(Bool16 Debug, Bool16 DeepDebug)
: fDebug(Debug), fDeepDebug(DeepDebug),
fNextTOCID(1),
#if DSS_USE_API_CALLBACKS
fMovieFD(NULL),
fOSFileSourceFD(NULL),
#endif
fCacheBuffersSet(false),
fTOC(NULL), fTOCOrdHead(NULL), fTOCOrdTail(NULL),
fNumTracks(0),
fFirstTrack(NULL), fLastTrack(NULL),
fMovieHeaderAtom(NULL),
fFile(-1)
{
}
QTFile::~QTFile(void)
{
//
// Free our track list (and the associated tracks)
TrackListEntry *TrackEntry = fFirstTrack,
*NextTrackEntry = TrackEntry ? TrackEntry->NextTrack : NULL;
while( TrackEntry != NULL ) {
//
// Delete this track entry and move to the next one.
if( TrackEntry->Track != NULL )
delete TrackEntry->Track;
delete TrackEntry;
TrackEntry = NextTrackEntry;
if( TrackEntry != NULL )
NextTrackEntry = TrackEntry->NextTrack;
}
//
// Free our variables.
if( fMovieHeaderAtom != NULL )
delete fMovieHeaderAtom;
//
// Free our table of contents
AtomTOCEntry *TOCEntry = fTOCOrdHead,
*NextTOCEntry = TOCEntry ? TOCEntry->NextOrdAtom : NULL;
while( TOCEntry != NULL ) {
//
// Delete this track entry and move to the next one.
delete TOCEntry;
TOCEntry = NextTOCEntry;
if( TOCEntry != NULL )
NextTOCEntry = TOCEntry->NextOrdAtom;
}
//
// Delete our mutexen.
if( fReadMutex != NULL )
delete fReadMutex;
//
// Free our path.
if( fMoviePath != NULL )
//free(fMoviePath);
delete [] fMoviePath;
#if DSS_USE_API_CALLBACKS
(void)QTSS_CloseFileObject(fMovieFD);
#endif
#if MMAP_TABLES
::close(fFile);
#endif
}
// -------------------------------------
// Public functions
//
//
// Open a movie file and generate the atom table of contents.
QTFile::ErrorCode QTFile::Open(const char * MoviePath)
{
// General vars
AtomTOCEntry *TOCEntry;
//
// Create our mutexen.
fReadMutex = NEW OSMutex();
if( fReadMutex == NULL )
return errInternalError;
//
// Attempt to open the movie file.
DEBUG_PRINT(("QTFile::Open - Opening movie.\n"));
fMoviePath = NEW char[strlen(MoviePath) + 1];
::strcpy(fMoviePath, MoviePath);
#if MMAP_TABLES
fFile = open(fMoviePath, O_RDONLY);
#endif
#if DSS_USE_API_CALLBACKS
QTSS_Error theErr = QTSS_OpenFileObject(fMoviePath, qtssOpenFileReadAhead, &fMovieFD);
if (theErr != QTSS_NoErr)
return errFileNotFound;
QTSS_AttrInfoObject attrInfoObject;
QTSS_Error error = QTSS_GetAttrInfoByName(fMovieFD, "QTSSPosixFileSysModuleOSFileSource", &attrInfoObject);
if (QTSS_NoErr == error)
{
QTSS_AttributeID fdID;
UInt32 len = sizeof(fdID);
error = QTSS_GetValue(attrInfoObject, qtssAttrID, 0, &fdID, &len);
if (theErr == QTSS_NoErr && len > 0)
{ len = sizeof(fOSFileSourceFD);
error = QTSS_GetValue(fMovieFD, fdID, 0, &fOSFileSourceFD, &len);
if (theErr != QTSS_NoErr || len == 0)
fOSFileSourceFD = NULL;
}
}
#else
fMovieFD.Set(MoviePath);
if( !fMovieFD.IsValid() )
return errFileNotFound;
#endif
//
// We have a file, generate the mod date str
fModDateBuffer.Update(this->GetModDate());
//
// Generate the table of contents for this movie.
DEBUG_PRINT(("QTFile::Open - Generating Atom TOC.\n"));
if( !GenerateAtomTOC() )
return errInvalidQuickTimeFile;
//
// Find the Movie Header atom and read it in.
DEBUG_PRINT(("QTFile::Open - Reading movie header.\n"));
if( !FindTOCEntry("moov:mvhd", &TOCEntry) )
return errInvalidQuickTimeFile;
fMovieHeaderAtom = NEW QTAtom_mvhd(this, TOCEntry, fDebug, fDeepDebug);
if( fMovieHeaderAtom == NULL )
return errInternalError;
if( !fMovieHeaderAtom->Initialize() )
return errInvalidQuickTimeFile;
if(fDeepDebug) fMovieHeaderAtom->DumpAtom();
//
// Create QTTrack objects for all of the tracks in this movie. (Although
// this does incur some extra resource usage where tracks are not used,
// they can always A) be disposed of later, or B) be ignored as their use
// of system resources is exceptionally minimal.)
// NOTE that the tracks are *not* initialized here. That is done when they
// are actually used; either directly or by a QTHintTrack.
DEBUG_PRINT(("QTFile::Open - Loading tracks.\n"));
TOCEntry = NULL;
while( FindTOCEntry("moov:trak", &TOCEntry, TOCEntry) ) {
// General vars
TrackListEntry *ListEntry;
//
// Allocate space for this list entry.
ListEntry = NEW TrackListEntry();
if( ListEntry == NULL )
return errInternalError;
//
// Make a hint track if that's what this is.
if( FindTOCEntry(":tref:hint", NULL, TOCEntry) ) {
ListEntry->Track = NEW QTHintTrack(this, TOCEntry, fDebug, fDeepDebug);
ListEntry->IsHintTrack = true;
} else {
ListEntry->Track = NEW QTTrack(this, TOCEntry, fDebug, fDeepDebug);
ListEntry->IsHintTrack = false;
}
if( ListEntry->Track == NULL ) {
delete ListEntry;
return errInternalError;
}
QTTrack* theTrack = NULL;
if (FindTrack(ListEntry->Track->GetTrackID(), &theTrack))
{
//
// A track with this track ID already exists. Ignore other tracks with
// identical track IDs.
delete ListEntry->Track;
delete ListEntry;
continue;
}
//
// Add this track object to our track list.
ListEntry->TrackID = ListEntry->Track->GetTrackID();
ListEntry->NextTrack = NULL;
if( fFirstTrack == NULL ) {
fFirstTrack = fLastTrack = ListEntry;
} else {
fLastTrack->NextTrack = ListEntry;
fLastTrack = ListEntry;
}
//
// One more track..
fNumTracks++;
}
//
// The file has been successfully opened.
DEBUG_PRINT(("QTFile::Open - Finished loading.\n"));
return errNoError;
}
char *QTFile::GetModDateStr()
{
return fModDateBuffer.GetDateBuffer();
}
void QTFile::AllocateBuffers(UInt32 inUnitSizeInK, UInt32 inBufferInc, UInt32 inBufferSizeUnits, UInt32 inMaxBitRateBuffSizeInBlocks, UInt32 inBitrate)
{
#if DSS_USE_API_CALLBACKS
if (fOSFileSourceFD != NULL)
{
if (!fCacheBuffersSet)
{
fCacheBuffersSet = true;
fOSFileSourceFD->AllocateFileCache(inUnitSizeInK, inBufferSizeUnits, inBufferInc,inMaxBitRateBuffSizeInBlocks, inBitrate);
fOSFileSourceFD->EnableFileCache(fCacheBuffersSet);
}
else
{
fOSFileSourceFD->IncMaxBuffers();
}
}
#else
if (!fCacheBuffersSet)
{
fCacheBuffersSet = true;
fMovieFD.AllocateFileCache(inUnitSizeInK, inBufferSizeUnits, inBufferInc,inMaxBitRateBuffSizeInBlocks, inBitrate);
fMovieFD.EnableFileCache(fCacheBuffersSet);
}
else
{
fMovieFD.IncMaxBuffers();
}
#endif
}
//
// Table of Contents functions.
Bool16 QTFile::FindTOCEntry(const char * AtomPath, AtomTOCEntry **TOCEntry, AtomTOCEntry *LastFoundTOCEntry)
{
// General vars
AtomTOCEntry *Atom, *CurParent;
const char *pCurAtomType = AtomPath;
UInt32 RootTOCID = 0;
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - Searching for \"%s\".\n", AtomPath));
//
// If we were given a LastFoundTOCEntry to start from, then we need to
// find that before we can do the real search.
if( LastFoundTOCEntry != NULL ) {
for( Atom = fTOCOrdHead; ; Atom = Atom->NextOrdAtom ) {
//
// If it's NULL, then something is seriously wrong.
if( Atom == NULL )
return false;
//
// Check for matches.
if( Atom->TOCID == LastFoundTOCEntry->TOCID )
break;
}
//
// Is this a root search or a rooted search?
if( *pCurAtomType == ':' ) {
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ..Rooting search at [%03"_U32BITARG_"].\n", LastFoundTOCEntry->TOCID));
RootTOCID = LastFoundTOCEntry->TOCID;
pCurAtomType++;
Atom = Atom->FirstChild;
} else {
//
// "Wind up" the list to get our new search path.
for( CurParent = Atom->Parent; CurParent != NULL; CurParent = CurParent->Parent )
pCurAtomType += (4 + 1);
//
// Move to the next atom.
Atom = Atom->NextAtom;
if( Atom != NULL ) {
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ..Starting search at [%03"_U32BITARG_"] '%c%c%c%c'. Search path is \"%s\"\n",
Atom->TOCID,
(char)((Atom->AtomType & 0xff000000) >> 24),
(char)((Atom->AtomType & 0x00ff0000) >> 16),
(char)((Atom->AtomType & 0x0000ff00) >> 8),
(char)((Atom->AtomType & 0x000000ff)),
pCurAtomType));
}
}
} else {
//
// Start at the head..
Atom = fTOC;
}
//
// Recurse through our table of contents until we find this path.
while( Atom != NULL ) { // already initialized by the above
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ..Comparing against [%03"_U32BITARG_" '%c%c%c%c'\n",
Atom->TOCID,
(char)((Atom->AtomType & 0xff000000) >> 24),
(char)((Atom->AtomType & 0x00ff0000) >> 16),
(char)((Atom->AtomType & 0x0000ff00) >> 8),
(char)((Atom->AtomType & 0x000000ff))));
//
// Is this a match?
if( memcmp(&Atom->beAtomType, pCurAtomType, 4) == 0 ) {
//
// Skip to the delimiter.
pCurAtomType += 4;
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ....Found match for '%c%c%c%c'; search path is \"%s\"\n",
(char)((Atom->AtomType & 0xff000000) >> 24),
(char)((Atom->AtomType & 0x00ff0000) >> 16),
(char)((Atom->AtomType & 0x0000ff00) >> 8),
(char)((Atom->AtomType & 0x000000ff)),
pCurAtomType));
//
// Did we finish matching?
if( *pCurAtomType == '\0' ) {
//
// Here's the atom.
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ..Matched atom path.\n"));
if( TOCEntry != NULL )
*TOCEntry = Atom;
return true;
}
//
// Not done yet; descend.
pCurAtomType++;
Atom = Atom->FirstChild;
continue;
}
//
// If there is no next atom, but we have a parent, then move up and
// continue the search. (this is necessary if A) the file is wacky,
// or B) we were given a LastFoundTOCEntry) Do not, however, leave
// the realm of the RootTOCID (if we have one).
while( (Atom->NextAtom == NULL) && (Atom->Parent != NULL) ) {
//
// Do not leave the realm of the RootTOCID (if we have one).
if( RootTOCID && (RootTOCID == Atom->Parent->TOCID) ) {
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ....Hit RootTOCID; aborting ascension.\n"));
break;
}
//
// Move up.
pCurAtomType -= (4 + 1);
Atom = Atom->Parent;
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ....Failed match; ascending to parent. Search path is \"%s\".\n", pCurAtomType));
}
//
// No match; keep going.
Atom = Atom->NextAtom;
}
//
// Couldn't find a match..
DEEP_DEBUG_PRINT(("QTFile::FindTOCEntry - ..Match failed.\n"));
return false;
}
//
// Track List functions.
Bool16 QTFile::NextTrack(QTTrack **Track, QTTrack *LastFoundTrack)
{
// General vars
TrackListEntry *ListEntry;
//
// Return the first track if requested.
if( LastFoundTrack == NULL ) {
if( fFirstTrack != NULL ) {
*Track = fFirstTrack->Track;
return true;
} else {
return false;
}
}
//
// Find LastTrack and return the one after it.
for( ListEntry = fFirstTrack; ListEntry != NULL; ListEntry = ListEntry->NextTrack ) {
//
// Check for matches.
if( ListEntry->TrackID == LastFoundTrack->GetTrackID() ) {
//
// Is there a next track?
if( ListEntry->NextTrack != NULL ) {
*Track = ListEntry->NextTrack->Track;
return true;
} else {
return false;
}
}
}
//
// This should never happen, but..
return false;
}
Bool16 QTFile::FindTrack(UInt32 TrackID, QTTrack **Track)
{
// General vars
TrackListEntry *ListEntry;
//
// Find the specified track.
for( ListEntry = fFirstTrack; ListEntry != NULL; ListEntry = ListEntry->NextTrack ) {
//
// Check for matches.
if( ListEntry->TrackID == TrackID ) {
*Track = ListEntry->Track;
return true;
}
}
//
// The search failed.
return false;
}
Bool16 QTFile::IsHintTrack(QTTrack *Track)
{
// General vars
TrackListEntry *ListEntry;
//
// Find the specified track.
for( ListEntry = fFirstTrack; ListEntry != NULL; ListEntry = ListEntry->NextTrack ) {
//
// Check for matches.
if( ListEntry->Track == Track )
return ListEntry->IsHintTrack;
}
//
// The search failed. Can this actually happen?
return false;
}
//
// Accessors
Float64 QTFile::GetTimeScale(void)
{
if (fMovieHeaderAtom == NULL)
return 0.0;
return fMovieHeaderAtom->GetTimeScale();
}
Float64 QTFile::GetDurationInSeconds(void)
{
if (fMovieHeaderAtom == NULL)
return 0.0;
return fMovieHeaderAtom->GetDurationInSeconds();
}
SInt64 QTFile::GetModDate()
{
#if DSS_USE_API_CALLBACKS
SInt64 theTime = 0;
UInt32 theLen = sizeof(SInt64);
(void)QTSS_GetValue(fMovieFD, qtssFlObjModDate, 0, (void*)&theTime, &theLen);
return theTime;
#else
time_t theTime = fMovieFD.GetModDate();
return (SInt64)theTime * 1000;
#endif
}
//
// Read functions.
Bool16 QTFile::Read(UInt64 Offset, char * const Buffer, UInt32 Length, QTFile_FileControlBlock * FCB)
{
// General vars
OSMutexLocker ReadMutex(fReadMutex);
Bool16 rv = false;
UInt32 gotlen = 0;
if( FCB )
rv = FCB->Read(&fMovieFD,Offset,Buffer,Length);
else
{
#if DSS_USE_API_CALLBACKS
QTSS_Error theErr = QTSS_Seek(fMovieFD, Offset);
if (theErr == QTSS_NoErr)
theErr = QTSS_Read(fMovieFD, Buffer, Length, &gotlen);
if ((theErr == QTSS_NoErr) && (gotlen == Length))
rv = true;
#else
if ((fMovieFD.Read(Offset,Buffer,Length,&gotlen) == OS_NoErr) &&
(gotlen == Length))
rv = true;
#endif
}
return rv;
}
// -------------------------------------
// Protected functions
//
Bool16 QTFile::GenerateAtomTOC(void)
{
// General vars
OSType AtomType;
UInt32 atomLength;
UInt64 BigAtomLength;
UInt64 CurPos;
UInt32 CurAtomHeaderSize;
AtomTOCEntry *NewTOCEntry = NULL,
*CurParent = NULL, *LastTOCEntry = NULL;
Bool16 hasMoovAtom = false;
Bool16 hasBigAtom = false;
//
// Scan through all of the atoms in this movie, generating a TOC entry
// for each one.
CurPos = 0;
while( Read(CurPos, (char *)&atomLength, 4) ) {
//
// Swap the AtomLength for little-endian machines.
CurPos += 4;
atomLength = ntohl(atomLength);
BigAtomLength = (UInt64) atomLength;
hasBigAtom = false;
//
// Is AtomLength zero? If so, and we're in a 'udta' atom, then all
// is well (this is the end of a 'udta' atom). Leave this level of
// siblings as the 'udta' atom is obviously over.
if( (BigAtomLength == 0) && CurParent && (CurParent->AtomType == FOUR_CHARS_TO_INT('u', 'd', 't', 'a')) ) {
//
// Do no harm..
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Found End-of-udta marker.\n"));
LastTOCEntry = CurParent;
CurParent = CurParent->Parent;
//
// Keep moving up.
goto lbl_SkipAtom;
//
// Is the AtomLength zero? If so, this is a "QT atom" which needs
// some additional work before it can be processed.
}
else if( BigAtomLength == 0 )
{
//
// This is a QT atom; skip the (rest of the) reserved field and
// the lock count field.
CurPos += 22;
//
// Read the size and the type of this atom.
if( !Read(CurPos, (char *)&atomLength, 4) )
return false;
CurPos += 4;
BigAtomLength = (UInt64) ntohl(atomLength);
if( !Read(CurPos, (char *)&AtomType, 4) )
return false;
CurPos += 4;
AtomType = ntohl(AtomType);
//
// Skip over the rest of the fields.
CurPos += 12;
//
// Set the header size to that of a QT atom.
CurAtomHeaderSize = 10 + 16 + 4 + 4 + 4 + 2 + 2 + 4;
//
// This is a normal atom; get the atom type.
}
else // This is a normal atom; get the atom type.
{
if( !Read(CurPos, (char *)&AtomType, 4) )
break;
CurPos += 4;
CurAtomHeaderSize = 4 + 4; // AtomLength + AtomType
AtomType = ntohl(AtomType);
if ( atomLength == 1 ) //large size atom
{
if( !Read(CurPos, (char *)&BigAtomLength, 8) )
break;
BigAtomLength = QTAtom::NTOH64(BigAtomLength);
CurPos += 8;
CurAtomHeaderSize += 8; // AtomLength + AtomType + big atom length
hasBigAtom = true;
}
if (AtomType == FOUR_CHARS_TO_INT('u', 'u', 'i', 'd'))
{
static const int sExtendedTypeSize = 16;
UInt8 usertype[sExtendedTypeSize + 1]; //sExtendedTypeSize for the type + 1 for 0 terminator.
usertype[sExtendedTypeSize] = 0;
if( !Read(CurPos, (char *)usertype, 16) ) // read and just throw it away we don't need to store
return false;
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Found 'uuid' extended type name= %s.\n",usertype));
CurPos += sExtendedTypeSize;
CurAtomHeaderSize += sExtendedTypeSize;
}
}
if (0 == BigAtomLength)
{
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Bail atom is bad. type= '%c%c%c%c'; pos=%"_64BITARG_"u; length=%"_64BITARG_"u; header=%"_U32BITARG_".\n",
(char)((AtomType & 0xff000000) >> 24),
(char)((AtomType & 0x00ff0000) >> 16),
(char)((AtomType & 0x0000ff00) >> 8),
(char)((AtomType & 0x000000ff)),
CurPos - CurAtomHeaderSize, BigAtomLength, CurAtomHeaderSize));
return false;
}
if (hasBigAtom)
{ DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Found 64 bit atom '%c%c%c%c'; pos=%"_64BITARG_"u; length=%"_64BITARG_"u; header=%"_U32BITARG_".\n",
(char)((AtomType & 0xff000000) >> 24),
(char)((AtomType & 0x00ff0000) >> 16),
(char)((AtomType & 0x0000ff00) >> 8),
(char)((AtomType & 0x000000ff)),
CurPos - CurAtomHeaderSize, BigAtomLength, CurAtomHeaderSize));
}
else
{ DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Found 32 bit atom '%c%c%c%c'; pos=%"_64BITARG_"u; length=%"_64BITARG_"u; header=%"_U32BITARG_".\n",
(char)((AtomType & 0xff000000) >> 24),
(char)((AtomType & 0x00ff0000) >> 16),
(char)((AtomType & 0x0000ff00) >> 8),
(char)((AtomType & 0x000000ff)),
CurPos - CurAtomHeaderSize, BigAtomLength, CurAtomHeaderSize));
}
if ((AtomType == FOUR_CHARS_TO_INT('m', 'o', 'o', 'v')) && (hasMoovAtom))
{
//
// Skip over any additional 'moov' atoms once we find one.
CurPos += BigAtomLength - CurAtomHeaderSize;
continue;
}
else if (AtomType == FOUR_CHARS_TO_INT('m', 'o', 'o', 'v'))
{
hasMoovAtom = true;
}
else if (!hasMoovAtom)
{
CurPos += BigAtomLength - CurAtomHeaderSize;
continue;
}
//
// Create a TOC entry for this atom.
NewTOCEntry = NEW AtomTOCEntry();
if( NewTOCEntry == NULL )
return false;
NewTOCEntry->TOCID = fNextTOCID++;
NewTOCEntry->AtomType = AtomType;
NewTOCEntry->beAtomType = htonl(AtomType);
NewTOCEntry->AtomDataPos = CurPos;
NewTOCEntry->AtomDataLength = BigAtomLength - CurAtomHeaderSize;
NewTOCEntry->AtomHeaderSize = CurAtomHeaderSize;
NewTOCEntry->NextOrdAtom = NULL;
NewTOCEntry->PrevAtom = LastTOCEntry;
NewTOCEntry->NextAtom = NULL;
if( NewTOCEntry->PrevAtom )
NewTOCEntry->PrevAtom->NextAtom = NewTOCEntry;
NewTOCEntry->Parent = CurParent;
NewTOCEntry->FirstChild = NULL;
LastTOCEntry = NewTOCEntry;
//
// Make this entry the head of the TOC list if necessary.
if( fTOC == NULL ) {
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Placing this atom at the head of the TOC.\n"));
fTOC = NewTOCEntry;
fTOCOrdHead = fTOCOrdTail = NewTOCEntry;
} else {
fTOCOrdTail->NextOrdAtom = NewTOCEntry;
fTOCOrdTail = NewTOCEntry;
}
//
// Make this the first child if we have one.
if( CurParent && (CurParent->FirstChild == NULL) ) {
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - ..This atom is the first child of our new parent.\n"));
CurParent->FirstChild = NewTOCEntry;
}
//
// Figure out if we have to descend into this entry and do so.
switch( NewTOCEntry->AtomType )
{
case FOUR_CHARS_TO_INT('m', 'o', 'o', 'v'): //moov
case FOUR_CHARS_TO_INT('c', 'l', 'i', 'p'): //clip
case FOUR_CHARS_TO_INT('t', 'r', 'a', 'k'): //trak
case FOUR_CHARS_TO_INT('m', 'a', 't', 't'): //matt
case FOUR_CHARS_TO_INT('e', 'd', 't', 's'): //edts
case FOUR_CHARS_TO_INT('t', 'r', 'e', 'f'): //tref
case FOUR_CHARS_TO_INT('m', 'd', 'i', 'a'): //mdia
case FOUR_CHARS_TO_INT('m', 'i', 'n', 'f'): //minf
case FOUR_CHARS_TO_INT('d', 'i', 'n', 'f'): //dinf
case FOUR_CHARS_TO_INT('s', 't', 'b', 'l'): //stbl
case FOUR_CHARS_TO_INT('u', 'd', 't', 'a'): /* can appear anywhere */ //udta
case FOUR_CHARS_TO_INT('h', 'n', 't', 'i'): //hnti
case FOUR_CHARS_TO_INT('h', 'i', 'n', 'f'): //hinf
{
//
// All of the above atoms need to be descended into. Set up
// our variables to descend into this atom.
if (NewTOCEntry->AtomDataLength > 0) // maybe it should be greater than some number such as header size?
{
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - ..Creating a new parent.\n"));
CurParent = NewTOCEntry;
LastTOCEntry = NULL;
continue; // skip the level checks below
}
else
{
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - Empty atom.\n"));
}
}
break;
}
//
// Skip over this atom's data.
CurPos += NewTOCEntry->AtomDataLength;
//
// Would continuing to the next atom cause us to leave this level?
// If so, move up a level and move on. Keep doing this until we find
// a level we can continue on.
lbl_SkipAtom:
while( CurParent && ((LastTOCEntry->AtomDataPos - LastTOCEntry->AtomHeaderSize) + (LastTOCEntry->AtomDataLength + LastTOCEntry->AtomHeaderSize)) >= ((CurParent->AtomDataPos - CurParent->AtomHeaderSize) + (CurParent->AtomDataLength + CurParent->AtomHeaderSize)) ) {
DEEP_DEBUG_PRINT(("QTFile::GenerateAtomTOC - End of this parent's ('%c%c%c%c') children.\n",
(char)((CurParent->AtomType & 0xff000000) >> 24),
(char)((CurParent->AtomType & 0x00ff0000) >> 16),
(char)((CurParent->AtomType & 0x0000ff00) >> 8),
(char)((CurParent->AtomType & 0x000000ff))));
LastTOCEntry = CurParent;
CurParent = CurParent->Parent;
}
}
if (!this->ValidTOC()) // make sure we were able to read all the atoms.
return false;
//
// The TOC has been successfully read in.
return true;
}
char *QTFile::MapFileToMem(UInt64 offset, UInt32 length)
{
#if MMAP_TABLES
char* mappedMem = (char *) mmap( NULL,
(size_t) length,
PROT_READ,
0,
fFile,
(off_t) offset);
if(mappedMem == MAP_FAILED )
{ //printf("MAP_FAILED\n");
mappedMem = NULL;
}
return mappedMem;
#else
return NULL;
#endif
}
int QTFile::UnmapMem(char* memPtr, UInt32 length)
{
#if MMAP_TABLES
return munmap( (caddr_t) memPtr, (size_t) length);
#else
return 0;
#endif
}
// -------------------------------------
// Debugging functions.
void QTFile::DumpAtomTOC(void)
{
// General vars
AtomTOCEntry *Atom;
char Indent[128] = { '\0' };
// Display all of the atoms.
DEBUG_PRINT(("QTFile::DumpAtomTOC - Dumping TOC.\n"));
for( Atom = fTOC; Atom != NULL; )
{
// Print out this atom.
DEBUG_PRINT(("%s[%03"_U32BITARG_"] AtomType=%c%c%c%c; AtomDataPos=%"_64BITARG_"u; AtomDataLength=%"_64BITARG_"u\n",
Indent,
Atom->TOCID,
(char)((Atom->AtomType & 0xff000000) >> 24),
(char)((Atom->AtomType & 0x00ff0000) >> 16),
(char)((Atom->AtomType & 0x0000ff00) >> 8),
(char)((Atom->AtomType & 0x000000ff)),
Atom->AtomDataPos, Atom->AtomDataLength));
// Descend into this atom's children if it has any.
if( Atom->FirstChild != NULL ) {
Atom = Atom->FirstChild;
strcat(Indent, " ");
continue;
}
// Are we at the end of a sibling list? If so, move up a level. Keep
// moving up until we find a non-NULL atom.
while( Atom && (Atom->NextAtom == NULL) )
{
Atom = Atom->Parent;
Indent[strlen(Indent) - 2] = '\0';
}
// Next atom..
if( Atom != NULL ) // could be NULL if we just moved up to a NULL parent
Atom = Atom->NextAtom;
}
}

215
QTFileLib/QTFile.h Normal file
View file

@ -0,0 +1,215 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTFile.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTFile:
// The central point of control for a file in the QuickTime File Format.
#ifndef QTFile_H
#define QTFile_H
//
// Includes
#include "OSHeaders.h"
#include "OSFileSource.h"
#include "QTFile_FileControlBlock.h"
#include "DateTranslator.h"
//
// External classes
class OSMutex;
class QTAtom_mvhd;
class QTTrack;
//
// QTFile class
class QTFile {
public:
//
// Class constants
//
// Class error codes
enum ErrorCode {
errNoError = 0,
errFileNotFound = 1,
errInvalidQuickTimeFile = 2,
errInternalError = 100
};
//
// Class typedefs.
struct AtomTOCEntry {
// TOC id (used to compare TOCs)
UInt32 TOCID;
// Atom information
OSType AtomType, beAtomType; // be = Big Endian
UInt64 AtomDataPos;
UInt64 AtomDataLength;
UInt32 AtomHeaderSize;
// TOC pointers
AtomTOCEntry *NextOrdAtom;
AtomTOCEntry *PrevAtom, *NextAtom;
AtomTOCEntry *Parent, *FirstChild;
};
struct TrackListEntry {
// Track information
UInt32 TrackID;
QTTrack *Track;
Bool16 IsHintTrack;
// List pointers
TrackListEntry *NextTrack;
};
public:
//
// Constructors and destructor.
QTFile(Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTFile(void);
//
// Open a movie file and generate the atom table of contents.
ErrorCode Open(const char * MoviePath);
OSMutex* GetMutex() { return fReadMutex; }
//
// Table of Contents functions.
Bool16 FindTOCEntry(const char * AtomPath,
AtomTOCEntry **TOCEntry,
AtomTOCEntry *LastFoundTOCEntry = NULL);
//
// Track List functions
inline UInt32 GetNumTracks(void) { return fNumTracks; }
Bool16 NextTrack(QTTrack **Track, QTTrack *LastFoundTrack = NULL);
Bool16 FindTrack(UInt32 TrackID, QTTrack **Track);
Bool16 IsHintTrack(QTTrack *Track);
//
// Accessors
inline char * GetMoviePath(void) { return fMoviePath; }
Float64 GetTimeScale(void);
Float64 GetDurationInSeconds(void);
SInt64 GetModDate();
// Returns the mod date as a RFC 1123 formatted string
char* GetModDateStr();
//
// Read functions.
Bool16 Read(UInt64 Offset, char * const Buffer, UInt32 Length, QTFile_FileControlBlock * FCB = NULL);
void AllocateBuffers(UInt32 inUnitSizeInK, UInt32 inBufferInc, UInt32 inBufferSize, UInt32 inMaxBitRateBuffSizeInBlocks, UInt32 inBitrate);
#if DSS_USE_API_CALLBACKS
void IncBufferUserCount() {if (fOSFileSourceFD != NULL) fOSFileSourceFD->IncMaxBuffers();}
void DecBufferUserCount() {if (fOSFileSourceFD != NULL) fOSFileSourceFD->DecMaxBuffers();}
#else
void IncBufferUserCount() {fMovieFD.IncMaxBuffers();}
void DecBufferUserCount() {fMovieFD.DecMaxBuffers();}
#endif
inline Bool16 ValidTOC();
char* MapFileToMem(UInt64 offset, UInt32 length);
int UnmapMem(char *memPtr, UInt32 length);
//
// Debugging functions.
void DumpAtomTOC(void);
protected:
//
// Protected member functions.
Bool16 GenerateAtomTOC(void);
//
// Protected member variables.
Bool16 fDebug, fDeepDebug;
UInt32 fNextTOCID;
#if DSS_USE_API_CALLBACKS
QTSS_Object fMovieFD;
OSFileSource *fOSFileSourceFD;
#else
OSFileSource fMovieFD;
#endif
Bool16 fCacheBuffersSet;
DateBuffer fModDateBuffer;
char *fMoviePath;
AtomTOCEntry *fTOC, *fTOCOrdHead, *fTOCOrdTail;
UInt32 fNumTracks;
TrackListEntry *fFirstTrack, *fLastTrack;
QTAtom_mvhd *fMovieHeaderAtom;
OSMutex *fReadMutex;
int fFile;
};
Bool16 QTFile::ValidTOC()
{
UInt64 theLength = 0;
UInt64 thePos = 0;
#if DSS_USE_API_CALLBACKS
UInt32 theDataLen = sizeof(UInt64);
(void)QTSS_GetValue(fMovieFD, qtssFlObjLength, 0, (void*)&theLength, &theDataLen);
(void)QTSS_GetValue(fMovieFD, qtssFlObjPosition, 0, (void*)&thePos, &theDataLen);
// qtss_printf("GenerateAtomTOC failed CurPos=%"_64BITARG_"u < Length=%"_64BITARG_"u\n", CurPos, theLength);
#else
theLength = fMovieFD.GetLength();
thePos = fMovieFD.GetCurOffset();
#endif
if (thePos < theLength) // failure pos not at end of file
{
// qtss_printf("GenerateAtomTOC failed CurPos=%"_64BITARG_"u < Length=%"_64BITARG_"u\n", CurPos, theLength);
return false;
}
return true;
}
#endif // QTFile_H

View file

@ -0,0 +1,322 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTFile:
// The central point of control for a file in the QuickTime File Format.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#include "OSMutex.h"
#include "OSMemory.h"
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_mvhd.h"
#include "QTAtom_tkhd.h"
#include "QTTrack.h"
#include "QTHintTrack.h"
#include <fcntl.h>
// -------------------------------------
// Macros
//
//#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
//#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Class state cookie
//
QTFile_FileControlBlock::QTFile_FileControlBlock(void)
: fDataFD(NULL), fDataBufferPool(NULL),
fDataBufferSize(0), fDataBufferPosStart(0), fDataBufferPosEnd(0),
fCurrentDataBuffer(NULL), fPreviousDataBuffer(NULL),
fCurrentDataBufferLength(0), fPreviousDataBufferLength(0),
fNumBlocksPerBuff(1),fNumBuffs(1),
fCacheEnabled(false)
{
}
QTFile_FileControlBlock::~QTFile_FileControlBlock(void)
{
if( fDataBufferPool != NULL )
delete[] fDataBufferPool;
#if DSS_USE_API_CALLBACKS
(void)QTSS_CloseFileObject(fDataFD);
#endif
}
void QTFile_FileControlBlock::Set( char * DataPath)
{
#if DSS_USE_API_CALLBACKS
(void)QTSS_OpenFileObject(DataPath, qtssOpenFileReadAhead, &fDataFD);
#else
fDataFD.Set(DataPath);
#endif
}
Bool16 QTFile_FileControlBlock::ReadInternal(FILE_SOURCE *dataFD, UInt64 inPosition, void* inBuffer, UInt32 inLength, UInt32 *inReadLenPtr)
{
UInt32 readLen = 0;
if (NULL != inReadLenPtr)
*inReadLenPtr = 0;
#if DSS_USE_API_CALLBACKS
QTSS_Error theErr = QTSS_Seek(*dataFD, inPosition);
if (theErr == QTSS_NoErr)
theErr = QTSS_Read(*dataFD, inBuffer, inLength, &readLen);
if (theErr != QTSS_NoErr)
return false;
#else
if( dataFD->Read(inPosition, inBuffer, inLength, &readLen) != OS_NoErr )
return false;
#endif
if (NULL != inReadLenPtr)
*inReadLenPtr = readLen;
if(inReadLenPtr == NULL && readLen != inLength) //external reads expect false if it fails to read all the requested data.
return false;
return true;
}
Bool16 QTFile_FileControlBlock::Read(FILE_SOURCE *dflt, UInt64 inPosition, void* inBuffer, UInt32 inLength)
{
// Temporary vars
UInt32 rcSize;
// General vars
FILE_SOURCE *dataFD;
// success or failure
Bool16 result = false;
// Get the file descriptor. If the FCB is NULL, or the descriptor in
// the FCB is -1, then we need to use the class' descriptor.
if (this->IsValid())
dataFD = &fDataFD;
else
dataFD = dflt;
if (
( !fCacheEnabled) || // file control block caching disabled
( inLength > fDataBufferSize ) || // too big for this cache
( inPosition < fDataBufferPosStart) // backing up
)
{
//if ( !fCacheEnabled) qtss_printf("QTFile_FileControlBlock::Read cache not enabled\n");
//if ( inLength > fDataBufferSize) qtss_printf("QTFile_FileControlBlock::Read read too big for cache len=%"_U32BITARG_" max%"_U32BITARG_"\n",inLength,fDataBufferSize);
//if ( inPosition < fDataBufferPosStart) qtss_printf("QTFile_FileControlBlock::Read backing up skipping cache missed by =%"_U32BITARG_" bytes\n", fDataBufferPosStart - inPosition);
result = this->ReadInternal(dataFD, inPosition, inBuffer, inLength);
goto done;
}
// Is the requested block of data in our data buffer? If not, read in the
// section of the file where this piece of data is.
if( (inPosition < fDataBufferPosStart) || ((inPosition + inLength) > fDataBufferPosEnd) )
{
// If this is a forward-moving, contiguous read, then we can keep the
// current buffer around.
if ( (fCurrentDataBufferLength != 0)
&& ((fDataBufferPosEnd - fCurrentDataBufferLength) <= inPosition)
&& ((fDataBufferPosEnd + fDataBufferSize) >= (inPosition + inLength))
)
{
// Temporary vars
char *TempDataBuffer;
//qtss_printf("QTFile_FileControlBlock::Read forward read inPosition=%"_64BITARG_"u fPreviousDataBuffer=%"_64BITARG_"u start=%"_64BITARG_"u\n",inPosition,fDataBufferPosStart,fDataBufferPosEnd);
// First, demote the current buffer.
fDataBufferPosStart += fPreviousDataBufferLength;
TempDataBuffer = fPreviousDataBuffer;
fPreviousDataBuffer = fCurrentDataBuffer;
fPreviousDataBufferLength = fCurrentDataBufferLength;
fCurrentDataBuffer = TempDataBuffer;
fCurrentDataBufferLength = 0;
//
// Then, fill the now-current buffer with data.
if (!this->ReadInternal(dataFD, fDataBufferPosEnd, fCurrentDataBuffer, fDataBufferSize, &rcSize) )
goto done;
//Assert(rcSize == fDataBufferSize);
fCurrentDataBufferLength = (UInt32)rcSize;
fDataBufferPosEnd += fCurrentDataBufferLength;
}
else
{
//qtss_printf("QTFile_FileControlBlock::Read not a contiguous forward read inPosition=%"_64BITARG_"u fPreviousDataBuffer=%"_64BITARG_"u missed=%"_64BITARG_"d\n ",inPosition,fDataBufferPosStart,(fDataBufferPosStart > inPosition) ? fDataBufferPosStart-inPosition: inPosition - fDataBufferPosStart);
// We need to play with our current and previous data buffers in
// order to skip around while reading.
fCurrentDataBuffer = fDataBufferPool;
fCurrentDataBufferLength = 0;
fPreviousDataBuffer = (char *)fDataBufferPool + fDataBufferSize;
fPreviousDataBufferLength = 0;
fDataBufferPosStart = inPosition;
if (! this->ReadInternal(dataFD, fDataBufferPosStart, fCurrentDataBuffer, fDataBufferSize, &rcSize) )
goto done;
//Assert(rcSize == fDataBufferSize);
fCurrentDataBufferLength = (UInt32)rcSize;
fDataBufferPosEnd = fDataBufferPosStart + fCurrentDataBufferLength;
}
}
//
// Copy the data out of our buffer(s).
{
// General vars
UInt64 ReadLength = inLength;
UInt64 ReadOffset = inPosition - fDataBufferPosStart;
//
// Figure out if doing a continuous copy would cause us to cross a
// buffer boundary.
if ( (inPosition < (fDataBufferPosStart + fPreviousDataBufferLength))
&& ((ReadOffset + ReadLength) > fPreviousDataBufferLength )
)
{
// Temporary vars
char *pBuffer = (char *)inBuffer;
//
// Read the first part of the block.
ReadLength = fDataBufferSize - ReadOffset;
if (ReadLength <= (fPreviousDataBufferLength - ReadOffset) )
::memcpy(pBuffer, fPreviousDataBuffer + ReadOffset, (UInt32) ReadLength);
else
goto done;
pBuffer += ReadLength;
//
// Read the last part of the block.
ReadLength = inLength - ReadLength;
if (ReadLength <= fCurrentDataBufferLength )
{ ::memcpy(pBuffer, fCurrentDataBuffer, (UInt32) ReadLength);
result = true;
}
//
// Or maybe this is a continuous copy out of the old buffer.
}
else if ( inPosition < (fDataBufferPosEnd - fCurrentDataBufferLength) )
{
if (ReadLength <= (fPreviousDataBufferLength - ReadOffset) )
{ ::memcpy(inBuffer, fPreviousDataBuffer + ReadOffset, (UInt32)ReadLength);
result = true;
}
}
else
{
ReadOffset -= fPreviousDataBufferLength;
if (ReadLength <= (fCurrentDataBufferLength - ReadOffset) )
{ ::memcpy(inBuffer, fCurrentDataBuffer + ReadOffset, (UInt32) ReadLength);
result = true;
}
}
}
done:
// We're done.
return result;
}
void QTFile_FileControlBlock::AdjustDataBufferBitRate(UInt32 inUnitSizeInK, UInt32 inFileBitRate, UInt32 inNumBuffSizeUnits, UInt32 inMaxBitRateBuffSizeInBlocks)
{
if (!fCacheEnabled)
return;
// General vars
UInt32 newDataBufferSizeInUnits = inNumBuffSizeUnits;
UInt32 newDataBufferSize = 0;
UInt32 newUnitSizeBytes = 0;
if (inUnitSizeInK < 1)
inUnitSizeInK = 32;
newUnitSizeBytes = inUnitSizeInK * 1024;
if (inMaxBitRateBuffSizeInBlocks < 1)
inMaxBitRateBuffSizeInBlocks = kMaxDefaultBlocks;
if (inFileBitRate == 0) // set the maximum
inFileBitRate = inMaxBitRateBuffSizeInBlocks * newUnitSizeBytes;
if (inNumBuffSizeUnits < 1) // calculate if not set to a given number
{
newDataBufferSizeInUnits = (inFileBitRate + newUnitSizeBytes) / newUnitSizeBytes; // 32k bytes of buffer for every 32k bits in rate
if( newDataBufferSizeInUnits > inMaxBitRateBuffSizeInBlocks ) // Limit the buffer size value to a reasonable maximum. should be pref
newDataBufferSizeInUnits = inMaxBitRateBuffSizeInBlocks;
}
newDataBufferSize = newDataBufferSizeInUnits * kBlockByteSize;
//qtss_printf("QTFile_FileControlBlock::AdjustDataBuffer private buffers NewDataBufferSizeInUnits =%"_U32BITARG_" NewDataBufferSize = %"_U32BITARG_"\n",newDataBufferSizeInUnits,newDataBufferSize);
// Free the old buffer.
delete[] fDataBufferPool;
fDataBufferSize = newDataBufferSize;
fDataBufferPool = NEW char[2 * newDataBufferSize]; // 2 contiguous buffers
fCurrentDataBuffer = fDataBufferPool;
fPreviousDataBuffer = (char *)fDataBufferPool + newDataBufferSize;
fDataBufferPosStart = 0;
fDataBufferPosEnd = 0;
fCurrentDataBufferLength = 0;
fPreviousDataBuffer = 0;
}

View file

@ -0,0 +1,113 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTFile_FileControlBlock:
// All the per-client stuff for QTFile.
#ifndef _QTFILE_FILECONTROLBLOCK_H_
#define _QTFILE_FILECONTROLBLOCK_H_
//
// Includes
#include "OSHeaders.h"
#include "OSFileSource.h"
#if DSS_USE_API_CALLBACKS
#include "QTSS.h"
#endif
#if DSS_USE_API_CALLBACKS
#define FILE_SOURCE QTSS_Object
#else
#define FILE_SOURCE OSFileSource
#endif
//
// Class state cookie
class QTFile_FileControlBlock {
public:
//
// Constructor and destructor.
QTFile_FileControlBlock(void);
virtual ~QTFile_FileControlBlock(void);
//Sets this object to reference this file
void Set(char *inPath);
//Advise: this advises the OS that we are going to be reading soon from the
//following position in the file
// void Advise(OSFileSource *dflt, UInt64 advisePos, UInt32 adviseAmt);
Bool16 Read(FILE_SOURCE *dflt, UInt64 inPosition, void* inBuffer, UInt32 inLength);
Bool16 ReadInternal(FILE_SOURCE *dataFD, UInt64 inPosition, void* inBuffer, UInt32 inLength, UInt32 *inReadLenPtr = NULL);
//
// Buffer management functions
void AdjustDataBufferBitRate(UInt32 inUnitSizeInK = 32, UInt32 inFileBitRate = 32768, UInt32 inNumBuffSizeUnits = 0, UInt32 inMaxBitRateBuffSizeInBlocks = 8);
void AdjustDataBuffers(UInt32 inBlockSizeKBits = 32, UInt32 inBlockCountPerBuff = 1);
void EnableCacheBuffers(Bool16 enabled) {fCacheEnabled = enabled;}
// QTSS_ErrorCode Close();
Bool16 IsValid()
{
#if DSS_USE_API_CALLBACKS
return fDataFD != NULL;
#else
return fDataFD.IsValid();
#endif
}
private:
//
// File descriptor for this control block
FILE_SOURCE fDataFD;
enum
{
kMaxDefaultBlocks = 8,
kDataBufferUnitSizeExp = 15, // 32Kbytes
kBlockByteSize = ( 1 << kDataBufferUnitSizeExp)
};
//
// Data buffer cache
char *fDataBufferPool;
UInt32 fDataBufferSize;
UInt64 fDataBufferPosStart, fDataBufferPosEnd;
char *fCurrentDataBuffer, *fPreviousDataBuffer;
UInt32 fCurrentDataBufferLength, fPreviousDataBufferLength;
UInt32 fNumBlocksPerBuff;
UInt32 fNumBuffs;
Bool16 fCacheEnabled;
};
#endif //_QTFILE_FILECONTROLBLOCK_H_

1516
QTFileLib/QTHintTrack.cpp Normal file

File diff suppressed because it is too large Load diff

243
QTFileLib/QTHintTrack.h Normal file
View file

@ -0,0 +1,243 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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; }
inline void SetAllowInvalidHintRefs(Bool16 inAllowInvalidHintRefs) { fAllowInvalidHintRefs = inAllowInvalidHintRefs; }
//
// 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
};
enum
{
kMaxHintTrackRefs = 1024
};
//
// Protected member variables.
QTAtom_hinf *fHintInfoAtom;
QTAtom_tref *fHintTrackReferenceAtom;
QTTrack **fTrackRefs;
UInt32 fMaxPacketSize;
UInt32 fRTPTimescale, fFirstRTPTimestamp;
UInt32 fTimestampRandomOffset;
UInt16 fSequenceNumberRandomOffset;
Bool16 fHintTrackInitialized;
SInt16 fHintType;
Float64 fFirstTransmitTime;
Bool16 fAllowInvalidHintRefs;
//
// 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

1544
QTFileLib/QTRTPFile.cpp Normal file

File diff suppressed because it is too large Load diff

283
QTFileLib/QTRTPFile.h Normal file
View file

@ -0,0 +1,283 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
// $Id: QTRTPFile.h,v 1.1 2006/01/05 13:20:36 murata Exp $
//
// QTRTPFile:
// An interface to QTFile for TimeShare.
#ifndef QTRTPFile_H
#define QTRTPFile_H
//
// Includes
#include "OSHeaders.h"
#include "MyAssert.h"
#include "RTPMetaInfoPacket.h"
#include "QTHintTrack.h"
#ifndef __Win32__
#include <sys/stat.h>
#endif
//
// Constants
#define QTRTPFILE_MAX_PACKET_LENGTH 2048
//
// QTRTPFile class
class OSMutex;
class QTFile;
class QTFile_FileControlBlock;
class QTHintTrack;
class QTHintTrack_HintTrackControlBlock;
class QTRTPFile {
public:
//
// Class error codes
enum ErrorCode {
errNoError = 0,
errFileNotFound = 1,
errInvalidQuickTimeFile = 2,
errNoHintTracks = 3,
errTrackIDNotFound = 4,
errCallAgain = 5,
errInternalError = 100
};
//
// Class typedefs.
struct RTPFileCacheEntry {
//
// Init mutex (do not use this entry until you have acquired and
// released this.
OSMutex *InitMutex;
//
// File information
char* fFilename;
QTFile *File;
//
// Reference count for this cache entry
int ReferenceCount;
//
// List pointers
RTPFileCacheEntry *PrevEntry, *NextEntry;
};
struct RTPTrackListEntry {
//
// Track information
UInt32 TrackID;
QTHintTrack *HintTrack;
QTHintTrack_HintTrackControlBlock *HTCB;
Bool16 IsTrackActive, IsPacketAvailable;
UInt32 QualityLevel;
//
// Server information
void *Cookie1;
UInt32 Cookie2;
UInt32 SSRC;
UInt16 FileSequenceNumberRandomOffset, BaseSequenceNumberRandomOffset,
LastSequenceNumber;
SInt32 SequenceNumberAdditive;
UInt32 FileTimestampRandomOffset, BaseTimestampRandomOffset;
//
// Sample/Packet information
UInt32 CurSampleNumber;
UInt32 ConsecutivePFramesSent;
UInt32 TargetPercentage;
UInt32 SampleToSeekTo;
UInt32 LastSyncSampleNumber;
UInt32 NextSyncSampleNumber;
UInt16 NumPacketsInThisSample, CurPacketNumber;
Float64 CurPacketTime;
char CurPacket[QTRTPFILE_MAX_PACKET_LENGTH];
UInt32 CurPacketLength;
//
// List pointers
RTPTrackListEntry *NextTrack;
};
public:
//
// Global initialize function; CALL THIS FIRST!
static void Initialize(void);
//
// Returns a static array of the RTP-Meta-Info fields supported by QTFileLib.
// It also returns field IDs for the fields it recommends being compressed.
static const RTPMetaInfoPacket::FieldID* GetSupportedRTPMetaInfoFields() { return kMetaInfoFields; }
//
// Constructors and destructor.
QTRTPFile(Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTRTPFile(void);
//
// Initialization functions.
virtual ErrorCode Initialize(const char * FilePath);
void AllocateSharedBuffers(UInt32 inUnitSizeInK, UInt32 inBufferInc, UInt32 inBufferSizeUnits, UInt32 inMaxBitRateBuffSizeInBlocks)
{ fFile->AllocateBuffers(inUnitSizeInK, inBufferInc, inBufferSizeUnits, inMaxBitRateBuffSizeInBlocks, this->GetBytesPerSecond() * 8 );
}
void AllocatePrivateBuffers(UInt32 inUnitSizeInK, UInt32 inNumBuffSizeUnits, UInt32 inMaxBitRateBuffSizeInBlocks);
//
// Accessors
Float64 GetMovieDuration(void);
UInt64 GetAddedTracksRTPBytes(void);
char * GetSDPFile(int * SDPFileLength);
UInt32 GetBytesPerSecond(void);
char* GetMoviePath();
QTFile* GetQTFile() { return fFile; }
//
// Track functions
//
// AddTrack
//
// If you would like this track to be an RTP-Meta-Info stream, pass in
// the field names you would like to see
ErrorCode AddTrack(UInt32 TrackID, Bool16 UseRandomOffset = true);
Float64 GetTrackDuration(UInt32 TrackID);
UInt32 GetTrackTimeScale(UInt32 TrackID);
void SetTrackSSRC(UInt32 TrackID, UInt32 SSRC);
void SetTrackCookies(UInt32 TrackID, void * Cookie1, UInt32 Cookie2);
void SetAllowInvalidHintRefs(Bool16 inAllowInvalidHintRefs) { fAllowInvalidHintRefs = inAllowInvalidHintRefs; }
//
// If you want QTRTPFile to output an RTP-Meta-Info packet instead
// of a normal RTP packet for this track, call this function and
// pass in a proper Field ID array (see RTPMetaInfoPacket.h) to
// tell QTRTPFile which fields to include and which IDs to use with the fields.
// You have to let this function know whether this is a video track or not.
void SetTrackRTPMetaInfo(UInt32 TrackID, RTPMetaInfoPacket::FieldID* inFieldArray, Bool16 isVideo );
//
// What sort of packets do you want?
enum
{
kAllPackets = 0,
kNoBFrames = 1,
k75PercentPFrames = 2,
k50PercentPFrames = 3,
k25PercentPFrames = 4,
kKeyFramesOnly = 5,
kKeyFramesPlusOneP = 6 //Special quality level with Key frames followed by 1 P frame
};
void SetTrackQualityLevel(RTPTrackListEntry* inEntry, UInt32 inNewLevel);
//
// Packet functions
ErrorCode Seek(Float64 Time, Float64 MaxBackupTime = 3.0);
ErrorCode SeekToPacketNumber(UInt32 inTrackID, UInt64 inPacketNumber);
UInt32 GetSeekTimestamp(UInt32 TrackID);
Float64 GetRequestedSeekTime() { return fRequestedSeekTime; }
Float64 GetActualSeekTime() { return fSeekTime; }
Float64 GetFirstPacketTransmitTime();
RTPTrackListEntry* GetLastPacketTrack() { return fLastPacketTrack; }
UInt32 GetNumSkippedSamples() { return fNumSkippedSamples; }
UInt16 GetNextTrackSequenceNumber(UInt32 TrackID);
Float64 GetNextPacket(char ** Packet, int * PacketLength);
SInt32 GetMovieHintType();
Bool16 DropRepeatPackets() { return fDropRepeatPackets; }
Bool16 SetDropRepeatPackets(Bool16 allowRepeatPackets) { (!fHasRTPMetaInfoFieldArray) ? fDropRepeatPackets = allowRepeatPackets : fDropRepeatPackets = false; return fDropRepeatPackets;}
ErrorCode Error() { return fErr; };
Bool16 FindTrackEntry(UInt32 TrackID, RTPTrackListEntry **TrackEntry);
protected:
//
// Protected cache functions and variables.
static OSMutex *gFileCacheMutex, *gFileCacheAddMutex;
static RTPFileCacheEntry *gFirstFileCacheEntry;
static ErrorCode new_QTFile(const char * FilePath, QTFile ** File, Bool16 Debug = false, Bool16 DeepDebug = false);
static void delete_QTFile(QTFile * File);
static void AddFileToCache(const char *inFilename, QTRTPFile::RTPFileCacheEntry ** NewListEntry);
static Bool16 FindAndRefcountFileCacheEntry(const char *inFilename, QTRTPFile::RTPFileCacheEntry **CacheEntry);
//
// Protected member functions.
Bool16 PrefetchNextPacket(RTPTrackListEntry * TrackEntry, Bool16 doSeek = false);
ErrorCode ScanToCorrectSample();
ErrorCode ScanToCorrectPacketNumber(UInt32 inTrackID, UInt64 inPacketNumber);
//
// Protected member variables.
Bool16 fDebug, fDeepDebug;
QTFile *fFile;
QTFile_FileControlBlock *fFCB;
UInt32 fNumHintTracks;
RTPTrackListEntry *fFirstTrack, *fLastTrack, *fCurSeekTrack;
char *fSDPFile;
UInt32 fSDPFileLength;
UInt32 fNumSkippedSamples;
Float64 fRequestedSeekTime, fSeekTime;
RTPTrackListEntry *fLastPacketTrack;
UInt32 fBytesPerSecond;
Bool16 fHasRTPMetaInfoFieldArray;
Bool16 fWasLastSeekASeekToPacketNumber;
Bool16 fDropRepeatPackets;
Bool16 fAllowInvalidHintRefs;
ErrorCode fErr;
static const RTPMetaInfoPacket::FieldID kMetaInfoFields[];
};
#endif // QTRTPFile

485
QTFileLib/QTTrack.cpp Normal file
View file

@ -0,0 +1,485 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTTrack:
// The central point of control for a track in a QTFile.
// -------------------------------------
// Includes
//
#include <stdio.h>
#include <stdlib.h>
#include "SafeStdLib.h"
#include <string.h>
#include <time.h>
#include "QTFile.h"
#include "QTAtom.h"
#include "QTAtom_dref.h"
#include "QTAtom_elst.h"
#include "QTAtom_mdhd.h"
#include "QTAtom_tkhd.h"
#include "QTAtom_stco.h"
#include "QTAtom_stsc.h"
#include "QTAtom_stsd.h"
#include "QTAtom_stss.h"
#include "QTAtom_stsz.h"
#include "QTAtom_stts.h"
#include "QTTrack.h"
#include "OSMemory.h"
// -------------------------------------
// Macros
//
#define DEBUG_PRINT(s) if(fDebug) qtss_printf s
#define DEEP_DEBUG_PRINT(s) if(fDeepDebug) qtss_printf s
// -------------------------------------
// Constructors and destructors
//
QTTrack::QTTrack(QTFile * File, QTFile::AtomTOCEntry * Atom, Bool16 Debug, Bool16 DeepDebug)
: fDebug(Debug), fDeepDebug(DeepDebug),
fFile(File),
fIsInitialized(false),
fTrackHeaderAtom(NULL),
fTrackName(NULL),
fMediaHeaderAtom(NULL),
fEditListAtom(NULL), fDataReferenceAtom(NULL),
fTimeToSampleAtom(NULL),fCompTimeToSampleAtom(NULL), fSampleToChunkAtom(NULL), fSampleDescriptionAtom(NULL),
fChunkOffsetAtom(NULL), fSampleSizeAtom(NULL), fSyncSampleAtom(NULL),
fFirstEditMediaTime(0)
{
// Temporary vars
QTFile::AtomTOCEntry *tempTOCEntry;
//
// Make a copy of the TOC entry.
memcpy(&fTOCEntry, Atom, sizeof(QTFile::AtomTOCEntry));
//
// Load in the track header atom for this track.
if( !fFile->FindTOCEntry(":tkhd", &tempTOCEntry, &fTOCEntry) )
return;
fTrackHeaderAtom = NEW QTAtom_tkhd(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fTrackHeaderAtom == NULL )
return;
if( !fTrackHeaderAtom->Initialize() ) {
delete fTrackHeaderAtom;
fTrackHeaderAtom = NULL;
}
}
QTTrack::~QTTrack(void)
{
//
// Free our variables
if( fTrackHeaderAtom != NULL )
delete fTrackHeaderAtom;
if( fTrackName != NULL )
delete[] fTrackName;
if( fMediaHeaderAtom != NULL )
delete fMediaHeaderAtom;
if( fEditListAtom != NULL )
delete fEditListAtom;
if( fDataReferenceAtom != NULL )
delete fDataReferenceAtom;
if( fTimeToSampleAtom != NULL )
delete fTimeToSampleAtom;
if( fSampleToChunkAtom != NULL )
delete fSampleToChunkAtom;
if( fSampleDescriptionAtom != NULL )
delete fSampleDescriptionAtom;
if( fChunkOffsetAtom != NULL )
delete fChunkOffsetAtom;
if( fSampleSizeAtom != NULL )
delete fSampleSizeAtom;
if( fSyncSampleAtom != NULL )
delete fSyncSampleAtom;
}
// -------------------------------------
// Initialization functions
//
QTTrack::ErrorCode QTTrack::Initialize(void)
{
// Temporary vars
QTFile::AtomTOCEntry *tempTOCEntry;
//
// Don't initialize more than once.
if( IsInitialized() )
return errNoError;
//
// Make sure that we were able to read in our track header atom.
if( fTrackHeaderAtom == NULL )
return errInvalidQuickTimeFile;
//
// See if this track has a name and load it in.
if( fFile->FindTOCEntry(":udta:name", &tempTOCEntry, &fTOCEntry) ) {
fTrackName = NEW char[ (SInt32) (tempTOCEntry->AtomDataLength + 1) ];
if( fTrackName != NULL )
fFile->Read(tempTOCEntry->AtomDataPos, fTrackName, (UInt32) tempTOCEntry->AtomDataLength);
}
//
// Load in the media header atom for this track.
if( !fFile->FindTOCEntry(":mdia:mdhd", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fMediaHeaderAtom = NEW QTAtom_mdhd(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fMediaHeaderAtom == NULL )
return errInternalError;
if( !fMediaHeaderAtom->Initialize() )
return errInvalidQuickTimeFile;
//
// Load in the edit list atom for this track.
DEEP_DEBUG_PRINT(("Searching track #%"_U32BITARG_" 'elst' atom.\n", GetTrackID()));
if( fFile->FindTOCEntry(":edts:elst", &tempTOCEntry, &fTOCEntry) ) {
fEditListAtom = NEW QTAtom_elst(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fEditListAtom == NULL )
return errInternalError;
if( !fEditListAtom->Initialize() )
return errInvalidQuickTimeFile;
//
// Compute the first edit's media time.
fFirstEditMediaTime = (UInt32)(( ( (Float64) (SInt64) GetFirstEditMovieTime())/ fFile->GetTimeScale()) * GetTimeScale());
} else {
fEditListAtom = NULL;
}
//
// Load in the data reference atom for this track.
if( !fFile->FindTOCEntry(":mdia:minf:dinf:dref", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fDataReferenceAtom = NEW QTAtom_dref(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fDataReferenceAtom == NULL )
return errInternalError;
if( !fDataReferenceAtom->Initialize() )
return errInvalidQuickTimeFile;
//
// Load in the sample table atoms.
if( !fFile->FindTOCEntry(":mdia:minf:stbl:stts", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fTimeToSampleAtom = NEW QTAtom_stts(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fTimeToSampleAtom == NULL )
return errInternalError;
if( !fTimeToSampleAtom->Initialize() )
return errInvalidQuickTimeFile;
if( fFile->FindTOCEntry(":mdia:minf:stbl:ctts", &tempTOCEntry, &fTOCEntry) )
{
fCompTimeToSampleAtom = NEW QTAtom_ctts(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fCompTimeToSampleAtom == NULL )
return errInternalError;
if( !fCompTimeToSampleAtom->Initialize() )
return errInvalidQuickTimeFile;
}
if( !fFile->FindTOCEntry(":mdia:minf:stbl:stsc", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fSampleToChunkAtom = NEW QTAtom_stsc(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fSampleToChunkAtom == NULL )
return errInternalError;
if( !fSampleToChunkAtom->Initialize() )
return errInvalidQuickTimeFile;
if( !fFile->FindTOCEntry(":mdia:minf:stbl:stsd", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fSampleDescriptionAtom = NEW QTAtom_stsd(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fSampleDescriptionAtom == NULL )
return errInternalError;
if( !fSampleDescriptionAtom->Initialize() )
return errInvalidQuickTimeFile;
UInt16 offSetSize = 0;
Bool16 coFound = false;
if( fFile->FindTOCEntry(":mdia:minf:stbl:stco", &tempTOCEntry, &fTOCEntry) )
{
coFound = true;
offSetSize = 4;
} else if( fFile->FindTOCEntry(":mdia:minf:stbl:co64", &tempTOCEntry, &fTOCEntry) )
{
coFound = true;
offSetSize = 8;
}
if (!coFound)
return errInvalidQuickTimeFile;
fChunkOffsetAtom = NEW QTAtom_stco(fFile, tempTOCEntry, offSetSize, fDebug, fDeepDebug);
if( fChunkOffsetAtom == NULL )
return errInternalError;
if( !fChunkOffsetAtom->Initialize() )
return errInvalidQuickTimeFile;
if( !fFile->FindTOCEntry(":mdia:minf:stbl:stsz", &tempTOCEntry, &fTOCEntry) )
return errInvalidQuickTimeFile;
fSampleSizeAtom = NEW QTAtom_stsz(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fSampleSizeAtom == NULL )
return errInternalError;
if( !fSampleSizeAtom->Initialize() )
return errInvalidQuickTimeFile;
if( fFile->FindTOCEntry(":mdia:minf:stbl:stss", &tempTOCEntry, &fTOCEntry) ) {
fSyncSampleAtom = NEW QTAtom_stss(fFile, tempTOCEntry, fDebug, fDeepDebug);
if( fSyncSampleAtom == NULL )
return errInternalError;
if( !fSyncSampleAtom->Initialize() )
return errInvalidQuickTimeFile;
} else {
fSyncSampleAtom = NULL;
}
//
// This track has been successfully initialiazed.
fIsInitialized = true;
return errNoError;
}
// -------------------------------------
// Sample functions
//
Bool16 QTTrack::GetSampleInfo(UInt32 SampleNumber, UInt32 * const Length, UInt64 * const Offset, UInt32 * const SampleDescriptionIndex, QTAtom_stsc_SampleTableControlBlock * STCB)
{
Assert(STCB != NULL);
// qtss_printf("GetSampleInfo QTTrack SampleNumber = %"_S32BITARG_" \n", SampleNumber);
if (STCB->fGetSampleInfo_SampleNumber == SampleNumber && STCB->fGetSampleInfo_Length > 0)
{
// qtss_printf("----- GetSampleInfo Cache Hit QTTrack SampleNumber = %"_S32BITARG_" \n", SampleNumber);
if (Length) *Length = STCB->fGetSampleInfo_Length;
if (Offset) *Offset = STCB->fGetSampleInfo_Offset;
if (SampleDescriptionIndex) *SampleDescriptionIndex = STCB->fGetSampleInfo_SampleDescriptionIndex;
return true;
}
// Temporary vars
UInt32 sampleLength = 0;
UInt32 sampleDescriptionIndex = 0;
// General vars
UInt32 ChunkNumber, SampleOffsetInChunk;
UInt64 sampleFileStartOffset = 0;
UInt64 ChunkOffset = 0;
// Locate this sample, compute its offset, and get its size.
if( !SampleNumberToChunkNumber(SampleNumber, &ChunkNumber, &sampleDescriptionIndex, &SampleOffsetInChunk, STCB) )
return false;
if( !fSampleSizeAtom->SampleSize(SampleNumber, &sampleLength) )
return false;
if (ChunkNumber == STCB->fGetSampleInfo_LastChunk && (SampleNumber == (STCB->fGetSampleInfo_SampleNumber+1) ) )
{
sampleFileStartOffset = STCB->fGetSampleInfo_Offset;
sampleFileStartOffset += STCB->fGetSampleInfo_Length;
}
else
{
if( !fChunkOffsetAtom->ChunkOffset(ChunkNumber, &ChunkOffset) )
return false;
// Walk through all of the samples previous to this one, adding up
// their lengths to figure out what the offset from the start of
// the chunk to this sample is.
UInt32 tempSampleLength = fSampleSizeAtom->GetCommonSampleSize();
sampleFileStartOffset = ChunkOffset;
if (tempSampleLength > 0) // samples are the same size so just multiply to get size
{ sampleFileStartOffset += ( tempSampleLength * SampleOffsetInChunk );
}
else
{
for( UInt32 CurSample = (SampleNumber - SampleOffsetInChunk);CurSample < SampleNumber; CurSample++)
{
// Get the length of this sample and add it to our offset.
if( !fSampleSizeAtom->SampleSize(CurSample, &tempSampleLength) )
return false;
sampleFileStartOffset += tempSampleLength;
}
}
STCB->fGetSampleInfo_LastChunk = ChunkNumber;
STCB->fGetSampleInfo_LastChunkOffset = (UInt32) ChunkOffset;
STCB->fGetSampleInfo_SampleDescriptionIndex = sampleDescriptionIndex;
}
STCB->fGetSampleInfo_SampleNumber = SampleNumber;
STCB->fGetSampleInfo_Length = sampleLength;
STCB->fGetSampleInfo_Offset = sampleFileStartOffset;
if (Length != NULL) *Length = sampleLength;
if (Offset != NULL) *Offset = sampleFileStartOffset;
if (SampleDescriptionIndex != NULL) *SampleDescriptionIndex = sampleDescriptionIndex;
//
// The sample was successfully located.
return true;
}
Bool16 QTTrack::GetSizeOfSamplesInChunk(UInt32 chunkNumber, UInt32 * const sizePtr, UInt32 * const firstSampleNumPtr, UInt32 * const lastSampleNumPtr, QTAtom_stsc_SampleTableControlBlock * stcbPtr)
{
UInt32 firstSample = 0;
UInt32 lastSample = 0;
UInt32 size = 0;
if (stcbPtr && stcbPtr->fGetSizeOfSamplesInChunk_chunkNumber == chunkNumber)
{
// qtss_printf("QTTrack::GetSizeOfSamplesInChunk cache hit %"_S32BITARG_" \n", chunkNumber);
if (firstSampleNumPtr != NULL) *firstSampleNumPtr = stcbPtr->fGetSizeOfSamplesInChunk_firstSample;
if (lastSampleNumPtr != NULL) *lastSampleNumPtr = stcbPtr->fGetSizeOfSamplesInChunk_lastSample;
if (sizePtr != NULL) *sizePtr = stcbPtr->fGetSizeOfSamplesInChunk_size;
return true;
}
Bool16 result = GetChunkFirstLastSample(chunkNumber, &firstSample, &lastSample, stcbPtr);
if (result && (sizePtr != NULL) )
{
result = SampleRangeSize(firstSample, lastSample, &size);
}
if (firstSampleNumPtr != NULL) *firstSampleNumPtr = firstSample;
if (lastSampleNumPtr != NULL) *lastSampleNumPtr = lastSample;
if (sizePtr != NULL) *sizePtr = size;
if (stcbPtr && result)
{
stcbPtr->fGetSizeOfSamplesInChunk_chunkNumber = chunkNumber;
stcbPtr->fGetSizeOfSamplesInChunk_firstSample = firstSample;
stcbPtr->fGetSizeOfSamplesInChunk_lastSample = lastSample;
stcbPtr->fGetSizeOfSamplesInChunk_size = size;
}
return result;
}
Bool16 QTTrack::GetSample(UInt32 SampleNumber, char * Buffer, UInt32 * Length, QTFile_FileControlBlock * FCB, QTAtom_stsc_SampleTableControlBlock * STCB)
{
// General vars
UInt32 SampleDescriptionIndex;
UInt64 SampleOffset;
//
// Get the location and size of this sample.
if( !this->GetSampleInfo(SampleNumber, Length, &SampleOffset, &SampleDescriptionIndex, STCB) )
return false;
//
// Read in the sample
if( !fDataReferenceAtom->Read(SampleDescriptionIndex, SampleOffset, Buffer, *Length, FCB) )
return false;
//
// The sample was successfully read in.
return true;
}
// -------------------------------------
// Debugging functions
//
void QTTrack::DumpTrack(void)
{
//
// Dump this track's information.
DEBUG_PRINT(("QTTrack::DumpTrack - Dumping track.\n"));
DEBUG_PRINT(("QTTrack::DumpTrack - ..Track name: \"%s\".\n", fTrackName ? fTrackName : "<untitled>"));
//
// Dump the sub-atoms of this track.
if( fTrackHeaderAtom != NULL )
fTrackHeaderAtom->DumpAtom();
if( fMediaHeaderAtom != NULL )
fMediaHeaderAtom->DumpAtom();
if( fDataReferenceAtom != NULL )
fDataReferenceAtom->DumpAtom();
if( fCompTimeToSampleAtom != NULL)
fCompTimeToSampleAtom->DumpAtom();
if( fTimeToSampleAtom != NULL )
fTimeToSampleAtom->DumpAtom();
if( fSampleToChunkAtom != NULL )
fSampleToChunkAtom->DumpAtom();
if( fSampleDescriptionAtom != NULL )
fSampleDescriptionAtom->DumpAtom();
if( fChunkOffsetAtom != NULL )
fChunkOffsetAtom->DumpAtom();
if( fSampleSizeAtom != NULL )
fSampleSizeAtom->DumpAtom();
}

221
QTFileLib/QTTrack.h Normal file
View file

@ -0,0 +1,221 @@
/*
*
* @APPLE_LICENSE_HEADER_START@
*
* Copyright (c) 1999-2008 Apple Inc. All Rights Reserved.
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The 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@
*
*/
//
// QTTrack:
// The central point of control for a track in a QTFile.
#ifndef QTTrack_H
#define QTTrack_H
//
// Includes
#include "QTAtom_dref.h"
#include "QTAtom_elst.h"
#include "QTAtom_mdhd.h"
#include "QTAtom_tkhd.h"
#include "QTAtom_stco.h"
#include "QTAtom_stsc.h"
#include "QTAtom_stsd.h"
#include "QTAtom_stss.h"
#include "QTAtom_stsz.h"
#include "QTAtom_stts.h"
//
// External classes
class QTFile;
class QTFile_FileControlBlock;
class QTAtom_stsc_SampleTableControlBlock;
class QTAtom_stts_SampleTableControlBlock;
//
// QTTrack class
class QTTrack {
public:
//
// Class error codes
enum ErrorCode {
errNoError = 0,
errInvalidQuickTimeFile = 1,
errParamError = 2,
errIsSkippedPacket = 3,
errInternalError = 100
};
public:
//
// Constructors and destructor.
QTTrack(QTFile * File, QTFile::AtomTOCEntry * trakAtom,
Bool16 Debug = false, Bool16 DeepDebug = false);
virtual ~QTTrack(void);
//
// Initialization functions.
virtual ErrorCode Initialize(void);
//
// Accessors.
inline Bool16 IsInitialized(void) { return fIsInitialized; }
inline const char *GetTrackName(void) { return (fTrackName ? fTrackName : ""); }
inline UInt32 GetTrackID(void) { return fTrackHeaderAtom->GetTrackID(); }
inline UInt64 GetCreationTime(void) { return fTrackHeaderAtom->GetCreationTime(); }
inline UInt64 GetModificationTime(void) { return fTrackHeaderAtom->GetModificationTime(); }
inline SInt64 GetDuration(void) { return (SInt64) fTrackHeaderAtom->GetDuration(); }
inline Float64 GetTimeScale(void) { return fMediaHeaderAtom->GetTimeScale(); }
inline Float64 GetTimeScaleRecip(void) { return fMediaHeaderAtom->GetTimeScaleRecip(); }
inline Float64 GetDurationInSeconds(void) { return GetDuration() / (Float64)GetTimeScale(); }
inline UInt64 GetFirstEditMovieTime(void)
{ if(fEditListAtom != NULL) return fEditListAtom->FirstEditMovieTime();
else return 0; }
inline UInt32 GetFirstEditMediaTime(void) { return fFirstEditMediaTime; }
//
// Sample functions
Bool16 GetSizeOfSamplesInChunk(UInt32 chunkNumber, UInt32 * const sizePtr, UInt32 * const firstSampleNumPtr, UInt32 * const lastSampleNumPtr, QTAtom_stsc_SampleTableControlBlock * stcbPtr);
inline Bool16 GetChunkFirstLastSample(UInt32 chunkNumber, UInt32 *firstSample, UInt32 *lastSample,
QTAtom_stsc_SampleTableControlBlock *STCB)
{ return fSampleToChunkAtom->GetChunkFirstLastSample(chunkNumber,firstSample, lastSample, STCB);
}
inline Bool16 SampleToChunkInfo(UInt32 SampleNumber, UInt32 *samplesPerChunk, UInt32 *ChunkNumber, UInt32 *SampleDescriptionIndex, UInt32 *SampleOffsetInChunk,
QTAtom_stsc_SampleTableControlBlock * STCB)
{ return fSampleToChunkAtom->SampleToChunkInfo(SampleNumber,samplesPerChunk, ChunkNumber, SampleDescriptionIndex, SampleOffsetInChunk, STCB);
}
inline Bool16 SampleNumberToChunkNumber(UInt32 SampleNumber, UInt32 *ChunkNumber, UInt32 *SampleDescriptionIndex, UInt32 *SampleOffsetInChunk,
QTAtom_stsc_SampleTableControlBlock * STCB)
{ return fSampleToChunkAtom->SampleNumberToChunkNumber(SampleNumber, ChunkNumber, SampleDescriptionIndex, SampleOffsetInChunk, STCB);
}
inline UInt32 GetChunkFirstSample(UInt32 chunkNumber)
{ return fSampleToChunkAtom->GetChunkFirstSample(chunkNumber);
}
inline Bool16 ChunkOffset(UInt32 ChunkNumber, UInt64 *Offset = NULL)
{ return fChunkOffsetAtom->ChunkOffset(ChunkNumber, Offset);
}
inline Bool16 SampleSize(UInt32 SampleNumber, UInt32 *Size = NULL)
{ return fSampleSizeAtom->SampleSize(SampleNumber, Size);
}
inline Bool16 SampleRangeSize(UInt32 firstSample, UInt32 lastSample, UInt32 *sizePtr = NULL)
{ return fSampleSizeAtom->SampleRangeSize(firstSample, lastSample, sizePtr);
}
Bool16 GetSampleInfo(UInt32 SampleNumber, UInt32 * const Length, UInt64 * const Offset, UInt32 * const SampleDescriptionIndex,
QTAtom_stsc_SampleTableControlBlock * STCB);
Bool16 GetSample(UInt32 SampleNumber, char * Buffer, UInt32 * Length,QTFile_FileControlBlock * FCB,
QTAtom_stsc_SampleTableControlBlock * STCB);
inline Bool16 GetSampleMediaTime(UInt32 SampleNumber, UInt32 * const MediaTime,
QTAtom_stts_SampleTableControlBlock * STCB)
{ return fTimeToSampleAtom->SampleNumberToMediaTime(SampleNumber, MediaTime, STCB);
}
inline Bool16 GetSampleNumberFromMediaTime(UInt32 MediaTime, UInt32 * const SampleNumber,
QTAtom_stts_SampleTableControlBlock * STCB)
{ return fTimeToSampleAtom->MediaTimeToSampleNumber(MediaTime, SampleNumber, STCB);
}
inline void GetPreviousSyncSample(UInt32 SampleNumber, UInt32 * SyncSampleNumber)
{ if(fSyncSampleAtom != NULL) fSyncSampleAtom->PreviousSyncSample(SampleNumber, SyncSampleNumber);
else *SyncSampleNumber = SampleNumber;
}
inline void GetNextSyncSample(UInt32 SampleNumber, UInt32 * SyncSampleNumber)
{ if(fSyncSampleAtom != NULL) fSyncSampleAtom->NextSyncSample(SampleNumber, SyncSampleNumber);
else *SyncSampleNumber = SampleNumber + 1;
}
inline Bool16 IsSyncSample(UInt32 SampleNumber, UInt32 SyncSampleCursor)
{ if (fSyncSampleAtom != NULL) return fSyncSampleAtom->IsSyncSample(SampleNumber, SyncSampleCursor);
else return true;
}
//
// Read functions.
inline Bool16 Read(UInt32 SampleDescriptionID, UInt64 Offset, char * const Buffer, UInt32 Length,
QTFile_FileControlBlock * FCB = NULL)
{ return fDataReferenceAtom->Read(fSampleDescriptionAtom->SampleDescriptionToDataReference(SampleDescriptionID), Offset, Buffer, Length, FCB);
}
inline Bool16 GetSampleMediaTimeOffset(UInt32 SampleNumber, UInt32 *mediaTimeOffset, QTAtom_ctts_SampleTableControlBlock * STCB)
{
if (fCompTimeToSampleAtom)
return fCompTimeToSampleAtom->SampleNumberToMediaTimeOffset(SampleNumber, mediaTimeOffset, STCB);
else
return false;
}
//
// Debugging functions.
virtual void DumpTrack(void);
inline void DumpSampleToChunkTable(void) { fSampleToChunkAtom->DumpTable(); }
inline void DumpChunkOffsetTable(void) { fChunkOffsetAtom->DumpTable(); }
inline void DumpSampleSizeTable(void) { fSampleSizeAtom->DumpTable(); }
inline void DumpTimeToSampleTable(void) { fTimeToSampleAtom->DumpTable(); }
inline void DumpCompTimeToSampleTable(void) { if (fCompTimeToSampleAtom) fCompTimeToSampleAtom->DumpTable(); else printf("*** no ctts table ****\n"); }
protected:
//
// Protected member variables.
Bool16 fDebug, fDeepDebug;
QTFile *fFile;
QTFile::AtomTOCEntry fTOCEntry;
Bool16 fIsInitialized;
QTAtom_tkhd *fTrackHeaderAtom;
char *fTrackName;
QTAtom_mdhd *fMediaHeaderAtom;
QTAtom_elst *fEditListAtom;
QTAtom_dref *fDataReferenceAtom;
QTAtom_stts *fTimeToSampleAtom;
QTAtom_ctts *fCompTimeToSampleAtom;
QTAtom_stsc *fSampleToChunkAtom;
QTAtom_stsd *fSampleDescriptionAtom;
QTAtom_stco *fChunkOffsetAtom;
QTAtom_stsz *fSampleSizeAtom;
QTAtom_stss *fSyncSampleAtom;
UInt32 fFirstEditMediaTime;
};
#endif // QTTrack_H