added support to MOV for MPEG4 video
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14026 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -86,7 +86,7 @@ bool AtomBase::MoveToEnd()
|
|||||||
off_t NewPosition = streamOffset + atomSize;
|
off_t NewPosition = streamOffset + atomSize;
|
||||||
|
|
||||||
if (getStream()->Position() != NewPosition) {
|
if (getStream()->Position() != NewPosition) {
|
||||||
return (getStream()->Seek(NewPosition,0) > 0);
|
return (getStream()->Seek(NewPosition,SEEK_SET) > 0);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,8 @@ public:
|
|||||||
off_t getAtomOffset() {return atomOffset;};
|
off_t getAtomOffset() {return atomOffset;};
|
||||||
off_t getStreamOffset() {return streamOffset;};
|
off_t getStreamOffset() {return streamOffset;};
|
||||||
|
|
||||||
|
uint64 getDataSize() {return atomSize - 8;};
|
||||||
|
|
||||||
uint64 getBytesRemaining();
|
uint64 getBytesRemaining();
|
||||||
|
|
||||||
bool IsType(uint32 patomType) {return patomType == atomType;};
|
bool IsType(uint32 patomType) {return patomType == atomType;};
|
||||||
|
|||||||
@@ -460,6 +460,9 @@ const AudioMetaData *MOVFileReader::AudioFormat(uint32 stream_index, size_t *
|
|||||||
theAudio.SampleRate = aSoundDescription.desc.SampleRate / 65536; // Convert from fixed point decimal to float
|
theAudio.SampleRate = aSoundDescription.desc.SampleRate / 65536; // Convert from fixed point decimal to float
|
||||||
theAudio.PacketSize = uint32((theAudio.SampleRate * theAudio.NoOfChannels * theAudio.SampleSize) / 8);
|
theAudio.PacketSize = uint32((theAudio.SampleRate * theAudio.NoOfChannels * theAudio.SampleSize) / 8);
|
||||||
|
|
||||||
|
theAudio.theVOL = aSoundDescription.theVOL;
|
||||||
|
theAudio.VOLSize = aSoundDescription.VOLSize;
|
||||||
|
|
||||||
// // Do we have a wave structure
|
// // Do we have a wave structure
|
||||||
// if ((aSoundDescription.samplesPerPacket == 0) && (aSoundDescription.theWaveFormat.format_tag != 0)) {
|
// if ((aSoundDescription.samplesPerPacket == 0) && (aSoundDescription.theWaveFormat.format_tag != 0)) {
|
||||||
// theAudio.PacketSize = aSoundDescription.theWaveFormat.frames_per_sec;
|
// theAudio.PacketSize = aSoundDescription.theWaveFormat.frames_per_sec;
|
||||||
@@ -502,6 +505,9 @@ const VideoMetaData *MOVFileReader::VideoFormat(uint32 stream_index)
|
|||||||
theVideo.HorizontalResolution = aVideoDescriptionV0.desc.HorizontalResolution;
|
theVideo.HorizontalResolution = aVideoDescriptionV0.desc.HorizontalResolution;
|
||||||
theVideo.VerticalResolution = aVideoDescriptionV0.desc.VerticalResolution;
|
theVideo.VerticalResolution = aVideoDescriptionV0.desc.VerticalResolution;
|
||||||
|
|
||||||
|
theVideo.theVOL = aVideoDescriptionV0.theVOL;
|
||||||
|
theVideo.VOLSize = aVideoDescriptionV0.VOLSize;
|
||||||
|
|
||||||
aAtomBase = aTrakAtom->GetChildAtom(uint32('stts'),0);
|
aAtomBase = aTrakAtom->GetChildAtom(uint32('stts'),0);
|
||||||
if (aAtomBase) {
|
if (aAtomBase) {
|
||||||
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
|
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
|
||||||
|
|||||||
@@ -173,6 +173,10 @@ AtomBase *getAtom(BPositionIO *pStream)
|
|||||||
return new CMVDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
return new CMVDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aAtomType == uint32('esds')) {
|
||||||
|
return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
|
}
|
||||||
|
|
||||||
return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -718,6 +722,34 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
|||||||
return 0LL;
|
return 0LL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||||
|
{
|
||||||
|
theVOL = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESDSAtom::~ESDSAtom()
|
||||||
|
{
|
||||||
|
if (theVOL) {
|
||||||
|
free(theVOL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ESDSAtom::OnProcessMetaData()
|
||||||
|
{
|
||||||
|
theVOL = (uint8 *)(malloc(getBytesRemaining()));
|
||||||
|
Read(theVOL,getBytesRemaining());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 *ESDSAtom::getVOL()
|
||||||
|
{
|
||||||
|
return theVOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *ESDSAtom::OnGetAtomName()
|
||||||
|
{
|
||||||
|
return "Extended Sample Description Atom";
|
||||||
|
}
|
||||||
|
|
||||||
STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
|
||||||
{
|
{
|
||||||
theHeader.NoEntries = 0;
|
theHeader.NoEntries = 0;
|
||||||
@@ -727,11 +759,21 @@ STSDAtom::~STSDAtom()
|
|||||||
{
|
{
|
||||||
if (getMediaComponentSubType() == 'soun') {
|
if (getMediaComponentSubType() == 'soun') {
|
||||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||||
|
if (theAudioDescArray[i]->theVOL) {
|
||||||
|
free(theAudioDescArray[i]->theVOL);
|
||||||
|
theAudioDescArray[i]->theVOL = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
delete theAudioDescArray[i];
|
delete theAudioDescArray[i];
|
||||||
theAudioDescArray[i] = NULL;
|
theAudioDescArray[i] = NULL;
|
||||||
}
|
}
|
||||||
} else if (getMediaComponentSubType() == 'vide') {
|
} else if (getMediaComponentSubType() == 'vide') {
|
||||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||||
|
if (theVideoDescArray[i]->theVOL) {
|
||||||
|
free(theVideoDescArray[i]->theVOL);
|
||||||
|
theVideoDescArray[i]->theVOL = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
delete theVideoDescArray[i];
|
delete theVideoDescArray[i];
|
||||||
theVideoDescArray[i] = NULL;
|
theVideoDescArray[i] = NULL;
|
||||||
}
|
}
|
||||||
@@ -755,6 +797,9 @@ void STSDAtom::ReadSoundDescription()
|
|||||||
Read(aSoundDescriptionV1->basefields.Reserved,6);
|
Read(aSoundDescriptionV1->basefields.Reserved,6);
|
||||||
Read(&aSoundDescriptionV1->basefields.DataReference);
|
Read(&aSoundDescriptionV1->basefields.DataReference);
|
||||||
|
|
||||||
|
aSoundDescriptionV1->VOLSize = 0;
|
||||||
|
aSoundDescriptionV1->theVOL = NULL;
|
||||||
|
|
||||||
// Read in Audio Sample Data
|
// Read in Audio Sample Data
|
||||||
// We place into a V1 description even though it might be a V0 or earlier
|
// We place into a V1 description even though it might be a V0 or earlier
|
||||||
|
|
||||||
@@ -803,6 +848,13 @@ void STSDAtom::ReadSoundDescription()
|
|||||||
aSoundDescriptionV1->theWaveFormat = dynamic_cast<WAVEAtom *>(aAtomBase)->getWaveFormat();
|
aSoundDescriptionV1->theWaveFormat = dynamic_cast<WAVEAtom *>(aAtomBase)->getWaveFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dynamic_cast<ESDSAtom *>(aAtomBase)) {
|
||||||
|
// ESDS atom good
|
||||||
|
aSoundDescriptionV1->VOLSize = aAtomBase->getDataSize();
|
||||||
|
aSoundDescriptionV1->theVOL = (uint8 *)(malloc(aSoundDescriptionV1->VOLSize));
|
||||||
|
memcpy(aSoundDescriptionV1->theVOL,dynamic_cast<ESDSAtom *>(aAtomBase)->getVOL(),aSoundDescriptionV1->VOLSize);
|
||||||
|
}
|
||||||
|
|
||||||
if (aAtomBase->getAtomSize() > 0) {
|
if (aAtomBase->getAtomSize() > 0) {
|
||||||
descBytesLeft = descBytesLeft - aAtomBase->getAtomSize();
|
descBytesLeft = descBytesLeft - aAtomBase->getAtomSize();
|
||||||
} else {
|
} else {
|
||||||
@@ -811,7 +863,6 @@ void STSDAtom::ReadSoundDescription()
|
|||||||
}
|
}
|
||||||
|
|
||||||
delete aAtomBase;
|
delete aAtomBase;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
theAudioDescArray[0] = aSoundDescriptionV1;
|
theAudioDescArray[0] = aSoundDescriptionV1;
|
||||||
@@ -821,6 +872,8 @@ void STSDAtom::ReadSoundDescription()
|
|||||||
|
|
||||||
void STSDAtom::ReadVideoDescription()
|
void STSDAtom::ReadVideoDescription()
|
||||||
{
|
{
|
||||||
|
uint64 descBytesLeft;
|
||||||
|
|
||||||
// read in Video Sample Data
|
// read in Video Sample Data
|
||||||
VideoDescriptionV0 *aVideoDescription;
|
VideoDescriptionV0 *aVideoDescription;
|
||||||
|
|
||||||
@@ -847,8 +900,38 @@ void STSDAtom::ReadVideoDescription()
|
|||||||
Read(&aVideoDescription->desc.Depth);
|
Read(&aVideoDescription->desc.Depth);
|
||||||
Read(&aVideoDescription->desc.ColourTableID);
|
Read(&aVideoDescription->desc.ColourTableID);
|
||||||
|
|
||||||
|
aVideoDescription->VOLSize = 0;
|
||||||
|
aVideoDescription->theVOL = NULL;
|
||||||
|
|
||||||
theVideoDescArray[0] = aVideoDescription;
|
theVideoDescArray[0] = aVideoDescription;
|
||||||
|
|
||||||
|
descBytesLeft = getBytesRemaining();
|
||||||
|
|
||||||
|
// May be a VOL
|
||||||
|
// If not then seek back to where we are as it may be a complete new video description
|
||||||
|
|
||||||
|
if (descBytesLeft > 0) {
|
||||||
|
|
||||||
|
off_t pos = theStream->Position();
|
||||||
|
// More extended atoms
|
||||||
|
AtomBase *aAtomBase = getAtom(theStream);
|
||||||
|
|
||||||
|
aAtomBase->OnProcessMetaData();
|
||||||
|
printf("%s\n",aAtomBase->getAtomName());
|
||||||
|
|
||||||
|
if (dynamic_cast<ESDSAtom *>(aAtomBase)) {
|
||||||
|
// ESDS atom good
|
||||||
|
aVideoDescription->VOLSize = aAtomBase->getDataSize();
|
||||||
|
aVideoDescription->theVOL = (uint8 *)(malloc(aVideoDescription->VOLSize));
|
||||||
|
memcpy(aVideoDescription->theVOL,dynamic_cast<ESDSAtom *>(aAtomBase)->getVOL(),aVideoDescription->VOLSize);
|
||||||
|
} else {
|
||||||
|
// Seek Back
|
||||||
|
theStream->Seek(pos,SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete aAtomBase;
|
||||||
|
}
|
||||||
|
|
||||||
PRINT(("Size:Format=%ld:%ld %Ld\n",aVideoDescription->basefields.Size,aVideoDescription->basefields.DataFormat,getBytesRemaining()));
|
PRINT(("Size:Format=%ld:%ld %Ld\n",aVideoDescription->basefields.Size,aVideoDescription->basefields.DataFormat,getBytesRemaining()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -873,7 +956,9 @@ void STSDAtom::OnProcessMetaData()
|
|||||||
Read(aSampleDescBase.Reserved,6);
|
Read(aSampleDescBase.Reserved,6);
|
||||||
Read(&aSampleDescBase.DataReference);
|
Read(&aSampleDescBase.DataReference);
|
||||||
|
|
||||||
theStream->Seek(aSampleDescBase.Size - SampleDescBaseSize, 0);
|
printf("%c%c%c%c\n",char(aSampleDescBase.DataFormat>>24),char(aSampleDescBase.DataFormat>>16),char(aSampleDescBase.DataFormat>>8),char(aSampleDescBase.DataFormat));
|
||||||
|
|
||||||
|
theStream->Seek(aSampleDescBase.Size - SampleDescBaseSize, SEEK_CUR);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,6 +254,18 @@ public:
|
|||||||
off_t getEOF();
|
off_t getEOF();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ESDSAtom : public AtomBase {
|
||||||
|
public:
|
||||||
|
ESDSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize);
|
||||||
|
virtual ~ESDSAtom();
|
||||||
|
void OnProcessMetaData();
|
||||||
|
char *OnGetAtomName();
|
||||||
|
|
||||||
|
uint8 *getVOL();
|
||||||
|
private:
|
||||||
|
uint8 *theVOL;
|
||||||
|
};
|
||||||
|
|
||||||
// Atom class for reading the sdst atom
|
// Atom class for reading the sdst atom
|
||||||
class STSDAtom : public AtomBase {
|
class STSDAtom : public AtomBase {
|
||||||
public:
|
public:
|
||||||
@@ -293,7 +305,7 @@ public:
|
|||||||
// 0x008 Track in Poster
|
// 0x008 Track in Poster
|
||||||
// It seems active tracks have all 4 flags set?
|
// It seems active tracks have all 4 flags set?
|
||||||
|
|
||||||
bool IsActive() {return (theHeader.Flags3 == 0x0f);};
|
bool IsActive() {return ((theHeader.Flags3 == 0x0f) || (theHeader.Flags3 == 0x03));};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
tkhdV1 theHeader;
|
tkhdV1 theHeader;
|
||||||
|
|||||||
@@ -92,6 +92,8 @@ struct VideoMetaData
|
|||||||
uint32 HorizontalResolution;
|
uint32 HorizontalResolution;
|
||||||
uint32 VerticalResolution;
|
uint32 VerticalResolution;
|
||||||
float FrameRate;
|
float FrameRate;
|
||||||
|
uint8 *theVOL;
|
||||||
|
size_t VOLSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AudioMetaData
|
struct AudioMetaData
|
||||||
@@ -101,6 +103,8 @@ struct AudioMetaData
|
|||||||
uint16 SampleSize; // bits per sample
|
uint16 SampleSize; // bits per sample
|
||||||
float SampleRate; // Samples per second (OR Frames per second)
|
float SampleRate; // Samples per second (OR Frames per second)
|
||||||
uint32 PacketSize; // (Sample Rate * NoOfchannels * SampleSize)/8 = bytes per second
|
uint32 PacketSize; // (Sample Rate * NoOfchannels * SampleSize)/8 = bytes per second
|
||||||
|
uint8 *theVOL;
|
||||||
|
size_t VOLSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wave_format_ex
|
struct wave_format_ex
|
||||||
@@ -306,6 +310,8 @@ struct SoundDescriptionV1 {
|
|||||||
uint32 bytesPerSample;
|
uint32 bytesPerSample;
|
||||||
// These are optional data from atoms that follow
|
// These are optional data from atoms that follow
|
||||||
wave_format_ex theWaveFormat; // wave atom is a copy of wave_format_ex
|
wave_format_ex theWaveFormat; // wave atom is a copy of wave_format_ex
|
||||||
|
uint8 *theVOL;
|
||||||
|
size_t VOLSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoDescription {
|
struct VideoDescription {
|
||||||
@@ -331,4 +337,6 @@ struct VideoDescription {
|
|||||||
struct VideoDescriptionV0 {
|
struct VideoDescriptionV0 {
|
||||||
SampleDescBase basefields;
|
SampleDescBase basefields;
|
||||||
VideoDescription desc;
|
VideoDescription desc;
|
||||||
|
uint8 *theVOL;
|
||||||
|
size_t VOLSize;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -402,6 +402,14 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
TRACE("max_bit_rate %.3f\n", format->u.encoded_video.max_bit_rate);
|
TRACE("max_bit_rate %.3f\n", format->u.encoded_video.max_bit_rate);
|
||||||
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
||||||
|
|
||||||
|
// Set the VOL
|
||||||
|
if (video_format->VOLSize > 0) {
|
||||||
|
TRACE("VOL SIZE %ld\n", video_format->VOLSize);
|
||||||
|
size_t size = video_format->VOLSize;
|
||||||
|
const void *data = video_format->theVOL;
|
||||||
|
format->SetMetaData(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -899,7 +899,10 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
|||||||
return theChunkToOffsetArray[pChunkID - 1]->Offset;
|
return theChunkToOffsetArray[pChunkID - 1]->Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUGGER(("Bad Chunk ID %ld / %ld\n",pChunkID,theHeader.NoEntries));
|
#if DEBUG
|
||||||
|
char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkID, theHeader.NoEntries);
|
||||||
|
DEBUGGER(msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
TRESPASS();
|
TRESPASS();
|
||||||
return 0LL;
|
return 0LL;
|
||||||
|
|||||||
@@ -427,6 +427,7 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
||||||
|
|
||||||
// Set the VOL
|
// Set the VOL
|
||||||
|
if (video_format->VOLSize > 0) {
|
||||||
size_t size = video_format->VOLSize;
|
size_t size = video_format->VOLSize;
|
||||||
const void *data = video_format->theVOL;
|
const void *data = video_format->theVOL;
|
||||||
format->SetMetaData(data, size);
|
format->SetMetaData(data, size);
|
||||||
@@ -438,6 +439,7 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
|||||||
size, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
|
size, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user