/*---------------------------------------------------------------------- | 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 = 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: atom = DNew AP4_AvcCAtom(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_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_DVC: case AP4_ATOM_TYPE_DV5P: case AP4_ATOM_TYPE_DVCP: case AP4_ATOM_TYPE_DVPP: atom = DNew AP4_VisualSampleEntry(type, size, stream, *this); break; case AP4_ATOM_TYPE_MJPG: case AP4_ATOM_TYPE_AVDJ://uncommon fourcc case AP4_ATOM_TYPE_DMB1://uncommon fourcc atom = DNew AP4_VisualSampleEntry(AP4_ATOM_TYPE_MJPG, 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_LPCM: case AP4_ATOM_TYPE_ALAW: case AP4_ATOM_TYPE_ULAW: case AP4_ATOM_TYPE_NMOS: case AP4_ATOM_TYPE_ALAC: 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_TrakAtom::AP4_TrakAtom +---------------------------------------------------------------------*/ AP4_TrakAtom::AP4_TrakAtom(AP4_SampleTable* sample_table, AP4_Atom::Type hdlr_type, const char* hdlr_name, AP4_UI32 track_id, AP4_UI64 creation_time, AP4_UI64 modification_time, AP4_UI64 track_duration, AP4_UI32 media_time_scale, AP4_UI64 media_duration, AP4_UI16 volume, const char* language, AP4_UI32 width, AP4_UI32 height) : AP4_ContainerAtom(AP4_ATOM_TYPE_TRAK) { AP4_Result result; // create a tkhd atom m_TkhdAtom = DNew AP4_TkhdAtom(creation_time, modification_time, track_id, track_duration, volume, width, height); // create an edts // create a mdia atom AP4_ContainerAtom* mdia = DNew AP4_ContainerAtom(AP4_ATOM_TYPE_MDIA); // create a hdlr atom for the mdia atom m_HdlrAtom = DNew AP4_HdlrAtom(hdlr_type, hdlr_name); // create a minf atom AP4_ContainerAtom* minf = DNew AP4_ContainerAtom(AP4_ATOM_TYPE_MINF); // create a media header atom for minf (vmhd, smhd, hmhd or nmhd) AP4_Atom* minf_header; switch (hdlr_type) { case AP4_HANDLER_TYPE_VIDE: minf_header = DNew AP4_VmhdAtom(0, 0, 0, 0); break; case AP4_HANDLER_TYPE_SOUN: minf_header = DNew AP4_SmhdAtom(0); break; default: minf_header = DNew AP4_NmhdAtom(); break; } // create a dinf atom for minf AP4_ContainerAtom* dinf = DNew AP4_ContainerAtom(AP4_ATOM_TYPE_DINF); // create a url atom as a ref for dref AP4_Atom* url = DNew AP4_UrlAtom(); // local ref // create a dref atom for dinf AP4_DrefAtom* dref = DNew AP4_DrefAtom(&url, 1); // create a stbl atom for minf AP4_ContainerAtom* stbl; result = sample_table->GenerateStblAtom(stbl); if (AP4_FAILED(result)) stbl = NULL; // populate the dinf atom dinf->AddChild(dref); // populate the minf atom minf->AddChild(minf_header); minf->AddChild(dinf); if (stbl) minf->AddChild(stbl); // create a mdhd atom for the mdia atom AP4_MdhdAtom* mdhd = DNew AP4_MdhdAtom(creation_time, modification_time, media_time_scale, media_duration, language); // populate the mdia atom mdia->AddChild(mdhd); mdia->AddChild(m_HdlrAtom); mdia->AddChild(minf); // attach the children AddChild(m_TkhdAtom); AddChild(mdia); }