- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# Ap4AtomFactory.cpp

    00001 /*****************************************************************
    00002 |
    00003 |    AP4 - Atom Factory
    00004 |
    00005 |    Copyright 2002 Gilles Boccon-Gibod
    00006 |
    00007 |
    00008 |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
    00009 |
    00010 |    Unless you have obtained Bento4 under a difference license,
    00011 |    this version of Bento4 is Bento4|GPL.
    00012 |    Bento4|GPL is free software; you can redistribute it and/or modify
    00013 |    it under the terms of the GNU General Public License as published by
    00014 |    the Free Software Foundation; either version 2, or (at your option)
    00015 |    any later version.
    00016 |
    00017 |    Bento4|GPL is distributed in the hope that it will be useful,
    00018 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
    00019 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00020 |    GNU General Public License for more details.
    00021 |
    00022 |    You should have received a copy of the GNU General Public License
    00023 |    along with Bento4|GPL; see the file COPYING.  If not, write to the
    00024 |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    00025 |    02111-1307, USA.
    00026 |
    00027  ****************************************************************/
    00028
    00029 /*----------------------------------------------------------------------
    00030 |       includes
    00031 +---------------------------------------------------------------------*/
    00032 #include "Ap4.h"
    00033 #include "Ap4AtomFactory.h"
    00034 #include "Ap4SampleEntry.h"
    00035 #include "Ap4IsmaCryp.h"
    00036 #include "Ap4UrlAtom.h"
    00037 #include "Ap4MoovAtom.h"
    00038 #include "Ap4MvhdAtom.h"
    00039 #include "Ap4TrakAtom.h"
    00040 #include "Ap4HdlrAtom.h"
    00041 #include "Ap4DrefAtom.h"
    00042 #include "Ap4TkhdAtom.h"
    00043 #include "Ap4MdhdAtom.h"
    00044 #include "Ap4StsdAtom.h"
    00045 #include "Ap4StscAtom.h"
    00046 #include "Ap4StcoAtom.h"
    00047 #include "Ap4Co64Atom.h"
    00048 #include "Ap4StszAtom.h"
    00049 #include "Ap4EsdsAtom.h"
    00050 #include "Ap4SttsAtom.h"
    00051 #include "Ap4CttsAtom.h"
    00052 #include "Ap4StssAtom.h"
    00053 #include "Ap4FtypAtom.h"
    00054 #include "Ap4VmhdAtom.h"
    00055 #include "Ap4SmhdAtom.h"
    00056 #include "Ap4NmhdAtom.h"
    00057 #include "Ap4HmhdAtom.h"
    00058 #include "Ap4SchmAtom.h"
    00059 #include "Ap4FrmaAtom.h"
    00060 #include "Ap4TimsAtom.h"
    00061 #include "Ap4RtpAtom.h"
    00062 #include "Ap4SdpAtom.h"
    00063 #include "Ap4IkmsAtom.h"
    00064 #include "Ap4IsfmAtom.h"
    00065 #include "Ap4TrefTypeAtom.h"
    00066 #include "Ap4AvcCAtom.h"
    00067 #include "Ap4FtabAtom.h"
    00068 #include "Ap4ChplAtom.h"
    00069 #include "Ap4DataAtom.h"
    00070
    00071 /*----------------------------------------------------------------------
    00072 |       class variables
    00073 +---------------------------------------------------------------------*/
    00074 AP4_AtomFactory AP4_AtomFactory::DefaultFactory;
    00075
    00076 /*----------------------------------------------------------------------
    00077 |       AP4_AtomFactory::AddTypeHandler
    00078 +---------------------------------------------------------------------*/
    00079 AP4_Result
    00080 AP4_AtomFactory::AddTypeHandler(TypeHandler* handler)
    00081 {
    00082     return m_TypeHandlers.Add(handler);
    00083 }
    00084
    00085 /*----------------------------------------------------------------------
    00086 |       AP4_AtomFactory::RemoveTypeHandler
    00087 +---------------------------------------------------------------------*/
    00088 AP4_Result
    00089 AP4_AtomFactory::RemoveTypeHandler(TypeHandler* handler)
    00090 {
    00091     return m_TypeHandlers.Remove(handler);
    00092 }
    00093
    00094 /*----------------------------------------------------------------------
    00095 |       AP4_AtomFactory::CreateAtomFromStream
    00096 +---------------------------------------------------------------------*/
    00097 AP4_Result
    00098 AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
    00099                                       AP4_Atom*&      atom)
    00100 {
    00101     AP4_Size bytes_available = 0;
    00102     if (AP4_FAILED(stream.GetSize(bytes_available)) ||
    00103         bytes_available == 0) {
    00104         bytes_available = (AP4_Size)((unsigned long)(-1));
    00105     }
    00106     return CreateAtomFromStream(stream, bytes_available, atom);
    00107 }
    00108
    00109 /*----------------------------------------------------------------------
    00110 |       AP4_AtomFactory::CreateAtomFromStream
    00111 +---------------------------------------------------------------------*/
    00112 AP4_Result
    00113 AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream,
    00114                                       AP4_Size&       bytes_available,
    00115                                       AP4_Atom*&      atom)
    00116 {
    00117     AP4_Result result;
    00118
    00119     // NULL by default
    00120     atom = NULL;
    00121
    00122     // check that there are enough bytes for at least a header
    00123     if (bytes_available < 8) return AP4_ERROR_EOS;
    00124
    00125     // remember current stream offset
    00126     AP4_Offset start;
    00127     stream.Tell(start);
    00128
    00129     // read atom size
    00130     AP4_UI32 size;
    00131     result = stream.ReadUI32(size);
    00132     if (AP4_FAILED(result)) {
    00133         stream.Seek(start);
    00134         return result;
    00135     }
    00136
    00137     if (size == 0) {
    00138         // atom extends to end of file
    00139         AP4_Size streamSize = 0;
    00140         stream.GetSize(streamSize);
    00141         if (streamSize >= start) {
    00142             size = streamSize - start;
    00143         }
    00144     }
    00145
    00146     // check the size (we don't handle extended size yet)
    00147     if (size != 1 && size < 8 || size > bytes_available) {
    00148         stream.Seek(start);
    00149         return AP4_ERROR_INVALID_FORMAT;
    00150     }
    00151
    00152     // read atom type
    00153     AP4_Atom::Type type;
    00154     result = stream.ReadUI32(type);
    00155     if (AP4_FAILED(result)) {
    00156         stream.Seek(start);
    00157         return result;
    00158     }
    00159
    00160         if (size == 1)
    00161         {
    00162                 AP4_UI32 size_high;
    00163
    00164                 result = stream.ReadUI32(size_high);
    00165                 if (AP4_FAILED(result) || size_high) {
    00166                         stream.Seek(start);
    00167                         return AP4_ERROR_INVALID_FORMAT;
    00168                 }
    00169
    00170                 result = stream.ReadUI32(size);
    00171                 if (AP4_FAILED(result)) {
    00172                         stream.Seek(start);
    00173                         return result;
    00174                 }
    00175         }
    00176
    00177     // create the atom
    00178     switch (type) {
    00179       case AP4_ATOM_TYPE_MOOV:
    00180         atom = new AP4_MoovAtom(size, stream, *this);
    00181         break;
    00182
    00183       case AP4_ATOM_TYPE_MVHD:
    00184         atom = new AP4_MvhdAtom(size, stream);
    00185         break;
    00186
    00187       case AP4_ATOM_TYPE_TRAK:
    00188         atom = new AP4_TrakAtom(size, stream, *this);
    00189         break;
    00190
    00191       case AP4_ATOM_TYPE_HDLR:
    00192         atom = new AP4_HdlrAtom(size, stream);
    00193         break;
    00194
    00195       case AP4_ATOM_TYPE_DREF:
    00196         atom = new AP4_DrefAtom(size, stream, *this);
    00197         break;
    00198
    00199       case AP4_ATOM_TYPE_URL:
    00200         atom = new AP4_UrlAtom(size, stream);
    00201         break;
    00202
    00203       case AP4_ATOM_TYPE_TKHD:
    00204         atom = new AP4_TkhdAtom(size, stream);
    00205         break;
    00206
    00207       case AP4_ATOM_TYPE_MDHD:
    00208         atom = new AP4_MdhdAtom(size, stream);
    00209         break;
    00210
    00211       case AP4_ATOM_TYPE_STSD:
    00212         atom = new AP4_StsdAtom(size, stream, *this);
    00213         break;
    00214
    00215       case AP4_ATOM_TYPE_STSC:
    00216         atom = new AP4_StscAtom(size, stream);
    00217         break;
    00218
    00219       case AP4_ATOM_TYPE_STCO:
    00220         atom = new AP4_StcoAtom(size, stream);
    00221         break;
    00222
    00223       case AP4_ATOM_TYPE_CO64:
    00224         atom = new AP4_Co64Atom(size, stream);
    00225         break;
    00226
    00227       case AP4_ATOM_TYPE_STSZ:
    00228         atom = new AP4_StszAtom(size, stream);
    00229         break;
    00230
    00231       case AP4_ATOM_TYPE_STTS:
    00232         atom = new AP4_SttsAtom(size, stream);
    00233         break;
    00234
    00235       case AP4_ATOM_TYPE_CTTS:
    00236         atom = new AP4_CttsAtom(size, stream);
    00237         break;
    00238
    00239       case AP4_ATOM_TYPE_STSS:
    00240         atom = new AP4_StssAtom(size, stream);
    00241         break;
    00242
    00243       case AP4_ATOM_TYPE_MP4S:
    00244         atom = new AP4_Mp4sSampleEntry(size, stream, *this);
    00245         break;
    00246
    00247       case AP4_ATOM_TYPE_MP4A:
    00248         atom = new AP4_Mp4aSampleEntry(size, stream, *this);
    00249         break;
    00250
    00251       case AP4_ATOM_TYPE_MP4V:
    00252         atom = new AP4_Mp4vSampleEntry(size, stream, *this);
    00253         break;
    00254
    00255       case AP4_ATOM_TYPE_AVC1:
    00256         atom = new AP4_Avc1SampleEntry(size, stream, *this);
    00257         break;
    00258
    00259       case AP4_ATOM_TYPE_ENCA:
    00260         atom = new AP4_EncaSampleEntry(size, stream, *this);
    00261         break;
    00262
    00263       case AP4_ATOM_TYPE_ENCV:
    00264         atom = new AP4_EncvSampleEntry(size, stream, *this);
    00265         break;
    00266
    00267       case AP4_ATOM_TYPE_ESDS:
    00268         atom = new AP4_EsdsAtom(size, stream);
    00269         break;
    00270
    00271       case AP4_ATOM_TYPE_VMHD:
    00272         atom = new AP4_VmhdAtom(size, stream);
    00273         break;
    00274
    00275       case AP4_ATOM_TYPE_SMHD:
    00276         atom = new AP4_SmhdAtom(size, stream);
    00277         break;
    00278
    00279       case AP4_ATOM_TYPE_NMHD:
    00280         atom = new AP4_NmhdAtom(size, stream);
    00281         break;
    00282
    00283       case AP4_ATOM_TYPE_HMHD:
    00284         atom = new AP4_HmhdAtom(size, stream);
    00285         break;
    00286
    00287       case AP4_ATOM_TYPE_FRMA:
    00288         atom = new AP4_FrmaAtom(size, stream);
    00289         break;
    00290
    00291       case AP4_ATOM_TYPE_SCHM:
    00292           atom = new AP4_SchmAtom(size, stream);
    00293           break;
    00294
    00295       case AP4_ATOM_TYPE_FTYP:
    00296         atom = new AP4_FtypAtom(size, stream);
    00297         break;
    00298
    00299       case AP4_ATOM_TYPE_RTP:
    00300         if (m_Context == AP4_ATOM_TYPE_HNTI) {
    00301             atom = new AP4_RtpAtom(size, stream);
    00302         } else {
    00303             atom = new AP4_RtpHintSampleEntry(size, stream, *this);
    00304         }
    00305         break;
    00306
    00307       case AP4_ATOM_TYPE_TIMS:
    00308         atom = new AP4_TimsAtom(size, stream);
    00309         break;
    00310
    00311       case AP4_ATOM_TYPE_SDP:
    00312         atom = new AP4_SdpAtom(size, stream);
    00313         break;
    00314
    00315       case AP4_ATOM_TYPE_IKMS:
    00316         atom = new AP4_IkmsAtom(size, stream);
    00317         break;
    00318
    00319       case AP4_ATOM_TYPE_ISFM:
    00320         atom = new AP4_IsfmAtom(size, stream);
    00321         break;
    00322
    00323       case AP4_ATOM_TYPE_HINT:
    00324         atom = new AP4_TrefTypeAtom(type, size, stream);
    00325         break;
    00326
    00327       // container atoms
    00328       case AP4_ATOM_TYPE_TREF:
    00329       case AP4_ATOM_TYPE_HNTI:
    00330       case AP4_ATOM_TYPE_STBL:
    00331       case AP4_ATOM_TYPE_MDIA:
    00332       case AP4_ATOM_TYPE_DINF:
    00333       case AP4_ATOM_TYPE_MINF:
    00334       case AP4_ATOM_TYPE_SCHI:
    00335       case AP4_ATOM_TYPE_SINF:
    00336       case AP4_ATOM_TYPE_UDTA:
    00337       case AP4_ATOM_TYPE_ILST:
    00338           case AP4_ATOM_TYPE_NAM:
    00339           case AP4_ATOM_TYPE_ART:
    00340       case AP4_ATOM_TYPE_WRT:
    00341       case AP4_ATOM_TYPE_ALB:
    00342       case AP4_ATOM_TYPE_DAY:
    00343       case AP4_ATOM_TYPE_TOO:
    00344       case AP4_ATOM_TYPE_CMT:
    00345       case AP4_ATOM_TYPE_GEN:
    00346           case AP4_ATOM_TYPE_TRKN:
    00347           case AP4_ATOM_TYPE_EDTS: {
    00348           AP4_UI32 context = m_Context;
    00349           m_Context = type; // set the context for the children
    00350           atom = new AP4_ContainerAtom(type, size, false, stream, *this);
    00351           m_Context = context; // restore the previous context
    00352           break;
    00353       }
    00354
    00355       // full container atoms
    00356       case AP4_ATOM_TYPE_META:
    00357         atom = new AP4_ContainerAtom(type, size, true, stream, *this);
    00358         break;
    00359
    00360       // other
    00361
    00362       case AP4_ATOM_TYPE_AVCC:
    00363         atom = new AP4_AvcCAtom(size, stream);
    00364         break;
    00365
    00366       case AP4_ATOM_TYPE_TEXT:
    00367         atom = new AP4_TextSampleEntry(size, stream, *this);
    00368         break;
    00369
    00370       case AP4_ATOM_TYPE_TX3G:
    00371         atom = new AP4_Tx3gSampleEntry(size, stream, *this);
    00372         break;
    00373
    00374       case AP4_ATOM_TYPE_FTAB:
    00375         atom = new AP4_FtabAtom(size, stream);
    00376         break;
    00377
    00378       case AP4_ATOM_TYPE_S263:
    00379         atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE_S263, size, stream, *this); // TODO
    00380         break;
    00381
    00382           case AP4_ATOM_TYPE_SAMR:
    00383         atom = new AP4_AudioSampleEntry(AP4_ATOM_TYPE_SAMR, size, stream, *this); // TODO
    00384         break;
    00385
    00386       case AP4_ATOM_TYPE_CHPL:
    00387         atom = new AP4_ChplAtom(size, stream);
    00388         break;
    00389
    00390           case AP4_ATOM_TYPE_DATA:
    00391         atom = new AP4_DataAtom(size, stream);
    00392         break;
    00393
    00394       default:
    00395         // try all the external type handlers
    00396         {
    00397             atom = NULL;
    00398             AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
    00399             while (handler_item) {
    00400                 TypeHandler* handler = handler_item->GetData();
    00401                 if (AP4_SUCCEEDED(handler->CreateAtom(type, size, stream, atom))) {
    00402                     break;
    00403                 }
    00404                 handler_item = handler_item->GetNext();
    00405             }
    00406             if (atom == NULL) {
    00407                 // no custom handlers, create a generic atom
    00408                 atom = new AP4_UnknownAtom(type, size, false, stream);
    00409             }
    00410             break;
    00411         }
    00412     }
    00413
    00414     // skip to the end of the atom
    00415     bytes_available -= size;
    00416     result = stream.Seek(start+size);
    00417     if (AP4_FAILED(result)) {
    00418         delete atom;
    00419         atom = NULL;
    00420     }
    00421
    00422     return result;
    00423 }
    00424