Cleanup and preparation for h264/aac in mov
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33610 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
676ef01ba7
commit
ff67bc43da
@ -60,12 +60,16 @@ bool MOVFileReader::IsEndOfData(off_t pPosition)
|
||||
{
|
||||
AtomBase *aAtomBase;
|
||||
|
||||
aAtomBase = GetChildAtom(uint32('mdat'),0);
|
||||
if (aAtomBase) {
|
||||
MDATAtom *aMdatAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
||||
return pPosition >= aMdatAtom->getEOF();
|
||||
for (uint32 index=0;index<CountChildAtoms('mdat');index++) {
|
||||
aAtomBase = GetChildAtom(uint32('mdat'),index);
|
||||
if ((aAtomBase) && (aAtomBase->getAtomSize() > 8)) {
|
||||
MDATAtom *aMDATAtom = dynamic_cast<MDATAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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)
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user