diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp index 72d6bca455..4fdae1c1ba 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.cpp @@ -60,12 +60,16 @@ bool MOVFileReader::IsEndOfData(off_t pPosition) { AtomBase *aAtomBase; - aAtomBase = GetChildAtom(uint32('mdat'),0); - if (aAtomBase) { - MDATAtom *aMdatAtom = dynamic_cast(aAtomBase); - return pPosition >= aMdatAtom->getEOF(); + for (uint32 index=0;indexgetAtomSize() > 8)) { + MDATAtom *aMDATAtom = dynamic_cast(aAtomBase); + if (pPosition >= aMDATAtom->getAtomOffset() && pPosition <= aMDATAtom->getEOF()) { + return false; + } + } } - + return true; } @@ -276,74 +280,59 @@ uint32 MOVFileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID) return 0; } -uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo) +uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pChunkID) { // Find Track AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); if (aAtomBase) { TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - uint32 ChunkNo = 1; - if (IsAudio(stream_index)) { - ChunkNo = pFrameNo; - } - - if (IsVideo(stream_index)) { - uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo); - - uint32 OffsetInChunk; - ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); - } - - return aTrakAtom->getNoSamplesInChunk(ChunkNo); + return aTrakAtom->getNoSamplesInChunk(pChunkID); } return 0; } -uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo) +uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo, uint32 *chunkFrameCount) { // Find Track AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index); 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 ChunkID = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); // Get Offset For Chunk - return aTrakAtom->getOffsetForChunk(ChunkNo); - } + uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkID); - if (IsVideo(stream_index)) { + if (IsAudio(stream_index)) { + // For audio we return all frames in Chunk less any offset + *chunkFrameCount = aTrakAtom->getNoSamplesInChunk(ChunkID) - OffsetInChunk; + } else { + // For video we always return 1 frame at a time + *chunkFrameCount = 1; + } - 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 SampleSize; - // Adjust the Offset for the Offset in the chunk - if (aTrakAtom->IsSingleSampleSize()) { - SampleSize = aTrakAtom->getSizeForSample(SampleNo); - OffsetNo = OffsetNo + (OffsetInChunk * SampleSize); - } else { - // This is bad news performance wise - for (uint32 i=1;i<=OffsetInChunk;i++) { - SampleSize = aTrakAtom->getSizeForSample(SampleNo-i); - OffsetNo = OffsetNo + SampleSize; - } + if (ChunkID != 0) { + uint32 SampleSize; + // Adjust the Offset for the Offset in the chunk + if (aTrakAtom->IsSingleSampleSize()) { + SampleSize = aTrakAtom->getSizeForSample(SampleNo); + OffsetNo = OffsetNo + (OffsetInChunk * SampleSize); + } else { + // This is bad news performance wise + for (uint32 i=1;i<=OffsetInChunk;i++) { + SampleSize = aTrakAtom->getSizeForSample(SampleNo - i); + OffsetNo = OffsetNo + SampleSize; } } - - return OffsetNo; } + + return OffsetNo; } } @@ -568,7 +557,7 @@ const mov_stream_header *MOVFileReader::StreamFormat(uint32 stream_index) uint32 -MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber) +MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNo) { AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex); if (aAtomBase == NULL) @@ -576,17 +565,22 @@ MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber) TRAKAtom *aTrakAtom = dynamic_cast(aAtomBase); - if (IsAudio(streamIndex)) { - // We read audio in chunk by chunk so chunk size is chunk size - off_t chunkStart = aTrakAtom->getOffsetForChunk(frameNumber); - return theChunkSuperIndex.getChunkSize(streamIndex, frameNumber, chunkStart); - } + if (frameNo < aTrakAtom->FrameCount()) { + uint32 SampleNo = aTrakAtom->getSampleForFrame(frameNo); + + if (IsAudio(streamIndex)) { + // Audio Chunk Size is all samples in the chunk + // Get Chunk For Sample and the offset for the frame within that chunk + uint32 OffsetInChunk; + uint32 ChunkID = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk); - if (IsVideo(streamIndex)) { - if (frameNumber < aTrakAtom->FrameCount()) { + off_t chunkStart = aTrakAtom->getOffsetForChunk(ChunkID); + return theChunkSuperIndex.getChunkSize(streamIndex, ChunkID, chunkStart); + } + + if (IsVideo(streamIndex)) { // We read video in Sample by Sample so chunk size is Sample Size - uint32 sampleNumber = aTrakAtom->getSampleForFrame(frameNumber); - return aTrakAtom->getSizeForSample(sampleNumber); + return aTrakAtom->getSizeForSample(SampleNo); } } @@ -608,16 +602,23 @@ MOVFileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo) return false; } -bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe) +bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe, uint32 *chunkFrameCount) { - *start = getOffsetForFrame(stream_index, pFrameNo); + *start = getOffsetForFrame(stream_index, pFrameNo, chunkFrameCount); *size = getChunkSize(stream_index, pFrameNo); if ((*start > 0) && (*size > 0)) { *keyframe = IsKeyFrame(stream_index, pFrameNo); } - return ((*start > 0) && (*size > 0) && !(IsEndOfFile(*start + *size)) && !(IsEndOfData(*start + *size))); + printf("(%ld) frame %ld start %Ld, size %ld, eof %s, eod %s\n",stream_index, pFrameNo,*start,*size, IsEndOfFile(*start + *size) ? "true" : "false", IsEndOfData(*start + *size) ? "true" : "false"); + + // TODO need a better method for detecting End of Data + if (IsEndOfFile(*start + *size) || IsEndOfData(*start + *size)) { + return false; + } + + return *start > 0 && *size > 0; } bool MOVFileReader::IsActive(uint32 stream_index) diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.h b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.h index 7c9eed4372..cf637049fa 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.h +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVFileReader.h @@ -98,10 +98,10 @@ public: // Is stream (track) a audio track bool IsAudio(uint32 stream_index); - uint32 getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo); + uint32 getNoFramesInChunk(uint32 stream_index, uint32 pChunkID); uint32 getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID); - uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo); + uint64 getOffsetForFrame(uint32 stream_index, uint32 pFrameNo, uint32 *chunkFrameCount); uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo); bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo); @@ -110,7 +110,7 @@ public: bool IsActive(uint32 stream_index); - bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe); + bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe, uint32 *chunkFrameCount); // Return all Audio Meta Data const AudioMetaData *AudioFormat(uint32 stream_index); diff --git a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp index 7a40593308..119ae252bf 100644 --- a/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp +++ b/src/add-ons/media/plugins/mov_reader/libMOV/MOVParser.cpp @@ -177,6 +177,10 @@ AtomBase *getAtom(BPositionIO *pStream) return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize); } + if (aAtomType == uint32('avcC')) { + return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize); + } + if (aAtomType == uint32('ftyp')) { return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize); } @@ -645,7 +649,6 @@ SampleSizeEntry *aSampleSize; char *STSZAtom::OnGetAtomName() { - printf("%ld ",theHeader.SampleSize); return "Sample Size Atom"; } diff --git a/src/add-ons/media/plugins/mov_reader/mov_reader.cpp b/src/add-ons/media/plugins/mov_reader/mov_reader.cpp index 691d7c8fa3..28f6d99e35 100644 --- a/src/add-ons/media/plugins/mov_reader/mov_reader.cpp +++ b/src/add-ons/media/plugins/mov_reader/mov_reader.cpp @@ -559,9 +559,9 @@ movReader::GetNextChunk(void *_cookie, { mov_cookie *cookie = (mov_cookie *)_cookie; - int64 start; uint32 size; bool keyframe; + int64 start; uint32 size; bool keyframe; uint32 chunkFrameCount; - if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe)) + if (!theFileReader->GetNextChunkInfo(cookie->stream, cookie->frame_pos, &start, &size, &keyframe, &chunkFrameCount)) return B_LAST_BUFFER_ERROR; if (cookie->buffer_size < size) { @@ -577,12 +577,12 @@ movReader::GetNextChunk(void *_cookie, // This will only work with raw audio I think. mediaHeader->start_time = (cookie->byte_pos * 1000000LL * cookie->bytes_per_sec_scale) / cookie->bytes_per_sec_rate; - TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using byte_pos\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time); +// TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using byte_pos\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time); // We should find the current frame position (ie first frame in chunk) then compute using fps - cookie->frame_pos = theFileReader->getFirstFrameInChunk(cookie->stream,cookie->frame_pos); +// cookie->frame_pos = theFileReader->getFirstFrameInChunk(cookie->stream,cookie->frame_pos); mediaHeader->start_time = (cookie->frame_pos * 1000000LL * (int64)cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate; - TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using frame_no %ld\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time, cookie->frame_pos); +// TRACE("Audio - Frames in Chunk %ld / Actual Start Time %Ld using frame_no %ld\n",theFileReader->getNoFramesInChunk(cookie->stream,cookie->frame_pos),mediaHeader->start_time, cookie->frame_pos); cookie->byte_pos += size; } else { @@ -594,7 +594,7 @@ movReader::GetNextChunk(void *_cookie, mediaHeader->u.encoded_video.line_count = cookie->line_count; } - cookie->frame_pos++; + cookie->frame_pos += chunkFrameCount; TRACE("stream %d: start_time %.6f\n", cookie->stream, mediaHeader->start_time / 1000000.0); *chunkBuffer = cookie->buffer;