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
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();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue