00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "avformat.h"
00022 #include "riff.h"
00023
00024
00025
00026
00027 #define CHECK_SUBSEQUENT_NSVS
00028
00029
00030
00031
00032
00033 #define NSV_MAX_RESYNC (500*1024)
00034 #define NSV_MAX_RESYNC_TRIES 300
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #ifdef DEBUG
00085 #define PRINT(_v) printf _v
00086 #else
00087 #define PRINT(_v)
00088 #endif
00089
00090 #if 0
00091 struct NSVf_header {
00092 uint32_t chunk_tag;
00093 uint32_t chunk_size;
00094 uint32_t file_size;
00095 uint32_t file_length;
00096 uint32_t info_strings_size;
00097 uint32_t table_entries;
00098 uint32_t table_entries_used;
00099 };
00100
00101 struct NSVs_header {
00102 uint32_t chunk_tag;
00103 uint32_t v4cc;
00104 uint32_t a4cc;
00105 uint16_t vwidth;
00106 uint16_t vheight;
00107 uint8_t framerate;
00108 uint16_t unknown;
00109 };
00110
00111 struct nsv_avchunk_header {
00112 uint8_t vchunk_size_lsb;
00113 uint16_t vchunk_size_msb;
00114 uint16_t achunk_size;
00115 };
00116
00117 struct nsv_pcm_header {
00118 uint8_t bits_per_sample;
00119 uint8_t channel_count;
00120 uint16_t sample_rate;
00121 };
00122 #endif
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132 #define T_NSVF MKTAG('N', 'S', 'V', 'f')
00133 #define T_NSVS MKTAG('N', 'S', 'V', 's')
00134 #define T_TOC2 MKTAG('T', 'O', 'C', '2')
00135 #define T_NONE MKTAG('N', 'O', 'N', 'E')
00136 #define T_SUBT MKTAG('S', 'U', 'B', 'T')
00137 #define T_ASYN MKTAG('A', 'S', 'Y', 'N')
00138 #define T_KEYF MKTAG('K', 'E', 'Y', 'F')
00139
00140 #define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
00141 #define TB_NSVS MKBETAG('N', 'S', 'V', 's')
00142
00143
00144 #define NSV_ST_VIDEO 0
00145 #define NSV_ST_AUDIO 1
00146 #define NSV_ST_SUBT 2
00147
00148 enum NSVStatus {
00149 NSV_UNSYNC,
00150 NSV_FOUND_NSVF,
00151 NSV_HAS_READ_NSVF,
00152 NSV_FOUND_NSVS,
00153 NSV_HAS_READ_NSVS,
00154 NSV_FOUND_BEEF,
00155 NSV_GOT_VIDEO,
00156 NSV_GOT_AUDIO,
00157 };
00158
00159 typedef struct NSVStream {
00160 int frame_offset;
00161
00162 int scale;
00163 int rate;
00164 int sample_size;
00165 int start;
00166
00167 int new_frame_offset;
00168 int cum_len;
00169 } NSVStream;
00170
00171 typedef struct {
00172 int base_offset;
00173 int NSVf_end;
00174 uint32_t *nsvf_index_data;
00175 int index_entries;
00176 enum NSVStatus state;
00177 AVPacket ahead[2];
00178
00179 int64_t duration;
00180 uint32_t vtag, atag;
00181 uint16_t vwidth, vheight;
00182 int16_t avsync;
00183 AVRational framerate;
00184
00185 } NSVContext;
00186
00187 static const AVCodecTag nsv_codec_video_tags[] = {
00188 { CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
00189 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
00190 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
00191 { CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
00192 { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
00193 { CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
00194 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
00195 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
00196 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
00197
00198
00199
00200
00201 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
00202 { CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
00203 { 0, 0 },
00204 };
00205
00206 static const AVCodecTag nsv_codec_audio_tags[] = {
00207 { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
00208 { CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
00209 { CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') },
00210 { CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
00211 { 0, 0 },
00212 };
00213
00214
00215 static int nsv_read_chunk(AVFormatContext *s, int fill_header);
00216
00217 #ifdef DEBUG
00218 static void print_tag(const char *str, unsigned int tag, int size)
00219 {
00220 printf("%s: tag=%c%c%c%c\n",
00221 str, tag & 0xff,
00222 (tag >> 8) & 0xff,
00223 (tag >> 16) & 0xff,
00224 (tag >> 24) & 0xff);
00225 }
00226 #endif
00227
00228
00229 static int nsv_resync(AVFormatContext *s)
00230 {
00231 NSVContext *nsv = s->priv_data;
00232 ByteIOContext *pb = s->pb;
00233 uint32_t v = 0;
00234 int i;
00235
00236 PRINT(("%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, url_ftell(pb), nsv->state));
00237
00238
00239
00240 for (i = 0; i < NSV_MAX_RESYNC; i++) {
00241 if (url_feof(pb)) {
00242 PRINT(("NSV EOF\n"));
00243 nsv->state = NSV_UNSYNC;
00244 return -1;
00245 }
00246 v <<= 8;
00247 v |= get_byte(pb);
00248
00249
00250
00251
00252
00253
00254 if ((v & 0x0000ffff) == 0xefbe) {
00255 PRINT(("NSV resynced on BEEF after %d bytes\n", i+1));
00256 nsv->state = NSV_FOUND_BEEF;
00257 return 0;
00258 }
00259
00260 if (v == TB_NSVF) {
00261 PRINT(("NSV resynced on NSVf after %d bytes\n", i+1));
00262 nsv->state = NSV_FOUND_NSVF;
00263 return 0;
00264 }
00265 if (v == MKBETAG('N', 'S', 'V', 's')) {
00266 PRINT(("NSV resynced on NSVs after %d bytes\n", i+1));
00267 nsv->state = NSV_FOUND_NSVS;
00268 return 0;
00269 }
00270
00271 }
00272 PRINT(("NSV sync lost\n"));
00273 return -1;
00274 }
00275
00276 static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
00277 {
00278 NSVContext *nsv = s->priv_data;
00279 ByteIOContext *pb = s->pb;
00280 unsigned int file_size, size;
00281 int64_t duration;
00282 int strings_size;
00283 int table_entries;
00284 int table_entries_used;
00285
00286 PRINT(("%s()\n", __FUNCTION__));
00287
00288 nsv->state = NSV_UNSYNC;
00289
00290 size = get_le32(pb);
00291 if (size < 28)
00292 return -1;
00293 nsv->NSVf_end = size;
00294
00295
00296 file_size = (uint32_t)get_le32(pb);
00297 PRINT(("NSV NSVf chunk_size %u\n", size));
00298 PRINT(("NSV NSVf file_size %u\n", file_size));
00299
00300 nsv->duration = duration = get_le32(pb);
00301 PRINT(("NSV NSVf duration %"PRId64" ms\n", duration));
00302
00303
00304 strings_size = get_le32(pb);
00305 table_entries = get_le32(pb);
00306 table_entries_used = get_le32(pb);
00307 PRINT(("NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
00308 strings_size, table_entries, table_entries_used));
00309 if (url_feof(pb))
00310 return -1;
00311
00312 PRINT(("NSV got header; filepos %"PRId64"\n", url_ftell(pb)));
00313
00314 if (strings_size > 0) {
00315 char *strings;
00316 char *p, *endp;
00317 char *token, *value;
00318 char quote;
00319
00320 p = strings = av_mallocz((size_t)strings_size + 1);
00321 if (!p)
00322 return AVERROR(ENOMEM);
00323 endp = strings + strings_size;
00324 get_buffer(pb, strings, strings_size);
00325 while (p < endp) {
00326 while (*p == ' ')
00327 p++;
00328 if (p >= endp-2)
00329 break;
00330 token = p;
00331 p = strchr(p, '=');
00332 if (!p || p >= endp-2)
00333 break;
00334 *p++ = '\0';
00335 quote = *p++;
00336 value = p;
00337 p = strchr(p, quote);
00338 if (!p || p >= endp)
00339 break;
00340 *p++ = '\0';
00341 PRINT(("NSV NSVf INFO: %s='%s'\n", token, value));
00342 av_metadata_set(&s->metadata, token, value);
00343 }
00344 av_free(strings);
00345 }
00346 if (url_feof(pb))
00347 return -1;
00348
00349 PRINT(("NSV got infos; filepos %"PRId64"\n", url_ftell(pb)));
00350
00351 if (table_entries_used > 0) {
00352 nsv->index_entries = table_entries_used;
00353 if((unsigned)table_entries >= UINT_MAX / sizeof(uint32_t))
00354 return -1;
00355 nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));
00356 if (!nsv->nsvf_index_data)
00357 return AVERROR(ENOMEM);
00358 #warning "FIXME: Byteswap buffer as needed"
00359 get_buffer(pb, (unsigned char *)nsv->nsvf_index_data, table_entries * sizeof(uint32_t));
00360 }
00361
00362 PRINT(("NSV got index; filepos %"PRId64"\n", url_ftell(pb)));
00363
00364 #ifdef DEBUG_DUMP_INDEX
00365 #define V(v) ((v<0x20 || v > 127)?'.':v)
00366
00367 PRINT(("NSV %d INDEX ENTRIES:\n", table_entries));
00368 PRINT(("NSV [dataoffset][fileoffset]\n", table_entries));
00369 for (i = 0; i < table_entries; i++) {
00370 unsigned char b[8];
00371 url_fseek(pb, size + nsv->nsvf_index_data[i], SEEK_SET);
00372 get_buffer(pb, b, 8);
00373 PRINT(("NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
00374 "%c%c%c%c%c%c%c%c\n",
00375 nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i],
00376 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
00377 V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ));
00378 }
00379
00380 #undef V
00381 #endif
00382
00383 url_fseek(pb, nsv->base_offset + size, SEEK_SET);
00384
00385 if (url_feof(pb))
00386 return -1;
00387 nsv->state = NSV_HAS_READ_NSVF;
00388 return 0;
00389 }
00390
00391 static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
00392 {
00393 NSVContext *nsv = s->priv_data;
00394 ByteIOContext *pb = s->pb;
00395 uint32_t vtag, atag;
00396 uint16_t vwidth, vheight;
00397 AVRational framerate;
00398 int i;
00399 AVStream *st;
00400 NSVStream *nst;
00401 PRINT(("%s()\n", __FUNCTION__));
00402
00403 vtag = get_le32(pb);
00404 atag = get_le32(pb);
00405 vwidth = get_le16(pb);
00406 vheight = get_le16(pb);
00407 i = get_byte(pb);
00408
00409 PRINT(("NSV NSVs framerate code %2x\n", i));
00410 if(i&0x80) {
00411 int t=(i & 0x7F)>>2;
00412 if(t<16) framerate = (AVRational){1, t+1};
00413 else framerate = (AVRational){t-15, 1};
00414
00415 if(i&1){
00416 framerate.num *= 1000;
00417 framerate.den *= 1001;
00418 }
00419
00420 if((i&3)==3) framerate.num *= 24;
00421 else if((i&3)==2) framerate.num *= 25;
00422 else framerate.num *= 30;
00423 }
00424 else
00425 framerate= (AVRational){i, 1};
00426
00427 nsv->avsync = get_le16(pb);
00428 nsv->framerate = framerate;
00429 #ifdef DEBUG
00430 print_tag("NSV NSVs vtag", vtag, 0);
00431 print_tag("NSV NSVs atag", atag, 0);
00432 PRINT(("NSV NSVs vsize %dx%d\n", vwidth, vheight));
00433 #endif
00434
00435
00436 if (s->nb_streams == 0) {
00437 nsv->vtag = vtag;
00438 nsv->atag = atag;
00439 nsv->vwidth = vwidth;
00440 nsv->vheight = vwidth;
00441 if (vtag != T_NONE) {
00442 st = av_new_stream(s, NSV_ST_VIDEO);
00443 if (!st)
00444 goto fail;
00445
00446 nst = av_mallocz(sizeof(NSVStream));
00447 if (!nst)
00448 goto fail;
00449 st->priv_data = nst;
00450 st->codec->codec_type = CODEC_TYPE_VIDEO;
00451 st->codec->codec_tag = vtag;
00452 st->codec->codec_id = codec_get_id(nsv_codec_video_tags, vtag);
00453 st->codec->width = vwidth;
00454 st->codec->height = vheight;
00455 st->codec->bits_per_coded_sample = 24;
00456
00457 av_set_pts_info(st, 64, framerate.den, framerate.num);
00458 st->start_time = 0;
00459 st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
00460 }
00461 if (atag != T_NONE) {
00462 #ifndef DISABLE_AUDIO
00463 st = av_new_stream(s, NSV_ST_AUDIO);
00464 if (!st)
00465 goto fail;
00466
00467 nst = av_mallocz(sizeof(NSVStream));
00468 if (!nst)
00469 goto fail;
00470 st->priv_data = nst;
00471 st->codec->codec_type = CODEC_TYPE_AUDIO;
00472 st->codec->codec_tag = atag;
00473 st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag);
00474
00475 st->need_parsing = AVSTREAM_PARSE_FULL;
00476
00477
00478 av_set_pts_info(st, 64, 1, framerate.num*1000);
00479 st->start_time = 0;
00480 st->duration = (int64_t)nsv->duration * framerate.num;
00481 #endif
00482 }
00483 #ifdef CHECK_SUBSEQUENT_NSVS
00484 } else {
00485 if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
00486 PRINT(("NSV NSVs header values differ from the first one!!!\n"));
00487
00488 }
00489 #endif
00490 }
00491
00492 nsv->state = NSV_HAS_READ_NSVS;
00493 return 0;
00494 fail:
00495
00496 nsv->state = NSV_UNSYNC;
00497 return -1;
00498 }
00499
00500 static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00501 {
00502 NSVContext *nsv = s->priv_data;
00503 int i, err;
00504
00505 PRINT(("%s()\n", __FUNCTION__));
00506 PRINT(("filename '%s'\n", s->filename));
00507
00508 nsv->state = NSV_UNSYNC;
00509 nsv->ahead[0].data = nsv->ahead[1].data = NULL;
00510
00511 for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
00512 if (nsv_resync(s) < 0)
00513 return -1;
00514 if (nsv->state == NSV_FOUND_NSVF) {
00515 err = nsv_parse_NSVf_header(s, ap);
00516 if (err < 0)
00517 return err;
00518 }
00519
00520 if (nsv->state == NSV_FOUND_NSVS) {
00521 err = nsv_parse_NSVs_header(s, ap);
00522 if (err < 0)
00523 return err;
00524 break;
00525 }
00526 }
00527 if (s->nb_streams < 1)
00528 return -1;
00529
00530 err = nsv_read_chunk(s, 1);
00531
00532 PRINT(("parsed header\n"));
00533 return 0;
00534 }
00535
00536 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
00537 {
00538 NSVContext *nsv = s->priv_data;
00539 ByteIOContext *pb = s->pb;
00540 AVStream *st[2] = {NULL, NULL};
00541 NSVStream *nst;
00542 AVPacket *pkt;
00543 int i, err = 0;
00544 uint8_t auxcount;
00545 uint32_t vsize;
00546 uint16_t asize;
00547 uint16_t auxsize;
00548 uint32_t auxtag;
00549
00550 PRINT(("%s(%d)\n", __FUNCTION__, fill_header));
00551
00552 if (nsv->ahead[0].data || nsv->ahead[1].data)
00553 return 0;
00554
00555 null_chunk_retry:
00556 if (url_feof(pb))
00557 return -1;
00558
00559 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00560 err = nsv_resync(s);
00561 if (err < 0)
00562 return err;
00563 if (nsv->state == NSV_FOUND_NSVS)
00564 err = nsv_parse_NSVs_header(s, NULL);
00565 if (err < 0)
00566 return err;
00567 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00568 return -1;
00569
00570 auxcount = get_byte(pb);
00571 vsize = get_le16(pb);
00572 asize = get_le16(pb);
00573 vsize = (vsize << 4) | (auxcount >> 4);
00574 auxcount &= 0x0f;
00575 PRINT(("NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize));
00576
00577 for (i = 0; i < auxcount; i++) {
00578 auxsize = get_le16(pb);
00579 auxtag = get_le32(pb);
00580 PRINT(("NSV aux data: '%c%c%c%c', %d bytes\n",
00581 (auxtag & 0x0ff),
00582 ((auxtag >> 8) & 0x0ff),
00583 ((auxtag >> 16) & 0x0ff),
00584 ((auxtag >> 24) & 0x0ff),
00585 auxsize));
00586 url_fskip(pb, auxsize);
00587 vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t);
00588 }
00589
00590 if (url_feof(pb))
00591 return -1;
00592 if (!vsize && !asize) {
00593 nsv->state = NSV_UNSYNC;
00594 goto null_chunk_retry;
00595 }
00596
00597
00598 if (s->nb_streams > 0)
00599 st[s->streams[0]->id] = s->streams[0];
00600 if (s->nb_streams > 1)
00601 st[s->streams[1]->id] = s->streams[1];
00602
00603 if (vsize && st[NSV_ST_VIDEO]) {
00604 nst = st[NSV_ST_VIDEO]->priv_data;
00605 pkt = &nsv->ahead[NSV_ST_VIDEO];
00606 av_get_packet(pb, pkt, vsize);
00607 pkt->stream_index = st[NSV_ST_VIDEO]->index;
00608 pkt->dts = nst->frame_offset;
00609 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0;
00610
00611
00612
00613
00614 }
00615 if(st[NSV_ST_VIDEO])
00616 ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
00617
00618 if (asize && st[NSV_ST_AUDIO]) {
00619 nst = st[NSV_ST_AUDIO]->priv_data;
00620 pkt = &nsv->ahead[NSV_ST_AUDIO];
00621
00622
00623 if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')) {
00624 uint8_t bps;
00625 uint8_t channels;
00626 uint16_t samplerate;
00627 bps = get_byte(pb);
00628 channels = get_byte(pb);
00629 samplerate = get_le16(pb);
00630 asize-=4;
00631 PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
00632 if (fill_header) {
00633 st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE;
00634 if (bps != 16) {
00635 PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps));
00636 }
00637 bps /= channels;
00638 if (bps == 8)
00639 st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
00640 samplerate /= 4;
00641 channels = 1;
00642 st[NSV_ST_AUDIO]->codec->channels = channels;
00643 st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
00644 PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
00645 }
00646 }
00647 av_get_packet(pb, pkt, asize);
00648 pkt->stream_index = st[NSV_ST_AUDIO]->index;
00649 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0;
00650 if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
00651
00652 pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
00653 pkt->dts *= (int64_t)1000 * nsv->framerate.den;
00654 pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
00655 PRINT(("NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts));
00656 }
00657 nst->frame_offset++;
00658 }
00659
00660 nsv->state = NSV_UNSYNC;
00661 return 0;
00662 }
00663
00664
00665 static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
00666 {
00667 NSVContext *nsv = s->priv_data;
00668 int i, err = 0;
00669
00670 PRINT(("%s()\n", __FUNCTION__));
00671
00672
00673 if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
00674 err = nsv_read_chunk(s, 0);
00675 if (err < 0)
00676 return err;
00677
00678
00679 for (i = 0; i < 2; i++) {
00680 if (nsv->ahead[i].data) {
00681 PRINT(("%s: using cached packet[%d]\n", __FUNCTION__, i));
00682
00683 memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
00684 nsv->ahead[i].data = NULL;
00685 return pkt->size;
00686 }
00687 }
00688
00689
00690 return -1;
00691 }
00692
00693 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00694 {
00695 #if 0
00696 NSVContext *avi = s->priv_data;
00697 AVStream *st;
00698 NSVStream *ast;
00699 int frame_number, i;
00700 int64_t pos;
00701 #endif
00702
00703 return -1;
00704 }
00705
00706 static int nsv_read_close(AVFormatContext *s)
00707 {
00708
00709 NSVContext *nsv = s->priv_data;
00710
00711 if (nsv->index_entries)
00712 av_free(nsv->nsvf_index_data);
00713
00714 #if 0
00715
00716 for(i=0;i<s->nb_streams;i++) {
00717 AVStream *st = s->streams[i];
00718 NSVStream *ast = st->priv_data;
00719 if(ast){
00720 av_free(ast->index_entries);
00721 av_free(ast);
00722 }
00723 av_free(st->codec->palctrl);
00724 }
00725
00726 #endif
00727 return 0;
00728 }
00729
00730 static int nsv_probe(AVProbeData *p)
00731 {
00732 int i;
00733
00734
00735
00736 if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
00737 p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
00738 return AVPROBE_SCORE_MAX;
00739
00740
00741
00742
00743 for (i = 1; i < p->buf_size - 3; i++) {
00744 if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
00745 p->buf[i+2] == 'V' && p->buf[i+3] == 's')
00746 return AVPROBE_SCORE_MAX-20;
00747 }
00748
00749 if (match_ext(p->filename, "nsv"))
00750 return AVPROBE_SCORE_MAX/2;
00751
00752 return 0;
00753 }
00754
00755 AVInputFormat nsv_demuxer = {
00756 "nsv",
00757 NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
00758 sizeof(NSVContext),
00759 nsv_probe,
00760 nsv_read_header,
00761 nsv_read_packet,
00762 nsv_read_close,
00763 nsv_read_seek,
00764 };