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"
32 #include <MediaFormats.h>
33 #include <SupportKit.h>
37 #include "BitParser.h"
41 GetAtom(BPositionIO
*pStream
)
48 aStreamOffset
= pStream
->Position();
51 pStream
->Read(&aAtomSize
,4);
52 aAtomSize
= B_BENDIAN_TO_HOST_INT32(aAtomSize
);
54 pStream
->Read(&aAtomType
,4);
55 aAtomType
= B_BENDIAN_TO_HOST_INT32(aAtomType
);
56 // Check for extended size
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
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
,
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
,
190 MOOVAtom::~MOOVAtom()
197 MOOVAtom::OnProcessMetaData()
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
,
212 theUncompressedStream
= NULL
;
216 CMOVAtom::~CMOVAtom()
222 CMOVAtom::OnGetStream()
224 // Use the decompressed stream instead of file stream
225 if (theUncompressedStream
)
226 return theUncompressedStream
;
233 CMOVAtom::OnProcessMetaData()
235 BMallocIO
*theUncompressedData
;
237 CMVDAtom
*aCMVDAtom
= NULL
;
238 uint32 compressionID
= 0;
239 uint64 descBytesLeft
;
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();
253 printf("Invalid Atom found when reading Compressed Headers\n");
257 if (dynamic_cast<DCOMAtom
*>(aAtomBase
)) {
259 compressionID
= dynamic_cast<DCOMAtom
*>(aAtomBase
)->GetCompressionID();
262 if (dynamic_cast<CMVDAtom
*>(aAtomBase
)) {
264 aCMVDAtom
= dynamic_cast<CMVDAtom
*>(aAtomBase
);
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 ");
283 DEBUGGER("Lack of Memory Error\n");
286 DEBUGGER("Lack of Output buffer space Error\n");
289 DEBUGGER("Input Data is corrupt or not a compressed set Error\n");
294 // Copy uncompressed data into BMAllocIO
295 theUncompressedData
= new BMallocIO();
296 theUncompressedData
->SetSize(Size
);
297 theUncompressedData
->WriteAt(0L,outBuffer
,Size
);
302 // reset position on BMAllocIO
303 theUncompressedData
->Seek(SEEK_SET
,0L);
305 theUncompressedStream
= theUncompressedData
;
307 // All subsequent reads should use theUncompressedStream
314 CMOVAtom::OnChildProcessingComplete()
316 // revert back to file stream once all children have finished
317 if (theUncompressedStream
) {
318 delete theUncompressedStream
;
320 theUncompressedStream
= NULL
;
325 CMOVAtom::OnGetAtomName()
327 return "Compressed MPEG-4 Movie";
331 DCOMAtom::DCOMAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
334 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
339 DCOMAtom::~DCOMAtom()
345 DCOMAtom::OnProcessMetaData()
347 Read(&compressionID
);
352 DCOMAtom::OnGetAtomName()
354 return "Decompression Atom";
358 CMVDAtom::CMVDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
361 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
364 UncompressedSize
= 0;
369 CMVDAtom::~CMVDAtom()
377 CMVDAtom::OnProcessMetaData()
379 Read(&UncompressedSize
);
381 if (UncompressedSize
> 0) {
382 BufferSize
= GetBytesRemaining();
383 Buffer
= (uint8
*)(malloc(BufferSize
));
384 Read(Buffer
,BufferSize
);
390 CMVDAtom::OnGetAtomName()
392 return "Compressed Movie Data";
396 MVHDAtom::MVHDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
399 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
404 MVHDAtom::~MVHDAtom()
410 MVHDAtom::OnProcessMetaData()
412 FullAtom::OnProcessMetaData();
414 if (GetVersion() == 0) {
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
);
467 MVHDAtom::OnGetAtomName()
469 return "MPEG-4 Movie Header";
474 MOOVAtom::GetMVHDAtom()
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");
488 STTSAtom::STTSAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
491 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
493 theHeader
.NoEntries
= 0;
499 STTSAtom::~STTSAtom()
501 for (uint32 i
=0;i
<theHeader
.NoEntries
;i
++) {
502 delete theTimeToSampleArray
[i
];
503 theTimeToSampleArray
[i
] = NULL
;
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
;
532 STTSAtom::OnGetAtomName()
534 return "Time to Sample Atom";
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);
563 STTSAtom::GetSampleForFrame(uint32 pFrame
)
565 // Convert frame to time and call GetSampleForTime()
570 CTTSAtom::CTTSAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
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
;
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
;
609 CTTSAtom::OnGetAtomName()
611 return "Composition Time to Sample Atom";
615 STSCAtom::STSCAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
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
;
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
);
652 TotalPrevSamples
= TotalPrevSamples
+ (aSampleToChunk
->FirstChunk
- theSampleToChunkArray
[i
-1]->FirstChunk
) * theSampleToChunkArray
[i
-1]->SamplesPerChunk
;
653 aSampleToChunk
->TotalPrevSamples
= TotalPrevSamples
;
655 aSampleToChunk
->TotalPrevSamples
= 0;
658 theSampleToChunkArray
.push_back(aSampleToChunk
);
664 STSCAtom::OnGetAtomName()
666 return "Sample to Chunk Atom";
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
;
684 STSCAtom::GetFirstSampleInChunk(uint32 pChunkID
)
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
;
703 STSCAtom::GetChunkForSample(uint32 pSample
, uint32
*pOffsetInChunk
)
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
;
721 return theSampleToChunkArray
[theHeader
.NoEntries
-1]->FirstChunk
;
725 STSSAtom::STSSAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
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
;
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
);
764 STSSAtom::OnGetAtomName()
766 return "Sync Sample Atom";
771 STSSAtom::IsSyncSample(uint32 pSampleNo
)
774 for (uint32 i
=0;i
<theHeader
.NoEntries
;i
++) {
775 if (theSyncSampleArray
[i
]->SyncSampleNo
== pSampleNo
) {
779 if (pSampleNo
< theSyncSampleArray
[i
]->SyncSampleNo
) {
788 STSZAtom::STSZAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
791 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
797 STSZAtom::~STSZAtom()
799 for (uint32 i
=0;i
<SampleCount
;i
++) {
800 delete theSampleSizeArray
[i
];
801 theSampleSizeArray
[i
] = NULL
;
807 STSZAtom::OnProcessMetaData()
809 FullAtom::OnProcessMetaData();
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
);
831 STSZAtom::OnGetAtomName()
833 return "Sample Size Atom";
838 STSZAtom::GetSizeForSample(uint32 pSampleNo
)
840 if (SampleSize
> 0) {
841 // All samples are the same size
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
);
856 STSZAtom::IsSingleSampleSize()
858 return (SampleSize
> 0);
862 STZ2Atom::STZ2Atom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
865 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
871 STZ2Atom::~STZ2Atom()
873 for (uint32 i
=0;i
<SampleCount
;i
++) {
874 delete theSampleSizeArray
[i
];
875 theSampleSizeArray
[i
] = NULL
;
881 STZ2Atom::OnProcessMetaData()
883 FullAtom::OnProcessMetaData();
893 SampleSizePtr aSampleSizePtr
;
897 for (uint32 i
=0;i
<SampleCount
;i
++) {
898 aSampleSizePtr
= new SampleSizeEntry
;
904 aSampleSizePtr
->EntrySize
= (uint32
)(EntrySize8
);
909 aSampleSizePtr
->EntrySize
= (uint32
)(EntrySize8
);
913 // 1 value per 2 bytes
914 aSampleSizePtr
->EntrySize
= (uint32
)(EntrySize16
);
918 theSampleSizeArray
.push_back(aSampleSizePtr
);
924 STZ2Atom::OnGetAtomName()
926 return "Compressed Sample Size Atom";
931 STZ2Atom::GetSizeForSample(uint32 pSampleNo
)
933 // THIS CODE NEEDS SOME TESTING, never seen a STZ2 atom
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;
945 // odd so return high nibble
946 return theSampleSizeArray
[pSampleNo
]->EntrySize
&& 0x000000f0;
950 return theSampleSizeArray
[pSampleNo
]->EntrySize
;
953 return theSampleSizeArray
[pSampleNo
]->EntrySize
;
957 // Sample Array indexed by SampleNo
958 return theSampleSizeArray
[pSampleNo
]->EntrySize
;
963 STZ2Atom::IsSingleSampleSize()
969 STCOAtom::STCOAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
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
;
988 STCOAtom::OnGetChunkOffset()
994 // Upconvert to uint64
995 return uint64(Offset
);
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
;
1019 STCOAtom::OnGetAtomName()
1021 return "Chunk to Offset Atom";
1026 STCOAtom::GetOffsetForChunk(uint32 pChunkIndex
)
1028 // Chunk Indexes start at 1
1029 if ((pChunkIndex
> 0) && (pChunkIndex
<= theHeader
.NoEntries
)) {
1030 return theChunkToOffsetArray
[pChunkIndex
- 1]->Offset
;
1034 char msg
[100]; sprintf(msg
, "Bad Chunk ID %ld / %ld\n", pChunkIndex
,
1035 theHeader
.NoEntries
);
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
);
1072 DecoderConfigAtom::GetDecoderConfig()
1074 return theDecoderConfig
;
1079 DecoderConfigAtom::SkipTag(uint8
*ESDS
, uint8 Tag
, uint32
*offset
)
1083 byte
= ESDS
[(*offset
)++];
1086 unsigned int length
= 0;
1089 byte
= ESDS
[(*offset
)++];
1091 length
= (length
<< 7) | (byte
& 0x7F);
1092 } while ((byte
& 0x80) && numBytes
< 4);
1094 // go back Tag not found
1104 DecoderConfigAtom::OnGetAtomName()
1106 return "Decoder Config Atom - Unknown type";
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
);
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
,
1137 DecoderConfigAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1142 ESDSAtom::~ESDSAtom()
1148 ESDSAtom::OnProcessMetaData()
1150 // Read 4 bytes because this is really a FullAtom
1153 DecoderConfigAtom::OnProcessMetaData();
1158 ESDSAtom::OnGetAtomName()
1160 return "Extended Sample Description Atom";
1164 const char * obj_type_names
[]=
1176 int aac_sampling_rate
[16] =
1178 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
1179 16000, 12000, 11025, 8000, 7350, 0, 0, 0
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
1191 if (SkipTag(pAudioDescription
->theDecoderConfig
, 0x03, &offset
)) {
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);
1204 NeededBufferSize
= parser
.GetValue(24);
1205 MaxBitRate
= parser
.GetValue(32);
1206 AvgBitRate
= parser
.GetValue(32);
1208 pAudioDescription
->BitRate
= AvgBitRate
;
1213 // Find Tag 0x05 that describes the audio format
1214 SkipTag(pAudioDescription
->theDecoderConfig
, 0x05, &offset
);
1215 bool smallFrameSize
;
1218 // remember where the tag 5 starts
1219 uint32 extendedAudioConfig
= offset
;
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);
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;
1252 pAudioDescription
->codecSubType
= 'haac';
1253 pAudioDescription
->FrameSize
= 2048;
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);
1269 pAudioDescription
->codecSubType
= '.mp3';
1271 // Only set this for mp3, we calc it normally
1272 if (NeededBufferSize
> pAudioDescription
->BufferSize
) {
1273 pAudioDescription
->BufferSize
= NeededBufferSize
;
1282 ESDSAtom::OnOverrideVideoDescription(VideoDescription
*pVideoDescription
)
1284 // Nothing to override
1288 ALACAtom::ALACAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1291 DecoderConfigAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1296 ALACAtom::~ALACAtom()
1302 ALACAtom::OnProcessMetaData()
1304 DecoderConfigAtom::OnProcessMetaData();
1309 ALACAtom::OnGetAtomName()
1311 return "ALAC Decoder Config Atom";
1316 ALACAtom::OnOverrideAudioDescription(AudioDescription
*pAudioDescription
)
1318 pAudioDescription
->codecSubType
= 'alac';
1319 pAudioDescription
->FrameSize
= 4096;
1324 ALACAtom::OnOverrideVideoDescription(VideoDescription
*pVideoDescription
)
1326 // Nothing to override
1330 WAVEAtom::WAVEAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1333 DecoderConfigAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1338 WAVEAtom::~WAVEAtom()
1344 WAVEAtom::OnProcessMetaData()
1350 WAVEAtom::OnGetAtomName()
1352 return "WAVE Decoder Config Atom";
1357 WAVEAtom::OnOverrideAudioDescription(AudioDescription
*pAudioDescription
)
1359 pAudioDescription
->codecSubType
= '.mp3';
1360 pAudioDescription
->FrameSize
= 1;
1365 WAVEAtom::OnOverrideVideoDescription(VideoDescription
*pVideoDescription
)
1367 // Nothing to override
1371 DAC3Atom::DAC3Atom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1374 DecoderConfigAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1379 DAC3Atom::~DAC3Atom()
1385 DAC3Atom::OnProcessMetaData()
1387 DecoderConfigAtom::OnProcessMetaData();
1392 DAC3Atom::OnOverrideAudioDescription(AudioDescription
*pAudioDescription
)
1394 pAudioDescription
->codecSubType
= 'dac3';
1395 pAudioDescription
->FrameSize
= 1536;
1400 DAC3Atom::OnOverrideVideoDescription(VideoDescription
*pVideoDescription
)
1402 // Nothing to override
1407 DAC3Atom::OnGetAtomName()
1409 return "Digital AC3";
1413 DEC3Atom::DEC3Atom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1416 DecoderConfigAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1421 DEC3Atom::~DEC3Atom()
1427 DEC3Atom::OnProcessMetaData()
1429 DecoderConfigAtom::OnProcessMetaData();
1434 DEC3Atom::OnOverrideAudioDescription(AudioDescription
*pAudioDescription
)
1436 pAudioDescription
->codecSubType
= 'dec3';
1437 pAudioDescription
->FrameSize
= 1536;
1442 DEC3Atom::OnOverrideVideoDescription(VideoDescription
*pVideoDescription
)
1444 // Nothing to override
1449 DEC3Atom::OnGetAtomName()
1451 return "Digital EAC3";
1455 STSDAtom::STSDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
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
;
1486 STSDAtom::GetMediaHandlerType()
1488 return dynamic_cast<STBLAtom
*>(GetParent())->GetMediaHandlerType();
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
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
);
1520 printf("Unknown atom %s\n",aAtomBase
->GetAtomName());
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
);
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
);
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.
1597 Read(theSampleEntry
.Reserved
,6);
1598 Read(&theSampleEntry
.DataReference
);
1600 switch (GetMediaHandlerType()) {
1602 ReadSoundDescription();
1603 theAudioDescription
.codecid
= codecid
;
1606 ReadVideoDescription();
1607 theVideoDescription
.codecid
= codecid
;
1618 STSDAtom::GetAsVideo()
1621 return theVideoDescription
;
1625 AudioDescription
STSDAtom::GetAsAudio()
1628 return theAudioDescription
;
1633 STSDAtom::OnGetAtomName()
1635 return "Sample Description Atom";
1639 TMCDAtom::TMCDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1642 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1647 TMCDAtom::~TMCDAtom()
1653 TMCDAtom::OnProcessMetaData()
1659 TMCDAtom::OnGetAtomName()
1661 return "TimeCode Atom";
1665 WIDEAtom::WIDEAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1668 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1673 WIDEAtom::~WIDEAtom()
1679 WIDEAtom::OnProcessMetaData()
1685 WIDEAtom::OnGetAtomName()
1691 FTYPAtom::FTYPAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1694 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1700 FTYPAtom::~FTYPAtom()
1706 FTYPAtom::OnProcessMetaData()
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
]);
1725 FTYPAtom::OnGetAtomName()
1727 return "File type Atom";
1731 FTYPAtom::HasBrand(uint32 brand
)
1734 if (major_brand
== brand
) {
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
) {
1749 FREEAtom::FREEAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1752 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1757 FREEAtom::~FREEAtom()
1763 FREEAtom::OnProcessMetaData()
1769 FREEAtom::OnGetAtomName()
1775 PNOTAtom::PNOTAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1778 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1783 PNOTAtom::~PNOTAtom()
1789 PNOTAtom::OnProcessMetaData()
1795 PNOTAtom::OnGetAtomName()
1797 return "Preview Atom";
1801 SKIPAtom::SKIPAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1804 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1809 SKIPAtom::~SKIPAtom()
1815 SKIPAtom::OnProcessMetaData()
1821 SKIPAtom::OnGetAtomName()
1827 MDATAtom::MDATAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1830 AtomBase(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1835 MDATAtom::~MDATAtom()
1841 MDATAtom::OnProcessMetaData()
1847 MDATAtom::OnGetAtomName()
1849 return "Media Data Atom";
1856 return GetAtomOffset() + GetAtomSize() - 8;
1860 MINFAtom::MINFAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1863 AtomContainer(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1868 MINFAtom::~MINFAtom()
1874 MINFAtom::OnProcessMetaData()
1880 MINFAtom::OnGetAtomName()
1882 return "MPEG-4 Media Information Atom";
1887 MINFAtom::GetMediaHandlerType()
1889 return dynamic_cast<MDIAAtom
*>(GetParent())->GetMediaHandlerType();
1893 STBLAtom::STBLAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1896 AtomContainer(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1901 STBLAtom::~STBLAtom()
1907 STBLAtom::OnProcessMetaData()
1913 STBLAtom::OnGetAtomName()
1915 return "MPEG-4 Sample Table Atom";
1920 STBLAtom::GetMediaHandlerType()
1922 return dynamic_cast<MINFAtom
*>(GetParent())->GetMediaHandlerType();
1926 DINFAtom::DINFAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1929 AtomContainer(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1934 DINFAtom::~DINFAtom()
1940 DINFAtom::OnProcessMetaData()
1946 DINFAtom::OnGetAtomName()
1948 return "MPEG-4 Data Information Atom";
1952 TKHDAtom::TKHDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
1955 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
1960 TKHDAtom::~TKHDAtom()
1966 TKHDAtom::OnProcessMetaData()
1969 FullAtom::OnProcessMetaData();
1971 if (GetVersion() == 0) {
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
;
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
);
2026 TKHDAtom::OnGetAtomName()
2028 return "MPEG-4 Track Header";
2032 MDIAAtom::MDIAAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
2035 AtomContainer(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
2040 MDIAAtom::~MDIAAtom()
2046 MDIAAtom::OnProcessMetaData()
2052 MDIAAtom::OnGetAtomName()
2054 return "MPEG-4 Media Atom";
2059 MDIAAtom::GetMediaHandlerType()
2061 // Get child atom hdlr
2062 HDLRAtom
*aHDLRAtom
;
2063 aHDLRAtom
= dynamic_cast<HDLRAtom
*>(GetChildAtom(uint32('hdlr')));
2066 return aHDLRAtom
->GetMediaHandlerType();
2073 MDHDAtom::MDHDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
2076 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
2081 MDHDAtom::~MDHDAtom()
2087 MDHDAtom::OnProcessMetaData()
2089 FullAtom::OnProcessMetaData();
2091 if (GetVersion() == 0) {
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
;
2107 Read(&theHeader
.CreationTime
);
2108 Read(&theHeader
.ModificationTime
);
2109 Read(&theHeader
.TimeScale
);
2110 Read(&theHeader
.Duration
);
2111 Read(&theHeader
.Language
);
2112 Read(&theHeader
.Reserved
);
2118 MDHDAtom::OnGetAtomName()
2120 return "MPEG-4 Media Header";
2125 MDHDAtom::GetDuration()
2127 return bigtime_t((theHeader
.Duration
* 1000000.0) / theHeader
.TimeScale
);
2132 MDHDAtom::GetTimeScale()
2134 return theHeader
.TimeScale
;
2138 HDLRAtom::HDLRAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
2141 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
2147 HDLRAtom::~HDLRAtom()
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());
2173 HDLRAtom::OnGetAtomName()
2175 return "MPEG-4 Handler Reference Atom ";
2180 HDLRAtom::IsVideoHandler()
2182 return (theHeader
.handler_type
== 'vide');
2187 HDLRAtom::IsAudioHandler()
2189 return (theHeader
.handler_type
== 'soun');
2194 HDLRAtom::GetMediaHandlerType()
2196 return theHeader
.handler_type
;
2200 VMHDAtom::VMHDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
2203 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
2208 VMHDAtom::~VMHDAtom()
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]);
2226 VMHDAtom::OnGetAtomName()
2228 return "MPEG-4 Video Media Header";
2232 SMHDAtom::SMHDAtom(BPositionIO
*pStream
, off_t pStreamOffset
, uint32 pAtomType
,
2235 FullAtom(pStream
, pStreamOffset
, pAtomType
, pAtomSize
)
2240 SMHDAtom::~SMHDAtom()
2246 SMHDAtom::OnProcessMetaData()
2248 FullAtom::OnProcessMetaData();
2250 Read(&theHeader
.Balance
);
2251 Read(&theHeader
.Reserved
);
2256 SMHDAtom::OnGetAtomName()
2258 return "MPEG-4 Sound Media Header";