3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / plugins / mp4_reader / libMP4 / MP4TrakAtom.cpp
blob35e96483a1fd18a3539f1ec055d5887f64bd7d66
1 /*
2 * Copyright (c) 2005, David McPaul
3 * All rights reserved.
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,
31 uint64 patomSize)
33 AtomContainer(pStream, pstreamOffset, patomType, patomSize)
35 theTKHDAtom = NULL;
36 theMDHDAtom = NULL;
37 frameCount = 0;
38 bytesPerSample = 0;
39 timeScale = 1;
43 TRAKAtom::~TRAKAtom()
48 void
49 TRAKAtom::OnProcessMetaData()
54 const char *
55 TRAKAtom::OnGetAtomName()
57 return "MPEG-4 Track Atom";
61 TKHDAtom *
62 TRAKAtom::GetTKHDAtom()
64 if (theTKHDAtom) {
65 return theTKHDAtom;
68 theTKHDAtom = dynamic_cast<TKHDAtom *>(GetChildAtom(uint32('tkhd'),0));
70 // Assert(theTKHDAtom != NULL,"Track has no Track Header");
72 return theTKHDAtom;
76 MDHDAtom *
77 TRAKAtom::GetMDHDAtom()
79 if (theMDHDAtom)
80 return theMDHDAtom;
82 theMDHDAtom = dynamic_cast<MDHDAtom *>(GetChildAtom(uint32('mdhd'),0));
84 // Assert(theMDHDAtom != NULL,"Track has no Media Header");
86 return theMDHDAtom;
90 bigtime_t
91 TRAKAtom::Duration(uint32 TimeScale)
93 if (IsAudio() || IsVideo())
94 return GetMDHDAtom()->GetDuration();
96 return bigtime_t(GetTKHDAtom()->GetDuration() * 1000000.0) / TimeScale;
100 void
101 TRAKAtom::OnChildProcessingComplete()
103 timeScale = GetMDHDAtom()->GetTimeScale();
105 STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>
106 (GetChildAtom(uint32('stts'),0));
108 if (aSTTSAtom) {
109 frameCount = aSTTSAtom->GetSUMCounts();
110 aSTTSAtom->SetFrameRate(GetFrameRate());
116 bool
117 TRAKAtom::IsVideo()
119 // video tracks have a vmhd atom
120 return (GetChildAtom(uint32('vmhd'),0) != NULL);
124 bool
125 TRAKAtom::IsAudio()
127 // audio tracks have a smhd atom
128 return (GetChildAtom(uint32('smhd'),0) != NULL);
132 // frames per us
133 float
134 TRAKAtom::GetFrameRate()
136 if (IsAudio()) {
137 AtomBase *aAtomBase = GetChildAtom(uint32('stsd'),0);
138 if (aAtomBase) {
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();
149 return 0.0;
153 float
154 TRAKAtom::GetSampleRate()
156 // Only valid for Audio
157 if (IsAudio()) {
158 AtomBase *aAtomBase = GetChildAtom(uint32('stsd'),0);
159 if (aAtomBase) {
160 STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
162 AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio();
163 return aAudioDescription.theAudioSampleEntry.SampleRate;
167 return 0.0;
171 uint32
172 TRAKAtom::GetFrameForTime(bigtime_t time) {
173 // time / duration * frameCount?
174 //return uint32(time * GetFrameRate() / 1000000LL);
175 return time * frameCount / Duration();
179 bigtime_t
180 TRAKAtom::GetTimeForFrame(uint32 pFrame)
182 return bigtime_t((pFrame * 1000000LL) / GetFrameRate());
186 uint32
187 TRAKAtom::GetSampleForTime(bigtime_t pTime)
189 AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0);
191 if (aAtomBase) {
192 return (dynamic_cast<STTSAtom *>(aAtomBase))->GetSampleForTime(pTime);
195 return 0;
199 uint32
200 TRAKAtom::GetSampleForFrame(uint32 pFrame)
202 AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0);
204 if (aAtomBase) {
205 return (dynamic_cast<STTSAtom *>
206 (aAtomBase))->GetSampleForTime(GetTimeForFrame(pFrame));
209 return 0;
213 uint32
214 TRAKAtom::GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
216 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
218 if (aAtomBase)
219 return (dynamic_cast<STSCAtom *>(aAtomBase))->GetChunkForSample(pSample,
220 pOffsetInChunk);
222 return 0;
226 uint32
227 TRAKAtom::GetNoSamplesInChunk(uint32 pChunkIndex)
229 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
231 if (aAtomBase)
232 return (dynamic_cast<STSCAtom *>
233 (aAtomBase))->GetNoSamplesInChunk(pChunkIndex);
235 return 0;
239 uint32
240 TRAKAtom::GetSizeForSample(uint32 pSample)
242 AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0);
244 if (aAtomBase) {
245 return (dynamic_cast<STSZAtom *>(aAtomBase))->GetSizeForSample(pSample);
248 return 0;
252 uint64
253 TRAKAtom::GetOffsetForChunk(uint32 pChunkIndex)
255 AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
257 if (aAtomBase) {
258 return (dynamic_cast<STCOAtom *>
259 (aAtomBase))->GetOffsetForChunk(pChunkIndex);
262 return 0;
266 uint32
267 TRAKAtom::ChunkCount()
269 AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
271 if (aAtomBase)
272 return (dynamic_cast<STCOAtom *>(aAtomBase))->GetTotalChunks();
274 return 0;
278 uint32
279 TRAKAtom::GetFirstSampleInChunk(uint32 pChunkIndex)
281 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0);
283 if (aAtomBase)
284 return (dynamic_cast<STSCAtom *>
285 (aAtomBase))->GetFirstSampleInChunk(pChunkIndex);
287 return 0;
291 bool
292 TRAKAtom::IsSyncSample(uint32 pSampleNo)
294 AtomBase *aAtomBase = GetChildAtom(uint32('stss'),0);
296 if (aAtomBase)
297 return (dynamic_cast<STSSAtom *>(aAtomBase))->IsSyncSample(pSampleNo);
299 return false;
303 bool
304 TRAKAtom::IsSingleSampleSize()
306 AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0);
308 if (aAtomBase)
309 return (dynamic_cast<STSZAtom *>(aAtomBase))->IsSingleSampleSize();
311 return false;
315 bool
316 TRAKAtom::IsActive()
318 return GetTKHDAtom()->IsActive();
322 uint32
323 TRAKAtom::GetBytesPerSample()
325 AtomBase *aAtomBase;
327 if (bytesPerSample > 0)
328 return bytesPerSample;
330 // calculate bytes per sample and cache it
332 if (IsAudio()) {
333 // only used by Audio
334 aAtomBase = GetChildAtom(uint32('stsd'),0);
335 if (aAtomBase) {
336 STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase);
338 AudioDescription aAudioDescription = aSTSDAtom->GetAsAudio();
340 bytesPerSample = aAudioDescription.theAudioSampleEntry.SampleSize
341 / 8;
345 return bytesPerSample;
349 uint32
350 TRAKAtom::GetChunkSize(uint32 pChunkIndex)
352 uint32 totalSamples = GetNoSamplesInChunk(pChunkIndex);
354 if (IsSingleSampleSize()) {
355 return totalSamples * GetBytesPerSample();
356 } else {
357 uint32 SampleNo = GetFirstSampleInChunk(pChunkIndex);
358 uint32 ChunkSize = 0;
360 if (SampleNo >= 0) {
361 while (totalSamples-- > 0) {
362 ChunkSize += GetSizeForSample(SampleNo++);
366 return ChunkSize;
369 return 0;
373 uint32
374 TRAKAtom::GetTotalChunks()
376 AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0);
378 if (aAtomBase)
379 return (dynamic_cast<STCOAtom *>(aAtomBase))->GetTotalChunks();
381 return 0;