1
0

NSV_Reader.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688
  1. #if !defined(NSV_READER_HPP)
  2. #define NSV_READER_HPP
  3. //______________________________________________________________________________
  4. //
  5. // NSV_Reader.hpp
  6. // NSV Reader Class
  7. #include "NSV.hpp"
  8. #include "endian.hpp"
  9. #include <string>
  10. #include <memory>
  11. #include <fstream>
  12. #include <sstream>
  13. #include <cassert>
  14. namespace NSV
  15. {
  16. //--------------------------------------
  17. // Defines the interface for the basic_Reader template instantiations
  18. class Reader_base
  19. {
  20. public:
  21. virtual ~Reader_base()
  22. {
  23. }
  24. virtual void open(const std::string& strFile) = 0;
  25. virtual void close() = 0;
  26. virtual File& file() = 0;
  27. virtual const std::string& fileName() const = 0;
  28. virtual void readFileHeader() = 0;
  29. virtual void readFrame() = 0;
  30. virtual void readFrameInfo() = 0;
  31. virtual void readFrameHeader() = 0;
  32. virtual void readPayload() = 0;
  33. virtual void readPayloadInfo() = 0;
  34. virtual void readPayloadHeader(int& nAux, int& iAuxPlusVideo, int& iAudio) = 0;
  35. virtual void buildIndex(int nIndexEntries) = 0;
  36. virtual INT64 frames() const = 0;
  37. virtual INT64 frame() const = 0;
  38. virtual void seek(INT64 nFrame) = 0;
  39. virtual void readSample(int nStream, unsigned char* pData, size_t sizeDataMax, size_t& sizeData, bool& bKeyFrame) = 0;
  40. virtual bool eof() = 0;
  41. virtual const FileHeader& fileHeader() const = 0;
  42. virtual const FrameHeader& frameHeader() const = 0;
  43. virtual void* get_ifs() = 0;
  44. };
  45. //--------------------------------------
  46. template<typename T>
  47. class basic_Reader : public Reader_base
  48. {
  49. public:
  50. basic_Reader(File& f);
  51. ~basic_Reader();
  52. void open(const std::string& strFile);
  53. void close();
  54. File& file();
  55. const std::string& fileName() const;
  56. void readFileHeader();
  57. void readFrame();
  58. void readFrameInfo();
  59. void readFrameHeader();
  60. void readPayload();
  61. void readPayloadInfo();
  62. void readPayloadHeader(int& nAux, int& iAuxPlusVideo, int& iAudio);
  63. void buildIndex(int nIndexEntries = 0); // index all frames by default
  64. INT64 frames() const;
  65. INT64 frame() const;
  66. void seek(INT64 nFrame);
  67. void readSample(int nStream, unsigned char* pData, size_t sizeDataMax, size_t& sizeData, bool& bKeyFrame);
  68. bool eof();
  69. const FileHeader& fileHeader() const;
  70. const FrameHeader& frameHeader() const;
  71. void* get_ifs();
  72. private:
  73. basic_Reader(const basic_Reader& r); // Not implemented
  74. basic_Reader& operator=(const basic_Reader& r); // Not implemented
  75. short read_i16();
  76. unsigned short read_ui16();
  77. int read_i32();
  78. unsigned int read_ui32();
  79. File& m_file;
  80. std::string m_strFile;
  81. T m_ifs;
  82. FileHeader m_fileHeader;
  83. FrameHeader m_frameHeader;
  84. bool m_bFrameHeader;
  85. INT64 m_nFrame;
  86. };
  87. //--------------------------------------
  88. template<typename T>
  89. basic_Reader<T>::basic_Reader(File& f) :
  90. m_file(f),
  91. m_strFile(),
  92. m_fileHeader(),
  93. m_frameHeader(),
  94. m_bFrameHeader(false),
  95. m_nFrame(0)
  96. {
  97. }
  98. //--------------------------------------
  99. template<typename T>
  100. basic_Reader<T>::~basic_Reader()
  101. {
  102. close();
  103. }
  104. //--------------------------------------
  105. template<typename T>
  106. void basic_Reader<T>::open(const std::string& strFile)
  107. {
  108. m_strFile = strFile;
  109. m_ifs.open(m_strFile.c_str(), IOS_BASE::binary);
  110. if (!m_ifs)
  111. {
  112. std::ostringstream ossError;
  113. ossError << "Error opening file " << m_strFile;
  114. throw Exception(ossError.str());
  115. }
  116. readFileHeader();
  117. return;
  118. }
  119. //--------------------------------------
  120. template<typename T>
  121. void basic_Reader<T>::close()
  122. {
  123. if (m_ifs)
  124. {
  125. m_ifs.close();
  126. }
  127. m_strFile.erase();
  128. return;
  129. }
  130. //--------------------------------------
  131. template<typename T>
  132. File& basic_Reader<T>::file()
  133. {
  134. return m_file;
  135. }
  136. //--------------------------------------
  137. template<typename T>
  138. const std::string& basic_Reader<T>::fileName() const
  139. {
  140. return m_strFile;
  141. }
  142. //--------------------------------------
  143. template<typename T>
  144. void basic_Reader<T>::readFileHeader()
  145. {
  146. assert(m_ifs);
  147. // Read file header signature
  148. char cSignature[5];
  149. m_ifs.read(cSignature, 4);
  150. if (strncmp(cSignature, "NSVf", 4) == 0)
  151. {
  152. cSignature[4] = '\0';
  153. m_fileHeader.m_fccSignature = cSignature;
  154. m_fileHeader.m_sizeHeader = read_i32();
  155. m_fileHeader.m_sizeFile = read_i32();
  156. m_fileHeader.m_iFileSize_ms = read_i32();
  157. m_fileHeader.m_sizeMetaData = read_i32();
  158. m_fileHeader.m_nTOCAlloc = read_i32();
  159. m_fileHeader.m_nTOCSize = read_i32();
  160. if ((m_fileHeader.m_sizeFile > 0 && m_fileHeader.m_sizeFile < m_fileHeader.m_sizeHeader)
  161. || m_fileHeader.m_nTOCSize > m_fileHeader.m_nTOCAlloc)
  162. {
  163. throw Exception("Invalid NSV file header");
  164. }
  165. if (m_fileHeader.m_sizeMetaData > 0)
  166. {
  167. std::auto_ptr<char> apcMetaData(new char[m_fileHeader.m_sizeMetaData + 1]);
  168. char* pcMetaData = apcMetaData.get();
  169. if (pcMetaData == 0)
  170. {
  171. throw Exception("Out of memory");
  172. }
  173. m_ifs.read(pcMetaData, m_fileHeader.m_sizeMetaData);
  174. pcMetaData[m_fileHeader.m_sizeMetaData] = '\0';
  175. m_file.header(pcMetaData, m_fileHeader.m_nTOCSize);
  176. }
  177. else
  178. {
  179. m_file.header("", m_fileHeader.m_nTOCSize);
  180. }
  181. for (int nEntry = 0; nEntry < m_fileHeader.m_nTOCSize; ++nEntry)
  182. {
  183. POS_TYPE posOffset;
  184. posOffset = read_ui32();
  185. m_file.indexEntry(nEntry, posOffset);
  186. }
  187. m_ifs.ignore((m_fileHeader.m_nTOCAlloc - m_fileHeader.m_nTOCSize) * 4);
  188. if (m_ifs.tellg() > static_cast<POS_TYPE>(m_fileHeader.m_sizeHeader))
  189. {
  190. throw Exception("Invalid NSV file header");
  191. }
  192. m_file.dataOffset(m_fileHeader.m_sizeHeader);
  193. m_ifs.seekg(m_file.dataOffset());
  194. }
  195. else // No file header present
  196. {
  197. m_fileHeader.m_sizeHeader = 0;
  198. m_ifs.seekg(0, IOS_BASE::end);
  199. m_fileHeader.m_sizeFile = m_ifs.tellg();
  200. m_fileHeader.m_iFileSize_ms = 0;
  201. m_fileHeader.m_nTOCAlloc = 0;
  202. m_file.header("", 0);
  203. m_file.dataOffset(0);
  204. m_ifs.seekg(m_file.dataOffset());
  205. }
  206. // Read stream info from first frame header
  207. readFrameHeader();
  208. int nAux;
  209. int iAuxPlusVideo;
  210. int iAudio;
  211. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  212. m_file.size(m_frameHeader.m_iWidth, m_frameHeader.m_iHeight);
  213. m_file.frameRate(m_frameHeader.m_iFrameRate);
  214. if (m_fileHeader.m_iFileSize_ms > 0)
  215. {
  216. INT64 nFramesDenom = static_cast<INT64>(m_file.rateDenom()) * 1000;
  217. INT64 nFrames = (static_cast<INT64>(m_fileHeader.m_iFileSize_ms) * static_cast<INT64>(m_file.rateNum()) + nFramesDenom / 2) / nFramesDenom;
  218. m_file.frames(nFrames);
  219. }
  220. // Set up primary video and audio streams
  221. m_file.newStream(m_frameHeader.m_fccVideo);
  222. m_file.newStream(m_frameHeader.m_fccAudio);
  223. m_file.stream(0).rate(m_file.rateNum(), m_file.rateDenom());
  224. m_file.stream(0).samples(m_file.frames());
  225. // Set up aux streams
  226. for (int n = 0; n < nAux; ++n)
  227. {
  228. unsigned short uh = read_ui16();
  229. unsigned long ul = read_ui32();
  230. m_ifs.ignore(uh);
  231. m_file.newStream(FourCC(ul));
  232. // More info ...
  233. }
  234. m_ifs.seekg(m_file.dataOffset());
  235. return;
  236. }
  237. //--------------------------------------
  238. template<typename T>
  239. void basic_Reader<T>::readFrame()
  240. {
  241. readFrameHeader();
  242. readPayload();
  243. return;
  244. }
  245. //--------------------------------------
  246. template<typename T>
  247. void basic_Reader<T>::readFrameInfo()
  248. {
  249. readFrameHeader();
  250. readPayloadInfo();
  251. return;
  252. }
  253. //--------------------------------------
  254. template<typename T>
  255. void basic_Reader<T>::readFrameHeader()
  256. {
  257. assert(m_ifs);
  258. // Read frame header signature
  259. char cSignature[5];
  260. m_ifs.read(cSignature, 2);
  261. if (strncmp(cSignature, "\xef\xbe", 2) == 0)
  262. {
  263. m_frameHeader.m_fccSignature = 0UL;
  264. m_frameHeader.m_bKeyFrame = false;
  265. m_file.syncOffset(0);
  266. return;
  267. }
  268. m_ifs.read(&cSignature[2], 2);
  269. if (strncmp(cSignature, "NSVs", 4) != 0)
  270. {
  271. throw Exception("Invalid NSV frame header");
  272. }
  273. cSignature[4] = '\0';
  274. m_frameHeader.m_fccSignature = cSignature;
  275. m_ifs.read(reinterpret_cast<char*>(&m_frameHeader.m_fccVideo), 4);
  276. m_ifs.read(reinterpret_cast<char*>(&m_frameHeader.m_fccAudio), 4);
  277. m_frameHeader.m_iWidth = read_i16();
  278. m_frameHeader.m_iHeight = read_i16();
  279. unsigned char uc;
  280. m_ifs.read(reinterpret_cast<char*>(&uc), 1);
  281. m_frameHeader.m_iFrameRate = uc;
  282. m_frameHeader.m_iSyncOffset_ms = read_i16();
  283. m_frameHeader.m_bKeyFrame = true;
  284. if (!m_bFrameHeader)
  285. {
  286. // m_file.newStream(m_frameHeader.m_fccVideo);
  287. // m_file.newStream(m_frameHeader.m_fccAudio);
  288. // m_file.size(m_frameHeader.m_iWidth, m_frameHeader.m_iHeight);
  289. // m_file.frameRate(m_frameHeader.m_iFrameRate);
  290. m_bFrameHeader = true;
  291. }
  292. else
  293. {
  294. if ((m_file.streamVideo() >= 0 && m_file.videoFormat() != m_frameHeader.m_fccVideo)
  295. || (m_file.streamAudio() >= 0 && m_file.audioFormat() != m_frameHeader.m_fccAudio)
  296. || m_file.width() != m_frameHeader.m_iWidth
  297. || m_file.height() != m_frameHeader.m_iHeight
  298. || m_file.frameRate() != m_frameHeader.m_iFrameRate)
  299. {
  300. throw Exception("Invalid NSV frame header");
  301. }
  302. }
  303. m_file.syncOffset(m_frameHeader.m_iSyncOffset_ms);
  304. return;
  305. }
  306. //--------------------------------------
  307. template<typename T>
  308. void basic_Reader<T>::readPayload()
  309. {
  310. assert(m_ifs);
  311. int nAux;
  312. int iAuxPlusVideo;
  313. int iAudio;
  314. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  315. int iAux = 0;
  316. for (int n = 0; n < nAux; ++n)
  317. {
  318. unsigned short uh = read_ui16();
  319. unsigned int ui = read_ui32();
  320. Stream& s = m_file.stream(m_file.streamAux(n));
  321. s.dataSize(uh);
  322. m_ifs.read(reinterpret_cast<char*>(s.data()), uh);
  323. iAux += uh;
  324. }
  325. if (m_file.streamVideo() >= 0)
  326. {
  327. int iVideo = iAuxPlusVideo - iAux;
  328. Stream& sVideo = m_file.stream(m_file.streamVideo());
  329. sVideo.dataSize(iVideo);
  330. m_ifs.read(reinterpret_cast<char*>(sVideo.data()), iVideo);
  331. sVideo.keyFrame(m_frameHeader.m_bKeyFrame);
  332. }
  333. else
  334. {
  335. m_ifs.seekg(iAuxPlusVideo - iAux, IOS_BASE::cur);
  336. }
  337. if (m_file.streamAudio() >= 0)
  338. {
  339. Stream& sAudio = m_file.stream(m_file.streamAudio());
  340. sAudio.dataSize(iAudio);
  341. m_ifs.read(reinterpret_cast<char*>(sAudio.data()), iAudio);
  342. sAudio.keyFrame(true);
  343. }
  344. else
  345. {
  346. m_ifs.seekg(iAudio, IOS_BASE::cur);
  347. }
  348. return;
  349. }
  350. //--------------------------------------
  351. template<typename T>
  352. void basic_Reader<T>::readPayloadInfo()
  353. {
  354. assert(m_ifs);
  355. int nAux;
  356. int iAuxPlusVideo;
  357. int iAudio;
  358. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  359. int iAux = 0;
  360. for (int n = 0; n < nAux; ++n)
  361. {
  362. unsigned short uh = read_ui16();
  363. unsigned int ui = read_ui32();
  364. m_ifs.ignore(uh);
  365. Stream& s = m_file.stream(m_file.streamAux(n));
  366. s.dataSize(uh);
  367. iAux += uh;
  368. }
  369. if (m_file.streamVideo() >= 0)
  370. {
  371. int iVideo = iAuxPlusVideo - iAux;
  372. Stream& sVideo = m_file.stream(m_file.streamVideo());
  373. sVideo.dataSize(iVideo);
  374. sVideo.keyFrame(m_frameHeader.m_bKeyFrame);
  375. }
  376. if (m_file.streamAudio() >= 0)
  377. {
  378. Stream& sAudio = m_file.stream(m_file.streamAudio());
  379. sAudio.dataSize(iAudio);
  380. sAudio.keyFrame(true);
  381. }
  382. return;
  383. }
  384. //--------------------------------------
  385. template<typename T>
  386. void basic_Reader<T>::readPayloadHeader(int& nAux, int& iAuxPlusVideo, int& iAudio)
  387. {
  388. assert(m_ifs);
  389. char c;
  390. unsigned short uh;
  391. unsigned short uhAudio;
  392. m_ifs.get(c);
  393. uh = read_ui16();
  394. uhAudio = read_ui16();
  395. nAux = c & 0xf;
  396. iAuxPlusVideo = (static_cast<int>(uh) << 4) | ((c >> 4) & 0xf);
  397. iAudio = uhAudio;
  398. return;
  399. }
  400. //--------------------------------------
  401. template<typename T>
  402. void basic_Reader<T>::buildIndex(int nIndexEntries)
  403. {
  404. assert(nIndexEntries == 0); // Only creates full index for now ...
  405. m_file.index().clear();
  406. m_file.frames(0);
  407. m_ifs.seekg(m_file.dataOffset());
  408. INT64 nFrames = 0;
  409. for (; !eof(); ++nFrames)
  410. {
  411. m_file.appendIndexEntry(static_cast<POS_TYPE>(m_ifs.tellg()) - m_file.dataOffset());
  412. readFrameHeader();
  413. int nAux;
  414. int iAuxPlusVideo;
  415. int iAudio;
  416. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  417. m_ifs.seekg(iAuxPlusVideo + iAudio, IOS_BASE::cur);
  418. }
  419. m_file.frames(nFrames);
  420. m_ifs.seekg(m_file.dataOffset());
  421. return;
  422. }
  423. //--------------------------------------
  424. template<typename T>
  425. INT64 basic_Reader<T>::frames() const
  426. {
  427. return m_file.frames();
  428. }
  429. //--------------------------------------
  430. template<typename T>
  431. INT64 basic_Reader<T>::frame() const
  432. {
  433. return m_nFrame;
  434. }
  435. //--------------------------------------
  436. template<typename T>
  437. void basic_Reader<T>::seek(INT64 nFrame)
  438. {
  439. assert(m_ifs);
  440. INT64 nFrames = m_file.frames();
  441. assert(nFrame < nFrames || nFrames == -1);
  442. int nIndexEntries = m_file.index().size();
  443. if (nIndexEntries > 0)
  444. {
  445. int nIndexEntry = nIndexEntries * nFrame / nFrames;
  446. INT64 nFrameIndex = (nIndexEntry * nFrames + nIndexEntries / 2) / nIndexEntries;
  447. m_ifs.seekg(m_file.dataOffset() + m_file.index()[nIndexEntry].m_posOffset);
  448. for (; nFrameIndex < nFrame; ++nFrameIndex)
  449. {
  450. readFrameHeader();
  451. int nAux;
  452. int iAuxPlusVideo;
  453. int iAudio;
  454. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  455. m_ifs.seekg(iAuxPlusVideo + iAudio, IOS_BASE::cur);
  456. }
  457. m_nFrame = nFrame;
  458. }
  459. else
  460. {
  461. m_ifs.seekg(m_file.dataOffset());
  462. for (m_nFrame = 0; m_nFrame < nFrame; ++m_nFrame)
  463. {
  464. readFrameHeader();
  465. int nAux;
  466. int iAuxPlusVideo;
  467. int iAudio;
  468. readPayloadHeader(nAux, iAuxPlusVideo, iAudio);
  469. m_ifs.seekg(iAuxPlusVideo + iAudio, IOS_BASE::cur);
  470. }
  471. assert(m_nFrame == nFrame);
  472. }
  473. return;
  474. }
  475. //--------------------------------------
  476. template<typename T>
  477. void basic_Reader<T>::readSample(int nStream, unsigned char* pData, size_t sizeDataMax, size_t& sizeData, bool& bKeyFrame)
  478. {
  479. assert(m_ifs);
  480. assert(pData != 0);
  481. readFrame();
  482. Stream& s = m_file.stream(nStream);
  483. size_t size = s.dataSize();
  484. if (sizeDataMax < s.dataSize())
  485. {
  486. size = sizeDataMax;
  487. }
  488. memcpy(pData, s.data(), size);
  489. sizeData = s.dataSize();
  490. bKeyFrame = s.keyFrame();
  491. return;
  492. }
  493. //--------------------------------------
  494. template<typename T>
  495. bool basic_Reader<T>::eof()
  496. {
  497. return m_ifs.tellg() >= m_fileHeader.m_sizeFile;
  498. }
  499. //--------------------------------------
  500. template<typename T>
  501. const FileHeader& basic_Reader<T>::fileHeader() const
  502. {
  503. return m_fileHeader;
  504. }
  505. //--------------------------------------
  506. template<typename T>
  507. const FrameHeader& basic_Reader<T>::frameHeader() const
  508. {
  509. return m_frameHeader;
  510. }
  511. //--------------------------------------
  512. template<typename T>
  513. void* basic_Reader<T>::get_ifs()
  514. {
  515. return &m_ifs;
  516. }
  517. //--------------------------------------
  518. template<typename T>
  519. short basic_Reader<T>::read_i16()
  520. {
  521. assert(m_ifs);
  522. short i16;
  523. m_ifs.read(reinterpret_cast<char*>(&i16), 2);
  524. return native_endian(i16, false);
  525. }
  526. //--------------------------------------
  527. template<typename T>
  528. unsigned short basic_Reader<T>::read_ui16()
  529. {
  530. assert(m_ifs);
  531. unsigned short ui16;
  532. m_ifs.read(reinterpret_cast<char*>(&ui16), 2);
  533. return native_endian(ui16, false);
  534. }
  535. //--------------------------------------
  536. template<typename T>
  537. int basic_Reader<T>::read_i32()
  538. {
  539. assert(m_ifs);
  540. int i32;
  541. m_ifs.read(reinterpret_cast<char*>(&i32), 4);
  542. return native_endian(i32, false);
  543. }
  544. //--------------------------------------
  545. template<typename T>
  546. unsigned int basic_Reader<T>::read_ui32()
  547. {
  548. assert(m_ifs);
  549. unsigned int ui32;
  550. m_ifs.read(reinterpret_cast<char*>(&ui32), 4);
  551. return native_endian(ui32, false);
  552. }
  553. } // namespace NSV
  554. #endif // NSV_READER_HPP