mp4file_io.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
  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 [email protected]
  20. */
  21. #include "mp4common.h"
  22. // MP4File low level IO support
  23. u_int64_t MP4File::GetPosition(FILE* pFile)
  24. {
  25. if (m_memoryBuffer == NULL) {
  26. if (pFile == NULL) {
  27. ASSERT(m_pFile);
  28. u_int64_t fpos;
  29. if (m_virtual_IO->GetPosition(m_pFile, &fpos) != 0) {
  30. throw new MP4Error("getting position via Virtual I/O", "MP4GetPosition");
  31. }
  32. return fpos;
  33. } else {
  34. fpos_t fpos;
  35. if (fgetpos(pFile, &fpos) < 0) {
  36. throw new MP4Error(errno, "MP4GetPosition");
  37. }
  38. uint64_t ret;
  39. FPOS_TO_VAR(fpos, uint64_t, ret);
  40. return ret;
  41. }
  42. } else {
  43. return m_memoryBufferPosition;
  44. }
  45. }
  46. void MP4File::SetPosition(u_int64_t pos, FILE* pFile)
  47. {
  48. if (m_memoryBuffer == NULL) {
  49. if (pFile == NULL) {
  50. ASSERT(m_pFile);
  51. if (m_virtual_IO->SetPosition(m_pFile, pos) != 0) {
  52. throw new MP4Error("setting position via Virtual I/O", "MP4SetPosition");
  53. }
  54. } else {
  55. fpos_t fpos;
  56. VAR_TO_FPOS(fpos, pos);
  57. if (fsetpos(pFile, &fpos) < 0) {
  58. throw new MP4Error(errno, "MP4SetPosition");
  59. }
  60. }
  61. } else {
  62. if (pos >= m_memoryBufferSize) {
  63. // abort();
  64. throw new MP4Error("position out of range", "MP4SetPosition");
  65. }
  66. m_memoryBufferPosition = pos;
  67. }
  68. }
  69. u_int64_t MP4File::GetSize()
  70. {
  71. if (m_mode == 'w') {
  72. // we're always positioned at the end of file in write mode
  73. // except for short intervals in ReadSample and FinishWrite routines
  74. // so we rely on the faster approach of GetPosition()
  75. // instead of flushing to disk, and then stat'ing the file
  76. m_fileSize = GetPosition();
  77. } // else read mode, fileSize was determined at Open()
  78. return m_fileSize;
  79. }
  80. void MP4File::ReadBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
  81. {
  82. // handle degenerate cases
  83. if (numBytes == 0) {
  84. return;
  85. }
  86. ASSERT(pBytes);
  87. WARNING(m_numReadBits > 0);
  88. if (m_memoryBuffer == NULL) {
  89. if (pFile == NULL) {
  90. ASSERT(m_pFile);
  91. if (m_virtual_IO->Read(m_pFile, pBytes, numBytes) != numBytes) {
  92. throw new MP4Error("not enough bytes, reached end-of-file", "MP4ReadBytes");
  93. }
  94. } else {
  95. if (fread(pBytes, 1, numBytes, pFile) != numBytes) {
  96. if (feof(pFile)) {
  97. throw new MP4Error(
  98. "not enough bytes, reached end-of-file",
  99. "MP4ReadBytes");
  100. } else {
  101. throw new MP4Error(errno, "MP4ReadBytes");
  102. }
  103. }
  104. }
  105. } else {
  106. if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) {
  107. throw new MP4Error(
  108. "not enough bytes, reached end-of-memory",
  109. "MP4ReadBytes");
  110. }
  111. memcpy(pBytes, &m_memoryBuffer[m_memoryBufferPosition], numBytes);
  112. m_memoryBufferPosition += numBytes;
  113. }
  114. return;
  115. }
  116. void MP4File::PeekBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
  117. {
  118. u_int64_t pos = GetPosition(pFile);
  119. ReadBytes(pBytes, numBytes, pFile);
  120. SetPosition(pos, pFile);
  121. }
  122. void MP4File::EnableMemoryBuffer(u_int8_t* pBytes, u_int64_t numBytes)
  123. {
  124. ASSERT(m_memoryBuffer == NULL);
  125. if (pBytes) {
  126. m_memoryBuffer = pBytes;
  127. m_memoryBufferSize = numBytes;
  128. } else {
  129. if (numBytes) {
  130. m_memoryBufferSize = numBytes;
  131. } else {
  132. m_memoryBufferSize = 4096;
  133. }
  134. m_memoryBuffer = (u_int8_t*)MP4Malloc(m_memoryBufferSize);
  135. }
  136. m_memoryBufferPosition = 0;
  137. }
  138. void MP4File::DisableMemoryBuffer(u_int8_t** ppBytes, u_int64_t* pNumBytes)
  139. {
  140. ASSERT(m_memoryBuffer != NULL);
  141. if (ppBytes) {
  142. *ppBytes = m_memoryBuffer;
  143. }
  144. if (pNumBytes) {
  145. *pNumBytes = m_memoryBufferPosition;
  146. }
  147. m_memoryBuffer = NULL;
  148. m_memoryBufferSize = 0;
  149. m_memoryBufferPosition = 0;
  150. }
  151. void MP4File::WriteBytes(u_int8_t* pBytes, u_int32_t numBytes, FILE* pFile)
  152. {
  153. ASSERT(m_numWriteBits == 0 || m_numWriteBits >= 8);
  154. if (pBytes == NULL || numBytes == 0) {
  155. return;
  156. }
  157. if (m_memoryBuffer == NULL) {
  158. if (pFile == NULL) {
  159. ASSERT(m_pFile);
  160. if (m_virtual_IO->Write(m_pFile, pBytes, numBytes) != numBytes) {
  161. throw new MP4Error("error writing bytes via virtual I/O", "MP4WriteBytes");
  162. }
  163. } else {
  164. u_int32_t rc = (u_int32_t)fwrite(pBytes, 1, numBytes, pFile);
  165. if (rc != numBytes) {
  166. throw new MP4Error(errno, "MP4WriteBytes");
  167. }
  168. }
  169. } else {
  170. if (m_memoryBufferPosition + numBytes > m_memoryBufferSize) {
  171. m_memoryBufferSize = 2 * (m_memoryBufferSize + numBytes);
  172. m_memoryBuffer = (u_int8_t*)
  173. MP4Realloc(m_memoryBuffer, m_memoryBufferSize);
  174. }
  175. memcpy(&m_memoryBuffer[m_memoryBufferPosition], pBytes, numBytes);
  176. m_memoryBufferPosition += numBytes;
  177. }
  178. }
  179. u_int64_t MP4File::ReadUInt(u_int8_t size)
  180. {
  181. switch (size) {
  182. case 1:
  183. return ReadUInt8();
  184. case 2:
  185. return ReadUInt16();
  186. case 3:
  187. return ReadUInt24();
  188. case 4:
  189. return ReadUInt32();
  190. case 8:
  191. return ReadUInt64();
  192. default:
  193. ASSERT(false);
  194. return 0;
  195. }
  196. }
  197. void MP4File::WriteUInt(u_int64_t val, u_int8_t size)
  198. {
  199. switch (size) {
  200. case 1:
  201. WriteUInt8((u_int8_t)val);
  202. break;
  203. case 2:
  204. WriteUInt16((u_int16_t)val);
  205. break;
  206. case 3:
  207. WriteUInt24((u_int32_t)val);
  208. break;
  209. case 4:
  210. WriteUInt32((u_int32_t)val);
  211. break;
  212. case 8:
  213. WriteUInt64((u_int64_t)val);
  214. break;
  215. default:
  216. ASSERT(false);
  217. break;
  218. }
  219. }
  220. #if 0
  221. void MP4File::WriteUInt(u_int64_t value, u_int8_t size)
  222. {
  223. switch (size) {
  224. case 1:
  225. WriteUInt8(value);
  226. case 2:
  227. WriteUInt16(value);
  228. case 3:
  229. WriteUInt24(value);
  230. case 4:
  231. WriteUInt32(value);
  232. case 8:
  233. WriteUInt64(value);
  234. default:
  235. ASSERT(false);
  236. }
  237. }
  238. #endif
  239. u_int8_t MP4File::ReadUInt8()
  240. {
  241. u_int8_t data;
  242. ReadBytes(&data, 1);
  243. return data;
  244. }
  245. void MP4File::WriteUInt8(u_int8_t value)
  246. {
  247. WriteBytes(&value, 1);
  248. }
  249. u_int16_t MP4File::ReadUInt16()
  250. {
  251. u_int8_t data[2];
  252. ReadBytes(&data[0], 2);
  253. return ((data[0] << 8) | data[1]);
  254. }
  255. void MP4File::WriteUInt16(u_int16_t value)
  256. {
  257. u_int8_t data[2];
  258. data[0] = (value >> 8) & 0xFF;
  259. data[1] = value & 0xFF;
  260. WriteBytes(data, 2);
  261. }
  262. u_int32_t MP4File::ReadUInt24()
  263. {
  264. u_int8_t data[3];
  265. ReadBytes(&data[0], 3);
  266. return ((data[0] << 16) | (data[1] << 8) | data[2]);
  267. }
  268. void MP4File::WriteUInt24(u_int32_t value)
  269. {
  270. u_int8_t data[3];
  271. data[0] = (value >> 16) & 0xFF;
  272. data[1] = (value >> 8) & 0xFF;
  273. data[2] = value & 0xFF;
  274. WriteBytes(data, 3);
  275. }
  276. u_int32_t MP4File::ReadUInt32()
  277. {
  278. u_int8_t data[4];
  279. ReadBytes(&data[0], 4);
  280. return ((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]);
  281. }
  282. void MP4File::WriteUInt32(u_int32_t value)
  283. {
  284. u_int8_t data[4];
  285. data[0] = (value >> 24) & 0xFF;
  286. data[1] = (value >> 16) & 0xFF;
  287. data[2] = (value >> 8) & 0xFF;
  288. data[3] = value & 0xFF;
  289. WriteBytes(data, 4);
  290. }
  291. u_int64_t MP4File::ReadUInt64()
  292. {
  293. u_int8_t data[8];
  294. u_int64_t result = 0;
  295. u_int64_t temp;
  296. ReadBytes(&data[0], 8);
  297. for (int i = 0; i < 8; i++) {
  298. temp = data[i];
  299. result |= temp << ((7 - i) * 8);
  300. }
  301. return result;
  302. }
  303. void MP4File::WriteUInt64(u_int64_t value)
  304. {
  305. u_int8_t data[8];
  306. for (int i = 7; i >= 0; i--) {
  307. data[i] = value & 0xFF;
  308. value >>= 8;
  309. }
  310. WriteBytes(data, 8);
  311. }
  312. float MP4File::ReadFixed16()
  313. {
  314. u_int8_t iPart = ReadUInt8();
  315. u_int8_t fPart = ReadUInt8();
  316. return iPart + (((float)fPart) / 0x100);
  317. }
  318. void MP4File::WriteFixed16(float value)
  319. {
  320. if (value >= 0x100) {
  321. throw new MP4Error(ERANGE, "MP4WriteFixed16");
  322. }
  323. u_int8_t iPart = (u_int8_t)value;
  324. u_int8_t fPart = (u_int8_t)((value - iPart) * 0x100);
  325. WriteUInt8(iPart);
  326. WriteUInt8(fPart);
  327. }
  328. float MP4File::ReadFixed32()
  329. {
  330. u_int16_t iPart = ReadUInt16();
  331. u_int16_t fPart = ReadUInt16();
  332. return iPart + (((float)fPart) / 0x10000);
  333. }
  334. void MP4File::WriteFixed32(float value)
  335. {
  336. if (value >= 0x10000) {
  337. throw new MP4Error(ERANGE, "MP4WriteFixed32");
  338. }
  339. u_int16_t iPart = (u_int16_t)value;
  340. u_int16_t fPart = (u_int16_t)((value - iPart) * 0x10000);
  341. WriteUInt16(iPart);
  342. WriteUInt16(fPart);
  343. }
  344. float MP4File::ReadFloat()
  345. {
  346. union {
  347. float f;
  348. u_int32_t i;
  349. } u;
  350. u.i = ReadUInt32();
  351. return u.f;
  352. }
  353. void MP4File::WriteFloat(float value)
  354. {
  355. union {
  356. float f;
  357. u_int32_t i;
  358. } u;
  359. u.f = value;
  360. WriteUInt32(u.i);
  361. }
  362. char* MP4File::ReadString()
  363. {
  364. uint32_t readSize=1;
  365. u_int32_t length = 0;
  366. u_int32_t alloced = 64;
  367. uint8_t* data = (uint8_t*)MP4Malloc(alloced);
  368. ReadBytes((u_int8_t*)&data[length++], 1);
  369. if (data[0] == 0xFF || data[0] == 0xFE)
  370. {
  371. ReadBytes((u_int8_t*)&data[length++], 1);
  372. if ((data[0] == 0xFF && data[1] == 0xFE)
  373. || (data[0] == 0xFE && data[1] == 0xFF))
  374. readSize=2; // Unicode
  375. }
  376. while (1)
  377. {
  378. if (readSize == 1 && data[length - 1] == 0)
  379. break;
  380. if (readSize == 2)
  381. {
  382. uint16_t *utf16 = (uint16_t *)data;
  383. if (utf16[length/2 - 1] == 0)
  384. break;
  385. }
  386. if (length == alloced) {
  387. data = (uint8_t*)MP4Realloc(data, alloced * 2);
  388. if (data == NULL) return NULL;
  389. alloced *= 2;
  390. }
  391. ReadBytes((u_int8_t*)&data[length], readSize);
  392. length+=readSize;
  393. }
  394. data = (uint8_t*)MP4Realloc(data, length);
  395. return (char *)data;
  396. }
  397. uint16_t *MP4File::ReadUnicodeString()
  398. {
  399. u_int32_t length = 0;
  400. u_int32_t alloced = 64;
  401. uint16_t *data = (uint16_t *)MP4Malloc(alloced*sizeof(uint16_t));
  402. do {
  403. if (length == alloced) {
  404. data = (uint16_t *)MP4Realloc(data, (alloced * 2)*sizeof(uint16_t));
  405. if (data == NULL) return NULL;
  406. alloced *= 2;
  407. }
  408. ReadBytes((u_int8_t *)&data[length], 2);
  409. length++;
  410. } while (data[length - 1] != 0);
  411. data = (uint16_t *)MP4Realloc(data, length*sizeof(uint16_t));
  412. return data;
  413. }
  414. void MP4File::WriteString(char* string)
  415. {
  416. if (string == NULL) {
  417. u_int8_t zero = 0;
  418. WriteBytes(&zero, 1);
  419. } else {
  420. WriteBytes((u_int8_t*)string, (u_int32_t)strlen(string) + 1);
  421. }
  422. }
  423. void MP4File::WriteUnicodeString(const uint16_t *string)
  424. {
  425. if (string == NULL) {
  426. u_int8_t zero = 0;
  427. WriteBytes(&zero, 1);
  428. } else {
  429. const uint16_t *itr = string;
  430. int len=0;
  431. while (*itr)
  432. {
  433. itr++;
  434. len++;
  435. }
  436. WriteBytes((u_int8_t*)string, (len + 1)*sizeof(uint16_t));
  437. }
  438. }
  439. char* MP4File::ReadCountedString(u_int8_t charSize, bool allowExpandedCount)
  440. {
  441. u_int32_t charLength;
  442. if (allowExpandedCount) {
  443. u_int8_t b;
  444. uint ix = 0;
  445. charLength = 0;
  446. do {
  447. b = ReadUInt8();
  448. charLength += b;
  449. ix++;
  450. if (ix > 25)
  451. throw new MP4Error(ERANGE,
  452. "Counted string too long 25 * 255");
  453. } while (b == 255);
  454. } else {
  455. charLength = ReadUInt8();
  456. }
  457. u_int32_t byteLength = charLength * charSize;
  458. char* data = (char*)MP4Malloc(byteLength + 1);
  459. if (byteLength > 0) {
  460. ReadBytes((u_int8_t*)data, byteLength);
  461. }
  462. data[byteLength] = '\0';
  463. return data;
  464. }
  465. void MP4File::WriteCountedString(char* string,
  466. u_int8_t charSize, bool allowExpandedCount)
  467. {
  468. u_int32_t byteLength;
  469. if (string) {
  470. byteLength = (u_int32_t)strlen(string);
  471. } else {
  472. byteLength = 0;
  473. }
  474. u_int32_t charLength = byteLength / charSize;
  475. if (allowExpandedCount) {
  476. while (charLength >= 0xFF) {
  477. WriteUInt8(0xFF);
  478. charLength -= 0xFF;
  479. }
  480. WriteUInt8(charLength);
  481. } else {
  482. if (charLength > 255) {
  483. throw new MP4Error(ERANGE, "Length is %d", "MP4WriteCountedString", charLength);
  484. }
  485. WriteUInt8(charLength);
  486. }
  487. if (byteLength > 0) {
  488. WriteBytes((u_int8_t*)string, byteLength);
  489. }
  490. }
  491. u_int64_t MP4File::ReadBits(u_int8_t numBits)
  492. {
  493. ASSERT(numBits > 0);
  494. ASSERT(numBits <= 64);
  495. u_int64_t bits = 0;
  496. for (u_int8_t i = numBits; i > 0; i--) {
  497. if (m_numReadBits == 0) {
  498. ReadBytes(&m_bufReadBits, 1);
  499. m_numReadBits = 8;
  500. }
  501. bits = (bits << 1) | ((m_bufReadBits >> (--m_numReadBits)) & 1);
  502. }
  503. return bits;
  504. }
  505. void MP4File::FlushReadBits()
  506. {
  507. // eat any remaining bits in the read buffer
  508. m_numReadBits = 0;
  509. }
  510. void MP4File::WriteBits(u_int64_t bits, u_int8_t numBits)
  511. {
  512. ASSERT(numBits <= 64);
  513. for (u_int8_t i = numBits; i > 0; i--) {
  514. m_bufWriteBits |=
  515. (((bits >> (i - 1)) & 1) << (8 - ++m_numWriteBits));
  516. if (m_numWriteBits == 8) {
  517. FlushWriteBits();
  518. }
  519. }
  520. }
  521. void MP4File::PadWriteBits(u_int8_t pad)
  522. {
  523. if (m_numWriteBits) {
  524. WriteBits(pad ? 0xFF : 0x00, 8 - m_numWriteBits);
  525. }
  526. }
  527. void MP4File::FlushWriteBits()
  528. {
  529. if (m_numWriteBits > 0) {
  530. WriteBytes(&m_bufWriteBits, 1);
  531. m_numWriteBits = 0;
  532. m_bufWriteBits = 0;
  533. }
  534. }
  535. u_int32_t MP4File::ReadMpegLength()
  536. {
  537. u_int32_t length = 0;
  538. u_int8_t numBytes = 0;
  539. u_int8_t b;
  540. do {
  541. b = ReadUInt8();
  542. length = (length << 7) | (b & 0x7F);
  543. numBytes++;
  544. } while ((b & 0x80) && numBytes < 4);
  545. return length;
  546. }
  547. void MP4File::WriteMpegLength(u_int32_t value, bool compact)
  548. {
  549. if (value > 0x0FFFFFFF) {
  550. throw new MP4Error(ERANGE, "MP4WriteMpegLength");
  551. }
  552. int8_t numBytes;
  553. if (compact) {
  554. if (value <= 0x7F) {
  555. numBytes = 1;
  556. } else if (value <= 0x3FFF) {
  557. numBytes = 2;
  558. } else if (value <= 0x1FFFFF) {
  559. numBytes = 3;
  560. } else {
  561. numBytes = 4;
  562. }
  563. } else {
  564. numBytes = 4;
  565. }
  566. int8_t i = numBytes;
  567. do {
  568. i--;
  569. u_int8_t b = (value >> (i * 7)) & 0x7F;
  570. if (i > 0) {
  571. b |= 0x80;
  572. }
  573. WriteUInt8(b);
  574. } while (i > 0);
  575. }