|
|
|
@ -296,7 +296,7 @@ static int wav_read_header(AVFormatContext *s, |
|
|
|
|
AVStream *st; |
|
|
|
|
WAVContext *wav = s->priv_data; |
|
|
|
|
int ret, got_fmt = 0; |
|
|
|
|
int64_t next_tag_ofs; |
|
|
|
|
int64_t next_tag_ofs, data_ofs = -1; |
|
|
|
|
|
|
|
|
|
/* check RIFF header */ |
|
|
|
|
tag = avio_rl32(pb); |
|
|
|
@ -327,13 +327,13 @@ static int wav_read_header(AVFormatContext *s, |
|
|
|
|
avio_skip(pb, size - 16); /* skip rest of ds64 chunk */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
|
if (pb->eof_reached) |
|
|
|
|
return -1; |
|
|
|
|
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 */ |
|
|
|
@ -350,26 +350,43 @@ static int wav_read_header(AVFormatContext *s, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
goto break_loop; |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
avio_seek(pb, next_tag_ofs, SEEK_SET); |
|
|
|
|
|
|
|
|
|
/* 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 (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 (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)) |
|
|
|
|
sample_count = (size<<3) / (st->codec->channels * (uint64_t)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 (sample_count) |
|
|
|
|
st->duration = sample_count; |
|
|
|
|
return 0; |
|
|
|
|