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