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:
parent
2fcd430e35
commit
a658e5df2d
@ -86,7 +86,7 @@ bool AtomBase::MoveToEnd()
|
||||
off_t NewPosition = streamOffset + atomSize;
|
||||
|
||||
if (getStream()->Position() != NewPosition) {
|
||||
return (getStream()->Seek(NewPosition,0) > 0);
|
||||
return (getStream()->Seek(NewPosition,SEEK_SET) > 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -104,6 +104,8 @@ public:
|
||||
off_t getAtomOffset() {return atomOffset;};
|
||||
off_t getStreamOffset() {return streamOffset;};
|
||||
|
||||
uint64 getDataSize() {return atomSize - 8;};
|
||||
|
||||
uint64 getBytesRemaining();
|
||||
|
||||
bool IsType(uint32 patomType) {return patomType == atomType;};
|
||||
|
@ -459,6 +459,9 @@ const AudioMetaData *MOVFileReader::AudioFormat(uint32 stream_index, size_t *
|
||||
theAudio.SampleSize = aSoundDescription.desc.SampleSize;
|
||||
theAudio.SampleRate = aSoundDescription.desc.SampleRate / 65536; // Convert from fixed point decimal to float
|
||||
theAudio.PacketSize = uint32((theAudio.SampleRate * theAudio.NoOfChannels * theAudio.SampleSize) / 8);
|
||||
|
||||
theAudio.theVOL = aSoundDescription.theVOL;
|
||||
theAudio.VOLSize = aSoundDescription.VOLSize;
|
||||
|
||||
// // Do we have a wave structure
|
||||
// if ((aSoundDescription.samplesPerPacket == 0) && (aSoundDescription.theWaveFormat.format_tag != 0)) {
|
||||
@ -502,6 +505,9 @@ const VideoMetaData *MOVFileReader::VideoFormat(uint32 stream_index)
|
||||
theVideo.HorizontalResolution = aVideoDescriptionV0.desc.HorizontalResolution;
|
||||
theVideo.VerticalResolution = aVideoDescriptionV0.desc.VerticalResolution;
|
||||
|
||||
theVideo.theVOL = aVideoDescriptionV0.theVOL;
|
||||
theVideo.VOLSize = aVideoDescriptionV0.VOLSize;
|
||||
|
||||
aAtomBase = aTrakAtom->GetChildAtom(uint32('stts'),0);
|
||||
if (aAtomBase) {
|
||||
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
|
||||
|
@ -173,6 +173,10 @@ AtomBase *getAtom(BPositionIO *pStream)
|
||||
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);
|
||||
|
||||
}
|
||||
@ -718,6 +722,34 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
||||
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)
|
||||
{
|
||||
theHeader.NoEntries = 0;
|
||||
@ -727,11 +759,21 @@ STSDAtom::~STSDAtom()
|
||||
{
|
||||
if (getMediaComponentSubType() == 'soun') {
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
if (theAudioDescArray[i]->theVOL) {
|
||||
free(theAudioDescArray[i]->theVOL);
|
||||
theAudioDescArray[i]->theVOL = NULL;
|
||||
}
|
||||
|
||||
delete theAudioDescArray[i];
|
||||
theAudioDescArray[i] = NULL;
|
||||
}
|
||||
} else if (getMediaComponentSubType() == 'vide') {
|
||||
for (uint32 i=0;i<theHeader.NoEntries;i++) {
|
||||
if (theVideoDescArray[i]->theVOL) {
|
||||
free(theVideoDescArray[i]->theVOL);
|
||||
theVideoDescArray[i]->theVOL = NULL;
|
||||
}
|
||||
|
||||
delete theVideoDescArray[i];
|
||||
theVideoDescArray[i] = NULL;
|
||||
}
|
||||
@ -755,6 +797,9 @@ void STSDAtom::ReadSoundDescription()
|
||||
Read(aSoundDescriptionV1->basefields.Reserved,6);
|
||||
Read(&aSoundDescriptionV1->basefields.DataReference);
|
||||
|
||||
aSoundDescriptionV1->VOLSize = 0;
|
||||
aSoundDescriptionV1->theVOL = NULL;
|
||||
|
||||
// Read in Audio Sample Data
|
||||
// We place into a V1 description even though it might be a V0 or earlier
|
||||
|
||||
@ -802,7 +847,14 @@ void STSDAtom::ReadSoundDescription()
|
||||
// WAVE atom
|
||||
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) {
|
||||
descBytesLeft = descBytesLeft - aAtomBase->getAtomSize();
|
||||
} else {
|
||||
@ -811,7 +863,6 @@ void STSDAtom::ReadSoundDescription()
|
||||
}
|
||||
|
||||
delete aAtomBase;
|
||||
|
||||
}
|
||||
|
||||
theAudioDescArray[0] = aSoundDescriptionV1;
|
||||
@ -821,6 +872,8 @@ void STSDAtom::ReadSoundDescription()
|
||||
|
||||
void STSDAtom::ReadVideoDescription()
|
||||
{
|
||||
uint64 descBytesLeft;
|
||||
|
||||
// read in Video Sample Data
|
||||
VideoDescriptionV0 *aVideoDescription;
|
||||
|
||||
@ -830,7 +883,7 @@ void STSDAtom::ReadVideoDescription()
|
||||
Read(&aVideoDescription->basefields.DataFormat);
|
||||
Read(aVideoDescription->basefields.Reserved,6);
|
||||
Read(&aVideoDescription->basefields.DataReference);
|
||||
|
||||
|
||||
Read(&aVideoDescription->desc.Version);
|
||||
Read(&aVideoDescription->desc.Revision);
|
||||
Read(&aVideoDescription->desc.Vendor);
|
||||
@ -847,8 +900,38 @@ void STSDAtom::ReadVideoDescription()
|
||||
Read(&aVideoDescription->desc.Depth);
|
||||
Read(&aVideoDescription->desc.ColourTableID);
|
||||
|
||||
aVideoDescription->VOLSize = 0;
|
||||
aVideoDescription->theVOL = NULL;
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
@ -872,8 +955,10 @@ void STSDAtom::OnProcessMetaData()
|
||||
Read(&aSampleDescBase.DataFormat);
|
||||
Read(aSampleDescBase.Reserved,6);
|
||||
Read(&aSampleDescBase.DataReference);
|
||||
|
||||
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, 0);
|
||||
theStream->Seek(aSampleDescBase.Size - SampleDescBaseSize, SEEK_CUR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -254,6 +254,18 @@ public:
|
||||
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
|
||||
class STSDAtom : public AtomBase {
|
||||
public:
|
||||
@ -293,7 +305,7 @@ public:
|
||||
// 0x008 Track in Poster
|
||||
// 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:
|
||||
tkhdV1 theHeader;
|
||||
|
@ -92,6 +92,8 @@ struct VideoMetaData
|
||||
uint32 HorizontalResolution;
|
||||
uint32 VerticalResolution;
|
||||
float FrameRate;
|
||||
uint8 *theVOL;
|
||||
size_t VOLSize;
|
||||
};
|
||||
|
||||
struct AudioMetaData
|
||||
@ -101,6 +103,8 @@ struct AudioMetaData
|
||||
uint16 SampleSize; // bits per sample
|
||||
float SampleRate; // Samples per second (OR Frames per second)
|
||||
uint32 PacketSize; // (Sample Rate * NoOfchannels * SampleSize)/8 = bytes per second
|
||||
uint8 *theVOL;
|
||||
size_t VOLSize;
|
||||
};
|
||||
|
||||
struct wave_format_ex
|
||||
@ -306,6 +310,8 @@ struct SoundDescriptionV1 {
|
||||
uint32 bytesPerSample;
|
||||
// These are optional data from atoms that follow
|
||||
wave_format_ex theWaveFormat; // wave atom is a copy of wave_format_ex
|
||||
uint8 *theVOL;
|
||||
size_t VOLSize;
|
||||
};
|
||||
|
||||
struct VideoDescription {
|
||||
@ -331,4 +337,6 @@ struct VideoDescription {
|
||||
struct VideoDescriptionV0 {
|
||||
SampleDescBase basefields;
|
||||
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("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;
|
||||
}
|
||||
|
||||
|
@ -899,7 +899,10 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
|
||||
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();
|
||||
return 0LL;
|
||||
|
@ -427,17 +427,19 @@ mp4Reader::AllocateCookie(int32 streamNumber, void **_cookie)
|
||||
TRACE("field_rate %.3f\n", format->u.encoded_video.output.field_rate);
|
||||
|
||||
// Set the VOL
|
||||
size_t size = video_format->VOLSize;
|
||||
const void *data = video_format->theVOL;
|
||||
format->SetMetaData(data, size);
|
||||
if (video_format->VOLSize > 0) {
|
||||
size_t size = video_format->VOLSize;
|
||||
const void *data = video_format->theVOL;
|
||||
format->SetMetaData(data, size);
|
||||
|
||||
#ifdef TRACE_MP4_READER
|
||||
if (data) {
|
||||
uint8 *p = (uint8 *)data;
|
||||
TRACE("extra_data: %ld: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
size, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
|
||||
}
|
||||
if (data) {
|
||||
uint8 *p = (uint8 *)data;
|
||||
TRACE("extra_data: %ld: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
size, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user