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