00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/mathematics.h"
00023 #include "avformat.h"
00024 #include "internal.h"
00025 #include "riff.h"
00026 #include "libavutil/dict.h"
00027
00028
00029 #define CHECK_SUBSEQUENT_NSVS
00030
00031
00032
00033
00034
00035 #define NSV_MAX_RESYNC (500*1024)
00036 #define NSV_MAX_RESYNC_TRIES 300
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
00085
00086
00087
00088
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 #define print_tag(str, tag, size) \
00220 av_dlog(NULL, "%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
00227 static int nsv_resync(AVFormatContext *s)
00228 {
00229 NSVContext *nsv = s->priv_data;
00230 AVIOContext *pb = s->pb;
00231 uint32_t v = 0;
00232 int i;
00233
00234 av_dlog(s, "%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, avio_tell(pb), nsv->state);
00235
00236
00237
00238 for (i = 0; i < NSV_MAX_RESYNC; i++) {
00239 if (pb->eof_reached) {
00240 av_dlog(s, "NSV EOF\n");
00241 nsv->state = NSV_UNSYNC;
00242 return -1;
00243 }
00244 v <<= 8;
00245 v |= avio_r8(pb);
00246 if (i < 8) {
00247 av_dlog(s, "NSV resync: [%d] = %02x\n", i, v & 0x0FF);
00248 }
00249
00250 if ((v & 0x0000ffff) == 0xefbe) {
00251 av_dlog(s, "NSV resynced on BEEF after %d bytes\n", i+1);
00252 nsv->state = NSV_FOUND_BEEF;
00253 return 0;
00254 }
00255
00256 if (v == TB_NSVF) {
00257 av_dlog(s, "NSV resynced on NSVf after %d bytes\n", i+1);
00258 nsv->state = NSV_FOUND_NSVF;
00259 return 0;
00260 }
00261 if (v == MKBETAG('N', 'S', 'V', 's')) {
00262 av_dlog(s, "NSV resynced on NSVs after %d bytes\n", i+1);
00263 nsv->state = NSV_FOUND_NSVS;
00264 return 0;
00265 }
00266
00267 }
00268 av_dlog(s, "NSV sync lost\n");
00269 return -1;
00270 }
00271
00272 static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
00273 {
00274 NSVContext *nsv = s->priv_data;
00275 AVIOContext *pb = s->pb;
00276 unsigned int av_unused file_size;
00277 unsigned int size;
00278 int64_t duration;
00279 int strings_size;
00280 int table_entries;
00281 int table_entries_used;
00282
00283 av_dlog(s, "%s()\n", __FUNCTION__);
00284
00285 nsv->state = NSV_UNSYNC;
00286
00287 size = avio_rl32(pb);
00288 if (size < 28)
00289 return -1;
00290 nsv->NSVf_end = size;
00291
00292
00293 file_size = (uint32_t)avio_rl32(pb);
00294 av_dlog(s, "NSV NSVf chunk_size %u\n", size);
00295 av_dlog(s, "NSV NSVf file_size %u\n", file_size);
00296
00297 nsv->duration = duration = avio_rl32(pb);
00298 av_dlog(s, "NSV NSVf duration %"PRId64" ms\n", duration);
00299
00300
00301 strings_size = avio_rl32(pb);
00302 table_entries = avio_rl32(pb);
00303 table_entries_used = avio_rl32(pb);
00304 av_dlog(s, "NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
00305 strings_size, table_entries, table_entries_used);
00306 if (pb->eof_reached)
00307 return -1;
00308
00309 av_dlog(s, "NSV got header; filepos %"PRId64"\n", avio_tell(pb));
00310
00311 if (strings_size > 0) {
00312 char *strings;
00313 char *p, *endp;
00314 char *token, *value;
00315 char quote;
00316
00317 p = strings = av_mallocz(strings_size + 1);
00318 endp = strings + strings_size;
00319 avio_read(pb, strings, strings_size);
00320 while (p < endp) {
00321 while (*p == ' ')
00322 p++;
00323 if (p >= endp-2)
00324 break;
00325 token = p;
00326 p = strchr(p, '=');
00327 if (!p || p >= endp-2)
00328 break;
00329 *p++ = '\0';
00330 quote = *p++;
00331 value = p;
00332 p = strchr(p, quote);
00333 if (!p || p >= endp)
00334 break;
00335 *p++ = '\0';
00336 av_dlog(s, "NSV NSVf INFO: %s='%s'\n", token, value);
00337 av_dict_set(&s->metadata, token, value, 0);
00338 }
00339 av_free(strings);
00340 }
00341 if (pb->eof_reached)
00342 return -1;
00343
00344 av_dlog(s, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb));
00345
00346 if (table_entries_used > 0) {
00347 int i;
00348 nsv->index_entries = table_entries_used;
00349 if((unsigned)table_entries_used >= UINT_MAX / sizeof(uint32_t))
00350 return -1;
00351 nsv->nsvs_file_offset = av_malloc((unsigned)table_entries_used * sizeof(uint32_t));
00352
00353 for(i=0;i<table_entries_used;i++)
00354 nsv->nsvs_file_offset[i] = avio_rl32(pb) + size;
00355
00356 if(table_entries > table_entries_used &&
00357 avio_rl32(pb) == MKTAG('T','O','C','2')) {
00358 nsv->nsvs_timestamps = av_malloc((unsigned)table_entries_used*sizeof(uint32_t));
00359 for(i=0;i<table_entries_used;i++) {
00360 nsv->nsvs_timestamps[i] = avio_rl32(pb);
00361 }
00362 }
00363 }
00364
00365 av_dlog(s, "NSV got index; filepos %"PRId64"\n", avio_tell(pb));
00366
00367 #ifdef DEBUG_DUMP_INDEX
00368 #define V(v) ((v<0x20 || v > 127)?'.':v)
00369
00370 av_dlog(s, "NSV %d INDEX ENTRIES:\n", table_entries);
00371 av_dlog(s, "NSV [dataoffset][fileoffset]\n", table_entries);
00372 for (i = 0; i < table_entries; i++) {
00373 unsigned char b[8];
00374 avio_seek(pb, size + nsv->nsvs_file_offset[i], SEEK_SET);
00375 avio_read(pb, b, 8);
00376 av_dlog(s, "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->nsvs_file_offset[i], size + nsv->nsvs_file_offset[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 avio_seek(pb, nsv->base_offset + size, SEEK_SET);
00387
00388 if (pb->eof_reached)
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 AVIOContext *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 av_dlog(s, "%s()\n", __FUNCTION__);
00405
00406 vtag = avio_rl32(pb);
00407 atag = avio_rl32(pb);
00408 vwidth = avio_rl16(pb);
00409 vheight = avio_rl16(pb);
00410 i = avio_r8(pb);
00411
00412 av_dlog(s, "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 = avio_rl16(pb);
00431 nsv->framerate = framerate;
00432
00433 print_tag("NSV NSVs vtag", vtag, 0);
00434 print_tag("NSV NSVs atag", atag, 0);
00435 av_dlog(s, "NSV NSVs vsize %dx%d\n", vwidth, vheight);
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 int i;
00445 st = avformat_new_stream(s, NULL);
00446 if (!st)
00447 goto fail;
00448
00449 st->id = NSV_ST_VIDEO;
00450 nst = av_mallocz(sizeof(NSVStream));
00451 if (!nst)
00452 goto fail;
00453 st->priv_data = nst;
00454 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00455 st->codec->codec_tag = vtag;
00456 st->codec->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag);
00457 st->codec->width = vwidth;
00458 st->codec->height = vheight;
00459 st->codec->bits_per_coded_sample = 24;
00460
00461 avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
00462 st->start_time = 0;
00463 st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
00464
00465 for(i=0;i<nsv->index_entries;i++) {
00466 if(nsv->nsvs_timestamps) {
00467 av_add_index_entry(st, nsv->nsvs_file_offset[i], nsv->nsvs_timestamps[i],
00468 0, 0, AVINDEX_KEYFRAME);
00469 } else {
00470 int64_t ts = av_rescale(i*nsv->duration/nsv->index_entries, framerate.num, 1000*framerate.den);
00471 av_add_index_entry(st, nsv->nsvs_file_offset[i], ts, 0, 0, AVINDEX_KEYFRAME);
00472 }
00473 }
00474 }
00475 if (atag != T_NONE) {
00476 #ifndef DISABLE_AUDIO
00477 st = avformat_new_stream(s, NULL);
00478 if (!st)
00479 goto fail;
00480
00481 st->id = NSV_ST_AUDIO;
00482 nst = av_mallocz(sizeof(NSVStream));
00483 if (!nst)
00484 goto fail;
00485 st->priv_data = nst;
00486 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00487 st->codec->codec_tag = atag;
00488 st->codec->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag);
00489
00490 st->need_parsing = AVSTREAM_PARSE_FULL;
00491
00492
00493 avpriv_set_pts_info(st, 64, 1, framerate.num*1000);
00494 st->start_time = 0;
00495 st->duration = (int64_t)nsv->duration * framerate.num;
00496 #endif
00497 }
00498 #ifdef CHECK_SUBSEQUENT_NSVS
00499 } else {
00500 if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
00501 av_dlog(s, "NSV NSVs header values differ from the first one!!!\n");
00502
00503 }
00504 #endif
00505 }
00506
00507 nsv->state = NSV_HAS_READ_NSVS;
00508 return 0;
00509 fail:
00510
00511 nsv->state = NSV_UNSYNC;
00512 return -1;
00513 }
00514
00515 static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00516 {
00517 NSVContext *nsv = s->priv_data;
00518 int i, err;
00519
00520 av_dlog(s, "%s()\n", __FUNCTION__);
00521 av_dlog(s, "filename '%s'\n", s->filename);
00522
00523 nsv->state = NSV_UNSYNC;
00524 nsv->ahead[0].data = nsv->ahead[1].data = NULL;
00525
00526 for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
00527 if (nsv_resync(s) < 0)
00528 return -1;
00529 if (nsv->state == NSV_FOUND_NSVF)
00530 err = nsv_parse_NSVf_header(s, ap);
00531
00532 if (nsv->state == NSV_FOUND_NSVS) {
00533 err = nsv_parse_NSVs_header(s, ap);
00534 break;
00535 }
00536 }
00537 if (s->nb_streams < 1)
00538 return -1;
00539
00540 err = nsv_read_chunk(s, 1);
00541
00542 av_dlog(s, "parsed header\n");
00543 return err;
00544 }
00545
00546 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
00547 {
00548 NSVContext *nsv = s->priv_data;
00549 AVIOContext *pb = s->pb;
00550 AVStream *st[2] = {NULL, NULL};
00551 NSVStream *nst;
00552 AVPacket *pkt;
00553 int i, err = 0;
00554 uint8_t auxcount;
00555 uint32_t vsize;
00556 uint16_t asize;
00557 uint16_t auxsize;
00558 uint32_t av_unused auxtag;
00559
00560 av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header);
00561
00562 if (nsv->ahead[0].data || nsv->ahead[1].data)
00563 return 0;
00564
00565 null_chunk_retry:
00566 if (pb->eof_reached)
00567 return -1;
00568
00569 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00570 err = nsv_resync(s);
00571 if (err < 0)
00572 return err;
00573 if (nsv->state == NSV_FOUND_NSVS)
00574 err = nsv_parse_NSVs_header(s, NULL);
00575 if (err < 0)
00576 return err;
00577 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00578 return -1;
00579
00580 auxcount = avio_r8(pb);
00581 vsize = avio_rl16(pb);
00582 asize = avio_rl16(pb);
00583 vsize = (vsize << 4) | (auxcount >> 4);
00584 auxcount &= 0x0f;
00585 av_dlog(s, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize);
00586
00587 for (i = 0; i < auxcount; i++) {
00588 auxsize = avio_rl16(pb);
00589 auxtag = avio_rl32(pb);
00590 av_dlog(s, "NSV aux data: '%c%c%c%c', %d bytes\n",
00591 (auxtag & 0x0ff),
00592 ((auxtag >> 8) & 0x0ff),
00593 ((auxtag >> 16) & 0x0ff),
00594 ((auxtag >> 24) & 0x0ff),
00595 auxsize);
00596 avio_skip(pb, auxsize);
00597 vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t);
00598 }
00599
00600 if (pb->eof_reached)
00601 return -1;
00602 if (!vsize && !asize) {
00603 nsv->state = NSV_UNSYNC;
00604 goto null_chunk_retry;
00605 }
00606
00607
00608 if (s->streams[0])
00609 st[s->streams[0]->id] = s->streams[0];
00610 if (s->streams[1])
00611 st[s->streams[1]->id] = s->streams[1];
00612
00613 if (vsize) {
00614 nst = st[NSV_ST_VIDEO]->priv_data;
00615 pkt = &nsv->ahead[NSV_ST_VIDEO];
00616 av_get_packet(pb, pkt, vsize);
00617 pkt->stream_index = st[NSV_ST_VIDEO]->index;
00618 pkt->dts = nst->frame_offset;
00619 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00620 for (i = 0; i < FFMIN(8, vsize); i++)
00621 av_dlog(s, "NSV video: [%d] = %02x\n", i, pkt->data[i]);
00622 }
00623 if(st[NSV_ST_VIDEO])
00624 ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
00625
00626 if (asize) {
00627 nst = st[NSV_ST_AUDIO]->priv_data;
00628 pkt = &nsv->ahead[NSV_ST_AUDIO];
00629
00630
00631 if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')) {
00632 uint8_t bps;
00633 uint8_t channels;
00634 uint16_t samplerate;
00635 bps = avio_r8(pb);
00636 channels = avio_r8(pb);
00637 samplerate = avio_rl16(pb);
00638 asize-=4;
00639 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00640 if (fill_header) {
00641 st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE;
00642 if (bps != 16) {
00643 av_dlog(s, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps);
00644 }
00645 bps /= channels;
00646 if (bps == 8)
00647 st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
00648 samplerate /= 4;
00649 channels = 1;
00650 st[NSV_ST_AUDIO]->codec->channels = channels;
00651 st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
00652 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00653 }
00654 }
00655 av_get_packet(pb, pkt, asize);
00656 pkt->stream_index = st[NSV_ST_AUDIO]->index;
00657 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00658 if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
00659
00660 pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
00661 pkt->dts *= (int64_t)1000 * nsv->framerate.den;
00662 pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
00663 av_dlog(s, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts);
00664 }
00665 nst->frame_offset++;
00666 }
00667
00668 nsv->state = NSV_UNSYNC;
00669 return 0;
00670 }
00671
00672
00673 static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
00674 {
00675 NSVContext *nsv = s->priv_data;
00676 int i, err = 0;
00677
00678 av_dlog(s, "%s()\n", __FUNCTION__);
00679
00680
00681 if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
00682 err = nsv_read_chunk(s, 0);
00683 if (err < 0)
00684 return err;
00685
00686
00687 for (i = 0; i < 2; i++) {
00688 if (nsv->ahead[i].data) {
00689 av_dlog(s, "%s: using cached packet[%d]\n", __FUNCTION__, i);
00690
00691 memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
00692 nsv->ahead[i].data = NULL;
00693 return pkt->size;
00694 }
00695 }
00696
00697
00698 return -1;
00699 }
00700
00701 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00702 {
00703 NSVContext *nsv = s->priv_data;
00704 AVStream *st = s->streams[stream_index];
00705 NSVStream *nst = st->priv_data;
00706 int index;
00707
00708 index = av_index_search_timestamp(st, timestamp, flags);
00709 if(index < 0)
00710 return -1;
00711
00712 avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET);
00713 nst->frame_offset = st->index_entries[index].timestamp;
00714 nsv->state = NSV_UNSYNC;
00715 return 0;
00716 }
00717
00718 static int nsv_read_close(AVFormatContext *s)
00719 {
00720
00721 NSVContext *nsv = s->priv_data;
00722
00723 av_freep(&nsv->nsvs_file_offset);
00724 av_freep(&nsv->nsvs_timestamps);
00725 if (nsv->ahead[0].data)
00726 av_free_packet(&nsv->ahead[0]);
00727 if (nsv->ahead[1].data)
00728 av_free_packet(&nsv->ahead[1]);
00729
00730 #if 0
00731
00732 for(i=0;i<s->nb_streams;i++) {
00733 AVStream *st = s->streams[i];
00734 NSVStream *ast = st->priv_data;
00735 if(ast){
00736 av_free(ast->index_entries);
00737 av_free(ast);
00738 }
00739 av_free(st->codec->palctrl);
00740 }
00741
00742 #endif
00743 return 0;
00744 }
00745
00746 static int nsv_probe(AVProbeData *p)
00747 {
00748 int i;
00749 int score;
00750 int vsize, asize, auxcount;
00751 score = 0;
00752 av_dlog(NULL, "nsv_probe(), buf_size %d\n", p->buf_size);
00753
00754
00755 if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
00756 p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
00757 return AVPROBE_SCORE_MAX;
00758
00759
00760
00761
00762 for (i = 1; i < p->buf_size - 3; i++) {
00763 if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
00764 p->buf[i+2] == 'V' && p->buf[i+3] == 's') {
00765 score = AVPROBE_SCORE_MAX/5;
00766
00767 auxcount = p->buf[i+19];
00768 vsize = p->buf[i+20] | p->buf[i+21] << 8;
00769 asize = p->buf[i+22] | p->buf[i+23] << 8;
00770 vsize = (vsize << 4) | (auxcount >> 4);
00771 if ((asize + vsize + i + 23) < p->buf_size - 2) {
00772 if (p->buf[i+23+asize+vsize+1] == 0xEF &&
00773 p->buf[i+23+asize+vsize+2] == 0xBE)
00774 return AVPROBE_SCORE_MAX-20;
00775 }
00776 }
00777 }
00778
00779 if (av_match_ext(p->filename, "nsv"))
00780 return AVPROBE_SCORE_MAX/2;
00781
00782 return score;
00783 }
00784
00785 AVInputFormat ff_nsv_demuxer = {
00786 .name = "nsv",
00787 .long_name = NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
00788 .priv_data_size = sizeof(NSVContext),
00789 .read_probe = nsv_probe,
00790 .read_header = nsv_read_header,
00791 .read_packet = nsv_read_packet,
00792 .read_close = nsv_read_close,
00793 .read_seek = nsv_read_seek,
00794 };