1
0

nsvlib.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. ** nsvlib.cpp - NSV file/bitstream reading/writing code
  3. **
  4. ** Copyright (C) 2001-2002 Nullsoft, Inc.
  5. **
  6. ** Confidential Subject to NDA
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <bfc/platform/strcmp.h>
  12. #include "nsvlib.h"
  13. #define NSV_HDR_DWORD (NSV_MAKETYPE('N','S','V','f'))
  14. #define NSV_SYNC_HEADERLEN_BITS 192
  15. #define NSV_SYNC_DWORD (NSV_MAKETYPE('N','S','V','s'))
  16. #define NSV_NONSYNC_HEADERLEN_BITS 56
  17. #define NSV_NONSYNC_WORD 0xBEEF
  18. #define NSV_INVALID_SYNC_OFFSET 0x80000000
  19. long glSyncFrameCount = 0l;
  20. long glCounterNSVf = 0l;
  21. long glNonSyncFrameCount = 0l;
  22. /*
  23. NSV sync packet header
  24. 32 bits: NSV_SYNC_DWORD
  25. 32 bits: video format
  26. 32 bits: audio format
  27. 16 bits: width
  28. 16 bits: height
  29. 8 bits: framerate (see getfrate/setfrate)
  30. 16 bits: audio/video sync offset
  31. or
  32. NSV nonsync packet header
  33. 16 bits: NSV_NONSYNC_WORD
  34. then
  35. 4 bits: # aux data channels present (max 15)
  36. 20 bits: video data + aux channels length
  37. 16 bits: audio data length
  38. --------------------------------
  39. sync:
  40. 192 bit header,
  41. 136 bits are invariant
  42. nonsync:
  43. 56 bit header
  44. 16 bits are invariant
  45. */
  46. static int is_type_char_valid(int c)
  47. {
  48. c&=0xff;
  49. return (c >= 'a' && c <= 'z') ||
  50. (c >= 'A' && c <= 'Z') ||
  51. (c >= '0' && c <= '9') ||
  52. c == ' ' || c == '-' ||
  53. c == '.' || c == '_';
  54. }
  55. static int is_type_valid(unsigned int t)
  56. {
  57. return (t&0xff) != ' ' &&
  58. is_type_char_valid(t>>24) &&
  59. is_type_char_valid(t>>16) &&
  60. is_type_char_valid(t>>8) &&
  61. is_type_char_valid(t);
  62. }
  63. void nsv_type_to_string(unsigned int t, char *out)
  64. {
  65. if (is_type_valid(t))
  66. {
  67. out[0]=(t)&0xff;
  68. out[1]=(t>>8)&0xff;
  69. out[2]=(t>>16)&0xff;
  70. out[3]=(t>>24)&0xff;
  71. out[4]=0;
  72. int x=3;
  73. while (out[x]==' ' && x > 0) out[x--]=0;
  74. }
  75. else *out=0;
  76. }
  77. unsigned int nsv_string_to_type(char *in)
  78. {
  79. int n;
  80. unsigned int ret=*in;
  81. if (*in == ' ' || !is_type_char_valid(*in)) return 0;
  82. in++;
  83. for (n = 0; n < 3; n ++)
  84. {
  85. if (!is_type_char_valid(*in)) break;
  86. ret|=(*in<<(8+8*n));
  87. in++;
  88. }
  89. if (*in) return 0;
  90. return ret;
  91. }
  92. // frate is specified
  93. // XYYYYYZZ
  94. // if !X, framerate is YYYYYZZ (1-127)
  95. // otherwise:
  96. // ZZ indexes base
  97. // YYYYY is scale (0-32).
  98. // if YYYYY < 16, then scale = 1/(YYYY+1)
  99. // otherwise scale = YYYYY-15
  100. static double frate2double(unsigned char fr)
  101. {
  102. static double fratetab[]=
  103. {
  104. 30.0,
  105. 30.0*1000.0/1001.0,
  106. 25.0,
  107. 24.0*1000.0/1001.0,
  108. };
  109. if (!(fr&0x80)) return (double)fr;
  110. double sc;
  111. int d=(fr&0x7f)>>2;
  112. if (d < 16) sc=1.0/(double)(d+1);
  113. else sc=d-15;
  114. return fratetab[fr&3]*sc;
  115. }
  116. static unsigned char double2frate(double fr)
  117. {
  118. int best=0;
  119. double best_v=1000000.0;
  120. int x;
  121. for (x = 0; x < 256; x ++)
  122. {
  123. double this_v=(fr-frate2double(x));
  124. if (this_v<0) this_v=-this_v;
  125. if (this_v < best_v)
  126. {
  127. best_v=this_v;
  128. best=x;
  129. }
  130. }
  131. return (unsigned char) best;
  132. }
  133. nsv_Packeter::nsv_Packeter()
  134. {
  135. vidfmt=audfmt=0;
  136. width=height=0;
  137. framerate_idx=0;
  138. framerate=0.0;
  139. syncoffset_cur=0;
  140. video=NULL;
  141. audio=NULL;
  142. video_len=0;
  143. audio_len=0;
  144. aux_used=0;
  145. }
  146. void nsv_Packeter::setVidFmt(unsigned int vfmt, unsigned int w, unsigned int h, double frt)
  147. {
  148. vidfmt=vfmt;
  149. width=w;
  150. height=h;
  151. framerate=frt;
  152. framerate_idx=double2frate(frt);
  153. }
  154. nsv_Packeter::~nsv_Packeter()
  155. {
  156. }
  157. int nsv_Packeter::packet(nsv_OutBS &bs)
  158. {
  159. int total_auxlen=0;
  160. int x;
  161. if (width >= (1<<16) || height >= (1<<16) ||
  162. !framerate_idx || framerate_idx > 255 ||
  163. !is_type_valid(audfmt) ||
  164. !is_type_valid(vidfmt) ||
  165. video_len > NSV_MAX_VIDEO_LEN ||
  166. audio_len > NSV_MAX_AUDIO_LEN ||
  167. aux_used > NSV_MAX_AUXSTREAMS ||
  168. aux_used < 0
  169. ) return -1;
  170. for (x = 0; x < aux_used; x ++)
  171. {
  172. if (aux_len[x] > NSV_MAX_AUX_LEN) return -1;
  173. total_auxlen+=aux_len[x]+6;
  174. }
  175. if (is_sync_frame)
  176. {
  177. bs.putbits(32,NSV_SYNC_DWORD);
  178. bs.putbits(32,vidfmt);
  179. bs.putbits(32,audfmt);
  180. bs.putbits(16,width);
  181. bs.putbits(16,height);
  182. bs.putbits(8 ,framerate_idx);
  183. bs.putbits(16,syncoffset_cur);
  184. }
  185. else
  186. {
  187. bs.putbits(16,NSV_NONSYNC_WORD);
  188. }
  189. bs.putbits(4,aux_used); // no aux data channels for our streams yet
  190. bs.putbits(20,video_len+total_auxlen);
  191. bs.putbits(16,audio_len);
  192. for (x = 0; x < aux_used; x ++)
  193. {
  194. bs.putbits(16,aux_len[x]); // length of 0 for aux channels
  195. bs.putbits(32,aux_types[x]);
  196. if (aux_len[x]) bs.putdata(aux_len[x]*8,aux[x]);
  197. }
  198. if (video_len) bs.putdata(video_len*8,video);
  199. if (audio_len) bs.putdata(audio_len*8,audio);
  200. return 0;
  201. }
  202. void nsv_Unpacketer::reset(int full)
  203. {
  204. synched=0;
  205. is_sync_frame=0;
  206. syncoffset_cur=0;
  207. syncoffset=NSV_INVALID_SYNC_OFFSET;
  208. if (full)
  209. {
  210. m_auxbs=NULL;
  211. m_audiobs=NULL;
  212. m_videobs=NULL;
  213. m_eof=0;
  214. vidfmt=0;
  215. audfmt=0;
  216. valid=0;
  217. width=0;
  218. height=0;
  219. framerate=0.0;
  220. framerate_idx=0;
  221. }
  222. }
  223. // returns 0 on success, >0 on needs (at least X bytes) more data,
  224. // -1 on error (no header found in block)
  225. int nsv_Unpacketer::unpacket(nsv_InBS &bs)
  226. {
  227. int gotframe=0;
  228. unsigned int num_aux=0;
  229. unsigned int vl=0;
  230. unsigned int al=0;
  231. while (bs.avail()>=NSV_NONSYNC_HEADERLEN_BITS)
  232. {
  233. if (valid && synched)
  234. {
  235. if (bs.avail() < NSV_NONSYNC_HEADERLEN_BITS)
  236. return m_eof?-1:(NSV_NONSYNC_HEADERLEN_BITS- (int)(bs.avail())/8);
  237. unsigned int d=bs.getbits(16);
  238. if (d == NSV_NONSYNC_WORD)
  239. {
  240. glNonSyncFrameCount++;
  241. num_aux=bs.getbits(4);
  242. vl=bs.getbits(20);
  243. al=bs.getbits(16);
  244. if (al >= NSV_MAX_AUDIO_LEN ||
  245. vl >= (NSV_MAX_VIDEO_LEN+num_aux*(NSV_MAX_AUX_LEN+6)))
  246. {
  247. bs.seek(-NSV_NONSYNC_HEADERLEN_BITS);
  248. }
  249. else
  250. {
  251. if ((unsigned int)bs.avail() < 8*(vl+al)+(m_eof?0:32))
  252. {
  253. int l=(al+vl+32/8)- (int)(bs.avail()/8);
  254. bs.seek(-NSV_NONSYNC_HEADERLEN_BITS);
  255. return m_eof?-1:l;
  256. }
  257. if ((unsigned int)bs.avail() >= 8*(vl+al)+32)
  258. {
  259. bs.seek(8*(vl+al));
  260. unsigned int a32=bs.getbits(32);
  261. bs.seek(-32);
  262. unsigned int a16=bs.getbits(16);
  263. bs.seek(-16);
  264. bs.seek(-8*(vl+al));
  265. if (a16 != NSV_NONSYNC_WORD && a32 != NSV_SYNC_DWORD)
  266. {
  267. bs.seek(-NSV_NONSYNC_HEADERLEN_BITS);
  268. }
  269. else gotframe=NSV_NONSYNC_HEADERLEN_BITS;
  270. }
  271. else gotframe=NSV_NONSYNC_HEADERLEN_BITS;
  272. }
  273. }
  274. else bs.seek(-16);
  275. } // inf.valid && inf.synched
  276. // gotframe is set if we successfully got a nonsync frame, otherwise
  277. // let's see if we can't interpret this as a sync frame
  278. if (!gotframe)
  279. {
  280. if (bs.avail() < NSV_SYNC_HEADERLEN_BITS)
  281. return (int)(m_eof?-1:(NSV_SYNC_HEADERLEN_BITS-(bs.avail())/8));
  282. unsigned int d=bs.getbits(32);
  283. if (d != NSV_SYNC_DWORD)
  284. {
  285. bs.seek(8-32); // seek back 3 bytes
  286. synched=0;
  287. continue;
  288. }else{
  289. // count the # of sync frames (for debugging)
  290. glSyncFrameCount++;
  291. }
  292. unsigned int vfmt=bs.getbits(32);
  293. unsigned int afmt=bs.getbits(32);
  294. unsigned int w=bs.getbits(16);
  295. unsigned int h=bs.getbits(16);
  296. unsigned char frt=bs.getbits(8);
  297. unsigned int so=bs.getbits(16);
  298. num_aux=bs.getbits(4);
  299. vl=bs.getbits(20);
  300. al=bs.getbits(16);
  301. if (al >= NSV_MAX_AUDIO_LEN ||
  302. vl >= (NSV_MAX_VIDEO_LEN+num_aux*(NSV_MAX_AUX_LEN+6)) ||
  303. !frt || !is_type_valid(vfmt) || !is_type_valid(afmt) ||
  304. (valid &&
  305. (width != w || height != h ||
  306. vidfmt != vfmt || audfmt != afmt || framerate_idx != frt)))
  307. { // frame is definately not valid
  308. bs.seek(8-NSV_SYNC_HEADERLEN_BITS); // seek back what we just read
  309. synched=0;
  310. continue;
  311. }
  312. if ((unsigned int)bs.avail() < (al+vl)*8+((m_eof||(valid&&synched))?0:32))
  313. {
  314. int l=(al+vl)*8+NSV_SYNC_HEADERLEN_BITS- (int)(bs.avail());
  315. bs.seek(-NSV_SYNC_HEADERLEN_BITS);
  316. return m_eof?-1:(l/8);
  317. }
  318. if (valid && synched)
  319. {
  320. gotframe=NSV_SYNC_HEADERLEN_BITS;
  321. }
  322. else // we need to do more robust sync
  323. {
  324. int sk=(al+vl)*8;
  325. bs.seek(sk);
  326. unsigned int a16=bs.getbits(16);
  327. bs.seek(-16);
  328. unsigned int a32=bs.getbits(32);
  329. bs.seek(-32);
  330. if (a16 == NSV_NONSYNC_WORD)
  331. {
  332. sk+=16+4+20+16;
  333. bs.seek(16);
  334. unsigned int _num_aux=bs.getbits(4);
  335. unsigned int _vl=bs.getbits(20);
  336. unsigned int _al=bs.getbits(16);
  337. if ((unsigned int)bs.avail() < (_vl+_al)*8 + 32)
  338. {
  339. int l=(_al+_vl+32)- (int)(bs.avail()/8);
  340. bs.seek(-NSV_SYNC_HEADERLEN_BITS-sk);
  341. return m_eof?-1:l;
  342. }
  343. bs.seek((_vl+_al)*8);
  344. sk+=(_vl+_al)*8;
  345. unsigned int a16=bs.getbits(16);
  346. bs.seek(-16);
  347. unsigned int a32=bs.getbits(32);
  348. bs.seek(-32);
  349. bs.seek(-sk);
  350. if (a16 == NSV_NONSYNC_WORD || a32 == NSV_SYNC_DWORD)
  351. gotframe=NSV_SYNC_HEADERLEN_BITS;
  352. }
  353. else if (a32 == NSV_SYNC_DWORD)
  354. {
  355. glSyncFrameCount++;
  356. sk+=32+32+32+16+16+8;
  357. bs.seek(32);
  358. unsigned int _vfmt=bs.getbits(32);
  359. unsigned int _afmt=bs.getbits(32);
  360. unsigned int _w=bs.getbits(16);
  361. unsigned int _h=bs.getbits(16);
  362. unsigned char _frt=bs.getbits(8);
  363. bs.seek(-sk);
  364. if (_vfmt==vfmt && _afmt==afmt && _w==w && _h==h && _frt==frt) // matches
  365. {
  366. gotframe=NSV_SYNC_HEADERLEN_BITS;
  367. }
  368. }
  369. }
  370. if (!gotframe)
  371. {
  372. synched=0;
  373. bs.seek(8-NSV_SYNC_HEADERLEN_BITS);
  374. }
  375. else
  376. {
  377. if (so & 0x8000) so|=0xFFFF0000;
  378. syncoffset_cur=so;
  379. if (!valid || syncoffset == NSV_INVALID_SYNC_OFFSET) syncoffset=so;
  380. if (!valid) framerate=frate2double(frt);
  381. framerate_idx=frt;
  382. width=w;
  383. height=h;
  384. audfmt=afmt;
  385. vidfmt=vfmt;
  386. valid=1;
  387. synched=1;
  388. }
  389. }
  390. if (gotframe)
  391. {
  392. is_sync_frame = (gotframe == NSV_SYNC_HEADERLEN_BITS);
  393. // read aux channels
  394. int rd=gotframe;
  395. unsigned int x;
  396. for (x = 0; x < num_aux; x ++)
  397. {
  398. unsigned int l=bs.getbits(16);
  399. unsigned int fmt=bs.getbits(32);
  400. vl -= 4+2;
  401. rd += 16+32;
  402. if (l > NSV_MAX_AUX_LEN) break;
  403. if (m_auxbs)
  404. {
  405. m_auxbs->addint(l);
  406. m_auxbs->addint(fmt);
  407. m_auxbs->add(bs.getcurbyteptr(),l);
  408. }
  409. bs.seek(l*8); // toss aux
  410. vl-=l;
  411. rd+=l*8;
  412. if (vl<0) break; // invalid frame (aux channels add up to more than video)
  413. }
  414. if (x < num_aux) // oh shit, invalid frame
  415. {
  416. synched=0;
  417. bs.seek(8-rd);
  418. gotframe=0;
  419. continue;
  420. }
  421. if (m_videobs)
  422. {
  423. m_videobs->addint(vl);
  424. m_videobs->add(bs.getcurbyteptr(),vl);
  425. }
  426. bs.seek(vl*8);
  427. if (m_audiobs)
  428. {
  429. m_audiobs->addint(al);
  430. m_audiobs->add(bs.getcurbyteptr(),al);
  431. }
  432. bs.seek(al*8);
  433. return 0;
  434. }
  435. } // while
  436. return m_eof?-1:(NSV_NONSYNC_HEADERLEN_BITS- (int)(bs.avail())/8);
  437. }
  438. /* NSV file header
  439. 4: NSV_HDR_DWORD
  440. 4: length of header in bytes
  441. -- may not be 0 or 0xFFFFFFFF. :)
  442. 4: length of file, in bytes (including header - if this is 0 we are invalid)
  443. -- can be 0xFFFFFFFF which means unknown length
  444. 4: length of file, in milliseconds (max file length, 24 days or so)
  445. -- can be 0xFFFFFFFF which means unknown length
  446. 4: metadata length
  447. 4: number of TOC entries allocated
  448. 4: number of TOC entries used
  449. mdlen: metadata
  450. TOC_alloc*4:offset in file at time t.
  451. */
  452. void nsv_writeheader(nsv_OutBS &bs, nsv_fileHeader *hdr, unsigned int padto)
  453. {
  454. if (hdr->toc_alloc < hdr->toc_size)
  455. hdr->toc_alloc=hdr->toc_size;
  456. if (hdr->toc_ex && hdr->toc_alloc <= hdr->toc_size*2)
  457. hdr->toc_alloc=hdr->toc_size*2+1;
  458. hdr->header_size = 4+4+4+4+4+hdr->metadata_len+4+4+4*hdr->toc_alloc;
  459. bs.putbits(32,NSV_HDR_DWORD);
  460. bs.putbits(32,hdr->header_size>padto?hdr->header_size:padto);
  461. if (hdr->file_lenbytes == 0xFFFFFFFF) bs.putbits(32,hdr->file_lenbytes);
  462. else bs.putbits(32,hdr->file_lenbytes+(hdr->header_size>padto?hdr->header_size:padto));
  463. bs.putbits(32,hdr->file_lenms);
  464. bs.putbits(32,hdr->metadata_len);
  465. bs.putbits(32,hdr->toc_alloc);
  466. bs.putbits(32,hdr->toc_size);
  467. bs.putdata(hdr->metadata_len*8,hdr->metadata);
  468. unsigned int numtoc=hdr->toc_alloc;
  469. unsigned int numtocused=hdr->toc_size;
  470. unsigned int *toc=hdr->toc;
  471. unsigned int *toc_ex=hdr->toc_ex;
  472. unsigned int numtocused2=(toc_ex && hdr->toc_alloc > hdr->toc_size*2) ? (hdr->toc_size + 1): 0;
  473. while (numtoc--)
  474. {
  475. if (!numtocused)
  476. {
  477. if (numtocused2)
  478. {
  479. if (--numtocused2 == hdr->toc_size) // signal extended TOC :)
  480. bs.putbits(32,NSV_MAKETYPE('T','O','C','2'));
  481. else
  482. bs.putbits(32,*toc_ex++);
  483. }
  484. else // extra (unused by this implementation but could be used someday so we fill it with 0xFF) space
  485. bs.putbits(32,~0);
  486. }
  487. else if (toc)
  488. {
  489. bs.putbits(32,*toc++);
  490. numtocused--;
  491. }
  492. else bs.putbits(32,0);
  493. }
  494. unsigned int x;
  495. for (x = hdr->header_size; x < padto; x ++) bs.putbits(8,0);
  496. }
  497. int nsv_readheader(nsv_InBS &bs, nsv_fileHeader *hdr)
  498. {
  499. int s=0;
  500. hdr->metadata=(void*)NULL;
  501. hdr->toc=(unsigned int *)NULL;
  502. hdr->toc_ex=(unsigned int *)NULL;
  503. hdr->header_size=0;
  504. hdr->file_lenbytes=~0;
  505. hdr->file_lenms=~0;
  506. hdr->toc_alloc=0;
  507. hdr->toc_size=0;
  508. hdr->metadata_len=0;
  509. if (bs.avail()<64) {
  510. return 8- (int)(bs.avail()/8);
  511. }
  512. s+=32;
  513. if (bs.getbits(32) != NSV_HDR_DWORD)
  514. {
  515. bs.seek(-s);
  516. return -1;
  517. }else{
  518. glCounterNSVf++;
  519. }
  520. s+=32;
  521. unsigned int headersize=bs.getbits(32);
  522. if (headersize >= 0x20000000)
  523. {
  524. bs.seek(-s);
  525. return -1;
  526. }
  527. if ((unsigned int)bs.avail() < (headersize-4)*8)
  528. {
  529. int l=headersize-4- (int)(bs.avail()/8);
  530. bs.seek(-s);
  531. return l;
  532. }
  533. s+=32;
  534. unsigned int lenbytes=bs.getbits(32);
  535. s+=32;
  536. unsigned int lenms=bs.getbits(32);
  537. s+=32;
  538. unsigned int metadatalen=bs.getbits(32);
  539. s+=32;
  540. unsigned int tocalloc=bs.getbits(32);
  541. s+=32;
  542. unsigned int tocsize=bs.getbits(32);
  543. if (tocalloc < tocsize || lenbytes < headersize || tocalloc + metadatalen + s/8 > headersize)
  544. {
  545. bs.seek(-s);
  546. return -1;
  547. }
  548. void *metadata=NULL;
  549. if (metadatalen)
  550. {
  551. if (metadatalen > (SIZE_MAX/8))
  552. {
  553. bs.seek(-s);
  554. return -1;
  555. }
  556. metadata=malloc(metadatalen+1);
  557. if (!metadata)
  558. {
  559. bs.seek(-s);
  560. return -1;
  561. }
  562. s+=metadatalen*8;
  563. bs.getdata(metadatalen*8,metadata);
  564. ((char*)metadata)[metadatalen]=0;
  565. }
  566. unsigned int *toc=NULL;
  567. unsigned int *toc_ex=NULL;
  568. if (tocalloc && tocsize < (SIZE_MAX/8))
  569. {
  570. toc=(unsigned int *)malloc(tocsize * 4 * 2);
  571. if (!toc)
  572. {
  573. free(metadata);
  574. bs.seek(-s);
  575. return -1;
  576. }
  577. unsigned int x;
  578. int bitsread=0;
  579. for (x = 0; x < tocsize; x ++) { toc[x] = bs.getbits(32); bitsread += 32; }
  580. if (tocalloc > tocsize*2)
  581. {
  582. bitsread += 32;
  583. if (bs.getbits(32) == NSV_MAKETYPE('T','O','C','2'))
  584. {
  585. toc_ex=toc + tocsize;
  586. for (x = 0; x < tocsize; x ++) { toc_ex[x] = bs.getbits(32); bitsread += 32; }
  587. }
  588. }
  589. bs.seek((tocalloc-tocsize)*32 - bitsread);
  590. s+=tocalloc*32;
  591. }
  592. hdr->header_size=headersize;
  593. if (lenbytes == 0xFFFFFFFF)
  594. hdr->file_lenbytes=lenbytes;
  595. else
  596. hdr->file_lenbytes=lenbytes-headersize;
  597. hdr->file_lenms=lenms;
  598. hdr->metadata=metadata;
  599. hdr->metadata_len=metadatalen;
  600. hdr->toc=toc;
  601. hdr->toc_ex=toc_ex;
  602. hdr->toc_alloc=tocalloc;
  603. hdr->toc_size=tocsize;
  604. return 0;
  605. }
  606. char *nsv_getmetadata(void *metadata, char *name)
  607. {
  608. if (!metadata) return NULL;
  609. char *p=(char*)metadata;
  610. size_t ln=strlen(name);
  611. for (;;)
  612. {
  613. while (p && (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')) p++;
  614. if (p || !*p) break;
  615. if (!_strnicmp(p,name,ln) && p[ln]=='=' && p[ln+1] && p[ln+2])
  616. {
  617. int cnt=0;
  618. char *np=p+ln+1;
  619. char c=*np++;
  620. while (np[cnt] && np[cnt] != c) cnt++;
  621. char *s=(char*)malloc(cnt+1);
  622. if (!s) return NULL;
  623. memcpy(s,np,cnt);
  624. s[cnt]=0;
  625. return s;
  626. }
  627. // advance to next item
  628. while (p && *p && *p != '=') p++;
  629. if (!*p++) break;
  630. if (!*p) break;
  631. char c=*p++;
  632. while (p && *p && *p != c) p++;
  633. if (*p) p++;
  634. }
  635. return NULL;
  636. }