Add even more of the source
This should be about everything needed to build so far?
This commit is contained in:
parent
af3619d4fa
commit
849723c9cf
547 changed files with 149239 additions and 0 deletions
269
QTFileLib/QTAtom.cpp
Normal file
269
QTFileLib/QTAtom.cpp
Normal 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
100
QTFileLib/QTAtom.h
Normal 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
381
QTFileLib/QTAtom_dref.cpp
Normal 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
113
QTFileLib/QTAtom_dref.h
Normal 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
174
QTFileLib/QTAtom_elst.cpp
Normal 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
91
QTFileLib/QTAtom_elst.h
Normal 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
212
QTFileLib/QTAtom_hinf.cpp
Normal 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
103
QTFileLib/QTAtom_hinf.h
Normal 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
161
QTFileLib/QTAtom_mdhd.cpp
Normal 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
83
QTFileLib/QTAtom_mdhd.h
Normal 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
229
QTFileLib/QTAtom_mvhd.cpp
Normal 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
91
QTFileLib/QTAtom_mvhd.h
Normal 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
149
QTFileLib/QTAtom_stco.cpp
Normal 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
95
QTFileLib/QTAtom_stco.h
Normal 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
619
QTFileLib/QTAtom_stsc.cpp
Normal 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
150
QTFileLib/QTAtom_stsc.h
Normal 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
222
QTFileLib/QTAtom_stsd.cpp
Normal 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
79
QTFileLib/QTAtom_stsd.h
Normal 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
231
QTFileLib/QTAtom_stss.cpp
Normal 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
93
QTFileLib/QTAtom_stss.h
Normal 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
205
QTFileLib/QTAtom_stsz.cpp
Normal 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
92
QTFileLib/QTAtom_stsz.h
Normal 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
581
QTFileLib/QTAtom_stts.cpp
Normal 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
181
QTFileLib/QTAtom_stts.h
Normal 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
210
QTFileLib/QTAtom_tkhd.cpp
Normal 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
98
QTFileLib/QTAtom_tkhd.h
Normal 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
114
QTFileLib/QTAtom_tref.cpp
Normal 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
85
QTFileLib/QTAtom_tref.h
Normal 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
988
QTFileLib/QTFile.cpp
Normal 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
215
QTFileLib/QTFile.h
Normal 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
|
322
QTFileLib/QTFile_FileControlBlock.cpp
Normal file
322
QTFileLib/QTFile_FileControlBlock.cpp
Normal 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;
|
||||
|
||||
}
|
113
QTFileLib/QTFile_FileControlBlock.h
Normal file
113
QTFileLib/QTFile_FileControlBlock.h
Normal 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
1516
QTFileLib/QTHintTrack.cpp
Normal file
File diff suppressed because it is too large
Load diff
243
QTFileLib/QTHintTrack.h
Normal file
243
QTFileLib/QTHintTrack.h
Normal 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
1544
QTFileLib/QTRTPFile.cpp
Normal file
File diff suppressed because it is too large
Load diff
283
QTFileLib/QTRTPFile.h
Normal file
283
QTFileLib/QTRTPFile.h
Normal 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
485
QTFileLib/QTTrack.cpp
Normal 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
221
QTFileLib/QTTrack.h
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue