Added compressed header support to movreader

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13149 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2005-06-15 09:41:32 +00:00
parent 49a755ef15
commit b497352618
8 changed files with 372 additions and 108 deletions
@@ -8,6 +8,7 @@ Addon mov_reader : media plugins :
false
:
libmovreader.a
libz.a
;
LinkSharedOSLibs mov_reader : be libmedia.so ;
@@ -22,7 +22,7 @@
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdio.h>
#include "MOVAtom.h"
@@ -69,7 +69,7 @@ void AtomBase::ProcessMetaData()
// - Calls ProcessMetaData on each child atom
// (ensures stream is correct for child via offset)
{
setAtomOffset(theStream->Position());
setAtomOffset(getStream()->Position());
OnProcessMetaData();
@@ -85,12 +85,19 @@ bool AtomBase::MoveToEnd()
{
off_t NewPosition = streamOffset + atomSize;
if (theStream->Position() != NewPosition) {
return (theStream->Seek(NewPosition,0) > 0);
if (getStream()->Position() != NewPosition) {
return (getStream()->Seek(NewPosition,0) > 0);
}
return true;
}
uint64 AtomBase::getBytesRemaining()
{
off_t EndPosition = streamOffset + atomSize;
return (EndPosition - getStream()->Position());
}
void AtomBase::DisplayAtoms()
{
uint32 aindent = 0;
@@ -117,11 +124,22 @@ bool AtomBase::IsKnown()
void AtomBase::ReadArrayHeader(array_header *pHeader)
{
theStream->Read(pHeader,sizeof(array_header));
getStream()->Read(pHeader,sizeof(array_header));
pHeader->NoEntries = B_BENDIAN_TO_HOST_INT32(pHeader->NoEntries);
}
BPositionIO *AtomBase::OnGetStream()
{
// default implementation
return theStream;
}
BPositionIO *AtomBase::getStream()
{
return OnGetStream();
}
AtomContainer::AtomContainer(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
TotalChildren = 0;
@@ -145,18 +163,20 @@ void AtomContainer::DisplayAtoms(uint32 pindent)
void AtomContainer::ProcessMetaData()
{
setAtomOffset(theStream->Position());
setAtomOffset(getStream()->Position());
OnProcessMetaData();
AtomBase *aChild;
while (IsEndOfAtom() == false) {
aChild = getAtom(theStream);
aChild = getAtom(getStream());
if (AddChild(aChild)) {
aChild->ProcessMetaData();
}
}
OnChildProcessingComplete();
MoveToEnd();
}
@@ -87,8 +87,12 @@ public:
virtual ~AtomBase();
virtual bool IsContainer() {return false;};
virtual BPositionIO *OnGetStream();
BPositionIO *getStream();
bool IsExtended() {return false;};
bool IsEndOfAtom() {return (theStream->Position() >= off_t(streamOffset + atomSize));};
bool IsEndOfAtom() {return (getStream()->Position() >= off_t(streamOffset + atomSize));};
// Is this a known atom type
bool IsKnown();
@@ -98,6 +102,8 @@ public:
uint64 getAtomSize() {return atomSize;};
uint32 getAtomType() {return atomType;};
uint64 getBytesRemaining();
bool IsType(uint32 patomType) {return patomType == atomType;};
void setAtomOffset(off_t patomOffset) {atomOffset = patomOffset;};
@@ -159,7 +165,7 @@ public:
// OnProcessMetaData() - Subclass override to read/set meta data
virtual void OnProcessMetaData();
virtual void OnChildProcessingComplete() {};
};
extern AtomBase *getAtom(BPositionIO *pStream);
@@ -180,10 +180,7 @@ AtomBase *aAtomBase;
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
aAtomBase = dynamic_cast<TRAKAtom *>(aAtomBase)->GetChildAtom(uint32('stts'),0);
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
return aSTTSAtom->getSUMCounts();
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
}
}
@@ -253,10 +250,7 @@ uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
}
// Add up all sample sizes in chunk
// uint32 ChunkSize = 0;
while (aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk) == ChunkNo) {
// ChunkSize += aTrakAtom->getSizeForSample(SampleNo);
SampleNo++;
}
return SampleNo ;
@@ -273,42 +267,55 @@ uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
{
// BStopWatch *watch;
// Find Track
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
// Convert Frame to Track Time
// uint32 FrameTime = aTrakAtom->getTimeForFrame(pFrameNo, getMovieTimeScale());
// Get Sample for Frame
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
// Get Chunk For Sample and the offset for the frame within that chunk
uint32 OffsetInChunk;
if (stream_index == 0) {
OffsetInChunk = 99;
}
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
// Get Offset For Chunk
// printf("Stream: %ld Frame %ld %ld <%ld/%ld> (",stream_index, pFrameNo, SampleNo, ChunkNo, OffsetInChunk);
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
if (pFrameNo < aTrakAtom->FrameCount()) {
// Convert Frame to Track Time
// uint32 FrameTime = aTrakAtom->getTimeForFrame(pFrameNo, getMovieTimeScale());
// Get Sample for Frame
// watch = new BStopWatch("getSampleForFrame");
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
// delete watch;
// Get Chunk For Sample and the offset for the frame within that chunk
// watch = new BStopWatch("getChunkForSample");
uint32 OffsetInChunk;
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
// delete watch;
// Get Offset For Chunk
// printf("Stream: %ld Frame %ld %ld <%ld/%ld> (",stream_index, pFrameNo, SampleNo, ChunkNo, OffsetInChunk);
// watch = new BStopWatch("getOffsetForChunk");
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
// delete watch;
// printf("Frame %ld {%lld} <%ld/%ld> (",pFrameNo, OffsetNo, ChunkNo, OffsetInChunk);
// printf("Frame %ld {%lld} <%ld/%ld> (",pFrameNo, OffsetNo, ChunkNo, OffsetInChunk);
if (ChunkNo != 0) {
uint32 SampleSize;
// Adjust the Offset for the Offset in the chunk
for (uint32 i=1;i<=OffsetInChunk;i++) {
SampleSize = aTrakAtom->getSizeForSample(SampleNo-i);
// printf(" %ld ",SampleSize);
OffsetNo = OffsetNo + SampleSize;
if (ChunkNo != 0) {
uint32 SampleSize;
// Adjust the Offset for the Offset in the chunk
// watch = new BStopWatch("getSizeForSample");
if (aTrakAtom->IsSingleSampleSize()) {
SampleSize = aTrakAtom->getSizeForSample(SampleNo);
OffsetNo = OffsetNo + (OffsetInChunk * SampleSize);
} else {
// This is bad news performance wise
for (uint32 i=1;i<=OffsetInChunk;i++) {
SampleSize = aTrakAtom->getSizeForSample(SampleNo-i);
// printf(" %ld ",SampleSize);
OffsetNo = OffsetNo + SampleSize;
}
}
// printf(") %lld\n",OffsetNo);
// delete watch;
}
// printf(") %lld\n",OffsetNo);
}
// printf("%ld:%ld:%ld:%lld\n",pFrameNo, SampleNo, ChunkNo, OffsetNo);
// printf("\n");
// printf("%ld:%ld:%ld:%lld\n",pFrameNo, SampleNo, ChunkNo, OffsetNo);
// printf("\n");
return OffsetNo;
return OffsetNo;
}
}
return 0;
@@ -466,13 +473,13 @@ const mov_stream_header *MOVFileReader::StreamFormat(uint32 stream_index)
theStreamHeader.length = 0;
if (IsVideo(stream_index)) {
theStreamHeader.rate = 0;
theStreamHeader.rate = uint32(1000000*VideoFormat(stream_index)->FrameRate);
theStreamHeader.scale = 1000000;
theStreamHeader.length = getVideoFrameCount();
}
if (IsAudio(stream_index)) {
theStreamHeader.rate = AudioFormat(stream_index)->SampleRate;
theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate);
theStreamHeader.scale = 1;
theStreamHeader.length = getAudioFrameCount();
theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize;
@@ -488,31 +495,33 @@ uint32 MOVFileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo)
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
if (pFrameNo < aTrakAtom->FrameCount()) {
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
if (IsAudio(stream_index)) {
uint32 OffsetInChunk;
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
if (IsAudio(stream_index)) {
uint32 OffsetInChunk;
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
// Go back to first Sample in Chunk
while (aTrakAtom->getChunkForSample(SampleNo-1, &OffsetInChunk) == ChunkNo) {
SampleNo--;
// Go back to first Sample in Chunk
while (aTrakAtom->getChunkForSample(SampleNo-1, &OffsetInChunk) == ChunkNo) {
SampleNo--;
}
// Add up all sample sizes in chunk
uint32 ChunkSize = 0;
while (aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk) == ChunkNo) {
ChunkSize += aTrakAtom->getSizeForSample(SampleNo);
SampleNo++;
}
return ChunkSize;
}
if (IsVideo(stream_index)) {
return aTrakAtom->getSizeForSample(SampleNo);
}
// Add up all sample sizes in chunk
uint32 ChunkSize = 0;
while (aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk) == ChunkNo) {
ChunkSize += aTrakAtom->getSizeForSample(SampleNo);
SampleNo++;
}
return ChunkSize;
}
if (IsVideo(stream_index)) {
return aTrakAtom->getSizeForSample(SampleNo);
}
}
return 0;
@@ -536,9 +545,14 @@ bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t
*start = getOffsetForFrame(stream_index, pFrameNo);
*size = getChunkSize(stream_index, pFrameNo);
*keyframe = IsKeyFrame(stream_index, pFrameNo);
if ((*start > 0) && (*size > 0)) {
*keyframe = IsKeyFrame(stream_index, pFrameNo);
}
return !(IsEndOfFile(*start) || *start < 0);
return ((*start > 0) && (*size > 0));
// return !(IsEndOfFile(*start) || *start < 0);
}
/* static */
@@ -28,6 +28,9 @@
#include <SupportKit.h>
#include <MediaFormats.h>
#include <libs/zlib/zlib.h>
//#include <zlib.h>
#include "MOVParser.h"
//static
@@ -159,6 +162,18 @@ AtomBase *getAtom(BPositionIO *pStream)
return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
if (aAtomType == uint32('cmov')) {
return new CMOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
if (aAtomType == uint32('dcom')) {
return new DCOMAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
if (aAtomType == uint32('cmvd')) {
return new CMVDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
}
@@ -182,6 +197,171 @@ char *MOOVAtom::OnGetAtomName()
return "Quicktime Movie";
}
CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize)
{
theUncompressedStream = NULL;
}
CMOVAtom::~CMOVAtom()
{
}
BPositionIO *CMOVAtom::OnGetStream()
{
// Use the decompressed stream instead of file stream
if (theUncompressedStream) {
return theUncompressedStream;
}
return theStream;
}
void CMOVAtom::OnProcessMetaData()
{
BMallocIO *theUncompressedData;
uint8 *outBuffer;
CMVDAtom *aCMVDAtom = NULL;
uint32 compressionID = 0;
uint64 descBytesLeft;
uint32 Size;
descBytesLeft = getAtomSize();
// Check for Compression Type
while (descBytesLeft > 0) {
AtomBase *aAtomBase = getAtom(theStream);
aAtomBase->OnProcessMetaData();
printf("%s [%Ld]\n",aAtomBase->getAtomName(),aAtomBase->getAtomSize());
if (aAtomBase->getAtomSize() > 0) {
descBytesLeft = descBytesLeft - aAtomBase->getAtomSize();
} else {
printf("Invalid Atom found when reading Compressed Headers\n");
descBytesLeft = 0;
}
if (dynamic_cast<DCOMAtom *>(aAtomBase)) {
// DCOM atom
compressionID = dynamic_cast<DCOMAtom *>(aAtomBase)->getCompressionID();
delete aAtomBase;
} else {
if (dynamic_cast<CMVDAtom *>(aAtomBase)) {
// CMVD atom
aCMVDAtom = dynamic_cast<CMVDAtom *>(aAtomBase);
descBytesLeft = 0;
}
}
}
// Decompress data
if (compressionID == 'zlib') {
Size = aCMVDAtom->getUncompressedSize();
outBuffer = (uint8 *)(malloc(Size));
printf("Decompressing %ld bytes to %ld bytes\n",aCMVDAtom->getBufferSize(),Size);
int result = uncompress(outBuffer, &Size, aCMVDAtom->getCompressedData(), aCMVDAtom->getBufferSize());
if (result != Z_OK) {
printf("Failed to decompress headers uncompress returned ");
switch (result) {
case Z_MEM_ERROR:
printf("Lack of Memory Error\n");
break;
case Z_BUF_ERROR:
printf("Lack of Output buffer space Error\n");
break;
case Z_DATA_ERROR:
printf("Input Data is corrupt or not a compressed set Error\n");
break;
}
}
// Copy uncompressed data into BMAllocIO
theUncompressedData = new BMallocIO();
theUncompressedData->SetSize(Size);
theUncompressedData->WriteAt(0L,outBuffer,Size);
free(outBuffer);
delete aCMVDAtom;
// reset position on BMAllocIO
theUncompressedData->Seek(SEEK_SET,0L);
// Assign to Stream
theUncompressedStream = theUncompressedData;
// All subsequent reads should use theUncompressedStream
}
}
void CMOVAtom::OnChildProcessingComplete()
{
// revert back to file stream once all children have finished
if (theUncompressedStream) {
delete theUncompressedStream;
}
theUncompressedStream = NULL;
}
char *CMOVAtom::OnGetAtomName()
{
return "Compressed Quicktime Movie";
}
DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
}
DCOMAtom::~DCOMAtom()
{
}
void DCOMAtom::OnProcessMetaData()
{
theStream->Read(&compressionID,sizeof(uint32));
compressionID = B_BENDIAN_TO_HOST_INT32(compressionID);
}
char *DCOMAtom::OnGetAtomName()
{
return "Decompression Atom";
}
CMVDAtom::CMVDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
Buffer = NULL;
UncompressedSize = 0;
BufferSize = 0;
}
CMVDAtom::~CMVDAtom()
{
if (Buffer) {
free(Buffer);
}
}
void CMVDAtom::OnProcessMetaData()
{
theStream->Read(&UncompressedSize,sizeof(uint32));
UncompressedSize = B_BENDIAN_TO_HOST_INT32(UncompressedSize);
if (UncompressedSize > 0) {
BufferSize = getBytesRemaining();
Buffer = (uint8 *)(malloc(BufferSize));
theStream->Read(Buffer,BufferSize);
}
}
char *CMVDAtom::OnGetAtomName()
{
return "Compressed Movie Data";
}
MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
}
@@ -289,6 +469,7 @@ uint64 STTSAtom::getSUMDurations()
uint32 STTSAtom::getSampleForTime(uint32 pTime)
{
// TODO this is too slow. PreCalc SUMCounts when loading this.
uint64 SUMDurations = 0;
for (uint32 i=0;i<theHeader.NoEntries;i++) {
@@ -303,23 +484,8 @@ uint32 STTSAtom::getSampleForTime(uint32 pTime)
uint32 STTSAtom::getSampleForFrame(uint32 pFrame)
{
// Hmm Sample is Frame really.
uint64 SUMCounts = 0;
uint64 SUMDurations = 0;
for (uint32 i=0;i<theHeader.NoEntries;i++) {
for (uint32 j=0;j<theTimeToSampleArray[i]->Count;j++) {
SUMCounts ++;
SUMDurations += theTimeToSampleArray[i]->Duration;
// printf("(i=%ld j=%ld) Duration %ld, Count %ld, Duration*Count %ld, SUM(Count) %lld, SUM(Duration*Count) %lld\n",i,j,theTimeToSampleArray[i]->Duration,theTimeToSampleArray[i]->Count,theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count,SUMCounts, SUMDurations);
if (SUMCounts > pFrame) {
return SUMCounts-1;
}
}
}
return theHeader.NoEntries;
// Hmm Sample is Frame really, this Atom is more usefull for time->sample calcs
return pFrame;
}
STSCAtom::STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
@@ -361,12 +527,8 @@ SampleToChunk *aSampleToChunk;
aSampleToChunk->TotalPrevFrames = 0;
}
// printf("First Chunk/Samples Per Chunk/ID %ld/%ld/%ld (%ld)\n",aSampleToChunk->FirstChunk,aSampleToChunk->SamplesPerChunk,aSampleToChunk->SampleDescriptionID,aSampleToChunk->TotalPrevFrames);
theSampleToChunkArray[i] = aSampleToChunk;
}
// printf("Sample To Chunk Array contains %ld Entries\n",theHeader.NoEntries);
}
char *STSCAtom::OnGetAtomName()
@@ -387,10 +549,6 @@ uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
OffsetInChunk = (pSample - theSampleToChunkArray[i]->TotalPrevFrames) % theSampleToChunkArray[i]->SamplesPerChunk;
if (*pOffsetInChunk == 99) {
// printf("%ld (%ld/%ld)\n",pSample, ChunkID, OffsetInChunk);
}
*pOffsetInChunk = OffsetInChunk;
return ChunkID;
}
@@ -502,6 +660,11 @@ uint32 STSZAtom::getSizeForSample(uint32 pSampleNo)
return theSampleSizeArray[pSampleNo]->Size;
}
bool STSZAtom::IsSingleSampleSize()
{
return (theHeader.SampleSize > 0);
}
STCOAtom::STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
theHeader.NoEntries = 0;
@@ -536,8 +699,6 @@ ChunkToOffset *aChunkToOffset;
aChunkToOffset->Offset = OnGetChunkOffset();
// printf("%ld : %lld\n",i,aChunkToOffset->Offset);
theChunkToOffsetArray[i] = aChunkToOffset;
}
@@ -551,14 +712,13 @@ char *STCOAtom::OnGetAtomName()
uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
{
// printf("?Chunk ID %ld / %ld\n",pChunkID,theHeader.NoEntries);
// First chunk is first array entry
if ((pChunkID > 0) && (pChunkID <= theHeader.NoEntries)) {
return theChunkToOffsetArray[pChunkID - 1]->Offset;
}
printf("Bad Chunk ID %ld / %ld\n",pChunkID,theHeader.NoEntries);
// TODO Yes this will seg fault. But I get a very bad lock up if I don't :-(
return theChunkToOffsetArray[pChunkID - 1]->Offset;
// return theChunkToOffsetArray[0]->Offset;
@@ -604,9 +764,6 @@ void STSDAtom::ReadSoundDescription()
descBytesLeft = aSoundDescriptionV1->basefields.Size - sizeof(SampleDescBase);
// Hmm this should be ok if each stsd describes only a single type
DataFormat = aSoundDescriptionV1->basefields.DataFormat;
// Read in Audio Sample Data
// We place into a V1 description even though it might be a V0 or earlier
@@ -77,6 +77,49 @@ private:
MVHDAtom *theMVHDAtom;
};
// Atom class for reading the cmov atom
class CMOVAtom : public AtomContainer {
public:
CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
virtual ~CMOVAtom();
BPositionIO *OnGetStream();
void OnProcessMetaData();
void OnChildProcessingComplete();
char *OnGetAtomName();
private:
BMallocIO *theUncompressedStream;
};
// Atom class for reading the dcom atom
class DCOMAtom : public AtomBase {
public:
DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
virtual ~DCOMAtom();
void OnProcessMetaData();
char *OnGetAtomName();
uint32 getCompressionID() {return compressionID;};
private:
uint32 compressionID;
};
// Atom class for reading the cmvd atom
class CMVDAtom : public AtomBase {
public:
CMVDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
virtual ~CMVDAtom();
void OnProcessMetaData();
char *OnGetAtomName();
uint32 getUncompressedSize() {return UncompressedSize;};
uint8 *getCompressedData() {return Buffer;};
uint32 getBufferSize() {return BufferSize;};
private:
uint32 UncompressedSize;
uint32 BufferSize;
uint8 *Buffer;
};
// Atom class for reading the ftyp atom
class FTYPAtom : public AtomBase {
public:
@@ -190,7 +233,7 @@ public:
char *OnGetAtomName();
uint32 getSizeForSample(uint32 pSampleNo);
bool IsSingleSampleSize();
private:
SampleSizeHeader theHeader;
SampleSizeArray theSampleSizeArray;
@@ -224,8 +267,6 @@ public:
void OnProcessMetaData();
char *OnGetAtomName();
uint32 DataFormat;
VideoDescriptionV0 getAsVideo();
SoundDescriptionV1 getAsAudio();
@@ -299,9 +340,10 @@ public:
virtual ~TRAKAtom();
void OnProcessMetaData();
char *OnGetAtomName();
void OnChildProcessingComplete();
bigtime_t Duration(uint32 TimeScale); // Return duration of track
uint32 FrameCount();
uint32 FrameCount() {return framecount;};
bool IsVideo(); // Is this a video track
bool IsAudio(); // Is this a audio track
// GetAudioMetaData() // If this is a audio track get the audio meta data
@@ -314,12 +356,15 @@ public:
uint64 getOffsetForChunk(uint32 pChunk);
uint32 getSizeForSample(uint32 pSample);
bool IsSyncSample(uint32 pSampleNo);
bool IsSingleSampleSize();
TKHDAtom *getTKHDAtom();
MDHDAtom *getMDHDAtom();
private:
TKHDAtom *theTKHDAtom;
MDHDAtom *theMDHDAtom;
uint32 framecount;
};
// Atom class for reading the media container atom
@@ -399,7 +444,7 @@ public:
uint32 getMediaComponentSubType();
private:
hdlr theHeader;
hdlr theHeader;
};
#endif
@@ -28,6 +28,7 @@ TRAKAtom::TRAKAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType,
{
theTKHDAtom = NULL;
theMDHDAtom = NULL;
framecount = 0;
}
TRAKAtom::~TRAKAtom()
@@ -79,6 +80,15 @@ bigtime_t TRAKAtom::Duration(uint32 TimeScale)
return bigtime_t(getTKHDAtom()->getDuration() * 1000000) / TimeScale;
}
void TRAKAtom::OnChildProcessingComplete()
{
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(GetChildAtom(uint32('stts'),0));
if (aSTTSAtom) {
framecount = aSTTSAtom->getSUMCounts();
}
}
// Is this a video track
bool TRAKAtom::IsVideo()
{
@@ -177,5 +187,16 @@ bool TRAKAtom::IsSyncSample(uint32 pSampleNo)
return false;
}
bool TRAKAtom::IsSingleSampleSize()
{
AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0);
if (aAtomBase) {
return (dynamic_cast<STSZAtom *>(aAtomBase))->IsSingleSampleSize();
}
return false;
}
// GetAudioMetaData() // If this is a audio track get the audio meta data
// GetVideoMetaData() // If this is a video track get the video meta data
@@ -461,8 +461,6 @@ movReader::GetNextChunk(void *_cookie,
if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe))
return B_LAST_BUFFER_ERROR;
TRACE("stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
if (cookie->buffer_size < size) {
delete [] cookie->buffer;
cookie->buffer_size = (size + 15) & ~15;
@@ -470,6 +468,7 @@ movReader::GetNextChunk(void *_cookie,
}
if (cookie->audio) {
TRACE("Audio stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
mediaHeader->start_time = (cookie->byte_pos * 1000000LL * (int64)cookie->bytes_per_sec_scale) / cookie->bytes_per_sec_rate;
mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
mediaHeader->u.encoded_audio.buffer_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;
@@ -484,6 +483,7 @@ movReader::GetNextChunk(void *_cookie,
// cookie->frame_pos += theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos);
// cookie->frame_pos += 2205;
} else {
TRACE("Video stream %d: frame %ld start %lld Size %ld key %d\n",cookie->stream, cookie->frame_pos, start, size, keyframe);
mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
mediaHeader->type = B_MEDIA_ENCODED_VIDEO;
mediaHeader->u.encoded_video.field_flags = keyframe ? B_MEDIA_KEY_FRAME : 0;