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:
+59
-33
@@ -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;
|
||||
}
|
||||
+19
-24
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user