1 /*****************************************************************
2 |
3 |    AP4 - Atom Factory
4 |
5 |    Copyright 2002-2012 Axiomatic Systems, LLC
6 |
7 |
8 |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
9 |
10 |    Unless you have obtained Bento4 under a difference license,
11 |    this version of Bento4 is Bento4|GPL.
12 |    Bento4|GPL is free software; you can redistribute it and/or modify
13 |    it under the terms of the GNU General Public License as published by
14 |    the Free Software Foundation; either version 2, or (at your option)
15 |    any later version.
16 |
17 |    Bento4|GPL is distributed in the hope that it will be useful,
18 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
19 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 |    GNU General Public License for more details.
21 |
22 |    You should have received a copy of the GNU General Public License
23 |    along with Bento4|GPL; see the file COPYING.  If not, write to the
24 |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 |    02111-1307, USA.
26 |
27  ****************************************************************/
28 
29 /*----------------------------------------------------------------------
30 |   includes
31 +---------------------------------------------------------------------*/
32 #include "Ap4Types.h"
33 #include "Ap4Utils.h"
34 #include "Ap4AtomFactory.h"
35 #include "Ap4SampleEntry.h"
36 #include "Ap4UuidAtom.h"
37 #include "Ap4IsmaCryp.h"
38 #include "Ap4UrlAtom.h"
39 #include "Ap4MoovAtom.h"
40 #include "Ap4MvhdAtom.h"
41 #include "Ap4MehdAtom.h"
42 #include "Ap4MfhdAtom.h"
43 #include "Ap4TfhdAtom.h"
44 #include "Ap4TrunAtom.h"
45 #include "Ap4TrakAtom.h"
46 #include "Ap4HdlrAtom.h"
47 #include "Ap4DrefAtom.h"
48 #include "Ap4TkhdAtom.h"
49 #include "Ap4TrexAtom.h"
50 #include "Ap4TfhdAtom.h"
51 #include "Ap4MdhdAtom.h"
52 #include "Ap4StsdAtom.h"
53 #include "Ap4StscAtom.h"
54 #include "Ap4StcoAtom.h"
55 #include "Ap4Co64Atom.h"
56 #include "Ap4StszAtom.h"
57 #include "Ap4Stz2Atom.h"
58 #include "Ap4IodsAtom.h"
59 #include "Ap4EsdsAtom.h"
60 #include "Ap4SttsAtom.h"
61 #include "Ap4CttsAtom.h"
62 #include "Ap4StssAtom.h"
63 #include "Ap4FtypAtom.h"
64 #include "Ap4VmhdAtom.h"
65 #include "Ap4SmhdAtom.h"
66 #include "Ap4NmhdAtom.h"
67 #include "Ap4SthdAtom.h"
68 #include "Ap4HmhdAtom.h"
69 #include "Ap4ElstAtom.h"
70 #include "Ap4SchmAtom.h"
71 #include "Ap4FrmaAtom.h"
72 #include "Ap4TimsAtom.h"
73 #include "Ap4RtpAtom.h"
74 #include "Ap4SdpAtom.h"
75 #include "Ap4IkmsAtom.h"
76 #include "Ap4IsfmAtom.h"
77 #include "Ap4IsltAtom.h"
78 #include "Ap4OdheAtom.h"
79 #include "Ap4OhdrAtom.h"
80 #include "Ap4OddaAtom.h"
81 #include "Ap4TrefTypeAtom.h"
82 #include "Ap4MetaData.h"
83 #include "Ap4IproAtom.h"
84 #include "Ap4OdafAtom.h"
85 #include "Ap4GrpiAtom.h"
86 #include "Ap4AvccAtom.h"
87 #include "Ap4HvccAtom.h"
88 #include "Ap4Marlin.h"
89 #include "Ap48bdlAtom.h"
90 #include "Ap4Piff.h"
91 #include "Ap4TfraAtom.h"
92 #include "Ap4MfroAtom.h"
93 #include "Ap4TfdtAtom.h"
94 #include "Ap4TencAtom.h"
95 #include "Ap4SencAtom.h"
96 #include "Ap4SaioAtom.h"
97 #include "Ap4SaizAtom.h"
98 #include "Ap4PdinAtom.h"
99 #include "Ap4BlocAtom.h"
100 #include "Ap4AinfAtom.h"
101 #include "Ap4PsshAtom.h"
102 #include "Ap4Dec3Atom.h"
103 #include "Ap4Dac3Atom.h"
104 #include "Ap4SidxAtom.h"
105 #include "Ap4SbgpAtom.h"
106 #include "Ap4SgpdAtom.h"
107 #include "Ap4TrafAtom.h"
108 #include "Ap4VpcCAtom.h"
109 
110 /*----------------------------------------------------------------------
111 |   AP4_AtomFactory::~AP4_AtomFactory
112 +---------------------------------------------------------------------*/
~AP4_AtomFactory()113 AP4_AtomFactory::~AP4_AtomFactory()
114 {
115     m_TypeHandlers.DeleteReferences();
116 }
117 
118 /*----------------------------------------------------------------------
119 |   AP4_AtomFactory::AddTypeHandler
120 +---------------------------------------------------------------------*/
121 AP4_Result
AddTypeHandler(TypeHandler * handler)122 AP4_AtomFactory::AddTypeHandler(TypeHandler* handler)
123 {
124     return m_TypeHandlers.Add(handler);
125 }
126 
127 /*----------------------------------------------------------------------
128 |   AP4_AtomFactory::RemoveTypeHandler
129 +---------------------------------------------------------------------*/
130 AP4_Result
RemoveTypeHandler(TypeHandler * handler)131 AP4_AtomFactory::RemoveTypeHandler(TypeHandler* handler)
132 {
133     return m_TypeHandlers.Remove(handler);
134 }
135 
136 /*----------------------------------------------------------------------
137 |   AP4_AtomFactory::CreateAtomFromStream
138 +---------------------------------------------------------------------*/
139 AP4_Result
CreateAtomFromStream(AP4_ByteStream & stream,AP4_Atom * & atom)140 AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
141                                       AP4_Atom*&      atom)
142 {
143     AP4_LargeSize stream_size     = 0;
144     AP4_Position  stream_position = 0;
145     AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
146     if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
147         stream_size != 0 &&
148         AP4_SUCCEEDED(stream.Tell(stream_position)) &&
149         stream_position <= stream_size) {
150         bytes_available = stream_size-stream_position;
151     }
152     return CreateAtomFromStream(stream, bytes_available, atom);
153 }
154 
155 /*----------------------------------------------------------------------
156 |   AP4_AtomFactory::CreateAtomFromStream
157 +---------------------------------------------------------------------*/
158 AP4_Result
CreateAtomFromStream(AP4_ByteStream & stream,AP4_LargeSize & bytes_available,AP4_Atom * & atom)159 AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
160                                       AP4_LargeSize&  bytes_available,
161                                       AP4_Atom*&      atom)
162 {
163     AP4_Result result;
164 
165     // NULL by default
166     atom = NULL;
167 
168     // check that there are enough bytes for at least a header
169     if (bytes_available < 8) return AP4_ERROR_EOS;
170 
171     // remember current stream offset
172     AP4_Position start;
173     stream.Tell(start);
174 
175     // read atom size
176     AP4_UI32 size_32;
177     result = stream.ReadUI32(size_32);
178     if (AP4_FAILED(result)) {
179         stream.Seek(start);
180         return result;
181     }
182     AP4_UI64 size = size_32;
183 
184     // read atom type
185     AP4_Atom::Type type;
186     result = stream.ReadUI32(type);
187     if (AP4_FAILED(result)) {
188         stream.Seek(start);
189         return result;
190     }
191 
192     // handle special size values
193     bool atom_is_large = false;
194     bool force_64      = false;
195     if (size == 0) {
196         // atom extends to end of file
197         AP4_LargeSize stream_size = 0;
198         stream.GetSize(stream_size);
199         if (stream_size >= start) {
200             size = stream_size - start;
201         }
202     } else if (size == 1) {
203         // 64-bit size
204         atom_is_large = true;
205         if (bytes_available < 16) {
206             stream.Seek(start);
207             return AP4_ERROR_INVALID_FORMAT;
208         }
209         stream.ReadUI64(size);
210         if (size <= 0xFFFFFFFF) {
211             force_64 = true;
212         }
213     }
214 
215     // check the size
216     if ((size > 0 && size < 8) || size > bytes_available) {
217         stream.Seek(start);
218         return AP4_ERROR_INVALID_FORMAT;
219     }
220 
221     // create the atom
222     result = CreateAtomFromStream(stream, type, size_32, size, atom);
223     if (AP4_FAILED(result)) return result;
224 
225     // if we failed to create an atom, use a generic version
226     if (atom == NULL) {
227         unsigned int payload_offset = 8;
228         if (atom_is_large) payload_offset += 8;
229         stream.Seek(start+payload_offset);
230         atom = new AP4_UnknownAtom(type, size, stream);
231     }
232 
233     // special case: if the atom is poorly encoded and has a 64-bit
234     // size header but an actual size that fits on 32-bit, adjust the
235     // object to reflect that.
236     if (force_64) {
237         atom->SetSize32(1);
238         atom->SetSize64(size);
239     }
240 
241     // adjust the available size
242     bytes_available -= size;
243 
244     // skip to the end of the atom
245     result = stream.Seek(start+size);
246     if (AP4_FAILED(result)) {
247         delete atom;
248         atom = NULL;
249         return result;
250     }
251 
252     return AP4_SUCCESS;
253 }
254 
255 /*----------------------------------------------------------------------
256 |   AP4_AtomFactory::CreateAtomFromStream
257 +---------------------------------------------------------------------*/
258 AP4_Result
CreateAtomFromStream(AP4_ByteStream & stream,AP4_UI32 type,AP4_UI32 size_32,AP4_UI64 size_64,AP4_Atom * & atom)259 AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
260                                       AP4_UI32        type,
261                                       AP4_UI32        size_32,
262                                       AP4_UI64        size_64,
263                                       AP4_Atom*&      atom)
264 {
265     bool atom_is_large = (size_32 == 1);
266     bool force_64 = (size_32==1 && ((size_64>>32) == 0));
267 
268     // create the atom
269     if (GetContext() == AP4_ATOM_TYPE_STSD) {
270         // sample entry
271         if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
272         switch (type) {
273           case AP4_ATOM_TYPE_MP4A:
274             atom = new AP4_Mp4aSampleEntry(size_32, stream, *this);
275             break;
276 
277           case AP4_ATOM_TYPE_MP4V:
278             atom = new AP4_Mp4vSampleEntry(size_32, stream, *this);
279             break;
280 
281           case AP4_ATOM_TYPE_MP4S:
282             atom = new AP4_Mp4sSampleEntry(size_32, stream, *this);
283             break;
284 
285           case AP4_ATOM_TYPE_ENCA:
286             atom = new AP4_EncaSampleEntry(size_32, stream, *this);
287             break;
288 
289           case AP4_ATOM_TYPE_ENCV:
290             atom = new AP4_EncvSampleEntry(size_32, stream, *this);
291             break;
292 
293           case AP4_ATOM_TYPE_DRMS:
294             atom = new AP4_DrmsSampleEntry(size_32, stream, *this);
295             break;
296 
297           case AP4_ATOM_TYPE_DRMI:
298             atom = new AP4_DrmiSampleEntry(size_32, stream, *this);
299             break;
300 
301           case AP4_ATOM_TYPE_AVC1:
302           case AP4_ATOM_TYPE_AVC2:
303           case AP4_ATOM_TYPE_AVC3:
304           case AP4_ATOM_TYPE_AVC4:
305             atom = new AP4_AvcSampleEntry(type, size_32, stream, *this);
306             break;
307 
308           case AP4_ATOM_TYPE_HEV1:
309           case AP4_ATOM_TYPE_HVC1:
310             atom = new AP4_HevcSampleEntry(type, size_32, stream, *this);
311             break;
312 
313           case AP4_ATOM_TYPE_ALAC:
314           case AP4_ATOM_TYPE_AC_3:
315           case AP4_ATOM_TYPE_EC_3:
316           case AP4_ATOM_TYPE_DTSC:
317           case AP4_ATOM_TYPE_DTSH:
318           case AP4_ATOM_TYPE_DTSL:
319           case AP4_ATOM_TYPE_DTSE:
320             atom = new AP4_AudioSampleEntry(type, size_32, stream, *this);
321             break;
322 
323           case AP4_ATOM_TYPE_RTP_:
324             atom = new AP4_RtpHintSampleEntry(size_32, stream, *this);
325             break;
326 
327           case AP4_ATOM_TYPE_STPP:
328             atom = new AP4_SubtitleSampleEntry(type, size_32, stream, *this);
329             break;
330 
331           default: {
332             // try all the external type handlers
333             AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
334             while (handler_item) {
335                 TypeHandler* handler = handler_item->GetData();
336                 if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
337                     break;
338                 }
339                 handler_item = handler_item->GetNext();
340             }
341 
342             // no custom handler, create a generic entry
343             if (atom == NULL) {
344                 atom = new AP4_UnknownSampleEntry(type, (AP4_UI32)size_64, stream);
345             }
346 
347             break;
348           }
349         }
350     } else {
351         // regular atom
352         switch (type) {
353           case AP4_ATOM_TYPE_MOOV:
354             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
355             atom = AP4_MoovAtom::Create(size_32, stream, *this);
356             break;
357 
358           case AP4_ATOM_TYPE_MVHD:
359             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
360             atom = AP4_MvhdAtom::Create(size_32, stream);
361             break;
362 
363           case AP4_ATOM_TYPE_MEHD:
364             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
365             atom = AP4_MehdAtom::Create(size_32, stream);
366             break;
367 
368           case AP4_ATOM_TYPE_MFHD:
369             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
370             atom = AP4_MfhdAtom::Create(size_32, stream);
371             break;
372 
373           case AP4_ATOM_TYPE_TRAK:
374             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
375             atom = AP4_TrakAtom::Create(size_32, stream, *this);
376             break;
377 
378           case AP4_ATOM_TYPE_TREX:
379             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
380             atom = AP4_TrexAtom::Create(size_32, stream);
381             break;
382 
383           case AP4_ATOM_TYPE_HDLR:
384             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
385             atom = AP4_HdlrAtom::Create(size_32, stream);
386             break;
387 
388           case AP4_ATOM_TYPE_TKHD:
389             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
390             atom = AP4_TkhdAtom::Create(size_32, stream);
391             break;
392 
393           case AP4_ATOM_TYPE_TFHD:
394             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
395             atom = AP4_TfhdAtom::Create(size_32, stream);
396             break;
397 
398           case AP4_ATOM_TYPE_TRUN:
399             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
400             atom = AP4_TrunAtom::Create(size_32, stream);
401             break;
402 
403           case AP4_ATOM_TYPE_TFRA:
404             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
405             atom = AP4_TfraAtom::Create(size_32, stream);
406             break;
407 
408           case AP4_ATOM_TYPE_MFRO:
409             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
410             atom = AP4_MfroAtom::Create(size_32, stream);
411             break;
412 
413           case AP4_ATOM_TYPE_MDHD:
414             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
415             atom = AP4_MdhdAtom::Create(size_32, stream);
416             break;
417 
418           case AP4_ATOM_TYPE_STSD:
419             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
420             atom = AP4_StsdAtom::Create(size_32, stream, *this);
421             break;
422 
423           case AP4_ATOM_TYPE_STSC:
424             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
425             atom = AP4_StscAtom::Create(size_32, stream);
426             break;
427 
428           case AP4_ATOM_TYPE_STCO:
429             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
430             atom = AP4_StcoAtom::Create(size_32, stream);
431             break;
432 
433           case AP4_ATOM_TYPE_CO64:
434             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
435             atom = AP4_Co64Atom::Create(size_32, stream);
436             break;
437 
438           case AP4_ATOM_TYPE_STSZ:
439             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
440             atom = AP4_StszAtom::Create(size_32, stream);
441             break;
442 
443           case AP4_ATOM_TYPE_STZ2:
444             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
445             atom = AP4_Stz2Atom::Create(size_32, stream);
446             break;
447 
448           case AP4_ATOM_TYPE_STTS:
449             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
450             atom = AP4_SttsAtom::Create(size_32, stream);
451             break;
452 
453           case AP4_ATOM_TYPE_CTTS:
454             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
455             atom = AP4_CttsAtom::Create(size_32, stream);
456             break;
457 
458           case AP4_ATOM_TYPE_STSS:
459             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
460             atom = AP4_StssAtom::Create(size_32, stream);
461             break;
462 
463           case AP4_ATOM_TYPE_IODS:
464             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
465             atom = AP4_IodsAtom::Create(size_32, stream);
466             break;
467 
468           case AP4_ATOM_TYPE_ESDS:
469             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
470             atom = AP4_EsdsAtom::Create(size_32, stream);
471             break;
472 
473           case AP4_ATOM_TYPE_AVCC:
474             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
475             atom = AP4_AvccAtom::Create(size_32, stream);
476             break;
477 
478           case AP4_ATOM_TYPE_HVCC:
479             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
480             atom = AP4_HvccAtom::Create(size_32, stream);
481             break;
482 
483     #if !defined(AP4_CONFIG_MINI_BUILD)
484           case AP4_ATOM_TYPE_UUID: {
485               AP4_UI08 uuid[16];
486               AP4_Result result = stream.Read(uuid, 16);
487               if (AP4_FAILED(result)) return result;
488 
489               if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_TRACK_ENCRYPTION_ATOM, 16) == 0) {
490                   atom = AP4_PiffTrackEncryptionAtom::Create((AP4_UI32)size_64, stream);
491               } else if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_SAMPLE_ENCRYPTION_ATOM, 16) == 0) {
492                   atom = AP4_PiffSampleEncryptionAtom::Create((AP4_UI32)size_64, stream);
493               } else {
494                   atom = new AP4_UnknownUuidAtom(size_64, uuid, stream);
495               }
496               break;
497           }
498 
499           case AP4_ATOM_TYPE_8ID_:
500             atom = new AP4_NullTerminatedStringAtom(type, size_64, stream);
501             break;
502 
503           case AP4_ATOM_TYPE_8BDL:
504             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
505             atom = AP4_8bdlAtom::Create(size_32, stream);
506             break;
507 
508           case AP4_ATOM_TYPE_DREF:
509             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
510             atom = AP4_DrefAtom::Create(size_32, stream, *this);
511             break;
512 
513           case AP4_ATOM_TYPE_URL:
514             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
515             atom = AP4_UrlAtom::Create(size_32, stream);
516             break;
517 
518           case AP4_ATOM_TYPE_ELST:
519             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
520             atom = AP4_ElstAtom::Create(size_32, stream);
521             break;
522 
523           case AP4_ATOM_TYPE_VMHD:
524             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
525             atom = AP4_VmhdAtom::Create(size_32, stream);
526             break;
527 
528           case AP4_ATOM_TYPE_SMHD:
529             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
530             atom = AP4_SmhdAtom::Create(size_32, stream);
531             break;
532 
533           case AP4_ATOM_TYPE_NMHD:
534             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
535             atom = AP4_NmhdAtom::Create(size_32, stream);
536             break;
537 
538           case AP4_ATOM_TYPE_STHD:
539             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
540             atom = AP4_SthdAtom::Create(size_32, stream);
541             break;
542 
543           case AP4_ATOM_TYPE_HMHD:
544             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
545             atom = AP4_HmhdAtom::Create(size_32, stream);
546             break;
547 
548           case AP4_ATOM_TYPE_FRMA:
549             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
550             atom = AP4_FrmaAtom::Create(size_32, stream);
551             break;
552 
553           case AP4_ATOM_TYPE_SCHM:
554             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
555             atom = AP4_SchmAtom::Create(size_32, &m_ContextStack, stream);
556             break;
557 
558           case AP4_ATOM_TYPE_FTYP:
559             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
560             atom = AP4_FtypAtom::Create(size_32, stream);
561             break;
562 
563           case AP4_ATOM_TYPE_TIMS:
564             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
565             atom = AP4_TimsAtom::Create(size_32, stream);
566             break;
567 
568           case AP4_ATOM_TYPE_SDP_:
569             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
570             atom = AP4_SdpAtom::Create(size_32, stream);
571             break;
572 
573           case AP4_ATOM_TYPE_IKMS:
574             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
575             atom = AP4_IkmsAtom::Create(size_32, stream);
576             break;
577 
578           case AP4_ATOM_TYPE_ISFM:
579             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
580             atom = AP4_IsfmAtom::Create(size_32, stream);
581             break;
582 
583           case AP4_ATOM_TYPE_ISLT:
584             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
585             atom = AP4_IsltAtom::Create(size_32, stream);
586             break;
587 
588           case AP4_ATOM_TYPE_ODHE:
589             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
590             atom = AP4_OdheAtom::Create(size_32, stream, *this);
591             break;
592 
593           case AP4_ATOM_TYPE_OHDR:
594             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
595             atom = AP4_OhdrAtom::Create(size_32, stream, *this);
596             break;
597 
598           case AP4_ATOM_TYPE_ODDA:
599             atom = AP4_OddaAtom::Create(size_64, stream);
600             break;
601 
602           case AP4_ATOM_TYPE_ODAF:
603             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
604             atom = AP4_OdafAtom::Create(size_32, stream);
605             break;
606 
607           case AP4_ATOM_TYPE_GRPI:
608             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
609             atom = AP4_GrpiAtom::Create(size_32, stream);
610             break;
611 
612           case AP4_ATOM_TYPE_IPRO:
613             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
614             atom = AP4_IproAtom::Create(size_32, stream, *this);
615             break;
616 
617           case AP4_ATOM_TYPE_RTP_:
618             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
619             atom = AP4_RtpAtom::Create(size_32, stream);
620             break;
621 
622           case AP4_ATOM_TYPE_TFDT:
623             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
624             atom = AP4_TfdtAtom::Create(size_32, stream);
625             break;
626 
627           case AP4_ATOM_TYPE_TENC:
628             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
629             atom = AP4_TencAtom::Create(size_32, stream);
630             break;
631 
632           case AP4_ATOM_TYPE_SENC:
633             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
634             atom = AP4_SencAtom::Create(size_32, stream);
635             break;
636 
637           case AP4_ATOM_TYPE_SAIZ:
638             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
639             atom = AP4_SaizAtom::Create(size_32, stream);
640             break;
641 
642           case AP4_ATOM_TYPE_SAIO:
643             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
644             atom = AP4_SaioAtom::Create(size_32, stream);
645             break;
646 
647           case AP4_ATOM_TYPE_PDIN:
648             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
649             atom = AP4_PdinAtom::Create(size_32, stream);
650             break;
651 
652           case AP4_ATOM_TYPE_BLOC:
653             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
654             atom = AP4_BlocAtom::Create(size_32, stream);
655             break;
656 
657           case AP4_ATOM_TYPE_AINF:
658             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
659             atom = AP4_AinfAtom::Create(size_32, stream);
660             break;
661 
662           case AP4_ATOM_TYPE_PSSH:
663             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
664             atom = AP4_PsshAtom::Create(size_32, stream);
665             break;
666 
667           case AP4_ATOM_TYPE_SIDX:
668             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
669             atom = AP4_SidxAtom::Create(size_32, stream);
670             break;
671 
672           case AP4_ATOM_TYPE_SBGP:
673             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
674             atom = AP4_SbgpAtom::Create(size_32, stream);
675             break;
676 
677           case AP4_ATOM_TYPE_SGPD:
678             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
679             atom = AP4_SgpdAtom::Create(size_32, stream);
680             break;
681 
682           case AP4_ATOM_TYPE_VPCC:
683             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
684             atom = AP4_VpcCAtom::Create(size_32, stream);
685             break;
686 
687           case AP4_ATOM_TYPE_MKID:
688             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
689             if (GetContext() == AP4_ATOM_TYPE_MARL) {
690                 atom = AP4_MkidAtom::Create(size_32, stream);
691             }
692             break;
693 
694           case AP4_ATOM_TYPE_DAC3:
695             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
696             if (GetContext() == AP4_ATOM_TYPE_AC_3) {
697               atom = AP4_Dac3Atom::Create(size_32, stream);
698             }
699             break;
700 
701           case AP4_ATOM_TYPE_DEC3:
702             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
703             if (GetContext() == AP4_ATOM_TYPE_EC_3) {
704                 atom = AP4_Dec3Atom::Create(size_32, stream);
705             }
706             break;
707 
708 		  case AP4_ATOM_TYPE_TRAF:
709 			  if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
710 			  atom = AP4_TrafAtom::Create(type, size_64, force_64, stream, *this);
711 			  break;
712 
713           // track ref types
714           case AP4_ATOM_TYPE_HINT:
715           case AP4_ATOM_TYPE_CDSC:
716           case AP4_ATOM_TYPE_SYNC:
717           case AP4_ATOM_TYPE_MPOD:
718           case AP4_ATOM_TYPE_DPND:
719           case AP4_ATOM_TYPE_IPIR:
720           case AP4_ATOM_TYPE_ALIS:
721           case AP4_ATOM_TYPE_CHAP:
722             if (GetContext() == AP4_ATOM_TYPE_TREF) {
723                 if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
724                 atom = AP4_TrefTypeAtom::Create(type, size_32, stream);
725             }
726             break;
727 
728     #endif // AP4_CONFIG_MINI_BUILD
729 
730           // container atoms
731           case AP4_ATOM_TYPE_MOOF:
732           case AP4_ATOM_TYPE_MVEX:
733           case AP4_ATOM_TYPE_TREF:
734           case AP4_ATOM_TYPE_MFRA:
735           case AP4_ATOM_TYPE_HNTI:
736           case AP4_ATOM_TYPE_STBL:
737           case AP4_ATOM_TYPE_MDIA:
738           case AP4_ATOM_TYPE_DINF:
739           case AP4_ATOM_TYPE_MINF:
740           case AP4_ATOM_TYPE_SCHI:
741           case AP4_ATOM_TYPE_SINF:
742           case AP4_ATOM_TYPE_UDTA:
743           case AP4_ATOM_TYPE_ILST:
744           case AP4_ATOM_TYPE_EDTS:
745           case AP4_ATOM_TYPE_MDRI:
746           case AP4_ATOM_TYPE_WAVE:
747             if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
748             atom = AP4_ContainerAtom::Create(type, size_64, false, force_64, stream, *this);
749             break;
750 
751           // containers, only at the top
752           case AP4_ATOM_TYPE_MARL:
753             if (GetContext() == 0) {
754                 atom = AP4_ContainerAtom::Create(type, size_64, false, force_64, stream, *this);
755             }
756             break;
757 
758           // full container atoms
759           case AP4_ATOM_TYPE_META:
760           case AP4_ATOM_TYPE_ODRM:
761           case AP4_ATOM_TYPE_ODKM:
762             atom = AP4_ContainerAtom::Create(type, size_64, true, force_64, stream, *this);
763             break;
764 
765           case AP4_ATOM_TYPE_FREE:
766           case AP4_ATOM_TYPE_WIDE:
767           case AP4_ATOM_TYPE_MDAT:
768             // generic atoms
769             break;
770 
771           default: {
772             // try all the external type handlers
773             AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
774             while (handler_item) {
775                 TypeHandler* handler = handler_item->GetData();
776                 if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
777                     break;
778                 }
779                 handler_item = handler_item->GetNext();
780             }
781 
782             break;
783           }
784         }
785     }
786 
787     return AP4_SUCCESS;
788 }
789 
790 /*----------------------------------------------------------------------
791 |   AP4_AtomFactory::CreateAtomsFromStream
792 +---------------------------------------------------------------------*/
793 AP4_Result
CreateAtomsFromStream(AP4_ByteStream & stream,AP4_AtomParent & atoms)794 AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
795                                        AP4_AtomParent& atoms)
796 {
797     AP4_LargeSize stream_size     = 0;
798     AP4_Position  stream_position = 0;
799     AP4_LargeSize bytes_available = (AP4_LargeSize)(-1);
800     if (AP4_SUCCEEDED(stream.GetSize(stream_size)) &&
801         stream_size != 0 &&
802         AP4_SUCCEEDED(stream.Tell(stream_position)) &&
803         stream_position <= stream_size) {
804         bytes_available = stream_size-stream_position;
805     }
806     return CreateAtomsFromStream(stream, bytes_available, atoms);
807 }
808 
809 /*----------------------------------------------------------------------
810 |   AP4_AtomFactory::CreateAtomsFromStream
811 +---------------------------------------------------------------------*/
812 AP4_Result
CreateAtomsFromStream(AP4_ByteStream & stream,AP4_LargeSize bytes_available,AP4_AtomParent & atoms)813 AP4_AtomFactory::CreateAtomsFromStream(AP4_ByteStream& stream,
814                                        AP4_LargeSize   bytes_available,
815                                        AP4_AtomParent& atoms)
816 {
817     AP4_Result result;
818     do {
819         AP4_Atom* atom = NULL;
820         result = CreateAtomFromStream(stream, bytes_available, atom);
821         if (AP4_SUCCEEDED(result) && atom != NULL) {
822             atoms.AddChild(atom);
823         }
824     } while (AP4_SUCCEEDED(result));
825 
826     return AP4_SUCCESS;
827 }
828 
829 /*----------------------------------------------------------------------
830 |   AP4_AtomFactory::PushContext
831 +---------------------------------------------------------------------*/
832 void
PushContext(AP4_Atom::Type context)833 AP4_AtomFactory::PushContext(AP4_Atom::Type context)
834 {
835     m_ContextStack.Append(context);
836 }
837 
838 /*----------------------------------------------------------------------
839 |   AP4_AtomFactory::PopContext
840 +---------------------------------------------------------------------*/
841 void
PopContext()842 AP4_AtomFactory::PopContext()
843 {
844     m_ContextStack.RemoveLast();
845 }
846 
847 /*----------------------------------------------------------------------
848 |   AP4_AtomFactory::GetContext
849 +---------------------------------------------------------------------*/
850 AP4_Atom::Type
GetContext(AP4_Ordinal depth)851 AP4_AtomFactory::GetContext(AP4_Ordinal depth)
852 {
853     AP4_Ordinal available = m_ContextStack.ItemCount();
854     if (depth >= available) return 0;
855     return m_ContextStack[available-depth-1];
856 }
857 
858 /*----------------------------------------------------------------------
859 |   AP4_DefaultAtomFactory::Instance
860 +---------------------------------------------------------------------*/
861 AP4_DefaultAtomFactory AP4_DefaultAtomFactory::Instance;
862 
863 /*----------------------------------------------------------------------
864 |   AP4_DefaultAtomFactory::Instance
865 +---------------------------------------------------------------------*/
AP4_DefaultAtomFactory()866 AP4_DefaultAtomFactory::AP4_DefaultAtomFactory()
867 {
868     Initialize();
869 }
870 
871 /*----------------------------------------------------------------------
872 |   AP4_DefaultAtomFactory::Initialize
873 +---------------------------------------------------------------------*/
874 AP4_Result
Initialize()875 AP4_DefaultAtomFactory::Initialize()
876 {
877     // register built-in type handlers
878     AP4_Result result = AddTypeHandler(new AP4_MetaDataAtomTypeHandler(this));
879     if (AP4_SUCCEEDED(result)) m_Initialized = true;
880     return result;
881 }
882