mp4property.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. MP4Property::MP4Property(const char* name)
  23. {
  24. m_name = name;
  25. m_pParentAtom = NULL;
  26. m_readOnly = false;
  27. m_implicit = false;
  28. }
  29. bool MP4Property::FindProperty(const char* name, 
  30. MP4Property** ppProperty, u_int32_t* pIndex) 
  31. {
  32. if (name == NULL) {
  33. return false;
  34. }
  35. if (!strcasecmp(m_name, name)) {
  36. if (m_pParentAtom) {
  37. VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(),
  38. printf("FindProperty: matched %sn", name));
  39. }
  40. *ppProperty = this;
  41. return true;
  42. }
  43. return false;
  44. }
  45. // Integer Property
  46. u_int64_t MP4IntegerProperty::GetValue(u_int32_t index)
  47. {
  48. switch (this->GetType()) {
  49. case Integer8Property:
  50. return ((MP4Integer8Property*)this)->GetValue(index);
  51. case Integer16Property:
  52. return ((MP4Integer16Property*)this)->GetValue(index);
  53. case Integer24Property:
  54. return ((MP4Integer24Property*)this)->GetValue(index);
  55. case Integer32Property:
  56. return ((MP4Integer32Property*)this)->GetValue(index);
  57. case Integer64Property:
  58. return ((MP4Integer64Property*)this)->GetValue(index);
  59. default:
  60. ASSERT(FALSE);
  61. }
  62. return (0);
  63. }
  64. void MP4IntegerProperty::SetValue(u_int64_t value, u_int32_t index)
  65. {
  66. switch (this->GetType()) {
  67. case Integer8Property:
  68. ((MP4Integer8Property*)this)->SetValue(value, index);
  69. break;
  70. case Integer16Property:
  71. ((MP4Integer16Property*)this)->SetValue(value, index);
  72. break;
  73. case Integer24Property:
  74. ((MP4Integer24Property*)this)->SetValue(value, index);
  75. break;
  76. case Integer32Property:
  77. ((MP4Integer32Property*)this)->SetValue(value, index);
  78. break;
  79. case Integer64Property:
  80. ((MP4Integer64Property*)this)->SetValue(value, index);
  81. break;
  82. default:
  83. ASSERT(FALSE);
  84. }
  85. }
  86. void MP4IntegerProperty::InsertValue(u_int64_t value, u_int32_t index)
  87. {
  88. switch (this->GetType()) {
  89. case Integer8Property:
  90. ((MP4Integer8Property*)this)->InsertValue(value, index);
  91. break;
  92. case Integer16Property:
  93. ((MP4Integer16Property*)this)->InsertValue(value, index);
  94. break;
  95. case Integer24Property:
  96. ((MP4Integer24Property*)this)->InsertValue(value, index);
  97. break;
  98. case Integer32Property:
  99. ((MP4Integer32Property*)this)->InsertValue(value, index);
  100. break;
  101. case Integer64Property:
  102. ((MP4Integer64Property*)this)->InsertValue(value, index);
  103. break;
  104. default:
  105. ASSERT(FALSE);
  106. }
  107. }
  108. void MP4IntegerProperty::DeleteValue(u_int32_t index)
  109. {
  110. switch (this->GetType()) {
  111. case Integer8Property:
  112. ((MP4Integer8Property*)this)->DeleteValue(index);
  113. break;
  114. case Integer16Property:
  115. ((MP4Integer16Property*)this)->DeleteValue(index);
  116. break;
  117. case Integer24Property:
  118. ((MP4Integer24Property*)this)->DeleteValue(index);
  119. break;
  120. case Integer32Property:
  121. ((MP4Integer32Property*)this)->DeleteValue(index);
  122. break;
  123. case Integer64Property:
  124. ((MP4Integer64Property*)this)->DeleteValue(index);
  125. break;
  126. default:
  127. ASSERT(FALSE);
  128. }
  129. }
  130. void MP4IntegerProperty::IncrementValue(int32_t increment, u_int32_t index)
  131. {
  132. SetValue(GetValue() + increment);
  133. }
  134. void MP4Integer8Property::Dump(FILE* pFile, u_int8_t indent,
  135. bool dumpImplicits, u_int32_t index)
  136. {
  137. if (m_implicit && !dumpImplicits) {
  138. return;
  139. }
  140. Indent(pFile, indent);
  141. fprintf(pFile, "%s = %u (0x%02x)n", 
  142. m_name, m_values[index], m_values[index]);
  143. }
  144. void MP4Integer16Property::Dump(FILE* pFile, u_int8_t indent,
  145. bool dumpImplicits, u_int32_t index)
  146. {
  147. if (m_implicit && !dumpImplicits) {
  148. return;
  149. }
  150. Indent(pFile, indent);
  151. fprintf(pFile, "%s = %u (0x%04x)n", 
  152. m_name, m_values[index], m_values[index]);
  153. }
  154. void MP4Integer24Property::Dump(FILE* pFile, u_int8_t indent,
  155. bool dumpImplicits, u_int32_t index)
  156. {
  157. if (m_implicit && !dumpImplicits) {
  158. return;
  159. }
  160. Indent(pFile, indent);
  161. fprintf(pFile, "%s = %u (0x%06x)n", 
  162. m_name, m_values[index], m_values[index]);
  163. }
  164. void MP4Integer32Property::Dump(FILE* pFile, u_int8_t indent,
  165. bool dumpImplicits, u_int32_t index)
  166. {
  167. if (m_implicit && !dumpImplicits) {
  168. return;
  169. }
  170. Indent(pFile, indent);
  171. fprintf(pFile, "%s = %u (0x%08x)n", 
  172. m_name, m_values[index], m_values[index]);
  173. }
  174. void MP4Integer64Property::Dump(FILE* pFile, u_int8_t indent,
  175. bool dumpImplicits, u_int32_t index)
  176. {
  177. if (m_implicit && !dumpImplicits) {
  178. return;
  179. }
  180. Indent(pFile, indent);
  181. fprintf(pFile, 
  182. #ifdef WIN32
  183. "%s = "LLU" (0x%016I64x)n", 
  184. #else
  185. "%s = "LLU" (0x%016llx)n", 
  186. #endif
  187. m_name, m_values[index], m_values[index]);
  188. }
  189. // MP4BitfieldProperty
  190. void MP4BitfieldProperty::Read(MP4File* pFile, u_int32_t index)
  191. {
  192. if (m_implicit) {
  193. return;
  194. }
  195. m_values[index] = pFile->ReadBits(m_numBits);
  196. }
  197. void MP4BitfieldProperty::Write(MP4File* pFile, u_int32_t index)
  198. {
  199. if (m_implicit) {
  200. return;
  201. }
  202. pFile->WriteBits(m_values[index], m_numBits);
  203. }
  204. void MP4BitfieldProperty::Dump(FILE* pFile, u_int8_t indent,
  205. bool dumpImplicits, u_int32_t index)
  206. {
  207. if (m_implicit && !dumpImplicits) {
  208. return;
  209. }
  210. Indent(pFile, indent);
  211. u_int8_t hexWidth = m_numBits / 4;
  212. if (hexWidth == 0 || (m_numBits % 4)) {
  213. hexWidth++;
  214. }
  215. fprintf(pFile, 
  216. #ifdef WIN32
  217. "%s = "LLU" (0x%0*I64x) <%u bits>n", 
  218. #else
  219. "%s = "LLU" (0x%0*llx) <%u bits>n", 
  220. #endif
  221. m_name, m_values[index], (int)hexWidth, m_values[index], m_numBits);
  222. }
  223. // MP4Float32Property
  224. void MP4Float32Property::Read(MP4File* pFile, u_int32_t index) 
  225. {
  226. if (m_implicit) {
  227. return;
  228. }
  229. if (m_useFixed16Format) {
  230. m_values[index] = pFile->ReadFixed16();
  231. } else if (m_useFixed32Format) {
  232. m_values[index] = pFile->ReadFixed32();
  233. } else {
  234. m_values[index] = pFile->ReadFloat();
  235. }
  236. }
  237. void MP4Float32Property::Write(MP4File* pFile, u_int32_t index) 
  238. {
  239. if (m_implicit) {
  240. return;
  241. }
  242. if (m_useFixed16Format) {
  243. pFile->WriteFixed16(m_values[index]);
  244. } else if (m_useFixed32Format) {
  245. pFile->WriteFixed32(m_values[index]);
  246. } else {
  247. pFile->WriteFloat(m_values[index]);
  248. }
  249. }
  250. void MP4Float32Property::Dump(FILE* pFile, u_int8_t indent,
  251. bool dumpImplicits, u_int32_t index)
  252. {
  253. if (m_implicit && !dumpImplicits) {
  254. return;
  255. }
  256. Indent(pFile, indent);
  257. fprintf(pFile, "%s = %fn", 
  258. m_name, m_values[index]);
  259. }
  260. // MP4StringProperty
  261. MP4StringProperty::MP4StringProperty(char* name, 
  262. bool useCountedFormat, bool useUnicode)
  263. : MP4Property(name)
  264. {
  265. SetCount(1);
  266. m_values[0] = NULL;
  267. m_useCountedFormat = useCountedFormat;
  268. m_useExpandedCount = false;
  269. m_useUnicode = useUnicode;
  270. m_fixedLength = 0; // length not fixed
  271. }
  272. MP4StringProperty::~MP4StringProperty() 
  273. {
  274. u_int32_t count = GetCount();
  275. for (u_int32_t i = 0; i < count; i++) {
  276. MP4Free(m_values[i]);
  277. }
  278. }
  279. void MP4StringProperty::SetCount(u_int32_t count) 
  280. {
  281. u_int32_t oldCount = m_values.Size();
  282. m_values.Resize(count);
  283. for (u_int32_t i = oldCount; i < count; i++) {
  284. m_values[i] = NULL;
  285. }
  286. }
  287. void MP4StringProperty::SetValue(const char* value, u_int32_t index) 
  288. {
  289. if (m_readOnly) {
  290. throw new MP4Error(EACCES, "property is read-only", m_name);
  291. }
  292. MP4Free(m_values[index]);
  293. if (m_fixedLength) {
  294. m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
  295. if (value) {
  296. strncpy(m_values[index], value, m_fixedLength);
  297. }
  298. } else {
  299. if (value) {
  300. m_values[index] = MP4Stralloc(value);
  301. } else {
  302. m_values[index] = NULL;
  303. }
  304. }
  305. }
  306. void MP4StringProperty::Read(MP4File* pFile, u_int32_t index)
  307. {
  308. if (m_implicit) {
  309. return;
  310. }
  311. if (m_useCountedFormat) {
  312. m_values[index] = pFile->ReadCountedString(
  313. (m_useUnicode ? 2 : 1), m_useExpandedCount);
  314. } else if (m_fixedLength) {
  315. MP4Free(m_values[index]);
  316. m_values[index] = (char*)MP4Calloc(m_fixedLength + 1);
  317. pFile->ReadBytes((u_int8_t*)m_values[index], m_fixedLength);
  318. } else {
  319. m_values[index] = pFile->ReadString();
  320. }
  321. }
  322. void MP4StringProperty::Write(MP4File* pFile, u_int32_t index)
  323. {
  324. if (m_implicit) {
  325. return;
  326. }
  327. if (m_useCountedFormat) {
  328. pFile->WriteCountedString(m_values[index],
  329. (m_useUnicode ? 2 : 1), m_useExpandedCount);
  330. } else if (m_fixedLength) {
  331. pFile->WriteBytes((u_int8_t*)m_values[index], m_fixedLength);
  332. } else {
  333. pFile->WriteString(m_values[index]);
  334. }
  335. }
  336. void MP4StringProperty::Dump(FILE* pFile, u_int8_t indent,
  337. bool dumpImplicits, u_int32_t index)
  338. {
  339. if (m_implicit && !dumpImplicits) {
  340. return;
  341. }
  342. Indent(pFile, indent);
  343. if (m_useUnicode) {
  344. fprintf(pFile, "%s = %lsn", m_name, (wchar_t*)m_values[index]);
  345. } else {
  346. fprintf(pFile, "%s = %sn", m_name, m_values[index]);
  347. }
  348. }
  349. // MP4BytesProperty
  350. MP4BytesProperty::MP4BytesProperty(char* name, u_int32_t valueSize)
  351. : MP4Property(name)
  352. {
  353. SetCount(1);
  354. m_values[0] = (u_int8_t*)MP4Calloc(valueSize);
  355. m_valueSizes[0] = valueSize;
  356. m_fixedValueSize = 0;
  357. }
  358. MP4BytesProperty::~MP4BytesProperty() 
  359. {
  360. u_int32_t count = GetCount();
  361. for (u_int32_t i = 0; i < count; i++) {
  362. MP4Free(m_values[i]);
  363. }
  364. }
  365.   
  366. void MP4BytesProperty::SetCount(u_int32_t count) 
  367. {
  368. u_int32_t oldCount = m_values.Size();
  369. m_values.Resize(count);
  370. m_valueSizes.Resize(count);
  371. for (u_int32_t i = oldCount; i < count; i++) {
  372. m_values[i] = NULL;
  373. m_valueSizes[i] = 0;
  374. }
  375. }
  376. void MP4BytesProperty::SetValue(const u_int8_t* pValue, u_int32_t valueSize, 
  377. u_int32_t index) 
  378. {
  379. if (m_readOnly) {
  380. throw new MP4Error(EACCES, "property is read-only", m_name);
  381. }
  382. if (m_fixedValueSize) {
  383. if (valueSize > m_fixedValueSize) {
  384. throw new MP4Error("value size exceeds fixed value size",
  385. "MP4BytesProperty::SetValue");
  386. }
  387. if (m_values[index] == NULL) {
  388. m_values[index] = (u_int8_t*)MP4Calloc(m_fixedValueSize);
  389. m_valueSizes[index] = m_fixedValueSize;
  390. }
  391. if (pValue) {
  392. memcpy(m_values[index], pValue, valueSize);
  393. }
  394. } else {
  395. MP4Free(m_values[index]);
  396. if (pValue) {
  397. m_values[index] = (u_int8_t*)MP4Malloc(valueSize);
  398. memcpy(m_values[index], pValue, valueSize);
  399. m_valueSizes[index] = valueSize;
  400. } else {
  401. m_values[index] = NULL;
  402. m_valueSizes[index] = 0;
  403. }
  404. }
  405. }
  406. void MP4BytesProperty::SetValueSize(u_int32_t valueSize, u_int32_t index) 
  407. {
  408. if (m_fixedValueSize) {
  409. throw new MP4Error("can't change size of fixed sized property",
  410. "MP4BytesProperty::SetValueSize");
  411. }
  412. if (m_values[index] != NULL) {
  413. m_values[index] = (u_int8_t*)MP4Realloc(m_values[index], valueSize);
  414. }
  415. m_valueSizes[index] = valueSize;
  416. }
  417. void MP4BytesProperty::SetFixedSize(u_int32_t fixedSize) 
  418. {
  419. m_fixedValueSize = 0;
  420. for (u_int32_t i = 0; i < GetCount(); i++) {
  421. SetValueSize(fixedSize, i);
  422. }
  423. m_fixedValueSize = fixedSize;
  424. }
  425. void MP4BytesProperty::Read(MP4File* pFile, u_int32_t index)
  426. {
  427. if (m_implicit) {
  428. return;
  429. }
  430. MP4Free(m_values[index]);
  431. m_values[index] = (u_int8_t*)MP4Malloc(m_valueSizes[index]);
  432. pFile->ReadBytes(m_values[index], m_valueSizes[index]);
  433. }
  434. void MP4BytesProperty::Write(MP4File* pFile, u_int32_t index)
  435. {
  436. if (m_implicit) {
  437. return;
  438. }
  439. pFile->WriteBytes(m_values[index], m_valueSizes[index]);
  440. }
  441. void MP4BytesProperty::Dump(FILE* pFile, u_int8_t indent,
  442. bool dumpImplicits, u_int32_t index)
  443. {
  444. if (m_implicit && !dumpImplicits) {
  445. return;
  446. }
  447. Indent(pFile, indent);
  448. fprintf(pFile, "%s = <%u bytes> ", m_name, m_valueSizes[index]);
  449. for (u_int32_t i = 0; i < m_valueSizes[index]; i++) {
  450. if ((i % 16) == 0 && m_valueSizes[index] > 16) {
  451. fprintf(pFile, "n");
  452. Indent(pFile, indent);
  453. }
  454. fprintf(pFile, "%02x ", m_values[index][i]);
  455. }
  456. fprintf(pFile, "n");
  457. }
  458. // MP4TableProperty
  459. MP4TableProperty::MP4TableProperty(char* name, MP4Property* pCountProperty)
  460. : MP4Property(name) 
  461. {
  462. ASSERT(pCountProperty->GetType() == Integer8Property
  463. || pCountProperty->GetType() == Integer32Property);
  464. m_pCountProperty = pCountProperty;
  465. m_pCountProperty->SetReadOnly();
  466. }
  467. MP4TableProperty::~MP4TableProperty()
  468. {
  469. for (u_int32_t i = 0; i < m_pProperties.Size(); i++) {
  470. delete m_pProperties[i];
  471. }
  472. }
  473. void MP4TableProperty::AddProperty(MP4Property* pProperty) 
  474. {
  475. ASSERT(pProperty);
  476. ASSERT(pProperty->GetType() != TableProperty);
  477. ASSERT(pProperty->GetType() != DescriptorProperty);
  478. m_pProperties.Add(pProperty);
  479. pProperty->SetParentAtom(m_pParentAtom);
  480. pProperty->SetCount(0);
  481. }
  482. bool MP4TableProperty::FindProperty(const char *name,
  483. MP4Property** ppProperty, u_int32_t* pIndex)
  484. {
  485. ASSERT(m_name);
  486. // check if first component of name matches ourselves
  487. if (!MP4NameFirstMatches(m_name, name)) {
  488. return false;
  489. }
  490. // check if the specified table entry exists
  491. u_int32_t index;
  492. bool haveIndex = MP4NameFirstIndex(name, &index);
  493. if (haveIndex) {
  494. if (index >= GetCount()) {
  495. return false;
  496. }
  497. if (pIndex) {
  498. *pIndex = index;
  499. }
  500. }
  501. VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(),
  502. printf("FindProperty: matched %sn", name));
  503. // get name of table property
  504. const char *tablePropName = MP4NameAfterFirst(name);
  505. if (tablePropName == NULL) {
  506. if (!haveIndex) {
  507. *ppProperty = this;
  508. return true;
  509. }
  510. return false;
  511. }
  512. // check if this table property exists
  513. return FindContainedProperty(tablePropName, ppProperty, pIndex);
  514. }
  515. bool MP4TableProperty::FindContainedProperty(const char *name,
  516. MP4Property** ppProperty, u_int32_t* pIndex)
  517. {
  518. u_int32_t numProperties = m_pProperties.Size();
  519. for (u_int32_t i = 0; i < numProperties; i++) {
  520. if (m_pProperties[i]->FindProperty(name, ppProperty, pIndex)) {
  521. return true;
  522. }
  523. }
  524. return false;
  525. }
  526. void MP4TableProperty::Read(MP4File* pFile, u_int32_t index)
  527. {
  528. ASSERT(index == 0);
  529. if (m_implicit) {
  530. return;
  531. }
  532. u_int32_t numProperties = m_pProperties.Size();
  533. if (numProperties == 0) {
  534. WARNING(numProperties == 0);
  535. return;
  536. }
  537. u_int32_t numEntries = GetCount();
  538. /* for each property set size */
  539. for (u_int32_t j = 0; j < numProperties; j++) {
  540. m_pProperties[j]->SetCount(numEntries);
  541. }
  542. for (u_int32_t i = 0; i < numEntries; i++) {
  543. ReadEntry(pFile, i);
  544. }
  545. }
  546. void MP4TableProperty::ReadEntry(MP4File* pFile, u_int32_t index)
  547. {
  548. for (u_int32_t j = 0; j < m_pProperties.Size(); j++) {
  549. m_pProperties[j]->Read(pFile, index);
  550. }
  551. }
  552. void MP4TableProperty::Write(MP4File* pFile, u_int32_t index)
  553. {
  554. ASSERT(index == 0);
  555. if (m_implicit) {
  556. return;
  557. }
  558. u_int32_t numProperties = m_pProperties.Size();
  559. if (numProperties == 0) {
  560. WARNING(numProperties == 0);
  561. return;
  562. }
  563. u_int32_t numEntries = GetCount();
  564. ASSERT(m_pProperties[0]->GetCount() == numEntries);
  565. for (u_int32_t i = 0; i < numEntries; i++) {
  566. WriteEntry(pFile, i);
  567. }
  568. }
  569. void MP4TableProperty::WriteEntry(MP4File* pFile, u_int32_t index)
  570. {
  571. for (u_int32_t j = 0; j < m_pProperties.Size(); j++) {
  572. m_pProperties[j]->Write(pFile, index);
  573. }
  574. }
  575. void MP4TableProperty::Dump(FILE* pFile, u_int8_t indent,
  576. bool dumpImplicits, u_int32_t index)
  577. {
  578. ASSERT(index == 0);
  579. // implicit tables just can't be dumped
  580. if (m_implicit) {
  581. return;
  582. }
  583. u_int32_t numProperties = m_pProperties.Size();
  584. if (numProperties == 0) {
  585. WARNING(numProperties == 0);
  586. return;
  587. }
  588. u_int32_t numEntries = GetCount();
  589. for (u_int32_t i = 0; i < numEntries; i++) {
  590. for (u_int32_t j = 0; j < numProperties; j++) {
  591. m_pProperties[j]->Dump(pFile, indent + 1, dumpImplicits, i);
  592. }
  593. }
  594. }
  595. // MP4DescriptorProperty
  596.   
  597. MP4DescriptorProperty::MP4DescriptorProperty(char* name, 
  598. u_int8_t tagsStart, u_int8_t tagsEnd, bool mandatory, bool onlyOne)
  599. : MP4Property(name) 
  600. SetTags(tagsStart, tagsEnd);
  601. m_sizeLimit = 0;
  602. m_mandatory = mandatory;
  603. m_onlyOne = onlyOne;
  604. }
  605. MP4DescriptorProperty::~MP4DescriptorProperty() 
  606. {
  607. for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) {
  608. delete m_pDescriptors[i];
  609. }
  610. }
  611. void MP4DescriptorProperty::SetParentAtom(MP4Atom* pParentAtom) {
  612. m_pParentAtom = pParentAtom;
  613. for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) {
  614. m_pDescriptors[i]->SetParentAtom(pParentAtom);
  615. }
  616. }
  617. MP4Descriptor* MP4DescriptorProperty::AddDescriptor(u_int8_t tag)
  618. {
  619. // check that tag is in expected range
  620. ASSERT(tag >= m_tagsStart && tag <= m_tagsEnd);
  621. MP4Descriptor* pDescriptor = CreateDescriptor(tag);
  622. ASSERT(pDescriptor);
  623. m_pDescriptors.Add(pDescriptor);
  624. pDescriptor->SetParentAtom(m_pParentAtom);
  625. return pDescriptor;
  626. }
  627. void MP4DescriptorProperty::DeleteDescriptor(u_int32_t index)
  628. {
  629. delete m_pDescriptors[index];
  630. m_pDescriptors.Delete(index);
  631. }
  632. void MP4DescriptorProperty::Generate()
  633. {
  634. // generate a default descriptor
  635. // if it is mandatory, and single
  636. if (m_mandatory && m_onlyOne) {
  637. MP4Descriptor* pDescriptor = 
  638. AddDescriptor(m_tagsStart);
  639. pDescriptor->Generate();
  640. }
  641. }
  642. bool MP4DescriptorProperty::FindProperty(const char *name,
  643. MP4Property** ppProperty, u_int32_t* pIndex)
  644. {
  645. // we're unnamed, so just check contained properties
  646. if (m_name == NULL || !strcmp(m_name, "")) {
  647. return FindContainedProperty(name, ppProperty, pIndex);
  648. }
  649. // check if first component of name matches ourselves
  650. if (!MP4NameFirstMatches(m_name, name)) {
  651. return false;
  652. }
  653. // check if the specific descriptor entry exists
  654. u_int32_t descrIndex;
  655. bool haveDescrIndex = MP4NameFirstIndex(name, &descrIndex);
  656. if (haveDescrIndex && descrIndex >= GetCount()) {
  657. return false;
  658. }
  659. if (m_pParentAtom) {
  660. VERBOSE_FIND(m_pParentAtom->GetFile()->GetVerbosity(),
  661. printf("FindProperty: matched %sn", name));
  662. }
  663. // get name of descriptor property
  664. name = MP4NameAfterFirst(name);
  665. if (name == NULL) {
  666. if (!haveDescrIndex) {
  667. *ppProperty = this;
  668. return true;
  669. }
  670. return false;
  671. }
  672. /* check rest of name */
  673. if (haveDescrIndex) {
  674. return m_pDescriptors[descrIndex]->FindProperty(name, 
  675. ppProperty, pIndex); 
  676. } else {
  677. return FindContainedProperty(name, ppProperty, pIndex);
  678. }
  679. }
  680. bool MP4DescriptorProperty::FindContainedProperty(const char *name,
  681. MP4Property** ppProperty, u_int32_t* pIndex)
  682. {
  683. for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) {
  684. if (m_pDescriptors[i]->FindProperty(name, ppProperty, pIndex)) {
  685. return true;
  686. }
  687. }
  688. return false;
  689. }
  690. void MP4DescriptorProperty::Read(MP4File* pFile, u_int32_t index)
  691. {
  692. ASSERT(index == 0);
  693. if (m_implicit) {
  694. return;
  695. }
  696. u_int64_t start = pFile->GetPosition();
  697. while (true) {
  698. // enforce size limitation
  699. if (m_sizeLimit && pFile->GetPosition() >= start + m_sizeLimit) {
  700. break;
  701. }
  702. u_int8_t tag;
  703. try {
  704. pFile->PeekBytes(&tag, 1);
  705. }
  706. catch (MP4Error* e) {
  707. if (pFile->GetPosition() >= pFile->GetSize()) {
  708. // EOF
  709. delete e;
  710. break;
  711. }
  712. throw e;
  713. }
  714. // check if tag is in desired range
  715. if (tag < m_tagsStart || tag > m_tagsEnd) {
  716. break;
  717. }
  718. MP4Descriptor* pDescriptor = 
  719. AddDescriptor(tag);
  720. pDescriptor->Read(pFile);
  721. }
  722. // warnings
  723. if (m_mandatory && m_pDescriptors.Size() == 0) {
  724. VERBOSE_READ(pFile->GetVerbosity(),
  725. printf("Warning: Mandatory descriptor 0x%02x missingn",
  726. m_tagsStart));
  727. } else if (m_onlyOne && m_pDescriptors.Size() > 1) {
  728. VERBOSE_READ(pFile->GetVerbosity(),
  729. printf("Warning: Descriptor 0x%02x has more than one instancen",
  730. m_tagsStart));
  731. }
  732. }
  733. void MP4DescriptorProperty::Write(MP4File* pFile, u_int32_t index)
  734. {
  735. ASSERT(index == 0);
  736. if (m_implicit) {
  737. return;
  738. }
  739. for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) {
  740. m_pDescriptors[i]->Write(pFile);
  741. }
  742. }
  743. void MP4DescriptorProperty::Dump(FILE* pFile, u_int8_t indent,
  744. bool dumpImplicits, u_int32_t index)
  745. {
  746. ASSERT(index == 0);
  747. if (m_implicit && !dumpImplicits) {
  748. return;
  749. }
  750. if (m_name) {
  751. Indent(pFile, indent);
  752. fprintf(pFile, "%sn", m_name);
  753. indent++;
  754. }
  755. for (u_int32_t i = 0; i < m_pDescriptors.Size(); i++) {
  756. m_pDescriptors[i]->Dump(pFile, indent, dumpImplicits);
  757. }
  758. }