📄 nsvdec.c.svn-base
字号:
nsv->nsvf_index_data[i], size + nsv->nsvf_index_data[i], b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) )); } //url_fseek(pb, size, SEEK_SET); /* go back to end of header */#undef V#endif url_fseek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */ if (url_feof(pb)) return -1; nsv->state = NSV_HAS_READ_NSVF; return 0;}static int nsv_parse_NSVs_header(AVFormatContext *s, AVFormatParameters *ap){ NSVContext *nsv = s->priv_data; ByteIOContext *pb = &s->pb; uint32_t vtag, atag; uint16_t vwidth, vheight; AVRational framerate; int i; uint16_t unknown; AVStream *st; NSVStream *nst; PRINT(("%s()\n", __FUNCTION__)); vtag = get_le32(pb); atag = get_le32(pb); vwidth = get_le16(pb); vheight = get_le16(pb); i = get_byte(pb); /* XXX how big must the table be ? */ /* seems there is more to that... */ PRINT(("NSV NSVs framerate code %2x\n", i)); if(i&0x80) framerate= nsv_framerate_table[i & 0x7F]; else framerate= (AVRational){i, 1}; unknown = get_le16(pb);#ifdef DEBUG print_tag("NSV NSVs vtag", vtag, 0); print_tag("NSV NSVs atag", atag, 0); PRINT(("NSV NSVs vsize %dx%d\n", vwidth, vheight));#endif /* XXX change to ap != NULL ? */ if (s->nb_streams == 0) { /* streams not yet published, let's do that */ nsv->vtag = vtag; nsv->atag = atag; nsv->vwidth = vwidth; nsv->vheight = vwidth; if (vtag != T_NONE) { st = av_new_stream(s, NSV_ST_VIDEO); if (!st) goto fail; nst = av_mallocz(sizeof(NSVStream)); if (!nst) goto fail; st->priv_data = nst; st->codec->codec_type = CODEC_TYPE_VIDEO; st->codec->codec_tag = vtag; st->codec->codec_id = codec_get_id(nsv_codec_video_tags, vtag); st->codec->width = vwidth; st->codec->height = vheight; st->codec->bits_per_sample = 24; /* depth XXX */ av_set_pts_info(st, 64, framerate.den, framerate.num); st->start_time = 0; st->duration = av_rescale(nsv->duration, framerate.num, 1000*framerate.den); } if (atag != T_NONE) {#ifndef DISABLE_AUDIO st = av_new_stream(s, NSV_ST_AUDIO); if (!st) goto fail; nst = av_mallocz(sizeof(NSVStream)); if (!nst) goto fail; st->priv_data = nst; st->codec->codec_type = CODEC_TYPE_AUDIO; st->codec->codec_tag = atag; st->codec->codec_id = codec_get_id(nsv_codec_audio_tags, atag); st->start_time = 0;// st->duration = nsv->duration; //FIXME st->need_parsing = 1; /* for PCM we will read a chunk later and put correct info */ /* XXX:FIXME */ //st->codec->channels = 2; //XXX:channels; //st->codec->sample_rate = 1000; //av_set_pts_info(st, 64, 1, st->codec->sample_rate);#endif }#ifdef CHECK_SUBSEQUENT_NSVS } else { if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) { PRINT(("NSV NSVs header values differ from the first one!!!\n")); //return -1; }#endif /* CHECK_SUBSEQUENT_NSVS */ } nsv->state = NSV_HAS_READ_NSVS; return 0;fail: /* XXX */ nsv->state = NSV_UNSYNC; return -1;}static int nsv_read_header(AVFormatContext *s, AVFormatParameters *ap){ NSVContext *nsv = s->priv_data; int i, err; PRINT(("%s()\n", __FUNCTION__)); PRINT(("filename '%s'\n", s->filename)); nsv->state = NSV_UNSYNC; nsv->ahead[0].data = nsv->ahead[1].data = NULL; for (i = 0; i < NSV_MAX_RESYNC_TRIES; i++) { if (nsv_resync(s) < 0) return -1; if (nsv->state == NSV_FOUND_NSVF) err = nsv_parse_NSVf_header(s, ap); /* we need the first NSVs also... */ if (nsv->state == NSV_FOUND_NSVS) { err = nsv_parse_NSVs_header(s, ap); break; /* we just want the first one */ } } if (s->nb_streams < 1) /* no luck so far */ return -1; /* now read the first chunk, so we can attempt to decode more info */ err = nsv_read_chunk(s, 1); PRINT(("parsed header\n")); return 0;}static int nsv_read_chunk(AVFormatContext *s, int fill_header){ NSVContext *nsv = s->priv_data; ByteIOContext *pb = &s->pb; AVStream *st[2] = {NULL, NULL}; NSVStream *nst; AVPacket *pkt; int i, err = 0; uint8_t auxcount; /* number of aux metadata, also 4 bits of vsize */ uint32_t vsize; uint16_t asize; uint16_t auxsize; uint32_t auxtag; PRINT(("%s(%d)\n", __FUNCTION__, fill_header)); if (nsv->ahead[0].data || nsv->ahead[1].data) return 0; //-1; /* hey! eat what you've in your plate first! */null_chunk_retry: if (url_feof(pb)) return -1; for (i = 0; i < NSV_MAX_RESYNC_TRIES && nsv->state < NSV_FOUND_NSVS && !err; i++) err = nsv_resync(s); if (err < 0) return err; if (nsv->state == NSV_FOUND_NSVS) err = nsv_parse_NSVs_header(s, NULL); if (err < 0) return err; if (nsv->state != NSV_HAS_READ_NSVS && nsv->state != NSV_FOUND_BEEF) return -1; auxcount = get_byte(pb); vsize = get_le16(pb); asize = get_le16(pb); vsize = (vsize << 4) | (auxcount >> 4); auxcount &= 0x0f; PRINT(("NSV CHUNK %d aux, %u bytes video, %d bytes audio\n", auxcount, vsize, asize)); /* skip aux stuff */ for (i = 0; i < auxcount; i++) { auxsize = get_le16(pb); auxtag = get_le32(pb); PRINT(("NSV aux data: '%c%c%c%c', %d bytes\n", (auxtag & 0x0ff), ((auxtag >> 8) & 0x0ff), ((auxtag >> 16) & 0x0ff), ((auxtag >> 24) & 0x0ff), auxsize)); url_fskip(pb, auxsize); vsize -= auxsize + sizeof(uint16_t) + sizeof(uint32_t); /* that's becoming braindead */ } if (url_feof(pb)) return -1; if (!vsize && !asize) { nsv->state = NSV_UNSYNC; goto null_chunk_retry; } /* map back streams to v,a */ if (s->streams[0]) st[s->streams[0]->id] = s->streams[0]; if (s->streams[1]) st[s->streams[1]->id] = s->streams[1]; if (vsize/* && st[NSV_ST_VIDEO]*/) { nst = st[NSV_ST_VIDEO]->priv_data; pkt = &nsv->ahead[NSV_ST_VIDEO]; av_get_packet(pb, pkt, vsize); pkt->stream_index = st[NSV_ST_VIDEO]->index;//NSV_ST_VIDEO; pkt->dts = nst->frame_offset++; pkt->flags |= PKT_FLAG_KEY; /* stupid format has no way to tell XXX: try the index *//* for (i = 0; i < MIN(8, vsize); i++) PRINT(("NSV video: [%d] = %02x\n", i, pkt->data[i]));*/ } if (asize/*st[NSV_ST_AUDIO]*/) { nst = st[NSV_ST_AUDIO]->priv_data; pkt = &nsv->ahead[NSV_ST_AUDIO]; /* read raw audio specific header on the first audio chunk... */ /* on ALL audio chunks ?? seems so! */ if (asize && st[NSV_ST_AUDIO]->codec->codec_tag == MKTAG('P', 'C', 'M', ' ')/* && fill_header*/) { uint8_t bps; uint8_t channels; uint16_t samplerate; bps = get_byte(pb); channels = get_byte(pb); samplerate = get_le16(pb); asize-=4; PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate)); if (fill_header) { st[NSV_ST_AUDIO]->need_parsing = 0; /* we know everything */ if (bps != 16) { PRINT(("NSV AUDIO bit/sample != 16 (%d)!!!\n", bps)); } bps /= channels; // ??? if (bps == 8) st[NSV_ST_AUDIO]->codec->codec_id = CODEC_ID_PCM_U8; samplerate /= 4;/* UGH ??? XXX */ channels = 1; st[NSV_ST_AUDIO]->codec->channels = channels; st[NSV_ST_AUDIO]->codec->sample_rate = samplerate; av_set_pts_info(st[NSV_ST_AUDIO], 64, 1, st[NSV_ST_AUDIO]->codec->sample_rate); PRINT(("NSV RAWAUDIO: bps %d, nchan %d, srate %d\n", bps, channels, samplerate)); } } av_get_packet(pb, pkt, asize); pkt->stream_index = st[NSV_ST_AUDIO]->index;//NSV_ST_AUDIO; //pkt->dts = nst->frame_offset; //if (nst->sample_size) // pkt->dts /= nst->sample_size; nst->frame_offset += asize; // XXX: that's valid only for PCM !? } //pkt->flags |= PKT_FLAG_KEY; nsv->state = NSV_UNSYNC; return 0;}static int nsv_read_packet(AVFormatContext *s, AVPacket *pkt){ NSVContext *nsv = s->priv_data; int i, err = 0; PRINT(("%s()\n", __FUNCTION__)); /* in case we don't already have something to eat ... */ if (nsv->ahead[0].data == NULL && nsv->ahead[1].data == NULL) err = nsv_read_chunk(s, 0); if (err < 0) return err; /* now pick one of the plates */ for (i = 0; i < 2; i++) { if (nsv->ahead[i].data) { PRINT(("%s: using cached packet[%d]\n", __FUNCTION__, i)); /* avoid the cost of new_packet + memcpy(->data) */ memcpy(pkt, &nsv->ahead[i], sizeof(AVPacket)); nsv->ahead[i].data = NULL; /* we ate that one */ return pkt->size; } } /* this restaurant is not approvisionned :^] */ return -1;}static int nsv_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags){#if 0 NSVContext *avi = s->priv_data; AVStream *st; NSVStream *ast; int frame_number, i; int64_t pos;#endif return -1;}static int nsv_read_close(AVFormatContext *s){/* int i; */ NSVContext *nsv = s->priv_data; if (nsv->index_entries) av_free(nsv->nsvf_index_data);#if 0 for(i=0;i<s->nb_streams;i++) { AVStream *st = s->streams[i]; NSVStream *ast = st->priv_data; if(ast){ av_free(ast->index_entries); av_free(ast); } av_free(st->codec->extradata); av_free(st->codec->palctrl); }#endif return 0;}static int nsv_probe(AVProbeData *p){ int i;// PRINT(("nsv_probe(), buf_size %d\n", p->buf_size)); /* check file header */ if (p->buf_size <= 32) return 0; if (p->buf[0] == 'N' && p->buf[1] == 'S' && p->buf[2] == 'V' && p->buf[3] == 'f') return AVPROBE_SCORE_MAX; /* streamed files might not have any header */ if (p->buf[0] == 'N' && p->buf[1] == 'S' && p->buf[2] == 'V' && p->buf[3] == 's') return AVPROBE_SCORE_MAX; /* XXX: do streamed files always start at chunk boundary ?? */ /* or do we need to search NSVs in the byte stream ? */ /* seems the servers don't bother starting clean chunks... */ /* sometimes even the first header is at 9KB or something :^) */ for (i = 1; i < p->buf_size - 3; i++) { if (p->buf[i+0] == 'N' && p->buf[i+1] == 'S' && p->buf[i+2] == 'V' && p->buf[i+3] == 's') return AVPROBE_SCORE_MAX-20; } /* so we'll have more luck on extension... */ if (match_ext(p->filename, "nsv")) return AVPROBE_SCORE_MAX-20; /* FIXME: add mime-type check */ return 0;}static AVInputFormat nsv_iformat = { "nsv", "NullSoft Video format", sizeof(NSVContext), nsv_probe, nsv_read_header, nsv_read_packet, nsv_read_close, nsv_read_seek,};int nsvdec_init(void){ av_register_input_format(&nsv_iformat); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -