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:
@@ -60,12 +60,16 @@ bool MOVFileReader::IsEndOfData(off_t pPosition)
|
|||||||
{
|
{
|
||||||
AtomBase *aAtomBase;
|
AtomBase *aAtomBase;
|
||||||
|
|
||||||
aAtomBase = GetChildAtom(uint32('mdat'),0);
|
for (uint32 index=0;index<CountChildAtoms('mdat');index++) {
|
||||||
if (aAtomBase) {
|
aAtomBase = GetChildAtom(uint32('mdat'),index);
|
||||||
MDATAtom *aMdatAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
if ((aAtomBase) && (aAtomBase->getAtomSize() > 8)) {
|
||||||
return pPosition >= aMdatAtom->getEOF();
|
MDATAtom *aMDATAtom = dynamic_cast<MDATAtom *>(aAtomBase);
|
||||||
|
if (pPosition >= aMDATAtom->getAtomOffset() && pPosition <= aMDATAtom->getEOF()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,74 +280,59 @@ uint32 MOVFileReader::getFirstFrameInChunk(uint32 stream_index, uint32 pChunkID)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pFrameNo)
|
uint32 MOVFileReader::getNoFramesInChunk(uint32 stream_index, uint32 pChunkID)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
uint32 ChunkNo = 1;
|
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
return aTrakAtom->getNoSamplesInChunk(pChunkID);
|
||||||
ChunkNo = pFrameNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsVideo(stream_index)) {
|
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
|
||||||
|
|
||||||
uint32 OffsetInChunk;
|
|
||||||
ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return aTrakAtom->getNoSamplesInChunk(ChunkNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo)
|
uint64 MOVFileReader::getOffsetForFrame(uint32 stream_index, uint32 pFrameNo, uint32 *chunkFrameCount)
|
||||||
{
|
{
|
||||||
// Find Track
|
// Find Track
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
if (IsAudio(stream_index)) {
|
if (pFrameNo < aTrakAtom->FrameCount()) {
|
||||||
// FrameNo is really chunk No for audio
|
// Get Sample for Frame
|
||||||
uint32 ChunkNo = pFrameNo;
|
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
|
// 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()) {
|
if (ChunkID != 0) {
|
||||||
// Get Sample for Frame
|
uint32 SampleSize;
|
||||||
uint32 SampleNo = aTrakAtom->getSampleForFrame(pFrameNo);
|
// Adjust the Offset for the Offset in the chunk
|
||||||
// Get Chunk For Sample and the offset for the frame within that chunk
|
if (aTrakAtom->IsSingleSampleSize()) {
|
||||||
uint32 OffsetInChunk;
|
SampleSize = aTrakAtom->getSizeForSample(SampleNo);
|
||||||
uint32 ChunkNo = aTrakAtom->getChunkForSample(SampleNo, &OffsetInChunk);
|
OffsetNo = OffsetNo + (OffsetInChunk * SampleSize);
|
||||||
// Get Offset For Chunk
|
} else {
|
||||||
uint64 OffsetNo = aTrakAtom->getOffsetForChunk(ChunkNo);
|
// This is bad news performance wise
|
||||||
|
for (uint32 i=1;i<=OffsetInChunk;i++) {
|
||||||
if (ChunkNo != 0) {
|
SampleSize = aTrakAtom->getSizeForSample(SampleNo - i);
|
||||||
uint32 SampleSize;
|
OffsetNo = OffsetNo + 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
|
uint32
|
||||||
MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber)
|
MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNo)
|
||||||
{
|
{
|
||||||
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
AtomBase *aAtomBase = GetChildAtom(uint32('trak'), streamIndex);
|
||||||
if (aAtomBase == NULL)
|
if (aAtomBase == NULL)
|
||||||
@@ -576,17 +565,22 @@ MOVFileReader::getChunkSize(uint32 streamIndex, uint32 frameNumber)
|
|||||||
|
|
||||||
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
|
||||||
|
|
||||||
if (IsAudio(streamIndex)) {
|
if (frameNo < aTrakAtom->FrameCount()) {
|
||||||
// We read audio in chunk by chunk so chunk size is chunk size
|
uint32 SampleNo = aTrakAtom->getSampleForFrame(frameNo);
|
||||||
off_t chunkStart = aTrakAtom->getOffsetForChunk(frameNumber);
|
|
||||||
return theChunkSuperIndex.getChunkSize(streamIndex, frameNumber, chunkStart);
|
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)) {
|
off_t chunkStart = aTrakAtom->getOffsetForChunk(ChunkID);
|
||||||
if (frameNumber < aTrakAtom->FrameCount()) {
|
return theChunkSuperIndex.getChunkSize(streamIndex, ChunkID, chunkStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsVideo(streamIndex)) {
|
||||||
// We read video in Sample by Sample so chunk size is Sample Size
|
// We read video in Sample by Sample so chunk size is Sample Size
|
||||||
uint32 sampleNumber = aTrakAtom->getSampleForFrame(frameNumber);
|
return aTrakAtom->getSizeForSample(SampleNo);
|
||||||
return aTrakAtom->getSizeForSample(sampleNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -608,16 +602,23 @@ MOVFileReader::IsKeyFrame(uint32 stream_index, uint32 pFrameNo)
|
|||||||
return false;
|
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);
|
*size = getChunkSize(stream_index, pFrameNo);
|
||||||
|
|
||||||
if ((*start > 0) && (*size > 0)) {
|
if ((*start > 0) && (*size > 0)) {
|
||||||
*keyframe = IsKeyFrame(stream_index, pFrameNo);
|
*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)
|
bool MOVFileReader::IsActive(uint32 stream_index)
|
||||||
|
|||||||
@@ -98,10 +98,10 @@ public:
|
|||||||
// Is stream (track) a audio track
|
// Is stream (track) a audio track
|
||||||
bool IsAudio(uint32 stream_index);
|
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);
|
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);
|
uint32 getChunkSize(uint32 stream_index, uint32 pFrameNo);
|
||||||
bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo);
|
bool IsKeyFrame(uint32 stream_index, uint32 pFrameNo);
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ public:
|
|||||||
|
|
||||||
bool IsActive(uint32 stream_index);
|
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
|
// Return all Audio Meta Data
|
||||||
const AudioMetaData *AudioFormat(uint32 stream_index);
|
const AudioMetaData *AudioFormat(uint32 stream_index);
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ AtomBase *getAtom(BPositionIO *pStream)
|
|||||||
return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aAtomType == uint32('avcC')) {
|
||||||
|
return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (aAtomType == uint32('ftyp')) {
|
if (aAtomType == uint32('ftyp')) {
|
||||||
return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
}
|
}
|
||||||
@@ -645,7 +649,6 @@ SampleSizeEntry *aSampleSize;
|
|||||||
|
|
||||||
char *STSZAtom::OnGetAtomName()
|
char *STSZAtom::OnGetAtomName()
|
||||||
{
|
{
|
||||||
printf("%ld ",theHeader.SampleSize);
|
|
||||||
return "Sample Size Atom";
|
return "Sample Size Atom";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -559,9 +559,9 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
{
|
{
|
||||||
mov_cookie *cookie = (mov_cookie *)_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;
|
return B_LAST_BUFFER_ERROR;
|
||||||
|
|
||||||
if (cookie->buffer_size < size) {
|
if (cookie->buffer_size < size) {
|
||||||
@@ -577,12 +577,12 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
|
|
||||||
// This will only work with raw audio I think.
|
// 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;
|
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
|
// 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;
|
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;
|
cookie->byte_pos += size;
|
||||||
} else {
|
} else {
|
||||||
@@ -594,7 +594,7 @@ movReader::GetNextChunk(void *_cookie,
|
|||||||
mediaHeader->u.encoded_video.line_count = cookie->line_count;
|
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);
|
TRACE("stream %d: start_time %.6f\n", cookie->stream, mediaHeader->start_time / 1000000.0);
|
||||||
|
|
||||||
*chunkBuffer = cookie->buffer;
|
*chunkBuffer = cookie->buffer;
|
||||||
|
|||||||
Reference in New Issue
Block a user