diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.cpp b/src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.cpp similarity index 58% rename from src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.cpp rename to src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.cpp index 3c7328b200..86a9e9a587 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, David McPaul + * Copyright (c) 2010, David McPaul * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -22,43 +22,69 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "ChunkSuperIndex.h" - -ChunkSuperIndex::ChunkSuperIndex() -{ + +#include "BitParser.h" + +#include + +BitParser::BitParser(uint8 *bits, uint32 bitLength) { + this->bits = bits; + this->bitLength = bitLength; + this->index = 0; } -ChunkSuperIndex::~ChunkSuperIndex() -{ - theChunkIndexArray.erase(theChunkIndexArray.begin(),theChunkIndexArray.end()); +BitParser::BitParser() { + bits = NULL; + bitLength = 0; + index = 1; } -void ChunkSuperIndex::AddChunkIndex(uint32 stream, uint32 chunkid, off_t chunk_start) -{ - ChunkIndexPtr aChunkIndexPtr; - aChunkIndexPtr = new ChunkIndex; - aChunkIndexPtr->stream = stream; - aChunkIndexPtr->chunkid = chunkid; - aChunkIndexPtr->chunk_start = chunk_start; +BitParser::~BitParser() { + bits = NULL; +} + +void +BitParser::Init(uint8 *bits, uint32 bitLength) { + this->bits = bits; + this->bitLength = bitLength; + this->index = 1; +} + +void +BitParser::Skip(uint8 length) { + if (bitLength >= length) { + + while (length-- > 0) { + index++; + bitLength--; + + if (index > 8) { + index = 1; + bits++; + } + } + } +} + +uint32 +BitParser::GetValue(uint8 length) { + uint32 result = 0; - theChunkIndexArray[chunk_start] = aChunkIndexPtr; -} - -uint32 ChunkSuperIndex::getChunkSize(uint32 stream, uint32 chunkid, off_t chunk_start) -{ - ChunkIndexPtr aChunkIndexPtr = theChunkIndexArray[chunk_start]; - - if (aChunkIndexPtr) { - // Find next chunkIndex - ChunkIndexPtr nextChunkIndex; - - nextChunkIndex = theChunkIndexArray.upper_bound(chunk_start)->second; - - // Assert stream - // Assert chunkid - return (nextChunkIndex->chunk_start - aChunkIndexPtr->chunk_start); + if (bitLength < length) { + return 0; } - return 0; + while (length-- > 0) { + result = result << 1; + result += (*bits) & (uint8)(pow(2, 8-index)) ? 1 : 0; + index++; + bitLength--; + + if (index > 8) { + index = 1; + bits++; + } + } + + return result; } diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.h b/src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.h similarity index 70% rename from src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.h rename to src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.h index a0caee5ea6..67f927c2cb 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/ChunkSuperIndex.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/BitParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, David McPaul + * Copyright (c) 2010, David McPaul * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, @@ -22,33 +22,28 @@ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef _CHUNK_INDEX_H -#define _CHUNK_INDEX_H +#ifndef _BIT_PARSER_H +#define _BIT_PARSER_H #include -#include - - -struct ChunkIndex { - uint32 stream; - uint32 chunkid; - off_t chunk_start; -}; - -typedef ChunkIndex* ChunkIndexPtr; -typedef std::map > ChunkIndexArray; - -class ChunkSuperIndex { +class BitParser { + /* + A class to pull out arbitary values from a sequence of bits. + */ public: - ChunkSuperIndex(); - virtual ~ChunkSuperIndex(); - - void AddChunkIndex(uint32 stream, uint32 chunkid, off_t chunk_start); - uint32 getChunkSize(uint32 stream, uint32 chunkid, off_t chunk_start); - + BitParser(); + BitParser(uint8 *bits, uint32 bitLength); + virtual ~BitParser(); + + void Init(uint8 *bits, uint32 bitLength); + uint32 GetValue(uint8 length); + void Skip(uint8 length); + private: - ChunkIndexArray theChunkIndexArray; + uint8* bits; + uint32 bitLength; + uint8 index; }; -#endif // _CHUNK_INDEX_H +#endif // _BIT_PARSER_H diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/Jamfile b/src/add-ons/media/plugins/mp4_reader/libMP4/Jamfile index 31d310f00b..d611c47667 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/Jamfile +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/Jamfile @@ -7,5 +7,5 @@ StaticLibrary libmp4reader.a : MP4FileReader.cpp MP4Atom.cpp MP4TrakAtom.cpp - ChunkSuperIndex.cpp + BitParser.cpp ; diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.cpp b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.cpp index 7e7fe0d0c9..2ef4ef5844 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.cpp @@ -41,7 +41,7 @@ AtomBase::~AtomBase() parentAtom = NULL; } -char *AtomBase::getAtomTypeAsFourcc() +char *AtomBase::GetAtomTypeAsFourcc() { fourcc[0] = (char)((atomType >> 24) & 0xff); fourcc[1] = (char)((atomType >> 16) & 0xff); @@ -52,7 +52,7 @@ char *AtomBase::getAtomTypeAsFourcc() return fourcc; } -char *AtomBase::getAtomName() +char *AtomBase::GetAtomName() { char *_result; _result = OnGetAtomName(); @@ -80,7 +80,7 @@ void AtomBase::ProcessMetaData() // - Calls ProcessMetaData on each child atom // (ensures stream is correct for child via offset) { - setAtomOffset(getStream()->Position()); + SetAtomOffset(GetStream()->Position()); OnProcessMetaData(); @@ -96,16 +96,16 @@ bool AtomBase::MoveToEnd() { off_t NewPosition = streamOffset + atomSize; - if (getStream()->Position() != NewPosition) { - return (getStream()->Seek(NewPosition,0) > 0); + if (GetStream()->Position() != NewPosition) { + return (GetStream()->Seek(NewPosition,0) > 0); } return true; } -uint64 AtomBase::getBytesRemaining() +uint64 AtomBase::GetBytesRemaining() { off_t EndPosition = streamOffset + atomSize; - off_t CurrPosition = getStream()->Position(); + off_t CurrPosition = GetStream()->Position(); if (CurrPosition > EndPosition) { printf("ERROR: Read past atom boundary by %Ld bytes\n",CurrPosition - EndPosition); @@ -124,7 +124,7 @@ void AtomBase::DisplayAtoms() void AtomBase::DisplayAtoms(uint32 pindent) { Indent(pindent); - printf("(%s)\n",getAtomName()); + printf("(%s)\n",GetAtomName()); } void AtomBase::Indent(uint32 pindent) @@ -150,7 +150,7 @@ BPositionIO *AtomBase::OnGetStream() return theStream; } -BPositionIO *AtomBase::getStream() +BPositionIO *AtomBase::GetStream() { return OnGetStream(); } @@ -159,7 +159,7 @@ void AtomBase::Read(uint64 *value) { uint32 bytes_read; - bytes_read = getStream()->Read(value,sizeof(uint64)); + bytes_read = GetStream()->Read(value,sizeof(uint64)); // Assert((bytes_read == sizeof(uint64),"Read Error"); @@ -170,7 +170,7 @@ void AtomBase::Read(uint32 *value) { uint32 bytes_read; - bytes_read = getStream()->Read(value,sizeof(uint32)); + bytes_read = GetStream()->Read(value,sizeof(uint32)); // Assert((bytes_read == sizeof(uint32),"Read Error"); @@ -181,7 +181,7 @@ void AtomBase::Read(int32 *value) { uint32 bytes_read; - bytes_read = getStream()->Read(value,sizeof(int32)); + bytes_read = GetStream()->Read(value,sizeof(int32)); // Assert((bytes_read == sizeof(int32),"Read Error"); @@ -192,7 +192,7 @@ void AtomBase::Read(uint16 *value) { uint32 bytes_read; - bytes_read = getStream()->Read(value,sizeof(uint16)); + bytes_read = GetStream()->Read(value,sizeof(uint16)); // Assert((bytes_read == sizeof(uint16),"Read Error"); @@ -203,7 +203,7 @@ void AtomBase::Read(uint8 *value) { uint32 bytes_read; - bytes_read = getStream()->Read(value,sizeof(uint8)); + bytes_read = GetStream()->Read(value,sizeof(uint8)); // Assert((bytes_read == sizeof(uint8),"Read Error"); } @@ -212,7 +212,7 @@ void AtomBase::Read(char *value, uint32 maxread) { uint32 bytes_read; - bytes_read = getStream()->Read(value,maxread); + bytes_read = GetStream()->Read(value,maxread); // Assert((bytes_read == maxread,"Read Error"); } @@ -221,7 +221,7 @@ void AtomBase::Read(uint8 *value, uint32 maxread) { uint32 bytes_read; - bytes_read = getStream()->Read(value,maxread); + bytes_read = GetStream()->Read(value,maxread); // Assert((bytes_read == maxread,"Read Error"); } @@ -234,8 +234,6 @@ uint64 AtomBase::GetBits(uint64 buffer, uint8 startBit, uint8 totalBits) buffer = buffer << startBit; buffer = buffer >> (64 - (totalBits + startBit) + startBit); - printf("buffer = %Ld\n",buffer); - return buffer; } @@ -284,7 +282,7 @@ AtomContainer::~AtomContainer() void AtomContainer::DisplayAtoms(uint32 pindent) { Indent(pindent); - printf("%ld:(%s)\n",TotalChildren,getAtomName()); + printf("%ld:(%s)\n",TotalChildren,GetAtomName()); pindent++; // for each child for (uint32 i = 0;i < TotalChildren;i++) { @@ -295,13 +293,13 @@ void AtomContainer::DisplayAtoms(uint32 pindent) void AtomContainer::ProcessMetaData() { - setAtomOffset(getStream()->Position()); + SetAtomOffset(GetStream()->Position()); OnProcessMetaData(); AtomBase *aChild; while (IsEndOfAtom() == false) { - aChild = getAtom(getStream()); + aChild = GetAtom(GetStream()); if (AddChild(aChild)) { aChild->ProcessMetaData(); } @@ -315,7 +313,7 @@ void AtomContainer::ProcessMetaData() bool AtomContainer::AddChild(AtomBase *pChildAtom) { if (pChildAtom) { - pChildAtom->setParent(this); + pChildAtom->SetParent(this); atomChildren.push_back(pChildAtom); TotalChildren++; return true; diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.h b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.h index a138119078..84be06a179 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Atom.h @@ -89,32 +89,32 @@ public: virtual bool IsContainer() {return false;}; virtual BPositionIO *OnGetStream(); - BPositionIO *getStream(); + BPositionIO *GetStream(); bool IsExtended() {return false;}; - bool IsEndOfAtom() {return (getStream()->Position() >= off_t(streamOffset + atomSize));}; + bool IsEndOfAtom() {return (GetStream()->Position() >= off_t(streamOffset + atomSize));}; // Is this a known atom type bool IsKnown(); virtual void DisplayAtoms(uint32 pindent); - uint64 getAtomSize() {return atomSize;}; - uint32 getAtomType() {return atomType;}; - char *getAtomTypeAsFourcc(); - off_t getAtomOffset() { return atomOffset; }; - off_t getStreamOffset() { return streamOffset; }; + uint64 GetAtomSize() {return atomSize;}; + uint32 GetAtomType() {return atomType;}; + char *GetAtomTypeAsFourcc(); + off_t GetAtomOffset() { return atomOffset; }; + off_t GetStreamOffset() { return streamOffset; }; - uint64 getDataSize() { return atomSize - 8;}; + uint64 GetDataSize() { return atomSize - 8;}; - uint64 getBytesRemaining(); + uint64 GetBytesRemaining(); bool IsType(uint32 patomType) { return patomType == atomType; }; - void setAtomOffset(off_t patomOffset) { atomOffset = patomOffset; }; - void setStreamOffset(off_t pstreamOffset) { streamOffset = pstreamOffset; }; + void SetAtomOffset(off_t patomOffset) { atomOffset = patomOffset; }; + void SetStreamOffset(off_t pstreamOffset) { streamOffset = pstreamOffset; }; - char *getAtomName(); + char *GetAtomName(); virtual char *OnGetAtomName(); @@ -133,8 +133,8 @@ public: // Many atoms use an array header void ReadArrayHeader(array_header *pHeader); - void setParent(AtomBase *pParent) {parentAtom = pParent;}; - AtomBase *getParent() { return parentAtom;}; + void SetParent(AtomBase *pParent) {parentAtom = pParent;}; + AtomBase *GetParent() { return parentAtom;}; void Read(uint64 *value); void Read(uint32 *value); @@ -154,10 +154,10 @@ public: virtual ~FullAtom(); virtual void OnProcessMetaData(); - uint8 getVersion() {return Version;}; - uint8 getFlags1() {return Flags1;}; - uint8 getFlags2() {return Flags2;}; - uint8 getFlags3() {return Flags3;}; + uint8 GetVersion() {return Version;}; + uint8 GetFlags1() {return Flags1;}; + uint8 GetFlags2() {return Flags2;}; + uint8 GetFlags3() {return Flags3;}; private: uint8 Version; @@ -202,6 +202,6 @@ public: virtual void OnChildProcessingComplete() {}; }; -extern AtomBase *getAtom(BPositionIO *pStream); +extern AtomBase *GetAtom(BPositionIO *pStream); #endif // _MP4_ATOM_H diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp index 0fb7f96359..c26f5cd859 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp @@ -33,7 +33,7 @@ #include -extern AtomBase *getAtom(BPositionIO *pStream); +extern AtomBase *GetAtom(BPositionIO *pStream); MP4FileReader::MP4FileReader(BPositionIO *pStream) @@ -63,13 +63,11 @@ MP4FileReader::IsEndOfData(off_t pPosition) AtomBase* aAtomBase; // check all mdat atoms to make sure pPosition is within one of them - - for (uint32 index=0;indexgetAtomSize() > 8)) { + if ((aAtomBase) && (aAtomBase->GetAtomSize() > 8)) { MDATAtom *aMDATAtom = dynamic_cast(aAtomBase); - if (pPosition >= aMDATAtom->getAtomOffset() && pPosition <= aMDATAtom->getEOF()) { -// printf("IsEndOfData %Ld,%Ld,%Ld\n",pPosition,aMDATAtom->getAtomOffset(),aMDATAtom->getEOF()); + if (pPosition >= aMDATAtom->GetAtomOffset() && pPosition <= aMDATAtom->GetEOF()) { return false; } } @@ -143,9 +141,33 @@ MP4FileReader::CountChildAtoms(uint32 patomType) return count; } +TRAKAtom * +MP4FileReader::GetTrack(uint32 streamIndex) +{ + if (tracks[streamIndex] == NULL) { + AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); + if (aAtomBase) { + tracks[streamIndex] = (dynamic_cast(aAtomBase)); + } + } + + if (tracks[streamIndex] != NULL) { + return tracks[streamIndex]; + } + + #ifdef DEBUG + char msg[100]; sprintf(msg, "Bad Stream Index %ld\n", streamIndex); + DEBUGGER(msg); + #endif + + TRESPASS(); + + return NULL; // Never to happen +} + MVHDAtom* -MP4FileReader::getMVHDAtom() +MP4FileReader::GetMVHDAtom() { AtomBase *aAtomBase; @@ -159,46 +181,22 @@ MP4FileReader::getMVHDAtom() } -void -MP4FileReader::BuildSuperIndex() -{ - AtomBase *aAtomBase; - - for (uint32 stream=0;stream(aAtomBase); - for (uint32 chunkid=1;chunkid<=aTrakAtom->getTotalChunks();chunkid++) { - theChunkSuperIndex.AddChunkIndex(stream,chunkid,aTrakAtom->getOffsetForChunk(chunkid)); - } - } - } - - // Add end of file to index - aAtomBase = GetChildAtom(uint32('mdat'),0); - if (aAtomBase) { - MDATAtom *aMdatAtom = dynamic_cast(aAtomBase); - theChunkSuperIndex.AddChunkIndex(0,0,aMdatAtom->getEOF()); - } -} - - uint32 -MP4FileReader::getMovieTimeScale() +MP4FileReader::GetMovieTimeScale() { - return getMVHDAtom()->getTimeScale(); + return GetMVHDAtom()->GetTimeScale(); } bigtime_t -MP4FileReader::getMovieDuration() +MP4FileReader::GetMovieDuration() { - return bigtime_t((getMVHDAtom()->getDuration() * 1000000.0) / getMovieTimeScale()); + return bigtime_t((GetMVHDAtom()->GetDuration() * 1000000.0) / GetMovieTimeScale()); } uint32 -MP4FileReader::getStreamCount() +MP4FileReader::GetStreamCount() { // count the number of tracks in the file return CountChildAtoms(uint32('trak')); @@ -206,59 +204,54 @@ MP4FileReader::getStreamCount() bigtime_t -MP4FileReader::getVideoDuration(uint32 streamIndex) +MP4FileReader::GetVideoDuration(uint32 streamIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); + if (IsVideo(streamIndex)) { + return GetTrack(streamIndex)->Duration(1); + } + + return 0; +} - if (aAtomBase && dynamic_cast(aAtomBase)->IsVideo()) - return dynamic_cast(aAtomBase)->Duration(1); + +bigtime_t +MP4FileReader::GetAudioDuration(uint32 streamIndex) +{ + if (IsAudio(streamIndex)) { + return GetTrack(streamIndex)->Duration(1); + } return 0; } bigtime_t -MP4FileReader::getAudioDuration(uint32 streamIndex) +MP4FileReader::GetMaxDuration() { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - - if (aAtomBase && dynamic_cast(aAtomBase)->IsAudio()) - return dynamic_cast(aAtomBase)->Duration(1); - - return 0; -} - - -bigtime_t -MP4FileReader::getMaxDuration() -{ - AtomBase *aAtomBase; int32 videoIndex = -1; int32 audioIndex = -1; // find the active video and audio tracks - for (uint32 i = 0; i < getStreamCount(); i++) { - aAtomBase = GetChildAtom(uint32('trak'), i); - - if ((aAtomBase) && (dynamic_cast(aAtomBase)->IsActive())) { - if (dynamic_cast(aAtomBase)->IsAudio()) { + for (uint32 i = 0; i < GetStreamCount(); i++) { + if (GetTrack(i)->IsActive()) { + if (GetTrack(i)->IsAudio()) { audioIndex = int32(i); } - if (dynamic_cast(aAtomBase)->IsVideo()) { + if (GetTrack(i)->IsVideo()) { videoIndex = int32(i); } } } if (videoIndex >= 0 && audioIndex >= 0) { - return max_c(getVideoDuration(videoIndex), - getAudioDuration(audioIndex)); + return max_c(GetVideoDuration(videoIndex), + GetAudioDuration(audioIndex)); } if (videoIndex < 0 && audioIndex >= 0) { - return getAudioDuration(audioIndex); + return GetAudioDuration(audioIndex); } if (videoIndex >= 0 && audioIndex < 0) { - return getVideoDuration(videoIndex); + return GetVideoDuration(videoIndex); } return 0; @@ -266,24 +259,17 @@ MP4FileReader::getMaxDuration() uint32 -MP4FileReader::getFrameCount(uint32 streamIndex) +MP4FileReader::GetFrameCount(uint32 streamIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - - if (aAtomBase) { - return dynamic_cast(aAtomBase)->FrameCount(); - } - - return 1; + return GetTrack(streamIndex)->FrameCount(); } uint32 -MP4FileReader::getAudioChunkCount(uint32 streamIndex) +MP4FileReader::GetAudioChunkCount(uint32 streamIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - - if (aAtomBase && dynamic_cast(aAtomBase)->IsAudio()) - return dynamic_cast(aAtomBase)->getTotalChunks(); + if (IsAudio(streamIndex)) { + return GetTrack(streamIndex)->GetTotalChunks(); + } return 0; } @@ -291,131 +277,102 @@ MP4FileReader::getAudioChunkCount(uint32 streamIndex) bool MP4FileReader::IsVideo(uint32 streamIndex) { - // Look for a 'trak' with a vmhd atom - - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - if (aAtomBase) - return dynamic_cast(aAtomBase)->IsVideo(); - - // No track - return false; + return GetTrack(streamIndex)->IsVideo(); } bool MP4FileReader::IsAudio(uint32 streamIndex) { - // Look for a 'trak' with a smhd atom - - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - - if (aAtomBase) - return dynamic_cast(aAtomBase)->IsAudio(); - - // No track - return false; + return GetTrack(streamIndex)->IsAudio(); } uint32 -MP4FileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID) +MP4FileReader::GetFirstFrameInChunk(uint32 streamIndex, uint32 pChunkIndex) { - // Find Track - AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - - return aTrakAtom->getFirstSampleInChunk(pChunkID); - } - - return 0; + return GetTrack(streamIndex)->GetFirstSampleInChunk(pChunkIndex); } uint32 -MP4FileReader::getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo) +MP4FileReader::GetNoFramesInChunk(uint32 streamIndex, uint32 pChunkIndex) { - // Find Track - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); - if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - uint32 ChunkNo = 1; + return GetTrack(streamIndex)->GetNoSamplesInChunk(pChunkIndex); +} - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - - uint32 OffsetInChunk; - ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); - - return aTrakAtom->getNoSamplesInChunk(ChunkNo); - } - - return 0; +uint32 +MP4FileReader::GetChunkForFrame(uint32 streamIndex, uint32 pFrameNo) { + uint32 OffsetInChunk; + return GetTrack(streamIndex)->GetChunkForSample(pFrameNo, &OffsetInChunk); } uint64 -MP4FileReader::getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo) +MP4FileReader::GetOffsetForFrame(uint32 streamIndex, uint32 pFrameNo) { - // Find Track - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); - if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); + TRAKAtom *aTrakAtom = GetTrack(streamIndex); + + if (pFrameNo < aTrakAtom->FrameCount()) { + // Get time for Frame + bigtime_t Time = aTrakAtom->GetTimeForFrame(pFrameNo); + + // Get Sample for Time + uint32 SampleNo = aTrakAtom->GetSampleForTime(Time); + + // Get Chunk For Sample and the offset for the frame within that chunk + uint32 OffsetInChunk; + uint32 ChunkIndex = aTrakAtom->GetChunkForSample(SampleNo, &OffsetInChunk); + // Get Offset For Chunk + uint64 OffsetNo = aTrakAtom->GetOffsetForChunk(ChunkIndex); - if (pFrameNo < aTrakAtom->FrameCount()) { - // Get time for Frame - bigtime_t Time = aTrakAtom->getTimeForFrame(pFrameNo); - - // Get Sample for Time - uint32 SampleNo = aTrakAtom->getSampleForTime(Time); - - // Get Chunk For Sample and the offset for the frame within that chunk - uint32 OffsetInChunk; - uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); - // Get Offset For Chunk - uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo); - - if (ChunkNo != 0) { - uint32 SizeForSample; - // Adjust the Offset for the Offset in the chunk - if (aTrakAtom->IsSingleSampleSize()) { - SizeForSample = aTrakAtom->getSizeForSample(SampleNo); - OffsetNo = OffsetNo + (OffsetInChunk * SizeForSample); - } else { - // This is bad news performance wise - for (uint32 i=1;i<=OffsetInChunk;i++) { - SizeForSample = aTrakAtom->getSizeForSample(SampleNo-i); - OffsetNo = OffsetNo + SizeForSample; - } + if (ChunkIndex != 0) { + uint32 SizeForSample; + // Adjust the Offset for the Offset in the chunk + if (aTrakAtom->IsSingleSampleSize()) { + SizeForSample = aTrakAtom->GetSizeForSample(SampleNo); + OffsetNo = OffsetNo + (OffsetInChunk * SizeForSample); + } else { + // This is bad news performance wise + for (uint32 i=1;i<=OffsetInChunk;i++) { + SizeForSample = aTrakAtom->GetSizeForSample(SampleNo-i); + OffsetNo = OffsetNo + SizeForSample; } } - -// printf("frame %ld, time %Ld, sample %ld, Chunk %ld, OffsetInChunk %ld, Offset %Ld\n",pFrameNo, Time, SampleNo, ChunkNo, OffsetInChunk, OffsetNo); - - return OffsetNo; } + +// printf("frame %ld, time %Ld, sample %ld, Chunk %ld, OffsetInChunk %ld, Offset %Ld\n",pFrameNo, Time, SampleNo, ChunkNo, OffsetInChunk, OffsetNo); + + return OffsetNo; } return 0; } +uint64 +MP4FileReader::GetOffsetForChunk(uint32 streamIndex, uint32 pChunkIndex) +{ + return GetTrack(streamIndex)->GetOffsetForChunk(pChunkIndex); +} + status_t MP4FileReader::ParseFile() { AtomBase *aChild; while (IsEndOfFile() == false) { - aChild = getAtom(theStream); + aChild = GetAtom(theStream); if (AddChild(aChild)) { aChild->ProcessMetaData(); } } +#ifdef DEBUG // Debug info for (uint32 i=0;iDisplayAtoms(); } - - BuildSuperIndex(); +#endif return B_OK; } @@ -424,7 +381,7 @@ MP4FileReader::ParseFile() const mp4_main_header* MP4FileReader::MovMainHeader() { - // Fill In theMainHeader +// Fill In theMainHeader // uint32 micro_sec_per_frame; // uint32 max_bytes_per_sec; // uint32 padding_granularity; @@ -438,7 +395,7 @@ MP4FileReader::MovMainHeader() uint32 videoStream = 0; - theMainHeader.streams = getStreamCount(); + theMainHeader.streams = GetStreamCount(); theMainHeader.flags = 0; theMainHeader.initial_frames = 0; @@ -458,7 +415,7 @@ MP4FileReader::MovMainHeader() } else { theMainHeader.width = VideoFormat(videoStream)->width; theMainHeader.height = VideoFormat(videoStream)->height; - theMainHeader.total_frames = getFrameCount(videoStream); + theMainHeader.total_frames = GetFrameCount(videoStream); theMainHeader.suggested_buffer_size = theMainHeader.width * theMainHeader.height * VideoFormat(videoStream)->bit_count / 8; theMainHeader.micro_sec_per_frame = uint32(1000000.0 / VideoFormat(videoStream)->FrameRate); } @@ -484,7 +441,7 @@ MP4FileReader::AudioFormat(uint32 streamIndex, size_t *size) STSDAtom *aSTSDAtom = dynamic_cast(aAtomBase); // Fill in the AudioMetaData structure - AudioDescription aAudioDescription = aSTSDAtom->getAsAudio(); + AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio(); theAudio.compression = aAudioDescription.codecid; theAudio.codecSubType = aAudioDescription.codecSubType; @@ -498,7 +455,7 @@ MP4FileReader::AudioFormat(uint32 streamIndex, size_t *size) theAudio.SampleSize = aAudioDescription.theAudioSampleEntry.SampleSize; } - theAudio.SampleRate = aAudioDescription.theAudioSampleEntry.SampleRate / 65536; // Convert from fixed point decimal to float + theAudio.SampleRate = aAudioDescription.theAudioSampleEntry.SampleRate; theAudio.FrameSize = aAudioDescription.FrameSize; if (aAudioDescription.BufferSize == 0) { theAudio.BufferSize = uint32((theAudio.SampleSize * theAudio.NoOfChannels * theAudio.FrameSize) / 8); @@ -531,7 +488,7 @@ MP4FileReader::VideoFormat(uint32 streamIndex) aAtomBase = aTrakAtom->GetChildAtom(uint32('stsd'),0); if (aAtomBase) { STSDAtom *aSTSDAtom = dynamic_cast(aAtomBase); - VideoDescription aVideoDescription = aSTSDAtom->getAsVideo(); + VideoDescription aVideoDescription = aSTSDAtom->GetAsVideo(); theVideo.compression = aVideoDescription.codecid; theVideo.codecSubType = aVideoDescription.codecSubType; @@ -553,7 +510,7 @@ MP4FileReader::VideoFormat(uint32 streamIndex) if (aAtomBase) { STTSAtom *aSTTSAtom = dynamic_cast(aAtomBase); - theVideo.FrameRate = ((aSTTSAtom->getSUMCounts() * 1000000.0) / aTrakAtom->Duration(1)); + theVideo.FrameRate = ((aSTTSAtom->GetSUMCounts() * 1000000.0) / aTrakAtom->Duration(1)); return &theVideo; } @@ -578,13 +535,13 @@ MP4FileReader::StreamFormat(uint32 streamIndex) if (IsVideo(streamIndex)) { theStreamHeader.rate = uint32(1000000.0*VideoFormat(streamIndex)->FrameRate); theStreamHeader.scale = 1000000L; - theStreamHeader.length = getFrameCount(streamIndex); + theStreamHeader.length = GetFrameCount(streamIndex); } if (IsAudio(streamIndex)) { theStreamHeader.rate = uint32(AudioFormat(streamIndex)->SampleRate); theStreamHeader.scale = 1; - theStreamHeader.length = getFrameCount(streamIndex); + theStreamHeader.length = GetFrameCount(streamIndex); theStreamHeader.sample_size = AudioFormat(streamIndex)->SampleSize; theStreamHeader.suggested_buffer_size = AudioFormat(streamIndex)->BufferSize; } @@ -594,50 +551,140 @@ MP4FileReader::StreamFormat(uint32 streamIndex) uint32 -MP4FileReader::getChunkSize(uint32 streamIndex, uint32 pFrameNo) +MP4FileReader::GetFrameSize(uint32 streamIndex, uint32 pFrameNo) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); - if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - - if (pFrameNo < aTrakAtom->FrameCount()) { - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - return aTrakAtom->getSizeForSample(SampleNo); - } + if (pFrameNo < GetTrack(streamIndex)->FrameCount()) { + uint32 SampleNo = GetTrack(streamIndex)->GetSampleForFrame(pFrameNo); + return GetTrack(streamIndex)->GetSizeForSample(SampleNo); } return 0; } +bool +MP4FileReader::isValidFrame(uint32 streamIndex, uint32 pFrameNo) { + return (pFrameNo < GetTrack(streamIndex)->FrameCount()); +} + +bool +MP4FileReader::isValidChunkIndex(uint32 streamIndex, uint32 pChunkIndex) { + return (pChunkIndex > 0 && pChunkIndex <= GetTrack(streamIndex)->ChunkCount()); +} + + +uint32 +MP4FileReader::GetChunkSize(uint32 streamIndex, uint32 pChunkIndex) +{ + return GetTrack(streamIndex)->GetChunkSize(pChunkIndex); +} + bool MP4FileReader::IsKeyFrame(uint32 streamIndex, uint32 pFrameNo) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); - if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - - return aTrakAtom->IsSyncSample(pFrameNo); + if (IsAudio(streamIndex)) { + return true; } + + return GetTrack(streamIndex)->IsSyncSample(pFrameNo); +} - return false; +bigtime_t +MP4FileReader::GetTimeForFrame(uint32 streamIndex, uint32 pFrameNo) { + // Calculate PTS + return GetTrack(streamIndex)->GetTimeForFrame(pFrameNo); +} + + +uint32 +MP4FileReader::GetFrameForTime(uint32 streamIndex, bigtime_t time) { + return GetTrack(streamIndex)->GetFrameForTime(time); +} + + +uint32 +MP4FileReader::GetFrameForSample(uint32 streamIndex, uint32 sample) { + if (IsVideo(streamIndex)) { + return sample; // frame = sample for video + } + + if (IsAudio(streamIndex)) { + bigtime_t time = bigtime_t((sample * 1000000.0) / GetTrack(streamIndex)->GetSampleRate()); + return GetTrack(streamIndex)->GetFrameForTime(time); + } + + return 0; +} + + +uint32 +MP4FileReader::GetSampleForTime(uint32 streamIndex, bigtime_t time) { + return GetTrack(streamIndex)->GetSampleForTime(time); +} + + +uint32 +MP4FileReader::GetTimeForSample(uint32 streamIndex, uint32 sample) { + return GetTimeForFrame(streamIndex, GetFrameForSample(streamIndex, sample)); } bool -MP4FileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, - off_t *start, uint32 *size, bool *keyframe) -{ - *start = getOffsetForFrame(streamIndex, pFrameNo); - *size = getChunkSize(streamIndex, pFrameNo); +MP4FileReader::GetBufferForChunk(uint32 streamIndex, uint32 pChunkIndex, off_t *start, uint32 *size, bool *keyframe, bigtime_t *time, uint32 *framesInBuffer) { + + if (isValidChunkIndex(streamIndex, pChunkIndex) == false) { + *start = 0; + *size = 0; + *keyframe = false; + *time = 0; + *framesInBuffer = 0; + return false; + } + + *start = GetOffsetForChunk(streamIndex, pChunkIndex); + *size = GetChunkSize(streamIndex, pChunkIndex); + + uint32 frameNo = GetFirstFrameInChunk(streamIndex, pChunkIndex); + + if ((*start > 0) && (*size > 0)) { + *keyframe = IsKeyFrame(streamIndex, frameNo); + } + + *framesInBuffer = GetNoFramesInChunk(streamIndex, pChunkIndex); + *time = GetTimeForFrame(streamIndex, frameNo); + + if (IsEndOfFile(*start + *size) || IsEndOfData(*start + *size)) { + return false; + } + + return *start > 0 && *size > 0; +} + + +bool +MP4FileReader::GetBufferForFrame(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe, bigtime_t *time, uint32 *framesInBuffer) { + // Get the offset for a given frame and the size of the remaining bytes in the chunk + // framesInBuffer is how many frames there are in the buffer. + + if (isValidFrame(streamIndex, pFrameNo) == false) { + *start = 0; + *size = 0; + *keyframe = false; + *time = 0; + *framesInBuffer = 0; + return false; + } + + *start = GetOffsetForFrame(streamIndex, pFrameNo); + *size = GetFrameSize(streamIndex, pFrameNo); if ((*start > 0) && (*size > 0)) { *keyframe = IsKeyFrame(streamIndex, pFrameNo); } -// printf("frame %ld start %Ld, size %ld, eof %s, eod %s\n",pFrameNo,*start,*size, IsEndOfFile(*start + *size) ? "true" : "false", IsEndOfData(*start + *size) ? "true" : "false"); - - // TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it. + *framesInBuffer = 1; + *time = GetTimeForFrame(streamIndex, pFrameNo); + if (IsEndOfFile(*start + *size) || IsEndOfData(*start + *size)) { return false; } @@ -649,12 +696,12 @@ MP4FileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, bool MP4FileReader::IsActive(uint32 streamIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); + // Don't use helper method streamIndex is likely invalid + AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); if (aAtomBase) { - TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - return aTrakAtom->IsActive(); + return dynamic_cast(aAtomBase)->IsActive(); } - + return false; } @@ -663,7 +710,7 @@ MP4FileReader::IsActive(uint32 streamIndex) bool MP4FileReader::IsSupported(BPositionIO *source) { - AtomBase *aAtom = getAtom(source); + AtomBase *aAtom = GetAtom(source); if (aAtom) { if (dynamic_cast(aAtom)) { aAtom->ProcessMetaData(); diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h index a79823c51b..2d31fff804 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h @@ -31,7 +31,6 @@ #include #include "MP4Parser.h" -#include "ChunkSuperIndex.h" // MP4 file reader class MP4FileReader { @@ -45,7 +44,9 @@ private: AtomBase *GetChildAtom(uint32 patomType, uint32 offset=0); uint32 CountChildAtoms(uint32 patomType); - uint32 getMovieTimeScale(); + TRAKAtom *GetTrack(uint32 streamIndex); + + uint32 GetMovieTimeScale(); // Add a atom to the children array (return false on failure) bool AddChild(AtomBase *pChildAtom); @@ -56,17 +57,14 @@ private: mp4_main_header theMainHeader; MVHDAtom *theMVHDAtom; - - ChunkSuperIndex theChunkSuperIndex; + std::map > tracks; - void BuildSuperIndex(); - public: MP4FileReader(BPositionIO *pStream); virtual ~MP4FileReader(); // getter for MVHDAtom - MVHDAtom *getMVHDAtom(); + MVHDAtom *GetMVHDAtom(); bool IsEndOfFile(off_t pPosition); bool IsEndOfFile(); @@ -76,40 +74,56 @@ public: static bool IsSupported(BPositionIO *source); // How many tracks in file - uint32 getStreamCount(); + uint32 GetStreamCount(); // Duration defined by the movie header - bigtime_t getMovieDuration(); + bigtime_t GetMovieDuration(); // The first video track duration indexed by streamIndex - bigtime_t getVideoDuration(uint32 streamIndex); + bigtime_t GetVideoDuration(uint32 streamIndex); // the first audio track duration indexed by streamIndex - bigtime_t getAudioDuration(uint32 streamIndex); + bigtime_t GetAudioDuration(uint32 streamIndex); // the max of all active audio or video durations - bigtime_t getMaxDuration(); + bigtime_t GetMaxDuration(); // The no of frames in the video track indexed by streamIndex - uint32 getFrameCount(uint32 streamIndex); + uint32 GetFrameCount(uint32 streamIndex); // The no of chunks in the audio track indexed by streamIndex - uint32 getAudioChunkCount(uint32 streamIndex); + uint32 GetAudioChunkCount(uint32 streamIndex); // Is stream (track) a video track bool IsVideo(uint32 streamIndex); // Is stream (track) a audio track bool IsAudio(uint32 streamIndex); - uint32 getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo); - uint32 getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID); + // Frame functions + uint64 GetOffsetForFrame(uint32 streamIndex, uint32 pFrameNo); + uint32 GetChunkForFrame(uint32 streamIndex, uint32 pFrameNo); + uint32 GetFrameSize(uint32 streamIndex, uint32 pFrameNo); - uint64 getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo); - uint32 getChunkSize(uint32 streamIndex, uint32 pFrameNo); + // Chunk functions + uint64 GetOffsetForChunk(uint32 streamIndex, uint32 pChunkIndex); + uint32 GetFirstFrameInChunk(uint32 streamIndex, uint32 pChunkIndex); + uint32 GetChunkSize(uint32 streamIndex, uint32 pChunkIndex); + uint32 GetNoFramesInChunk(uint32 streamIndex, uint32 pChunkIndex); + + bool isValidChunkIndex(uint32 streamIndex, uint32 pChunkIndex); + bool isValidFrame(uint32 streamIndex, uint32 pFrameNo); bool IsKeyFrame(uint32 streamIndex, uint32 pFrameNo); + bigtime_t GetTimeForFrame(uint32 streamIndex, uint32 pFrameNo); + uint32 GetFrameForTime(uint32 streamIndex, bigtime_t time); + uint32 GetFrameForSample(uint32 streamIndex, uint32 sample); + + uint32 GetSampleForTime(uint32 streamIndex, bigtime_t time); + uint32 GetTimeForSample(uint32 streamIndex, uint32 sample); + status_t ParseFile(); BPositionIO *Source() {return theStream;}; bool IsActive(uint32 streamIndex); - bool GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe); + bool GetBufferForChunk(uint32 streamIndex, uint32 pChunkIndex, off_t *start, uint32 *size, bool *keyframe, bigtime_t *time, uint32 *framesInBuffer); + bool GetBufferForFrame(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe, bigtime_t *time, uint32 *framesInBuffer); // Return all Audio Meta Data const AudioMetaData *AudioFormat(uint32 streamIndex, size_t *size = 0); diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp index b285e8abcf..2843e472f6 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp @@ -28,16 +28,13 @@ #include #include -#ifdef __HAIKU__ -#include -#else #include -#endif #include "MP4Parser.h" +#include "BitParser.h" //static -AtomBase *getAtom(BPositionIO *pStream) +AtomBase *GetAtom(BPositionIO *pStream) { uint32 aAtomType; uint32 aAtomSize; @@ -213,7 +210,7 @@ AtomBase *getAtom(BPositionIO *pStream) } -MOOVAtom::MOOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +MOOVAtom::MOOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { theMVHDAtom = NULL; } @@ -232,7 +229,7 @@ char *MOOVAtom::OnGetAtomName() return "MPEG-4 Movie"; } -CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { theUncompressedStream = NULL; } @@ -260,17 +257,16 @@ void CMOVAtom::OnProcessMetaData() uint64 descBytesLeft; uint32 Size; - descBytesLeft = getAtomSize(); + descBytesLeft = GetAtomSize(); // Check for Compression Type while (descBytesLeft > 0) { - AtomBase *aAtomBase = getAtom(theStream); + AtomBase *aAtomBase = GetAtom(theStream); aAtomBase->OnProcessMetaData(); - printf("%s [%Ld]\n",aAtomBase->getAtomName(),aAtomBase->getAtomSize()); - if (aAtomBase->getAtomSize() > 0) { - descBytesLeft = descBytesLeft - aAtomBase->getAtomSize(); + if (aAtomBase->GetAtomSize() > 0) { + descBytesLeft = descBytesLeft - aAtomBase->GetAtomSize(); } else { printf("Invalid Atom found when reading Compressed Headers\n"); descBytesLeft = 0; @@ -278,7 +274,7 @@ void CMOVAtom::OnProcessMetaData() if (dynamic_cast(aAtomBase)) { // DCOM atom - compressionID = dynamic_cast(aAtomBase)->getCompressionID(); + compressionID = dynamic_cast(aAtomBase)->GetCompressionID(); delete aAtomBase; } else { if (dynamic_cast(aAtomBase)) { @@ -291,12 +287,12 @@ void CMOVAtom::OnProcessMetaData() // Decompress data if (compressionID == 'zlib') { - Size = aCMVDAtom->getUncompressedSize(); + 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()); + 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 "); @@ -345,7 +341,7 @@ char *CMOVAtom::OnGetAtomName() return "Compressed MPEG-4 Movie"; } -DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -363,7 +359,7 @@ char *DCOMAtom::OnGetAtomName() return "Decompression Atom"; } -CMVDAtom::CMVDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +CMVDAtom::CMVDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { Buffer = NULL; UncompressedSize = 0; @@ -382,7 +378,7 @@ void CMVDAtom::OnProcessMetaData() Read(&UncompressedSize); if (UncompressedSize > 0) { - BufferSize = getBytesRemaining(); + BufferSize = GetBytesRemaining(); Buffer = (uint8 *)(malloc(BufferSize)); Read(Buffer,BufferSize); } @@ -393,7 +389,7 @@ char *CMVDAtom::OnGetAtomName() return "Compressed Movie Data"; } -MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -405,7 +401,7 @@ void MVHDAtom::OnProcessMetaData() { FullAtom::OnProcessMetaData(); - if (getVersion() == 0) { + if (GetVersion() == 0) { mvhdV0 aHeader; Read(&aHeader.CreationTime); @@ -435,7 +431,7 @@ void MVHDAtom::OnProcessMetaData() theHeader.NextTrackID = aHeader.NextTrackID; } - if (getVersion() == 1) { + if (GetVersion() == 1) { // Read direct into V1 Header Read(&theHeader.CreationTime); Read(&theHeader.ModificationTime); @@ -461,7 +457,7 @@ char *MVHDAtom::OnGetAtomName() return "MPEG-4 Movie Header"; } -MVHDAtom *MOOVAtom::getMVHDAtom() +MVHDAtom *MOOVAtom::GetMVHDAtom() { AtomBase *aAtomBase; @@ -474,7 +470,7 @@ AtomBase *aAtomBase; return theMVHDAtom; } -STTSAtom::STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STTSAtom::STTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; SUMDurations = 0; @@ -497,8 +493,6 @@ TimeToSample *aTimeToSample; ReadArrayHeader(&theHeader); -// printf("STTS:: Entries %ld\n",theHeader.NoEntries); - for (uint32 i=0;iDuration * theTimeToSampleArray[i]->Count); SUMCounts += theTimeToSampleArray[i]->Count; - -// printf("(%ld,%ld)",aTimeToSample->Count,aTimeToSample->Duration); - } -// printf("\n"); } char *STTSAtom::OnGetAtomName() @@ -520,7 +510,7 @@ char *STTSAtom::OnGetAtomName() return "Time to Sample Atom"; } -uint32 STTSAtom::getSampleForTime(bigtime_t pTime) +uint32 STTSAtom::GetSampleForTime(bigtime_t pTime) { // Sample for time is this calc, how does STTS help us? return uint32((pTime * FrameRate + 50) / 1000000.0); @@ -541,13 +531,13 @@ uint32 STTSAtom::getSampleForTime(bigtime_t pTime) return 0; */ } -uint32 STTSAtom::getSampleForFrame(uint32 pFrame) +uint32 STTSAtom::GetSampleForFrame(uint32 pFrame) { - // Convert frame to time and call getSampleForTime() + // Convert frame to time and call GetSampleForTime() return pFrame; } -CTTSAtom::CTTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +CTTSAtom::CTTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; } @@ -583,7 +573,7 @@ char *CTTSAtom::OnGetAtomName() return "Composition Time to Sample Atom"; } -STSCAtom::STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STSCAtom::STSCAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; } @@ -606,8 +596,6 @@ SampleToChunk *aSampleToChunk; uint32 TotalPrevSamples = 0; -// printf("STSC:: Entries %ld\n",theHeader.NoEntries); - for (uint32 i=0;iTotalPrevSamples = 0; } -// printf("(%ld,%ld)",aSampleToChunk->SamplesPerChunk, aSampleToChunk->TotalPrevSamples); - - theSampleToChunkArray[i] = aSampleToChunk; + theSampleToChunkArray.push_back(aSampleToChunk); } -// printf("\n"); } char *STSCAtom::OnGetAtomName() @@ -634,7 +619,7 @@ char *STSCAtom::OnGetAtomName() return "Sample to Chunk Atom"; } -uint32 STSCAtom::getNoSamplesInChunk(uint32 pChunkID) +uint32 STSCAtom::GetNoSamplesInChunk(uint32 pChunkID) { for (uint32 i=0;iFirstChunk > pChunkID) { @@ -645,7 +630,7 @@ uint32 STSCAtom::getNoSamplesInChunk(uint32 pChunkID) return theSampleToChunkArray[theHeader.NoEntries-1]->SamplesPerChunk; } -uint32 STSCAtom::getFirstSampleInChunk(uint32 pChunkID) +uint32 STSCAtom::GetFirstSampleInChunk(uint32 pChunkID) { uint32 Diff; @@ -660,20 +645,18 @@ uint32 Diff; return ((Diff * theSampleToChunkArray[theHeader.NoEntries-1]->SamplesPerChunk) + theSampleToChunkArray[theHeader.NoEntries-1]->TotalPrevSamples); } -uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) +uint32 STSCAtom::GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) { uint32 ChunkID = 0; - uint32 OffsetInChunk = 0; for (int32 i=theHeader.NoEntries-1;i>=0;i--) { if (pSample >= theSampleToChunkArray[i]->TotalPrevSamples) { // Found chunk now calculate offset - ChunkID = (pSample - theSampleToChunkArray[i]->TotalPrevSamples) / theSampleToChunkArray[i]->SamplesPerChunk; - ChunkID += theSampleToChunkArray[i]->FirstChunk; + ChunkID = ((pSample - theSampleToChunkArray[i]->TotalPrevSamples) / theSampleToChunkArray[i]->SamplesPerChunk) + + theSampleToChunkArray[i]->FirstChunk; - OffsetInChunk = (pSample - theSampleToChunkArray[i]->TotalPrevSamples) % theSampleToChunkArray[i]->SamplesPerChunk; + *pOffsetInChunk = (pSample - theSampleToChunkArray[i]->TotalPrevSamples) % theSampleToChunkArray[i]->SamplesPerChunk; - *pOffsetInChunk = OffsetInChunk; return ChunkID; } } @@ -682,7 +665,7 @@ uint32 STSCAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) return theSampleToChunkArray[theHeader.NoEntries-1]->FirstChunk; } -STSSAtom::STSSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STSSAtom::STSSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; } @@ -707,8 +690,9 @@ SyncSample *aSyncSample; aSyncSample = new SyncSample; Read(&aSyncSample->SyncSampleNo); + aSyncSample->SyncSampleNo--; // First frame is 0 for haiku - theSyncSampleArray[i] = aSyncSample; + theSyncSampleArray.push_back(aSyncSample); } } @@ -733,7 +717,7 @@ bool STSSAtom::IsSyncSample(uint32 pSampleNo) return false; } -STSZAtom::STSZAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STSZAtom::STSZAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { SampleCount = 0; } @@ -762,26 +746,30 @@ void STSZAtom::OnProcessMetaData() Read(&aSampleSizePtr->EntrySize); - theSampleSizeArray[i] = aSampleSizePtr; + theSampleSizeArray.push_back(aSampleSizePtr); } } } char *STSZAtom::OnGetAtomName() { - printf("SS=%ld Count=%ld ",SampleSize,SampleCount); return "Sample Size Atom"; } -uint32 STSZAtom::getSizeForSample(uint32 pSampleNo) +uint32 STSZAtom::GetSizeForSample(uint32 pSampleNo) { if (SampleSize > 0) { // All samples are the same size return SampleSize; } - // Sample Array indexed by SampleNo - return theSampleSizeArray[pSampleNo]->EntrySize; + if (pSampleNo < SampleCount) { + // Sample Array indexed by SampleNo + return theSampleSizeArray[pSampleNo]->EntrySize; + } + + printf("SampleNo %ld is outside SampleSize Array\n", pSampleNo); + return 0; } bool STSZAtom::IsSingleSampleSize() @@ -789,7 +777,7 @@ bool STSZAtom::IsSingleSampleSize() return (SampleSize > 0); } -STZ2Atom::STZ2Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STZ2Atom::STZ2Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { SampleCount = 0; } @@ -839,7 +827,7 @@ void STZ2Atom::OnProcessMetaData() break; } - theSampleSizeArray[i] = aSampleSizePtr; + theSampleSizeArray.push_back(aSampleSizePtr); } } @@ -848,7 +836,7 @@ char *STZ2Atom::OnGetAtomName() return "Compressed Sample Size Atom"; } -uint32 STZ2Atom::getSizeForSample(uint32 pSampleNo) +uint32 STZ2Atom::GetSizeForSample(uint32 pSampleNo) { // THIS CODE NEEDS SOME TESTING, never seen a STZ2 atom @@ -883,7 +871,7 @@ bool STZ2Atom::IsSingleSampleSize() return false; } -STCOAtom::STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STCOAtom::STCOAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; } @@ -921,8 +909,6 @@ ChunkToOffset *aChunkToOffset; theChunkToOffsetArray[i] = aChunkToOffset; } - - PRINT(("Chunk to Offset Array has %ld entries\n",theHeader.NoEntries)); } char *STCOAtom::OnGetAtomName() @@ -930,15 +916,15 @@ char *STCOAtom::OnGetAtomName() return "Chunk to Offset Atom"; } -uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID) +uint64 STCOAtom::GetOffsetForChunk(uint32 pChunkIndex) { - // First chunk is first array entry - if ((pChunkID > 0) && (pChunkID <= theHeader.NoEntries)) { - return theChunkToOffsetArray[pChunkID - 1]->Offset; + // Chunk Indexes start at 1 + if ((pChunkIndex > 0) && (pChunkIndex <= theHeader.NoEntries)) { + return theChunkToOffsetArray[pChunkIndex - 1]->Offset; } - #if DEBUG - char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkID, theHeader.NoEntries); + #ifdef DEBUG + char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkIndex, theHeader.NoEntries); DEBUGGER(msg); #endif @@ -946,7 +932,7 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID) return 0LL; } -DecoderConfigAtom::DecoderConfigAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +DecoderConfigAtom::DecoderConfigAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { theDecoderConfig = NULL; DecoderConfigSize = 0; @@ -961,13 +947,13 @@ DecoderConfigAtom::~DecoderConfigAtom() void DecoderConfigAtom::OnProcessMetaData() { - DecoderConfigSize = getBytesRemaining(); + DecoderConfigSize = GetBytesRemaining(); theDecoderConfig = (uint8 *)(malloc(DecoderConfigSize)); Read(theDecoderConfig,DecoderConfigSize); } -uint8 *DecoderConfigAtom::getDecoderConfig() +uint8 *DecoderConfigAtom::GetDecoderConfig() { return theDecoderConfig; } @@ -1020,7 +1006,7 @@ void DecoderConfigAtom::OverrideVideoDescription(VideoDescription *pVideoDescrip } } -ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : DecoderConfigAtom(pStream, pstreamOffset, patomType, patomSize) +ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1063,6 +1049,7 @@ void ESDSAtom::OnOverrideAudioDescription(AudioDescription *pAudioDescription) // decode for aac and check for HE-AAC which uses a framesize of 2048 // also check for MP3 which has an ESDS uint32 offset = 0; + BitParser parser; if (SkipTag(pAudioDescription->theDecoderConfig, 0x03, &offset)) { offset += 3; @@ -1071,64 +1058,64 @@ void ESDSAtom::OnOverrideAudioDescription(AudioDescription *pAudioDescription) } if (SkipTag(pAudioDescription->theDecoderConfig, 0x04, &offset)) { - ESDSType = pAudioDescription->theDecoderConfig[offset]; - StreamType = pAudioDescription->theDecoderConfig[offset+1]/4; - NeededBufferSize = uint32(pAudioDescription->theDecoderConfig[offset+2]) * 256 * 256 + - pAudioDescription->theDecoderConfig[offset+3] * 256 + pAudioDescription->theDecoderConfig[offset+4]; - MaxBitRate = uint32(pAudioDescription->theDecoderConfig[offset+5]) * 256 * 256 * 256 + - pAudioDescription->theDecoderConfig[offset+6] * 256 * 256 + - pAudioDescription->theDecoderConfig[offset+7] * 256 + - pAudioDescription->theDecoderConfig[offset+8]; - AvgBitRate = uint32(pAudioDescription->theDecoderConfig[offset+9]) * 256 * 256 * 256 + - pAudioDescription->theDecoderConfig[offset+10] * 256 * 256 + - pAudioDescription->theDecoderConfig[offset+11] * 256 + - pAudioDescription->theDecoderConfig[offset+12]; - printf("obj type id is %d \n", ESDSType); - printf("stream type is %d\n", StreamType); - printf("Buffer Size is %ld\n", NeededBufferSize); - printf("max Bitrate is %ld\n", MaxBitRate); - printf("avg Bitrate is %ld\n", AvgBitRate); + parser.Init(&pAudioDescription->theDecoderConfig[offset], (pAudioDescription->DecoderConfigSize-offset) * 8); + + ESDSType = parser.GetValue(8); + StreamType = parser.GetValue(6); + parser.Skip(2); + NeededBufferSize = parser.GetValue(24); + MaxBitRate = parser.GetValue(32); + AvgBitRate = parser.GetValue(32); pAudioDescription->BitRate = AvgBitRate; offset+=13; } + // Find Tag 0x05 that describes the audio format SkipTag(pAudioDescription->theDecoderConfig, 0x05, &offset); - uint32 buffer; - uint32 temp; + bool smallFrameSize; + uint32 SampleRate; // remember where the tag 5 starts uint32 extendedAudioConfig = offset; switch (ESDSType) { - case 64: // AAC - // Attempt to read AAC Header - buffer = pAudioDescription->theDecoderConfig[offset]; - buffer = buffer * 256 + pAudioDescription->theDecoderConfig[offset+1] ; - buffer = buffer * 256 + pAudioDescription->theDecoderConfig[offset+2] ; - buffer = buffer * 256 + pAudioDescription->theDecoderConfig[offset+3] ; - - // Bits 0-5 are decoder type - temp = GetBits(buffer,0,5); - theAACHeader.objTypeIndex = temp; - // Bits 6-9 are frequency index - temp = GetBits(buffer,6,3); - theAACHeader.sampleRateIndex = temp; - // Bits 10-12 are channels - temp = GetBits(buffer,10,3); - theAACHeader.totalChannels = temp; - + case 64: // AAC so use AAC Header details to override ESDS values + parser.Init(&pAudioDescription->theDecoderConfig[offset], (pAudioDescription->DecoderConfigSize-offset) * 8); + + // 5 bits are decoder type + theAACHeader.objTypeIndex = parser.GetValue(5); + if (theAACHeader.objTypeIndex == 31) { + theAACHeader.objTypeIndex = 32 + parser.GetValue(6); + } + // 4 bits are frequency index + theAACHeader.sampleRateIndex = parser.GetValue(4); + if (theAACHeader.sampleRateIndex == 15) { + // Direct encoding of SampleRate + SampleRate = parser.GetValue(24); + } else { + SampleRate = aac_sampling_rate[theAACHeader.sampleRateIndex]; + } + + // 4 bits are channels + theAACHeader.totalChannels = parser.GetValue(4); + // 1 bit determines small frame size + smallFrameSize = (parser.GetValue(1) == 1); + if (theAACHeader.objTypeIndex < 3) { pAudioDescription->codecSubType = 'mp4a'; pAudioDescription->FrameSize = 1024; + if (smallFrameSize) { + pAudioDescription->FrameSize = 960; + } } else { pAudioDescription->codecSubType = 'haac'; pAudioDescription->FrameSize = 2048; } - // SampleRate is in 16.16 format - pAudioDescription->theAudioSampleEntry.SampleRate = aac_sampling_rate[theAACHeader.sampleRateIndex] * 65536 ; + // Override STSD + pAudioDescription->theAudioSampleEntry.SampleRate = SampleRate; pAudioDescription->theAudioSampleEntry.ChannelCount = theAACHeader.totalChannels; // Reset decoder Config memory @@ -1153,7 +1140,7 @@ void ESDSAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription) // Nothing to override } -ALACAtom::ALACAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : DecoderConfigAtom(pStream, pstreamOffset, patomType, patomSize) +ALACAtom::ALACAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1182,7 +1169,7 @@ void ALACAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription) // Nothing to override } -WAVEAtom::WAVEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : DecoderConfigAtom(pStream, pstreamOffset, patomType, patomSize) +WAVEAtom::WAVEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1210,7 +1197,7 @@ void WAVEAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription) // Nothing to override } -DAC3Atom::DAC3Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : DecoderConfigAtom(pStream, pstreamOffset, patomType, patomSize) +DAC3Atom::DAC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1239,7 +1226,7 @@ char *DAC3Atom::OnGetAtomName() return "Digital AC3"; } -DEC3Atom::DEC3Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : DecoderConfigAtom(pStream, pstreamOffset, patomType, patomSize) +DEC3Atom::DEC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1269,7 +1256,7 @@ char *DEC3Atom::OnGetAtomName() } -STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +STSDAtom::STSDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { theHeader.NoEntries = 0; theAudioDescription.codecid = 0; @@ -1294,9 +1281,9 @@ STSDAtom::~STSDAtom() } } -uint32 STSDAtom::getMediaHandlerType() +uint32 STSDAtom::GetMediaHandlerType() { - return dynamic_cast(getParent())->getMediaHandlerType(); + return dynamic_cast(GetParent())->GetMediaHandlerType(); } void STSDAtom::ReadDecoderConfig(uint8 **pDecoderConfig, size_t *pDecoderConfigSize, AudioDescription *pAudioDescription, VideoDescription *pVideoDescription) @@ -1307,12 +1294,12 @@ void STSDAtom::ReadDecoderConfig(uint8 **pDecoderConfig, size_t *pDecoderConfigS // to work out how to properly construct the decoder // First make sure we have a something - if (getBytesRemaining() > 0) { + if (GetBytesRemaining() > 0) { // Well something is there so read it as an atom - AtomBase *aAtomBase = getAtom(theStream); + AtomBase *aAtomBase = GetAtom(theStream); aAtomBase->ProcessMetaData(); - printf("%s [%Ld]\n",aAtomBase->getAtomName(),aAtomBase->getAtomSize()); + printf("%s [%Ld]\n",aAtomBase->GetAtomName(),aAtomBase->GetAtomSize()); if (dynamic_cast(aAtomBase)) { // DecoderConfig atom good @@ -1323,7 +1310,7 @@ void STSDAtom::ReadDecoderConfig(uint8 **pDecoderConfig, size_t *pDecoderConfigS delete aAtomBase; } else { // Unknown atom bad - printf("Unknown atom %s\n",aAtomBase->getAtomName()); + printf("Unknown atom %s\n",aAtomBase->GetAtomName()); delete aAtomBase; } } @@ -1339,6 +1326,8 @@ void STSDAtom::ReadSoundDescription() Read(&theAudioDescription.theAudioSampleEntry.reserved); Read(&theAudioDescription.theAudioSampleEntry.SampleRate); + theAudioDescription.theAudioSampleEntry.SampleRate = theAudioDescription.theAudioSampleEntry.SampleRate / 65536; // Convert from fixed point decimal to float + ReadDecoderConfig(&theAudioDescription.theDecoderConfig, &theAudioDescription.DecoderConfigSize, &theAudioDescription, NULL); } @@ -1360,10 +1349,10 @@ void STSDAtom::ReadVideoDescription() // convert from pascal string (first bytes size) to C string (null terminated) uint8 size = (uint8)(theVideoDescription.theVideoSampleEntry.CompressorName[0]); - if (size > 0) { + if (size > 0 && size < 32) { memmove(&theVideoDescription.theVideoSampleEntry.CompressorName[0],&theVideoDescription.theVideoSampleEntry.CompressorName[1],size); theVideoDescription.theVideoSampleEntry.CompressorName[size] = '\0'; - printf("%s\n",theVideoDescription.theVideoSampleEntry.CompressorName); + printf("Compressed using %s\n",theVideoDescription.theVideoSampleEntry.CompressorName); } Read(&theVideoDescription.theVideoSampleEntry.Depth); @@ -1391,7 +1380,7 @@ void STSDAtom::OnProcessMetaData() Read(theSampleEntry.Reserved,6); Read(&theSampleEntry.DataReference); - switch (getMediaHandlerType()) { + switch (GetMediaHandlerType()) { case 'soun': ReadSoundDescription(); theAudioDescription.codecid = codecid; @@ -1407,13 +1396,13 @@ void STSDAtom::OnProcessMetaData() } } -VideoDescription STSDAtom::getAsVideo() +VideoDescription STSDAtom::GetAsVideo() { // Assert IsVideo return theVideoDescription; } -AudioDescription STSDAtom::getAsAudio() +AudioDescription STSDAtom::GetAsAudio() { // Assert IsAudio return theAudioDescription; @@ -1424,7 +1413,7 @@ char *STSDAtom::OnGetAtomName() return "Sample Description Atom"; } -TMCDAtom::TMCDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +TMCDAtom::TMCDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1441,7 +1430,7 @@ char *TMCDAtom::OnGetAtomName() return "TimeCode Atom"; } -WIDEAtom::WIDEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +WIDEAtom::WIDEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1458,7 +1447,7 @@ char *WIDEAtom::OnGetAtomName() return "WIDE Atom"; } -FTYPAtom::FTYPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +FTYPAtom::FTYPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { total_brands = 0; } @@ -1472,7 +1461,7 @@ void FTYPAtom::OnProcessMetaData() Read(&major_brand); Read(&minor_version); - total_brands = getBytesRemaining() / sizeof(uint32); + total_brands = GetBytesRemaining() / sizeof(uint32); if (total_brands > 32) { total_brands = 32; // restrict to 32 @@ -1506,7 +1495,7 @@ bool FTYPAtom::HasBrand(uint32 brand) return false; } -FREEAtom::FREEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +FREEAtom::FREEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1523,7 +1512,7 @@ char *FREEAtom::OnGetAtomName() return "Free Atom"; } -PNOTAtom::PNOTAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +PNOTAtom::PNOTAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1540,7 +1529,7 @@ char *PNOTAtom::OnGetAtomName() return "Preview Atom"; } -SKIPAtom::SKIPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +SKIPAtom::SKIPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1557,7 +1546,7 @@ char *SKIPAtom::OnGetAtomName() return "Skip Atom"; } -MDATAtom::MDATAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +MDATAtom::MDATAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1571,16 +1560,15 @@ void MDATAtom::OnProcessMetaData() char *MDATAtom::OnGetAtomName() { - printf("Offset %lld, Size %lld ",getAtomOffset(),getAtomSize() - 8); return "Media Data Atom"; } -off_t MDATAtom::getEOF() +off_t MDATAtom::GetEOF() { - return getAtomOffset() + getAtomSize() - 8; + return GetAtomOffset() + GetAtomSize() - 8; } -MINFAtom::MINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +MINFAtom::MINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1597,12 +1585,12 @@ char *MINFAtom::OnGetAtomName() return "MPEG-4 Media Information Atom"; } -uint32 MINFAtom::getMediaHandlerType() +uint32 MINFAtom::GetMediaHandlerType() { - return dynamic_cast(getParent())->getMediaHandlerType(); + return dynamic_cast(GetParent())->GetMediaHandlerType(); } -STBLAtom::STBLAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +STBLAtom::STBLAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1619,12 +1607,12 @@ char *STBLAtom::OnGetAtomName() return "MPEG-4 Sample Table Atom"; } -uint32 STBLAtom::getMediaHandlerType() +uint32 STBLAtom::GetMediaHandlerType() { - return dynamic_cast(getParent())->getMediaHandlerType(); + return dynamic_cast(GetParent())->GetMediaHandlerType(); } -DINFAtom::DINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +DINFAtom::DINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1641,7 +1629,7 @@ char *DINFAtom::OnGetAtomName() return "MPEG-4 Data Information Atom"; } -TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1654,7 +1642,7 @@ void TKHDAtom::OnProcessMetaData() FullAtom::OnProcessMetaData(); - if (getVersion() == 0) { + if (GetVersion() == 0) { tkhdV0 aHeaderV0; Read(&aHeaderV0.CreationTime); @@ -1715,7 +1703,7 @@ char *TKHDAtom::OnGetAtomName() return "MPEG-4 Track Header"; } -MDIAAtom::MDIAAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) +MDIAAtom::MDIAAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1732,20 +1720,20 @@ char *MDIAAtom::OnGetAtomName() return "MPEG-4 Media Atom"; } -uint32 MDIAAtom::getMediaHandlerType() +uint32 MDIAAtom::GetMediaHandlerType() { - // get child atom hdlr + // Get child atom hdlr HDLRAtom *aHDLRAtom; aHDLRAtom = dynamic_cast(GetChildAtom(uint32('hdlr'))); if (aHDLRAtom) { - return aHDLRAtom->getMediaHandlerType(); + return aHDLRAtom->GetMediaHandlerType(); } return 0; } -MDHDAtom::MDHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +MDHDAtom::MDHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1757,7 +1745,7 @@ void MDHDAtom::OnProcessMetaData() { FullAtom::OnProcessMetaData(); - if (getVersion() == 0) { + if (GetVersion() == 0) { mdhdV0 aHeader; Read(&aHeader.CreationTime); @@ -1787,17 +1775,17 @@ char *MDHDAtom::OnGetAtomName() return "MPEG-4 Media Header"; } -bigtime_t MDHDAtom::getDuration() +bigtime_t MDHDAtom::GetDuration() { return bigtime_t((theHeader.Duration * 1000000.0) / theHeader.TimeScale); } -uint32 MDHDAtom::getTimeScale() +uint32 MDHDAtom::GetTimeScale() { return theHeader.TimeScale; } -HDLRAtom::HDLRAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +HDLRAtom::HDLRAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { name = NULL; } @@ -1819,9 +1807,9 @@ void HDLRAtom::OnProcessMetaData() Read(&theHeader.Reserved[1]); Read(&theHeader.Reserved[2]); - name = (char *)(malloc(getBytesRemaining())); + name = (char *)(malloc(GetBytesRemaining())); - Read(name,getBytesRemaining()); + Read(name,GetBytesRemaining()); } char *HDLRAtom::OnGetAtomName() @@ -1839,12 +1827,12 @@ bool HDLRAtom::IsAudioHandler() return (theHeader.handler_type == 'soun'); } -uint32 HDLRAtom::getMediaHandlerType() +uint32 HDLRAtom::GetMediaHandlerType() { return theHeader.handler_type; } -VMHDAtom::VMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +VMHDAtom::VMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } @@ -1867,7 +1855,7 @@ char *VMHDAtom::OnGetAtomName() return "MPEG-4 Video Media Header"; } -SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) +SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize) : FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize) { } diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h index 4473b4180b..7a8ef9f7fa 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h @@ -40,23 +40,23 @@ typedef std::map > CompTimeToSamp typedef TimeToSample* TimeToSamplePtr; typedef std::map > TimeToSampleArray; typedef SampleToChunk* SampleToChunkPtr; -typedef std::map > SampleToChunkArray; +typedef std::vector SampleToChunkArray; typedef ChunkToOffset* ChunkToOffsetPtr; typedef std::map > ChunkToOffsetArray; typedef SyncSample* SyncSamplePtr; -typedef std::map > SyncSampleArray; +typedef std::vector SyncSampleArray; typedef SampleSizeEntry* SampleSizePtr; -typedef std::map > SampleSizeArray; +typedef std::vector SampleSizeArray; // Atom class for reading the movie header atom class MVHDAtom : public FullAtom { public: - MVHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MVHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MVHDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getTimeScale() {return theHeader.TimeScale;}; - uint32 getDuration() {return theHeader.Duration;}; + uint32 GetTimeScale() {return theHeader.TimeScale;}; + uint32 GetDuration() {return theHeader.Duration;}; private: mvhdV1 theHeader; }; @@ -64,12 +64,12 @@ private: // Atom class for reading the moov atom class MOOVAtom : public AtomContainer { public: - MOOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MOOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MOOVAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - MVHDAtom *getMVHDAtom(); + MVHDAtom *GetMVHDAtom(); private: MVHDAtom *theMVHDAtom; }; @@ -77,7 +77,7 @@ private: // Atom class for reading the cmov atom class CMOVAtom : public AtomContainer { public: - CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + CMOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~CMOVAtom(); BPositionIO *OnGetStream(); @@ -92,11 +92,11 @@ private: // Atom class for reading the dcom atom class DCOMAtom : public AtomBase { public: - DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + DCOMAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~DCOMAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getCompressionID() {return compressionID;}; + uint32 GetCompressionID() {return compressionID;}; private: uint32 compressionID; }; @@ -104,13 +104,13 @@ private: // Atom class for reading the cmvd atom class CMVDAtom : public AtomBase { public: - CMVDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + 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;}; + uint32 GetUncompressedSize() {return UncompressedSize;}; + uint8 *GetCompressedData() {return Buffer;}; + uint32 GetBufferSize() {return BufferSize;}; private: uint32 UncompressedSize; uint32 BufferSize; @@ -120,7 +120,7 @@ private: // Atom class for reading the ftyp atom class FTYPAtom : public AtomBase { public: - FTYPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + FTYPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~FTYPAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -136,7 +136,7 @@ private: // Atom class for reading the wide atom class WIDEAtom : public AtomBase { public: - WIDEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + WIDEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~WIDEAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -146,7 +146,7 @@ public: // Atom class for reading the free atom class FREEAtom : public AtomBase { public: - FREEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + FREEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~FREEAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -156,7 +156,7 @@ public: // Atom class for reading the preview atom class PNOTAtom : public AtomBase { public: - PNOTAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + PNOTAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~PNOTAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -166,16 +166,16 @@ public: // Atom class for reading the time to sample atom class STTSAtom : public FullAtom { public: - STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STTSAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint64 getSUMCounts() { return SUMCounts; }; - bigtime_t getSUMDurations() { return SUMDurations; }; - uint32 getSampleForTime(bigtime_t pTime); - uint32 getSampleForFrame(uint32 pFrame); - void setFrameRate(float pFrameRate) { FrameRate = pFrameRate; }; + uint64 GetSUMCounts() { return SUMCounts; }; + bigtime_t GetSUMDurations() { return SUMDurations; }; + uint32 GetSampleForTime(bigtime_t pTime); + uint32 GetSampleForFrame(uint32 pFrame); + void SetFrameRate(float pFrameRate) { FrameRate = pFrameRate; }; private: array_header theHeader; @@ -188,7 +188,7 @@ private: // Atom class for reading the composition time to sample atom class CTTSAtom : public FullAtom { public: - CTTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + CTTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~CTTSAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -201,14 +201,14 @@ private: // Atom class for reading the sample to chunk atom class STSCAtom : public FullAtom { public: - STSCAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STSCAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STSCAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk); - uint32 getFirstSampleInChunk(uint32 pChunkID); - uint32 getNoSamplesInChunk(uint32 pChunkID); + uint32 GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk); + uint32 GetFirstSampleInChunk(uint32 pChunkIndex); + uint32 GetNoSamplesInChunk(uint32 pChunkIndex); private: array_header theHeader; SampleToChunkArray theSampleToChunkArray; @@ -217,13 +217,13 @@ private: // Atom class for reading the chunk to offset atom class STCOAtom : public FullAtom { public: - STCOAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STCOAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STCOAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint64 getOffsetForChunk(uint32 pChunkID); - uint32 getTotalChunks() {return theHeader.NoEntries;}; + uint64 GetOffsetForChunk(uint32 pChunkIndex); + uint32 GetTotalChunks() {return theHeader.NoEntries;}; protected: // Read a single chunk offset from Stream @@ -237,7 +237,7 @@ private: // Atom class for reading the sync sample atom class STSSAtom : public FullAtom { public: - STSSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STSSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STSSAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -251,12 +251,12 @@ private: // Atom class for reading the sample size atom class STSZAtom : public FullAtom { public: - STSZAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STSZAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STSZAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getSizeForSample(uint32 pSampleNo); + uint32 GetSizeForSample(uint32 pSampleNo); bool IsSingleSampleSize(); private: uint32 SampleSize; @@ -268,12 +268,12 @@ private: // Atom class for reading the sample size 2 atom class STZ2Atom : public FullAtom { public: - STZ2Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STZ2Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STZ2Atom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getSizeForSample(uint32 pSampleNo); + uint32 GetSizeForSample(uint32 pSampleNo); bool IsSingleSampleSize(); private: uint32 SampleSize; @@ -286,7 +286,7 @@ private: // Atom class for reading the skip atom class SKIPAtom : public AtomBase { public: - SKIPAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + SKIPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~SKIPAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -296,18 +296,18 @@ public: // Atom class for reading the media data atom class MDATAtom : public AtomBase { public: - MDATAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MDATAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MDATAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - off_t getEOF(); + off_t GetEOF(); }; // Subclass for handling special decoder config atoms like ESDS, ALAC, AVCC, AMR // ESDS is actually a FullAtom but others are not :-( class DecoderConfigAtom : public AtomBase { public: - DecoderConfigAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + DecoderConfigAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~DecoderConfigAtom(); virtual void OnProcessMetaData(); virtual char *OnGetAtomName(); @@ -321,8 +321,8 @@ public: virtual void OnOverrideVideoDescription(VideoDescription *pVideoDescription) {} ; bool SkipTag(uint8 *ESDS, uint8 Tag, uint32 *offset); - uint8 *getDecoderConfig(); - size_t getDecoderConfigSize() { return DecoderConfigSize; } ; + uint8 *GetDecoderConfig(); + size_t GetDecoderConfigSize() { return DecoderConfigSize; } ; private: uint8 *theDecoderConfig; size_t DecoderConfigSize; @@ -331,7 +331,7 @@ private: // Atom class for reading the ESDS decoder config atom class ESDSAtom : public DecoderConfigAtom { public: - ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + ESDSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~ESDSAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -349,7 +349,7 @@ private: // Atom class for reading the ALAC decoder config atom class ALACAtom : public DecoderConfigAtom { public: - ALACAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + ALACAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~ALACAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -360,7 +360,7 @@ public: // Atom class for reading the WAVE atom for mp3 decoder config class WAVEAtom : public DecoderConfigAtom { public: - WAVEAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + WAVEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~WAVEAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -371,16 +371,16 @@ public: // Atom class for reading the Sample Description atom class STSDAtom : public FullAtom { public: - STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STSDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STSDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - VideoDescription getAsVideo(); - AudioDescription getAsAudio(); + VideoDescription GetAsVideo(); + AudioDescription GetAsAudio(); private: - uint32 getMediaHandlerType(); + uint32 GetMediaHandlerType(); void ReadDecoderConfig(uint8 **pDecoderConfig, size_t *pDecoderConfigSize, AudioDescription *pAudioDescription, VideoDescription *pVideoDescription); void ReadSoundDescription(); @@ -398,12 +398,12 @@ private: // Atom class for reading the track header atom class TKHDAtom : public FullAtom { public: - TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + TKHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~TKHDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getDuration() {return theHeader.Duration;}; // duration is in the scale of the media + uint32 GetDuration() {return theHeader.Duration;}; // duration is in the scale of the media // Flags3 should contain the following // 0x001 Track enabled @@ -411,7 +411,7 @@ public: // 0x004 Track in Preview // 0x008 Track in Poster - bool IsActive() {return ((getFlags3() && 0x01) || (getFlags3() && 0x0f));}; + bool IsActive() {return ((GetFlags3() && 0x01) || (GetFlags3() && 0x0f));}; private: tkhdV1 theHeader; @@ -421,14 +421,14 @@ private: // Atom class for reading the media header atom class MDHDAtom : public FullAtom { public: - MDHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MDHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MDHDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); // return duration in ms - bigtime_t getDuration(); - uint32 getTimeScale(); + bigtime_t GetDuration(); + uint32 GetTimeScale(); private: mdhdV1 theHeader; @@ -438,7 +438,7 @@ private: // Atom class for reading the video media header atom class VMHDAtom : public FullAtom { public: - VMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + VMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~VMHDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -451,7 +451,7 @@ private: // Atom class for reading the sound media header atom class SMHDAtom : public FullAtom { public: - SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + SMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~SMHDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -462,87 +462,90 @@ private: // Atom class for reading the track atom class TRAKAtom : public AtomContainer { public: - TRAKAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + TRAKAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~TRAKAtom(); void OnProcessMetaData(); char *OnGetAtomName(); void OnChildProcessingComplete(); bigtime_t Duration(uint32 TimeScale); // Return duration of track - bigtime_t Duration() { return Duration(timescale); } - uint32 FrameCount() { return framecount; }; + bigtime_t Duration() { return Duration(timeScale); } + 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 - // GetVideoMetaData() // If this is a video track get the video meta data + // GetAudioMetaData() // If this is a audio track Get the audio meta data + // GetVideoMetaData() // If this is a video track Get the video meta data - bigtime_t getTimeForFrame(uint32 pFrame); - uint32 getSampleForTime(bigtime_t pTime); - uint32 getSampleForFrame(uint32 pFrame); - uint32 getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk); - uint64 getOffsetForChunk(uint32 pChunkID); - uint32 getFirstSampleInChunk(uint32 pChunkID); - uint32 getSizeForSample(uint32 pSample); - uint32 getNoSamplesInChunk(uint32 pChunkID); - uint32 getTotalChunks(); + bigtime_t GetTimeForFrame(uint32 pFrame); + uint32 GetFrameForTime(bigtime_t time); + uint32 GetSampleForTime(bigtime_t pTime); + uint32 GetSampleForFrame(uint32 pFrame); + uint32 GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk); + uint64 GetOffsetForChunk(uint32 pChunkIndex); + uint32 GetFirstSampleInChunk(uint32 pChunkIndex); + uint32 GetSizeForSample(uint32 pSample); + uint32 GetNoSamplesInChunk(uint32 pChunkIndex); + uint32 GetTotalChunks(); + uint32 GetChunkSize(uint32 pChunkIndex); + uint32 ChunkCount(); - float getSampleRate(); - float getFrameRate(); + float GetSampleRate(); + float GetFrameRate(); bool IsSyncSample(uint32 pSampleNo); bool IsSingleSampleSize(); bool IsActive(); - uint32 getBytesPerSample(); + uint32 GetBytesPerSample(); - TKHDAtom *getTKHDAtom(); - MDHDAtom *getMDHDAtom(); + TKHDAtom *GetTKHDAtom(); + MDHDAtom *GetMDHDAtom(); private: TKHDAtom *theTKHDAtom; MDHDAtom *theMDHDAtom; - uint32 framecount; - uint32 bytespersample; - uint32 timescale; + uint32 frameCount; + uint32 bytesPerSample; + uint32 timeScale; }; // Atom class for reading the media container atom class MDIAAtom : public AtomContainer { public: - MDIAAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MDIAAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MDIAAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getMediaHandlerType(); + uint32 GetMediaHandlerType(); }; // Atom class for reading the media information atom class MINFAtom : public AtomContainer { public: - MINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + MINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~MINFAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getMediaHandlerType(); + uint32 GetMediaHandlerType(); }; // Atom class for reading the stbl atom class STBLAtom : public AtomContainer { public: - STBLAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + STBLAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~STBLAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint32 getMediaHandlerType(); + uint32 GetMediaHandlerType(); }; // Atom class for reading the dinf atom class DINFAtom : public AtomContainer { public: - DINFAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + DINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~DINFAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -551,7 +554,7 @@ public: // Atom class for reading the tmcd atom class TMCDAtom : public AtomBase { public: - TMCDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + TMCDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~TMCDAtom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -561,7 +564,7 @@ public: // Atom class for reading the dac3 atom class DAC3Atom : public DecoderConfigAtom { public: - DAC3Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + DAC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~DAC3Atom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -572,7 +575,7 @@ public: // Atom class for reading the dec3 atom class DEC3Atom : public DecoderConfigAtom { public: - DEC3Atom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + DEC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~DEC3Atom(); void OnProcessMetaData(); char *OnGetAtomName(); @@ -583,14 +586,14 @@ public: // Atom class for reading the Media Handler atom class HDLRAtom : public FullAtom { public: - HDLRAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); + HDLRAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType, uint64 pAtomSize); virtual ~HDLRAtom(); void OnProcessMetaData(); char *OnGetAtomName(); bool IsVideoHandler(); bool IsAudioHandler(); - uint32 getMediaHandlerType(); + uint32 GetMediaHandlerType(); private: hdlr theHeader; diff --git a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp index 4e9a3ba9b6..1458e9bd7d 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp @@ -28,9 +28,9 @@ TRAKAtom::TRAKAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, { theTKHDAtom = NULL; theMDHDAtom = NULL; - framecount = 0; - bytespersample = 0; - timescale = 1; + frameCount = 0; + bytesPerSample = 0; + timeScale = 1; } TRAKAtom::~TRAKAtom() @@ -46,7 +46,7 @@ char *TRAKAtom::OnGetAtomName() return "MPEG-4 Track Atom"; } -TKHDAtom *TRAKAtom::getTKHDAtom() +TKHDAtom *TRAKAtom::GetTKHDAtom() { if (theTKHDAtom) { return theTKHDAtom; @@ -59,7 +59,7 @@ TKHDAtom *TRAKAtom::getTKHDAtom() return theTKHDAtom; } -MDHDAtom *TRAKAtom::getMDHDAtom() +MDHDAtom *TRAKAtom::GetMDHDAtom() { if (theMDHDAtom) { return theMDHDAtom; @@ -76,21 +76,21 @@ MDHDAtom *TRAKAtom::getMDHDAtom() bigtime_t TRAKAtom::Duration(uint32 TimeScale) { if (IsAudio() || IsVideo()) { - return getMDHDAtom()->getDuration(); + return GetMDHDAtom()->GetDuration(); } - return bigtime_t(getTKHDAtom()->getDuration() * 1000000.0) / TimeScale; + return bigtime_t(GetTKHDAtom()->GetDuration() * 1000000.0) / TimeScale; } void TRAKAtom::OnChildProcessingComplete() { - timescale = getMDHDAtom()->getTimeScale(); + timeScale = GetMDHDAtom()->GetTimeScale(); STTSAtom *aSTTSAtom = dynamic_cast(GetChildAtom(uint32('stts'),0)); if (aSTTSAtom) { - framecount = aSTTSAtom->getSUMCounts(); - aSTTSAtom->setFrameRate(getFrameRate()); + frameCount = aSTTSAtom->GetSUMCounts(); + aSTTSAtom->SetFrameRate(GetFrameRate()); } } @@ -110,24 +110,24 @@ bool TRAKAtom::IsAudio() } // frames per us -float TRAKAtom::getFrameRate() +float TRAKAtom::GetFrameRate() { if (IsAudio()) { AtomBase *aAtomBase = GetChildAtom(uint32('stsd'),0); if (aAtomBase) { STSDAtom *aSTSDAtom = dynamic_cast(aAtomBase); - AudioDescription aAudioDescription = aSTSDAtom->getAsAudio(); - return (aAudioDescription.theAudioSampleEntry.SampleRate / 65536.0) / aAudioDescription.FrameSize; + AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio(); + return (aAudioDescription.theAudioSampleEntry.SampleRate) / aAudioDescription.FrameSize; } } else if (IsVideo()) { - return (framecount * 1000000.0) / Duration(); + return (frameCount * 1000000.0) / Duration(); } return 0.0; } -float TRAKAtom::getSampleRate() +float TRAKAtom::GetSampleRate() { // Only valid for Audio if (IsAudio()) { @@ -135,91 +135,109 @@ float TRAKAtom::getSampleRate() if (aAtomBase) { STSDAtom *aSTSDAtom = dynamic_cast(aAtomBase); - AudioDescription aAudioDescription = aSTSDAtom->getAsAudio(); - return aAudioDescription.theAudioSampleEntry.SampleRate / 65536; + AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio(); + return aAudioDescription.theAudioSampleEntry.SampleRate; } } return 0.0; } -bigtime_t TRAKAtom::getTimeForFrame(uint32 pFrame) -{ - return bigtime_t((pFrame * 1000000.0) / getFrameRate()); +uint32 +TRAKAtom::GetFrameForTime(bigtime_t time) { + // time / duration * frameCount? + //return uint32(time * GetFrameRate() / 1000000LL); + return time * frameCount / Duration(); } -uint32 TRAKAtom::getSampleForTime(bigtime_t pTime) +bigtime_t TRAKAtom::GetTimeForFrame(uint32 pFrame) +{ + return bigtime_t((pFrame * 1000000LL) / GetFrameRate()); +} + +uint32 TRAKAtom::GetSampleForTime(bigtime_t pTime) { AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getSampleForTime(pTime); + return (dynamic_cast(aAtomBase))->GetSampleForTime(pTime); } return 0; } -uint32 TRAKAtom::getSampleForFrame(uint32 pFrame) +uint32 TRAKAtom::GetSampleForFrame(uint32 pFrame) { AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getSampleForTime(getTimeForFrame(pFrame)); + return (dynamic_cast(aAtomBase))->GetSampleForTime(GetTimeForFrame(pFrame)); } return 0; } -uint32 TRAKAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) +uint32 TRAKAtom::GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) { AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getChunkForSample(pSample, pOffsetInChunk); + return (dynamic_cast(aAtomBase))->GetChunkForSample(pSample, pOffsetInChunk); } return 0; } -uint32 TRAKAtom::getNoSamplesInChunk(uint32 pChunkID) +uint32 TRAKAtom::GetNoSamplesInChunk(uint32 pChunkIndex) { AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getNoSamplesInChunk(pChunkID); + return (dynamic_cast(aAtomBase))->GetNoSamplesInChunk(pChunkIndex); } return 0; } -uint32 TRAKAtom::getSizeForSample(uint32 pSample) +uint32 TRAKAtom::GetSizeForSample(uint32 pSample) { AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getSizeForSample(pSample); + return (dynamic_cast(aAtomBase))->GetSizeForSample(pSample); } return 0; } -uint64 TRAKAtom::getOffsetForChunk(uint32 pChunkID) +uint64 TRAKAtom::GetOffsetForChunk(uint32 pChunkIndex) { AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getOffsetForChunk(pChunkID); + return (dynamic_cast(aAtomBase))->GetOffsetForChunk(pChunkIndex); } return 0; } -uint32 TRAKAtom::getFirstSampleInChunk(uint32 pChunkID) +uint32 TRAKAtom::ChunkCount() { + AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); + + if (aAtomBase) { + return (dynamic_cast(aAtomBase))->GetTotalChunks(); + } + + return 0; +} + + +uint32 TRAKAtom::GetFirstSampleInChunk(uint32 pChunkIndex) { AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getFirstSampleInChunk(pChunkID); + return (dynamic_cast(aAtomBase))->GetFirstSampleInChunk(pChunkIndex); } return 0; @@ -250,15 +268,15 @@ bool TRAKAtom::IsSingleSampleSize() bool TRAKAtom::IsActive() { - return getTKHDAtom()->IsActive(); + return GetTKHDAtom()->IsActive(); } -uint32 TRAKAtom::getBytesPerSample() +uint32 TRAKAtom::GetBytesPerSample() { AtomBase *aAtomBase; - if (bytespersample > 0) { - return bytespersample; + if (bytesPerSample > 0) { + return bytesPerSample; } // calculate bytes per sample and cache it @@ -269,21 +287,44 @@ AtomBase *aAtomBase; if (aAtomBase) { STSDAtom *aSTSDAtom = dynamic_cast(aAtomBase); - AudioDescription aAudioDescription = aSTSDAtom->getAsAudio(); + AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio(); - bytespersample = aAudioDescription.theAudioSampleEntry.SampleSize / 8; + bytesPerSample = aAudioDescription.theAudioSampleEntry.SampleSize / 8; } } - return bytespersample; + return bytesPerSample; } -uint32 TRAKAtom::getTotalChunks() +uint32 +TRAKAtom::GetChunkSize(uint32 pChunkIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); + uint32 totalSamples = GetNoSamplesInChunk(pChunkIndex); - if (aAtomBase) { - return (dynamic_cast(aAtomBase))->getTotalChunks(); + if (IsSingleSampleSize()) { + return totalSamples * GetBytesPerSample(); + } else { + uint32 SampleNo = GetFirstSampleInChunk(pChunkIndex); + uint32 ChunkSize = 0; + + if (SampleNo >= 0) { + while (totalSamples-- > 0) { + ChunkSize += GetSizeForSample(SampleNo++); + } + } + + return ChunkSize; + } + + return 0; +} + +uint32 TRAKAtom::GetTotalChunks() +{ + AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); + + if (aAtomBase) { + return (dynamic_cast(aAtomBase))->GetTotalChunks(); } return 0; diff --git a/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp b/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp index 511945c338..e7f0b50c68 100644 --- a/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp +++ b/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp @@ -67,6 +67,7 @@ struct mp4_cookie { // Common uint32 frame_pos; + uint32 chunk_index; uint32 frames_per_sec_rate; uint32 frames_per_sec_scale; uint32 frame_size; @@ -118,7 +119,7 @@ mp4Reader::Sniff(int32 *streamCount) return B_ERROR; } - *streamCount = theFileReader->getStreamCount(); + *streamCount = theFileReader->GetStreamCount(); return B_OK; } @@ -153,11 +154,14 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) cookie->buffer = 0; cookie->buffer_size = 0; cookie->frame_pos = 0; + cookie->chunk_index = 1; BMediaFormats formats; media_format *format = &cookie->format; media_format_description description; + printf("Allocate cookie for stream %ld\n",streamNumber); + if (theFileReader->IsActive(cookie->stream) == false) { ERROR("mp4Reader::AllocateCookie: stream %d is not active\n", cookie->stream); delete cookie; @@ -183,8 +187,8 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) } // frame_count is actually sample_count for audio - makes media_player happy but david sad - cookie->frame_count = theFileReader->getFrameCount(cookie->stream) * audio_format->FrameSize; - cookie->duration = theFileReader->getAudioDuration(cookie->stream); + cookie->frame_count = theFileReader->GetFrameCount(cookie->stream) * audio_format->FrameSize; + cookie->duration = theFileReader->GetAudioDuration(cookie->stream); cookie->frame_size = audio_format->FrameSize; cookie->audio = true; @@ -266,7 +270,7 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) format->u.raw_audio.buffer_size = stream_header->suggested_buffer_size; } else { - TRACE("codecid %s codecsubtype %s\n",&audio_format->compression,&audio_format->codecSubType); + TRACE("codecid %4s codecsubtype %4s\n", &audio_format->compression, &audio_format->codecSubType); description.family = B_QUICKTIME_FORMAT_FAMILY; @@ -310,7 +314,7 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) TRACE("Audio frame_rate %f, channel_count %ld, format %ld, buffer_size %ld, frame_size %ld, bit_rate %f\n", format->u.encoded_audio.output.frame_rate, format->u.encoded_audio.output.channel_count, format->u.encoded_audio.output.format,format->u.encoded_audio.output.buffer_size, format->u.encoded_audio.frame_size, format->u.encoded_audio.bit_rate); - TRACE("Track %d MP4 Audio FrameCount %ld Duration %Ld\n",cookie->stream,theFileReader->getFrameCount(cookie->stream),cookie->duration); + TRACE("Track %d MP4 Audio FrameCount %ld Duration %Ld\n",cookie->stream,theFileReader->GetFrameCount(cookie->stream),cookie->duration); break; case 'mp4a': codecID = 'aac '; @@ -341,7 +345,7 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) TRACE("Audio frame_rate %f, channel_count %ld, format %ld, buffer_size %ld, frame_size %ld, bit_rate %f\n", format->u.encoded_audio.output.frame_rate, format->u.encoded_audio.output.channel_count, format->u.encoded_audio.output.format,format->u.encoded_audio.output.buffer_size, format->u.encoded_audio.frame_size, format->u.encoded_audio.bit_rate); - TRACE("Track %d MP4 Audio FrameCount %ld Duration %Ld\n",cookie->stream,theFileReader->getFrameCount(cookie->stream),cookie->duration); + TRACE("Track %d MP4 Audio FrameCount %ld Duration %Ld\n",cookie->stream,theFileReader->GetFrameCount(cookie->stream),cookie->duration); break; default: @@ -553,7 +557,7 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration, ERROR("No stream Info for stream %d\n",cookie->stream); } - TRACE("GetStreamInfo (%d) fc %Ld duration %Ld extra %ld\n",cookie->stream,*frameCount,*duration,*infoSize); + TRACE("GetStreamInfo (%d) fc %Ld duration %Ld extra %ld\n", cookie->stream, *frameCount, *duration, *infoSize); } return B_OK; } @@ -566,18 +570,17 @@ mp4Reader::Seek(void *cookie, uint32 flags, int64 *frame, bigtime_t *time) mp4_cookie *mp4cookie = (mp4_cookie *)cookie; if (flags & B_MEDIA_SEEK_TO_TIME) { - // frame = (time * rate) / fps / 1000000LL - *frame = ((*time * mp4cookie->frames_per_sec_rate) / (int64)mp4cookie->frames_per_sec_scale) / 1000000LL; - mp4cookie->frame_pos = *frame; + mp4cookie->frame_pos = theFileReader->GetFrameForTime(mp4cookie->stream, *time); + *frame = theFileReader->GetSampleForTime(mp4cookie->stream, *time); } if (flags & B_MEDIA_SEEK_TO_FRAME) { - // time = frame * 1000000LL * fps / rate - *time = (*frame * 1000000LL * (int64)mp4cookie->frames_per_sec_scale) / mp4cookie->frames_per_sec_rate; - mp4cookie->frame_pos = *frame; + // Convert Sample to Frame + mp4cookie->frame_pos = theFileReader->GetFrameForSample(mp4cookie->stream, *frame); + *time = theFileReader->GetTimeForSample(mp4cookie->stream, *frame); } - TRACE("mp4Reader::Seek: seekTo%s%s%s%s, time %Ld, frame %Ld\n", + TRACE("mp4Reader::Seek: stream %d %s%s%s%s, time %Ld, frame %Ld\n", mp4cookie->stream, (flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", (flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "", (flags & B_MEDIA_SEEK_CLOSEST_FORWARD) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", @@ -592,17 +595,31 @@ mp4Reader::FindKeyFrame(void* cookie, uint32 flags, int64* frame, bigtime_t* time) { // Find the nearest keyframe to the given time or frame. + // frame is really sample for audio. mp4_cookie *mp4cookie = (mp4_cookie *)cookie; bool keyframe = false; - if (flags & B_MEDIA_SEEK_TO_TIME) { - // convert time to frame as we seek by frame - // frame = (time * rate) / fps / 1000000LL - *frame = ((*time * mp4cookie->frames_per_sec_rate) / (int64)mp4cookie->frames_per_sec_scale) / 1000000LL; + TRACE("mp4Reader::FindKeyFrame: input(stream %d %s%s%s%s, time %Ld, frame %Ld)\n", mp4cookie->stream, + (flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", + (flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "", + (flags & B_MEDIA_SEEK_CLOSEST_FORWARD) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", + (flags & B_MEDIA_SEEK_CLOSEST_BACKWARD) ? " B_MEDIA_SEEK_CLOSEST_BACKWARD" : "", + *time, *frame); + + if (flags & B_MEDIA_SEEK_TO_FRAME) { + if (mp4cookie->audio) { + // Convert Sample to Frame for Audio + *frame = theFileReader->GetFrameForSample(mp4cookie->stream, *frame); + } + *time = theFileReader->GetTimeForFrame(mp4cookie->stream, *frame); } - TRACE("mp4Reader::FindKeyFrame: seekTo%s%s%s%s, time %Ld, frame %Ld\n", + if (flags & B_MEDIA_SEEK_TO_TIME) { + *frame = theFileReader->GetFrameForTime(mp4cookie->stream, *time); + } + + TRACE("mp4Reader::FindKeyFrame: calc(stream %d %s%s%s%s, time %Ld, frame %Ld)\n", mp4cookie->stream, (flags & B_MEDIA_SEEK_TO_TIME) ? " B_MEDIA_SEEK_TO_TIME" : "", (flags & B_MEDIA_SEEK_TO_FRAME) ? " B_MEDIA_SEEK_TO_FRAME" : "", (flags & B_MEDIA_SEEK_CLOSEST_FORWARD) ? " B_MEDIA_SEEK_CLOSEST_FORWARD" : "", @@ -626,16 +643,17 @@ mp4Reader::FindKeyFrame(void* cookie, uint32 flags, // We consider frame 0 to be a keyframe but that is likely wrong if (!keyframe && *frame > 0) { - TRACE("Did NOT find keyframe at frame %Ld\n",*frame); + TRACE("mp4Reader::FindKeyFrame: Did NOT find keyframe at frame %Ld\n", *frame); return B_LAST_BUFFER_ERROR; } } - // convert frame found to time - // time = frame * 1000000LL * fps / rate - *time = (*frame * 1000000LL * (int64)mp4cookie->frames_per_sec_scale) / mp4cookie->frames_per_sec_rate; - - TRACE("Found keyframe at frame %Ld time %Ld\n",*frame,*time); + *time = theFileReader->GetTimeForFrame(mp4cookie->stream, *frame); + if (mp4cookie->audio) { + *frame = theFileReader->GetSampleForTime(mp4cookie->stream, *time); + } + + TRACE("mp4Reader::FindKeyFrame: Found keyframe at frame %Ld time %Ld\n" ,*frame, *time); return B_OK; } @@ -645,11 +663,12 @@ mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer, size_t *chunkSize, media_header *mediaHeader) { mp4_cookie *cookie = (mp4_cookie *)_cookie; - int64 start; + off_t start; uint32 size; bool keyframe; + uint32 frameCount; - if (theFileReader->GetNextChunkInfo(cookie->stream, (cookie->frame_pos / cookie->frame_size), &start, &size, &keyframe) == false) { + if (theFileReader->GetBufferForFrame(cookie->stream, cookie->frame_pos, &start, &size, &keyframe, &(mediaHeader->start_time), &frameCount) == false) { TRACE("LAST BUFFER : %d (%ld)\n",cookie->stream, cookie->frame_pos); return B_LAST_BUFFER_ERROR; } @@ -660,7 +679,7 @@ mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer, cookie->buffer = new char [cookie->buffer_size]; } - mediaHeader->start_time = bigtime_t(double(cookie->frame_pos) * 1000000.0 * double(cookie->frames_per_sec_scale)) / cookie->frames_per_sec_rate; +// mediaHeader->start_time = bigtime_t(double(cookie->frame_pos * cookie->frame_size) * 1000000.0 * double(cookie->frames_per_sec_scale)) / cookie->frames_per_sec_rate; if (cookie->audio) { TRACE("Audio"); @@ -675,9 +694,9 @@ mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer, mediaHeader->u.encoded_video.field_number = 0; mediaHeader->u.encoded_video.field_sequence = cookie->frame_pos; } - TRACE(" stream %d: frame %ld start time %.6f file pos %lld Size %ld key frame %s\n",cookie->stream, (cookie->frame_pos / cookie->frame_size), mediaHeader->start_time / 1000000.0, start, size, keyframe ? "true" : "false"); + TRACE(" stream %d: frame_pos %ld start time %.6f file pos %lld Size %ld key frame %s frameCount %ld\n", cookie->stream, cookie->frame_pos, mediaHeader->start_time / 1000000.0, start, size, keyframe ? "true" : "false", frameCount); - cookie->frame_pos += cookie->frame_size; + cookie->frame_pos += frameCount; *chunkBuffer = cookie->buffer; *chunkSize = size;