📄 mp4atom.cpp
字号:
/* * 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 dmackie@cisco.com * Alix Marchandise-Franquet alix@cisco.com * Ximpo Group Ltd. mp4v2@ximpo.com * Danijel Kopcinovic danijel.kopcinovic@adnecto.net */#include "mp4common.h"#include "atoms.h"MP4AtomInfo::MP4AtomInfo(const char* name, bool mandatory, bool onlyOne) { m_name = name; m_mandatory = mandatory; m_onlyOne = onlyOne; m_count = 0;}MP4Atom::MP4Atom(const char* type) { SetType(type); m_unknownType = FALSE; m_pFile = NULL; m_start = 0; m_end = 0; m_size = 0; m_pParentAtom = NULL; m_depth = 0xFF;}MP4Atom::~MP4Atom(){ u_int32_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(const char* type){ MP4Atom* pAtom = NULL; if (type == NULL) { pAtom = new MP4RootAtom(); } else { switch((uint8_t)type[0]) { case 'a': if (ATOMID(type) == ATOMID("avc1")) { pAtom = new MP4Avc1Atom(); } else if (ATOMID(type) == ATOMID("avcC")) { pAtom = new MP4AvcCAtom(); } else if (ATOMID(type) == ATOMID("alis")) { pAtom = new MP4UrlAtom("alis"); } else if (ATOMID(type) == ATOMID("alaw")) { pAtom = new MP4SoundAtom(type); } else if (ATOMID(type) == ATOMID("alac")) { pAtom = new MP4SoundAtom(type); } break; case 'd': if (ATOMID(type) == ATOMID("d263")) { pAtom = new MP4D263Atom(); } else if (ATOMID(type) == ATOMID("damr")) { pAtom = new MP4DamrAtom(); } else if (ATOMID(type) == ATOMID("dref")) { pAtom = new MP4DrefAtom(); } else if (ATOMID(type) == ATOMID("dpnd")) { pAtom = new MP4TrefTypeAtom(type); } else if (ATOMID(type) == ATOMID("data")) { /* Apple iTunes */ pAtom = new MP4DataAtom(); } break; case 'e': if (ATOMID(type) == ATOMID("elst")) { pAtom = new MP4ElstAtom(); } else if (ATOMID(type) == ATOMID("enca")) { pAtom = new MP4EncaAtom(); } else if (ATOMID(type) == ATOMID("encv")) { pAtom = new MP4EncvAtom(); } break; case 'f': if (ATOMID(type) == ATOMID("free")) { pAtom = new MP4FreeAtom(); } else if (ATOMID(type) == ATOMID("ftyp")) { pAtom = new MP4FtypAtom(); } break; case 'h': if (ATOMID(type) == ATOMID("hdlr")) { pAtom = new MP4HdlrAtom(); } else if (ATOMID(type) == ATOMID("hint")) { pAtom = new MP4TrefTypeAtom(type); } else if (ATOMID(type) == ATOMID("hnti")) { pAtom = new MP4HntiAtom(); } else if (ATOMID(type) == ATOMID("hinf")) { pAtom = new MP4HinfAtom(); } else if (ATOMID(type) == ATOMID("h263")) { pAtom = new MP4VideoAtom("h263"); } else if (ATOMID(type) == ATOMID("href")) { pAtom = new MP4HrefAtom(); } break; case 'i': if (ATOMID(type) == ATOMID("ipir")) { pAtom = new MP4TrefTypeAtom(type); } else if (ATOMID(type) == ATOMID("ima4")) { pAtom = new MP4SoundAtom("ima4"); } break; case 'j': if (ATOMID(type) == ATOMID("jpeg")) { pAtom = new MP4VideoAtom("jpeg"); } break; case 'm': if (ATOMID(type) == ATOMID("mdhd")) { pAtom = new MP4MdhdAtom(); } else if (ATOMID(type) == ATOMID("mvhd")) { pAtom = new MP4MvhdAtom(); } else if (ATOMID(type) == ATOMID("mdat")) { pAtom = new MP4MdatAtom(); } else if (ATOMID(type) == ATOMID("mpod")) { pAtom = new MP4TrefTypeAtom(type); } else if (ATOMID(type) == ATOMID("mp4a")) { pAtom = new MP4SoundAtom("mp4a"); } else if (ATOMID(type) == ATOMID("mp4s")) { pAtom = new MP4Mp4sAtom(); } else if (ATOMID(type) == ATOMID("mp4v")) { pAtom = new MP4Mp4vAtom(); } else if (ATOMID(type) == ATOMID("mean")) { // iTunes pAtom = new MP4Meta1Atom(type); } break; case 'n': if (ATOMID(type) == ATOMID("name")) { // iTunes pAtom = new MP4Meta1Atom(type); } break; case 'o': if (ATOMID(type) == ATOMID("ohdr")) { pAtom = new MP4OhdrAtom(); } break; case 'r': if (ATOMID(type) == ATOMID("rtp ")) { pAtom = new MP4RtpAtom(); } else if (ATOMID(type) == ATOMID("raw ")) { pAtom = new MP4VideoAtom("raw "); } break; case 's': if (ATOMID(type) == ATOMID("s263")) { pAtom = new MP4S263Atom(); } else if (ATOMID(type) == ATOMID("samr")) { pAtom = new MP4AmrAtom("samr"); } else if (ATOMID(type) == ATOMID("sawb")) { pAtom = new MP4AmrAtom("sawb"); } else if (ATOMID(type) == ATOMID("stbl")) { pAtom = new MP4StblAtom(); } else if (ATOMID(type) == ATOMID("stsd")) { pAtom = new MP4StsdAtom(); } else if (ATOMID(type) == ATOMID("stsz")) { pAtom = new MP4StszAtom(); } else if (ATOMID(type) == ATOMID("stsc")) { pAtom = new MP4StscAtom(); } else if (ATOMID(type) == ATOMID("stdp")) { pAtom = new MP4StdpAtom(); } else if (ATOMID(type) == ATOMID("sdp ")) { pAtom = new MP4SdpAtom(); } else if (ATOMID(type) == ATOMID("sync")) { pAtom = new MP4TrefTypeAtom(type); } else if (ATOMID(type) == ATOMID("skip")) { pAtom = new MP4FreeAtom(); pAtom->SetType("skip"); } else if (ATOMID(type) == ATOMID("sowt")) { pAtom = new MP4SoundAtom("sowt"); } break; case 't': if (ATOMID(type) == ATOMID("tkhd")) { pAtom = new MP4TkhdAtom(); } else if (ATOMID(type) == ATOMID("tfhd")) { pAtom = new MP4TfhdAtom(); } else if (ATOMID(type) == ATOMID("trun")) { pAtom = new MP4TrunAtom(); } else if (ATOMID(type) == ATOMID("twos")) { pAtom = new MP4SoundAtom("twos"); } break; case 'u': if (ATOMID(type) == ATOMID("udta")) { pAtom = new MP4UdtaAtom(); } else if (ATOMID(type) == ATOMID("url ")) { pAtom = new MP4UrlAtom(); } else if (ATOMID(type) == ATOMID("urn ")) { pAtom = new MP4UrnAtom(); } else if (ATOMID(type) == ATOMID("ulaw")) { pAtom = new MP4SoundAtom("ulaw"); } break; case 'v': if (ATOMID(type) == ATOMID("vmhd")) { pAtom = new MP4VmhdAtom(); } break; case 'y': if (ATOMID(type) == ATOMID("yuv2")) { pAtom = new MP4VideoAtom("yuv2"); } break; case 'S': if (ATOMID(type) == ATOMID("SVQ3")) { pAtom = new MP4VideoAtom("SVQ3"); } else if (ATOMID(type) == ATOMID("SMI ")) { pAtom = new MP4SmiAtom(); } break; case 0251: static const char name[5]={0251,'n', 'a', 'm', '\0'}; static const char cmt[5]={0251,'c', 'm', 't', '\0'}; static const char cpy[5]={0251,'c', 'p', 'y', '\0'}; static const char des[5]={0251,'d', 'e', 's','\0'}; static const char prd[5]={0251, 'p', 'r', 'd', '\0'}; if (ATOMID(type) == ATOMID(name) || ATOMID(type) == ATOMID(cmt) || ATOMID(type) == ATOMID(cpy) || ATOMID(type) == ATOMID(prd) || ATOMID(type) == ATOMID(des)) { pAtom = new MP4Meta2Atom(type); } break; } } if (pAtom == NULL) { pAtom = new MP4StandardAtom(type); // unknown type is set by StandardAtom type } ASSERT(pAtom); return pAtom;}// generate a skeletal selfvoid MP4Atom::Generate(){ u_int32_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_pChildAtomInfos[i]->m_name); AddChildAtom(pChildAtom); // and ask it to self generate pChildAtom->Generate(); } }}MP4Atom* MP4Atom::ReadAtom(MP4File* pFile, MP4Atom* pParentAtom){ u_int8_t hdrSize = 8; u_int8_t extendedType[16]; u_int64_t pos = pFile->GetPosition(); VERBOSE_READ(pFile->GetVerbosity(), printf("ReadAtom: pos = 0x"X64"\n", pos)); u_int64_t dataSize = pFile->ReadUInt32();//printf("\n[MP4Atom::ReadAtom] datasize = %u", (unsigned int) dataSize); char type[5]; pFile->ReadBytes((u_int8_t*)&type[0], 4); type[4] = '\0'; // extended size if (dataSize == 1) { dataSize = pFile->ReadUInt64(); hdrSize += 8; pFile->Check64BitStatus(type); } // extended type if (ATOMID(type) == ATOMID("uuid")) { pFile->ReadBytes(extendedType, sizeof(extendedType)); hdrSize += sizeof(extendedType); } if (dataSize == 0) { // extends to EOF dataSize = pFile->GetSize() - pos; } dataSize -= hdrSize; VERBOSE_READ(pFile->GetVerbosity(), printf("ReadAtom: type = \"%s\" data-size = "U64" (0x"X64") hdr %u\n", type, dataSize, dataSize, hdrSize)); if (pos + hdrSize + dataSize > pParentAtom->GetEnd()) { VERBOSE_ERROR(pFile->GetVerbosity(), printf("ReadAtom: invalid atom size, extends outside parent atom - skipping to end of \"%s\" \"%s\" "U64" vs "U64"\n", pParentAtom->GetType(), type, pos + hdrSize + dataSize, pParentAtom->GetEnd())); VERBOSE_READ(pFile->GetVerbosity(), printf("parent %s ("U64") pos "U64" hdr %d data "U64" sum "U64"\n", pParentAtom->GetType(), pParentAtom->GetEnd(), pos, hdrSize, dataSize, pos + hdrSize + dataSize));#if 0 throw new MP4Error("invalid atom size", "ReadAtom");#else // skip to end of atom dataSize = pParentAtom->GetEnd() - pos - hdrSize;#endif } MP4Atom* pAtom = CreateAtom(type); pAtom->SetFile(pFile); pAtom->SetStart(pos); pAtom->SetEnd(pos + hdrSize + dataSize); pAtom->SetSize(dataSize); if (ATOMID(type) == ATOMID("uuid")) { pAtom->SetExtendedType(extendedType); } if (pAtom->IsUnknownType()) { if (!IsReasonableType(pAtom->GetType())) { VERBOSE_READ(pFile->GetVerbosity(), printf("Warning: atom type %s is suspect\n", pAtom->GetType())); } else { VERBOSE_READ(pFile->GetVerbosity(), printf("Info: atom type %s is unknown\n", pAtom->GetType())); } if (dataSize > 0) { pAtom->AddProperty( new MP4BytesProperty("data", dataSize)); } } pAtom->SetParentAtom(pParentAtom); pAtom->Read(); return pAtom;}bool MP4Atom::IsReasonableType(const char* type){ for (u_int8_t i = 0; i < 4; i++) { if (isalnum(type[i])) { continue; } if (i == 3 && type[i] == ' ') { continue; } return false; } return true;}// generic readvoid MP4Atom::Read(){ ASSERT(m_pFile); if (ATOMID(m_type) != 0 && m_size > 1000000) { VERBOSE_READ(GetVerbosity(), printf("Warning: %s atom size "U64" is suspect\n", 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_pFile->GetPosition() != m_end) { VERBOSE_READ(m_pFile->GetVerbosity(), printf("Skip: "U64" bytes\n", m_end - m_pFile->GetPosition())); } m_pFile->SetPosition(m_end);}MP4Atom* MP4Atom::FindAtom(const char* name){ if (!IsMe(name)) { return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -