Пример #1
0
string
TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param,
				       const void *address)
{
	TypeHandler *target = fDefault;

	int index = get_value<int>(context.GetValue(context.GetSibling(fSibling)));

	SelectMap::const_iterator i = fMap.find(index);
	if (i != fMap.end())
		target = i->second;

	return target->GetParameterValue(context, param, address);
}
Пример #2
0
/*----------------------------------------------------------------------
|       AP4_AtomFactory::CreateAtomFromStream
+---------------------------------------------------------------------*/
AP4_Result
AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, 
                                      AP4_Size&       bytes_available,
                                      AP4_Atom*&      atom,
									  AP4_Atom*	      parent)
{
    AP4_Result result;


    // NULL by default
    atom = NULL;

    // check that there are enough bytes for at least a header
    if (bytes_available < 8) return AP4_ERROR_EOS;

    // remember current stream offset
    AP4_Offset start;
    stream.Tell(start);

    // read atom size

    AP4_UI64 size = 0;
    result = stream.ReadUI32((AP4_UI32&)size);
    if (AP4_FAILED(result)) {
        stream.Seek(start);
        return result;
    }

    if (size == 0) {
        // atom extends to end of file
        AP4_Size streamSize = 0;
        stream.GetSize(streamSize);
        if (streamSize >= start) {
            size = streamSize - start;
        }
    }

    // check the size (we don't handle extended size yet)
    if (size != 1 && size < 8 || size > bytes_available) {
        stream.Seek(start);
        return AP4_ERROR_INVALID_FORMAT;
    }

    // read atom type
    AP4_Atom::Type type;
    result = stream.ReadUI32(type);
    if (AP4_FAILED(result)) {
        stream.Seek(start);
        return result;
    }

	if (size == 1)
	{
		AP4_UI64 size_high;

		result = stream.ReadUI64(size_high);
		if (AP4_FAILED(result) ) {
			stream.Seek(start);
			return AP4_ERROR_INVALID_FORMAT;
		}
		size = size_high;
	}
    
    // create the atom
    switch (type) {
		case AP4_ATOM_TYPE_MOOV:
			atom = new AP4_MoovAtom(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_MVHD:
			atom = new AP4_MvhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_TRAK:
			atom = new AP4_TrakAtom(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_HDLR:
			atom = new AP4_HdlrAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_DREF:
			atom = new AP4_DrefAtom(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_URL:
			atom = new AP4_UrlAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_TKHD:
			atom = new AP4_TkhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_MDHD:
			atom = new AP4_MdhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_STSD:
			atom = new AP4_StsdAtom(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_STSC:
			atom = new AP4_StscAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_STCO:
			atom = new AP4_StcoAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_CO64:
			atom = new AP4_Co64Atom(size, stream);
			break;

		case AP4_ATOM_TYPE_STSZ:
			atom = new AP4_StszAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_STTS:
			atom = new AP4_SttsAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_CTTS:
			atom = new AP4_CttsAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_STSS:
			atom = new AP4_StssAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_MP4S:
			atom = new AP4_Mp4sSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_MP4A:
			atom = parent && parent->GetType() == AP4_ATOM_TYPE_STSD 
				? (AP4_Atom*)new AP4_Mp4aSampleEntry(size, stream, *this)
				: (AP4_Atom*)new AP4_UnknownAtom(type, size, false, stream);
			break;

		case AP4_ATOM_TYPE_MP4V:
			atom = new AP4_Mp4vSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_AVC1:
			atom = new AP4_Avc1SampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_ENCA:
			atom = new AP4_EncaSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_ENCV:
			atom = new AP4_EncvSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_ESDS:
			atom = new AP4_EsdsAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_VMHD:
			atom = new AP4_VmhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_SMHD:
			atom = new AP4_SmhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_NMHD:
			atom = new AP4_NmhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_HMHD:
			atom = new AP4_HmhdAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_FRMA:
			atom = new AP4_FrmaAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_SCHM:
			atom = new AP4_SchmAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_FTYP:
			atom = new AP4_FtypAtom(size, stream);
			break;
		  
		case AP4_ATOM_TYPE_RTP:
			if (m_Context == AP4_ATOM_TYPE_HNTI) {
				atom = new AP4_RtpAtom(size, stream);
			} else {
				atom = new AP4_RtpHintSampleEntry(size, stream, *this);
			}
			break;

		case AP4_ATOM_TYPE_TIMS:
			atom = new AP4_TimsAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_SDP:
			atom = new AP4_SdpAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_IKMS:
			atom = new AP4_IkmsAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_ISFM:
			atom = new AP4_IsfmAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_HINT:
			atom = new AP4_TrefTypeAtom(type, size, stream);
			break;

		// container atoms
		case AP4_ATOM_TYPE_TREF:
		case AP4_ATOM_TYPE_HNTI:
		case AP4_ATOM_TYPE_STBL:
		case AP4_ATOM_TYPE_MDIA:
		case AP4_ATOM_TYPE_DINF:
		case AP4_ATOM_TYPE_MINF:
		case AP4_ATOM_TYPE_SCHI:
		case AP4_ATOM_TYPE_SINF:
		case AP4_ATOM_TYPE_UDTA:
		case AP4_ATOM_TYPE_ILST:
		case AP4_ATOM_TYPE_NAM:
		case AP4_ATOM_TYPE_ART:
		case AP4_ATOM_TYPE_WRT:
		case AP4_ATOM_TYPE_ALB:
		case AP4_ATOM_TYPE_DAY:
		case AP4_ATOM_TYPE_TOO:
		case AP4_ATOM_TYPE_CMT:
		case AP4_ATOM_TYPE_GEN:
		case AP4_ATOM_TYPE_TRKN:
		case AP4_ATOM_TYPE_EDTS:
		case AP4_ATOM_TYPE_WAVE: 
		case AP4_ATOM_TYPE_CMOV: {
			AP4_UI32 context = m_Context;
			m_Context = type; // set the context for the children
			atom = new AP4_ContainerAtom(type, size, false, stream, *this);
			m_Context = context; // restore the previous context
			break;
		}

		// full container atoms
		case AP4_ATOM_TYPE_META:
			atom = new AP4_ContainerAtom(type, size, true, stream, *this);
			break;

		// other
		case AP4_ATOM_TYPE_AVCC:
			atom = new AP4_AvcCAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_TEXT:
			atom = new AP4_TextSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_TX3G:
			atom = new AP4_Tx3gSampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_FTAB:
			atom = new AP4_FtabAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_RAW:
			{
				AP4_Offset pos;
				AP4_UI16 ch_count_test;

				stream.Tell(pos);
				stream.Seek(pos + 16);
				stream.ReadUI16(ch_count_test);
				stream.Seek(pos);

				if (ch_count_test == 0) {
					atom = new AP4_VisualSampleEntry(type, size, stream, *this);
				} else {
					atom = new AP4_AudioSampleEntry(type, size, stream, *this);
				}
			}
			break;

		case AP4_ATOM_TYPE_CVID:
		case AP4_ATOM_TYPE_SVQ1:
		case AP4_ATOM_TYPE_SVQ2:
		case AP4_ATOM_TYPE_SVQ3:
		case AP4_ATOM_TYPE_H261:
		case AP4_ATOM_TYPE_H263:
		case AP4_ATOM_TYPE_S263:
		case AP4_ATOM_TYPE_JPEG:
		case AP4_ATOM_TYPE_PNG:
		case AP4_ATOM_TYPE_RLE:
		case AP4_ATOM_TYPE_MJPA:
		case AP4_ATOM_TYPE_MJPB:
		case AP4_ATOM_TYPE_RPZA:
		case AP4_ATOM_TYPE_DIV3:
		case AP4_ATOM_TYPE_DIVX:
		case AP4_ATOM_TYPE_8BPS:
		case AP4_ATOM_TYPE_3IV1:
		case AP4_ATOM_TYPE_3IV2:
		case AP4_ATOM_TYPE_IV32:
		case AP4_ATOM_TYPE_IV41:
		case AP4_ATOM_TYPE_VP31:
		case AP4_ATOM_TYPE_YV12:
		case AP4_ATOM_TYPE_APCN:
		case AP4_ATOM_TYPE_APCH:
		case AP4_ATOM_TYPE_APCO:
		case AP4_ATOM_TYPE_APCS:
			atom = new AP4_VisualSampleEntry(type, size, stream, *this);
			break;

		// DV Video Subtypes - http://msdn.microsoft.com/en-us/library/windows/desktop/dd388646%28v=vs.85%29.aspx
		case AP4_ATOM_TYPE_DVC:
		case AP4_ATOM_TYPE_DVCP:
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE('d','v','s','d'), size, stream, *this); // MEDIASUBTYPE_dvsd (DV Video Decoder, ffdshow, LAV)
			break;
		case AP4_ATOM_TYPE_DVPP:
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE('d','v','2','5'), size, stream, *this); // MEDIASUBTYPE_dv25 (ffdshow, LAV)
			break;
		case AP4_ATOM_TYPE_DV5N:
		case AP4_ATOM_TYPE_DV5P:
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE('d','v','5','0'), size, stream, *this); // MEDIASUBTYPE_dv50 (ffdshow, LAV)
			break;
		case AP4_ATOM_TYPE_DVHQ:
		case AP4_ATOM_TYPE_DVH5:
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE('C','D','V','H'), size, stream, *this); // MEDIASUBTYPE_CDVH (LAV)
			break;

		case AP4_ATOM_TYPE_MJPG:
		case AP4_ATOM_TYPE_AVDJ: // uncommon fourcc
		case AP4_ATOM_TYPE_DMB1: // uncommon fourcc
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE_MJPG, size, stream, *this);
			break;

		case AP4_ATOM_TYPE_2VUY: // = 'UYVY'
			atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE('U','Y','V','Y'), size, stream, *this);
			break;

		case AP4_ATOM_TYPE_SAMR:
		case AP4_ATOM_TYPE__MP3:
		case AP4_ATOM_TYPE_IMA4:
		case AP4_ATOM_TYPE_QDMC:
		case AP4_ATOM_TYPE_QDM2:
		case AP4_ATOM_TYPE_NONE:
		case AP4_ATOM_TYPE_TWOS:
		case AP4_ATOM_TYPE_SOWT:
		case AP4_ATOM_TYPE_IN24:
		case AP4_ATOM_TYPE_IN32:
		case AP4_ATOM_TYPE_FL32:
		case AP4_ATOM_TYPE_FL64:
		case AP4_ATOM_TYPE_LPCM:
		case AP4_ATOM_TYPE_ALAW:
		case AP4_ATOM_TYPE_ULAW:
		case AP4_ATOM_TYPE_NMOS:
		case AP4_ATOM_TYPE_ALAC:
		case AP4_ATOM_TYPE_MAC3:
		case AP4_ATOM_TYPE_MAC6:
			atom = new AP4_AudioSampleEntry(type, size, stream, *this);
			break;

		case AP4_ATOM_TYPE__AC3: // AC3-in-MP4 from ISO Standard
		case AP4_ATOM_TYPE_SAC3: // AC3-in-MP4 from Nero Stuff >.<
			atom = new AP4_AC3SampleEntry(size, stream, *this);
			break;
		case AP4_ATOM_TYPE_EAC3:
			atom = new AP4_EAC3SampleEntry(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_CHPL:
			atom = new AP4_ChplAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_DATA:
			atom = new AP4_DataAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_DCOM:
			atom = new AP4_DcomAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_CMVD:
			atom = new AP4_CmvdAtom(size, stream, *this);
			break;

		case AP4_ATOM_TYPE_ENDA:
			atom = new AP4_EndaAtom(size, stream);
			break;

		case AP4_ATOM_TYPE_PASP:
			atom = new AP4_PaspAtom(size, stream);
			break;

		default:
			if(parent && parent->GetType() == AP4_ATOM_TYPE_STSD && (type & 0xffff0000) == AP4_ATOM_TYPE('m', 's', 0, 0)) {
				atom = new AP4_AudioSampleEntry(type, size, stream, *this);
			} else {// try all the external type handlers
				atom = NULL;
				AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
				while (handler_item) {
					TypeHandler* handler = handler_item->GetData();
					if (AP4_SUCCEEDED(handler->CreateAtom(type, size, stream, atom))) {
						break;
					}
					handler_item = handler_item->GetNext();
				}
				if (atom == NULL) {
					// no custom handlers, create a generic atom
					atom = new AP4_UnknownAtom(type, size, false, stream);
				}
			}

			break;
    }

    // skip to the end of the atom
    bytes_available -= size;
    result = stream.Seek(start+size);
    if (AP4_FAILED(result)) {
        delete atom;
        atom = NULL;
    }

    return result;
}
Пример #3
0
/*----------------------------------------------------------------------
|       AP4_AtomFactory::CreateAtomFromStream
+---------------------------------------------------------------------*/
AP4_Result
AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, 
                                      AP4_Size&       bytes_available,
                                      AP4_Atom*&      atom,
									  AP4_Atom*	      parent)
{
    AP4_Result result;


    // NULL by default
    atom = NULL;

    // check that there are enough bytes for at least a header
    if (bytes_available < 8) return AP4_ERROR_EOS;

    // remember current stream offset
    AP4_Offset start;
    stream.Tell(start);

    // read atom size
    AP4_UI32 size;
    result = stream.ReadUI32(size);
    if (AP4_FAILED(result)) {
        stream.Seek(start);
        return result;
    }

    if (size == 0) {
        // atom extends to end of file
        AP4_Size streamSize = 0;
        stream.GetSize(streamSize);
        if (streamSize >= start) {
            size = streamSize - start;
        }
    }

    // check the size (we don't handle extended size yet)
    if (size != 1 && size < 8 || size > bytes_available) {
        stream.Seek(start);
        return AP4_ERROR_INVALID_FORMAT;
    }

    // read atom type
    AP4_Atom::Type type;
    result = stream.ReadUI32(type);
    if (AP4_FAILED(result)) {
        stream.Seek(start);
        return result;
    }

	if (size == 1)
	{
		AP4_UI32 size_high;

		result = stream.ReadUI32(size_high);
		if (AP4_FAILED(result) ) {
            stream.Seek(start);
			return AP4_ERROR_INVALID_FORMAT;
		}

		result = stream.ReadUI32(size);
		if (AP4_FAILED(result)) {
            stream.Seek(start);
			return result;
		}
        if(size_high > 0)
        {
            size = (((ULONGLONG)size_high) << 32) | size;
        }
	}

    
    // create the atom
    switch (type) {
	  case AP4_ATOM_TYPE_3DVF:
      case AP4_ATOM_TYPE_MOOV:
        atom = DNew AP4_MoovAtom(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_MVHD:
        atom = DNew AP4_MvhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_TRAK:
        atom = DNew AP4_TrakAtom(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_HDLR:
        atom = DNew AP4_HdlrAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_DREF:
        atom = DNew AP4_DrefAtom(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_URL:
        atom = DNew AP4_UrlAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_TKHD:
        atom = DNew AP4_TkhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_MDHD:
        atom = DNew AP4_MdhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_STSD:
        atom = DNew AP4_StsdAtom(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_STSC:
        atom = DNew AP4_StscAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_STCO:
        atom = DNew AP4_StcoAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_CO64:
        atom = DNew AP4_Co64Atom(size, stream);
        break;

      case AP4_ATOM_TYPE_STSZ:
        atom = DNew AP4_StszAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_STTS:
        atom = DNew AP4_SttsAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_CTTS:
        atom = DNew AP4_CttsAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_STSS:
        atom = DNew AP4_StssAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_MP4S:
        atom = DNew AP4_Mp4sSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_MP4A:
		atom = parent && parent->GetType() == AP4_ATOM_TYPE_STSD 
			? (AP4_Atom*)DNew AP4_Mp4aSampleEntry(size, stream, *this)
			: (AP4_Atom*)DNew AP4_UnknownAtom(type, size, false, stream);
        break;

      case AP4_ATOM_TYPE_MP4V:
        atom = DNew AP4_Mp4vSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_AVC1:
        atom = DNew AP4_Avc1SampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_ENCA:
        atom = DNew AP4_EncaSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_ENCV:
        atom = DNew AP4_EncvSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_ESDS:
        atom = DNew AP4_EsdsAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_VMHD:
        atom = DNew AP4_VmhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_SMHD:
        atom = DNew AP4_SmhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_NMHD:
        atom = DNew AP4_NmhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_HMHD:
        atom = DNew AP4_HmhdAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_FRMA:
        atom = DNew AP4_FrmaAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_SCHM:
          atom = DNew AP4_SchmAtom(size, stream);
          break;

      case AP4_ATOM_TYPE_FTYP:
        atom = DNew AP4_FtypAtom(size, stream);
        break;
          
      case AP4_ATOM_TYPE_RTP:
        if (m_Context == AP4_ATOM_TYPE_HNTI) {
            atom = DNew AP4_RtpAtom(size, stream);
        } else {
            atom = DNew AP4_RtpHintSampleEntry(size, stream, *this);
        }
        break;
      
      case AP4_ATOM_TYPE_TIMS:
        atom = DNew AP4_TimsAtom(size, stream);
        break;
 
      case AP4_ATOM_TYPE_SDP:
        atom = DNew AP4_SdpAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_IKMS:
        atom = DNew AP4_IkmsAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_ISFM:
        atom = DNew AP4_IsfmAtom(size, stream);
        break;

      case AP4_ATOM_TYPE_HINT:
        atom = DNew AP4_TrefTypeAtom(type, size, stream);
        break;

      // container atoms
      case AP4_ATOM_TYPE_TREF:
      case AP4_ATOM_TYPE_HNTI:
      case AP4_ATOM_TYPE_STBL:
      case AP4_ATOM_TYPE_MDIA:
      case AP4_ATOM_TYPE_DINF:
      case AP4_ATOM_TYPE_MINF:
      case AP4_ATOM_TYPE_SCHI:
      case AP4_ATOM_TYPE_SINF:
      case AP4_ATOM_TYPE_UDTA:
      case AP4_ATOM_TYPE_ILST:
	  case AP4_ATOM_TYPE_NAM:
	  case AP4_ATOM_TYPE_ART:
      case AP4_ATOM_TYPE_WRT:
      case AP4_ATOM_TYPE_ALB:
      case AP4_ATOM_TYPE_DAY:
      case AP4_ATOM_TYPE_TOO:
      case AP4_ATOM_TYPE_CMT:
      case AP4_ATOM_TYPE_GEN:
	  case AP4_ATOM_TYPE_TRKN:
	  case AP4_ATOM_TYPE_EDTS:
	  case AP4_ATOM_TYPE_WAVE: 
	  case AP4_ATOM_TYPE_CMOV: {
          AP4_UI32 context = m_Context;
          m_Context = type; // set the context for the children
          atom = DNew AP4_ContainerAtom(type, size, false, stream, *this);
          m_Context = context; // restore the previous context
          break;
      }

      // full container atoms
      case AP4_ATOM_TYPE_META:
        atom = DNew AP4_ContainerAtom(type, size, true, stream, *this);
        break;

      // other

      case AP4_ATOM_TYPE_AVCC:
	  case AP4_ATOM_TYPE_MVCC:
        atom = DNew AP4_AvcCAtom(type, size, stream);
        break;

      case AP4_ATOM_TYPE_TEXT:
        atom = DNew AP4_TextSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_TX3G:
        atom = DNew AP4_Tx3gSampleEntry(size, stream, *this);
        break;

      case AP4_ATOM_TYPE_FTAB:
        atom = DNew AP4_FtabAtom(size, stream);
        break;

	  case AP4_ATOM_TYPE_CVID:
      case AP4_ATOM_TYPE_SVQ1:
      case AP4_ATOM_TYPE_SVQ2:
      case AP4_ATOM_TYPE_SVQ3:
	  case AP4_ATOM_TYPE_H261:
	  case AP4_ATOM_TYPE_H263:
      case AP4_ATOM_TYPE_S263:
	  case AP4_ATOM_TYPE_JPEG:
	  case AP4_ATOM_TYPE_PNG:
      case AP4_ATOM_TYPE_RLE:
	  case AP4_ATOM_TYPE_MJPA:
	  case AP4_ATOM_TYPE_MJPB:
	  case AP4_ATOM_TYPE_MJPG:
	  case AP4_ATOM_TYPE_DMB1:
	  case AP4_ATOM_TYPE_RPZA:
	  case AP4_ATOM_TYPE_DVC:
	  case AP4_ATOM_TYPE_DIV3:
	  case AP4_ATOM_TYPE_DIVX:
	  case AP4_ATOM_TYPE_8BPS:
	  case AP4_ATOM_TYPE_3IV1:
	  case AP4_ATOM_TYPE_3IV2:
	  case AP4_ATOM_TYPE_IV32:
	  case AP4_ATOM_TYPE_VP31:
	  case AP4_ATOM_TYPE_YV12:
        atom = DNew AP4_VisualSampleEntry(type, size, stream, *this);
        break;

	  case AP4_ATOM_TYPE_SAMR:
	  case AP4_ATOM_TYPE__MP3:
	  case AP4_ATOM_TYPE_IMA4:
	  case AP4_ATOM_TYPE_QDMC:
	  case AP4_ATOM_TYPE_QDM2:
	  case AP4_ATOM_TYPE_NONE:
	  case AP4_ATOM_TYPE_RAW:
	  case AP4_ATOM_TYPE_TWOS:
	  case AP4_ATOM_TYPE_SOWT:
	  case AP4_ATOM_TYPE_IN24:
	  case AP4_ATOM_TYPE_IN32:
	  case AP4_ATOM_TYPE_FL32:
	  case AP4_ATOM_TYPE_FL64:
	  case AP4_ATOM_TYPE_ALAW:
	  case AP4_ATOM_TYPE_ULAW:
        atom = DNew AP4_AudioSampleEntry(type, size, stream, *this);
        break;

	  case AP4_ATOM_TYPE__AC3: // AC3-in-MP4 from ISO Standard
	  case AP4_ATOM_TYPE_SAC3: // AC3-in-MP4 from Nero Stuff >.<
        atom = DNew AP4_AC3SampleEntry(size, stream, *this);
        break;
	  case AP4_ATOM_TYPE_EAC3:
		atom = DNew AP4_EAC3SampleEntry(size, stream, *this);
		break;

      case AP4_ATOM_TYPE_CHPL:
        atom = DNew AP4_ChplAtom(size, stream);
        break;

	  case AP4_ATOM_TYPE_DATA:
        atom = DNew AP4_DataAtom(size, stream);
        break;

	  case AP4_ATOM_TYPE_DCOM:
        atom = DNew AP4_DcomAtom(size, stream);
	    break;

	  case AP4_ATOM_TYPE_CMVD:
        atom = DNew AP4_CmvdAtom(size, stream, *this);
	    break;

	  case AP4_ATOM_TYPE_ENDA:
        atom = DNew AP4_EndaAtom(size, stream);
	    break;

	  case AP4_ATOM_TYPE_PASP:
		  atom = DNew AP4_PaspAtom(size, stream);
		  break;

      default:

		if(parent && parent->GetType() == AP4_ATOM_TYPE_STSD && (type & 0xffff0000) == AP4_ATOM_TYPE('m', 's', 0, 0))
		{
	        atom = DNew AP4_AudioSampleEntry(type, size, stream, *this);
		}
		else // try all the external type handlers
        {
            atom = NULL;
            AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
            while (handler_item) {
                TypeHandler* handler = handler_item->GetData();
                if (AP4_SUCCEEDED(handler->CreateAtom(type, size, stream, atom))) {
                    break;
                }
                handler_item = handler_item->GetNext();
            }
            if (atom == NULL) {
                // no custom handlers, create a generic atom
                atom = DNew AP4_UnknownAtom(type, size, false, stream);
            }
        }

		break;
    }

    // skip to the end of the atom
    bytes_available -= size;
    result = stream.Seek(start+size);
    if (AP4_FAILED(result)) {
        delete atom;
        atom = NULL;
    }

    return result;
}
Пример #4
0
/*----------------------------------------------------------------------
|   AP4_AtomFactory::CreateAtomFromStream
+---------------------------------------------------------------------*/
AP4_Result
AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, 
                                      AP4_UI32        type,
                                      AP4_UI32        size_32,
                                      AP4_UI64        size_64,
                                      AP4_Atom*&      atom)
{
    bool atom_is_large = (size_32 == 1);
    bool force_64 = (size_32==1 && ((size_64>>32) == 0));
    
    // create the atom
    if (GetContext() == AP4_ATOM_TYPE_STSD) {
        // sample entry
        if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
        switch (type) {
          case AP4_ATOM_TYPE_MP4A:
            atom = new AP4_Mp4aSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_MP4V:
            atom = new AP4_Mp4vSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_MP4S:
            atom = new AP4_Mp4sSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_ENCA:
            atom = new AP4_EncaSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_ENCV:
            atom = new AP4_EncvSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_DRMS:
            atom = new AP4_DrmsSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_DRMI:
            atom = new AP4_DrmiSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_AVC1:
          case AP4_ATOM_TYPE_AVC2:
          case AP4_ATOM_TYPE_AVC3:
          case AP4_ATOM_TYPE_AVC4:
            atom = new AP4_AvcSampleEntry(type, size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_HEV1:
          case AP4_ATOM_TYPE_HVC1:
            atom = new AP4_HevcSampleEntry(type, size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_ALAC:
          case AP4_ATOM_TYPE_AC_3:
          case AP4_ATOM_TYPE_EC_3:
          case AP4_ATOM_TYPE_DTSC:
          case AP4_ATOM_TYPE_DTSH:
          case AP4_ATOM_TYPE_DTSL:
          case AP4_ATOM_TYPE_DTSE:
            atom = new AP4_AudioSampleEntry(type, size_32, stream, *this);
            break;
            
          case AP4_ATOM_TYPE_RTP_:
            atom = new AP4_RtpHintSampleEntry(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_STPP:
            atom = new AP4_SubtitleSampleEntry(type, size_32, stream, *this);
            break;

          default: {
            // try all the external type handlers
            AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
            while (handler_item) {
                TypeHandler* handler = handler_item->GetData();
                if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
                    break;
                }
                handler_item = handler_item->GetNext();
            }

            // no custom handler, create a generic entry
            if (atom == NULL) {
                atom = new AP4_UnknownSampleEntry(type, (AP4_UI32)size_64, stream);
            }

            break;
          }
        }
    } else {
        // regular atom
        switch (type) {
          case AP4_ATOM_TYPE_MOOV:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MoovAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_MVHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MvhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_MEHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MehdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_MFHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MfhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TRAK:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TrakAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_TREX:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TrexAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_HDLR:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_HdlrAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TKHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TkhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TFHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TfhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TRUN:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TrunAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TFRA:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TfraAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_MFRO:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MfroAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_MDHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_MdhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STSD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_StsdAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_STSC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_StscAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STCO:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_StcoAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_CO64:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_Co64Atom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STSZ:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_StszAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STZ2:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_Stz2Atom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STTS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SttsAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_CTTS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_CttsAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STSS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_StssAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_IODS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_IodsAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_ESDS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_EsdsAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_AVCC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_AvccAtom::Create(size_32, stream);
            break;
            
          case AP4_ATOM_TYPE_HVCC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_HvccAtom::Create(size_32, stream);
            break;

    #if !defined(AP4_CONFIG_MINI_BUILD)
          case AP4_ATOM_TYPE_UUID: {
              AP4_UI08 uuid[16];
              AP4_Result result = stream.Read(uuid, 16);
              if (AP4_FAILED(result)) return result;
              
              if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_TRACK_ENCRYPTION_ATOM, 16) == 0) {
                  atom = AP4_PiffTrackEncryptionAtom::Create((AP4_UI32)size_64, stream);
              } else if (AP4_CompareMemory(uuid, AP4_UUID_PIFF_SAMPLE_ENCRYPTION_ATOM, 16) == 0) {
                  atom = AP4_PiffSampleEncryptionAtom::Create((AP4_UI32)size_64, stream);
              } else {
                  atom = new AP4_UnknownUuidAtom(size_64, uuid, stream);
              }
              break;
          }
            
          case AP4_ATOM_TYPE_8ID_:
            atom = new AP4_NullTerminatedStringAtom(type, size_64, stream);
            break;

          case AP4_ATOM_TYPE_8BDL:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_8bdlAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_DREF:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_DrefAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_URL:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_UrlAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_ELST:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_ElstAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_VMHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_VmhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SMHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SmhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_NMHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_NmhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_STHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SthdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_HMHD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_HmhdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_FRMA:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_FrmaAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SCHM:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SchmAtom::Create(size_32, &m_ContextStack, stream);
            break;

          case AP4_ATOM_TYPE_FTYP:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_FtypAtom::Create(size_32, stream);
            break;
                        
          case AP4_ATOM_TYPE_TIMS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TimsAtom::Create(size_32, stream);
            break;
     
          case AP4_ATOM_TYPE_SDP_:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SdpAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_IKMS:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_IkmsAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_ISFM:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_IsfmAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_ISLT:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_IsltAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_ODHE:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_OdheAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_OHDR:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_OhdrAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_ODDA:
            atom = AP4_OddaAtom::Create(size_64, stream);
            break;

          case AP4_ATOM_TYPE_ODAF:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_OdafAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_GRPI:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_GrpiAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_IPRO:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_IproAtom::Create(size_32, stream, *this);
            break;

          case AP4_ATOM_TYPE_RTP_:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_RtpAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TFDT:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TfdtAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_TENC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_TencAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SENC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SencAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SAIZ:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SaizAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SAIO:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SaioAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_PDIN:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_PdinAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_BLOC:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_BlocAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_AINF:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_AinfAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_PSSH:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_PsshAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SIDX:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SidxAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SBGP:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SbgpAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_SGPD:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_SgpdAtom::Create(size_32, stream);
            break;

          case AP4_ATOM_TYPE_MKID:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            if (GetContext() == AP4_ATOM_TYPE_MARL) {
                atom = AP4_MkidAtom::Create(size_32, stream);
            }
            break;

          case AP4_ATOM_TYPE_DEC3:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            if (GetContext() == AP4_ATOM_TYPE_EC_3) {
                atom = AP4_Dec3Atom::Create(size_32, stream);
            }
            break;

          case AP4_ATOM_TYPE_XML:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_XmlAtom::Create(size_32, stream);
            break;

          // track ref types
          case AP4_ATOM_TYPE_HINT:
          case AP4_ATOM_TYPE_CDSC:
          case AP4_ATOM_TYPE_SYNC:
          case AP4_ATOM_TYPE_MPOD:
          case AP4_ATOM_TYPE_DPND:
          case AP4_ATOM_TYPE_IPIR:
          case AP4_ATOM_TYPE_ALIS:
          case AP4_ATOM_TYPE_CHAP:
            if (GetContext() == AP4_ATOM_TYPE_TREF) {
                if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
                atom = AP4_TrefTypeAtom::Create(type, size_32, stream);
            }
            break;

    #endif // AP4_CONFIG_MINI_BUILD

          // container atoms
          case AP4_ATOM_TYPE_MOOF:
          case AP4_ATOM_TYPE_MVEX:
          case AP4_ATOM_TYPE_TRAF:
          case AP4_ATOM_TYPE_TREF:
          case AP4_ATOM_TYPE_MFRA:
          case AP4_ATOM_TYPE_HNTI:
          case AP4_ATOM_TYPE_STBL:
          case AP4_ATOM_TYPE_MDIA:
          case AP4_ATOM_TYPE_DINF:
          case AP4_ATOM_TYPE_MINF:
          case AP4_ATOM_TYPE_SCHI:
          case AP4_ATOM_TYPE_SINF:
          case AP4_ATOM_TYPE_UDTA:
          case AP4_ATOM_TYPE_ILST:
          case AP4_ATOM_TYPE_EDTS: 
          case AP4_ATOM_TYPE_MDRI:
          case AP4_ATOM_TYPE_WAVE:
            if (atom_is_large) return AP4_ERROR_INVALID_FORMAT;
            atom = AP4_ContainerAtom::Create(type, size_64, false, force_64, stream, *this);
            break;

          // containers, only at the top
          case AP4_ATOM_TYPE_MARL:
            if (GetContext() == 0) {
                atom = AP4_ContainerAtom::Create(type, size_64, false, force_64, stream, *this);
            }
            break;
            
          // full container atoms
          case AP4_ATOM_TYPE_META:
          case AP4_ATOM_TYPE_ODRM:
          case AP4_ATOM_TYPE_ODKM:
            atom = AP4_ContainerAtom::Create(type, size_64, true, force_64, stream, *this);
            break;

          case AP4_ATOM_TYPE_FREE:
          case AP4_ATOM_TYPE_WIDE:
          case AP4_ATOM_TYPE_MDAT:
            // generic atoms
            break;
            
          default: {
            // try all the external type handlers
            AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
            while (handler_item) {
                TypeHandler* handler = handler_item->GetData();
                if (AP4_SUCCEEDED(handler->CreateAtom(type, size_32, stream, GetContext(), atom))) {
                    break;
                }
                handler_item = handler_item->GetNext();
            }

            break;
          }
        }
    }
    
    return AP4_SUCCESS;
}