Code Cleanup, Performance improvements, Seeking Improvements. Audio Seek still not quite right though.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37165 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul
2010-06-18 09:16:05 +00:00
parent 0df61fa3dc
commit 7436ac49e5
11 changed files with 771 additions and 640 deletions
@@ -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 <math.h>
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;
}
@@ -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 <SupportDefs.h>
#include <map>
struct ChunkIndex {
uint32 stream;
uint32 chunkid;
off_t chunk_start;
};
typedef ChunkIndex* ChunkIndexPtr;
typedef std::map<off_t, ChunkIndexPtr, std::less<off_t> > 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
@@ -7,5 +7,5 @@ StaticLibrary libmp4reader.a :
MP4FileReader.cpp
MP4Atom.cpp
MP4TrakAtom.cpp
ChunkSuperIndex.cpp
BitParser.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;
@@ -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
@@ -33,7 +33,7 @@
#include <iostream>
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;index<CountChildAtoms('mdat');index++) {
for (uint32 index=0; index < CountChildAtoms('mdat'); index++) {
aAtomBase = GetChildAtom(uint32('mdat'),index);
if ((aAtomBase) && (aAtomBase->getAtomSize() > 8)) {
if ((aAtomBase) && (aAtomBase->GetAtomSize() > 8)) {
MDATAtom *aMDATAtom = dynamic_cast<MDATAtom *>(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<TRAKAtom *>(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<getStreamCount();stream++) {
aAtomBase = GetChildAtom(uint32('trak'),stream);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(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<MDATAtom *>(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<TRAKAtom *>(aAtomBase)->IsVideo())
return dynamic_cast<TRAKAtom *>(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<TRAKAtom *>(aAtomBase)->IsAudio())
return dynamic_cast<TRAKAtom *>(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<TRAKAtom *>(aAtomBase)->IsActive())) {
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio()) {
for (uint32 i = 0; i < GetStreamCount(); i++) {
if (GetTrack(i)->IsActive()) {
if (GetTrack(i)->IsAudio()) {
audioIndex = int32(i);
}
if (dynamic_cast<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(aAtomBase)->IsAudio())
return dynamic_cast<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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;i<TotalChildren;i++) {
atomChildren[i]->DisplayAtoms();
}
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<STSDAtom *>(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<STSDAtom *>(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<STTSAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(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<TRAKAtom *>(aAtomBase);
return aTrakAtom->IsActive();
return dynamic_cast<TRAKAtom *>(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<FTYPAtom *>(aAtom)) {
aAtom->ProcessMetaData();
@@ -31,7 +31,6 @@
#include <SupportDefs.h>
#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<uint32, TRAKAtom*, std::less<uint32> > 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);
@@ -28,16 +28,13 @@
#include <SupportKit.h>
#include <MediaFormats.h>
#ifdef __HAIKU__
#include <libs/zlib/zlib.h>
#else
#include <zlib.h>
#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<DCOMAtom *>(aAtomBase)) {
// DCOM atom
compressionID = dynamic_cast<DCOMAtom *>(aAtomBase)->getCompressionID();
compressionID = dynamic_cast<DCOMAtom *>(aAtomBase)->GetCompressionID();
delete aAtomBase;
} else {
if (dynamic_cast<CMVDAtom *>(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;i<theHeader.NoEntries;i++) {
aTimeToSample = new TimeToSample;
@@ -508,11 +502,7 @@ TimeToSample *aTimeToSample;
theTimeToSampleArray[i] = aTimeToSample;
SUMDurations += (theTimeToSampleArray[i]->Duration * 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;i<theHeader.NoEntries;i++) {
aSampleToChunk = new SampleToChunk;
@@ -622,11 +610,8 @@ SampleToChunk *aSampleToChunk;
aSampleToChunk->TotalPrevSamples = 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;i<theHeader.NoEntries;i++) {
if (theSampleToChunkArray[i]->FirstChunk > 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<STBLAtom *>(getParent())->getMediaHandlerType();
return dynamic_cast<STBLAtom *>(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<DecoderConfigAtom *>(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<MDIAAtom *>(getParent())->getMediaHandlerType();
return dynamic_cast<MDIAAtom *>(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<MINFAtom *>(getParent())->getMediaHandlerType();
return dynamic_cast<MINFAtom *>(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<HDLRAtom *>(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)
{
}
@@ -40,23 +40,23 @@ typedef std::map<uint32, CompTimeToSamplePtr, std::less<uint32> > CompTimeToSamp
typedef TimeToSample* TimeToSamplePtr;
typedef std::map<uint32, TimeToSamplePtr, std::less<uint32> > TimeToSampleArray;
typedef SampleToChunk* SampleToChunkPtr;
typedef std::map<uint32, SampleToChunkPtr, std::less<uint32> > SampleToChunkArray;
typedef std::vector<SampleToChunkPtr> SampleToChunkArray;
typedef ChunkToOffset* ChunkToOffsetPtr;
typedef std::map<uint32, ChunkToOffsetPtr, std::less<uint32> > ChunkToOffsetArray;
typedef SyncSample* SyncSamplePtr;
typedef std::map<uint32, SyncSamplePtr, std::less<uint32> > SyncSampleArray;
typedef std::vector<SyncSamplePtr> SyncSampleArray;
typedef SampleSizeEntry* SampleSizePtr;
typedef std::map<uint32, SampleSizePtr, std::less<uint32> > SampleSizeArray;
typedef std::vector<SampleSizePtr> 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;
@@ -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<STTSAtom *>(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<STSDAtom *>(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<STSDAtom *>(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<STTSAtom *>(aAtomBase))->getSampleForTime(pTime);
return (dynamic_cast<STTSAtom *>(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<STTSAtom *>(aAtomBase))->getSampleForTime(getTimeForFrame(pFrame));
return (dynamic_cast<STTSAtom *>(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<STSCAtom *>(aAtomBase))->getChunkForSample(pSample, pOffsetInChunk);
return (dynamic_cast<STSCAtom *>(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<STSCAtom *>(aAtomBase))->getNoSamplesInChunk(pChunkID);
return (dynamic_cast<STSCAtom *>(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<STSZAtom *>(aAtomBase))->getSizeForSample(pSample);
return (dynamic_cast<STSZAtom *>(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<STCOAtom *>(aAtomBase))->getOffsetForChunk(pChunkID);
return (dynamic_cast<STCOAtom *>(aAtomBase))->GetOffsetForChunk(pChunkIndex);
}
return 0;
}
uint32 TRAKAtom::getFirstSampleInChunk(uint32 pChunkID)
uint32 TRAKAtom::ChunkCount() {
AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
if (aAtomBase) {
return (dynamic_cast<STCOAtom *>(aAtomBase))->GetTotalChunks();
}
return 0;
}
uint32 TRAKAtom::GetFirstSampleInChunk(uint32 pChunkIndex)
{
AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
if (aAtomBase) {
return (dynamic_cast<STSCAtom *>(aAtomBase))->getFirstSampleInChunk(pChunkID);
return (dynamic_cast<STSCAtom *>(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<STSDAtom *>(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<STCOAtom *>(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<STCOAtom *>(aAtomBase))->GetTotalChunks();
}
return 0;
@@ -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;