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 #include "libavutil/intreadwrite.h"
00028
00029
00030 #define CHECK_SUBSEQUENT_NSVS
00031
00032
00033
00034
00035
00036 #define NSV_MAX_RESYNC (500*1024)
00037 #define NSV_MAX_RESYNC_TRIES 300
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 #if 0
00088 struct NSVf_header {
00089 uint32_t chunk_tag;
00090 uint32_t chunk_size;
00091 uint32_t file_size;
00092 uint32_t file_length;
00093 uint32_t info_strings_size;
00094 uint32_t table_entries;
00095 uint32_t table_entries_used;
00096 };
00097
00098 struct NSVs_header {
00099 uint32_t chunk_tag;
00100 uint32_t v4cc;
00101 uint32_t a4cc;
00102 uint16_t vwidth;
00103 uint16_t vheight;
00104 uint8_t framerate;
00105 uint16_t unknown;
00106 };
00107
00108 struct nsv_avchunk_header {
00109 uint8_t vchunk_size_lsb;
00110 uint16_t vchunk_size_msb;
00111 uint16_t achunk_size;
00112 };
00113
00114 struct nsv_pcm_header {
00115 uint8_t bits_per_sample;
00116 uint8_t channel_count;
00117 uint16_t sample_rate;
00118 };
00119 #endif
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 #define T_NSVF MKTAG('N', 'S', 'V', 'f')
00130 #define T_NSVS MKTAG('N', 'S', 'V', 's')
00131 #define T_TOC2 MKTAG('T', 'O', 'C', '2')
00132 #define T_NONE MKTAG('N', 'O', 'N', 'E')
00133 #define T_SUBT MKTAG('S', 'U', 'B', 'T')
00134 #define T_ASYN MKTAG('A', 'S', 'Y', 'N')
00135 #define T_KEYF MKTAG('K', 'E', 'Y', 'F')
00136
00137 #define TB_NSVF MKBETAG('N', 'S', 'V', 'f')
00138 #define TB_NSVS MKBETAG('N', 'S', 'V', 's')
00139
00140
00141 #define NSV_ST_VIDEO 0
00142 #define NSV_ST_AUDIO 1
00143 #define NSV_ST_SUBT 2
00144
00145 enum NSVStatus {
00146 NSV_UNSYNC,
00147 NSV_FOUND_NSVF,
00148 NSV_HAS_READ_NSVF,
00149 NSV_FOUND_NSVS,
00150 NSV_HAS_READ_NSVS,
00151 NSV_FOUND_BEEF,
00152 NSV_GOT_VIDEO,
00153 NSV_GOT_AUDIO,
00154 };
00155
00156 typedef struct NSVStream {
00157 int frame_offset;
00158
00159 int scale;
00160 int rate;
00161 int sample_size;
00162 int start;
00163
00164 int new_frame_offset;
00165 int cum_len;
00166 } NSVStream;
00167
00168 typedef struct {
00169 int base_offset;
00170 int NSVf_end;
00171 uint32_t *nsvs_file_offset;
00172 int index_entries;
00173 enum NSVStatus state;
00174 AVPacket ahead[2];
00175
00176 int64_t duration;
00177 uint32_t vtag, atag;
00178 uint16_t vwidth, vheight;
00179 int16_t avsync;
00180 AVRational framerate;
00181 uint32_t *nsvs_timestamps;
00182
00183 } NSVContext;
00184
00185 static const AVCodecTag nsv_codec_video_tags[] = {
00186 { CODEC_ID_VP3, MKTAG('V', 'P', '3', ' ') },
00187 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '0') },
00188 { CODEC_ID_VP3, MKTAG('V', 'P', '3', '1') },
00189 { CODEC_ID_VP5, MKTAG('V', 'P', '5', ' ') },
00190 { CODEC_ID_VP5, MKTAG('V', 'P', '5', '0') },
00191 { CODEC_ID_VP6, MKTAG('V', 'P', '6', ' ') },
00192 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '0') },
00193 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '1') },
00194 { CODEC_ID_VP6, MKTAG('V', 'P', '6', '2') },
00195 { CODEC_ID_VP8, MKTAG('V', 'P', '8', '0') },
00196
00197
00198
00199
00200 { CODEC_ID_MPEG4, MKTAG('X', 'V', 'I', 'D') },
00201 { CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', '3') },
00202 { CODEC_ID_NONE, 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_AAC, MKTAG('V', 'L', 'B', ' ') },
00210 { CODEC_ID_SPEEX, MKTAG('S', 'P', 'X', ' ') },
00211 { CODEC_ID_PCM_U16LE, MKTAG('P', 'C', 'M', ' ') },
00212 { CODEC_ID_NONE, 0 },
00213 };
00214
00215
00216 static int nsv_read_chunk(AVFormatContext *s, int fill_header);
00217
00218 #define print_tag(str, tag, size) \
00219 av_dlog(NULL, "%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
00226 static int nsv_resync(AVFormatContext *s)
00227 {
00228 NSVContext *nsv = s->priv_data;
00229 AVIOContext *pb = s->pb;
00230 uint32_t v = 0;
00231 int i;
00232
00233 av_dlog(s, "%s(), offset = %"PRId64", state = %d\n", __FUNCTION__, avio_tell(pb), nsv->state);
00234
00235
00236
00237 for (i = 0; i < NSV_MAX_RESYNC; i++) {
00238 if (url_feof(pb)) {
00239 av_dlog(s, "NSV EOF\n");
00240 nsv->state = NSV_UNSYNC;
00241 return -1;
00242 }
00243 v <<= 8;
00244 v |= avio_r8(pb);
00245 if (i < 8) {
00246 av_dlog(s, "NSV resync: [%d] = %02x\n", i, v & 0x0FF);
00247 }
00248
00249 if ((v & 0x0000ffff) == 0xefbe) {
00250 av_dlog(s, "NSV resynced on BEEF after %d bytes\n", i+1);
00251 nsv->state = NSV_FOUND_BEEF;
00252 return 0;
00253 }
00254
00255 if (v == TB_NSVF) {
00256 av_dlog(s, "NSV resynced on NSVf after %d bytes\n", i+1);
00257 nsv->state = NSV_FOUND_NSVF;
00258 return 0;
00259 }
00260 if (v == MKBETAG('N', 'S', 'V', 's')) {
00261 av_dlog(s, "NSV resynced on NSVs after %d bytes\n", i+1);
00262 nsv->state = NSV_FOUND_NSVS;
00263 return 0;
00264 }
00265
00266 }
00267 av_dlog(s, "NSV sync lost\n");
00268 return -1;
00269 }
00270
00271 static int nsv_parse_NSVf_header(AVFormatContext *s, AVFormatParameters *ap)
00272 {
00273 NSVContext *nsv = s->priv_data;
00274 AVIOContext *pb = s->pb;
00275 unsigned int av_unused file_size;
00276 unsigned int size;
00277 int64_t duration;
00278 int strings_size;
00279 int table_entries;
00280 int table_entries_used;
00281
00282 av_dlog(s, "%s()\n", __FUNCTION__);
00283
00284 nsv->state = NSV_UNSYNC;
00285
00286 size = avio_rl32(pb);
00287 if (size < 28)
00288 return -1;
00289 nsv->NSVf_end = size;
00290
00291
00292 file_size = (uint32_t)avio_rl32(pb);
00293 av_dlog(s, "NSV NSVf chunk_size %u\n", size);
00294 av_dlog(s, "NSV NSVf file_size %u\n", file_size);
00295
00296 nsv->duration = duration = avio_rl32(pb);
00297 av_dlog(s, "NSV NSVf duration %"PRId64" ms\n", duration);
00298
00299
00300 strings_size = avio_rl32(pb);
00301 table_entries = avio_rl32(pb);
00302 table_entries_used = avio_rl32(pb);
00303 av_dlog(s, "NSV NSVf info-strings size: %d, table entries: %d, bis %d\n",
00304 strings_size, table_entries, table_entries_used);
00305 if (url_feof(pb))
00306 return -1;
00307
00308 av_dlog(s, "NSV got header; filepos %"PRId64"\n", avio_tell(pb));
00309
00310 if (strings_size > 0) {
00311 char *strings;
00312 char *p, *endp;
00313 char *token, *value;
00314 char quote;
00315
00316 p = strings = av_mallocz(strings_size + 1);
00317 if (!p)
00318 return AVERROR(ENOMEM);
00319 endp = strings + strings_size;
00320 avio_read(pb, strings, strings_size);
00321 while (p < endp) {
00322 while (*p == ' ')
00323 p++;
00324 if (p >= endp-2)
00325 break;
00326 token = p;
00327 p = strchr(p, '=');
00328 if (!p || p >= endp-2)
00329 break;
00330 *p++ = '\0';
00331 quote = *p++;
00332 value = p;
00333 p = strchr(p, quote);
00334 if (!p || p >= endp)
00335 break;
00336 *p++ = '\0';
00337 av_dlog(s, "NSV NSVf INFO: %s='%s'\n", token, value);
00338 av_dict_set(&s->metadata, token, value, 0);
00339 }
00340 av_free(strings);
00341 }
00342 if (url_feof(pb))
00343 return -1;
00344
00345 av_dlog(s, "NSV got infos; filepos %"PRId64"\n", avio_tell(pb));
00346
00347 if (table_entries_used > 0) {
00348 int i;
00349 nsv->index_entries = table_entries_used;
00350 if((unsigned)table_entries_used >= UINT_MAX / sizeof(uint32_t))
00351 return -1;
00352 nsv->nsvs_file_offset = av_malloc((unsigned)table_entries_used * sizeof(uint32_t));
00353
00354 for(i=0;i<table_entries_used;i++)
00355 nsv->nsvs_file_offset[i] = avio_rl32(pb) + size;
00356
00357 if(table_entries > table_entries_used &&
00358 avio_rl32(pb) == MKTAG('T','O','C','2')) {
00359 nsv->nsvs_timestamps = av_malloc((unsigned)table_entries_used*sizeof(uint32_t));
00360 for(i=0;i<table_entries_used;i++) {
00361 nsv->nsvs_timestamps[i] = avio_rl32(pb);
00362 }
00363 }
00364 }
00365
00366 av_dlog(s, "NSV got index; filepos %"PRId64"\n", avio_tell(pb));
00367
00368 #ifdef DEBUG_DUMP_INDEX
00369 #define V(v) ((v<0x20 || v > 127)?'.':v)
00370
00371 av_dlog(s, "NSV %d INDEX ENTRIES:\n", table_entries);
00372 av_dlog(s, "NSV [dataoffset][fileoffset]\n", table_entries);
00373 for (i = 0; i < table_entries; i++) {
00374 unsigned char b[8];
00375 avio_seek(pb, size + nsv->nsvs_file_offset[i], SEEK_SET);
00376 avio_read(pb, b, 8);
00377 av_dlog(s, "NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x"
00378 "%c%c%c%c%c%c%c%c\n",
00379 nsv->nsvs_file_offset[i], size + nsv->nsvs_file_offset[i],
00380 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7],
00381 V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) );
00382 }
00383
00384 #undef V
00385 #endif
00386
00387 avio_seek(pb, nsv->base_offset + size, SEEK_SET);
00388
00389 if (url_feof(pb))
00390 return -1;
00391 nsv->state = NSV_HAS_READ_NSVF;
00392 return 0;
00393 }
00394
00395 static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap)
00396 {
00397 NSVContext *nsv = s->priv_data;
00398 AVIOContext *pb = s->pb;
00399 uint32_t vtag, atag;
00400 uint16_t vwidth, vheight;
00401 AVRational framerate;
00402 int i;
00403 AVStream *st;
00404 NSVStream *nst;
00405 av_dlog(s, "%s()\n", __FUNCTION__);
00406
00407 vtag = avio_rl32(pb);
00408 atag = avio_rl32(pb);
00409 vwidth = avio_rl16(pb);
00410 vheight = avio_rl16(pb);
00411 i = avio_r8(pb);
00412
00413 av_dlog(s, "NSV NSVs framerate code %2x\n", i);
00414 if(i&0x80) {
00415 int t=(i & 0x7F)>>2;
00416 if(t<16) framerate = (AVRational){1, t+1};
00417 else framerate = (AVRational){t-15, 1};
00418
00419 if(i&1){
00420 framerate.num *= 1000;
00421 framerate.den *= 1001;
00422 }
00423
00424 if((i&3)==3) framerate.num *= 24;
00425 else if((i&3)==2) framerate.num *= 25;
00426 else framerate.num *= 30;
00427 }
00428 else
00429 framerate= (AVRational){i, 1};
00430
00431 nsv->avsync = avio_rl16(pb);
00432 nsv->framerate = framerate;
00433
00434 print_tag("NSV NSVs vtag", vtag, 0);
00435 print_tag("NSV NSVs atag", atag, 0);
00436 av_dlog(s, "NSV NSVs vsize %dx%d\n", vwidth, vheight);
00437
00438
00439 if (s->nb_streams == 0) {
00440 nsv->vtag = vtag;
00441 nsv->atag = atag;
00442 nsv->vwidth = vwidth;
00443 nsv->vheight = vwidth;
00444 if (vtag != T_NONE) {
00445 int i;
00446 st = avformat_new_stream(s, NULL);
00447 if (!st)
00448 goto fail;
00449
00450 st->id = NSV_ST_VIDEO;
00451 nst = av_mallocz(sizeof(NSVStream));
00452 if (!nst)
00453 goto fail;
00454 st->priv_data = nst;
00455 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00456 st->codec->codec_tag = vtag;
00457 st->codec->codec_id = ff_codec_get_id(nsv_codec_video_tags, vtag);
00458 st->codec->width = vwidth;
00459 st->codec->height = vheight;
00460 st->codec->bits_per_coded_sample = 24;
00461
00462 avpriv_set_pts_info(st, 64, framerate.den, framerate.num);
00463 st->start_time = 0;
00464 st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den);
00465
00466 for(i=0;i<nsv->index_entries;i++) {
00467 if(nsv->nsvs_timestamps) {
00468 av_add_index_entry(st, nsv->nsvs_file_offset[i], nsv->nsvs_timestamps[i],
00469 0, 0, AVINDEX_KEYFRAME);
00470 } else {
00471 int64_t ts = av_rescale(i*nsv->duration/nsv->index_entries, framerate.num, 1000*framerate.den);
00472 av_add_index_entry(st, nsv->nsvs_file_offset[i], ts, 0, 0, AVINDEX_KEYFRAME);
00473 }
00474 }
00475 }
00476 if (atag != T_NONE) {
00477 #ifndef DISABLE_AUDIO
00478 st = avformat_new_stream(s, NULL);
00479 if (!st)
00480 goto fail;
00481
00482 st->id = NSV_ST_AUDIO;
00483 nst = av_mallocz(sizeof(NSVStream));
00484 if (!nst)
00485 goto fail;
00486 st->priv_data = nst;
00487 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00488 st->codec->codec_tag = atag;
00489 st->codec->codec_id = ff_codec_get_id(nsv_codec_audio_tags, atag);
00490
00491 st->need_parsing = AVSTREAM_PARSE_FULL;
00492
00493
00494 avpriv_set_pts_info(st, 64, 1, framerate.num*1000);
00495 st->start_time = 0;
00496 st->duration = (int64_t)nsv->duration * framerate.num;
00497 #endif
00498 }
00499 #ifdef CHECK_SUBSEQUENT_NSVS
00500 } else {
00501 if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) {
00502 av_dlog(s, "NSV NSVs header values differ from the first one!!!\n");
00503
00504 }
00505 #endif
00506 }
00507
00508 nsv->state = NSV_HAS_READ_NSVS;
00509 return 0;
00510 fail:
00511
00512 nsv->state = NSV_UNSYNC;
00513 return -1;
00514 }
00515
00516 static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap)
00517 {
00518 NSVContext *nsv = s->priv_data;
00519 int i, err;
00520
00521 av_dlog(s, "%s()\n", __FUNCTION__);
00522 av_dlog(s, "filename '%s'\n", s->filename);
00523
00524 nsv->state = NSV_UNSYNC;
00525 nsv->ahead[0].data = nsv->ahead[1].data = NULL;
00526
00527 for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) {
00528 if (nsv_resync(s) < 0)
00529 return -1;
00530 if (nsv->state == NSV_FOUND_NSVF)
00531 err = nsv_parse_NSVf_header(s, ap);
00532
00533 if (nsv->state == NSV_FOUND_NSVS) {
00534 err = nsv_parse_NSVs_header(s, ap);
00535 break;
00536 }
00537 }
00538 if (s->nb_streams < 1)
00539 return -1;
00540
00541 err = nsv_read_chunk(s, 1);
00542
00543 av_dlog(s, "parsed header\n");
00544 return err;
00545 }
00546
00547 static int nsv_read_chunk(AVFormatContext *s, int fill_header)
00548 {
00549 NSVContext *nsv = s->priv_data;
00550 AVIOContext *pb = s->pb;
00551 AVStream *st[2] = {NULL, NULL};
00552 NSVStream *nst;
00553 AVPacket *pkt;
00554 int i, err = 0;
00555 uint8_t auxcount;
00556 uint32_t vsize;
00557 uint16_t asize;
00558 uint16_t auxsize;
00559 uint32_t av_unused auxtag;
00560
00561 av_dlog(s, "%s(%d)\n", __FUNCTION__, fill_header);
00562
00563 if (nsv->ahead[0].data || nsv->ahead[1].data)
00564 return 0;
00565
00566 null_chunk_retry:
00567 if (url_feof(pb))
00568 return -1;
00569
00570 for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++)
00571 err = nsv_resync(s);
00572 if (err < 0)
00573 return err;
00574 if (nsv->state == NSV_FOUND_NSVS)
00575 err = nsv_parse_NSVs_header(s, NULL);
00576 if (err < 0)
00577 return err;
00578 if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF)
00579 return -1;
00580
00581 auxcount = avio_r8(pb);
00582 vsize = avio_rl16(pb);
00583 asize = avio_rl16(pb);
00584 vsize = (vsize << 4) | (auxcount >> 4);
00585 auxcount &= 0x0f;
00586 av_dlog(s, "NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize);
00587
00588 for (i = 0; i < auxcount; i++) {
00589 auxsize = avio_rl16(pb);
00590 auxtag = avio_rl32(pb);
00591 av_dlog(s, "NSV aux data: '%c%c%c%c', %d bytes\n",
00592 (auxtag & 0x0ff),
00593 ((auxtag >> 8) & 0x0ff),
00594 ((auxtag >> 16) & 0x0ff),
00595 ((auxtag >> 24) & 0x0ff),
00596 auxsize);
00597 avio_skip(pb, auxsize);
00598 vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t);
00599 }
00600
00601 if (url_feof(pb))
00602 return -1;
00603 if (!vsize && !asize) {
00604 nsv->state = NSV_UNSYNC;
00605 goto null_chunk_retry;
00606 }
00607
00608
00609 if (s->streams[0])
00610 st[s->streams[0]->id] = s->streams[0];
00611 if (s->streams[1])
00612 st[s->streams[1]->id] = s->streams[1];
00613
00614 if (vsize) {
00615 nst = st[NSV_ST_VIDEO]->priv_data;
00616 pkt = &nsv->ahead[NSV_ST_VIDEO];
00617 av_get_packet(pb, pkt, vsize);
00618 pkt->stream_index = st[NSV_ST_VIDEO]->index;
00619 pkt->dts = nst->frame_offset;
00620 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00621 for (i = 0; i < FFMIN(8, vsize); i++)
00622 av_dlog(s, "NSV video: [%d] = %02x\n", i, pkt->data[i]);
00623 }
00624 if(st[NSV_ST_VIDEO])
00625 ((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset++;
00626
00627 if (asize) {
00628 nst = st[NSV_ST_AUDIO]->priv_data;
00629 pkt = &nsv->ahead[NSV_ST_AUDIO];
00630
00631
00632 if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')) {
00633 uint8_t bps;
00634 uint8_t channels;
00635 uint16_t samplerate;
00636 bps = avio_r8(pb);
00637 channels = avio_r8(pb);
00638 samplerate = avio_rl16(pb);
00639 asize-=4;
00640 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00641 if (fill_header) {
00642 st[NSV_ST_AUDIO]->need_parsing = AVSTREAM_PARSE_NONE;
00643 if (bps != 16) {
00644 av_dlog(s, "NSV AUDIO bit/sample != 16 (%d)!!!\n", bps);
00645 }
00646 bps /= channels;
00647 if (bps == 8)
00648 st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8;
00649 samplerate /= 4;
00650 channels = 1;
00651 st[NSV_ST_AUDIO]->codec->channels = channels;
00652 st[NSV_ST_AUDIO]->codec->sample_rate = samplerate;
00653 av_dlog(s, "NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate);
00654 }
00655 }
00656 av_get_packet(pb, pkt, asize);
00657 pkt->stream_index = st[NSV_ST_AUDIO]->index;
00658 pkt->flags |= nsv->state == NSV_HAS_READ_NSVS ? AV_PKT_FLAG_KEY : 0;
00659 if( nsv->state == NSV_HAS_READ_NSVS && st[NSV_ST_VIDEO] ) {
00660
00661 pkt->dts = (((NSVStream*)st[NSV_ST_VIDEO]->priv_data)->frame_offset-1);
00662 pkt->dts *= (int64_t)1000 * nsv->framerate.den;
00663 pkt->dts += (int64_t)nsv->avsync * nsv->framerate.num;
00664 av_dlog(s, "NSV AUDIO: sync:%d, dts:%"PRId64, nsv->avsync, pkt->dts);
00665 }
00666 nst->frame_offset++;
00667 }
00668
00669 nsv->state = NSV_UNSYNC;
00670 return 0;
00671 }
00672
00673
00674 static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt)
00675 {
00676 NSVContext *nsv = s->priv_data;
00677 int i, err = 0;
00678
00679 av_dlog(s, "%s()\n", __FUNCTION__);
00680
00681
00682 if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL)
00683 err = nsv_read_chunk(s, 0);
00684 if (err < 0)
00685 return err;
00686
00687
00688 for (i = 0; i < 2; i++) {
00689 if (nsv->ahead[i].data) {
00690 av_dlog(s, "%s: using cached packet[%d]\n", __FUNCTION__, i);
00691
00692 memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket));
00693 nsv->ahead[i].data = NULL;
00694 return pkt->size;
00695 }
00696 }
00697
00698
00699 return -1;
00700 }
00701
00702 static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
00703 {
00704 NSVContext *nsv = s->priv_data;
00705 AVStream *st = s->streams[stream_index];
00706 NSVStream *nst = st->priv_data;
00707 int index;
00708
00709 index = av_index_search_timestamp(st, timestamp, flags);
00710 if(index < 0)
00711 return -1;
00712
00713 if (avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET) < 0)
00714 return -1;
00715
00716 nst->frame_offset = st->index_entries[index].timestamp;
00717 nsv->state = NSV_UNSYNC;
00718 return 0;
00719 }
00720
00721 static int nsv_read_close(AVFormatContext *s)
00722 {
00723
00724 NSVContext *nsv = s->priv_data;
00725
00726 av_freep(&nsv->nsvs_file_offset);
00727 av_freep(&nsv->nsvs_timestamps);
00728 if (nsv->ahead[0].data)
00729 av_free_packet(&nsv->ahead[0]);
00730 if (nsv->ahead[1].data)
00731 av_free_packet(&nsv->ahead[1]);
00732
00733 #if 0
00734
00735 for(i=0;i<s->nb_streams;i++) {
00736 AVStream *st = s->streams[i];
00737 NSVStream *ast = st->priv_data;
00738 if(ast){
00739 av_free(ast->index_entries);
00740 av_free(ast);
00741 }
00742 av_free(st->codec->palctrl);
00743 }
00744
00745 #endif
00746 return 0;
00747 }
00748
00749 static int nsv_probe(AVProbeData *p)
00750 {
00751 int i, score = 0;
00752
00753 av_dlog(NULL, "nsv_probe(), buf_size %d\n", p->buf_size);
00754
00755
00756 if (p->buf[0] == 'N' && p->buf[1] == 'S' &&
00757 p->buf[2] == 'V' && (p->buf[3] == 'f' || p->buf[3] == 's'))
00758 return AVPROBE_SCORE_MAX;
00759
00760
00761
00762
00763 for (i = 1; i < p->buf_size - 3; i++) {
00764 if (AV_RL32(p->buf + i) == AV_RL32("NSVs")) {
00765
00766 int vsize = AV_RL24(p->buf+i+19) >> 4;
00767 int asize = AV_RL16(p->buf+i+22);
00768 int offset = i + 23 + asize + vsize + 1;
00769 if (offset <= p->buf_size - 2 && AV_RL16(p->buf + offset) == 0xBEEF)
00770 return 4*AVPROBE_SCORE_MAX/5;
00771 score = AVPROBE_SCORE_MAX/5;
00772 }
00773 }
00774
00775 if (av_match_ext(p->filename, "nsv"))
00776 return AVPROBE_SCORE_MAX/2;
00777
00778 return score;
00779 }
00780
00781 AVInputFormat ff_nsv_demuxer = {
00782 .name = "nsv",
00783 .long_name = NULL_IF_CONFIG_SMALL("Nullsoft Streaming Video"),
00784 .priv_data_size = sizeof(NSVContext),
00785 .read_probe = nsv_probe,
00786 .read_header = nsv_read_header,
00787 .read_packet = nsv_read_packet,
00788 .read_close = nsv_read_close,
00789 .read_seek = nsv_read_seek,
00790 };