From b497352618423afeddbd35ccc76b3af0f4fa42e2 Mon Sep 17 00:00:00 2001 From: David McPaul Date: Wed, 15 Jun 2005 09:41:32 +0000 Subject: [PATCH] Added compressed header support to movreader git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13149 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/media/plugins/mov_reader/Jamfile | 1 + .../plugins/mov_reader/libMOV/MOVAtom.cpp | 34 ++- .../media/plugins/mov_reader/libMOV/MOVAtom.h | 10 +- .../mov_reader/libMOV/MOVFileReader.cpp | 130 ++++++----- .../plugins/mov_reader/libMOV/MOVParser.cpp | 221 +++++++++++++++--- .../plugins/mov_reader/libMOV/MOVParser.h | 59 ++++- .../plugins/mov_reader/libMOV/MOVTrakAtom.cpp | 21 ++ .../media/plugins/mov_reader/mov_reader.cpp | 4 +- 8 files changed, 372 insertions(+), 108 deletions(-) diff --git a/src/add-ons/media/plugins/mov_reader/Jamfile b/src/add-ons/media/plugins/mov_reader/Jamfile index c531370fa8..2f8abfc6d2 100644 --- a/src/add-ons/media/plugins/mov_reader/Jamfile +++ b/src/add-ons/media/plugins/mov_reader/Jamfile @@ -8,6 +8,7 @@ Addon mov_reader : media plugins : false : libmovreader.a + libz.a ; LinkSharedOSLibs mov_reader : be libmedia.so ; diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.cpp index 5f190dc343..3ef4fe786b 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.cpp @@ -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 +#include #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(); } diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.h b/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.h index d0a4afbcd6..16d6628953 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.h +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVAtom.h @@ -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); diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp index 78ed07887b..2a33ffc812 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp @@ -180,10 +180,7 @@ AtomBase *aAtomBase; if ((aAtomBase) && (dynamic_cast(aAtomBase)->IsVideo())) { - aAtomBase = dynamic_cast(aAtomBase)->GetChildAtom(uint32('stts'),0); - STTSAtom *aSTTSAtom = dynamic_cast(aAtomBase); - - return aSTTSAtom->getSUMCounts(); + return dynamic_cast(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(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(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 */ diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp index f09d653721..ed83a2ff84 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp @@ -28,6 +28,9 @@ #include #include +#include +//#include + #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(aAtomBase)) { + // DCOM atom + compressionID = dynamic_cast(aAtomBase)->getCompressionID(); + delete aAtomBase; + } else { + if (dynamic_cast(aAtomBase)) { + // CMVD atom + aCMVDAtom = dynamic_cast(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;iCount;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 diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.h b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.h index 7276e9cae5..c1bd84c8d0 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.h +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.h @@ -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 diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVTrakAtom.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVTrakAtom.cpp index 26236f6d64..a8e2bfa0fd 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVTrakAtom.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVTrakAtom.cpp @@ -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(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(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 diff --git a/src/add-ons/media/plugins/mov_reader/mov_reader.cpp b/src/add-ons/media/plugins/mov_reader/mov_reader.cpp index 74fc4c1329..dace0bdcd6 100644 --- a/src/add-ons/media/plugins/mov_reader/mov_reader.cpp +++ b/src/add-ons/media/plugins/mov_reader/mov_reader.cpp @@ -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;