2 * Copyright (c) 2005, David McPaul
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
23 * OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "MP4Parser.h"
30 TRAKAtom::TRAKAtom(BPositionIO
*pStream
, off_t pstreamOffset
, uint32 patomType
,
33 AtomContainer(pStream
, pstreamOffset
, patomType
, patomSize
)
49 TRAKAtom::OnProcessMetaData()
55 TRAKAtom::OnGetAtomName()
57 return "MPEG-4 Track Atom";
62 TRAKAtom::GetTKHDAtom()
68 theTKHDAtom
= dynamic_cast<TKHDAtom
*>(GetChildAtom(uint32('tkhd'),0));
70 // Assert(theTKHDAtom != NULL,"Track has no Track Header");
77 TRAKAtom::GetMDHDAtom()
82 theMDHDAtom
= dynamic_cast<MDHDAtom
*>(GetChildAtom(uint32('mdhd'),0));
84 // Assert(theMDHDAtom != NULL,"Track has no Media Header");
91 TRAKAtom::Duration(uint32 TimeScale
)
93 if (IsAudio() || IsVideo())
94 return GetMDHDAtom()->GetDuration();
96 return bigtime_t(GetTKHDAtom()->GetDuration() * 1000000.0) / TimeScale
;
101 TRAKAtom::OnChildProcessingComplete()
103 timeScale
= GetMDHDAtom()->GetTimeScale();
105 STTSAtom
*aSTTSAtom
= dynamic_cast<STTSAtom
*>
106 (GetChildAtom(uint32('stts'),0));
109 frameCount
= aSTTSAtom
->GetSUMCounts();
110 aSTTSAtom
->SetFrameRate(GetFrameRate());
119 // video tracks have a vmhd atom
120 return (GetChildAtom(uint32('vmhd'),0) != NULL
);
127 // audio tracks have a smhd atom
128 return (GetChildAtom(uint32('smhd'),0) != NULL
);
134 TRAKAtom::GetFrameRate()
137 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsd'),0);
139 STSDAtom
*aSTSDAtom
= dynamic_cast<STSDAtom
*>(aAtomBase
);
141 AudioDescription aAudioDescription
= aSTSDAtom
->GetAsAudio();
142 return (aAudioDescription
.theAudioSampleEntry
.SampleRate
)
143 / aAudioDescription
.FrameSize
;
145 } else if (IsVideo()) {
146 return (frameCount
* 1000000.0) / Duration();
154 TRAKAtom::GetSampleRate()
156 // Only valid for Audio
158 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsd'),0);
160 STSDAtom
*aSTSDAtom
= dynamic_cast<STSDAtom
*>(aAtomBase
);
162 AudioDescription aAudioDescription
= aSTSDAtom
->GetAsAudio();
163 return aAudioDescription
.theAudioSampleEntry
.SampleRate
;
172 TRAKAtom::GetFrameForTime(bigtime_t time
) {
173 // time / duration * frameCount?
174 //return uint32(time * GetFrameRate() / 1000000LL);
175 return time
* frameCount
/ Duration();
180 TRAKAtom::GetTimeForFrame(uint32 pFrame
)
182 return bigtime_t((pFrame
* 1000000LL) / GetFrameRate());
187 TRAKAtom::GetSampleForTime(bigtime_t pTime
)
189 AtomBase
*aAtomBase
= GetChildAtom(uint32('stts'),0);
192 return (dynamic_cast<STTSAtom
*>(aAtomBase
))->GetSampleForTime(pTime
);
200 TRAKAtom::GetSampleForFrame(uint32 pFrame
)
202 AtomBase
*aAtomBase
= GetChildAtom(uint32('stts'),0);
205 return (dynamic_cast<STTSAtom
*>
206 (aAtomBase
))->GetSampleForTime(GetTimeForFrame(pFrame
));
214 TRAKAtom::GetChunkForSample(uint32 pSample
, uint32
*pOffsetInChunk
)
216 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsc'),0);
219 return (dynamic_cast<STSCAtom
*>(aAtomBase
))->GetChunkForSample(pSample
,
227 TRAKAtom::GetNoSamplesInChunk(uint32 pChunkIndex
)
229 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsc'),0);
232 return (dynamic_cast<STSCAtom
*>
233 (aAtomBase
))->GetNoSamplesInChunk(pChunkIndex
);
240 TRAKAtom::GetSizeForSample(uint32 pSample
)
242 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsz'),0);
245 return (dynamic_cast<STSZAtom
*>(aAtomBase
))->GetSizeForSample(pSample
);
253 TRAKAtom::GetOffsetForChunk(uint32 pChunkIndex
)
255 AtomBase
*aAtomBase
= GetChildAtom(uint32('stco'),0);
258 return (dynamic_cast<STCOAtom
*>
259 (aAtomBase
))->GetOffsetForChunk(pChunkIndex
);
267 TRAKAtom::ChunkCount()
269 AtomBase
*aAtomBase
= GetChildAtom(uint32('stco'),0);
272 return (dynamic_cast<STCOAtom
*>(aAtomBase
))->GetTotalChunks();
279 TRAKAtom::GetFirstSampleInChunk(uint32 pChunkIndex
)
281 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsc'),0);
284 return (dynamic_cast<STSCAtom
*>
285 (aAtomBase
))->GetFirstSampleInChunk(pChunkIndex
);
292 TRAKAtom::IsSyncSample(uint32 pSampleNo
)
294 AtomBase
*aAtomBase
= GetChildAtom(uint32('stss'),0);
297 return (dynamic_cast<STSSAtom
*>(aAtomBase
))->IsSyncSample(pSampleNo
);
304 TRAKAtom::IsSingleSampleSize()
306 AtomBase
*aAtomBase
= GetChildAtom(uint32('stsz'),0);
309 return (dynamic_cast<STSZAtom
*>(aAtomBase
))->IsSingleSampleSize();
318 return GetTKHDAtom()->IsActive();
323 TRAKAtom::GetBytesPerSample()
327 if (bytesPerSample
> 0)
328 return bytesPerSample
;
330 // calculate bytes per sample and cache it
333 // only used by Audio
334 aAtomBase
= GetChildAtom(uint32('stsd'),0);
336 STSDAtom
*aSTSDAtom
= dynamic_cast<STSDAtom
*>(aAtomBase
);
338 AudioDescription aAudioDescription
= aSTSDAtom
->GetAsAudio();
340 bytesPerSample
= aAudioDescription
.theAudioSampleEntry
.SampleSize
345 return bytesPerSample
;
350 TRAKAtom::GetChunkSize(uint32 pChunkIndex
)
352 uint32 totalSamples
= GetNoSamplesInChunk(pChunkIndex
);
354 if (IsSingleSampleSize()) {
355 return totalSamples
* GetBytesPerSample();
357 uint32 SampleNo
= GetFirstSampleInChunk(pChunkIndex
);
358 uint32 ChunkSize
= 0;
361 while (totalSamples
-- > 0) {
362 ChunkSize
+= GetSizeForSample(SampleNo
++);
374 TRAKAtom::GetTotalChunks()
376 AtomBase
*aAtomBase
= GetChildAtom(uint32('stco'),0);
379 return (dynamic_cast<STCOAtom
*>(aAtomBase
))->GetTotalChunks();