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 

Generated on Tue Dec 13 14:47:19 2005 for guliverkli by  doxygen 1.4.5