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((size_t)strings_size + 1);
00318 if (!p)
00319 return AVERROR(ENOMEM);
00320 endp = strings + strings_size;
00321 avio_read(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 av_dlog(s, "NSV NSVf INFO: %s='%s'\n", token, value);
00339 av_dict_set(&s->metadata, token, value, 0);
00340 }
00341 av_free(strings);
00342 }
00343 if (pb->eof_reached)
00344 return -1;
00345
00346 av_dlog(s, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb));
00347
00348 if (table_entries_used > 0) {
00349 int i;
00350 nsv->index_entries = table_entries_used;
00351 if((unsigned)table_entries_used >= UINT_MAX / sizeof(uint32_t))
00352 return -1;
00353 nsv->nsvs_file_offset = av_malloc((unsigned)table_entries_used * sizeof(uint32_t));
00354 if (!nsv->nsvs_file_offset)
00355 return AVERROR(ENOMEM);
00356
00357 for(i=0;i<table_entries_used;i++)
00358 nsv->nsvs_file_offset[i] = avio_rl32(pb) + size;
00359
00360 if(table_entries > table_entries_used &&
00361 avio_rl32(pb) == MKTAG('T','O','C','2')) {
00362 nsv->nsvs_timestamps = av_malloc((unsigned)table_entries_used*sizeof(uint32_t));
00363 if (!nsv->nsvs_timestamps)
00364 return AVERROR(ENOMEM);
00365 for(i=0;i<table_entries_used;i++) {
00366 nsv->nsvs_timestamps[i] = avio_rl32(pb);
00367 }
00368 }
00369 }
00370
00371 av_dlog(s, "NSV got index; filepos %"PRId64"\n", avio_tell(pb));
00372
00373 #ifdef DEBUG_DUMP_INDEX
00374 #define V(v) ((v<0x20 || v > 127)?'.':v)
00375
00376 av_dlog(s, "NSV %d INDEX ENTRIES:\n", table_entries);
00377 av_dlog(s, "NSV [dataoffset][fileoffset]\n", table_entries);
00378 for (i = 0; i < table_entries; i++) {
00379 unsigned char b[8];
00380 avio_seek(pb, size + nsv->nsvs_file_offset[i], SEEK_SET);
00381 avio_read(pb, b, 8);
00382 av_dlog(s, "NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
00383 "%c%c%c%c%c%c%c%c\n",
00384 nsv->nsvs_file_offset[i], size + nsv->nsvs_file_offset[i],
00385 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
00386 V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) );
00387 }
00388
00389 #undef V
00390 #endif
00391
00392 avio_seek(pb, nsv->base_offset + size, SEEK_SET);
00393
00394 if (pb->eof_reached)
00395 return -1;
00396 nsv->state = NSV_HAS_READ_NSVF;
00397 return 0;
00398 }
00399
00400 static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
00401 {
00402 NSVContext *nsv = s->priv_data;
00403 AVIOContext *pb = s->pb;
00404 uint32_t vtag, atag;
00405 uint16_t vwidth, vheight;
00406 AVRational framerate;
00407 int i;
00408 AVStream *st;
00409 NSVStream *nst;
00410 av_dlog(s, "%s()\n", __FUNCTION__);
00411
00412 vtag = avio_rl32(pb);
00413 atag = avio_rl32(pb);
00414 vwidth = avio_rl16(pb);
00415 vheight = avio_rl16(pb);
00416 i = avio_r8(pb);
00417
00418 av_dlog(s, "NSV NSVs framerate code %2x\n", i);
00419 if(i&0x80) {
00420 int t=(i & 0x7F)>>2;
00421 if(t<16) framerate = (AVRational){1, t+1};
00422 else framerate = (AVRational){t-15, 1};
00423
00424 if(i&1){
00425 framerate.num *= 1000;
00426 framerate.den *= 1001;
00427 }
00428
00429 if((i&3)==3) framerate.num *= 24;
00430 else if((i&3)==2) framerate.num *= 25;
00431 else framerate.num *= 30;
00432 }
00433 else
00434 framerate= (AVRational){i, 1};
00435
00436 nsv->avsync = avio_rl16(pb);
00437 nsv->framerate = framerate;
00438
00439 print_tag("NSV NSVs vtag", vtag, 0);
00440 print_tag("NSV NSVs atag", atag, 0);
00441 av_dlog(s, "NSV NSVs vsize %dx%d\n", vwidth, vheight);
00442
00443
00444 if (s->nb_streams == 0) {
00445 nsv->vtag = vtag;
00446 nsv->atag = atag;
00447 nsv->vwidth = vwidth;
00448 nsv->vheight = vwidth;
00449 if (vtag != T_NONE) {
00450 int i;
00451 st = avformat_new_stream(s, NULL);
00452 if (!st)
00453 goto fail;
00454
00455 st->id = NSV_ST_VIDEO;
00456 nst = av_mallocz(sizeof(NSVStream));
00457 if (!nst)
00458 goto fail;
00459 st->priv_data = nst;
00460 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00461 st->codec->codec_tag = vtag;
00462 st->codec->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag);
00463 st->codec->width = vwidth;
00464 st->codec->height = vheight;
00465 st->codec->bits_per_coded_sample = 24;
00466
00467 avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
00468 st->start_time = 0;
00469 st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
00470
00471 for(i=0;i<nsv->index_entries;i++) {
00472 if(nsv->nsvs_timestamps) {
00473 av_add_index_entry(st, nsv->nsvs_file_offset[i], nsv->nsvs_timestamps[i],
00474 0, 0, AVINDEX_KEYFRAME);
00475 } else {
00476 int64_t ts = av_rescale(i*nsv->duration/nsv->index_entries, framerate.num, 1000*framerate.den);
00477 av_add_index_entry(st, nsv->nsvs_file_offset[i], ts, 0, 0, AVINDEX_KEYFRAME);
00478 }
00479 }
00480 }
00481 if (atag != T_NONE) {
00482 #ifndef DISABLE_AUDIO
00483 st = avformat_new_stream(s, NULL);
00484 if (!st)
00485 goto fail;
00486
00487 st->id = NSV_ST_AUDIO;
00488 nst = av_mallocz(sizeof(NSVStream));
00489 if (!nst)
00490 goto fail;
00491 st->priv_data = nst;
00492 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00493 st->codec->codec_tag = atag;
00494 st->codec->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag);
00495
00496 st->need_parsing = AVSTREAM_PARSE_FULL;
00497
00498
00499 avpriv_set_pts_info(st, 64, 1, framerate.num*1000);
00500 st->start_time = 0;
00501 st->duration = (int64_t)nsv->duration * framerate.num;
00502 #endif
00503 }
00504 #ifdef CHECK_SUBSEQUENT_NSVS
00505 } else {
00506 if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
00507 av_dlog(s, "NSV NSVs header values differ from the first one!!!\n");
00508
00509 }
00510 #endif
00511 }
00512
00513 nsv->state = NSV_HAS_READ_NSVS;
00514 return 0;
00515 fail:
00516
00517 nsv->state = NSV_UNSYNC;
00518 return -1;
00519 }
00520
00521 static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00522 {
00523 NSVContext *nsv = s->priv_data;
00524 int i, err;
00525
00526 av_dlog(s, "%s()\n", __FUNCTION__);
00527 av_dlog(s, "filename '%s'\n", s->filename);
00528
00529 nsv->state = NSV_UNSYNC;
00530 nsv->ahead[0].data = nsv->ahead[1].data = NULL;
00531
00532 for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
00533 if (nsv_resync(s) < 0)
00534 return -1;
00535 if (nsv->state == NSV_FOUND_NSVF) {
00536 err = nsv_parse_NSVf_header(s, ap);
00537 if (err < 0)
00538 return err;
00539 }
00540
00541 if (nsv->state == NSV_FOUND_NSVS) {
00542 err = nsv_parse_NSVs_header(s, ap);
00543 if (err < 0)
00544 return err;
00545 break;
00546 }
00547 }
00548 if (s->nb_streams < 1)
00549 return -1;
00550
00551 err = nsv_read_chunk(s, 1);
00552
00553 av_dlog(s, "parsed header\n");
00554 return err;
00555 }
00556
00557 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
00558 {
00559 NSVContext *nsv = s->priv_data;
00560 AVIOContext *pb = s->pb;
00561 AVStream *st[2] = {NULL, NULL};
00562 NSVStream *nst;
00563 AVPacket *pkt;
00564 int i, err = 0;
00565 uint8_t auxcount;
00566 uint32_t vsize;
00567 uint16_t asize;
00568 uint16_t auxsize;
00569 uint32_t av_unused auxtag;
00570
00571 av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header);
00572
00573 if (nsv->ahead[0].data || nsv->ahead[1].data)
00574 return 0;
00575
00576 null_chunk_retry:
00577 if (pb->eof_reached)
00578 return -1;
00579
00580 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00581 err = nsv_resync(s);
00582 if (err < 0)
00583 return err;
00584 if (nsv->state == NSV_FOUND_NSVS)
00585 err = nsv_parse_NSVs_header(s, NULL);
00586 if (err < 0)
00587 return err;
00588 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00589 return -1;
00590
00591 auxcount = avio_r8(pb);
00592 vsize = avio_rl16(pb);
00593 asize = avio_rl16(pb);
00594 vsize = (vsize << 4) | (auxcount >> 4);
00595 auxcount &= 0x0f;
00596 av_dlog(s, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize);
00597
00598 for (i = 0; i < auxcount; i++) {
00599 auxsize = avio_rl16(pb);
00600 auxtag = avio_rl32(pb);
00601 av_dlog(s, "NSV aux data: '%c%c%c%c', %d bytes\n",
00602 (auxtag & 0x0ff),
00603 ((auxtag >> 8) & 0x0ff),
00604 ((auxtag >> 16) & 0x0ff),
00605 ((auxtag >> 24) & 0x0ff),
00606 auxsize);
00607 avio_skip(pb, auxsize);
00608 vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t);
00609 }
00610
00611 if (pb->eof_reached)
00612 return -1;
00613 if (!vsize && !asize) {
00614 nsv->state = NSV_UNSYNC;
00615 goto null_chunk_retry;
00616 }
00617
00618
00619 if (s->nb_streams > 0)
00620 st[s->streams[0]->id] = s->streams[0];
00621 if (s->nb_streams > 1)
00622 st[s->streams[1]->id] = s->streams[1];
00623
00624 if (vsize && st[NSV_ST_VIDEO]) {
00625 nst = st[NSV_ST_VIDEO]->priv_data;
00626 pkt = &nsv->ahead[NSV_ST_VIDEO];
00627 av_get_packet(pb, pkt, vsize);
00628 pkt->stream_index = st[NSV_ST_VIDEO]->index;
00629 pkt->dts = nst->frame_offset;
00630 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00631 for (i = 0; i < FFMIN(8, vsize); i++)
00632 av_dlog(s, "NSV video: [%d] = %02x\n", i, pkt->data[i]);
00633 }
00634 if(st[NSV_ST_VIDEO])
00635 ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
00636
00637 if (asize && st[NSV_ST_AUDIO]) {
00638 nst = st[NSV_ST_AUDIO]->priv_data;
00639 pkt = &nsv->ahead[NSV_ST_AUDIO];
00640
00641
00642 if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')) {
00643 uint8_t bps;
00644 uint8_t channels;
00645 uint16_t samplerate;
00646 bps = avio_r8(pb);
00647 channels = avio_r8(pb);
00648 samplerate = avio_rl16(pb);
00649 asize-=4;
00650 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00651 if (fill_header) {
00652 st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE;
00653 if (bps != 16) {
00654 av_dlog(s, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps);
00655 }
00656 bps /= channels;
00657 if (bps == 8)
00658 st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
00659 samplerate /= 4;
00660 channels = 1;
00661 st[NSV_ST_AUDIO]->codec->channels = channels;
00662 st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
00663 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00664 }
00665 }
00666 av_get_packet(pb, pkt, asize);
00667 pkt->stream_index = st[NSV_ST_AUDIO]->index;
00668 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00669 if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
00670
00671 pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
00672 pkt->dts *= (int64_t)1000 * nsv->framerate.den;
00673 pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
00674 av_dlog(s, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts);
00675 }
00676 nst->frame_offset++;
00677 }
00678
00679 nsv->state = NSV_UNSYNC;
00680 return 0;
00681 }
00682
00683
00684 static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
00685 {
00686 NSVContext *nsv = s->priv_data;
00687 int i, err = 0;
00688
00689 av_dlog(s, "%s()\n", __FUNCTION__);
00690
00691
00692 if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
00693 err = nsv_read_chunk(s, 0);
00694 if (err < 0)
00695 return err;
00696
00697
00698 for (i = 0; i < 2; i++) {
00699 if (nsv->ahead[i].data) {
00700 av_dlog(s, "%s: using cached packet[%d]\n", __FUNCTION__, i);
00701
00702 memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
00703 nsv->ahead[i].data = NULL;
00704 return pkt->size;
00705 }
00706 }
00707
00708
00709 return -1;
00710 }
00711
00712 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00713 {
00714 NSVContext *nsv = s->priv_data;
00715 AVStream *st = s->streams[stream_index];
00716 NSVStream *nst = st->priv_data;
00717 int index;
00718
00719 index = av_index_search_timestamp(st, timestamp, flags);
00720 if(index < 0)
00721 return -1;
00722
00723 avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET);
00724 nst->frame_offset = st->index_entries[index].timestamp;
00725 nsv->state = NSV_UNSYNC;
00726 return 0;
00727 }
00728
00729 static int nsv_read_close(AVFormatContext *s)
00730 {
00731
00732 NSVContext *nsv = s->priv_data;
00733
00734 av_freep(&nsv->nsvs_file_offset);
00735 av_freep(&nsv->nsvs_timestamps);
00736 if (nsv->ahead[0].data)
00737 av_free_packet(&nsv->ahead[0]);
00738 if (nsv->ahead[1].data)
00739 av_free_packet(&nsv->ahead[1]);
00740
00741 #if 0
00742
00743 for(i=0;i<s->nb_streams;i++) {
00744 AVStream *st = s->streams[i];
00745 NSVStream *ast = st->priv_data;
00746 if(ast){
00747 av_free(ast->index_entries);
00748 av_free(ast);
00749 }
00750 av_free(st->codec->palctrl);
00751 }
00752
00753 #endif
00754 return 0;
00755 }
00756
00757 static int nsv_probe(AVProbeData *p)
00758 {
00759 int i;
00760 int score;
00761 int vsize, asize, auxcount;
00762 score = 0;
00763 av_dlog(NULL, "nsv_probe(), buf_size %d\n", p->buf_size);
00764
00765
00766 if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
00767 p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
00768 return AVPROBE_SCORE_MAX;
00769
00770
00771
00772
00773 for (i = 1; i < p->buf_size - 3; i++) {
00774 if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' &&
00775 p->buf[i+2] == 'V' && p->buf[i+3] == 's') {
00776 score = AVPROBE_SCORE_MAX/5;
00777
00778 auxcount = p->buf[i+19];
00779 vsize = p->buf[i+20] | p->buf[i+21] << 8;
00780 asize = p->buf[i+22] | p->buf[i+23] << 8;
00781 vsize = (vsize << 4) | (auxcount >> 4);
00782 if ((asize + vsize + i + 23) < p->buf_size - 2) {
00783 if (p->buf[i+23+asize+vsize+1] == 0xEF &&
00784 p->buf[i+23+asize+vsize+2] == 0xBE)
00785 return AVPROBE_SCORE_MAX-20;
00786 }
00787 }
00788 }
00789
00790 if (av_match_ext(p->filename, "nsv"))
00791 return AVPROBE_SCORE_MAX/2;
00792
00793 return score;
00794 }
00795
00796 AVInputFormat ff_nsv_demuxer = {
00797 .name = "nsv",
00798 .long_name = NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
00799 .priv_data_size = sizeof(NSVContext),
00800 .read_probe = nsv_probe,
00801 .read_header = nsv_read_header,
00802 .read_packet = nsv_read_packet,
00803 .read_close = nsv_read_close,
00804 .read_seek = nsv_read_seek,
00805 };