00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/attributes.h"
00023 #include "libavutil/mathematics.h"
00024 #include "avformat.h"
00025 #include "internal.h"
00026 #include "riff.h"
00027 #include "libavutil/dict.h"
00028 #include "libavutil/intreadwrite.h"
00029
00030
00031 #define CHECK_SUBSEQUENT_NSVS
00032
00033
00034
00035
00036
00037 #define NSV_MAX_RESYNC (500*1024)
00038 #define NSV_MAX_RESYNC_TRIES 300
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 #if 0
00089 struct NSVf_header {
00090 uint32_t chunk_tag;
00091 uint32_t chunk_size;
00092 uint32_t file_size;
00093 uint32_t file_length;
00094 uint32_t info_strings_size;
00095 uint32_t table_entries;
00096 uint32_t table_entries_used;
00097 };
00098
00099 struct NSVs_header {
00100 uint32_t chunk_tag;
00101 uint32_t v4cc;
00102 uint32_t a4cc;
00103 uint16_t vwidth;
00104 uint16_t vheight;
00105 uint8_t framerate;
00106 uint16_t unknown;
00107 };
00108
00109 struct nsv_avchunk_header {
00110 uint8_t vchunk_size_lsb;
00111 uint16_t vchunk_size_msb;
00112 uint16_t achunk_size;
00113 };
00114
00115 struct nsv_pcm_header {
00116 uint8_t bits_per_sample;
00117 uint8_t channel_count;
00118 uint16_t sample_rate;
00119 };
00120 #endif
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 #define T_NSVF MKTAG('N', 'S', 'V', 'f')
00131 #define T_NSVS MKTAG('N', 'S', 'V', 's')
00132 #define T_TOC2 MKTAG('T', 'O', 'C', '2')
00133 #define T_NONE MKTAG('N', 'O', 'N', 'E')
00134 #define T_SUBT MKTAG('S', 'U', 'B', 'T')
00135 #define T_ASYN MKTAG('A', 'S', 'Y', 'N')
00136 #define T_KEYF MKTAG('K', 'E', 'Y', 'F')
00137
00138 #define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
00139 #define TB_NSVS MKBETAG('N', 'S', 'V', 's')
00140
00141
00142 #define NSV_ST_VIDEO 0
00143 #define NSV_ST_AUDIO 1
00144 #define NSV_ST_SUBT 2
00145
00146 enum NSVStatus {
00147 NSV_UNSYNC,
00148 NSV_FOUND_NSVF,
00149 NSV_HAS_READ_NSVF,
00150 NSV_FOUND_NSVS,
00151 NSV_HAS_READ_NSVS,
00152 NSV_FOUND_BEEF,
00153 NSV_GOT_VIDEO,
00154 NSV_GOT_AUDIO,
00155 };
00156
00157 typedef struct NSVStream {
00158 int frame_offset;
00159
00160 int scale;
00161 int rate;
00162 int sample_size;
00163 int start;
00164
00165 int new_frame_offset;
00166 int cum_len;
00167 } NSVStream;
00168
00169 typedef struct {
00170 int base_offset;
00171 int NSVf_end;
00172 uint32_t *nsvs_file_offset;
00173 int index_entries;
00174 enum NSVStatus state;
00175 AVPacket ahead[2];
00176
00177 int64_t duration;
00178 uint32_t vtag, atag;
00179 uint16_t vwidth, vheight;
00180 int16_t avsync;
00181 AVRational framerate;
00182 uint32_t *nsvs_timestamps;
00183
00184 } NSVContext;
00185
00186 static const AVCodecTag nsv_codec_video_tags[] = {
00187 { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
00188 { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
00189 { AV_CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
00190 { AV_CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
00191 { AV_CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
00192 { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
00193 { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
00194 { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
00195 { AV_CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
00196 { AV_CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') },
00197
00198
00199
00200
00201 { AV_CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
00202 { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
00203 { AV_CODEC_ID_NONE, 0 },
00204 };
00205
00206 static const AVCodecTag nsv_codec_audio_tags[] = {
00207 { AV_CODEC_ID_MP3, MKTAG('M', 'P', '3', ' ') },
00208 { AV_CODEC_ID_AAC, MKTAG('A', 'A', 'C', ' ') },
00209 { AV_CODEC_ID_AAC, MKTAG('A', 'A', 'C', 'P') },
00210 { AV_CODEC_ID_AAC, MKTAG('V', 'L', 'B', ' ') },
00211 { AV_CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', ' ') },
00212 { AV_CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
00213 { AV_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 (url_feof(pb)) {
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)
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 (url_feof(pb))
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 (url_feof(pb))
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 (url_feof(pb))
00395 return -1;
00396 nsv->state = NSV_HAS_READ_NSVF;
00397 return 0;
00398 }
00399
00400 static int nsv_parse_NSVs_header(AVFormatContext *s)
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)
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);
00537 if (err < 0)
00538 return err;
00539 }
00540
00541 if (nsv->state == NSV_FOUND_NSVS) {
00542 err = nsv_parse_NSVs_header(s);
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
00570 av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header);
00571
00572 if (nsv->ahead[0].data || nsv->ahead[1].data)
00573 return 0;
00574
00575 null_chunk_retry:
00576 if (url_feof(pb))
00577 return -1;
00578
00579 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00580 err = nsv_resync(s);
00581 if (err < 0)
00582 return err;
00583 if (nsv->state == NSV_FOUND_NSVS)
00584 err = nsv_parse_NSVs_header(s);
00585 if (err < 0)
00586 return err;
00587 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00588 return -1;
00589
00590 auxcount = avio_r8(pb);
00591 vsize = avio_rl16(pb);
00592 asize = avio_rl16(pb);
00593 vsize = (vsize << 4) | (auxcount >> 4);
00594 auxcount &= 0x0f;
00595 av_dlog(s, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize);
00596
00597 for (i = 0; i < auxcount; i++) {
00598 uint32_t av_unused auxtag;
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 (url_feof(pb))
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 = AV_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 if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0)
00724 return -1;
00725
00726 nst->frame_offset = st->index_entries[index].timestamp;
00727 nsv->state = NSV_UNSYNC;
00728 return 0;
00729 }
00730
00731 static int nsv_read_close(AVFormatContext *s)
00732 {
00733
00734 NSVContext *nsv = s->priv_data;
00735
00736 av_freep(&nsv->nsvs_file_offset);
00737 av_freep(&nsv->nsvs_timestamps);
00738 if (nsv->ahead[0].data)
00739 av_free_packet(&nsv->ahead[0]);
00740 if (nsv->ahead[1].data)
00741 av_free_packet(&nsv->ahead[1]);
00742
00743 #if 0
00744
00745 for(i=0;i<s->nb_streams;i++) {
00746 AVStream *st = s->streams[i];
00747 NSVStream *ast = st->priv_data;
00748 if(ast){
00749 av_free(ast->index_entries);
00750 av_free(ast);
00751 }
00752 av_free(st->codec->palctrl);
00753 }
00754
00755 #endif
00756 return 0;
00757 }
00758
00759 static int nsv_probe(AVProbeData *p)
00760 {
00761 int i, score = 0;
00762
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 (AV_RL32(p->buf + i) == AV_RL32("NSVs")) {
00775
00776 int vsize = AV_RL24(p->buf+i+19) >> 4;
00777 int asize = AV_RL16(p->buf+i+22);
00778 int offset = i + 23 + asize + vsize + 1;
00779 if (offset <= p->buf_size - 2 && AV_RL16(p->buf + offset) == 0xBEEF)
00780 return 4*AVPROBE_SCORE_MAX/5;
00781 score = AVPROBE_SCORE_MAX/5;
00782 }
00783 }
00784
00785 if (av_match_ext(p->filename, "nsv"))
00786 return AVPROBE_SCORE_MAX/2;
00787
00788 return score;
00789 }
00790
00791 AVInputFormat ff_nsv_demuxer = {
00792 .name = "nsv",
00793 .long_name = NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
00794 .priv_data_size = sizeof(NSVContext),
00795 .read_probe = nsv_probe,
00796 .read_header = nsv_read_header,
00797 .read_packet = nsv_read_packet,
00798 .read_close = nsv_read_close,
00799 .read_seek = nsv_read_seek,
00800 };