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
00184 } NSVContext;
00185
00186 static const AVCodecTag nsv_codec_video_tags[] = {
00187 { CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
00188 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
00189 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
00190 { CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
00191 { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
00192 { CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
00193 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
00194 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
00195 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
00196
00197
00198
00199
00200 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
00201 { CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
00202 { 0, 0 },
00203 };
00204
00205 static const AVCodecTag nsv_codec_audio_tags[] = {
00206 { CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
00207 { CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
00208 { CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') },
00209 { CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
00210 { 0, 0 },
00211 };
00212
00213
00214 static int nsv_read_chunk(AVFormatContext *s, int fill_header);
00215
00216 #ifdef DEBUG
00217 static void print_tag(const char *str, unsigned int tag, int size)
00218 {
00219 printf("%s: tag=%c%c%c%c\n",
00220 str, tag & 0xff,
00221 (tag >> 8) & 0xff,
00222 (tag >> 16) & 0xff,
00223 (tag >> 24) & 0xff);
00224 }
00225 #endif
00226
00227
00228 static int nsv_resync(AVFormatContext *s)
00229 {
00230 NSVContext *nsv = s->priv_data;
00231 ByteIOContext *pb = s->pb;
00232 uint32_t v = 0;
00233 int i;
00234
00235 PRINT(("%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, url_ftell(pb), nsv->state));
00236
00237
00238
00239 for (i = 0; i < NSV_MAX_RESYNC; i++) {
00240 if (url_feof(pb)) {
00241 PRINT(("NSV EOF\n"));
00242 nsv->state = NSV_UNSYNC;
00243 return -1;
00244 }
00245 v <<= 8;
00246 v |= get_byte(pb);
00247
00248
00249
00250
00251
00252
00253 if ((v & 0x0000ffff) == 0xefbe) {
00254 PRINT(("NSV resynced on BEEF after %d bytes\n", i+1));
00255 nsv->state = NSV_FOUND_BEEF;
00256 return 0;
00257 }
00258
00259 if (v == TB_NSVF) {
00260 PRINT(("NSV resynced on NSVf after %d bytes\n", i+1));
00261 nsv->state = NSV_FOUND_NSVF;
00262 return 0;
00263 }
00264 if (v == MKBETAG('N', 'S', 'V', 's')) {
00265 PRINT(("NSV resynced on NSVs after %d bytes\n", i+1));
00266 nsv->state = NSV_FOUND_NSVS;
00267 return 0;
00268 }
00269
00270 }
00271 PRINT(("NSV sync lost\n"));
00272 return -1;
00273 }
00274
00275 static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
00276 {
00277 NSVContext *nsv = s->priv_data;
00278 ByteIOContext *pb = s->pb;
00279 unsigned int file_size, size;
00280 int64_t duration;
00281 int strings_size;
00282 int table_entries;
00283 int table_entries_used;
00284
00285 PRINT(("%s()\n", __FUNCTION__));
00286
00287 nsv->state = NSV_UNSYNC;
00288
00289 size = get_le32(pb);
00290 if (size < 28)
00291 return -1;
00292 nsv->NSVf_end = size;
00293
00294
00295 file_size = (uint32_t)get_le32(pb);
00296 PRINT(("NSV NSVf chunk_size %u\n", size));
00297 PRINT(("NSV NSVf file_size %u\n", file_size));
00298
00299 nsv->duration = duration = get_le32(pb);
00300 PRINT(("NSV NSVf duration %"PRId64" ms\n", duration));
00301
00302
00303 strings_size = get_le32(pb);
00304 table_entries = get_le32(pb);
00305 table_entries_used = get_le32(pb);
00306 PRINT(("NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
00307 strings_size, table_entries, table_entries_used));
00308 if (url_feof(pb))
00309 return -1;
00310
00311 PRINT(("NSV got header; filepos %"PRId64"\n", url_ftell(pb)));
00312
00313 if (strings_size > 0) {
00314 char *strings;
00315 char *p, *endp;
00316 char *token, *value;
00317 char quote;
00318
00319 p = strings = av_mallocz(strings_size + 1);
00320 endp = strings + strings_size;
00321 get_buffer(pb, strings, strings_size);
00322 while (p < endp) {
00323 while (*p == ' ')
00324 p++;
00325 if (p >= endp-2)
00326 break;
00327 token = p;
00328 p = strchr(p, '=');
00329 if (!p || p >= endp-2)
00330 break;
00331 *p++ = '\0';
00332 quote = *p++;
00333 value = p;
00334 p = strchr(p, quote);
00335 if (!p || p >= endp)
00336 break;
00337 *p++ = '\0';
00338 PRINT(("NSV NSVf INFO: %s='%s'\n", token, value));
00339 if (!strcmp(token, "ASPECT")) {
00340
00341 } else if (!strcmp(token, "CREATOR") || !strcmp(token, "Author")) {
00342 strncpy(s->author, value, 512-1);
00343 } else if (!strcmp(token, "Copyright")) {
00344 strncpy(s->copyright, value, 512-1);
00345 } else if (!strcmp(token, "TITLE") || !strcmp(token, "Title")) {
00346 strncpy(s->title, value, 512-1);
00347 }
00348 }
00349 av_free(strings);
00350 }
00351 if (url_feof(pb))
00352 return -1;
00353
00354 PRINT(("NSV got infos; filepos %"PRId64"\n", url_ftell(pb)));
00355
00356 if (table_entries_used > 0) {
00357 nsv->index_entries = table_entries_used;
00358 if((unsigned)table_entries >= UINT_MAX / sizeof(uint32_t))
00359 return -1;
00360 nsv->nsvf_index_data = av_malloc(table_entries * sizeof(uint32_t));
00361 #warning "FIXME: Byteswap buffer as needed"
00362 get_buffer(pb, (unsigned char *)nsv->nsvf_index_data, table_entries * sizeof(uint32_t));
00363 }
00364
00365 PRINT(("NSV got index; filepos %"PRId64"\n", url_ftell(pb)));
00366
00367 #ifdef DEBUG_DUMP_INDEX
00368 #define V(v) ((v<0x20 || v > 127)?'.':v)
00369
00370 PRINT(("NSV %d INDEX ENTRIES:\n", table_entries));
00371 PRINT(("NSV [dataoffset][fileoffset]\n", table_entries));
00372 for (i = 0; i < table_entries; i++) {
00373 unsigned char b[8];
00374 url_fseek(pb, size + nsv->nsvf_index_data[i], SEEK_SET);
00375 get_buffer(pb, b, 8);
00376 PRINT(("NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
00377 "%c%c%c%c%c%c%c%c\n",
00378 nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i],
00379 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
00380 V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ));
00381 }
00382
00383 #undef V
00384 #endif
00385
00386 url_fseek(pb, nsv->base_offset + size, SEEK_SET);
00387
00388 if (url_feof(pb))
00389 return -1;
00390 nsv->state = NSV_HAS_READ_NSVF;
00391 return 0;
00392 }
00393
00394 static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
00395 {
00396 NSVContext *nsv = s->priv_data;
00397 ByteIOContext *pb = s->pb;
00398 uint32_t vtag, atag;
00399 uint16_t vwidth, vheight;
00400 AVRational framerate;
00401 int i;
00402 AVStream *st;
00403 NSVStream *nst;
00404 PRINT(("%s()\n", __FUNCTION__));
00405
00406 vtag = get_le32(pb);
00407 atag = get_le32(pb);
00408 vwidth = get_le16(pb);
00409 vheight = get_le16(pb);
00410 i = get_byte(pb);
00411
00412 PRINT(("NSV NSVs framerate code %2x\n", i));
00413 if(i&0x80) {
00414 int t=(i & 0x7F)>>2;
00415 if(t<16) framerate = (AVRational){1, t+1};
00416 else framerate = (AVRational){t-15, 1};
00417
00418 if(i&1){
00419 framerate.num *= 1000;
00420 framerate.den *= 1001;
00421 }
00422
00423 if((i&3)==3) framerate.num *= 24;
00424 else if((i&3)==2) framerate.num *= 25;
00425 else framerate.num *= 30;
00426 }
00427 else
00428 framerate= (AVRational){i, 1};
00429
00430 nsv->avsync = get_le16(pb);
00431 #ifdef DEBUG
00432 print_tag("NSV NSVs vtag", vtag, 0);
00433 print_tag("NSV NSVs atag", atag, 0);
00434 PRINT(("NSV NSVs vsize %dx%d\n", vwidth, vheight));
00435 #endif
00436
00437
00438 if (s->nb_streams == 0) {
00439 nsv->vtag = vtag;
00440 nsv->atag = atag;
00441 nsv->vwidth = vwidth;
00442 nsv->vheight = vwidth;
00443 if (vtag != T_NONE) {
00444 st = av_new_stream(s, NSV_ST_VIDEO);
00445 if (!st)
00446 goto fail;
00447
00448 nst = av_mallocz(sizeof(NSVStream));
00449 if (!nst)
00450 goto fail;
00451 st->priv_data = nst;
00452 st->codec->codec_type = CODEC_TYPE_VIDEO;
00453 st->codec->codec_tag = vtag;
00454 st->codec->codec_id = codec_get_id(nsv_codec_video_tags, vtag);
00455 st->codec->width = vwidth;
00456 st->codec->height = vheight;
00457 st->codec->bits_per_sample = 24;
00458
00459 av_set_pts_info(st, 64, framerate.den, framerate.num);
00460 st->start_time = 0;
00461 st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
00462 }
00463 if (atag != T_NONE) {
00464 #ifndef DISABLE_AUDIO
00465 st = av_new_stream(s, NSV_ST_AUDIO);
00466 if (!st)
00467 goto fail;
00468
00469 nst = av_mallocz(sizeof(NSVStream));
00470 if (!nst)
00471 goto fail;
00472 st->priv_data = nst;
00473 st->codec->codec_type = CODEC_TYPE_AUDIO;
00474 st->codec->codec_tag = atag;
00475 st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag);
00476
00477 st->need_parsing = AVSTREAM_PARSE_FULL;
00478
00479
00480 av_set_pts_info(st, 64, 1, framerate.num*1000);
00481 st->start_time = 0;
00482 st->duration = (int64_t)nsv->duration * framerate.num;
00483 #endif
00484 }
00485 #ifdef CHECK_SUBSEQUENT_NSVS
00486 } else {
00487 if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
00488 PRINT(("NSV NSVs header values differ from the first one!!!\n"));
00489
00490 }
00491 #endif
00492 }
00493
00494 nsv->state = NSV_HAS_READ_NSVS;
00495 return 0;
00496 fail:
00497
00498 nsv->state = NSV_UNSYNC;
00499 return -1;
00500 }
00501
00502 static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00503 {
00504 NSVContext *nsv = s->priv_data;
00505 int i, err;
00506
00507 PRINT(("%s()\n", __FUNCTION__));
00508 PRINT(("filename '%s'\n", s->filename));
00509
00510 nsv->state = NSV_UNSYNC;
00511 nsv->ahead[0].data = nsv->ahead[1].data = NULL;
00512
00513 for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
00514 if (nsv_resync(s) < 0)
00515 return -1;
00516 if (nsv->state == NSV_FOUND_NSVF)
00517 err = nsv_parse_NSVf_header(s, ap);
00518
00519 if (nsv->state == NSV_FOUND_NSVS) {
00520 err = nsv_parse_NSVs_header(s, ap);
00521 break;
00522 }
00523 }
00524 if (s->nb_streams < 1)
00525 return -1;
00526
00527 err = nsv_read_chunk(s, 1);
00528
00529 PRINT(("parsed header\n"));
00530 return 0;
00531 }
00532
00533 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
00534 {
00535 NSVContext *nsv = s->priv_data;
00536 ByteIOContext *pb = s->pb;
00537 AVStream *st[2] = {NULL, NULL};
00538 NSVStream *nst;
00539 AVPacket *pkt;
00540 int i, err = 0;
00541 uint8_t auxcount;
00542 uint32_t vsize;
00543 uint16_t asize;
00544 uint16_t auxsize;
00545 uint32_t auxtag;
00546
00547 PRINT(("%s(%d)\n", __FUNCTION__, fill_header));
00548
00549 if (nsv->ahead[0].data || nsv->ahead[1].data)
00550 return 0;
00551
00552 null_chunk_retry:
00553 if (url_feof(pb))
00554 return -1;
00555
00556 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00557 err = nsv_resync(s);
00558 if (err < 0)
00559 return err;
00560 if (nsv->state == NSV_FOUND_NSVS)
00561 err = nsv_parse_NSVs_header(s, NULL);
00562 if (err < 0)
00563 return err;
00564 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00565 return -1;
00566
00567 auxcount = get_byte(pb);
00568 vsize = get_le16(pb);
00569 asize = get_le16(pb);
00570 vsize = (vsize << 4) | (auxcount >> 4);
00571 auxcount &= 0x0f;
00572 PRINT(("NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize));
00573
00574 for (i = 0; i < auxcount; i++) {
00575 auxsize = get_le16(pb);
00576 auxtag = get_le32(pb);
00577 PRINT(("NSV aux data: '%c%c%c%c', %d bytes\n",
00578 (auxtag & 0x0ff),
00579 ((auxtag >> 8) & 0x0ff),
00580 ((auxtag >> 16) & 0x0ff),
00581 ((auxtag >> 24) & 0x0ff),
00582 auxsize));
00583 url_fskip(pb, auxsize);
00584 vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t);
00585 }
00586
00587 if (url_feof(pb))
00588 return -1;
00589 if (!vsize && !asize) {
00590 nsv->state = NSV_UNSYNC;
00591 goto null_chunk_retry;
00592 }
00593
00594
00595 if (s->streams[0])
00596 st[s->streams[0]->id] = s->streams[0];
00597 if (s->streams[1])
00598 st[s->streams[1]->id] = s->streams[1];
00599
00600 if (vsize) {
00601 nst = st[NSV_ST_VIDEO]->priv_data;
00602 pkt = &nsv->ahead[NSV_ST_VIDEO];
00603 av_get_packet(pb, pkt, vsize);
00604 pkt->stream_index = st[NSV_ST_VIDEO]->index;
00605 pkt->dts = nst->frame_offset;
00606 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0;
00607
00608
00609
00610
00611 }
00612 if(st[NSV_ST_VIDEO])
00613 ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
00614
00615 if (asize) {
00616 nst = st[NSV_ST_AUDIO]->priv_data;
00617 pkt = &nsv->ahead[NSV_ST_AUDIO];
00618
00619
00620 if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')) {
00621 uint8_t bps;
00622 uint8_t channels;
00623 uint16_t samplerate;
00624 bps = get_byte(pb);
00625 channels = get_byte(pb);
00626 samplerate = get_le16(pb);
00627 asize-=4;
00628 PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
00629 if (fill_header) {
00630 st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE;
00631 if (bps != 16) {
00632 PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps));
00633 }
00634 bps /= channels;
00635 if (bps == 8)
00636 st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
00637 samplerate /= 4;
00638 channels = 1;
00639 st[NSV_ST_AUDIO]->codec->channels = channels;
00640 st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
00641 PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate));
00642 }
00643 }
00644 av_get_packet(pb, pkt, asize);
00645 pkt->stream_index = st[NSV_ST_AUDIO]->index;
00646 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? PKT_FLAG_KEY : 0;
00647 if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
00648
00649 pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
00650 pkt->dts *= (int64_t)1000 * st[NSV_ST_VIDEO]->time_base.num;
00651 pkt->dts += (int64_t)nsv->avsync * st[NSV_ST_VIDEO]->time_base.den;
00652 PRINT(("NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts));
00653 }
00654 nst->frame_offset++;
00655 }
00656
00657 nsv->state = NSV_UNSYNC;
00658 return 0;
00659 }
00660
00661
00662 static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
00663 {
00664 NSVContext *nsv = s->priv_data;
00665 int i, err = 0;
00666
00667 PRINT(("%s()\n", __FUNCTION__));
00668
00669
00670 if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
00671 err = nsv_read_chunk(s, 0);
00672 if (err < 0)
00673 return err;
00674
00675
00676 for (i = 0; i < 2; i++) {
00677 if (nsv->ahead[i].data) {
00678 PRINT(("%s: using cached packet[%d]\n", __FUNCTION__, i));
00679
00680 memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
00681 nsv->ahead[i].data = NULL;
00682 return pkt->size;
00683 }
00684 }
00685
00686
00687 return -1;
00688 }
00689
00690 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00691 {
00692 #if 0
00693 NSVContext *avi = s->priv_data;
00694 AVStream *st;
00695 NSVStream *ast;
00696 int frame_number, i;
00697 int64_t pos;
00698 #endif
00699
00700 return -1;
00701 }
00702
00703 static int nsv_read_close(AVFormatContext *s)
00704 {
00705
00706 NSVContext *nsv = s->priv_data;
00707
00708 if (nsv->index_entries)
00709 av_free(nsv->nsvf_index_data);
00710
00711 #if 0
00712
00713 for(i=0;i<s->nb_streams;i++) {
00714 AVStream *st = s->streams[i];
00715 NSVStream *ast = st->priv_data;
00716 if(ast){
00717 av_free(ast->index_entries);
00718 av_free(ast);
00719 }
00720 av_free(st->codec->palctrl);
00721 }
00722
00723 #endif
00724 return 0;
00725 }
00726
00727 static int nsv_probe(AVProbeData *p)
00728 {
00729 int i;
00730
00731
00732
00733 if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
00734 p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
00735 return AVPROBE_SCORE_MAX;
00736
00737
00738
00739
00740 for (i = 1; i < p->buf_size - 3; i++) {
00741 if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
00742 p->buf[i+2] == 'V' && p->buf[i+3] == 's')
00743 return AVPROBE_SCORE_MAX-20;
00744 }
00745
00746 if (match_ext(p->filename, "nsv"))
00747 return AVPROBE_SCORE_MAX/2;
00748
00749 return 0;
00750 }
00751
00752 AVInputFormat nsv_demuxer = {
00753 "nsv",
00754 "NullSoft Video format",
00755 sizeof(NSVContext),
00756 nsv_probe,
00757 nsv_read_header,
00758 nsv_read_packet,
00759 nsv_read_close,
00760 nsv_read_seek,
00761 };