From 9f6dbdea6ac85b260c11e0d66b9cb750a2aa69bf Mon Sep 17 00:00:00 2001 From: David McPaul Date: Tue, 4 Mar 2008 09:55:49 +0000 Subject: [PATCH] changes for aac decoder git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@24229 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../mp4_reader/libMP4/MP4FileReader.cpp | 160 ++++++++---------- .../plugins/mp4_reader/libMP4/MP4FileReader.h | 44 ++--- .../plugins/mp4_reader/libMP4/MP4Parser.cpp | 151 ++++++++++++++--- .../plugins/mp4_reader/libMP4/MP4Parser.h | 9 +- .../plugins/mp4_reader/libMP4/MP4TrakAtom.cpp | 2 +- .../media/plugins/mp4_reader/mp4_reader.cpp | 66 ++++++-- 6 files changed, 278 insertions(+), 154 deletions(-) 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 bfa3d783a8..7d9723414b 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.cpp @@ -275,14 +275,24 @@ MP4FileReader::getVideoFrameCount(uint32 streamIndex) uint32 MP4FileReader::getAudioFrameCount(uint32 streamIndex) { - if (IsAudio(streamIndex)) { - return uint32(((getAudioDuration(streamIndex) - * AudioFormat(streamIndex)->SampleRate) / 1000000L) + 0.5); - } + AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); - return 0; + if (aAtomBase && dynamic_cast(aAtomBase)->IsAudio()) + return dynamic_cast(aAtomBase)->FrameCount(); + + return 1; } +uint32 +MP4FileReader::getAudioChunkCount(uint32 streamIndex) +{ + AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); + + if (aAtomBase && dynamic_cast(aAtomBase)->IsAudio()) + return dynamic_cast(aAtomBase)->getTotalChunks(); + + return 0; +} bool MP4FileReader::IsVideo(uint32 streamIndex) @@ -329,23 +339,18 @@ MP4FileReader::getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID) uint32 -MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo) +MP4FileReader::getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo) { // Find Track - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); uint32 ChunkNo = 1; - if (IsAudio(stream_index)) - ChunkNo = pFrameNo; + uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - if (IsVideo(stream_index)) { - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - - uint32 OffsetInChunk; - ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); - } + uint32 OffsetInChunk; + ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); return aTrakAtom->getNoSamplesInChunk(ChunkNo); } @@ -355,48 +360,38 @@ MP4FileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo) uint64 -MP4FileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo) +MP4FileReader::getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo) { // Find Track - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - if (IsAudio(stream_index)) { - // FrameNo is really chunk No for audio - uint32 ChunkNo = pFrameNo; - + if (pFrameNo < aTrakAtom->FrameCount()) { + // Get Sample for Frame + uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); + // 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 - return aTrakAtom->getOffsetForChunk(ChunkNo); - } + uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo); - if (IsVideo(stream_index)) { - if (pFrameNo < aTrakAtom->FrameCount()) { - // Get Sample for Frame - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - // 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 (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; } } - - return OffsetNo; } + + return OffsetNo; } } @@ -476,10 +471,10 @@ MP4FileReader::MovMainHeader() const AudioMetaData * -MP4FileReader::AudioFormat(uint32 stream_index, size_t *size) +MP4FileReader::AudioFormat(uint32 streamIndex, size_t *size) { - if (IsAudio(stream_index)) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + if (IsAudio(streamIndex)) { + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); @@ -496,7 +491,7 @@ MP4FileReader::AudioFormat(uint32 stream_index, size_t *size) theAudio.NoOfChannels = aAudioDescription.theAudioSampleEntry.ChannelCount; theAudio.SampleSize = aAudioDescription.theAudioSampleEntry.SampleSize; theAudio.SampleRate = aAudioDescription.theAudioSampleEntry.SampleRate / 65536; // Convert from fixed point decimal to float - theAudio.PacketSize = uint32((theAudio.SampleRate * theAudio.NoOfChannels * theAudio.SampleSize) / 8); + theAudio.PacketSize = uint32((theAudio.SampleSize * theAudio.NoOfChannels * 1024) / 8); theAudio.theVOL = aAudioDescription.theVOL; theAudio.VOLSize = aAudioDescription.VOLSize; @@ -509,12 +504,11 @@ MP4FileReader::AudioFormat(uint32 stream_index, size_t *size) return NULL; } - const VideoMetaData* -MP4FileReader::VideoFormat(uint32 stream_index) +MP4FileReader::VideoFormat(uint32 streamIndex) { - if (IsVideo(stream_index)) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + if (IsVideo(streamIndex)) { + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); @@ -556,26 +550,26 @@ MP4FileReader::VideoFormat(uint32 stream_index) const mp4_stream_header* -MP4FileReader::StreamFormat(uint32 stream_index) +MP4FileReader::StreamFormat(uint32 streamIndex) { // Fill In a Stream Header theStreamHeader.length = 0; - if (IsActive(stream_index) == false) { + if (IsActive(streamIndex) == false) { return NULL; } - if (IsVideo(stream_index)) { - theStreamHeader.rate = uint32(1000000L*VideoFormat(stream_index)->FrameRate); + if (IsVideo(streamIndex)) { + theStreamHeader.rate = uint32(1000000L*VideoFormat(streamIndex)->FrameRate); theStreamHeader.scale = 1000000L; - theStreamHeader.length = getVideoFrameCount(stream_index); + theStreamHeader.length = getVideoFrameCount(streamIndex); } - if (IsAudio(stream_index)) { - theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate); + if (IsAudio(streamIndex)) { + theStreamHeader.rate = uint32(AudioFormat(streamIndex)->SampleRate); theStreamHeader.scale = 1; - theStreamHeader.length = getAudioFrameCount(stream_index); - theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize; + theStreamHeader.length = getAudioFrameCount(streamIndex); + theStreamHeader.sample_size = AudioFormat(streamIndex)->SampleSize; theStreamHeader.suggested_buffer_size = theStreamHeader.rate * theStreamHeader.sample_size; } @@ -584,27 +578,15 @@ MP4FileReader::StreamFormat(uint32 stream_index) uint32 -MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo) +MP4FileReader::getChunkSize(uint32 streamIndex, uint32 pFrameNo) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - if (IsAudio(stream_index)) { - // We read audio in chunk by chunk so chunk size is chunk size - uint32 ChunkNo = pFrameNo; - off_t Chunk_Start = aTrakAtom->getOffsetForChunk(ChunkNo); - uint32 ChunkSize = theChunkSuperIndex.getChunkSize(stream_index,ChunkNo,Chunk_Start); - - return ChunkSize; - } - - if (IsVideo(stream_index)) { - if (pFrameNo < aTrakAtom->FrameCount()) { - // We read video in Sample by Sample so we use get Sample Size - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - return aTrakAtom->getSizeForSample(SampleNo); - } + if (pFrameNo < aTrakAtom->FrameCount()) { + uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); + return aTrakAtom->getSizeForSample(SampleNo); } } @@ -613,9 +595,9 @@ MP4FileReader::getChunkSize(uint32 stream_index, uint32 pFrameNo) bool -MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo) +MP4FileReader::IsKeyFrame(uint32 streamIndex, uint32 pFrameNo) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); @@ -628,14 +610,14 @@ MP4FileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo) bool -MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, +MP4FileReader::GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe) { - *start = getOffsetForFrame(stream_index, pFrameNo); - *size = getChunkSize(stream_index, pFrameNo); + *start = getOffsetForFrame(streamIndex, pFrameNo); + *size = getChunkSize(streamIndex, pFrameNo); if ((*start > 0) && (*size > 0)) { - *keyframe = IsKeyFrame(stream_index, pFrameNo); + *keyframe = IsKeyFrame(streamIndex, pFrameNo); } // TODO need a better method for detecting End of Data Note ChunkSize of 0 seems to be it. @@ -645,9 +627,9 @@ MP4FileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, bool -MP4FileReader::IsActive(uint32 stream_index) +MP4FileReader::IsActive(uint32 streamIndex) { - AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); + AtomBase *aAtomBase = GetChildAtom(uint32('trak'),streamIndex); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); return aTrakAtom->IsActive(); 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 30b0a7ef0b..d51175c1c2 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4FileReader.h @@ -81,45 +81,47 @@ public: // Duration defined by the movie header bigtime_t getMovieDuration(); - // The first video track duration indexed by stream_index - bigtime_t getVideoDuration(uint32 stream_index); - // the first audio track duration indexed by stream_index - bigtime_t getAudioDuration(uint32 stream_index); + // The first video track duration indexed by streamIndex + bigtime_t getVideoDuration(uint32 streamIndex); + // the first audio track duration indexed by streamIndex + bigtime_t getAudioDuration(uint32 streamIndex); // the max of all active audio or video durations bigtime_t getMaxDuration(); - // The no of frames in the video track indexed by stream_index - uint32 getVideoFrameCount(uint32 stream_index); - // The no of frames in the audio track indexed by stream_index - uint32 getAudioFrameCount(uint32 stream_index); - + // The no of frames in the video track indexed by streamIndex + // 1 frame = 1 chunk + uint32 getVideoFrameCount(uint32 streamIndex); + // The no of frames in the audio track indexed by streamIndex + uint32 getAudioFrameCount(uint32 streamIndex); + // The no of chunks in the audio track indexed by streamIndex + uint32 getAudioChunkCount(uint32 streamIndex); // Is stream (track) a video track - bool IsVideo(uint32 stream_index); + bool IsVideo(uint32 streamIndex); // Is stream (track) a audio track - bool IsAudio(uint32 stream_index); + bool IsAudio(uint32 streamIndex); - uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo); - uint32 getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID); + uint32 getNoFramesInChunk(uint32 streamIndex, uint32 pFrameNo); + uint32 getFirstFrameInChunk(uint32 streamIndex, uint32 pChunkID); - uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo); - uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo); - bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo); + uint64 getOffsetForFrame(uint32 streamIndex, uint32 pFrameNo); + uint32 getChunkSize(uint32 streamIndex, uint32 pFrameNo); + bool IsKeyFrame(uint32 streamIndex, uint32 pFrameNo); status_t ParseFile(); BPositionIO *Source() {return theStream;}; - bool IsActive(uint32 stream_index); + bool IsActive(uint32 streamIndex); - bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe); + bool GetNextChunkInfo(uint32 streamIndex, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe); // Return all Audio Meta Data - const AudioMetaData *AudioFormat(uint32 stream_index, size_t *size = 0); + const AudioMetaData *AudioFormat(uint32 streamIndex, size_t *size = 0); // Return all Video Meta Data - const VideoMetaData *VideoFormat(uint32 stream_index); + const VideoMetaData *VideoFormat(uint32 streamIndex); // XXX these need work const mp4_main_header *MovMainHeader(); - const mp4_stream_header *StreamFormat(uint32 stream_index); + const mp4_stream_header *StreamFormat(uint32 streamIndex); }; #endif 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 69bc25922c..593bc9b178 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.cpp @@ -209,7 +209,7 @@ void MOOVAtom::OnProcessMetaData() char *MOOVAtom::OnGetAtomName() { - return "Quicktime Movie"; + return "MPEG-4 Movie"; } CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) @@ -322,7 +322,7 @@ void CMOVAtom::OnChildProcessingComplete() char *CMOVAtom::OnGetAtomName() { - return "Compressed Quicktime Movie"; + return "Compressed MPEG-4 Movie"; } DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) @@ -438,7 +438,7 @@ void MVHDAtom::OnProcessMetaData() char *MVHDAtom::OnGetAtomName() { - return "Quicktime Movie Header"; + return "MPEG-4 Movie Header"; } MVHDAtom *MOOVAtom::getMVHDAtom() @@ -908,7 +908,7 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID) return 0LL; } -ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize) +ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) { theVOL = NULL; } @@ -920,15 +920,116 @@ ESDSAtom::~ESDSAtom() } } -void ESDSAtom::OnProcessMetaData() -{ - theVOL = (uint8 *)(malloc(getBytesRemaining())); - Read(theVOL,getBytesRemaining()); +bool ESDSAtom::SkipTag(uint8 Tag, uint32 *offset) { + uint8 byte; + + byte = theVOL[(*offset)++]; + if (byte == Tag) { + uint8 numBytes = 0; + unsigned int length = 0; + + do { + byte = theVOL[(*offset)++]; + numBytes++; + length = (length << 7) | (byte & 0x7F); + } while ((byte & 0x80) && numBytes < 4); + + } else { + // go back Tag not found + (*offset)--; + printf("No Tag %d\n",Tag); + return false; + } + + return true; } -uint8 *ESDSAtom::getVOL() +void ESDSAtom::OnProcessMetaData() { - return theVOL; + FullAtom::OnProcessMetaData(); + + VOLSize = getBytesRemaining(); + uint32 offset = 0; + + theVOL = (uint8 *)(malloc(VOLSize)); + Read(theVOL,VOLSize); + + // Display the VOL + if (VOLSize > 0) { + if (SkipTag(0x03,&offset)) { + offset += 3; + } else { + offset += 2; + } + + if (SkipTag(0x04,&offset)) { + printf("type id is %d", theVOL[offset]); + switch (theVOL[offset]) { + case 1: printf("system v1"); break; + case 2: printf("system v2"); break; + case 32: printf("MPEG-4 video"); break; + case 33: printf("MPEG-4 AVC SPS"); break; + case 34: printf("MPEG-4 AVC PPS"); break; + case 64: printf("MPEG-4 audio"); break; + } + + offset+=2; + + uint32 a,b,c; + uint32 buff; + + a = theVOL[offset]; + b = theVOL[offset+1]; + c = theVOL[offset+2]; + + buff = (a << 16) | (b << 8) | c; + + printf(" buf size %ld ",buff); + printf(" max bit rate %ld",uint32(theVOL[offset+4])); + printf(" avg bit rate %ld\n",uint32(theVOL[offset+8])); + } + } else { + printf("VOL size is 0\n"); + } + +} + +size_t ESDSAtom::getVOLSize(bool forAudio) +{ + uint32 offset = 0; + if (forAudio) { + if (SkipTag(0x03,&offset)) { + offset += 3; + } else { + offset += 2; + } + if (SkipTag(0x04,&offset)) { + offset += 13; + } + + SkipTag(0x05,&offset); + } + + return ( VOLSize - offset); +} + +uint8 *ESDSAtom::getVOL(bool forAudio) +{ + uint32 offset = 0; + if (forAudio) { + if (SkipTag(0x03,&offset)) { + offset += 3; + } else { + offset += 2; + } + if (SkipTag(0x04,&offset)) { + offset += 13; + } + + SkipTag(0x05,&offset); + } + + return &theVOL[offset]; } char *ESDSAtom::OnGetAtomName() @@ -961,7 +1062,7 @@ uint32 STSDAtom::getMediaHandlerType() return dynamic_cast(getParent())->getMediaHandlerType(); } -void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize) +void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize, bool forAudio) { // Check for a esds and if it exists read it into the VOL buffer // MPEG-4 video/audio use the esds to store the VOL (STUPID COMMITTEE IDEA) @@ -976,9 +1077,9 @@ void STSDAtom::ReadESDS(uint8 **VOL, size_t *VOLSize) if (dynamic_cast(aAtomBase)) { // ESDS atom good - *VOLSize = aAtomBase->getDataSize(); + *VOLSize = dynamic_cast(aAtomBase)->getVOLSize(forAudio); *VOL = (uint8 *)(malloc(*VOLSize)); - memcpy(*VOL,dynamic_cast(aAtomBase)->getVOL(),*VOLSize); + memcpy(*VOL,dynamic_cast(aAtomBase)->getVOL(forAudio),*VOLSize); delete aAtomBase; } else { @@ -997,8 +1098,8 @@ void STSDAtom::ReadSoundDescription() Read(&theAudioDescription.theAudioSampleEntry.pre_defined); Read(&theAudioDescription.theAudioSampleEntry.reserved); Read(&theAudioDescription.theAudioSampleEntry.SampleRate); - - ReadESDS(&theAudioDescription.theVOL,&theAudioDescription.VOLSize); + + ReadESDS(&theAudioDescription.theVOL,&theAudioDescription.VOLSize,true); } void STSDAtom::ReadVideoDescription() @@ -1028,7 +1129,7 @@ void STSDAtom::ReadVideoDescription() Read(&theVideoDescription.theVideoSampleEntry.Depth); Read(&theVideoDescription.theVideoSampleEntry.pre_defined3); - ReadESDS(&theVideoDescription.theVOL,&theVideoDescription.VOLSize); + ReadESDS(&theVideoDescription.theVOL,&theVideoDescription.VOLSize, false); } void STSDAtom::OnProcessMetaData() @@ -1253,7 +1354,7 @@ void MINFAtom::OnProcessMetaData() char *MINFAtom::OnGetAtomName() { - return "Quicktime Media Information Atom"; + return "MPEG-4 Media Information Atom"; } uint32 MINFAtom::getMediaHandlerType() @@ -1275,7 +1376,7 @@ void STBLAtom::OnProcessMetaData() char *STBLAtom::OnGetAtomName() { - return "Quicktime Sample Table Atom"; + return "MPEG-4 Sample Table Atom"; } uint32 STBLAtom::getMediaHandlerType() @@ -1297,7 +1398,7 @@ void DINFAtom::OnProcessMetaData() char *DINFAtom::OnGetAtomName() { - return "Quicktime Data Information Atom"; + return "MPEG-4 Data Information Atom"; } TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) @@ -1371,7 +1472,7 @@ void TKHDAtom::OnProcessMetaData() char *TKHDAtom::OnGetAtomName() { - return "Quicktime Track Header"; + return "MPEG-4 Track Header"; } MDIAAtom::MDIAAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) @@ -1388,7 +1489,7 @@ void MDIAAtom::OnProcessMetaData() char *MDIAAtom::OnGetAtomName() { - return "Quicktime Media Atom"; + return "MPEG-4 Media Atom"; } uint32 MDIAAtom::getMediaHandlerType() @@ -1443,7 +1544,7 @@ void MDHDAtom::OnProcessMetaData() char *MDHDAtom::OnGetAtomName() { - return "Quicktime Media Header"; + return "MPEG-4 Media Header"; } bigtime_t MDHDAtom::getDuration() @@ -1486,7 +1587,7 @@ void HDLRAtom::OnProcessMetaData() char *HDLRAtom::OnGetAtomName() { printf("%s %s:",(char *)&(theHeader.handler_type),name); - return "Quicktime Handler Reference Atom "; + return "MPEG-4 Handler Reference Atom "; } bool HDLRAtom::IsVideoHandler() @@ -1524,7 +1625,7 @@ void VMHDAtom::OnProcessMetaData() char *VMHDAtom::OnGetAtomName() { - return "Quicktime Video Media Header"; + return "MPEG-4 Video Media Header"; } SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : FullAtom(pStream, pstreamOffset, patomType, patomSize) @@ -1545,5 +1646,5 @@ void SMHDAtom::OnProcessMetaData() char *SMHDAtom::OnGetAtomName() { - return "Quicktime Sound Media Header"; + return "MPEG-4 Sound Media Header"; } 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 b3c80fe636..5c3b3bb2c5 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4Parser.h @@ -300,16 +300,19 @@ public: off_t getEOF(); }; -class ESDSAtom : public AtomBase { +class ESDSAtom : public FullAtom { public: ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize); virtual ~ESDSAtom(); void OnProcessMetaData(); char *OnGetAtomName(); - uint8 *getVOL(); + uint8 *getVOL(bool forAudio); + size_t getVOLSize(bool forAudio); private: + bool SkipTag(uint8 Tag, uint32 *offset); uint8 *theVOL; + size_t VOLSize; }; // Atom class for reading the sdst atom @@ -326,7 +329,7 @@ public: private: uint32 getMediaHandlerType(); - void ReadESDS(uint8 **VOL, size_t *VOLSize); + void ReadESDS(uint8 **VOL, size_t *VOLSize, bool forAudio); void ReadSoundDescription(); void ReadVideoDescription(); 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 8527c721e5..4172fec72b 100644 --- a/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp +++ b/src/add-ons/media/plugins/mp4_reader/libMP4/MP4TrakAtom.cpp @@ -42,7 +42,7 @@ void TRAKAtom::OnProcessMetaData() char *TRAKAtom::OnGetAtomName() { - return "Quicktime Track Atom"; + return "MPEG-4 Track Atom"; } TKHDAtom *TRAKAtom::getTKHDAtom() 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 df7ecea8b1..5d0ab21551 100644 --- a/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp +++ b/src/add-ons/media/plugins/mp4_reader/mp4_reader.cpp @@ -421,31 +421,56 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie) format->user_data_type = B_CODEC_TYPE_INFO; *(uint32 *)format->user_data = description.u.quicktime.codec; format->user_data[4] = 0; - format->u.encoded_video.max_bit_rate = 8 * theFileReader->MovMainHeader()->max_bytes_per_sec; - format->u.encoded_video.avg_bit_rate = format->u.encoded_video.max_bit_rate / 2; // XXX fix this +// format->u.encoded_video.max_bit_rate = 8 * theFileReader->MovMainHeader()->max_bytes_per_sec; +// format->u.encoded_video.avg_bit_rate = format->u.encoded_video.max_bit_rate / 2; // XXX fix this format->u.encoded_video.output.field_rate = cookie->frames_per_sec_rate / (float)cookie->frames_per_sec_scale; - format->u.encoded_video.output.interlace = 1; // 1: progressive - format->u.encoded_video.output.first_active = 0; - format->u.encoded_video.output.last_active = cookie->line_count - 1; - format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT; - format->u.encoded_video.output.pixel_width_aspect = 1; - format->u.encoded_video.output.pixel_height_aspect = 1; - // format->u.encoded_video.output.display.format = 0; - format->u.encoded_video.output.display.line_width = theFileReader->MovMainHeader()->width; - format->u.encoded_video.output.display.line_count = cookie->line_count; - format->u.encoded_video.output.display.bytes_per_row = 0; // format->u.encoded_video.output.display.line_width * 4; + + format->u.encoded_video.avg_bit_rate = 1; + format->u.encoded_video.max_bit_rate = 1; + + format->u.encoded_video.frame_size = video_format->width * video_format->height * video_format->planes / 8; + format->u.encoded_video.output.display.bytes_per_row = video_format->planes / 8 * video_format->width; + // align to 2 bytes + format->u.encoded_video.output.display.bytes_per_row += format->u.encoded_video.output.display.bytes_per_row & 1; + + switch (video_format->planes) { + case 16: + format->u.encoded_video.output.display.format = B_RGB15_BIG; + break; + case 24: + format->u.encoded_video.output.display.format = B_RGB24_BIG; + break; + case 32: + format->u.encoded_video.output.display.format = B_RGB32_BIG; + break; + default: + format->u.encoded_video.output.display.format = B_NO_COLOR_SPACE; + format->u.encoded_video.frame_size = video_format->width * video_format->height * 8 / 8; + } + + format->u.encoded_video.output.display.line_width = video_format->width; + format->u.encoded_video.output.display.line_count = video_format->height; format->u.encoded_video.output.display.pixel_offset = 0; format->u.encoded_video.output.display.line_offset = 0; format->u.encoded_video.output.display.flags = 0; + format->u.encoded_video.output.interlace = 1; // 1: progressive + format->u.encoded_video.output.first_active = 0; + format->u.encoded_video.output.last_active = format->u.encoded_video.output.display.line_count - 1; + format->u.encoded_video.output.orientation = B_VIDEO_TOP_LEFT_RIGHT; + format->u.encoded_video.output.pixel_width_aspect = 1; + format->u.encoded_video.output.pixel_height_aspect = 1; TRACE("max_bit_rate %.3f\n", format->u.encoded_video.max_bit_rate); TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate); // Set the VOL if (video_format->VOLSize > 0) { + TRACE("VOL Found Size is %ld\n",video_format->VOLSize); size_t size = video_format->VOLSize; const void *data = video_format->theVOL; - format->SetMetaData(data, size); + if (format->SetMetaData(data, size) != B_OK) { + printf("Failed to set VOL\n %d %d",(16 << 20),32000); + } #ifdef TRACE_MP4_READER if (data) { @@ -485,8 +510,17 @@ mp4Reader::GetStreamInfo(void *_cookie, int64 *frameCount, bigtime_t *duration, *frameCount = cookie->frame_count; *duration = cookie->duration; *format = cookie->format; - *infoBuffer = 0; - *infoSize = 0; + + // Copy metadata to infoBuffer + if (theFileReader->IsVideo(cookie->stream)) { + const VideoMetaData *video_format = theFileReader->VideoFormat(cookie->stream); + *infoBuffer = video_format->theVOL; + *infoSize = video_format->VOLSize; + } else { + const AudioMetaData *audio_format = theFileReader->AudioFormat(cookie->stream); + *infoBuffer = audio_format->theVOL; + *infoSize = audio_format->VOLSize; + } return B_OK; } @@ -578,6 +612,8 @@ mp4Reader::GetNextChunk(void *_cookie, const void **chunkBuffer, mediaHeader->u.encoded_video.field_flags = keyframe ? B_MEDIA_KEY_FRAME : 0; mediaHeader->u.encoded_video.first_active_line = 0; mediaHeader->u.encoded_video.line_count = cookie->line_count; + mediaHeader->u.encoded_video.field_number = 0; + mediaHeader->u.encoded_video.field_sequence = cookie->frame_pos; cookie->frame_pos++; }