diff options
author | Michele Calgaro <[email protected]> | 2020-09-11 14:38:47 +0900 |
---|---|---|
committer | Michele Calgaro <[email protected]> | 2020-09-11 14:38:47 +0900 |
commit | 884c8093d63402a1ad0b502244b791e3c6782be3 (patch) | |
tree | a600d4ab0d431a2bdfe4c15b70df43c14fbd8dd0 /debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp | |
parent | 14e1aa2006796f147f3f4811fb908a6b01e79253 (diff) | |
download | extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.tar.gz extra-dependencies-884c8093d63402a1ad0b502244b791e3c6782be3.zip |
Added debian extra dependency packages.
Signed-off-by: Michele Calgaro <[email protected]>
Diffstat (limited to 'debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp')
-rw-r--r-- | debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp | 1017 |
1 files changed, 1017 insertions, 0 deletions
diff --git a/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp new file mode 100644 index 00000000..520cbc87 --- /dev/null +++ b/debian/mp4v2/mp4v2-2.0.0~dfsg0/src/mp4atom.cpp @@ -0,0 +1,1017 @@ +/* + * The contents of this file are subject to the Mozilla Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is MPEG4IP. + * + * The Initial Developer of the Original Code is Cisco Systems Inc. + * Portions created by Cisco Systems Inc. are + * Copyright (C) Cisco Systems Inc. 2001 - 2004. All Rights Reserved. + * + * 3GPP features implementation is based on 3GPP's TS26.234-v5.60, + * and was contributed by Ximpo Group Ltd. + * + * Portions created by Ximpo Group Ltd. are + * Copyright (C) Ximpo Group Ltd. 2003, 2004. All Rights Reserved. + * + * Portions created by Adnecto d.o.o. are + * Copyright (C) Adnecto d.o.o. 2005. All Rights Reserved + * + * Contributor(s): + * Dave Mackie [email protected] + * Alix Marchandise-Franquet [email protected] + * Ximpo Group Ltd. [email protected] + * Danijel Kopcinovic [email protected] + */ + +#include "src/impl.h" + +namespace mp4v2 { namespace impl { + +/////////////////////////////////////////////////////////////////////////////// + +MP4AtomInfo::MP4AtomInfo(const char* name, bool mandatory, bool onlyOne) +{ + m_name = name; + m_mandatory = mandatory; + m_onlyOne = onlyOne; + m_count = 0; +} + +MP4Atom::MP4Atom(MP4File& file, const char* type) + : m_File(file) +{ + SetType(type); + m_unknownType = false; + m_start = 0; + m_end = 0; + m_largesizeMode = false; + m_size = 0; + m_pParentAtom = NULL; + m_depth = 0xFF; +} + +MP4Atom::~MP4Atom() +{ + uint32_t i; + + for (i = 0; i < m_pProperties.Size(); i++) { + delete m_pProperties[i]; + } + for (i = 0; i < m_pChildAtomInfos.Size(); i++) { + delete m_pChildAtomInfos[i]; + } + for (i = 0; i < m_pChildAtoms.Size(); i++) { + delete m_pChildAtoms[i]; + } +} + +MP4Atom* MP4Atom::CreateAtom( MP4File &file, MP4Atom* parent, const char* type ) +{ + MP4Atom* atom = factory( file, parent, type ); + ASSERT( atom ); + return atom; +} + +// generate a skeletal self + +void MP4Atom::Generate() +{ + uint32_t i; + + // for all properties + for (i = 0; i < m_pProperties.Size(); i++) { + // ask it to self generate + m_pProperties[i]->Generate(); + } + + // for all mandatory, single child atom types + for (i = 0; i < m_pChildAtomInfos.Size(); i++) { + if (m_pChildAtomInfos[i]->m_mandatory + && m_pChildAtomInfos[i]->m_onlyOne) { + + // create the mandatory, single child atom + MP4Atom* pChildAtom = + CreateAtom(m_File, this, m_pChildAtomInfos[i]->m_name); + + AddChildAtom(pChildAtom); + + // and ask it to self generate + pChildAtom->Generate(); + } + } +} + +MP4Atom* MP4Atom::ReadAtom(MP4File& file, MP4Atom* pParentAtom) +{ + uint8_t hdrSize = 8; + uint8_t extendedType[16]; + + uint64_t pos = file.GetPosition(); + + log.verbose1f("\"%s\": pos = 0x%" PRIx64, file.GetFilename().c_str(), pos); + + uint64_t dataSize = file.ReadUInt32(); + + char type[5]; + file.ReadBytes((uint8_t*)&type[0], 4); + type[4] = '\0'; + + // extended size + const bool largesizeMode = (dataSize == 1); + if (dataSize == 1) { + dataSize = file.ReadUInt64(); + hdrSize += 8; + file.Check64BitStatus(type); + } + + // extended type + if (ATOMID(type) == ATOMID("uuid")) { + file.ReadBytes(extendedType, sizeof(extendedType)); + hdrSize += sizeof(extendedType); + } + + if (dataSize == 0) { + // extends to EOF + dataSize = file.GetSize() - pos; + } + + dataSize -= hdrSize; + + log.verbose1f("\"%s\": type = \"%s\" data-size = %" PRIu64 " (0x%" PRIx64 ") hdr %u", + file.GetFilename().c_str(), type, dataSize, dataSize, hdrSize); + + if (pos + hdrSize + dataSize > pParentAtom->GetEnd()) { + log.errorf("%s: \"%s\": invalid atom size, extends outside parent atom - skipping to end of \"%s\" \"%s\" %" PRIu64 " vs %" PRIu64, + __FUNCTION__, file.GetFilename().c_str(), pParentAtom->GetType(), type, + pos + hdrSize + dataSize, + pParentAtom->GetEnd()); + log.verbose1f("\"%s\": parent %s (%" PRIu64 ") pos %" PRIu64 " hdr %d data %" PRIu64 " sum %" PRIu64, + file.GetFilename().c_str(), pParentAtom->GetType(), + pParentAtom->GetEnd(), + pos, + hdrSize, + dataSize, + pos + hdrSize + dataSize); + + // skip to end of atom + dataSize = pParentAtom->GetEnd() - pos - hdrSize; + } + + MP4Atom* pAtom = CreateAtom(file, pParentAtom, type); + // pAtom->SetFile(pFile); + pAtom->SetStart(pos); + pAtom->SetEnd(pos + hdrSize + dataSize); + pAtom->SetLargesizeMode(largesizeMode); + pAtom->SetSize(dataSize); + if (ATOMID(type) == ATOMID("uuid")) { + pAtom->SetExtendedType(extendedType); + } + if (pAtom->IsUnknownType()) { + if (!IsReasonableType(pAtom->GetType())) { + log.warningf("%s: \"%s\": atom type %s is suspect", __FUNCTION__, file.GetFilename().c_str(), + pAtom->GetType()); + } else { + log.verbose1f("\"%s\": Info: atom type %s is unknown", file.GetFilename().c_str(), + pAtom->GetType()); + } + + if (dataSize > 0) { + pAtom->AddProperty( + new MP4BytesProperty(*pAtom, "data", dataSize)); + } + } + + pAtom->SetParentAtom(pParentAtom); + + try { + pAtom->Read(); + } + catch (Exception* x) { + // delete atom and rethrow so we don't leak memory. + delete pAtom; + throw x; + } + + + return pAtom; +} + +bool MP4Atom::IsReasonableType(const char* type) +{ + // Unwound this. Pricy when called a lot. + if( isalnum((unsigned char) type[0])) { + if( isalnum((unsigned char) type[1])) { + if( isalnum((unsigned char) type[2])) { + if( isalnum((unsigned char) type[3]) || type[3] == ' ' ) { + return true; + } + } + } + } + + return false; +} + +// generic read +void MP4Atom::Read() +{ + if (ATOMID(m_type) != 0 && m_size > 1000000) { + log.verbose1f("%s: \"%s\": %s atom size %" PRIu64 " is suspect", __FUNCTION__, + m_File.GetFilename().c_str(), m_type, m_size); + } + + ReadProperties(); + + // read child atoms, if we expect there to be some + if (m_pChildAtomInfos.Size() > 0) { + ReadChildAtoms(); + } + + Skip(); // to end of atom +} + +void MP4Atom::Skip() +{ + if (m_File.GetPosition() != m_end) { + log.verbose1f("\"%s\": Skip: %" PRIu64 " bytes", + m_File.GetFilename().c_str(), m_end - m_File.GetPosition()); + } + m_File.SetPosition(m_end); +} + +MP4Atom* MP4Atom::FindAtom(const char* name) +{ + if (!IsMe(name)) { + return NULL; + } + + if (!IsRootAtom()) { + log.verbose1f("\"%s\": FindAtom: matched %s", + GetFile().GetFilename().c_str(), name); + + name = MP4NameAfterFirst(name); + + // I'm the sought after atom + if (name == NULL) { + return this; + } + } + + // else it's one of my children + return FindChildAtom(name); +} + +bool MP4Atom::FindProperty(const char *name, + MP4Property** ppProperty, uint32_t* pIndex) +{ + if (!IsMe(name)) { + return false; + } + + if (!IsRootAtom()) { + log.verbose1f("\"%s\": FindProperty: matched %s", + GetFile().GetFilename().c_str(), name); + + name = MP4NameAfterFirst(name); + + // no property name given + if (name == NULL) { + return false; + } + } + + return FindContainedProperty(name, ppProperty, pIndex); +} + +bool MP4Atom::IsMe(const char* name) +{ + if (name == NULL) { + return false; + } + + // root atom always matches + if (!strcmp(m_type, "")) { + return true; + } + + // check if our atom name is specified as the first component + if (!MP4NameFirstMatches(m_type, name)) { + return false; + } + + return true; +} + +MP4Atom* MP4Atom::FindChildAtom(const char* name) +{ + uint32_t atomIndex = 0; + + // get the index if we have one, e.g. moov.trak[2].mdia... + (void)MP4NameFirstIndex(name, &atomIndex); + + // need to get to the index'th child atom of the right type + for (uint32_t i = 0; i < m_pChildAtoms.Size(); i++) { + if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) { + if (atomIndex == 0) { + // this is the one, ask it to match + return m_pChildAtoms[i]->FindAtom(name); + } + atomIndex--; + } + } + + return NULL; +} + +bool MP4Atom::FindContainedProperty(const char *name, + MP4Property** ppProperty, uint32_t* pIndex) +{ + uint32_t numProperties = m_pProperties.Size(); + uint32_t i; + // check all of our properties + for (i = 0; i < numProperties; i++) { + if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) { + return true; + } + } + + // not one of our properties, + // presumably one of our children's properties + // check child atoms... + + // check if we have an index, e.g. trak[2].mdia... + uint32_t atomIndex = 0; + (void)MP4NameFirstIndex(name, &atomIndex); + + // need to get to the index'th child atom of the right type + for (i = 0; i < m_pChildAtoms.Size(); i++) { + if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) { + if (atomIndex == 0) { + // this is the one, ask it to match + return m_pChildAtoms[i]->FindProperty(name, ppProperty, pIndex); + } + atomIndex--; + } + } + + log.verbose1f("\"%s\": FindProperty: no match for %s", + GetFile().GetFilename().c_str(), name); + return false; +} + +void MP4Atom::ReadProperties(uint32_t startIndex, uint32_t count) +{ + uint32_t numProperties = min(count, m_pProperties.Size() - startIndex); + + // read any properties of the atom + for (uint32_t i = startIndex; i < startIndex + numProperties; i++) { + + m_pProperties[i]->Read(m_File); + + if (m_File.GetPosition() > m_end) { + log.verbose1f("ReadProperties: insufficient data for property: %s pos 0x%" PRIx64 " atom end 0x%" PRIx64, + m_pProperties[i]->GetName(), + m_File.GetPosition(), m_end); + + ostringstream oss; + oss << "atom '" << GetType() << "' is too small; overrun at property: " << m_pProperties[i]->GetName(); + throw new Exception( oss.str().c_str(), __FILE__, __LINE__, __FUNCTION__ ); + } + + MP4LogLevel thisVerbosity = + (m_pProperties[i]->GetType() == TableProperty) ? + MP4_LOG_VERBOSE2 : MP4_LOG_VERBOSE1; + + if (log.verbosity >= thisVerbosity) { + // log.printf(thisVerbosity,"Read: "); + m_pProperties[i]->Dump(0, true); + } + } +} + +void MP4Atom::ReadChildAtoms() +{ + bool this_is_udta = ATOMID(m_type) == ATOMID("udta"); + + log.verbose1f("\"%s\": of %s", m_File.GetFilename().c_str(), m_type[0] ? m_type : "root"); + for (uint64_t position = m_File.GetPosition(); + position < m_end; + position = m_File.GetPosition()) { + // make sure that we have enough to read at least 8 bytes + // size and type. + if (m_end - position < 2 * sizeof(uint32_t)) { + // if we're reading udta, it's okay to have 4 bytes of 0 + if (this_is_udta && + m_end - position == sizeof(uint32_t)) { + uint32_t mbz = m_File.ReadUInt32(); + if (mbz != 0) { + log.warningf("%s: \"%s\": In udta atom, end value is not zero %x", __FUNCTION__, + m_File.GetFilename().c_str(), mbz); + } + continue; + } + // otherwise, output a warning, but don't care + log.warningf("%s: \"%s\": In %s atom, extra %" PRId64 " bytes at end of atom", __FUNCTION__, + m_File.GetFilename().c_str(), m_type, (m_end - position)); + for (uint64_t ix = 0; ix < m_end - position; ix++) { + (void)m_File.ReadUInt8(); + } + continue; + } + MP4Atom* pChildAtom = MP4Atom::ReadAtom(m_File, this); + + AddChildAtom(pChildAtom); + + MP4AtomInfo* pChildAtomInfo = FindAtomInfo(pChildAtom->GetType()); + + // if child atom is of known type + // but not expected here print warning + if (pChildAtomInfo == NULL && !pChildAtom->IsUnknownType()) { + log.verbose1f("%s: \"%s\": In atom %s unexpected child atom %s", __FUNCTION__, + m_File.GetFilename().c_str(), GetType(), pChildAtom->GetType()); + } + + // if child atoms should have just one instance + // and this is more than one, print warning + if (pChildAtomInfo) { + pChildAtomInfo->m_count++; + + if (pChildAtomInfo->m_onlyOne && pChildAtomInfo->m_count > 1) { + log.warningf("%s: \"%s\": In atom %s multiple child atoms %s", __FUNCTION__, + m_File.GetFilename().c_str(), GetType(), pChildAtom->GetType()); + } + } + + } + + // if mandatory child atom doesn't exist, print warning + uint32_t numAtomInfo = m_pChildAtomInfos.Size(); + for (uint32_t i = 0; i < numAtomInfo; i++) { + if (m_pChildAtomInfos[i]->m_mandatory + && m_pChildAtomInfos[i]->m_count == 0) { + log.warningf("%s: \"%s\": In atom %s missing child atom %s", __FUNCTION__, + m_File.GetFilename().c_str(), GetType(), m_pChildAtomInfos[i]->m_name); + } + } + + log.verbose1f("\"%s\": finished %s", m_File.GetFilename().c_str(), m_type); +} + +MP4AtomInfo* MP4Atom::FindAtomInfo(const char* name) +{ + uint32_t numAtomInfo = m_pChildAtomInfos.Size(); + for (uint32_t i = 0; i < numAtomInfo; i++) { + if (ATOMID(m_pChildAtomInfos[i]->m_name) == ATOMID(name)) { + return m_pChildAtomInfos[i]; + } + } + return NULL; +} + +// generic write +void MP4Atom::Write() +{ + BeginWrite(); + + WriteProperties(); + + WriteChildAtoms(); + + FinishWrite(); +} + +void MP4Atom::Rewrite() +{ + if (!m_end) { + // This atom hasn't been written yet... + return; + } + + uint64_t fPos = m_File.GetPosition(); + m_File.SetPosition(GetStart()); + Write(); + m_File.SetPosition(fPos); +} + +void MP4Atom::BeginWrite(bool use64) +{ + m_start = m_File.GetPosition(); + //use64 = m_File.Use64Bits(); + if (use64) { + m_File.WriteUInt32(1); + } else { + m_File.WriteUInt32(0); + } + m_File.WriteBytes((uint8_t*)&m_type[0], 4); + if (use64) { + m_File.WriteUInt64(0); + } + if (ATOMID(m_type) == ATOMID("uuid")) { + m_File.WriteBytes(m_extendedType, sizeof(m_extendedType)); + } +} + +void MP4Atom::FinishWrite(bool use64) +{ + m_end = m_File.GetPosition(); + m_size = (m_end - m_start); + + log.verbose1f("end: type %s %" PRIu64 " %" PRIu64 " size %" PRIu64, + m_type,m_start, m_end, m_size); + //use64 = m_File.Use64Bits(); + if (use64) { + m_File.SetPosition(m_start + 8); + m_File.WriteUInt64(m_size); + } else { + ASSERT(m_size <= (uint64_t)0xFFFFFFFF); + m_File.SetPosition(m_start); + m_File.WriteUInt32(m_size); + } + m_File.SetPosition(m_end); + + // adjust size to just reflect data portion of atom + m_size -= (use64 ? 16 : 8); + if (ATOMID(m_type) == ATOMID("uuid")) { + m_size -= sizeof(m_extendedType); + } +} + +void MP4Atom::WriteProperties(uint32_t startIndex, uint32_t count) +{ + uint32_t numProperties = min(count, m_pProperties.Size() - startIndex); + + log.verbose1f("Write: \"%s\": type %s", m_File.GetFilename().c_str(), m_type); + + for (uint32_t i = startIndex; i < startIndex + numProperties; i++) { + m_pProperties[i]->Write(m_File); + + MP4LogLevel thisVerbosity = + (m_pProperties[i]->GetType() == TableProperty) ? + MP4_LOG_VERBOSE2 : MP4_LOG_VERBOSE1; + + if (log.verbosity >= thisVerbosity) { + log.printf(thisVerbosity,"Write: "); + m_pProperties[i]->Dump(0, false); + } + } +} + +void MP4Atom::WriteChildAtoms() +{ + uint32_t size = m_pChildAtoms.Size(); + for (uint32_t i = 0; i < size; i++) { + m_pChildAtoms[i]->Write(); + } + + log.verbose1f("Write: \"%s\": finished %s", m_File.GetFilename().c_str(), m_type); +} + +void MP4Atom::AddProperty(MP4Property* pProperty) +{ + ASSERT(pProperty); + m_pProperties.Add(pProperty); +} + +void MP4Atom::AddVersionAndFlags() +{ + AddProperty(new MP4Integer8Property(*this, "version")); + AddProperty(new MP4Integer24Property(*this, "flags")); +} + +void MP4Atom::AddReserved(MP4Atom& parentAtom, const char* name, uint32_t size) +{ + MP4BytesProperty* pReserved = new MP4BytesProperty(parentAtom, name, size); + pReserved->SetReadOnly(); + AddProperty(pReserved); +} + +void MP4Atom::ExpectChildAtom(const char* name, bool mandatory, bool onlyOne) +{ + m_pChildAtomInfos.Add(new MP4AtomInfo(name, mandatory, onlyOne)); +} + +uint8_t MP4Atom::GetVersion() +{ + if (strcmp("version", m_pProperties[0]->GetName())) { + return 0; + } + return ((MP4Integer8Property*)m_pProperties[0])->GetValue(); +} + +void MP4Atom::SetVersion(uint8_t version) +{ + if (strcmp("version", m_pProperties[0]->GetName())) { + return; + } + ((MP4Integer8Property*)m_pProperties[0])->SetValue(version); +} + +uint32_t MP4Atom::GetFlags() +{ + if (strcmp("flags", m_pProperties[1]->GetName())) { + return 0; + } + return ((MP4Integer24Property*)m_pProperties[1])->GetValue(); +} + +void MP4Atom::SetFlags(uint32_t flags) +{ + if (strcmp("flags", m_pProperties[1]->GetName())) { + return; + } + ((MP4Integer24Property*)m_pProperties[1])->SetValue(flags); +} + +void MP4Atom::Dump(uint8_t indent, bool dumpImplicits) +{ + if ( m_type[0] != '\0' ) { + // create list of ancestors + list<string> tlist; + for( MP4Atom* atom = this; atom; atom = atom->GetParentAtom() ) { + const char* const type = atom->GetType(); + if( type && type[0] != '\0' ) + tlist.push_front( type ); + } + + // create contextual atom-name + string can; + const list<string>::iterator ie = tlist.end(); + for( list<string>::iterator it = tlist.begin(); it != ie; it++ ) + can += *it + '.'; + if( can.length() ) + can.resize( can.length() - 1 ); + + log.dump(indent, MP4_LOG_VERBOSE1, "\"%s\": type %s (%s)", + GetFile().GetFilename().c_str(), + m_type, can.c_str() ); + } + + uint32_t i; + uint32_t size; + + // dump our properties + size = m_pProperties.Size(); + for (i = 0; i < size; i++) { + + /* skip details of tables unless we're told to be verbose */ + if (m_pProperties[i]->GetType() == TableProperty + && (log.verbosity < MP4_LOG_VERBOSE2)) { + log.dump(indent + 1, MP4_LOG_VERBOSE1, "\"%s\": <table entries suppressed>", + GetFile().GetFilename().c_str() ); + continue; + } + + m_pProperties[i]->Dump(indent + 1, dumpImplicits); + } + + // dump our children + size = m_pChildAtoms.Size(); + for (i = 0; i < size; i++) { + m_pChildAtoms[i]->Dump(indent + 1, dumpImplicits); + } +} + +uint8_t MP4Atom::GetDepth() +{ + if (m_depth < 0xFF) { + return m_depth; + } + + MP4Atom *pAtom = this; + m_depth = 0; + + while ((pAtom = pAtom->GetParentAtom()) != NULL) { + m_depth++; + ASSERT(m_depth < 255); + } + return m_depth; +} + +bool MP4Atom::GetLargesizeMode() +{ + return m_largesizeMode; +} + +void MP4Atom::SetLargesizeMode( bool mode ) +{ + m_largesizeMode = mode; +} + +bool +MP4Atom::descendsFrom( MP4Atom* parent, const char* type ) +{ + const uint32_t id = ATOMID( type ); + for( MP4Atom* atom = parent; atom; atom = atom->GetParentAtom() ) { + if( id == ATOMID(atom->GetType()) ) + return true; + } + return false; +} + +// UDTA child atom types to be constructed as MP4UdtaElementAtom. +// List gleaned from QTFF 2007-09-04. +static const char* const UDTA_ELEMENTS[] = { + "\xA9" "arg", + "\xA9" "ark", + "\xA9" "cok", + "\xA9" "com", + "\xA9" "cpy", + "\xA9" "day", + "\xA9" "dir", + "\xA9" "ed1", + "\xA9" "ed2", + "\xA9" "ed3", + "\xA9" "ed4", + "\xA9" "ed5", + "\xA9" "ed6", + "\xA9" "ed7", + "\xA9" "ed8", + "\xA9" "ed9", + "\xA9" "fmt", + "\xA9" "inf", + "\xA9" "isr", + "\xA9" "lab", + "\xA9" "lal", + "\xA9" "mak", + "\xA9" "nak", + "\xA9" "nam", + "\xA9" "pdk", + "\xA9" "phg", + "\xA9" "prd", + "\xA9" "prf", + "\xA9" "prk", + "\xA9" "prl", + "\xA9" "req", + "\xA9" "snk", + "\xA9" "snm", + "\xA9" "src", + "\xA9" "swf", + "\xA9" "swk", + "\xA9" "swr", + "\xA9" "wrt", + "Allf", + "name", + "LOOP", + "ptv ", + "SelO", + "WLOC", + NULL // must be last +}; + +MP4Atom* +MP4Atom::factory( MP4File &file, MP4Atom* parent, const char* type ) +{ + // type may be NULL only in case of root-atom + if( !type ) + return new MP4RootAtom(file); + + // construct atoms which are context-savvy + if( parent ) { + const char* const ptype = parent->GetType(); + + if( descendsFrom( parent, "ilst" )) { + if( ATOMID( ptype ) == ATOMID( "ilst" )) + return new MP4ItemAtom( file, type ); + + if( ATOMID( type ) == ATOMID( "data" )) + return new MP4DataAtom(file); + + if( ATOMID( ptype ) == ATOMID( "----" )) { + if( ATOMID( type ) == ATOMID( "mean" )) + return new MP4MeanAtom(file); + if( ATOMID( type ) == ATOMID( "name" )) + return new MP4NameAtom(file); + } + } + else if( ATOMID( ptype ) == ATOMID( "meta" )) { + if( ATOMID( type ) == ATOMID( "hdlr" )) + return new MP4ItmfHdlrAtom(file); + } + else if( ATOMID( ptype ) == ATOMID( "udta" )) { + if( ATOMID( type ) == ATOMID( "hnti" )) + return new MP4HntiAtom(file); + if( ATOMID( type ) == ATOMID( "hinf" )) + return new MP4HinfAtom(file); + for( const char* const* p = UDTA_ELEMENTS; *p; p++ ) + if( !strcmp( type, *p )) + return new MP4UdtaElementAtom( file, type ); + } + } + + // no-context construction (old-style) + switch( (uint8_t)type[0] ) { + case 'S': + if( ATOMID(type) == ATOMID("SVQ3") ) + return new MP4VideoAtom( file, type ); + if( ATOMID(type) == ATOMID("SMI ") ) + return new MP4SmiAtom(file); + break; + + case 'a': + if( ATOMID(type) == ATOMID("avc1") ) + return new MP4Avc1Atom(file); + if( ATOMID(type) == ATOMID("ac-3") ) + return new MP4Ac3Atom(file); + if( ATOMID(type) == ATOMID("avcC") ) + return new MP4AvcCAtom(file); + if( ATOMID(type) == ATOMID("alis") ) + return new MP4UrlAtom( file, type ); + if( ATOMID(type) == ATOMID("alaw") ) + return new MP4SoundAtom( file, type ); + if( ATOMID(type) == ATOMID("alac") ) + return new MP4SoundAtom( file, type ); + break; + + case 'c': + if( ATOMID(type) == ATOMID("chap") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("chpl") ) + return new MP4ChplAtom(file); + if( ATOMID(type) == ATOMID("colr") ) + return new MP4ColrAtom(file); + break; + + case 'd': + if( ATOMID(type) == ATOMID("d263") ) + return new MP4D263Atom(file); + if( ATOMID(type) == ATOMID("damr") ) + return new MP4DamrAtom(file); + if( ATOMID(type) == ATOMID("dref") ) + return new MP4DrefAtom(file); + if( ATOMID(type) == ATOMID("dpnd") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("dac3") ) + return new MP4DAc3Atom(file); + break; + + case 'e': + if( ATOMID(type) == ATOMID("elst") ) + return new MP4ElstAtom(file); + if( ATOMID(type) == ATOMID("enca") ) + return new MP4EncaAtom(file); + if( ATOMID(type) == ATOMID("encv") ) + return new MP4EncvAtom(file); + break; + + case 'f': + if( ATOMID(type) == ATOMID("free") ) + return new MP4FreeAtom(file); + if( ATOMID(type) == ATOMID("ftyp") ) + return new MP4FtypAtom(file); + if( ATOMID(type) == ATOMID("ftab") ) + return new MP4FtabAtom(file); + break; + + case 'g': + if( ATOMID(type) == ATOMID("gmin") ) + return new MP4GminAtom(file); + break; + + case 'h': + if( ATOMID(type) == ATOMID("hdlr") ) + return new MP4HdlrAtom(file); + if( ATOMID(type) == ATOMID("hint") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("h263") ) + return new MP4VideoAtom( file, type ); + if( ATOMID(type) == ATOMID("href") ) + return new MP4HrefAtom(file); + break; + + case 'i': + if( ATOMID(type) == ATOMID("ipir") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("ima4") ) + return new MP4SoundAtom( file, type ); + break; + + case 'j': + if( ATOMID(type) == ATOMID("jpeg") ) + return new MP4VideoAtom(file, "jpeg"); + break; + + case 'm': + if( ATOMID(type) == ATOMID("mdhd") ) + return new MP4MdhdAtom(file); + if( ATOMID(type) == ATOMID("mvhd") ) + return new MP4MvhdAtom(file); + if( ATOMID(type) == ATOMID("mdat") ) + return new MP4MdatAtom(file); + if( ATOMID(type) == ATOMID("mpod") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("mp4a") ) + return new MP4SoundAtom( file, type ); + if( ATOMID(type) == ATOMID("mp4s") ) + return new MP4Mp4sAtom(file); + if( ATOMID(type) == ATOMID("mp4v") ) + return new MP4Mp4vAtom(file); + break; + + case 'n': + if( ATOMID(type) == ATOMID("nmhd") ) + return new MP4NmhdAtom(file); + break; + + case 'o': + if( ATOMID(type) == ATOMID("ohdr") ) + return new MP4OhdrAtom(file); + break; + + case 'p': + if( ATOMID(type) == ATOMID("pasp") ) + return new MP4PaspAtom(file); + break; + + case 'r': + if( ATOMID(type) == ATOMID("rtp ") ) + return new MP4RtpAtom(file); + if( ATOMID(type) == ATOMID("raw ") ) + return new MP4VideoAtom( file, type ); + break; + + case 's': + if( ATOMID(type) == ATOMID("s263") ) + return new MP4S263Atom(file); + if( ATOMID(type) == ATOMID("samr") ) + return new MP4AmrAtom( file, type ); + if( ATOMID(type) == ATOMID("sawb") ) + return new MP4AmrAtom( file, type ); + if( ATOMID(type) == ATOMID("sdtp") ) + return new MP4SdtpAtom(file); + if( ATOMID(type) == ATOMID("stbl") ) + return new MP4StblAtom(file); + if( ATOMID(type) == ATOMID("stsd") ) + return new MP4StsdAtom(file); + if( ATOMID(type) == ATOMID("stsz") ) + return new MP4StszAtom(file); + if( ATOMID(type) == ATOMID("stsc") ) + return new MP4StscAtom(file); + if( ATOMID(type) == ATOMID("stz2") ) + return new MP4Stz2Atom(file); + if( ATOMID(type) == ATOMID("stdp") ) + return new MP4StdpAtom(file); + if( ATOMID(type) == ATOMID("sdp ") ) + return new MP4SdpAtom(file); + if( ATOMID(type) == ATOMID("sync") ) + return new MP4TrefTypeAtom( file, type ); + if( ATOMID(type) == ATOMID("skip") ) + return new MP4FreeAtom( file, type ); + if (ATOMID(type) == ATOMID("sowt") ) + return new MP4SoundAtom( file, type ); + break; + + case 't': + if( ATOMID(type) == ATOMID("text") ) + return new MP4TextAtom(file); + if( ATOMID(type) == ATOMID("tx3g") ) + return new MP4Tx3gAtom(file); + if( ATOMID(type) == ATOMID("tkhd") ) + return new MP4TkhdAtom(file); + if( ATOMID(type) == ATOMID("tfhd") ) + return new MP4TfhdAtom(file); + if( ATOMID(type) == ATOMID("trun") ) + return new MP4TrunAtom(file); + if( ATOMID(type) == ATOMID("twos") ) + return new MP4SoundAtom( file, type ); + break; + + case 'u': + if( ATOMID(type) == ATOMID("udta") ) + return new MP4UdtaAtom(file); + if( ATOMID(type) == ATOMID("url ") ) + return new MP4UrlAtom(file); + if( ATOMID(type) == ATOMID("urn ") ) + return new MP4UrnAtom(file); + if( ATOMID(type) == ATOMID("ulaw") ) + return new MP4SoundAtom( file, type ); + break; + + case 'v': + if( ATOMID(type) == ATOMID("vmhd") ) + return new MP4VmhdAtom(file); + break; + + case 'y': + if( ATOMID(type) == ATOMID("yuv2") ) + return new MP4VideoAtom( file, type ); + break; + + default: + break; + } + + // default to MP4StandardAtom implementation + return new MP4StandardAtom( file, type ); +} + +/////////////////////////////////////////////////////////////////////////////// + +}} // namespace mp4v2::impl |