1/* 2 * Copyright (c) 2005, David McPaul 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without modification, 6 * are permitted provided that the following conditions are met: 7 * 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. 13 * 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. 24 */ 25#include "MOVParser.h" 26 27TRAKAtom::TRAKAtom(BPositionIO *pStream, off_t pstreamOffset, uint32 patomType, uint64 patomSize) : AtomContainer(pStream, pstreamOffset, patomType, patomSize) 28{ 29 theTKHDAtom = NULL; 30 theMDHDAtom = NULL; 31 framecount = 0; 32 bytespersample = 0; 33} 34 35TRAKAtom::~TRAKAtom() 36{ 37} 38 39void TRAKAtom::OnProcessMetaData() 40{ 41} 42 43char *TRAKAtom::OnGetAtomName() 44{ 45 return "Quicktime Track Atom"; 46} 47 48TKHDAtom *TRAKAtom::getTKHDAtom() 49{ 50 if (theTKHDAtom) { 51 return theTKHDAtom; 52 } 53 54 theTKHDAtom = dynamic_cast<TKHDAtom *>(GetChildAtom(uint32('tkhd'),0)); 55 56 // Assert(theTKHDAtom != NULL,"Track has no Track Header"); 57 58 return theTKHDAtom; 59} 60 61MDHDAtom *TRAKAtom::getMDHDAtom() 62{ 63 if (theMDHDAtom) { 64 return theMDHDAtom; 65 } 66 67 theMDHDAtom = dynamic_cast<MDHDAtom *>(GetChildAtom(uint32('mdhd'),0)); 68 69 // Assert(theMDHDAtom != NULL,"Track has no Media Header"); 70 71 return theMDHDAtom; 72} 73 74// Return duration of track 75bigtime_t TRAKAtom::Duration(uint32 TimeScale) 76{ 77 if (IsAudio() || IsVideo()) { 78 return getMDHDAtom()->getDuration(); 79 } 80 81 return bigtime_t(getTKHDAtom()->getDuration() * 1000000L) / TimeScale; 82} 83 84void TRAKAtom::OnChildProcessingComplete() 85{ 86 STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(GetChildAtom(uint32('stts'),0)); 87 88 if (aSTTSAtom) { 89 framecount = aSTTSAtom->getSUMCounts(); 90 } 91} 92 93// Is this a video track 94bool TRAKAtom::IsVideo() 95{ 96 // video tracks have a vmhd atom 97 return (GetChildAtom(uint32('vmhd'),0) != NULL); 98} 99 100// Is this a audio track 101bool TRAKAtom::IsAudio() 102{ 103 // audio tracks have a smhd atom 104 return (GetChildAtom(uint32('smhd'),0) != NULL); 105} 106 107uint32 TRAKAtom::getTimeForFrame(uint32 pFrame, uint32 pTimeScale) 108{ 109 AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0); 110 111 if (aAtomBase) { 112 STTSAtom *aSTTSAtom = dynamic_cast<STTSAtom *>(aAtomBase); 113 114 if (IsAudio()) { 115 // Frame * SampleRate = Time 116 } else if (IsVideo()) { 117 // Frame * fps = Time 118 return pFrame * ((aSTTSAtom->getSUMCounts() * 1000000L) / Duration(pTimeScale)); 119 } 120 } 121 122 return 0; 123} 124 125uint32 TRAKAtom::getSampleForTime(uint32 pTime) 126{ 127 AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0); 128 129 if (aAtomBase) { 130 return (dynamic_cast<STTSAtom *>(aAtomBase))->getSampleForTime(pTime); 131 } 132 133 return 0; 134} 135 136uint32 TRAKAtom::getSampleForFrame(uint32 pFrame) 137{ 138 AtomBase *aAtomBase = GetChildAtom(uint32('stts'),0); 139 140 if (aAtomBase) { 141 return (dynamic_cast<STTSAtom *>(aAtomBase))->getSampleForFrame(pFrame); 142 } 143 144 return 0; 145} 146 147uint32 TRAKAtom::getChunkForSample(uint32 pSample, uint32 *pOffsetInChunk) 148{ 149 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); 150 151 if (aAtomBase) { 152 return (dynamic_cast<STSCAtom *>(aAtomBase))->getChunkForSample(pSample, pOffsetInChunk); 153 } 154 155 return 0; 156} 157 158uint32 TRAKAtom::getNoSamplesInChunk(uint32 pChunkID) 159{ 160 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); 161 162 if (aAtomBase) { 163 return (dynamic_cast<STSCAtom *>(aAtomBase))->getNoSamplesInChunk(pChunkID); 164 } 165 166 return 0; 167} 168 169uint32 TRAKAtom::getSizeForSample(uint32 pSample) 170{ 171 AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0); 172 173 if (aAtomBase) { 174 return (dynamic_cast<STSZAtom *>(aAtomBase))->getSizeForSample(pSample); 175 } 176 177 return 0; 178} 179 180uint64 TRAKAtom::getOffsetForChunk(uint32 pChunkID) 181{ 182 AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); 183 184 if (aAtomBase) { 185 return (dynamic_cast<STCOAtom *>(aAtomBase))->getOffsetForChunk(pChunkID); 186 } 187 188 return 0; 189} 190 191uint32 TRAKAtom::getFirstSampleInChunk(uint32 pChunkID) 192{ 193 AtomBase *aAtomBase = GetChildAtom(uint32('stsc'),0); 194 195 if (aAtomBase) { 196 return (dynamic_cast<STSCAtom *>(aAtomBase))->getFirstSampleInChunk(pChunkID); 197 } 198 199 return 0; 200} 201 202 203bool TRAKAtom::IsSyncSample(uint32 pSampleNo) 204{ 205 AtomBase *aAtomBase = GetChildAtom(uint32('stss'),0); 206 207 if (aAtomBase) { 208 return (dynamic_cast<STSSAtom *>(aAtomBase))->IsSyncSample(pSampleNo); 209 } 210 211 return false; 212} 213 214bool TRAKAtom::IsSingleSampleSize() 215{ 216 AtomBase *aAtomBase = GetChildAtom(uint32('stsz'),0); 217 218 if (aAtomBase) { 219 return (dynamic_cast<STSZAtom *>(aAtomBase))->IsSingleSampleSize(); 220 } 221 222 return false; 223} 224 225bool TRAKAtom::IsActive() 226{ 227 return getTKHDAtom()->IsActive(); 228} 229 230uint32 TRAKAtom::getBytesPerSample() 231{ 232AtomBase *aAtomBase; 233 234 if (bytespersample > 0) { 235 return bytespersample; 236 } 237 238 // calculate bytes per sample and cache it 239 240 if (IsAudio()) { 241 // only used by Audio 242 aAtomBase = GetChildAtom(uint32('stsd'),0); 243 if (aAtomBase) { 244 STSDAtom *aSTSDAtom = dynamic_cast<STSDAtom *>(aAtomBase); 245 246 SoundDescriptionV1 aSoundDescription = aSTSDAtom->getAsAudio(); 247 248 bytespersample = aSoundDescription.bytesPerSample; 249 } 250 } 251 252 return bytespersample; 253} 254 255uint32 TRAKAtom::getTotalChunks() 256{ 257 AtomBase *aAtomBase = GetChildAtom(uint32('stco'),0); 258 259 if (aAtomBase) { 260 return (dynamic_cast<STCOAtom *>(aAtomBase))->getTotalChunks(); 261 } 262 263 return 0; 264} 265 266// GetAudioMetaData() // If this is a audio track get the audio meta data 267// GetVideoMetaData() // If this is a video track get the video meta data 268