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); }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }
/*---------------------------------------------------------------------- | 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; }