3rdparty/licenseReport: Add seperate LGPL checks
[haiku.git] / src / add-ons / media / plugins / mp4_reader / libMP4 / MP4Parser.cpp
blob235a97cb75772522c16e1a662757b83516ec2752
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"
29 #include <stdio.h>
31 #include <DataIO.h>
32 #include <MediaFormats.h>
33 #include <SupportKit.h>
35 #include <zlib.h>
37 #include "BitParser.h"
40 AtomBase *
41 GetAtom(BPositionIO *pStream)
43 uint32 aAtomType;
44 uint32 aAtomSize;
45 uint64 aRealAtomSize;
46 off_t aStreamOffset;
48 aStreamOffset = pStream->Position();
50 // Get Size uint32
51 pStream->Read(&aAtomSize,4);
52 aAtomSize = B_BENDIAN_TO_HOST_INT32(aAtomSize);
53 // Get Type uint32
54 pStream->Read(&aAtomType,4);
55 aAtomType = B_BENDIAN_TO_HOST_INT32(aAtomType);
56 // Check for extended size
57 if (aAtomSize == 1) {
58 // Handle extended size
59 pStream->Read(&aRealAtomSize,4);
60 aRealAtomSize = B_BENDIAN_TO_HOST_INT64(aRealAtomSize);
61 } else if (aAtomSize == 0) {
62 // aAtomSize extends to end of file.
63 // TODO this is broken
64 aRealAtomSize = 0;
65 } else {
66 aRealAtomSize = aAtomSize;
69 if (aAtomType == uint32('moov'))
70 return new MOOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
72 if (aAtomType == uint32('mvhd'))
73 return new MVHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
75 if (aAtomType == uint32('trak'))
76 return new TRAKAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
78 if (aAtomType == uint32('tkhd'))
79 return new TKHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
81 if (aAtomType == uint32('free'))
82 return new FREEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
84 if (aAtomType == uint32('skip'))
85 return new SKIPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
87 if (aAtomType == uint32('wide'))
88 return new WIDEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
90 if (aAtomType == uint32('mdat'))
91 return new MDATAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
93 if (aAtomType == uint32('mdia'))
94 return new MDIAAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
96 if (aAtomType == uint32('mdhd'))
97 return new MDHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
99 if (aAtomType == uint32('hdlr'))
100 return new HDLRAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
102 if (aAtomType == uint32('minf'))
103 return new MINFAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
105 if (aAtomType == uint32('vmhd'))
106 return new VMHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
108 if (aAtomType == uint32('smhd'))
109 return new SMHDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
111 if (aAtomType == uint32('dinf'))
112 return new DINFAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
114 if (aAtomType == uint32('stbl'))
115 return new STBLAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
117 if (aAtomType == uint32('stsd'))
118 return new STSDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
120 if (aAtomType == uint32('tmcd'))
121 return new TMCDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
123 if (aAtomType == uint32('stts'))
124 return new STTSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
126 if (aAtomType == uint32('pnot'))
127 return new PNOTAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
129 if (aAtomType == uint32('stsc'))
130 return new STSCAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
132 if (aAtomType == uint32('stco'))
133 return new STCOAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
135 if (aAtomType == uint32('stss'))
136 return new STSSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
138 if (aAtomType == uint32('ctts'))
139 return new CTTSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
141 if (aAtomType == uint32('stsz'))
142 return new STSZAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
144 if (aAtomType == uint32('stz2'))
145 return new STZ2Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
147 if (aAtomType == uint32('ftyp'))
148 return new FTYPAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
150 if (aAtomType == uint32('cmov'))
151 return new CMOVAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
153 if (aAtomType == uint32('dcom'))
154 return new DCOMAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
156 if (aAtomType == uint32('cmvd'))
157 return new CMVDAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
159 if (aAtomType == uint32('esds'))
160 return new ESDSAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
162 if (aAtomType == uint32('alac'))
163 return new ALACAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
165 if (aAtomType == uint32('wave'))
166 return new WAVEAtom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
168 if (aAtomType == uint32('dac3'))
169 return new DAC3Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
171 if (aAtomType == uint32('dec3'))
172 return new DEC3Atom(pStream, aStreamOffset, aAtomType, aRealAtomSize);
174 if (aAtomType == uint32('avcC'))
175 return new DecoderConfigAtom(pStream, aStreamOffset, aAtomType,
176 aRealAtomSize);
178 return new AtomBase(pStream, aStreamOffset, aAtomType, aRealAtomSize);
182 MOOVAtom::MOOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
183 uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType,
184 pAtomSize)
186 theMVHDAtom = NULL;
190 MOOVAtom::~MOOVAtom()
192 theMVHDAtom = NULL;
196 void
197 MOOVAtom::OnProcessMetaData()
201 const char *
202 MOOVAtom::OnGetAtomName()
204 return "MPEG-4 Movie";
208 CMOVAtom::CMOVAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
209 uint64 pAtomSize) : AtomContainer(pStream, pStreamOffset, pAtomType,
210 pAtomSize)
212 theUncompressedStream = NULL;
216 CMOVAtom::~CMOVAtom()
221 BPositionIO *
222 CMOVAtom::OnGetStream()
224 // Use the decompressed stream instead of file stream
225 if (theUncompressedStream)
226 return theUncompressedStream;
228 return theStream;
232 void
233 CMOVAtom::OnProcessMetaData()
235 BMallocIO *theUncompressedData;
236 uint8 *outBuffer;
237 CMVDAtom *aCMVDAtom = NULL;
238 uint32 compressionID = 0;
239 uint64 descBytesLeft;
240 uint32 Size;
242 descBytesLeft = GetAtomSize();
244 // Check for Compression Type
245 while (descBytesLeft > 0) {
246 AtomBase *aAtomBase = GetAtom(theStream);
248 aAtomBase->OnProcessMetaData();
250 if (aAtomBase->GetAtomSize() > 0) {
251 descBytesLeft = descBytesLeft - aAtomBase->GetAtomSize();
252 } else {
253 printf("Invalid Atom found when reading Compressed Headers\n");
254 descBytesLeft = 0;
257 if (dynamic_cast<DCOMAtom *>(aAtomBase)) {
258 // DCOM atom
259 compressionID = dynamic_cast<DCOMAtom *>(aAtomBase)->GetCompressionID();
260 delete aAtomBase;
261 } else {
262 if (dynamic_cast<CMVDAtom *>(aAtomBase)) {
263 // CMVD atom
264 aCMVDAtom = dynamic_cast<CMVDAtom *>(aAtomBase);
265 descBytesLeft = 0;
270 // Decompress data
271 if (compressionID == 'zlib') {
272 Size = aCMVDAtom->GetUncompressedSize();
274 outBuffer = (uint8 *)(malloc(Size));
276 printf("Decompressing %ld bytes to %ld bytes\n",aCMVDAtom->GetBufferSize(),Size);
277 int result = uncompress(outBuffer, &Size, aCMVDAtom->GetCompressedData(), aCMVDAtom->GetBufferSize());
279 if (result != Z_OK) {
280 printf("Failed to decompress headers uncompress returned ");
281 switch (result) {
282 case Z_MEM_ERROR:
283 DEBUGGER("Lack of Memory Error\n");
284 break;
285 case Z_BUF_ERROR:
286 DEBUGGER("Lack of Output buffer space Error\n");
287 break;
288 case Z_DATA_ERROR:
289 DEBUGGER("Input Data is corrupt or not a compressed set Error\n");
290 break;
294 // Copy uncompressed data into BMAllocIO
295 theUncompressedData = new BMallocIO();
296 theUncompressedData->SetSize(Size);
297 theUncompressedData->WriteAt(0L,outBuffer,Size);
299 free(outBuffer);
300 delete aCMVDAtom;
302 // reset position on BMAllocIO
303 theUncompressedData->Seek(SEEK_SET,0L);
304 // Assign to Stream
305 theUncompressedStream = theUncompressedData;
307 // All subsequent reads should use theUncompressedStream
313 void
314 CMOVAtom::OnChildProcessingComplete()
316 // revert back to file stream once all children have finished
317 if (theUncompressedStream) {
318 delete theUncompressedStream;
320 theUncompressedStream = NULL;
324 const char *
325 CMOVAtom::OnGetAtomName()
327 return "Compressed MPEG-4 Movie";
331 DCOMAtom::DCOMAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
332 uint64 pAtomSize)
334 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
339 DCOMAtom::~DCOMAtom()
344 void
345 DCOMAtom::OnProcessMetaData()
347 Read(&compressionID);
351 const char *
352 DCOMAtom::OnGetAtomName()
354 return "Decompression Atom";
358 CMVDAtom::CMVDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
359 uint64 pAtomSize)
361 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
363 Buffer = NULL;
364 UncompressedSize = 0;
365 BufferSize = 0;
369 CMVDAtom::~CMVDAtom()
371 if (Buffer)
372 free(Buffer);
376 void
377 CMVDAtom::OnProcessMetaData()
379 Read(&UncompressedSize);
381 if (UncompressedSize > 0) {
382 BufferSize = GetBytesRemaining();
383 Buffer = (uint8 *)(malloc(BufferSize));
384 Read(Buffer,BufferSize);
389 const char *
390 CMVDAtom::OnGetAtomName()
392 return "Compressed Movie Data";
396 MVHDAtom::MVHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
397 uint64 pAtomSize)
399 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
404 MVHDAtom::~MVHDAtom()
409 void
410 MVHDAtom::OnProcessMetaData()
412 FullAtom::OnProcessMetaData();
414 if (GetVersion() == 0) {
415 mvhdV0 aHeader;
417 Read(&aHeader.CreationTime);
418 Read(&aHeader.ModificationTime);
419 Read(&aHeader.TimeScale);
420 Read(&aHeader.Duration);
421 Read(&aHeader.PreferredRate);
422 Read(&aHeader.PreferredVolume);
423 Read(&aHeader.Reserved1);
424 Read(&aHeader.Reserved2[0]);
425 Read(&aHeader.Reserved2[1]);
426 for (uint32 i=0;i<9;i++) {
427 Read(&aHeader.Matrix[i]);
429 for (uint32 j=0;j<6;j++) {
430 Read(&aHeader.pre_defined[j]);
432 Read(&aHeader.NextTrackID);
434 // Upconvert to V1 header
435 theHeader.CreationTime = (uint64)(aHeader.CreationTime);
436 theHeader.ModificationTime = (uint64)(aHeader.ModificationTime);
437 theHeader.TimeScale = aHeader.TimeScale;
438 theHeader.Duration = (uint64)(aHeader.Duration);
439 theHeader.PreferredRate = aHeader.PreferredRate;
440 theHeader.PreferredVolume = aHeader.PreferredVolume;
441 theHeader.NextTrackID = aHeader.NextTrackID;
444 if (GetVersion() == 1) {
445 // Read direct into V1 Header
446 Read(&theHeader.CreationTime);
447 Read(&theHeader.ModificationTime);
448 Read(&theHeader.TimeScale);
449 Read(&theHeader.Duration);
450 Read(&theHeader.PreferredRate);
451 Read(&theHeader.PreferredVolume);
452 Read(&theHeader.Reserved1);
453 Read(&theHeader.Reserved2[0]);
454 Read(&theHeader.Reserved2[1]);
455 for (uint32 i=0;i<9;i++) {
456 Read(&theHeader.Matrix[i]);
458 for (uint32 j=0;j<6;j++) {
459 Read(&theHeader.pre_defined[j]);
461 Read(&theHeader.NextTrackID);
466 const char *
467 MVHDAtom::OnGetAtomName()
469 return "MPEG-4 Movie Header";
473 MVHDAtom *
474 MOOVAtom::GetMVHDAtom()
476 AtomBase *aAtomBase;
478 if (theMVHDAtom == NULL) {
479 aAtomBase = GetChildAtom(uint32('mvhd'));
480 theMVHDAtom = dynamic_cast<MVHDAtom *>(aAtomBase);
483 // Assert(theMVHDAtom != NULL,"Movie has no movie header atom");
484 return theMVHDAtom;
488 STTSAtom::STTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
489 uint64 pAtomSize)
491 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
493 theHeader.NoEntries = 0;
494 SUMDurations = 0;
495 SUMCounts = 0;
499 STTSAtom::~STTSAtom()
501 for (uint32 i=0;i<theHeader.NoEntries;i++) {
502 delete theTimeToSampleArray[i];
503 theTimeToSampleArray[i] = NULL;
508 void
509 STTSAtom::OnProcessMetaData()
511 TimeToSample *aTimeToSample;
513 FullAtom::OnProcessMetaData();
515 ReadArrayHeader(&theHeader);
517 for (uint32 i=0;i<theHeader.NoEntries;i++) {
518 aTimeToSample = new TimeToSample;
520 Read(&aTimeToSample->Count);
521 Read(&aTimeToSample->Duration);
523 theTimeToSampleArray[i] = aTimeToSample;
524 SUMDurations += (theTimeToSampleArray[i]->Duration
525 * theTimeToSampleArray[i]->Count);
526 SUMCounts += theTimeToSampleArray[i]->Count;
531 const char *
532 STTSAtom::OnGetAtomName()
534 return "Time to Sample Atom";
538 uint32
539 STTSAtom::GetSampleForTime(bigtime_t pTime)
541 // Sample for time is this calc, how does STTS help us?
542 return uint32((pTime * FrameRate + 50) / 1000000.0);
544 // TODO this is too slow. PreCalc when loading this?
545 /* bigtime_t TotalDuration = 0;
546 uint64 TotalCount = 0;
548 for (uint32 i=0;i<theHeader.NoEntries;i++) {
549 TotalDuration += (theTimeToSampleArray[i]->Duration
550 * theTimeToSampleArray[i]->Count);
551 TotalCount += theTimeToSampleArray[i]->Count;
552 if ((TotalDuration * 44100) > pTime) {
553 return uint32((pTime * FrameRate + 50) / 1000000.0);
557 return 0;
562 uint32
563 STTSAtom::GetSampleForFrame(uint32 pFrame)
565 // Convert frame to time and call GetSampleForTime()
566 return pFrame;
570 CTTSAtom::CTTSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
571 uint64 pAtomSize)
573 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
575 theHeader.NoEntries = 0;
579 CTTSAtom::~CTTSAtom()
581 for (uint32 i=0;i<theHeader.NoEntries;i++) {
582 delete theCompTimeToSampleArray[i];
583 theCompTimeToSampleArray[i] = NULL;
588 void
589 CTTSAtom::OnProcessMetaData()
591 CompTimeToSample* aCompTimeToSample;
593 FullAtom::OnProcessMetaData();
595 ReadArrayHeader(&theHeader);
597 for (uint32 i=0;i<theHeader.NoEntries;i++) {
598 aCompTimeToSample = new CompTimeToSample;
600 Read(&aCompTimeToSample->Count);
601 Read(&aCompTimeToSample->Offset);
603 theCompTimeToSampleArray[i] = aCompTimeToSample;
608 const char *
609 CTTSAtom::OnGetAtomName()
611 return "Composition Time to Sample Atom";
615 STSCAtom::STSCAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
616 uint64 pAtomSize)
618 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
620 theHeader.NoEntries = 0;
624 STSCAtom::~STSCAtom()
626 for (uint32 i=0;i<theHeader.NoEntries;i++) {
627 delete theSampleToChunkArray[i];
628 theSampleToChunkArray[i] = NULL;
633 void
634 STSCAtom::OnProcessMetaData()
636 SampleToChunk *aSampleToChunk;
638 FullAtom::OnProcessMetaData();
640 ReadArrayHeader(&theHeader);
642 uint32 TotalPrevSamples = 0;
644 for (uint32 i=0;i<theHeader.NoEntries;i++) {
645 aSampleToChunk = new SampleToChunk;
647 Read(&aSampleToChunk->FirstChunk);
648 Read(&aSampleToChunk->SamplesPerChunk);
649 Read(&aSampleToChunk->SampleDescriptionID);
651 if (i > 0) {
652 TotalPrevSamples = TotalPrevSamples + (aSampleToChunk->FirstChunk - theSampleToChunkArray[i-1]->FirstChunk) * theSampleToChunkArray[i-1]->SamplesPerChunk;
653 aSampleToChunk->TotalPrevSamples = TotalPrevSamples;
654 } else {
655 aSampleToChunk->TotalPrevSamples = 0;
658 theSampleToChunkArray.push_back(aSampleToChunk);
663 const char *
664 STSCAtom::OnGetAtomName()
666 return "Sample to Chunk Atom";
670 uint32
671 STSCAtom::GetNoSamplesInChunk(uint32 pChunkID)
673 for (uint32 i=0;i<theHeader.NoEntries;i++) {
674 if (theSampleToChunkArray[i]->FirstChunk > pChunkID) {
675 return theSampleToChunkArray[i-1]->SamplesPerChunk;
679 return theSampleToChunkArray[theHeader.NoEntries-1]->SamplesPerChunk;
683 uint32
684 STSCAtom::GetFirstSampleInChunk(uint32 pChunkID)
686 uint32 Diff;
688 for (uint32 i=0;i<theHeader.NoEntries;i++) {
689 if (theSampleToChunkArray[i]->FirstChunk > pChunkID) {
690 Diff = pChunkID - theSampleToChunkArray[i-1]->FirstChunk;
691 return ((Diff * theSampleToChunkArray[i-1]->SamplesPerChunk)
692 + theSampleToChunkArray[i-1]->TotalPrevSamples);
696 Diff = pChunkID - theSampleToChunkArray[theHeader.NoEntries-1]->FirstChunk;
697 return Diff * theSampleToChunkArray[theHeader.NoEntries-1]->SamplesPerChunk
698 + theSampleToChunkArray[theHeader.NoEntries-1]->TotalPrevSamples;
702 uint32
703 STSCAtom::GetChunkForSample(uint32 pSample, uint32 *pOffsetInChunk)
705 uint32 ChunkID = 0;
707 for (int32 i=theHeader.NoEntries-1;i>=0;i--) {
708 if (pSample >= theSampleToChunkArray[i]->TotalPrevSamples) {
709 // Found chunk now calculate offset
710 ChunkID = ((pSample - theSampleToChunkArray[i]->TotalPrevSamples)
711 / theSampleToChunkArray[i]->SamplesPerChunk)
712 + theSampleToChunkArray[i]->FirstChunk;
714 *pOffsetInChunk = (pSample - theSampleToChunkArray[i]->TotalPrevSamples) % theSampleToChunkArray[i]->SamplesPerChunk;
716 return ChunkID;
720 *pOffsetInChunk = 0;
721 return theSampleToChunkArray[theHeader.NoEntries-1]->FirstChunk;
725 STSSAtom::STSSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
726 uint64 pAtomSize)
728 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
730 theHeader.NoEntries = 0;
734 STSSAtom::~STSSAtom()
736 for (uint32 i=0;i<theHeader.NoEntries;i++) {
737 delete theSyncSampleArray[i];
738 theSyncSampleArray[i] = NULL;
743 void
744 STSSAtom::OnProcessMetaData()
746 SyncSample *aSyncSample;
748 FullAtom::OnProcessMetaData();
750 ReadArrayHeader(&theHeader);
752 for (uint32 i=0;i<theHeader.NoEntries;i++) {
753 aSyncSample = new SyncSample;
755 Read(&aSyncSample->SyncSampleNo);
756 aSyncSample->SyncSampleNo--; // First frame is 0 for haiku
758 theSyncSampleArray.push_back(aSyncSample);
763 const char *
764 STSSAtom::OnGetAtomName()
766 return "Sync Sample Atom";
770 bool
771 STSSAtom::IsSyncSample(uint32 pSampleNo)
774 for (uint32 i=0;i<theHeader.NoEntries;i++) {
775 if (theSyncSampleArray[i]->SyncSampleNo == pSampleNo) {
776 return true;
779 if (pSampleNo < theSyncSampleArray[i]->SyncSampleNo) {
780 return false;
784 return false;
788 STSZAtom::STSZAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
789 uint64 pAtomSize)
791 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
793 SampleCount = 0;
797 STSZAtom::~STSZAtom()
799 for (uint32 i=0;i<SampleCount;i++) {
800 delete theSampleSizeArray[i];
801 theSampleSizeArray[i] = NULL;
806 void
807 STSZAtom::OnProcessMetaData()
809 FullAtom::OnProcessMetaData();
811 Read(&SampleSize);
812 Read(&SampleCount);
814 // If the sample size is constant there is no array and NoEntries seems to
815 // contain bad values
816 if (SampleSize == 0) {
817 SampleSizePtr aSampleSizePtr;
819 for (uint32 i=0;i<SampleCount;i++) {
820 aSampleSizePtr = new SampleSizeEntry;
822 Read(&aSampleSizePtr->EntrySize);
824 theSampleSizeArray.push_back(aSampleSizePtr);
830 const char *
831 STSZAtom::OnGetAtomName()
833 return "Sample Size Atom";
837 uint32
838 STSZAtom::GetSizeForSample(uint32 pSampleNo)
840 if (SampleSize > 0) {
841 // All samples are the same size
842 return SampleSize;
845 if (pSampleNo < SampleCount) {
846 // Sample Array indexed by SampleNo
847 return theSampleSizeArray[pSampleNo]->EntrySize;
850 printf("SampleNo %ld is outside SampleSize Array\n", pSampleNo);
851 return 0;
855 bool
856 STSZAtom::IsSingleSampleSize()
858 return (SampleSize > 0);
862 STZ2Atom::STZ2Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
863 uint64 pAtomSize)
865 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
867 SampleCount = 0;
871 STZ2Atom::~STZ2Atom()
873 for (uint32 i=0;i<SampleCount;i++) {
874 delete theSampleSizeArray[i];
875 theSampleSizeArray[i] = NULL;
880 void
881 STZ2Atom::OnProcessMetaData()
883 FullAtom::OnProcessMetaData();
885 uint8 reserved;
886 Read(&reserved);
887 Read(&reserved);
888 Read(&reserved);
890 Read(&FieldSize);
891 Read(&SampleCount);
893 SampleSizePtr aSampleSizePtr;
894 uint8 EntrySize8;
895 uint16 EntrySize16;
897 for (uint32 i=0;i<SampleCount;i++) {
898 aSampleSizePtr = new SampleSizeEntry;
900 switch (FieldSize) {
901 case 4:
902 Read(&EntrySize8);
903 // 2 values per byte
904 aSampleSizePtr->EntrySize = (uint32)(EntrySize8);
905 break;
906 case 8:
907 Read(&EntrySize8);
908 // 1 value per byte
909 aSampleSizePtr->EntrySize = (uint32)(EntrySize8);
910 break;
911 case 16:
912 Read(&EntrySize16);
913 // 1 value per 2 bytes
914 aSampleSizePtr->EntrySize = (uint32)(EntrySize16);
915 break;
918 theSampleSizeArray.push_back(aSampleSizePtr);
923 const char *
924 STZ2Atom::OnGetAtomName()
926 return "Compressed Sample Size Atom";
930 uint32
931 STZ2Atom::GetSizeForSample(uint32 pSampleNo)
933 // THIS CODE NEEDS SOME TESTING, never seen a STZ2 atom
935 uint32 index;
937 switch (FieldSize) {
938 case 4:
939 // 2 entries per array entry so Divide by 2
940 index = pSampleNo / 2;
941 if (index * 2 == pSampleNo) {
942 // even so return low nibble
943 return theSampleSizeArray[pSampleNo]->EntrySize && 0x0000000f;
944 } else {
945 // odd so return high nibble
946 return theSampleSizeArray[pSampleNo]->EntrySize && 0x000000f0;
948 break;
949 case 8:
950 return theSampleSizeArray[pSampleNo]->EntrySize;
951 break;
952 case 16:
953 return theSampleSizeArray[pSampleNo]->EntrySize;
954 break;
957 // Sample Array indexed by SampleNo
958 return theSampleSizeArray[pSampleNo]->EntrySize;
962 bool
963 STZ2Atom::IsSingleSampleSize()
965 return false;
969 STCOAtom::STCOAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
970 uint64 pAtomSize)
972 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
974 theHeader.NoEntries = 0;
978 STCOAtom::~STCOAtom()
980 for (uint32 i=0;i<theHeader.NoEntries;i++) {
981 delete theChunkToOffsetArray[i];
982 theChunkToOffsetArray[i] = NULL;
987 uint64
988 STCOAtom::OnGetChunkOffset()
990 uint32 Offset;
992 Read(&Offset);
994 // Upconvert to uint64
995 return uint64(Offset);
999 void
1000 STCOAtom::OnProcessMetaData()
1002 ChunkToOffset *aChunkToOffset;
1004 FullAtom::OnProcessMetaData();
1006 ReadArrayHeader(&theHeader);
1008 for (uint32 i=0;i<theHeader.NoEntries;i++) {
1009 aChunkToOffset = new ChunkToOffset;
1011 aChunkToOffset->Offset = OnGetChunkOffset();
1013 theChunkToOffsetArray[i] = aChunkToOffset;
1018 const char *
1019 STCOAtom::OnGetAtomName()
1021 return "Chunk to Offset Atom";
1025 uint64
1026 STCOAtom::GetOffsetForChunk(uint32 pChunkIndex)
1028 // Chunk Indexes start at 1
1029 if ((pChunkIndex > 0) && (pChunkIndex <= theHeader.NoEntries)) {
1030 return theChunkToOffsetArray[pChunkIndex - 1]->Offset;
1033 #ifdef DEBUG
1034 char msg[100]; sprintf(msg, "Bad Chunk ID %ld / %ld\n", pChunkIndex,
1035 theHeader.NoEntries);
1036 DEBUGGER(msg);
1037 #endif
1039 TRESPASS();
1040 return 0LL;
1044 DecoderConfigAtom::DecoderConfigAtom(BPositionIO *pStream, off_t pStreamOffset,
1045 uint32 pAtomType, uint64 pAtomSize)
1047 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1049 theDecoderConfig = NULL;
1050 DecoderConfigSize = 0;
1054 DecoderConfigAtom::~DecoderConfigAtom()
1056 if (theDecoderConfig) {
1057 free(theDecoderConfig);
1062 void DecoderConfigAtom::OnProcessMetaData()
1064 DecoderConfigSize = GetBytesRemaining();
1066 theDecoderConfig = (uint8 *)(malloc(DecoderConfigSize));
1067 Read(theDecoderConfig,DecoderConfigSize);
1071 uint8 *
1072 DecoderConfigAtom::GetDecoderConfig()
1074 return theDecoderConfig;
1078 bool
1079 DecoderConfigAtom::SkipTag(uint8 *ESDS, uint8 Tag, uint32 *offset)
1081 uint8 byte;
1083 byte = ESDS[(*offset)++];
1084 if (byte == Tag) {
1085 uint8 numBytes = 0;
1086 unsigned int length = 0;
1088 do {
1089 byte = ESDS[(*offset)++];
1090 numBytes++;
1091 length = (length << 7) | (byte & 0x7F);
1092 } while ((byte & 0x80) && numBytes < 4);
1093 } else {
1094 // go back Tag not found
1095 (*offset)--;
1096 return false;
1099 return true;
1103 const char *
1104 DecoderConfigAtom::OnGetAtomName()
1106 return "Decoder Config Atom - Unknown type";
1110 void
1111 DecoderConfigAtom::OverrideAudioDescription(AudioDescription *pAudioDescription)
1113 if (pAudioDescription) {
1114 pAudioDescription->DecoderConfigSize = DecoderConfigSize;
1115 pAudioDescription->theDecoderConfig = (uint8 *)(malloc(DecoderConfigSize));
1116 memcpy(pAudioDescription->theDecoderConfig, theDecoderConfig, DecoderConfigSize);
1117 OnOverrideAudioDescription(pAudioDescription);
1122 void
1123 DecoderConfigAtom::OverrideVideoDescription(VideoDescription *pVideoDescription)
1125 if (pVideoDescription) {
1126 pVideoDescription->DecoderConfigSize = DecoderConfigSize;
1127 pVideoDescription->theDecoderConfig = (uint8 *)(malloc(DecoderConfigSize));
1128 memcpy(pVideoDescription->theDecoderConfig, theDecoderConfig, DecoderConfigSize);
1129 OnOverrideVideoDescription(pVideoDescription);
1134 ESDSAtom::ESDSAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1135 uint64 pAtomSize)
1137 DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1142 ESDSAtom::~ESDSAtom()
1147 void
1148 ESDSAtom::OnProcessMetaData()
1150 // Read 4 bytes because this is really a FullAtom
1151 uint32 version;
1152 Read(&version);
1153 DecoderConfigAtom::OnProcessMetaData();
1157 const char *
1158 ESDSAtom::OnGetAtomName()
1160 return "Extended Sample Description Atom";
1164 const char * obj_type_names[]=
1166 "Unknown",
1167 "Main-AAC",
1168 "LC-AAC",
1169 "SSR-AAC",
1170 "LTP-AAC",
1171 "HE-AAC",
1172 "HE-AAC(disabled)"
1176 int aac_sampling_rate[16] =
1178 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1179 16000, 12000, 11025, 8000, 7350, 0, 0, 0
1183 void
1184 ESDSAtom::OnOverrideAudioDescription(AudioDescription *pAudioDescription)
1186 // decode for aac and check for HE-AAC which uses a framesize of 2048
1187 // also check for MP3 which has an ESDS
1188 uint32 offset = 0;
1189 BitParser parser;
1191 if (SkipTag(pAudioDescription->theDecoderConfig, 0x03, &offset)) {
1192 offset += 3;
1193 } else {
1194 offset += 2;
1197 if (SkipTag(pAudioDescription->theDecoderConfig, 0x04, &offset)) {
1198 parser.Init(&pAudioDescription->theDecoderConfig[offset],
1199 (pAudioDescription->DecoderConfigSize - offset) * 8);
1201 ESDSType = parser.GetValue(8);
1202 StreamType = parser.GetValue(6);
1203 parser.Skip(2);
1204 NeededBufferSize = parser.GetValue(24);
1205 MaxBitRate = parser.GetValue(32);
1206 AvgBitRate = parser.GetValue(32);
1208 pAudioDescription->BitRate = AvgBitRate;
1210 offset+=13;
1213 // Find Tag 0x05 that describes the audio format
1214 SkipTag(pAudioDescription->theDecoderConfig, 0x05, &offset);
1215 bool smallFrameSize;
1216 uint32 SampleRate;
1218 // remember where the tag 5 starts
1219 uint32 extendedAudioConfig = offset;
1221 switch (ESDSType) {
1222 case 64: // AAC so use AAC Header details to override ESDS values
1223 parser.Init(&pAudioDescription->theDecoderConfig[offset],
1224 (pAudioDescription->DecoderConfigSize - offset) * 8);
1226 // 5 bits are decoder type
1227 theAACHeader.objTypeIndex = parser.GetValue(5);
1228 if (theAACHeader.objTypeIndex == 31) {
1229 theAACHeader.objTypeIndex = 32 + parser.GetValue(6);
1231 // 4 bits are frequency index
1232 theAACHeader.sampleRateIndex = parser.GetValue(4);
1233 if (theAACHeader.sampleRateIndex == 15) {
1234 // Direct encoding of SampleRate
1235 SampleRate = parser.GetValue(24);
1236 } else {
1237 SampleRate = aac_sampling_rate[theAACHeader.sampleRateIndex];
1240 // 4 bits are channels
1241 theAACHeader.totalChannels = parser.GetValue(4);
1242 // 1 bit determines small frame size
1243 smallFrameSize = (parser.GetValue(1) == 1);
1245 if (theAACHeader.objTypeIndex < 3) {
1246 pAudioDescription->codecSubType = 'mp4a';
1247 pAudioDescription->FrameSize = 1024;
1248 if (smallFrameSize) {
1249 pAudioDescription->FrameSize = 960;
1251 } else {
1252 pAudioDescription->codecSubType = 'haac';
1253 pAudioDescription->FrameSize = 2048;
1256 // Override STSD
1257 pAudioDescription->theAudioSampleEntry.SampleRate = SampleRate;
1258 pAudioDescription->theAudioSampleEntry.ChannelCount =
1259 theAACHeader.totalChannels;
1261 // Reset decoder Config memory
1262 memcpy(pAudioDescription->theDecoderConfig,
1263 &pAudioDescription->theDecoderConfig[extendedAudioConfig],
1264 pAudioDescription->DecoderConfigSize - extendedAudioConfig + 1);
1266 break;
1268 case 107: // MP3
1269 pAudioDescription->codecSubType = '.mp3';
1271 // Only set this for mp3, we calc it normally
1272 if (NeededBufferSize > pAudioDescription->BufferSize) {
1273 pAudioDescription->BufferSize = NeededBufferSize;
1276 break;
1281 void
1282 ESDSAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription)
1284 // Nothing to override
1288 ALACAtom::ALACAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1289 uint64 pAtomSize)
1291 DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1296 ALACAtom::~ALACAtom()
1301 void
1302 ALACAtom::OnProcessMetaData()
1304 DecoderConfigAtom::OnProcessMetaData();
1308 const char *
1309 ALACAtom::OnGetAtomName()
1311 return "ALAC Decoder Config Atom";
1315 void
1316 ALACAtom::OnOverrideAudioDescription(AudioDescription *pAudioDescription)
1318 pAudioDescription->codecSubType = 'alac';
1319 pAudioDescription->FrameSize = 4096;
1323 void
1324 ALACAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription)
1326 // Nothing to override
1330 WAVEAtom::WAVEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1331 uint64 pAtomSize)
1333 DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1338 WAVEAtom::~WAVEAtom()
1343 void
1344 WAVEAtom::OnProcessMetaData()
1349 const char *
1350 WAVEAtom::OnGetAtomName()
1352 return "WAVE Decoder Config Atom";
1356 void
1357 WAVEAtom::OnOverrideAudioDescription(AudioDescription *pAudioDescription)
1359 pAudioDescription->codecSubType = '.mp3';
1360 pAudioDescription->FrameSize = 1;
1364 void
1365 WAVEAtom::OnOverrideVideoDescription(VideoDescription *pVideoDescription)
1367 // Nothing to override
1371 DAC3Atom::DAC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1372 uint64 pAtomSize)
1374 DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1379 DAC3Atom::~DAC3Atom()
1384 void
1385 DAC3Atom::OnProcessMetaData()
1387 DecoderConfigAtom::OnProcessMetaData();
1391 void
1392 DAC3Atom::OnOverrideAudioDescription(AudioDescription *pAudioDescription)
1394 pAudioDescription->codecSubType = 'dac3';
1395 pAudioDescription->FrameSize = 1536;
1399 void
1400 DAC3Atom::OnOverrideVideoDescription(VideoDescription *pVideoDescription)
1402 // Nothing to override
1406 const char *
1407 DAC3Atom::OnGetAtomName()
1409 return "Digital AC3";
1413 DEC3Atom::DEC3Atom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1414 uint64 pAtomSize)
1416 DecoderConfigAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1421 DEC3Atom::~DEC3Atom()
1426 void
1427 DEC3Atom::OnProcessMetaData()
1429 DecoderConfigAtom::OnProcessMetaData();
1433 void
1434 DEC3Atom::OnOverrideAudioDescription(AudioDescription *pAudioDescription)
1436 pAudioDescription->codecSubType = 'dec3';
1437 pAudioDescription->FrameSize = 1536;
1441 void
1442 DEC3Atom::OnOverrideVideoDescription(VideoDescription *pVideoDescription)
1444 // Nothing to override
1448 const char *
1449 DEC3Atom::OnGetAtomName()
1451 return "Digital EAC3";
1455 STSDAtom::STSDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1456 uint64 pAtomSize)
1458 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1460 theHeader.NoEntries = 0;
1461 theAudioDescription.codecid = 0;
1462 theAudioDescription.codecSubType = 0;
1463 theAudioDescription.FrameSize = 1;
1464 theAudioDescription.BufferSize = 0;
1465 theAudioDescription.BitRate = 0;
1466 theAudioDescription.theDecoderConfig = NULL;
1467 theVideoDescription.theDecoderConfig = NULL;
1471 STSDAtom::~STSDAtom()
1473 if (theAudioDescription.theDecoderConfig) {
1474 free(theAudioDescription.theDecoderConfig);
1475 theAudioDescription.theDecoderConfig = NULL;
1478 if (theVideoDescription.theDecoderConfig) {
1479 free(theVideoDescription.theDecoderConfig);
1480 theVideoDescription.theDecoderConfig = NULL;
1485 uint32
1486 STSDAtom::GetMediaHandlerType()
1488 return dynamic_cast<STBLAtom *>(GetParent())->GetMediaHandlerType();
1492 void
1493 STSDAtom::ReadDecoderConfig(uint8 **pDecoderConfig, size_t *pDecoderConfigSize,
1494 AudioDescription *pAudioDescription, VideoDescription *pVideoDescription)
1496 // Check for a Decoder Config and if it exists copy it back to the caller
1497 // MPEG-4 video/audio use the various decoder config structures to pass
1498 // additional decoder information to the decoder. The extractor sometimes
1499 // needs to decode the data to work out how to properly construct the
1500 // decoder
1502 // First make sure we have a something
1503 if (GetBytesRemaining() > 0) {
1504 // Well something is there so read it as an atom
1505 AtomBase *aAtomBase = GetAtom(theStream);
1507 aAtomBase->ProcessMetaData();
1508 printf("%s [%Ld]\n",aAtomBase->GetAtomName(),aAtomBase->GetAtomSize());
1510 if (dynamic_cast<DecoderConfigAtom *>(aAtomBase)) {
1511 // DecoderConfig atom good
1512 DecoderConfigAtom *aDecoderConfigAtom =
1513 dynamic_cast<DecoderConfigAtom *>(aAtomBase);
1514 aDecoderConfigAtom->OverrideAudioDescription(pAudioDescription);
1515 aDecoderConfigAtom->OverrideVideoDescription(pVideoDescription);
1517 delete aAtomBase;
1518 } else {
1519 // Unknown atom bad
1520 printf("Unknown atom %s\n",aAtomBase->GetAtomName());
1521 delete aAtomBase;
1527 void
1528 STSDAtom::ReadSoundDescription()
1530 Read(&theAudioDescription.theAudioSampleEntry.Reserved[1]);
1531 Read(&theAudioDescription.theAudioSampleEntry.Reserved[2]);
1532 Read(&theAudioDescription.theAudioSampleEntry.ChannelCount);
1533 Read(&theAudioDescription.theAudioSampleEntry.SampleSize);
1534 Read(&theAudioDescription.theAudioSampleEntry.pre_defined);
1535 Read(&theAudioDescription.theAudioSampleEntry.reserved);
1536 Read(&theAudioDescription.theAudioSampleEntry.SampleRate);
1538 theAudioDescription.theAudioSampleEntry.SampleRate =
1539 theAudioDescription.theAudioSampleEntry.SampleRate / 65536;
1540 // Convert from fixed point decimal to float
1542 ReadDecoderConfig(&theAudioDescription.theDecoderConfig,
1543 &theAudioDescription.DecoderConfigSize, &theAudioDescription, NULL);
1547 void
1548 STSDAtom::ReadVideoDescription()
1550 Read(&theVideoDescription.theVideoSampleEntry.pre_defined1);
1551 Read(&theVideoDescription.theVideoSampleEntry.reserved1);
1552 Read(&theVideoDescription.theVideoSampleEntry.pre_defined2[0]);
1553 Read(&theVideoDescription.theVideoSampleEntry.pre_defined2[1]);
1554 Read(&theVideoDescription.theVideoSampleEntry.pre_defined2[2]);
1555 Read(&theVideoDescription.theVideoSampleEntry.Width);
1556 Read(&theVideoDescription.theVideoSampleEntry.Height);
1557 Read(&theVideoDescription.theVideoSampleEntry.HorizontalResolution);
1558 Read(&theVideoDescription.theVideoSampleEntry.VerticalResolution);
1559 Read(&theVideoDescription.theVideoSampleEntry.reserved2);
1560 Read(&theVideoDescription.theVideoSampleEntry.FrameCount);
1562 Read(theVideoDescription.theVideoSampleEntry.CompressorName,32);
1564 // convert from pascal string (first bytes size) to C string (null terminated)
1565 uint8 size = (uint8)(theVideoDescription.theVideoSampleEntry.CompressorName[0]);
1566 if (size > 0 && size < 32) {
1567 memmove(&theVideoDescription.theVideoSampleEntry.CompressorName[0],
1568 &theVideoDescription.theVideoSampleEntry.CompressorName[1],size);
1569 theVideoDescription.theVideoSampleEntry.CompressorName[size] = '\0';
1570 printf("Compressed using %s\n",
1571 theVideoDescription.theVideoSampleEntry.CompressorName);
1574 Read(&theVideoDescription.theVideoSampleEntry.Depth);
1575 Read(&theVideoDescription.theVideoSampleEntry.pre_defined3);
1577 ReadDecoderConfig(&theVideoDescription.theDecoderConfig, &theVideoDescription.DecoderConfigSize, NULL, &theVideoDescription);
1581 void
1582 STSDAtom::OnProcessMetaData()
1584 FullAtom::OnProcessMetaData();
1586 ReadArrayHeader(&theHeader);
1588 // This Atom allows for multiple Desc Entries, we don't
1590 // Ok the committee was drunk when they designed this.
1591 // We are actually reading a Atom/Box where the Atom Type is the codec id.
1592 uint32 Size;
1594 Read(&Size);
1595 Read(&codecid);
1597 Read(theSampleEntry.Reserved,6);
1598 Read(&theSampleEntry.DataReference);
1600 switch (GetMediaHandlerType()) {
1601 case 'soun':
1602 ReadSoundDescription();
1603 theAudioDescription.codecid = codecid;
1604 break;
1605 case 'vide':
1606 ReadVideoDescription();
1607 theVideoDescription.codecid = codecid;
1608 break;
1609 case 'hint':
1610 break;
1611 default:
1612 break;
1617 VideoDescription
1618 STSDAtom::GetAsVideo()
1620 // Assert IsVideo
1621 return theVideoDescription;
1625 AudioDescription STSDAtom::GetAsAudio()
1627 // Assert IsAudio
1628 return theAudioDescription;
1632 const char *
1633 STSDAtom::OnGetAtomName()
1635 return "Sample Description Atom";
1639 TMCDAtom::TMCDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1640 uint64 pAtomSize)
1642 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1647 TMCDAtom::~TMCDAtom()
1652 void
1653 TMCDAtom::OnProcessMetaData()
1658 const char *
1659 TMCDAtom::OnGetAtomName()
1661 return "TimeCode Atom";
1665 WIDEAtom::WIDEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1666 uint64 pAtomSize)
1668 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1673 WIDEAtom::~WIDEAtom()
1678 void
1679 WIDEAtom::OnProcessMetaData()
1684 const char *
1685 WIDEAtom::OnGetAtomName()
1687 return "WIDE Atom";
1691 FTYPAtom::FTYPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1692 uint64 pAtomSize)
1694 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1696 total_brands = 0;
1700 FTYPAtom::~FTYPAtom()
1705 void
1706 FTYPAtom::OnProcessMetaData()
1708 Read(&major_brand);
1709 Read(&minor_version);
1711 total_brands = GetBytesRemaining() / sizeof(uint32);
1713 if (total_brands > 32) {
1714 total_brands = 32; // restrict to 32
1717 for (uint32 i=0;i<total_brands;i++) {
1718 Read(&compatable_brands[i]);
1724 const char *
1725 FTYPAtom::OnGetAtomName()
1727 return "File type Atom";
1730 bool
1731 FTYPAtom::HasBrand(uint32 brand)
1734 if (major_brand == brand) {
1735 return true;
1738 // return true if the specified brand is in the list
1739 for (uint32 i=0;i<total_brands;i++) {
1740 if (compatable_brands[i] == brand) {
1741 return true;
1745 return false;
1749 FREEAtom::FREEAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1750 uint64 pAtomSize)
1752 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1757 FREEAtom::~FREEAtom()
1762 void
1763 FREEAtom::OnProcessMetaData()
1768 const char *
1769 FREEAtom::OnGetAtomName()
1771 return "Free Atom";
1775 PNOTAtom::PNOTAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1776 uint64 pAtomSize)
1778 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1783 PNOTAtom::~PNOTAtom()
1788 void
1789 PNOTAtom::OnProcessMetaData()
1794 const char *
1795 PNOTAtom::OnGetAtomName()
1797 return "Preview Atom";
1801 SKIPAtom::SKIPAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1802 uint64 pAtomSize)
1804 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1809 SKIPAtom::~SKIPAtom()
1814 void
1815 SKIPAtom::OnProcessMetaData()
1820 const char *
1821 SKIPAtom::OnGetAtomName()
1823 return "Skip Atom";
1827 MDATAtom::MDATAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1828 uint64 pAtomSize)
1830 AtomBase(pStream, pStreamOffset, pAtomType, pAtomSize)
1835 MDATAtom::~MDATAtom()
1840 void
1841 MDATAtom::OnProcessMetaData()
1846 const char *
1847 MDATAtom::OnGetAtomName()
1849 return "Media Data Atom";
1853 off_t
1854 MDATAtom::GetEOF()
1856 return GetAtomOffset() + GetAtomSize() - 8;
1860 MINFAtom::MINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1861 uint64 pAtomSize)
1863 AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize)
1868 MINFAtom::~MINFAtom()
1873 void
1874 MINFAtom::OnProcessMetaData()
1879 const char *
1880 MINFAtom::OnGetAtomName()
1882 return "MPEG-4 Media Information Atom";
1886 uint32
1887 MINFAtom::GetMediaHandlerType()
1889 return dynamic_cast<MDIAAtom *>(GetParent())->GetMediaHandlerType();
1893 STBLAtom::STBLAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1894 uint64 pAtomSize)
1896 AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize)
1901 STBLAtom::~STBLAtom()
1906 void
1907 STBLAtom::OnProcessMetaData()
1912 const char *
1913 STBLAtom::OnGetAtomName()
1915 return "MPEG-4 Sample Table Atom";
1919 uint32
1920 STBLAtom::GetMediaHandlerType()
1922 return dynamic_cast<MINFAtom *>(GetParent())->GetMediaHandlerType();
1926 DINFAtom::DINFAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1927 uint64 pAtomSize)
1929 AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize)
1934 DINFAtom::~DINFAtom()
1939 void
1940 DINFAtom::OnProcessMetaData()
1945 const char *
1946 DINFAtom::OnGetAtomName()
1948 return "MPEG-4 Data Information Atom";
1952 TKHDAtom::TKHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
1953 uint64 pAtomSize)
1955 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
1960 TKHDAtom::~TKHDAtom()
1965 void
1966 TKHDAtom::OnProcessMetaData()
1969 FullAtom::OnProcessMetaData();
1971 if (GetVersion() == 0) {
1972 tkhdV0 aHeaderV0;
1974 Read(&aHeaderV0.CreationTime);
1975 Read(&aHeaderV0.ModificationTime);
1976 Read(&aHeaderV0.TrackID);
1977 Read(&aHeaderV0.Reserved1);
1978 Read(&aHeaderV0.Duration);
1979 Read(&aHeaderV0.Reserved2[0]);
1980 Read(&aHeaderV0.Reserved2[1]);
1981 Read(&aHeaderV0.Layer);
1982 Read(&aHeaderV0.AlternateGroup);
1983 Read(&aHeaderV0.Volume);
1984 Read(&aHeaderV0.Reserved3);
1986 for (uint32 i=0;i<9;i++) {
1987 Read(&theHeader.MatrixStructure[i]);
1990 Read(&aHeaderV0.TrackWidth);
1991 Read(&aHeaderV0.TrackHeight);
1993 // upconvert to V1 header
1994 theHeader.CreationTime = (uint64)(aHeaderV0.CreationTime);
1995 theHeader.ModificationTime = (uint64)(aHeaderV0.ModificationTime);
1996 theHeader.TrackID = aHeaderV0.TrackID;
1997 theHeader.Duration = (uint64)(aHeaderV0.Duration);
1998 theHeader.Layer = aHeaderV0.Layer;
1999 theHeader.AlternateGroup = aHeaderV0.AlternateGroup;
2000 theHeader.Volume = aHeaderV0.Volume;
2001 theHeader.TrackWidth = aHeaderV0.TrackWidth;
2002 theHeader.TrackHeight = aHeaderV0.TrackHeight;
2003 } else {
2004 Read(&theHeader.CreationTime);
2005 Read(&theHeader.ModificationTime);
2006 Read(&theHeader.TrackID);
2007 Read(&theHeader.Reserved1);
2008 Read(&theHeader.Duration);
2009 Read(&theHeader.Reserved2[0]);
2010 Read(&theHeader.Reserved2[1]);
2011 Read(&theHeader.Layer);
2012 Read(&theHeader.AlternateGroup);
2013 Read(&theHeader.Volume);
2014 Read(&theHeader.Reserved3);
2016 for (uint32 i=0;i<9;i++)
2017 Read(&theHeader.MatrixStructure[i]);
2019 Read(&theHeader.TrackWidth);
2020 Read(&theHeader.TrackHeight);
2025 const char *
2026 TKHDAtom::OnGetAtomName()
2028 return "MPEG-4 Track Header";
2032 MDIAAtom::MDIAAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
2033 uint64 pAtomSize)
2035 AtomContainer(pStream, pStreamOffset, pAtomType, pAtomSize)
2040 MDIAAtom::~MDIAAtom()
2045 void
2046 MDIAAtom::OnProcessMetaData()
2051 const char *
2052 MDIAAtom::OnGetAtomName()
2054 return "MPEG-4 Media Atom";
2058 uint32
2059 MDIAAtom::GetMediaHandlerType()
2061 // Get child atom hdlr
2062 HDLRAtom *aHDLRAtom;
2063 aHDLRAtom = dynamic_cast<HDLRAtom *>(GetChildAtom(uint32('hdlr')));
2065 if (aHDLRAtom) {
2066 return aHDLRAtom->GetMediaHandlerType();
2069 return 0;
2073 MDHDAtom::MDHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
2074 uint64 pAtomSize)
2076 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
2081 MDHDAtom::~MDHDAtom()
2086 void
2087 MDHDAtom::OnProcessMetaData()
2089 FullAtom::OnProcessMetaData();
2091 if (GetVersion() == 0) {
2092 mdhdV0 aHeader;
2094 Read(&aHeader.CreationTime);
2095 Read(&aHeader.ModificationTime);
2096 Read(&aHeader.TimeScale);
2097 Read(&aHeader.Duration);
2098 Read(&aHeader.Language);
2099 Read(&aHeader.Reserved);
2101 theHeader.CreationTime = (uint64)(aHeader.CreationTime);
2102 theHeader.ModificationTime = (uint64)(aHeader.ModificationTime);
2103 theHeader.TimeScale = aHeader.TimeScale;
2104 theHeader.Duration = (uint64)(aHeader.Duration);
2105 theHeader.Language = aHeader.Language;
2106 } else {
2107 Read(&theHeader.CreationTime);
2108 Read(&theHeader.ModificationTime);
2109 Read(&theHeader.TimeScale);
2110 Read(&theHeader.Duration);
2111 Read(&theHeader.Language);
2112 Read(&theHeader.Reserved);
2117 const char *
2118 MDHDAtom::OnGetAtomName()
2120 return "MPEG-4 Media Header";
2124 bigtime_t
2125 MDHDAtom::GetDuration()
2127 return bigtime_t((theHeader.Duration * 1000000.0) / theHeader.TimeScale);
2131 uint32
2132 MDHDAtom::GetTimeScale()
2134 return theHeader.TimeScale;
2138 HDLRAtom::HDLRAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
2139 uint64 pAtomSize)
2141 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
2143 name = NULL;
2147 HDLRAtom::~HDLRAtom()
2149 if (name) {
2150 free(name);
2155 void
2156 HDLRAtom::OnProcessMetaData()
2158 FullAtom::OnProcessMetaData();
2160 Read(&theHeader.pre_defined);
2161 Read(&theHeader.handler_type);
2162 Read(&theHeader.Reserved[0]);
2163 Read(&theHeader.Reserved[1]);
2164 Read(&theHeader.Reserved[2]);
2166 name = (char *)(malloc(GetBytesRemaining()));
2168 Read(name,GetBytesRemaining());
2172 const char *
2173 HDLRAtom::OnGetAtomName()
2175 return "MPEG-4 Handler Reference Atom ";
2179 bool
2180 HDLRAtom::IsVideoHandler()
2182 return (theHeader.handler_type == 'vide');
2186 bool
2187 HDLRAtom::IsAudioHandler()
2189 return (theHeader.handler_type == 'soun');
2193 uint32
2194 HDLRAtom::GetMediaHandlerType()
2196 return theHeader.handler_type;
2200 VMHDAtom::VMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
2201 uint64 pAtomSize)
2203 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
2208 VMHDAtom::~VMHDAtom()
2213 void
2214 VMHDAtom::OnProcessMetaData()
2216 FullAtom::OnProcessMetaData();
2218 Read(&theHeader.GraphicsMode);
2219 Read(&theHeader.OpColour[0]);
2220 Read(&theHeader.OpColour[1]);
2221 Read(&theHeader.OpColour[2]);
2225 const char *
2226 VMHDAtom::OnGetAtomName()
2228 return "MPEG-4 Video Media Header";
2232 SMHDAtom::SMHDAtom(BPositionIO *pStream, off_t pStreamOffset, uint32 pAtomType,
2233 uint64 pAtomSize)
2235 FullAtom(pStream, pStreamOffset, pAtomType, pAtomSize)
2240 SMHDAtom::~SMHDAtom()
2245 void
2246 SMHDAtom::OnProcessMetaData()
2248 FullAtom::OnProcessMetaData();
2250 Read(&theHeader.Balance);
2251 Read(&theHeader.Reserved);
2255 const char *
2256 SMHDAtom::OnGetAtomName()
2258 return "MPEG-4 Sound Media Header";