📄 mp4atom.cpp
字号:
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...
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;
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"LLX" atom end 0x"LLX"\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()
{
VERBOSE_READ(GetVerbosity(),
printf("ReadChildAtoms: of %s\n", m_type[0] ? m_type : "root"));
// read any child atoms
while (m_pFile->GetPosition() < m_end) {
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 write
void MP4Atom::Write()
{
ASSERT(m_pFile);
BeginWrite();
WriteProperties();
WriteChildAtoms();
FinishWrite();
}
void MP4Atom::BeginWrite(bool use64)
{
m_start = m_pFile->GetPosition();
if (use64) {
m_pFile->WriteUInt32(1);
m_pFile->WriteUInt64(0);
} else {
m_pFile->WriteUInt32(0);
}
m_pFile->WriteBytes((u_int8_t*)&m_type[0], 4);
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);
if (use64) {
m_pFile->SetPosition(m_start + 4);
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);
}
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 + -