mp4atom.cpp
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:20k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is MPEG4IP.
  13.  * 
  14.  * The Initial Developer of the Original Code is Cisco Systems Inc.
  15.  * Portions created by Cisco Systems Inc. are
  16.  * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
  17.  * 
  18.  * Contributor(s): 
  19.  * Dave Mackie dmackie@cisco.com
  20.  */
  21. #include "mp4common.h"
  22. #include "atoms.h"
  23. MP4AtomInfo::MP4AtomInfo(const char* name, bool mandatory, bool onlyOne) 
  24. {
  25. m_name = name;
  26. m_mandatory = mandatory;
  27. m_onlyOne = onlyOne;
  28. m_count = 0;
  29. }
  30. MP4Atom::MP4Atom(const char* type) 
  31. {
  32. SetType(type);
  33. m_unknownType = FALSE;
  34. m_pFile = NULL;
  35. m_start = 0;
  36. m_end = 0;
  37. m_size = 0;
  38. m_pParentAtom = NULL;
  39. m_depth = 0xFF;
  40. }
  41. MP4Atom::~MP4Atom()
  42. {
  43. u_int32_t i;
  44. for (i = 0; i < m_pProperties.Size(); i++) {
  45. delete m_pProperties[i];
  46. }
  47. for (i = 0; i < m_pChildAtomInfos.Size(); i++) {
  48. delete m_pChildAtomInfos[i];
  49. }
  50. for (i = 0; i < m_pChildAtoms.Size(); i++) {
  51. delete m_pChildAtoms[i];
  52. }
  53. }
  54. MP4Atom* MP4Atom::CreateAtom(const char* type)
  55. {
  56. MP4Atom* pAtom = NULL;
  57. if (type == NULL) {
  58. pAtom = new MP4RootAtom();
  59. } else if (type[0] == 'c') {
  60. if (ATOMID(type) == ATOMID("ctts")) {
  61. pAtom = new MP4CttsAtom();
  62. } else if (ATOMID(type) == ATOMID("co64")) {
  63. pAtom = new MP4Co64Atom();
  64. } else if (ATOMID(type) == ATOMID("cprt")) {
  65. pAtom = new MP4CprtAtom();
  66. }
  67. } else if (type[0] == 'd') {
  68. if (ATOMID(type) == ATOMID("dinf")) {
  69. pAtom = new MP4DinfAtom();
  70. } else if (ATOMID(type) == ATOMID("dref")) {
  71. pAtom = new MP4DrefAtom();
  72. } else if (ATOMID(type) == ATOMID("dpnd")) {
  73. pAtom = new MP4TrefTypeAtom(type);
  74. } else if (ATOMID(type) == ATOMID("dmed")) {
  75. pAtom = new MP4DmedAtom();
  76. } else if (ATOMID(type) == ATOMID("dimm")) {
  77. pAtom = new MP4DimmAtom();
  78. } else if (ATOMID(type) == ATOMID("drep")) {
  79. pAtom = new MP4DrepAtom();
  80. } else if (ATOMID(type) == ATOMID("dmax")) {
  81. pAtom = new MP4DmaxAtom();
  82. }
  83. } else if (type[0] == 'e') {
  84. if (ATOMID(type) == ATOMID("esds")) {
  85. pAtom = new MP4EsdsAtom();
  86. } else if (ATOMID(type) == ATOMID("edts")) {
  87. pAtom = new MP4EdtsAtom();
  88. } else if (ATOMID(type) == ATOMID("elst")) {
  89. pAtom = new MP4ElstAtom();
  90. }
  91. } else if (type[0] == 'h') {
  92. if (ATOMID(type) == ATOMID("hdlr")) {
  93. pAtom = new MP4HdlrAtom();
  94. } else if (ATOMID(type) == ATOMID("hmhd")) {
  95. pAtom = new MP4HmhdAtom();
  96. } else if (ATOMID(type) == ATOMID("hint")) {
  97. pAtom = new MP4TrefTypeAtom(type);
  98. } else if (ATOMID(type) == ATOMID("hnti")) {
  99. pAtom = new MP4HntiAtom();
  100. } else if (ATOMID(type) == ATOMID("hinf")) {
  101. pAtom = new MP4HinfAtom();
  102. }
  103. } else if (type[0] == 'm') {
  104. if (ATOMID(type) == ATOMID("mdia")) {
  105. pAtom = new MP4MdiaAtom();
  106. } else if (ATOMID(type) == ATOMID("minf")) {
  107. pAtom = new MP4MinfAtom();
  108. } else if (ATOMID(type) == ATOMID("mdhd")) {
  109. pAtom = new MP4MdhdAtom();
  110. } else if (ATOMID(type) == ATOMID("mdat")) {
  111. pAtom = new MP4MdatAtom();
  112. } else if (ATOMID(type) == ATOMID("moov")) {
  113. pAtom = new MP4MoovAtom();
  114. } else if (ATOMID(type) == ATOMID("mvhd")) {
  115. pAtom = new MP4MvhdAtom();
  116. } else if (ATOMID(type) == ATOMID("mpod")) {
  117. pAtom = new MP4TrefTypeAtom(type);
  118. } else if (ATOMID(type) == ATOMID("mp4a")) {
  119. pAtom = new MP4Mp4aAtom();
  120. } else if (ATOMID(type) == ATOMID("mp4s")) {
  121. pAtom = new MP4Mp4sAtom();
  122. } else if (ATOMID(type) == ATOMID("mp4v")) {
  123. pAtom = new MP4Mp4vAtom();
  124. } else if (ATOMID(type) == ATOMID("moof")) {
  125. pAtom = new MP4MoofAtom();
  126. } else if (ATOMID(type) == ATOMID("mfhd")) {
  127. pAtom = new MP4MfhdAtom();
  128. } else if (ATOMID(type) == ATOMID("mvex")) {
  129. pAtom = new MP4MvexAtom();
  130. } else if (ATOMID(type) == ATOMID("maxr")) {
  131. pAtom = new MP4MaxrAtom();
  132. }
  133. } else if (type[0] == 's') {
  134. if (ATOMID(type) == ATOMID("stbl")) {
  135. pAtom = new MP4StblAtom();
  136. } else if (ATOMID(type) == ATOMID("stsd")) {
  137. pAtom = new MP4StsdAtom();
  138. } else if (ATOMID(type) == ATOMID("stts")) {
  139. pAtom = new MP4SttsAtom();
  140. } else if (ATOMID(type) == ATOMID("stsz")) {
  141. pAtom = new MP4StszAtom();
  142. } else if (ATOMID(type) == ATOMID("stsc")) {
  143. pAtom = new MP4StscAtom();
  144. } else if (ATOMID(type) == ATOMID("stco")) {
  145. pAtom = new MP4StcoAtom();
  146. } else if (ATOMID(type) == ATOMID("stss")) {
  147. pAtom = new MP4StssAtom();
  148. } else if (ATOMID(type) == ATOMID("stsh")) {
  149. pAtom = new MP4StshAtom();
  150. } else if (ATOMID(type) == ATOMID("stdp")) {
  151. pAtom = new MP4StdpAtom();
  152. } else if (ATOMID(type) == ATOMID("smhd")) {
  153. pAtom = new MP4SmhdAtom();
  154. } else if (ATOMID(type) == ATOMID("sdp ")) {
  155. pAtom = new MP4SdpAtom();
  156. } else if (ATOMID(type) == ATOMID("snro")) {
  157. pAtom = new MP4SnroAtom();
  158. } else if (ATOMID(type) == ATOMID("sync")) {
  159. pAtom = new MP4TrefTypeAtom(type);
  160. } else if (ATOMID(type) == ATOMID("skip")) {
  161. pAtom = new MP4FreeAtom();
  162. pAtom->SetType("skip");
  163. }
  164. } else if (type[0] == 't') {
  165. if (ATOMID(type) == ATOMID("trak")) {
  166. pAtom = new MP4TrakAtom();
  167. } else if (ATOMID(type) == ATOMID("tkhd")) {
  168. pAtom = new MP4TkhdAtom();
  169. } else if (ATOMID(type) == ATOMID("tref")) {
  170. pAtom = new MP4TrefAtom();
  171. } else if (ATOMID(type) == ATOMID("traf")) {
  172. pAtom = new MP4TrafAtom();
  173. } else if (ATOMID(type) == ATOMID("tfhd")) {
  174. pAtom = new MP4TfhdAtom();
  175. } else if (ATOMID(type) == ATOMID("trex")) {
  176. pAtom = new MP4TrexAtom();
  177. } else if (ATOMID(type) == ATOMID("trun")) {
  178. pAtom = new MP4TrunAtom();
  179. } else if (ATOMID(type) == ATOMID("tmin")) {
  180. pAtom = new MP4TminAtom();
  181. } else if (ATOMID(type) == ATOMID("tmax")) {
  182. pAtom = new MP4TmaxAtom();
  183. } else if (ATOMID(type) == ATOMID("trpy")) {
  184. pAtom = new MP4TrpyAtom();
  185. } else if (ATOMID(type) == ATOMID("tpyl")) {
  186. pAtom = new MP4TpylAtom();
  187. } else if (ATOMID(type) == ATOMID("tims")) {
  188. pAtom = new MP4TimsAtom();
  189. } else if (ATOMID(type) == ATOMID("tsro")) {
  190. pAtom = new MP4TsroAtom();
  191. }
  192. } else if (type[0] == 'u') {
  193. if (ATOMID(type) == ATOMID("udta")) {
  194. pAtom = new MP4UdtaAtom();
  195. } else if (ATOMID(type) == ATOMID("url ")) {
  196. pAtom = new MP4UrlAtom();
  197. } else if (ATOMID(type) == ATOMID("urn ")) {
  198. pAtom = new MP4UrnAtom();
  199. }
  200. } else {
  201. if (ATOMID(type) == ATOMID("free")) {
  202. pAtom = new MP4FreeAtom();
  203. } else if (ATOMID(type) == ATOMID("ftyp")) {
  204. pAtom = new MP4FtypAtom();
  205. } else if (ATOMID(type) == ATOMID("iods")) {
  206. pAtom = new MP4IodsAtom();
  207. } else if (ATOMID(type) == ATOMID("ipir")) {
  208. pAtom = new MP4TrefTypeAtom(type);
  209. } else if (ATOMID(type) == ATOMID("nmhd")) {
  210. pAtom = new MP4NmhdAtom();
  211. } else if (ATOMID(type) == ATOMID("nump")) {
  212. pAtom = new MP4NumpAtom();
  213. } else if (ATOMID(type) == ATOMID("pmax")) {
  214. pAtom = new MP4PmaxAtom();
  215. } else if (ATOMID(type) == ATOMID("payt")) {
  216. pAtom = new MP4PaytAtom();
  217. } else if (ATOMID(type) == ATOMID("rtp ")) {
  218. pAtom = new MP4RtpAtom();
  219. } else if (ATOMID(type) == ATOMID("vmhd")) {
  220. pAtom = new MP4VmhdAtom();
  221. }
  222. }
  223. if (pAtom == NULL) {
  224. pAtom = new MP4Atom(type);
  225. pAtom->SetUnknownType(true);
  226. }
  227. ASSERT(pAtom);
  228. return pAtom;
  229. }
  230. // generate a skeletal self
  231. void MP4Atom::Generate()
  232. {
  233. u_int32_t i;
  234. // for all properties
  235. for (i = 0; i < m_pProperties.Size(); i++) {
  236. // ask it to self generate
  237. m_pProperties[i]->Generate();
  238. }
  239. // for all mandatory, single child atom types
  240. for (i = 0; i < m_pChildAtomInfos.Size(); i++) {
  241. if (m_pChildAtomInfos[i]->m_mandatory
  242.   && m_pChildAtomInfos[i]->m_onlyOne) {
  243. // create the mandatory, single child atom
  244. MP4Atom* pChildAtom = 
  245. CreateAtom(m_pChildAtomInfos[i]->m_name);
  246. AddChildAtom(pChildAtom);
  247. // and ask it to self generate
  248. pChildAtom->Generate();
  249. }
  250. }
  251. }
  252. MP4Atom* MP4Atom::ReadAtom(MP4File* pFile, MP4Atom* pParentAtom)
  253. {
  254. u_int8_t hdrSize = 8;
  255. u_int8_t extendedType[16];
  256. u_int64_t pos = pFile->GetPosition();
  257. VERBOSE_READ(pFile->GetVerbosity(), 
  258. printf("ReadAtom: pos = 0x"LLX"n", pos));
  259. u_int64_t dataSize = pFile->ReadUInt32();
  260. if (dataSize == 1) {
  261. dataSize = pFile->ReadUInt64(); 
  262. hdrSize += 8;
  263. }
  264. char type[5];
  265. pFile->ReadBytes((u_int8_t*)&type[0], 4);
  266. type[4] = '';
  267. // extended type
  268. if (ATOMID(type) == ATOMID("uuid")) {
  269. pFile->ReadBytes(extendedType, sizeof(extendedType));
  270. hdrSize += sizeof(extendedType);
  271. }
  272. if (dataSize == 0) {
  273. // extends to EOF
  274. dataSize = pFile->GetSize() - pos;
  275. }
  276. dataSize -= hdrSize;
  277. VERBOSE_READ(pFile->GetVerbosity(), 
  278. printf("ReadAtom: type = %s data-size = "LLU" (0x"LLX")n", 
  279. type, dataSize, dataSize));
  280. if (pos + hdrSize + dataSize > pParentAtom->GetEnd()) {
  281. VERBOSE_READ(pFile->GetVerbosity(), 
  282. printf("ReadAtom: invalid atom size, extends outside parent atomn"));
  283. throw new MP4Error("invalid atom size", "ReadAtom");
  284. }
  285. MP4Atom* pAtom = CreateAtom(type);
  286. pAtom->SetFile(pFile);
  287. pAtom->SetStart(pos);
  288. pAtom->SetEnd(pos + hdrSize + dataSize);
  289. pAtom->SetSize(dataSize);
  290. if (ATOMID(type) == ATOMID("uuid")) {
  291. pAtom->SetExtendedType(extendedType);
  292. }
  293. if (pAtom->IsUnknownType()) {
  294. if (!IsReasonableType(pAtom->GetType())) {
  295. VERBOSE_READ(pFile->GetVerbosity(),
  296. printf("Warning: atom type %s is suspectn", pAtom->GetType()));
  297. } else {
  298. VERBOSE_READ(pFile->GetVerbosity(),
  299. printf("Info: atom type %s is unknownn", pAtom->GetType()));
  300. }
  301. if (dataSize > 0) {
  302. pAtom->AddProperty(
  303. new MP4BytesProperty("data", dataSize));
  304. }
  305. }
  306. pAtom->SetParentAtom(pParentAtom);
  307. pAtom->Read();
  308. return pAtom;
  309. }
  310. bool MP4Atom::IsReasonableType(const char* type)
  311. {
  312. for (u_int8_t i = 0; i < 4; i++) {
  313. if (isalnum(type[i])) {
  314. continue;
  315. }
  316. if (i == 3 && type[i] == ' ') {
  317. continue;
  318. }
  319. return false;
  320. }
  321. return true;
  322. }
  323. // generic read
  324. void MP4Atom::Read()
  325. {
  326. ASSERT(m_pFile);
  327. if (ATOMID(m_type) != 0 && m_size > 1000000) {
  328. VERBOSE_READ(GetVerbosity(), 
  329. printf("Warning: %s atom size "LLU" is suspectn",
  330. m_type, m_size));
  331. }
  332. ReadProperties();
  333. // read child atoms, if we expect there to be some
  334. if (m_pChildAtomInfos.Size() > 0) {
  335. ReadChildAtoms();
  336. }
  337. Skip(); // to end of atom
  338. }
  339. void MP4Atom::Skip()
  340. {
  341. if (m_pFile->GetPosition() != m_end) {
  342. VERBOSE_READ(m_pFile->GetVerbosity(),
  343. printf("Skip: "LLU" bytesn", m_end - m_pFile->GetPosition()));
  344. }
  345. m_pFile->SetPosition(m_end);
  346. }
  347. MP4Atom* MP4Atom::FindAtom(const char* name)
  348. {
  349. if (!IsMe(name)) {
  350. return NULL;
  351. }
  352. if (!IsRootAtom()) {
  353. VERBOSE_FIND(m_pFile->GetVerbosity(),
  354. printf("FindAtom: matched %sn", name));
  355. name = MP4NameAfterFirst(name);
  356. // I'm the sought after atom 
  357. if (name == NULL) {
  358. return this;
  359. }
  360. }
  361. // else it's one of my children
  362. return FindChildAtom(name);
  363. }
  364. bool MP4Atom::FindProperty(const char *name, 
  365. MP4Property** ppProperty, u_int32_t* pIndex)
  366. {
  367. if (!IsMe(name)) {
  368. return false;
  369. }
  370. if (!IsRootAtom()) {
  371. VERBOSE_FIND(m_pFile->GetVerbosity(),
  372. printf("FindProperty: matched %sn", name));
  373. name = MP4NameAfterFirst(name);
  374. // no property name given
  375. if (name == NULL) {
  376. return false;
  377. }
  378. }
  379. return FindContainedProperty(name, ppProperty, pIndex);
  380. }
  381. bool MP4Atom::IsMe(const char* name)
  382. {
  383. if (name == NULL) {
  384. return false;
  385. }
  386. // root atom always matches
  387. if (!strcmp(m_type, "")) {
  388. return true;
  389. }
  390. // check if our atom name is specified as the first component
  391. if (!MP4NameFirstMatches(m_type, name)) {
  392. return false;
  393. }
  394. return true;
  395. }
  396. MP4Atom* MP4Atom::FindChildAtom(const char* name)
  397. {
  398. u_int32_t atomIndex = 0;
  399. // get the index if we have one, e.g. moov.trak[2].mdia...
  400. MP4NameFirstIndex(name, &atomIndex);
  401. // need to get to the index'th child atom of the right type
  402. for (u_int32_t i = 0; i < m_pChildAtoms.Size(); i++) {
  403. if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) {
  404. if (atomIndex == 0) {
  405. // this is the one, ask it to match
  406. return m_pChildAtoms[i]->FindAtom(name);
  407. }
  408. atomIndex--;
  409. }
  410. }
  411. return NULL;
  412. }
  413. bool MP4Atom::FindContainedProperty(const char *name,
  414. MP4Property** ppProperty, u_int32_t* pIndex)
  415. {
  416. u_int32_t numProperties = m_pProperties.Size();
  417. u_int32_t i;
  418. // check all of our properties
  419. for (i = 0; i < numProperties; i++) {
  420. if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) {
  421. return true;
  422. }
  423. }
  424. // not one of our properties, 
  425. // presumably one of our children's properties
  426. // check child atoms...
  427. // check if we have an index, e.g. trak[2].mdia...
  428. u_int32_t atomIndex = 0;
  429. MP4NameFirstIndex(name, &atomIndex);
  430. // need to get to the index'th child atom of the right type
  431. for (i = 0; i < m_pChildAtoms.Size(); i++) {
  432. if (MP4NameFirstMatches(m_pChildAtoms[i]->GetType(), name)) {
  433. if (atomIndex == 0) {
  434. // this is the one, ask it to match
  435. return m_pChildAtoms[i]->FindProperty(name, ppProperty, pIndex);
  436. }
  437. atomIndex--;
  438. }
  439. }
  440. VERBOSE_FIND(m_pFile->GetVerbosity(),
  441. printf("FindProperty: no match for %sn", name));
  442. return false;
  443. }
  444. void MP4Atom::ReadProperties(u_int32_t startIndex, u_int32_t count)
  445. {
  446. u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex);
  447. // read any properties of the atom
  448. for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) {
  449. m_pProperties[i]->Read(m_pFile);
  450. if (m_pFile->GetPosition() > m_end) {
  451. VERBOSE_READ(GetVerbosity(), 
  452. printf("ReadProperties: insufficient data for property: %s pos 0x"LLX" atom end 0x"LLX"n",
  453. m_pProperties[i]->GetName(), 
  454. m_pFile->GetPosition(), m_end)); 
  455. throw new MP4Error("atom is too small", "Atom ReadProperties");
  456. }
  457. if (m_pProperties[i]->GetType() == TableProperty) {
  458. VERBOSE_READ_TABLE(GetVerbosity(), 
  459. printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true));
  460. } else if (m_pProperties[i]->GetType() != DescriptorProperty) {
  461. VERBOSE_READ(GetVerbosity(), 
  462. printf("Read: "); m_pProperties[i]->Dump(stdout, 0, true));
  463. }
  464. }
  465. }
  466. void MP4Atom::ReadChildAtoms()
  467. {
  468. VERBOSE_READ(GetVerbosity(), 
  469. printf("ReadChildAtoms: of %sn", m_type[0] ? m_type : "root"));
  470. // read any child atoms
  471. while (m_pFile->GetPosition() < m_end) {
  472. MP4Atom* pChildAtom = MP4Atom::ReadAtom(m_pFile, this);
  473. AddChildAtom(pChildAtom);
  474. MP4AtomInfo* pChildAtomInfo = FindAtomInfo(pChildAtom->GetType());
  475. // if child atom is of known type
  476. // but not expected here print warning
  477. if (pChildAtomInfo == NULL && !pChildAtom->IsUnknownType()) {
  478. VERBOSE_READ(GetVerbosity(),
  479. printf("Warning: In atom %s unexpected child atom %sn",
  480. GetType(), pChildAtom->GetType()));
  481. }
  482. // if child atoms should have just one instance
  483. // and this is more than one, print warning
  484. if (pChildAtomInfo) {
  485. pChildAtomInfo->m_count++;
  486. if (pChildAtomInfo->m_onlyOne && pChildAtomInfo->m_count > 1) {
  487. VERBOSE_READ(GetVerbosity(),
  488. printf("Warning: In atom %s multiple child atoms %sn",
  489. GetType(), pChildAtom->GetType()));
  490. }
  491. }
  492. }
  493. // if mandatory child atom doesn't exist, print warning
  494. u_int32_t numAtomInfo = m_pChildAtomInfos.Size();
  495. for (u_int32_t i = 0; i < numAtomInfo; i++) {
  496. if (m_pChildAtomInfos[i]->m_mandatory
  497.   && m_pChildAtomInfos[i]->m_count == 0) {
  498. VERBOSE_READ(GetVerbosity(),
  499. printf("Warning: In atom %s missing child atom %sn",
  500. GetType(), m_pChildAtomInfos[i]->m_name));
  501. }
  502. }
  503. VERBOSE_READ(GetVerbosity(), 
  504. printf("ReadChildAtoms: finished %sn", m_type));
  505. }
  506. MP4AtomInfo* MP4Atom::FindAtomInfo(const char* name)
  507. {
  508. u_int32_t numAtomInfo = m_pChildAtomInfos.Size();
  509. for (u_int32_t i = 0; i < numAtomInfo; i++) {
  510. if (ATOMID(m_pChildAtomInfos[i]->m_name) == ATOMID(name)) {
  511. return m_pChildAtomInfos[i];
  512. }
  513. }
  514. return NULL;
  515. }
  516. // generic write
  517. void MP4Atom::Write()
  518. {
  519. ASSERT(m_pFile);
  520. BeginWrite();
  521. WriteProperties();
  522. WriteChildAtoms();
  523. FinishWrite();
  524. }
  525. void MP4Atom::BeginWrite(bool use64)
  526. {
  527. m_start = m_pFile->GetPosition();
  528. if (use64) {
  529. m_pFile->WriteUInt32(1);
  530. m_pFile->WriteUInt64(0);
  531. } else {
  532. m_pFile->WriteUInt32(0);
  533. }
  534. m_pFile->WriteBytes((u_int8_t*)&m_type[0], 4);
  535. if (ATOMID(m_type) == ATOMID("uuid")) {
  536. m_pFile->WriteBytes(m_extendedType, sizeof(m_extendedType));
  537. }
  538. }
  539. void MP4Atom::FinishWrite(bool use64)
  540. {
  541. m_end = m_pFile->GetPosition();
  542. m_size = (m_end - m_start);
  543. if (use64) {
  544. m_pFile->SetPosition(m_start + 4);
  545. m_pFile->WriteUInt64(m_size);
  546. } else {
  547. ASSERT(m_size <= (u_int64_t)0xFFFFFFFF);
  548. m_pFile->SetPosition(m_start);
  549. m_pFile->WriteUInt32(m_size);
  550. }
  551. m_pFile->SetPosition(m_end);
  552. // adjust size to just reflect data portion of atom
  553. m_size -= (use64 ? 16 : 8);
  554. if (ATOMID(m_type) == ATOMID("uuid")) {
  555. m_size -= sizeof(m_extendedType);
  556. }
  557. }
  558. void MP4Atom::WriteProperties(u_int32_t startIndex, u_int32_t count)
  559. {
  560. u_int32_t numProperties = MIN(count, m_pProperties.Size() - startIndex);
  561. VERBOSE_WRITE(GetVerbosity(), 
  562. printf("Write: type %sn", m_type));
  563. for (u_int32_t i = startIndex; i < startIndex + numProperties; i++) {
  564. m_pProperties[i]->Write(m_pFile);
  565. if (m_pProperties[i]->GetType() == TableProperty) {
  566. VERBOSE_WRITE_TABLE(GetVerbosity(), 
  567. printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false));
  568. } else {
  569. VERBOSE_WRITE(GetVerbosity(), 
  570. printf("Write: "); m_pProperties[i]->Dump(stdout, 0, false));
  571. }
  572. }
  573. }
  574. void MP4Atom::WriteChildAtoms()
  575. {
  576. u_int32_t size = m_pChildAtoms.Size();
  577. for (u_int32_t i = 0; i < size; i++) {
  578. m_pChildAtoms[i]->Write();
  579. }
  580. VERBOSE_WRITE(GetVerbosity(), 
  581. printf("Write: finished %sn", m_type));
  582. }
  583. void MP4Atom::AddProperty(MP4Property* pProperty) 
  584. {
  585. ASSERT(pProperty);
  586. m_pProperties.Add(pProperty);
  587. pProperty->SetParentAtom(this);
  588. }
  589. void MP4Atom::AddVersionAndFlags()
  590. {
  591. AddProperty(new MP4Integer8Property("version"));
  592. AddProperty(new MP4Integer24Property("flags"));
  593. }
  594. void MP4Atom::AddReserved(char* name, u_int32_t size) 
  595. {
  596. MP4BytesProperty* pReserved = new MP4BytesProperty(name, size); 
  597. pReserved->SetReadOnly();
  598. AddProperty(pReserved);
  599. }
  600. void MP4Atom::ExpectChildAtom(const char* name, bool mandatory, bool onlyOne)
  601. {
  602. m_pChildAtomInfos.Add(new MP4AtomInfo(name, mandatory, onlyOne));
  603. }
  604. u_int8_t MP4Atom::GetVersion()
  605. {
  606. if (strcmp("version", m_pProperties[0]->GetName())) {
  607. return 0;
  608. }
  609. return ((MP4Integer8Property*)m_pProperties[0])->GetValue();
  610. }
  611. void MP4Atom::SetVersion(u_int8_t version) 
  612. {
  613. if (strcmp("version", m_pProperties[0]->GetName())) {
  614. return;
  615. }
  616. ((MP4Integer8Property*)m_pProperties[0])->SetValue(version);
  617. }
  618. u_int32_t MP4Atom::GetFlags()
  619. {
  620. if (strcmp("flags", m_pProperties[1]->GetName())) {
  621. return 0;
  622. }
  623. return ((MP4Integer24Property*)m_pProperties[1])->GetValue();
  624. }
  625. void MP4Atom::SetFlags(u_int32_t flags) 
  626. {
  627. if (strcmp("flags", m_pProperties[1]->GetName())) {
  628. return;
  629. }
  630. ((MP4Integer24Property*)m_pProperties[1])->SetValue(flags);
  631. }
  632. void MP4Atom::Dump(FILE* pFile, u_int8_t indent, bool dumpImplicits)
  633. {
  634. if (m_type[0] != '') {
  635. Indent(pFile, indent);
  636. fprintf(pFile, "type %sn", m_type);
  637. }
  638. u_int32_t i;
  639. u_int32_t size;
  640. // dump our properties
  641. size = m_pProperties.Size();
  642. for (i = 0; i < size; i++) {
  643. /* skip details of tables unless we're told to be verbose */
  644. if (m_pProperties[i]->GetType() == TableProperty
  645.   && !(GetVerbosity() & MP4_DETAILS_TABLE)) {
  646. Indent(pFile, indent + 1);
  647. fprintf(pFile, "<table entries suppressed>n");
  648. continue;
  649. }
  650. m_pProperties[i]->Dump(pFile, indent + 1, dumpImplicits);
  651. }
  652. // dump our children
  653. size = m_pChildAtoms.Size();
  654. for (i = 0; i < size; i++) {
  655. m_pChildAtoms[i]->Dump(pFile, indent + 1, dumpImplicits);
  656. }
  657. }
  658. u_int32_t MP4Atom::GetVerbosity() 
  659. {
  660. ASSERT(m_pFile);
  661. return m_pFile->GetVerbosity();
  662. }
  663. u_int8_t MP4Atom::GetDepth()
  664. {
  665. if (m_depth < 0xFF) {
  666. return m_depth;
  667. }
  668. MP4Atom *pAtom = this;
  669. m_depth = 0;
  670. while ((pAtom = pAtom->GetParentAtom()) != NULL) {
  671. m_depth++;
  672. ASSERT(m_depth < 255);
  673. }
  674. return m_depth;
  675. }