You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

757 lines
24KB

  1. /*
  2. * NSV decoder.
  3. * Copyright (c) 2004 The FFmpeg Project.
  4. *
  5. * This file is part of FFmpeg.
  6. *
  7. * FFmpeg is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * FFmpeg is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with FFmpeg; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. */
  21. #include "avformat.h"
  22. #include "riff.h"
  23. #define DEBUG
  24. //#define DEBUG_DUMP_INDEX // XXX dumbdriving-271.nsv breaks with it commented!!
  25. //#define DEBUG_SEEK
  26. #define CHECK_SUBSEQUENT_NSVS
  27. //#define DISABLE_AUDIO
  28. /* max bytes to crawl for trying to resync
  29. * stupid streaming servers don't start at chunk boundaries...
  30. */
  31. #define NSV_MAX_RESYNC (500*1024)
  32. #define NSV_MAX_RESYNC_TRIES 300
  33. /*
  34. * First version by Francois Revol - revol@free.fr
  35. * References:
  36. * (1) http://www.multimedia.cx/nsv-format.txt
  37. * seems someone came to the same conclusions as me, and updated it:
  38. * (2) http://www.stud.ktu.lt/~vitslav/nsv/nsv-format.txt
  39. * http://www.stud.ktu.lt/~vitslav/nsv/
  40. * Sample files:
  41. * (S1) http://www.nullsoft.com/nsv/samples/
  42. * http://www.nullsoft.com/nsv/samples/faster.nsv
  43. * http://streamripper.sourceforge.net/openbb/read.php?TID=492&page=4
  44. */
  45. /*
  46. * notes on the header (Francois Revol):
  47. *
  48. * It is followed by strings, then a table, but nothing tells
  49. * where the table begins according to (1). After checking faster.nsv,
  50. * I believe NVSf[16-19] gives the size of the strings data
  51. * (that is the offset of the data table after the header).
  52. * After checking all samples from (S1) all confirms this.
  53. *
  54. * Then, about NSVf[12-15], faster.nsf has 179700. When veiwing it in VLC,
  55. * I noticed there was about 1 NVSs chunk/s, so I ran
  56. * strings faster.nsv | grep NSVs | wc -l
  57. * which gave me 180. That leads me to think that NSVf[12-15] might be the
  58. * file length in milliseconds.
  59. * Let's try that:
  60. * for f in *.nsv; do HTIME="$(od -t x4 "$f" | head -1 | sed 's/.* //')"; echo "'$f' $((0x$HTIME))s = $((0x$HTIME/1000/60)):$((0x$HTIME/1000%60))"; done
  61. * except for nstrailer (which doesn't have an NSVf header), it repports correct time.
  62. *
  63. * nsvtrailer.nsv (S1) does not have any NSVf header, only NSVs chunks,
  64. * so the header seems to not be mandatory. (for streaming).
  65. *
  66. * index slice duration check (excepts nsvtrailer.nsv):
  67. * for f in [^n]*.nsv; do DUR="$(ffmpeg -i "$f" 2>/dev/null | grep 'NSVf duration' | cut -d ' ' -f 4)"; IC="$(ffmpeg -i "$f" 2>/dev/null | grep 'INDEX ENTRIES' | cut -d ' ' -f 2)"; echo "duration $DUR, slite time $(($DUR/$IC))"; done
  68. */
  69. /*
  70. * TODO:
  71. * - handle timestamps !!!
  72. * - use index
  73. * - mime-type in probe()
  74. * - seek
  75. */
  76. #ifdef DEBUG
  77. #define PRINT(_v) printf _v
  78. #else
  79. #define PRINT(_v)
  80. #endif
  81. #if 0
  82. struct NSVf_header {
  83. uint32_t chunk_tag; /* 'NSVf' */
  84. uint32_t chunk_size;
  85. uint32_t file_size; /* max 4GB ??? noone learns anything it seems :^) */
  86. uint32_t file_length; //unknown1; /* what about MSB of file_size ? */
  87. uint32_t info_strings_size; /* size of the info strings */ //unknown2;
  88. uint32_t table_entries;
  89. uint32_t table_entries_used; /* the left ones should be -1 */
  90. };
  91. struct NSVs_header {
  92. uint32_t chunk_tag; /* 'NSVs' */
  93. uint32_t v4cc; /* or 'NONE' */
  94. uint32_t a4cc; /* or 'NONE' */
  95. uint16_t vwidth; /* assert(vwidth%16==0) */
  96. uint16_t vheight; /* assert(vheight%16==0) */
  97. uint8_t framerate; /* value = (framerate&0x80)?frtable[frameratex0x7f]:framerate */
  98. uint16_t unknown;
  99. };
  100. struct nsv_avchunk_header {
  101. uint8_t vchunk_size_lsb;
  102. uint16_t vchunk_size_msb; /* value = (vchunk_size_msb << 4) | (vchunk_size_lsb >> 4) */
  103. uint16_t achunk_size;
  104. };
  105. struct nsv_pcm_header {
  106. uint8_t bits_per_sample;
  107. uint8_t channel_count;
  108. uint16_t sample_rate;
  109. };
  110. #endif
  111. /* variation from avi.h */
  112. /*typedef struct CodecTag {
  113. int id;
  114. unsigned int tag;
  115. } CodecTag;*/
  116. /* tags */
  117. #define T_NSVF MKTAG('N', 'S', 'V', 'f') /* file header */
  118. #define T_NSVS MKTAG('N', 'S', 'V', 's') /* chunk header */
  119. #define T_TOC2 MKTAG('T', 'O', 'C', '2') /* extra index marker */
  120. #define T_NONE MKTAG('N', 'O', 'N', 'E') /* null a/v 4CC */
  121. #define T_SUBT MKTAG('S', 'U', 'B', 'T') /* subtitle aux data */
  122. #define T_ASYN MKTAG('A', 'S', 'Y', 'N') /* async a/v aux marker */
  123. #define T_KEYF MKTAG('K', 'E', 'Y', 'F') /* video keyframe aux marker (addition) */
  124. #define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
  125. #define TB_NSVS MKBETAG('N', 'S', 'V', 's')
  126. /* hardcoded stream indices */
  127. #define NSV_ST_VIDEO 0
  128. #define NSV_ST_AUDIO 1
  129. #define NSV_ST_SUBT 2
  130. enum NSVStatus {
  131. NSV_UNSYNC,
  132. NSV_FOUND_NSVF,
  133. NSV_HAS_READ_NSVF,
  134. NSV_FOUND_NSVS,
  135. NSV_HAS_READ_NSVS,
  136. NSV_FOUND_BEEF,
  137. NSV_GOT_VIDEO,
  138. NSV_GOT_AUDIO,
  139. };
  140. typedef struct NSVStream {
  141. int frame_offset; /* current frame (video) or byte (audio) counter
  142. (used to compute the pts) */
  143. int scale;
  144. int rate;
  145. int sample_size; /* audio only data */
  146. int start;
  147. int new_frame_offset; /* temporary storage (used during seek) */
  148. int cum_len; /* temporary storage (used during seek) */
  149. } NSVStream;
  150. typedef struct {
  151. int base_offset;
  152. int NSVf_end;
  153. uint32_t *nsvf_index_data;
  154. int index_entries;
  155. enum NSVStatus state;
  156. AVPacket ahead[2]; /* [v, a] if .data is !NULL there is something */
  157. /* cached */
  158. int64_t duration;
  159. uint32_t vtag, atag;
  160. uint16_t vwidth, vheight;
  161. //DVDemuxContext* dv_demux;
  162. } NSVContext;
  163. static const CodecTag nsv_codec_video_tags[] = {
  164. { CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
  165. { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
  166. { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
  167. { CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
  168. { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
  169. { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
  170. /*
  171. { CODEC_ID_VP4, MKTAG('V', 'P', '4', ' ') },
  172. { CODEC_ID_VP4, MKTAG('V', 'P', '4', '0') },
  173. { CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
  174. { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
  175. { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
  176. */
  177. { CODEC_ID_XVID, MKTAG('X', 'V', 'I', 'D') }, /* cf sample xvid decoder from nsv_codec_sdk.zip */
  178. { CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
  179. { 0, 0 },
  180. };
  181. static const CodecTag nsv_codec_audio_tags[] = {
  182. { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
  183. { CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
  184. { CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') }, /* _CUTTED__MUXED_2 Heads - Out Of The City.nsv */
  185. { CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
  186. { 0, 0 },
  187. };
  188. static const AVRational nsv_framerate_table[] = {
  189. {30,1},
  190. {30000,1001},
  191. {25,1},
  192. {24000,1001},
  193. {30,1},
  194. {15000,1001},
  195. };
  196. //static int nsv_load_index(AVFormatContext *s);
  197. static int nsv_read_chunk(AVFormatContext *s, int fill_header);
  198. #ifdef DEBUG
  199. static void print_tag(const char *str, unsigned int tag, int size)
  200. {
  201. printf("%s: tag=%c%c%c%c\n",
  202. str, tag & 0xff,
  203. (tag >> 8) & 0xff,
  204. (tag >> 16) & 0xff,
  205. (tag >> 24) & 0xff);
  206. }
  207. #endif
  208. /* try to find something we recognize, and set the state accordingly */
  209. static int nsv_resync(AVFormatContext *s)
  210. {
  211. NSVContext *nsv = s->priv_data;
  212. ByteIOContext *pb = &s->pb;
  213. uint32_t v = 0;
  214. int i;
  215. PRINT(("%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, url_ftell(pb), nsv->state));
  216. //nsv->state = NSV_UNSYNC;
  217. for (i = 0; i < NSV_MAX_RESYNC; i++) {
  218. if (url_feof(pb)) {
  219. PRINT(("NSV EOF\n"));
  220. nsv->state = NSV_UNSYNC;
  221. return -1;
  222. }
  223. v <<= 8;
  224. v |= get_byte(pb);
  225. /*
  226. if (i < 8) {
  227. PRINT(("NSV resync: [%d] = %02x\n", i, v & 0x0FF));
  228. }
  229. */
  230. if ((v & 0x0000ffff) == 0xefbe) { /* BEEF */
  231. PRINT(("NSV resynced on BEEF after %d bytes\n", i+1));
  232. nsv->state = NSV_FOUND_BEEF;
  233. return 0;
  234. }
  235. /* we read as big endian, thus the MK*BE* */
  236. if (v == TB_NSVF) { /* NSVf */
  237. PRINT(("NSV resynced on NSVf after %d bytes\n", i+1));
  238. nsv->state = NSV_FOUND_NSVF;
  239. return 0;
  240. }
  241. if (v == MKBETAG('N', 'S', 'V', 's')) { /* NSVs */
  242. PRINT(("NSV resynced on NSVs after %d bytes\n", i+1));
  243. nsv->state = NSV_FOUND_NSVS;
  244. return 0;
  245. }
  246. }
  247. PRINT(("NSV sync lost\n"));
  248. return -1;
  249. }
  250. static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
  251. {
  252. NSVContext *nsv = s->priv_data;
  253. ByteIOContext *pb = &s->pb;
  254. unsigned int file_size, size;
  255. int64_t duration;
  256. int strings_size;
  257. int table_entries;
  258. int table_entries_used;
  259. PRINT(("%s()\n", __FUNCTION__));
  260. nsv->state = NSV_UNSYNC; /* in case we fail */
  261. size = get_le32(pb);
  262. if (size < 28)
  263. return -1;
  264. nsv->NSVf_end = size;
  265. //s->file_size = (uint32_t)get_le32(pb);
  266. file_size = (uint32_t)get_le32(pb);
  267. PRINT(("NSV NSVf chunk_size %u\n", size));
  268. PRINT(("NSV NSVf file_size %u\n", file_size));
  269. nsv->duration = duration = get_le32(pb); /* in ms */
  270. PRINT(("NSV NSVf duration %"PRId64" ms\n", duration));
  271. // XXX: store it in AVStreams
  272. strings_size = get_le32(pb);
  273. table_entries = get_le32(pb);
  274. table_entries_used = get_le32(pb);
  275. PRINT(("NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
  276. strings_size, table_entries, table_entries_used));
  277. if (url_feof(pb))
  278. return -1;
  279. PRINT(("NSV got header; filepos %"PRId64"\n", url_ftell(pb)));
  280. if (strings_size > 0) {
  281. char *strings; /* last byte will be '\0' to play safe with str*() */
  282. char *p, *endp;
  283. char *token, *value;
  284. char quote;
  285. p = strings = av_mallocz(strings_size + 1);
  286. endp = strings + strings_size;
  287. get_buffer(pb, strings, strings_size);
  288. while (p < endp) {
  289. while (*p == ' ')
  290. p++; /* strip out spaces */
  291. if (p >= endp-2)
  292. break;
  293. token = p;
  294. p = strchr(p, '=');
  295. if (!p || p >= endp-2)
  296. break;
  297. *p++ = '\0';
  298. quote = *p++;
  299. value = p;
  300. p = strchr(p, quote);
  301. if (!p || p >= endp)
  302. break;
  303. *p++ = '\0';
  304. PRINT(("NSV NSVf INFO: %s='%s'\n", token, value));
  305. if (!strcmp(token, "ASPECT")) {
  306. /* don't care */
  307. } else if (!strcmp(token, "CREATOR") || !strcmp(token, "Author")) {
  308. strncpy(s->author, value, 512-1);
  309. } else if (!strcmp(token, "Copyright")) {
  310. strncpy(s->copyright, value, 512-1);
  311. } else if (!strcmp(token, "TITLE") || !strcmp(token, "Title")) {
  312. strncpy(s->title, value, 512-1);
  313. }
  314. }
  315. av_free(strings);
  316. }
  317. if (url_feof(pb))
  318. return -1;
  319. PRINT(("NSV got infos; filepos %"PRId64"\n", url_ftell(pb)));
  320. if (table_entries_used > 0) {
  321. nsv->index_entries = table_entries_used;
  322. if((unsigned)table_entries >= UINT_MAX / sizeof(uint32_t))
  323. return -1;
  324. nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));
  325. #warning "FIXME: Byteswap buffer as needed"
  326. get_buffer(pb, (unsigned char *)nsv->nsvf_index_data, table_entries * sizeof(uint32_t));
  327. }
  328. PRINT(("NSV got index; filepos %"PRId64"\n", url_ftell(pb)));
  329. #ifdef DEBUG_DUMP_INDEX
  330. #define V(v) ((v<0x20 || v > 127)?'.':v)
  331. /* dump index */
  332. PRINT(("NSV %d INDEX ENTRIES:\n", table_entries));
  333. PRINT(("NSV [dataoffset][fileoffset]\n", table_entries));
  334. for (i = 0; i < table_entries; i++) {
  335. unsigned char b[8];
  336. url_fseek(pb, size + nsv->nsvf_index_data[i], SEEK_SET);
  337. get_buffer(pb, b, 8);
  338. PRINT(("NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
  339. "%c%c%c%c%c%c%c%c\n",
  340. nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i],
  341. b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
  342. V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ));
  343. }
  344. //url_fseek(pb, size, SEEK_SET); /* go back to end of header */
  345. #undef V
  346. #endif
  347. url_fseek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */
  348. if (url_feof(pb))
  349. return -1;
  350. nsv->state = NSV_HAS_READ_NSVF;
  351. return 0;
  352. }
  353. static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
  354. {
  355. NSVContext *nsv = s->priv_data;
  356. ByteIOContext *pb = &s->pb;
  357. uint32_t vtag, atag;
  358. uint16_t vwidth, vheight;
  359. AVRational framerate;
  360. int i;
  361. uint16_t unknown;
  362. AVStream *st;
  363. NSVStream *nst;
  364. PRINT(("%s()\n", __FUNCTION__));
  365. vtag = get_le32(pb);
  366. atag = get_le32(pb);
  367. vwidth = get_le16(pb);
  368. vheight = get_le16(pb);
  369. i = get_byte(pb);
  370. /* XXX how big must the table be ? */
  371. /* seems there is more to that... */
  372. PRINT(("NSV NSVs framerate code %2x\n", i));
  373. if(i&0x80) framerate= nsv_framerate_table[i & 0x7F];
  374. else framerate= (AVRational){i, 1};
  375. unknown = get_le16(pb);
  376. #ifdef DEBUG
  377. print_tag("NSV NSVs vtag", vtag, 0);
  378. print_tag("NSV NSVs atag", atag, 0);
  379. PRINT(("NSV NSVs vsize %dx%d\n", vwidth, vheight));
  380. #endif
  381. /* XXX change to ap != NULL ? */
  382. if (s->nb_streams == 0) { /* streams not yet published, let's do that */
  383. nsv->vtag = vtag;
  384. nsv->atag = atag;
  385. nsv->vwidth = vwidth;
  386. nsv->vheight = vwidth;
  387. if (vtag != T_NONE) {
  388. st = av_new_stream(s, NSV_ST_VIDEO);
  389. if (!st)
  390. goto fail;
  391. nst = av_mallocz(sizeof(NSVStream));
  392. if (!nst)
  393. goto fail;
  394. st->priv_data = nst;
  395. st->codec->codec_type = CODEC_TYPE_VIDEO;
  396. st->codec->codec_tag = vtag;
  397. st->codec->codec_id = codec_get_id(nsv_codec_video_tags, vtag);
  398. st->codec->width = vwidth;
  399. st->codec->height = vheight;
  400. st->codec->bits_per_sample = 24; /* depth XXX */
  401. av_set_pts_info(st, 64, framerate.den, framerate.num);
  402. st->start_time = 0;
  403. st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
  404. }
  405. if (atag != T_NONE) {
  406. #ifndef DISABLE_AUDIO
  407. st = av_new_stream(s, NSV_ST_AUDIO);
  408. if (!st)
  409. goto fail;
  410. nst = av_mallocz(sizeof(NSVStream));
  411. if (!nst)
  412. goto fail;
  413. st->priv_data = nst;
  414. st->codec->codec_type = CODEC_TYPE_AUDIO;
  415. st->codec->codec_tag = atag;
  416. st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag);
  417. st->start_time = 0;
  418. // st->duration = nsv->duration; //FIXME
  419. st->need_parsing = 1; /* for PCM we will read a chunk later and put correct info */
  420. /* XXX:FIXME */
  421. //st->codec->channels = 2; //XXX:channels;
  422. //st->codec->sample_rate = 1000;
  423. //av_set_pts_info(st, 64, 1, st->codec->sample_rate);
  424. #endif
  425. }
  426. #ifdef CHECK_SUBSEQUENT_NSVS
  427. } else {
  428. if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
  429. PRINT(("NSV NSVs header values differ from the first one!!!\n"));
  430. //return -1;
  431. }
  432. #endif /* CHECK_SUBSEQUENT_NSVS */
  433. }
  434. nsv->state = NSV_HAS_READ_NSVS;
  435. return 0;
  436. fail:
  437. /* XXX */
  438. nsv->state = NSV_UNSYNC;
  439. return -1;
  440. }
  441. static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
  442. {
  443. NSVContext *nsv = s->priv_data;
  444. int i, err;
  445. PRINT(("%s()\n", __FUNCTION__));
  446. PRINT(("filename '%s'\n", s->filename));
  447. nsv->state = NSV_UNSYNC;
  448. nsv->ahead[0].data = nsv->ahead[1].data = NULL;
  449. for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
  450. if (nsv_resync(s) < 0)
  451. return -1;
  452. if (nsv->state == NSV_FOUND_NSVF)
  453. err = nsv_parse_NSVf_header(s, ap);
  454. /* we need the first NSVs also... */
  455. if (nsv->state == NSV_FOUND_NSVS) {
  456. err = nsv_parse_NSVs_header(s, ap);
  457. break; /* we just want the first one */
  458. }
  459. }
  460. if (s->nb_streams < 1) /* no luck so far */
  461. return -1;
  462. /* now read the first chunk, so we can attempt to decode more info */
  463. err = nsv_read_chunk(s, 1);
  464. PRINT(("parsed header\n"));
  465. return 0;
  466. }
  467. static int nsv_read_chunk(AVFormatContext *s, int fill_header)
  468. {
  469. NSVContext *nsv = s->priv_data;
  470. ByteIOContext *pb = &s->pb;
  471. AVStream *st[2] = {NULL, NULL};
  472. NSVStream *nst;
  473. AVPacket *pkt;
  474. int i, err = 0;
  475. uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */
  476. uint32_t vsize;
  477. uint16_t asize;
  478. uint16_t auxsize;
  479. uint32_t auxtag;
  480. PRINT(("%s(%d)\n", __FUNCTION__, fill_header));
  481. if (nsv->ahead[0].data || nsv->ahead[1].data)
  482. return 0; //-1; /* hey! eat what you've in your plate first! */
  483. null_chunk_retry:
  484. if (url_feof(pb))
  485. return -1;
  486. for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
  487. err = nsv_resync(s);
  488. if (err < 0)
  489. return err;
  490. if (nsv->state == NSV_FOUND_NSVS)
  491. err = nsv_parse_NSVs_header(s, NULL);
  492. if (err < 0)
  493. return err;
  494. if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
  495. return -1;
  496. auxcount = get_byte(pb);
  497. vsize = get_le16(pb);
  498. asize = get_le16(pb);
  499. vsize = (vsize << 4) | (auxcount >> 4);
  500. auxcount &= 0x0f;
  501. PRINT(("NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize));
  502. /* skip aux stuff */
  503. for (i = 0; i < auxcount; i++) {
  504. auxsize = get_le16(pb);
  505. auxtag = get_le32(pb);
  506. PRINT(("NSV aux data: '%c%c%c%c', %d bytes\n",
  507. (auxtag & 0x0ff),
  508. ((auxtag >> 8) & 0x0ff),
  509. ((auxtag >> 16) & 0x0ff),
  510. ((auxtag >> 24) & 0x0ff),
  511. auxsize));
  512. url_fskip(pb, auxsize);
  513. vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming braindead */
  514. }
  515. if (url_feof(pb))
  516. return -1;
  517. if (!vsize && !asize) {
  518. nsv->state = NSV_UNSYNC;
  519. goto null_chunk_retry;
  520. }
  521. /* map back streams to v,a */
  522. if (s->streams[0])
  523. st[s->streams[0]->id] = s->streams[0];
  524. if (s->streams[1])
  525. st[s->streams[1]->id] = s->streams[1];
  526. if (vsize/* && st[NSV_ST_VIDEO]*/) {
  527. nst = st[NSV_ST_VIDEO]->priv_data;
  528. pkt = &nsv->ahead[NSV_ST_VIDEO];
  529. av_get_packet(pb, pkt, vsize);
  530. pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO;
  531. pkt->dts = nst->frame_offset++;
  532. pkt->flags |= PKT_FLAG_KEY; /* stupid format has no way to tell XXX: try the index */
  533. /*
  534. for (i = 0; i < MIN(8, vsize); i++)
  535. PRINT(("NSV video: [%d] = %02x\n", i, pkt->data[i]));
  536. */
  537. }
  538. if (asize/*st[NSV_ST_AUDIO]*/) {
  539. nst = st[NSV_ST_AUDIO]->priv_data;
  540. pkt = &nsv->ahead[NSV_ST_AUDIO];
  541. /* read raw audio specific header on the first audio chunk... */
  542. /* on ALL audio chunks ?? seems so! */
  543. if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) {
  544. uint8_t bps;
  545. uint8_t channels;
  546. uint16_t samplerate;
  547. bps = get_byte(pb);
  548. channels = get_byte(pb);
  549. samplerate = get_le16(pb);
  550. asize-=4;
  551. PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
  552. if (fill_header) {
  553. st[NSV_ST_AUDIO]->need_parsing = 0; /* we know everything */
  554. if (bps != 16) {
  555. PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps));
  556. }
  557. bps /= channels; // ???
  558. if (bps == 8)
  559. st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
  560. samplerate /= 4;/* UGH ??? XXX */
  561. channels = 1;
  562. st[NSV_ST_AUDIO]->codec->channels = channels;
  563. st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
  564. av_set_pts_info(st[NSV_ST_AUDIO], 64, 1,
  565. st[NSV_ST_AUDIO]->codec->sample_rate);
  566. PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
  567. }
  568. }
  569. av_get_packet(pb, pkt, asize);
  570. pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO;
  571. //pkt->dts = nst->frame_offset;
  572. //if (nst->sample_size)
  573. // pkt->dts /= nst->sample_size;
  574. nst->frame_offset += asize; // XXX: that's valid only for PCM !?
  575. }
  576. //pkt->flags |= PKT_FLAG_KEY;
  577. nsv->state = NSV_UNSYNC;
  578. return 0;
  579. }
  580. static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
  581. {
  582. NSVContext *nsv = s->priv_data;
  583. int i, err = 0;
  584. PRINT(("%s()\n", __FUNCTION__));
  585. /* in case we don't already have something to eat ... */
  586. if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
  587. err = nsv_read_chunk(s, 0);
  588. if (err < 0)
  589. return err;
  590. /* now pick one of the plates */
  591. for (i = 0; i < 2; i++) {
  592. if (nsv->ahead[i].data) {
  593. PRINT(("%s: using cached packet[%d]\n", __FUNCTION__, i));
  594. /* avoid the cost of new_packet + memcpy(->data) */
  595. memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
  596. nsv->ahead[i].data = NULL; /* we ate that one */
  597. return pkt->size;
  598. }
  599. }
  600. /* this restaurant is not approvisionned :^] */
  601. return -1;
  602. }
  603. static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
  604. {
  605. #if 0
  606. NSVContext *avi = s->priv_data;
  607. AVStream *st;
  608. NSVStream *ast;
  609. int frame_number, i;
  610. int64_t pos;
  611. #endif
  612. return -1;
  613. }
  614. static int nsv_read_close(AVFormatContext *s)
  615. {
  616. /* int i; */
  617. NSVContext *nsv = s->priv_data;
  618. if (nsv->index_entries)
  619. av_free(nsv->nsvf_index_data);
  620. #if 0
  621. for(i=0;i<s->nb_streams;i++) {
  622. AVStream *st = s->streams[i];
  623. NSVStream *ast = st->priv_data;
  624. if(ast){
  625. av_free(ast->index_entries);
  626. av_free(ast);
  627. }
  628. av_free(st->codec->palctrl);
  629. }
  630. #endif
  631. return 0;
  632. }
  633. static int nsv_probe(AVProbeData *p)
  634. {
  635. int i;
  636. // PRINT(("nsv_probe(), buf_size %d\n", p->buf_size));
  637. /* check file header */
  638. if (p->buf_size <= 32)
  639. return 0;
  640. if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
  641. p->buf[2] == 'V' && p->buf[3] == 'f')
  642. return AVPROBE_SCORE_MAX;
  643. /* streamed files might not have any header */
  644. if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
  645. p->buf[2] == 'V' && p->buf[3] == 's')
  646. return AVPROBE_SCORE_MAX;
  647. /* XXX: do streamed files always start at chunk boundary ?? */
  648. /* or do we need to search NSVs in the byte stream ? */
  649. /* seems the servers don't bother starting clean chunks... */
  650. /* sometimes even the first header is at 9KB or something :^) */
  651. for (i = 1; i < p->buf_size - 3; i++) {
  652. if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
  653. p->buf[i+2] == 'V' && p->buf[i+3] == 's')
  654. return AVPROBE_SCORE_MAX-20;
  655. }
  656. /* so we'll have more luck on extension... */
  657. if (match_ext(p->filename, "nsv"))
  658. return AVPROBE_SCORE_MAX-20;
  659. /* FIXME: add mime-type check */
  660. return 0;
  661. }
  662. AVInputFormat nsv_demuxer = {
  663. "nsv",
  664. "NullSoft Video format",
  665. sizeof(NSVContext),
  666. nsv_probe,
  667. nsv_read_header,
  668. nsv_read_packet,
  669. nsv_read_close,
  670. nsv_read_seek,
  671. };