Removed many bugs relating to multiple video tracks. Replaced these bugs with much more interesting ones

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13657 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
David McPaul 2005-07-13 12:59:02 +00:00
parent b39b6ee51c
commit 24af6494ea
8 changed files with 200 additions and 117 deletions

View File

@ -32,9 +32,11 @@ const struct codec_table gCodecTable[] = {
{CODEC_ID_PCM_ALAW, B_MEDIA_ENCODED_AUDIO, B_AIFF_FORMAT_FAMILY, 'alaw' , "aLaw"},
{CODEC_ID_PCM_ALAW, B_MEDIA_ENCODED_AUDIO, B_AIFF_FORMAT_FAMILY, 'ALAW' , "aLaw"},
{CODEC_ID_PCM_ALAW, B_MEDIA_ENCODED_AUDIO, B_MISC_FORMAT_FAMILY, (uint64('au') << 32) | 27, "aLaw"},
/*
{CODEC_ID_PCM_MULAW, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 'ulaw', "µLaw"},
*/
{CODEC_ID_PCM_ALAW, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 'alaw', "aLaw"},
{CODEC_ID_PCM_ALAW, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 'ALAW', "aLaw"},
{CODEC_ID_PCM_MULAW, B_MEDIA_ENCODED_AUDIO, B_WAV_FORMAT_FAMILY, 0x07, "µLaw"},
{CODEC_ID_PCM_MULAW, B_MEDIA_ENCODED_AUDIO, B_AIFF_FORMAT_FAMILY, 'ulaw', "µLaw"},
{CODEC_ID_PCM_MULAW, B_MEDIA_ENCODED_AUDIO, B_AIFF_FORMAT_FAMILY, 'ULAW', "µLaw"},
@ -44,7 +46,8 @@ const struct codec_table gCodecTable[] = {
{CODEC_ID_ADPCM_MS, B_MEDIA_ENCODED_AUDIO, B_WAV_FORMAT_FAMILY, 0x0002, "MS ADPCM"},
{CODEC_ID_ADPCM_IMA_WAV, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 0x6D730011, "IMA ADPCM"},
{CODEC_ID_ADPCM_MS, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 0x6D730002, "MS ADPCM"},
{CODEC_ID_MP3, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 0x6D730055, "MP3"},
{CODEC_ID_MP2, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 0x6D730050, "MP Layer2"},
{CODEC_ID_MP2, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 0x6D730055, "MP Layer3"},
#ifdef HAS_MACE_AUDIO
{CODEC_ID_MACE3, B_MEDIA_ENCODED_AUDIO, B_QUICKTIME_FORMAT_FAMILY, 'MAC3', "MACE 3:1"},

View File

@ -125,7 +125,7 @@ uint32 MOVFileReader::getMovieTimeScale()
bigtime_t MOVFileReader::getMovieDuration()
{
return ((bigtime_t(getMVHDAtom()->getDuration()) * 1000000) / getMovieTimeScale());
return ((bigtime_t(getMVHDAtom()->getDuration()) * 1000000L) / getMovieTimeScale());
}
uint32 MOVFileReader::getStreamCount()
@ -134,33 +134,27 @@ uint32 MOVFileReader::getStreamCount()
return (CountChildAtoms(uint32('trak')));
}
bigtime_t MOVFileReader::getVideoDuration()
bigtime_t MOVFileReader::getVideoDuration(uint32 stream_index)
{
AtomBase *aAtomBase;
uint32 TimeScale = getMovieTimeScale();
for (uint32 i=0;i<getStreamCount();i++) {
aAtomBase = GetChildAtom(uint32('trak'),i);
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(TimeScale));
}
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
}
return 0;
}
bigtime_t MOVFileReader::getAudioDuration()
bigtime_t MOVFileReader::getAudioDuration(uint32 stream_index)
{
AtomBase *aAtomBase;
uint32 TimeScale = getMovieTimeScale();
for (uint32 i=0;i<getStreamCount();i++) {
aAtomBase = GetChildAtom(uint32('trak'),i);
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())) {
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(TimeScale));
}
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())) {
return (dynamic_cast<TRAKAtom *>(aAtomBase)->Duration(1));
}
return 0;
@ -168,39 +162,59 @@ uint32 TimeScale = getMovieTimeScale();
bigtime_t MOVFileReader::getMaxDuration()
{
return MAX(getVideoDuration(),getAudioDuration());
AtomBase *aAtomBase;
int32 video_index,audio_index;
video_index = -1;
audio_index = -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()) {
audio_index = int32(i);
}
if (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo()) {
video_index = int32(i);
}
}
}
if ((video_index >= 0) && (audio_index >= 0)) {
return MAX(getVideoDuration(video_index),getAudioDuration(audio_index));
}
if ((video_index < 0) && (audio_index >= 0)) {
return getAudioDuration(audio_index);
}
if ((video_index >= 0) && (audio_index < 0)) {
return getVideoDuration(video_index);
}
return 0;
}
uint32 MOVFileReader::getVideoFrameCount()
uint32 MOVFileReader::getVideoFrameCount(uint32 stream_index)
{
AtomBase *aAtomBase;
for (uint32 i=0;i<getStreamCount();i++) {
aAtomBase = GetChildAtom(uint32('trak'),i);
aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsVideo())) {
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
}
return dynamic_cast<TRAKAtom *>(aAtomBase)->FrameCount();
}
return 1;
}
uint32 MOVFileReader::getAudioFrameCount()
uint32 MOVFileReader::getAudioFrameCount(uint32 stream_index)
{
AtomBase *aAtomBase;
for (uint32 i=0;i<getStreamCount();i++) {
aAtomBase = GetChildAtom(uint32('trak'),i);
if ((aAtomBase) && (dynamic_cast<TRAKAtom *>(aAtomBase)->IsAudio())) {
return uint32(((getAudioDuration() * AudioFormat(i)->SampleRate) / 1000000L) + 0.5);
}
if (IsAudio(stream_index)) {
return uint32(((getAudioDuration(stream_index) * AudioFormat(stream_index)->SampleRate) / 1000000L) + 0.5);
}
return 1;
return 0;
}
bool MOVFileReader::IsVideo(uint32 stream_index)
@ -357,7 +371,7 @@ const mov_main_header *MOVFileReader::MovMainHeader()
theMainHeader.initial_frames = 0;
while ( videoStream < theMainHeader.streams ) {
if (IsVideo(videoStream)) {
if (IsVideo(videoStream) && IsActive(videoStream)) {
break;
}
videoStream++;
@ -372,7 +386,7 @@ const mov_main_header *MOVFileReader::MovMainHeader()
} else {
theMainHeader.width = VideoFormat(videoStream)->width;
theMainHeader.height = VideoFormat(videoStream)->height;
theMainHeader.total_frames = getVideoFrameCount();
theMainHeader.total_frames = getVideoFrameCount(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);
}
@ -454,7 +468,7 @@ const VideoMetaData *MOVFileReader::VideoFormat(uint32 stream_index)
if (aAtomBase) {
STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase);
theVideo.FrameRate = ((aSTTSAtom->getSUMCounts() * 1000000.0L) / getVideoDuration());
theVideo.FrameRate = ((aSTTSAtom->getSUMCounts() * 1000000.0L) / aTrakAtom->Duration(1));
return &theVideo;
}
@ -469,17 +483,21 @@ const mov_stream_header *MOVFileReader::StreamFormat(uint32 stream_index)
{
// Fill In a Stream Header
theStreamHeader.length = 0;
if (IsActive(stream_index) == false) {
return NULL;
}
if (IsVideo(stream_index)) {
theStreamHeader.rate = uint32(1000000*VideoFormat(stream_index)->FrameRate);
theStreamHeader.scale = 1000000;
theStreamHeader.length = getVideoFrameCount();
theStreamHeader.rate = uint32(1000000L*VideoFormat(stream_index)->FrameRate);
theStreamHeader.scale = 1000000L;
theStreamHeader.length = getVideoFrameCount(stream_index);
}
if (IsAudio(stream_index)) {
theStreamHeader.rate = uint32(AudioFormat(stream_index)->SampleRate);
theStreamHeader.scale = 1;
theStreamHeader.length = getAudioFrameCount();
theStreamHeader.length = getAudioFrameCount(stream_index);
theStreamHeader.sample_size = AudioFormat(stream_index)->SampleSize;
theStreamHeader.suggested_buffer_size = theStreamHeader.rate * theStreamHeader.sample_size;
}
@ -550,6 +568,17 @@ bool MOVFileReader::GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t
return ((*start > 0) && (*size > 0) && !(IsEndOfFile(*start)));
}
bool MOVFileReader::IsActive(uint32 stream_index)
{
AtomBase *aAtomBase = GetChildAtom(uint32('trak'),stream_index);
if (aAtomBase) {
TRAKAtom *aTrakAtom = dynamic_cast<TRAKAtom *>(aAtomBase);
return aTrakAtom->IsActive();
}
return false;
}
/* static */
bool MOVFileReader::IsSupported(BPositionIO *source)
{

View File

@ -72,20 +72,20 @@ public:
// How many tracks in file
uint32 getStreamCount();
// Duration defined
// Duration defined by the movie header
bigtime_t getMovieDuration();
// The first video track duration
bigtime_t getVideoDuration();
// the first audio track duration
bigtime_t getAudioDuration();
// the max of the audio or video durations
// The first video track duration indexed by stream_index
bigtime_t getVideoDuration(uint32 stream_index);
// the first audio track duration indexed by stream_index
bigtime_t getAudioDuration(uint32 stream_index);
// the max of all active audio or video durations
bigtime_t getMaxDuration();
// The no of frames in the first video track
uint32 getVideoFrameCount();
// The no of frames in the first audio track
uint32 getAudioFrameCount();
// The no of frames in the video track indexed by stream_index
uint32 getVideoFrameCount(uint32 stream_index);
// The no of frames in the audio track indexed by stream_index
uint32 getAudioFrameCount(uint32 stream_index);
// Is stream (track) a video track
bool IsVideo(uint32 stream_index);
@ -102,6 +102,8 @@ public:
status_t ParseFile();
BPositionIO *Source() {return theStream;};
bool IsActive(uint32 stream_index);
bool GetNextChunkInfo(uint32 stream_index, uint32 pFrameNo, off_t *start, uint32 *size, bool *keyframe);
// Return all Audio Meta Data

View File

@ -267,13 +267,13 @@ void CMOVAtom::OnProcessMetaData()
printf("Failed to decompress headers uncompress returned ");
switch (result) {
case Z_MEM_ERROR:
printf("Lack of Memory Error\n");
DEBUGGER("Lack of Memory Error\n");
break;
case Z_BUF_ERROR:
printf("Lack of Output buffer space Error\n");
DEBUGGER("Lack of Output buffer space Error\n");
break;
case Z_DATA_ERROR:
printf("Input Data is corrupt or not a compressed set Error\n");
DEBUGGER("Input Data is corrupt or not a compressed set Error\n");
break;
}
}
@ -387,6 +387,7 @@ void MVHDAtom::OnProcessMetaData()
theHeader.SelectionDuration = B_BENDIAN_TO_HOST_INT32(theHeader.SelectionDuration);
theHeader.CurrentTime = B_BENDIAN_TO_HOST_INT32(theHeader.CurrentTime);
theHeader.NextTrackID = B_BENDIAN_TO_HOST_INT32(theHeader.NextTrackID);
}
char *MVHDAtom::OnGetAtomName()
@ -410,6 +411,8 @@ AtomBase *aAtomBase;
STTSAtom::STTSAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
{
theHeader.NoEntries = 0;
SUMDurations = 0;
SUMCounts = 0;
}
STTSAtom::~STTSAtom()
@ -434,6 +437,8 @@ TimeToSample *aTimeToSample;
aTimeToSample->Duration = B_BENDIAN_TO_HOST_INT32(aTimeToSample->Duration);
theTimeToSampleArray[i] = aTimeToSample;
SUMDurations += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
SUMCounts += theTimeToSampleArray[i]->Count;
}
}
@ -442,39 +447,14 @@ char *STTSAtom::OnGetAtomName()
return "Time to Sample Atom";
}
uint64 STTSAtom::getSUMCounts()
{
uint64 SUMCounts = 0;
uint64 SUMDurations = 0;
for (uint32 i=0;i<theHeader.NoEntries;i++) {
SUMDurations += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
SUMCounts += theTimeToSampleArray[i]->Count;
}
return SUMCounts;
}
uint64 STTSAtom::getSUMDurations()
{
// this Duration is not scaled to timescale
uint64 SUMDurations = 0;
for (uint32 i=0;i<theHeader.NoEntries;i++) {
SUMDurations += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
}
return SUMDurations;
}
uint32 STTSAtom::getSampleForTime(uint32 pTime)
{
// TODO this is too slow. PreCalc SUMCounts when loading this.
uint64 SUMDurations = 0;
// TODO this is too slow. PreCalc when loading this?
uint64 Duration = 0;
for (uint32 i=0;i<theHeader.NoEntries;i++) {
SUMDurations += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
if (SUMDurations > pTime) {
Duration += (theTimeToSampleArray[i]->Duration * theTimeToSampleArray[i]->Count);
if (Duration > pTime) {
return i;
}
}
@ -528,7 +508,6 @@ SampleToChunk *aSampleToChunk;
}
theSampleToChunkArray[i] = aSampleToChunk;
// printf("%ld/%ld/%ld\n",aSampleToChunk->FirstChunk,aSampleToChunk->SamplesPerChunk,aSampleToChunk->TotalPrevFrames);
}
}
@ -727,7 +706,7 @@ ChunkToOffset *aChunkToOffset;
theChunkToOffsetArray[i] = aChunkToOffset;
}
printf("Chunk to Offset Array has %ld entries\n",theHeader.NoEntries);
PRINT(("Chunk to Offset Array has %ld entries\n",theHeader.NoEntries));
}
char *STCOAtom::OnGetAtomName()
@ -742,11 +721,10 @@ uint64 STCOAtom::getOffsetForChunk(uint32 pChunkID)
return theChunkToOffsetArray[pChunkID - 1]->Offset;
}
printf("Bad Chunk ID %ld / %ld\n",pChunkID,theHeader.NoEntries);
DEBUGGER(("Bad Chunk ID %ld / %ld\n",pChunkID,theHeader.NoEntries));
// TODO Yes this will seg fault. But I get a very bad lock up if I don't :-(
return theChunkToOffsetArray[pChunkID - 1]->Offset;
// return theChunkToOffsetArray[0]->Offset;
TRESPASS();
return theChunkToOffsetArray[0]->Offset;
}
STSDAtom::STSDAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomBase(pStream, pstreamOffset, patomType, patomSize)
@ -843,7 +821,7 @@ void STSDAtom::ReadSoundDescription()
if (aAtomBase->getAtomSize() > 0) {
descBytesLeft = descBytesLeft - aAtomBase->getAtomSize();
} else {
printf("Invalid Atom found when reading Sound Description\n");
DEBUGGER("Invalid Atom found when reading Sound Description\n");
descBytesLeft = 0;
}
@ -855,7 +833,7 @@ void STSDAtom::ReadSoundDescription()
theStream->Seek(descBytesLeft,0);
printf("Size:Format=%ld:%ld %ld\n",aSoundDescriptionV1->basefields.Size,aSoundDescriptionV1->basefields.DataFormat,descBytesLeft);
PRINT(("Size:Format=%ld:%ld %ld\n",aSoundDescriptionV1->basefields.Size,aSoundDescriptionV1->basefields.DataFormat,descBytesLeft));
}
void STSDAtom::ReadVideoDescription()
@ -896,7 +874,7 @@ void STSDAtom::ReadVideoDescription()
// We seem to have read 2 bytes too many???
theStream->Seek(descBytesLeft,0);
printf("Size:Format=%ld:%ld %ld\n",aVideoDescription->basefields.Size,aVideoDescription->basefields.DataFormat,descBytesLeft);
PRINT(("Size:Format=%ld:%ld %ld\n",aVideoDescription->basefields.Size,aVideoDescription->basefields.DataFormat,descBytesLeft));
}
void STSDAtom::OnProcessMetaData()
@ -1157,17 +1135,45 @@ TKHDAtom::~TKHDAtom()
void TKHDAtom::OnProcessMetaData()
{
theStream->Read(&theHeader,sizeof(tkhd));
theStream->Read(&Version,sizeof(uint8));
if (Version == 0) {
tkhdV0 aHeaderV0;
theStream->Read(&aHeaderV0,sizeof(tkhdV0));
theHeader.Flags1 = aHeaderV0.Flags1;
theHeader.Flags2 = aHeaderV0.Flags2;
theHeader.Flags3 = aHeaderV0.Flags3;
for (uint32 i=0;i<36;i++) {
theHeader.MatrixStructure[i] = aHeaderV0.MatrixStructure[i];
}
// upconvert to V1 header
theHeader.CreationTime = B_BENDIAN_TO_HOST_INT32(aHeaderV0.CreationTime);
theHeader.ModificationTime = B_BENDIAN_TO_HOST_INT32(aHeaderV0.ModificationTime);
theHeader.TrackID = B_BENDIAN_TO_HOST_INT32(aHeaderV0.TrackID);
theHeader.Duration = B_BENDIAN_TO_HOST_INT32(aHeaderV0.Duration);
theHeader.Layer = B_BENDIAN_TO_HOST_INT16(aHeaderV0.Layer);
theHeader.AlternateGroup = B_BENDIAN_TO_HOST_INT16(aHeaderV0.AlternateGroup);
theHeader.Volume = B_BENDIAN_TO_HOST_INT16(aHeaderV0.Volume);
theHeader.TrackWidth = B_BENDIAN_TO_HOST_INT32(aHeaderV0.TrackWidth);
theHeader.TrackHeight = B_BENDIAN_TO_HOST_INT32(aHeaderV0.TrackHeight);
} else {
theStream->Read(&theHeader,sizeof(tkhdV1));
theHeader.CreationTime = B_BENDIAN_TO_HOST_INT64(theHeader.CreationTime);
theHeader.ModificationTime = B_BENDIAN_TO_HOST_INT64(theHeader.ModificationTime);
theHeader.TrackID = B_BENDIAN_TO_HOST_INT32(theHeader.TrackID);
theHeader.Duration = B_BENDIAN_TO_HOST_INT32(theHeader.Duration);
theHeader.Layer = B_BENDIAN_TO_HOST_INT16(theHeader.Layer);
theHeader.AlternateGroup = B_BENDIAN_TO_HOST_INT16(theHeader.AlternateGroup);
theHeader.Volume = B_BENDIAN_TO_HOST_INT16(theHeader.Volume);
theHeader.TrackWidth = B_BENDIAN_TO_HOST_INT32(theHeader.TrackWidth);
theHeader.TrackHeight = B_BENDIAN_TO_HOST_INT32(theHeader.TrackHeight);
}
theHeader.CreationTime = B_BENDIAN_TO_HOST_INT32(theHeader.CreationTime);
theHeader.ModificationTime = B_BENDIAN_TO_HOST_INT32(theHeader.ModificationTime);
theHeader.TrackID = B_BENDIAN_TO_HOST_INT32(theHeader.TrackID);
theHeader.Duration = B_BENDIAN_TO_HOST_INT32(theHeader.Duration);
theHeader.Layer = B_BENDIAN_TO_HOST_INT16(theHeader.Layer);
theHeader.AlternateGroup = B_BENDIAN_TO_HOST_INT16(theHeader.AlternateGroup);
theHeader.Volume = B_BENDIAN_TO_HOST_INT16(theHeader.Volume);
theHeader.TrackWidth = B_BENDIAN_TO_HOST_INT32(theHeader.TrackWidth);
theHeader.TrackHeight = B_BENDIAN_TO_HOST_INT32(theHeader.TrackHeight);
}
char *TKHDAtom::OnGetAtomName()
@ -1232,7 +1238,7 @@ char *MDHDAtom::OnGetAtomName()
bigtime_t MDHDAtom::getDuration()
{
return (bigtime_t(theHeader.Duration) * 1000000) / (theHeader.TimeScale);
return bigtime_t((uint64(theHeader.Duration) * 1000000L) / theHeader.TimeScale);
}
uint32 MDHDAtom::getTimeScale()

