📄 mp4atom.cpp
字号:
m_pFile->SetPosition(m_end);}MP4Atom* MP4Atom::FindAtom(const char* name){ if (!IsMe(name)) { return NULL; } if (!IsRootAtom()) { VERBOSE_FIND(m_pFile->GetVerbosity(), printf("FindAtom: matched %s\n", 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, u_int32_t* pIndex){ if (!IsMe(name)) { return false; } if (!IsRootAtom()) { VERBOSE_FIND(m_pFile->GetVerbosity(), printf("FindProperty: matched %s\n", 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){ u_int32_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 (u_int32_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, u_int32_t* pIndex){ u_int32_t numProperties = m_pProperties.Size(); u_int32_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... u_int32_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--; } } VERBOSE_FIND(m_pFile->GetVerbosity(), printf("FindProperty: no match for %s\n", name)); return false;}void MP4Atom::ReadProperties(u_int32_t startIndex, u_int32_t count){ u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex); // read any properties of the atom for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) { m_pProperties[i]->Read(m_pFile); if (m_pFile->GetPosition() > m_end) { VERBOSE_READ(GetVerbosity(), printf("ReadProperties: insufficient data for property: %s pos 0x"X64" atom end 0x"X64"\n", m_pProperties[i]->GetName(), m_pFile->GetPosition(), m_end)); throw new MP4Error("atom is too small", "Atom ReadProperties"); } if (m_pProperties[i]->GetType() == TableProperty) { VERBOSE_READ_TABLE(GetVerbosity(), printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true)); } else if (m_pProperties[i]->GetType() != DescriptorProperty) { VERBOSE_READ(GetVerbosity(), printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true)); } }}void MP4Atom::ReadChildAtoms(){ bool this_is_udta = ATOMID(m_type) == ATOMID("udta"); VERBOSE_READ(GetVerbosity(), printf("ReadChildAtoms: of %s\n", m_type[0] ? m_type : "root")); for (u_int64_t position = m_pFile->GetPosition(); position < m_end; position = m_pFile->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)) { u_int32_t mbz = m_pFile->ReadUInt32(); if (mbz != 0) { VERBOSE_WARNING(GetVerbosity(), printf("Error: In udta atom, end value is not zero %x\n", mbz)); } continue; } // otherwise, output a warning, but don't care VERBOSE_WARNING(GetVerbosity(), printf("Error: In %s atom, extra "D64" bytes at end of atom\n", m_type, (m_end - position))); for (uint64_t ix = 0; ix < m_end - position; ix++) { (void)m_pFile->ReadUInt8(); } continue; } MP4Atom* pChildAtom = MP4Atom::ReadAtom(m_pFile, 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()) { VERBOSE_READ(GetVerbosity(), printf("Warning: In atom %s unexpected child atom %s\n", 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) { VERBOSE_READ(GetVerbosity(), printf("Warning: In atom %s multiple child atoms %s\n", GetType(), pChildAtom->GetType())); } } } // if mandatory child atom doesn't exist, print warning u_int32_t numAtomInfo = m_pChildAtomInfos.Size(); for (u_int32_t i = 0; i < numAtomInfo; i++) { if (m_pChildAtomInfos[i]->m_mandatory && m_pChildAtomInfos[i]->m_count == 0) { VERBOSE_READ(GetVerbosity(), printf("Warning: In atom %s missing child atom %s\n", GetType(), m_pChildAtomInfos[i]->m_name)); } } VERBOSE_READ(GetVerbosity(), printf("ReadChildAtoms: finished %s\n", m_type));}MP4AtomInfo* MP4Atom::FindAtomInfo(const char* name){ u_int32_t numAtomInfo = m_pChildAtomInfos.Size(); for (u_int32_t i = 0; i < numAtomInfo; i++) { if (ATOMID(m_pChildAtomInfos[i]->m_name) == ATOMID(name)) { return m_pChildAtomInfos[i]; } } return NULL;}// generic writevoid MP4Atom::Write(){ ASSERT(m_pFile); BeginWrite(); WriteProperties(); WriteChildAtoms(); FinishWrite();}void MP4Atom::Rewrite(){ ASSERT(m_pFile); if (!m_end) { // This atom hasn't been written yet... return; } u_int64_t fPos = m_pFile->GetPosition(); m_pFile->SetPosition(GetStart()); Write(); m_pFile->SetPosition(fPos);}void MP4Atom::BeginWrite(bool use64){ m_start = m_pFile->GetPosition(); //use64 = m_pFile->Use64Bits(); if (use64) { m_pFile->WriteUInt32(1); } else { m_pFile->WriteUInt32(0); } m_pFile->WriteBytes((u_int8_t*)&m_type[0], 4); if (use64) { m_pFile->WriteUInt64(0); } if (ATOMID(m_type) == ATOMID("uuid")) { m_pFile->WriteBytes(m_extendedType, sizeof(m_extendedType)); }}void MP4Atom::FinishWrite(bool use64){ m_end = m_pFile->GetPosition(); m_size = (m_end - m_start); VERBOSE_WRITE(GetVerbosity(), printf("end: type %s "U64" "U64" size "U64"\n", m_type, m_start, m_end, m_size)); //use64 = m_pFile->Use64Bits(); if (use64) { m_pFile->SetPosition(m_start + 8); m_pFile->WriteUInt64(m_size); } else { ASSERT(m_size <= (u_int64_t)0xFFFFFFFF); m_pFile->SetPosition(m_start); m_pFile->WriteUInt32(m_size); } m_pFile->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(u_int32_t startIndex, u_int32_t count){ u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex); VERBOSE_WRITE(GetVerbosity(), printf("Write: type %s\n", m_type)); for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) { m_pProperties[i]->Write(m_pFile); if (m_pProperties[i]->GetType() == TableProperty) { VERBOSE_WRITE_TABLE(GetVerbosity(), printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false)); } else { VERBOSE_WRITE(GetVerbosity(), printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false)); } }}void MP4Atom::WriteChildAtoms(){ u_int32_t size = m_pChildAtoms.Size(); for (u_int32_t i = 0; i < size; i++) { m_pChildAtoms[i]->Write(); } VERBOSE_WRITE(GetVerbosity(), printf("Write: finished %s\n", m_type));}void MP4Atom::AddProperty(MP4Property* pProperty) { ASSERT(pProperty); m_pProperties.Add(pProperty); pProperty->SetParentAtom(this);}void MP4Atom::AddVersionAndFlags(){ AddProperty(new MP4Integer8Property("version")); AddProperty(new MP4Integer24Property("flags"));}void MP4Atom::AddReserved(char* name, u_int32_t size) { MP4BytesProperty* pReserved = new MP4BytesProperty(name, size); pReserved->SetReadOnly(); AddProperty(pReserved);}void MP4Atom::ExpectChildAtom(const char* name, bool mandatory, bool onlyOne){ m_pChildAtomInfos.Add(new MP4AtomInfo(name, mandatory, onlyOne));}u_int8_t MP4Atom::GetVersion(){ if (strcmp("version", m_pProperties[0]->GetName())) { return 0; } return ((MP4Integer8Property*)m_pProperties[0])->GetValue();}void MP4Atom::SetVersion(u_int8_t version) { if (strcmp("version", m_pProperties[0]->GetName())) { return; } ((MP4Integer8Property*)m_pProperties[0])->SetValue(version);}u_int32_t MP4Atom::GetFlags(){ if (strcmp("flags", m_pProperties[1]->GetName())) { return 0; } return ((MP4Integer24Property*)m_pProperties[1])->GetValue();}void MP4Atom::SetFlags(u_int32_t flags) { if (strcmp("flags", m_pProperties[1]->GetName())) { return; } ((MP4Integer24Property*)m_pProperties[1])->SetValue(flags);}void MP4Atom::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits){ if (m_type[0] != '\0') { Indent(pFile, indent); fprintf(pFile, "type %s\n", m_type); fflush(pFile); } u_int32_t i; u_int32_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 && !(GetVerbosity() & MP4_DETAILS_TABLE)) { Indent(pFile, indent + 1); fprintf(pFile, "<table entries suppressed>\n"); continue; } m_pProperties[i]->Dump(pFile, indent + 1, dumpImplicits); } // dump our children size = m_pChildAtoms.Size(); for (i = 0; i < size; i++) { m_pChildAtoms[i]->Dump(pFile, indent + 1, dumpImplicits); }}u_int32_t MP4Atom::GetVerbosity() { ASSERT(m_pFile); return m_pFile->GetVerbosity();}u_int8_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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -