示例#1
0
/*************************************************************************
 *
 * Makes a copy of a tag into a PPPoE packe
 *
 ************************************************************************/
void copy_tag(struct pppoe_packet *dest, struct pppoe_tag *pt)
{
    struct pppoe_tag *end_tag = get_tag(dest->hdr, PTT_EOL);
    int tagid;
    int tag_len;
    if( !pt ) {
	return;
    }
    tagid = tag_index(pt->tag_type);

    tag_len = sizeof(struct pppoe_tag) + ntohs(pt->tag_len);

    if( end_tag ){
	memcpy(((char*)end_tag)+tag_len ,
	       end_tag, sizeof(struct pppoe_tag));

	dest->tags[tagid]=end_tag;
	dest->tags[TAG_EOL] = (struct pppoe_tag*)((char*)dest->tags[TAG_EOL] + tag_len);
	memcpy(end_tag, pt, tag_len);
	dest->hdr->length = htons(ntohs(dest->hdr->length) + tag_len);

    }else{
	memcpy(next_tag(dest->hdr),pt, tag_len);
	dest->tags[tagid]=next_tag(dest->hdr);
	add_tag(dest->hdr,next_tag(dest->hdr));
    }


}
示例#2
0
/*************************************************************************
 *
 * Look for a tag of a specific type
 *
 ************************************************************************/
struct pppoe_tag *get_tag(struct pppoe_hdr *ph, u_int16_t idx)
{
    char *end = (char *) next_tag(ph);
    char *ptn = NULL;
    struct pppoe_tag *pt = &ph->tag[0];

    /*
     * Keep processing tags while a tag header will still fit.
     *
     * This check will ensure that the entire tag header pointed
     * to by pt will fit inside the message, and thus it will be
     * valid to check the tag_type and tag_len fields.
     */
    while ((char *)(pt + 1) <= end) {
	/*
	 * If the tag data would go past the end of the packet, abort.
	 */
	ptn = (((char *) (pt + 1)) + ntohs(pt->tag_len));
	if (ptn > end)
	    return NULL;

	if (pt->tag_type == idx)
	    return pt;

	pt = (struct pppoe_tag *) ptn;
    }

    return NULL;
}
示例#3
0
static const char *parse_field(struct buffer *self, int tag)
{
	if (parse_tag(self) != tag) {
		next_tag(self);
		return NULL;
	}

	return parse_value(self);
}
示例#4
0
/**************************************************************************
 *
 * Update header to reflect the addition of a new tag
 *
 **************************************************************************/
static  void add_tag(struct pppoe_hdr *ph, struct pppoe_tag *pt)
{
    int len = (ntohs(ph->length) +
	       ntohs(pt->tag_len) +
	       sizeof(struct pppoe_tag));

    if (pt != next_tag(ph))
	printf("PPPoE add_tag caller is buggy\n");

    ph->length = htons(len);
}
示例#5
0
static const char *parse_field_promisc(struct buffer *self, int *tag)
{
	*tag = parse_tag(self);

	if (!(*tag)) {
		next_tag(self);
		return NULL;
	}

	return parse_value(self);
}
示例#6
0
int main(int argc, char *argv[]) {
    int valid = FALSE;
    int x = 0;
    char str1[8];
    char str2[8];

    next_tag(str1);
    gets(str2);

    if (strncmp(str1, str2, 8) == 0)
        valid = TRUE;

    printf("buffer1: str1(%s), str2(%s), valid(%d)\n", str1, str2, valid);
}
示例#7
0
/* return the size of the found tag */
static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
{
    unsigned int tag;
    int64_t size;

    for (;;) {
        if (pb->eof_reached)
            return -1;
        size = next_tag(pb, &tag);
        if (tag == tag1)
            break;
        wav_seek_tag(pb, size, SEEK_CUR);
    }
    return size;
}
示例#8
0
/* return the size of the found tag */
static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
{
    unsigned int tag;
    int64_t size;

    for (;;) {
        if (url_feof(pb))
            return -1;
        size = next_tag(pb, &tag);
        if (tag == tag1)
            break;
        avio_skip(pb, size);
    }
    return size;
}
示例#9
0
/* return the size of the found tag */
static int64_t find_tag(AVIOContext *pb, uint32_t tag1)
{
    unsigned int tag;
    int64_t size;

    for (;;) {
        if (url_feof(pb))
            return AVERROR_EOF;
        size = next_tag(pb, &tag);
        if (tag == tag1)
            break;
        wav_seek_tag(pb, size, SEEK_CUR);
    }
    return size;
}
示例#10
0
static int parse_field_promisc(struct buffer *self, int *tag, const char **value)
{
	int ret;

	ret = parse_tag(self, tag);

	if (ret)
		goto fail;

	return parse_value(self, value);

fail:
	next_tag(self);
	return ret;
}
示例#11
0
文件: tag.c 项目: nellynette/dex
bool find_tags(const char *name, struct ptr_array *tags)
{
	struct tag *t;
	size_t pos = 0;

	if (!load_tag_file())
		return false;

	t = xnew(struct tag, 1);
	while (next_tag(tag_file, &pos, name, 1, t)) {
		ptr_array_add(tags, t);
		t = xnew(struct tag, 1);
	}
	free(t);
	sort_tags(tags);
	return true;
}
示例#12
0
文件: tag.c 项目: nellynette/dex
void collect_tags(const char *prefix)
{
	struct tag t;
	size_t pos = 0;
	char *prev = NULL;

	if (!load_tag_file())
		return;

	while (next_tag(tag_file, &pos, prefix, 0, &t)) {
		if (!prev || strcmp(prev, t.name)) {
			add_completion(t.name);
			prev = t.name;
			t.name = NULL;
		}
		free_tag(&t);
	}
}
示例#13
0
static void parse_string(sd_stringparser *parser, 
                  void(*frame_cb)(sd_stringparser*, void*, char,int), 
                  void(*tag_cb)(sd_stringparser*, void*, tag_attribute*, int param), 
                  void *data) {

    if(parser->string) {
        int pos = 0;
        while(1) {
            const char *start = parser->string + pos;
            const char *str = parser->string + pos;

            int type = next_tag(&str);
            pos += (str-start);
            start = parser->string + pos;

            if(type == TAG_TAG) {
                // a tag
                tag_attribute attrib;
                if(rn_tag_attribute(static_taglist, &str, &attrib) == 0) {
                    // read the numeric param and call the callback function
                    // if a param is not present, 0 is assumed
                    int pos = 0;
                    int param = rn_int(&pos, str);
                    str += pos;
                    if(tag_cb) tag_cb(parser, data, &attrib, param);
                }
            } else if(type == TAG_FRAME) {
                // a frame
                int duration=0;
                char frame_letter=0;
                rn_frame(&str, &frame_letter, &duration);
                if(frame_cb) frame_cb(parser, data, frame_letter, duration);
            } else if(type == TAG_MARKER) {
                // an end of frame descriptor marker (a dash, '-')
                rn_descriptor_marker(&str);
            } else {
                // the end of stream
                break;
            }

            pos += (str-start);
        }
    }
}
示例#14
0
static int parse_field(struct buffer *self, int tag, const char **value)
{
	int ptag, ret;

	ret = parse_tag(self, &ptag);

	if (ret)
		goto fail;
	else if (ptag != tag) {
		ret = FIX_MSG_STATE_GARBLED;
		goto fail;
	}

	return parse_value(self, value);

fail:
	next_tag(self);
	return ret;
}
示例#15
0
文件: tobin.c 项目: huxiaomin/tstools
int main(int argc, char *argv[])
{
        int cnt;
        char tbuf[LINE_LENGTH_MAX + 10]; /* txt data buffer */
        uint8_t bbuf[LINE_LENGTH_MAX / 3 + 10]; /* bin data buffer */
        char *tag;
        char *pt;

        if(0 != deal_with_parameter(argc, argv)) {
                return -1;
        }

        fd_o = fopen(file_o, "wb");
        if(NULL == fd_o) {
                RPTERR("open \"%s\" failed", file_o);
                return -1;
        }

        while(NULL != fgets(tbuf, LINE_LENGTH_MAX, stdin)) {
                pt = tbuf;
                while(0 == next_tag(&tag, &pt)) {
                        if(0 == strcmp(tag, "*ts") ||
                           0 == strcmp(tag, "*rs") ||
                           0 == strcmp(tag, "*data") ||
                           0 == strcmp(tag, "*pes") ||
                           0 == strcmp(tag, "*es")) {
                                cnt = next_nbyte_hex(bbuf, &pt, LINE_LENGTH_MAX / 3);
                                (void)fwrite(bbuf, (size_t)cnt, 1, fd_o);
                        }
                }
        }

        fclose(fd_o);

        return 0;
}
示例#16
0
/* wav input */
static int wav_read_header(AVFormatContext *s)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count = 0;
    int rf64;
    uint32_t tag;
    AVIOContext *pb      = s->pb;
    AVStream *st         = NULL;
    WAVDemuxContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;

    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return AVERROR_INVALIDDATA;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return AVERROR_INVALIDDATA;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return AVERROR_INVALIDDATA;
        size = avio_rl32(pb);
        if (size < 16)
            return AVERROR_INVALIDDATA;
        avio_rl64(pb); /* RIFF size */

        data_size    = avio_rl64(pb);
        sample_count = avio_rl64(pb);

        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 16); /* skip rest of ds64 chunk */
    }

    for (;;) {
        size         = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (pb->eof_reached)
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR,
                       "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size    = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!(pb->seekable & AVIO_SEEKABLE_NORMAL) || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f', 'a', 'c', 't'):
            if (!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b', 'e', 'x', 't'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        case MKTAG('L', 'I', 'S', 'T'):
            if (size < 4) {
                av_log(s, AV_LOG_ERROR, "too short LIST");
                return AVERROR_INVALIDDATA;
            }
            switch (avio_rl32(pb)) {
            case MKTAG('I', 'N', 'F', 'O'):
                if ((ret = ff_read_riff_info(s, size - 4)) < 0)
                    return ret;
            }
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }

break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);

    if (!sample_count && st->codecpar->channels &&
        av_get_bits_per_sample(st->codecpar->codec_id))
        sample_count = (data_size << 3) /
                       (st->codecpar->channels *
                        (uint64_t)av_get_bits_per_sample(st->codecpar->codec_id));
    if (sample_count)
        st->duration = sample_count;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    return 0;
}
示例#17
0
/* wav input */
static int wav_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count=0;
    int rf64;
    unsigned int tag;
    AVIOContext *pb = s->pb;
    AVStream *st;
    WAVContext *wav = s->priv_data;

    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return -1;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return -1;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return -1;
        size = avio_rl32(pb);
        if (size < 16)
            return -1;
        avio_rl64(pb); /* RIFF size */
        data_size = avio_rl64(pb);
        sample_count = avio_rl64(pb);
        avio_seek(pb, size - 16, SEEK_CUR); /* skip rest of ds64 chunk */
    }

    /* parse fmt header */
    size = find_tag(pb, MKTAG('f', 'm', 't', ' '));
    if (size < 0)
        return -1;
    st = av_new_stream(s, 0);
    if (!st)
        return AVERROR(ENOMEM);

    ff_get_wav_header(pb, st->codec, size);
    st->need_parsing = AVSTREAM_PARSE_FULL;

    av_set_pts_info(st, 64, 1, st->codec->sample_rate);

    for (;;) {
        if (url_feof(pb))
            return -1;
        size = next_tag(pb, &tag);
        if (tag == MKTAG('d', 'a', 't', 'a')){
            break;
        }else if (tag == MKTAG('f','a','c','t') && !sample_count){
            sample_count = avio_rl32(pb);
            size -= 4;
        }
        avio_seek(pb, size, SEEK_CUR);
    }
    if (rf64)
        size = data_size;
    if (size < 0)
        return -1;
    if (!size) {
        wav->data_end = INT64_MAX;
    } else
        wav->data_end= avio_tell(pb) + size;

    if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
        sample_count = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
    if (sample_count)
        st->duration = sample_count;
    return 0;
}
示例#18
0
/*************************************************************************
 *
 * Construct and send a discovery message.
 *
 ************************************************************************/
int send_disc(struct session *ses, struct pppoe_packet *p)
{
    char buf[MAX_PAYLOAD + sizeof(struct pppoe_hdr)];
    int data_len = sizeof(struct pppoe_hdr);

    struct pppoe_hdr *ph = NULL;
    struct pppoe_tag *tag = NULL;
    int i, err = 0;
    int got_host_uniq = 0;
    int got_srv_name = 0;
    int got_ac_name = 0;

    for (i = 0; i < MAX_TAGS; i++) {
	if (!p->tags[i])
	    continue;

	got_host_uniq |= (p->tags[i]->tag_type == PTT_HOST_UNIQ);

	/* Relay identifiers qualify as HOST_UNIQ's:
	   we need HOST_UNIQ to uniquely identify the packet,
	   PTT_RELAY_SID is sufficient for us for outgoing packets */
	got_host_uniq |= (p->tags[i]->tag_type == PTT_RELAY_SID);

	got_srv_name |= (p->tags[i]->tag_type == PTT_SRV_NAME);
	got_ac_name  |= (p->tags[i]->tag_type == PTT_AC_NAME);

	data_len += (ntohs(p->tags[i]->tag_len) +
		     sizeof(struct pppoe_tag));
    }

    ph = (struct pppoe_hdr *) buf;


    memcpy(ph, p->hdr, sizeof(struct pppoe_hdr));
    ph->length = __constant_htons(0);

    /* if no HOST_UNIQ tags --- add one with process id */
    if (!got_host_uniq){
	data_len += (sizeof(struct pppoe_tag) +
		     sizeof(struct session *));
	tag = next_tag(ph);
	tag->tag_type = PTT_HOST_UNIQ;
	tag->tag_len = htons(sizeof(struct session *));
	memcpy(tag->tag_data,
	       &ses,
	       sizeof(struct session *));

	add_tag(ph, tag);
    }

    if( !got_srv_name ){
	data_len += sizeof(struct pppoe_tag);
	tag = next_tag(ph);
	tag->tag_type = PTT_SRV_NAME;
	tag->tag_len = 0;
	add_tag(ph, tag);
    }

    if(!got_ac_name && ph->code==PADO_CODE){
	data_len += sizeof(struct pppoe_tag);
	tag = next_tag(ph);
	tag->tag_type = PTT_AC_NAME;
	tag->tag_len = 0;
	add_tag(ph, tag);
    }

    for (i = 0; i < MAX_TAGS; i++) {
	if (!p->tags[i])
	    continue;

	tag = next_tag(ph);
	memcpy(tag, p->tags[i],
	       sizeof(struct pppoe_tag) + ntohs(p->tags[i]->tag_len));

	add_tag(ph, tag);
    }

    /* Now fixup the packet struct to make sure all of its pointers
       are self-contained */
    memcpy( p->hdr , ph, data_len );
    extract_tags( p->hdr, p->tags);

    err = sendto(disc_sock, buf, data_len, 0,
		   (struct sockaddr*) &p->addr,
		   sizeof(struct sockaddr_ll));

    if(err < 0)
	poe_error(ses,"sendto returned: %m\n");

    return err;
}
示例#19
0
/* wav input */
static int wav_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count=0;
    int rf64;
    unsigned int tag;
    AVIOContext *pb = s->pb;
    AVStream *st;
    WAVContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;
    int min_samples_est0=0;
	int min_samples_est1=0;
	unsigned char bit_per_sample = 0;
    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return -1;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return -1;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return -1;
        size = avio_rl32(pb);
        if (size < 24)
            return -1;
        avio_rl64(pb); /* RIFF size */
        data_size = avio_rl64(pb);
        sample_count = avio_rl64(pb);
        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 24); /* skip rest of ds64 chunk */
    }

    for (;;) {
        size = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (url_feof(pb))
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st) < 0)) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!pb->seekable || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f','a','c','t'):
            if(!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b','e','x','t'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }
break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);
	bit_per_sample = av_get_bits_per_sample(st->codec->codec_id);
	if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id))
		sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
	if(bit_per_sample&&st->codec->channels&&st->codec->bit_rate){//PCM audio
		min_samples_est0 = (size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
	    min_samples_est1 = (size<<3) / st->codec->bit_rate * st->codec->sample_rate;
		if (sample_count){
	      if(sample_count <= min_samples_est0)//:indecate that sample_count is unvalid
	            st->duration = min_samples_est1;
			else
				st->duration = (min_samples_est1 > sample_count? min_samples_est1:sample_count);
	    }
	}	
	
    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);

    return 0;
}
示例#20
0
/* wav input */
static int wav_read_header(AVFormatContext *s)
{
    int64_t size, av_uninit(data_size);
    int64_t sample_count = 0;
    int rf64;
    uint32_t tag;
    AVIOContext *pb      = s->pb;
    AVStream *st         = NULL;
    WAVDemuxContext *wav = s->priv_data;
    int ret, got_fmt = 0;
    int64_t next_tag_ofs, data_ofs = -1;

    wav->smv_data_ofs = -1;

    /* check RIFF header */
    tag = avio_rl32(pb);

    rf64 = tag == MKTAG('R', 'F', '6', '4');
    if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F'))
        return AVERROR_INVALIDDATA;
    avio_rl32(pb); /* file size */
    tag = avio_rl32(pb);
    if (tag != MKTAG('W', 'A', 'V', 'E'))
        return AVERROR_INVALIDDATA;

    if (rf64) {
        if (avio_rl32(pb) != MKTAG('d', 's', '6', '4'))
            return AVERROR_INVALIDDATA;
        size = avio_rl32(pb);
        if (size < 24)
            return AVERROR_INVALIDDATA;
        avio_rl64(pb); /* RIFF size */

        data_size    = avio_rl64(pb);
        sample_count = avio_rl64(pb);

        if (data_size < 0 || sample_count < 0) {
            av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in "
                   "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n",
                   data_size, sample_count);
            return AVERROR_INVALIDDATA;
        }
        avio_skip(pb, size - 24); /* skip rest of ds64 chunk */

    }

    for (;;) {
        AVStream *vst;
        size         = next_tag(pb, &tag);
        next_tag_ofs = avio_tell(pb) + size;

        if (url_feof(pb))
            break;

        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
            /* only parse the first 'fmt ' tag found */
            if (!got_fmt && (ret = wav_parse_fmt_tag(s, size, &st)) < 0) {
                return ret;
            } else if (got_fmt)
                av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");

            got_fmt = 1;
            break;
        case MKTAG('d', 'a', 't', 'a'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR,
                       "found no 'fmt ' tag before the 'data' tag\n");
                return AVERROR_INVALIDDATA;
            }

            if (rf64) {
                next_tag_ofs = wav->data_end = avio_tell(pb) + data_size;
            } else {
                data_size    = size;
                next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX;
            }

            data_ofs = avio_tell(pb);

            /* don't look for footer metadata if we can't seek or if we don't
             * know where the data tag ends
             */
            if (!pb->seekable || (!rf64 && !size))
                goto break_loop;
            break;
        case MKTAG('f', 'a', 'c', 't'):
            if (!sample_count)
                sample_count = avio_rl32(pb);
            break;
        case MKTAG('b', 'e', 'x', 't'):
            if ((ret = wav_parse_bext_tag(s, size)) < 0)
                return ret;
            break;
        case MKTAG('S','M','V','0'):
            if (!got_fmt) {
                av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'SMV0' tag\n");
                return AVERROR_INVALIDDATA;
            }
            // SMV file, a wav file with video appended.
            if (size != MKTAG('0','2','0','0')) {
                av_log(s, AV_LOG_ERROR, "Unknown SMV version found\n");
                goto break_loop;
            }
            av_log(s, AV_LOG_DEBUG, "Found SMV data\n");
            wav->smv_given_first = 0;
            vst = avformat_new_stream(s, NULL);
            if (!vst)
                return AVERROR(ENOMEM);
            avio_r8(pb);
            vst->id = 1;
            vst->codec->codec_type = AVMEDIA_TYPE_VIDEO;
            vst->codec->codec_id = AV_CODEC_ID_SMVJPEG;
            vst->codec->width  = avio_rl24(pb);
            vst->codec->height = avio_rl24(pb);
            vst->codec->extradata_size = 4;
            vst->codec->extradata = av_malloc(vst->codec->extradata_size +
                                              FF_INPUT_BUFFER_PADDING_SIZE);
            if (!vst->codec->extradata) {
                av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n");
                return AVERROR(ENOMEM);
            }
            size = avio_rl24(pb);
            wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3;
            avio_rl24(pb);
            wav->smv_block_size = avio_rl24(pb);
            avpriv_set_pts_info(vst, 32, 1, avio_rl24(pb));
            vst->duration = avio_rl24(pb);
            avio_rl24(pb);
            avio_rl24(pb);
            wav->smv_frames_per_jpeg = avio_rl24(pb);
            AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg);
            wav->smv_cur_pt = 0;
            goto break_loop;
        case MKTAG('L', 'I', 'S', 'T'):
            if (size < 4) {
                av_log(s, AV_LOG_ERROR, "too short LIST tag\n");
                return AVERROR_INVALIDDATA;
            }
            switch (avio_rl32(pb)) {
            case MKTAG('I', 'N', 'F', 'O'):
                ff_read_riff_info(s, size - 4);
            }
            break;
        }

        /* seek to next tag unless we know that we'll run into EOF */
        if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) ||
            wav_seek_tag(pb, next_tag_ofs, SEEK_SET) < 0) {
            break;
        }
    }

break_loop:
    if (data_ofs < 0) {
        av_log(s, AV_LOG_ERROR, "no 'data' tag found\n");
        return AVERROR_INVALIDDATA;
    }

    avio_seek(pb, data_ofs, SEEK_SET);

    if (!sample_count && st->codec->channels &&
        av_get_bits_per_sample(st->codec->codec_id) && wav->data_end <= avio_size(pb))
        sample_count = (data_size << 3) /
                       (st->codec->channels *
                        (uint64_t)av_get_bits_per_sample(st->codec->codec_id));
    if (sample_count)
        st->duration = sample_count;

    ff_metadata_conv_ctx(s, NULL, wav_metadata_conv);
    ff_metadata_conv_ctx(s, NULL, ff_riff_info_conv);

    return 0;
}