View File

@ -168,13 +168,15 @@ public:
void OnProcessMetaData();
char *OnGetAtomName();
uint64 getSUMCounts();
uint64 getSUMDurations();
uint64 getSUMCounts() {return SUMCounts;};
uint64 getSUMDurations() {return SUMDurations;};
uint32 getSampleForTime(uint32 pTime);
uint32 getSampleForFrame(uint32 pFrame);
private:
array_header theHeader;
TimeToSampleArray theTimeToSampleArray;
uint64 SUMDurations;
uint64 SUMCounts;
};
// Atom class for reading the sample to chunk atom
@ -292,9 +294,19 @@ public:
char *OnGetAtomName();
uint32 getDuration() {return theHeader.Duration;}; // duration is in the scale of the media
// Flags3 should contain the following
// 0x001 Track enabled
// 0x002 Track in Movie
// 0x004 Track in Preview
// 0x008 Track in Poster
// It seems active tracks have all 4 flags set?
bool IsActive() {return (theHeader.Flags3 == 0x0f);};
private:
tkhd theHeader;
tkhdV1 theHeader;
uint8 Version;
};
@ -361,6 +373,7 @@ public:
uint32 getNoSamplesInChunk(uint32 pChunkID);
bool IsSyncSample(uint32 pSampleNo);
bool IsSingleSampleSize();
bool IsActive();
TKHDAtom *getTKHDAtom();
MDHDAtom *getMDHDAtom();

View File

@ -77,7 +77,7 @@ bigtime_t TRAKAtom::Duration(uint32 TimeScale)
return getMDHDAtom()->getDuration();
}
return bigtime_t(getTKHDAtom()->getDuration() * 1000000) / TimeScale;
return bigtime_t(getTKHDAtom()->getDuration() * 1000000L) / TimeScale;
}
void TRAKAtom::OnChildProcessingComplete()
@ -221,5 +221,10 @@ bool TRAKAtom::IsSingleSampleSize()
return false;
}
bool TRAKAtom::IsActive()
{
return getTKHDAtom()->IsActive();
}
// GetAudioMetaData() // If this is a audio track get the audio meta data
// GetVideoMetaData() // If this is a video track get the video meta data

View File

@ -179,8 +179,7 @@ struct mvhd {
uint32 NextTrackID;
};
struct tkhd {
uint8 Version;
struct tkhdV0 {
uint8 Flags1;
uint8 Flags2;
uint8 Flags3;
@ -199,6 +198,25 @@ struct tkhd {
uint32 TrackHeight;
};
struct tkhdV1 {
uint8 Flags1;
uint8 Flags2;
uint8 Flags3;
uint64 CreationTime;
uint64 ModificationTime;
uint32 TrackID;
uint32 Reserved1;
uint32 Duration;
uint64 Reserved2;
uint16 Layer;
uint16 AlternateGroup;
uint16 Volume;
uint16 Reserved3;
uint8 MatrixStructure[36];
uint32 TrackWidth;
uint32 TrackHeight;
};
struct mdhd {
uint8 Version;
uint8 Flags1;

View File

@ -146,11 +146,17 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
BMediaFormats formats;
media_format *format = &cookie->format;
media_format_description description;
if (theFileReader->IsActive(cookie->stream) == false) {
ERROR("movReader::AllocateCookie: stream %d is not active\n", cookie->stream);
delete cookie;
return B_ERROR;
}
const mov_stream_header *stream_header;
stream_header = theFileReader->StreamFormat(cookie->stream);
if (!stream_header) {
ERROR("movReader::GetStreamInfo: stream %d has no header\n", cookie->stream);
ERROR("movReader::AllocateCookie: stream %d has no header\n", cookie->stream);
delete cookie;
return B_ERROR;
}
@ -160,13 +166,13 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
if (theFileReader->IsAudio(cookie->stream)) {
const AudioMetaData *audio_format = theFileReader->AudioFormat(cookie->stream);
if (!audio_format) {
ERROR("movReader::GetStreamInfo: audio stream %d has no format\n", cookie->stream);
ERROR("movReader::AllocateCookie: audio stream %d has no format\n", cookie->stream);
delete cookie;
return B_ERROR;
}
cookie->frame_count = theFileReader->getAudioFrameCount();
cookie->duration = theFileReader->getAudioDuration();
cookie->frame_count = theFileReader->getAudioFrameCount(cookie->stream);
cookie->duration = theFileReader->getAudioDuration(cookie->stream);
cookie->audio = true;
cookie->byte_pos = 0;
@ -336,7 +342,7 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
if (theFileReader->IsVideo(cookie->stream)) {
const VideoMetaData *video_format = theFileReader->VideoFormat(cookie->stream);
if (!video_format) {
ERROR("movReader::GetStreamInfo: video stream %d has no format\n", cookie->stream);
ERROR("movReader::AllocateCookie: video stream %d has no format\n", cookie->stream);
delete cookie;
return B_ERROR;
}
@ -363,6 +369,7 @@ movReader::AllocateCookie(int32 streamNumber, void **_cookie)
TRACE("frame_count %Ld\n", cookie->frame_count);
TRACE("duration %.6f (%Ld)\n", cookie->duration / 1E6, cookie->duration);
TRACE("compression %s\n", &video_format->compression);
description.family = B_QUICKTIME_FORMAT_FAMILY;
if (stream_header->fourcc_handler == 'ekaf' || stream_header->fourcc_handler == 0) // 'fake' or 0 fourcc => used compression id