|
|
@ -57,14 +57,19 @@ typedef struct WAVDemuxContext { |
|
|
|
int smv_cur_pt; |
|
|
|
int smv_cur_pt; |
|
|
|
int smv_given_first; |
|
|
|
int smv_given_first; |
|
|
|
int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
|
|
|
|
int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended
|
|
|
|
|
|
|
|
int rifx; // RIFX: integer byte order for parameters is big endian
|
|
|
|
} WAVDemuxContext; |
|
|
|
} WAVDemuxContext; |
|
|
|
|
|
|
|
|
|
|
|
#if CONFIG_WAV_DEMUXER |
|
|
|
#if CONFIG_WAV_DEMUXER |
|
|
|
|
|
|
|
|
|
|
|
static int64_t next_tag(AVIOContext *pb, uint32_t *tag) |
|
|
|
static int64_t next_tag(AVIOContext *pb, uint32_t *tag, int big_endian) |
|
|
|
{ |
|
|
|
{ |
|
|
|
*tag = avio_rl32(pb); |
|
|
|
*tag = avio_rl32(pb); |
|
|
|
|
|
|
|
if (!big_endian) { |
|
|
|
return avio_rl32(pb); |
|
|
|
return avio_rl32(pb); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
return avio_rb32(pb); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* RIFF chunks are always at even offsets relative to where they start. */ |
|
|
|
/* RIFF chunks are always at even offsets relative to where they start. */ |
|
|
@ -84,7 +89,7 @@ static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1) |
|
|
|
for (;;) { |
|
|
|
for (;;) { |
|
|
|
if (avio_feof(pb)) |
|
|
|
if (avio_feof(pb)) |
|
|
|
return AVERROR_EOF; |
|
|
|
return AVERROR_EOF; |
|
|
|
size = next_tag(pb, &tag); |
|
|
|
size = next_tag(pb, &tag, wav->rifx); |
|
|
|
if (tag == tag1) |
|
|
|
if (tag == tag1) |
|
|
|
break; |
|
|
|
break; |
|
|
|
wav_seek_tag(wav, pb, size, SEEK_CUR); |
|
|
|
wav_seek_tag(wav, pb, size, SEEK_CUR); |
|
|
@ -98,7 +103,7 @@ static int wav_probe(AVProbeData *p) |
|
|
|
if (p->buf_size <= 32) |
|
|
|
if (p->buf_size <= 32) |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
if (!memcmp(p->buf + 8, "WAVE", 4)) { |
|
|
|
if (!memcmp(p->buf + 8, "WAVE", 4)) { |
|
|
|
if (!memcmp(p->buf, "RIFF", 4)) |
|
|
|
if (!memcmp(p->buf, "RIFF", 4) || !memcmp(p->buf, "RIFX", 4)) |
|
|
|
/* Since the ACT demuxer has a standard WAV header at the top of
|
|
|
|
/* Since the ACT demuxer has a standard WAV header at the top of
|
|
|
|
* its own, the returned score is decreased to avoid a probe |
|
|
|
* its own, the returned score is decreased to avoid a probe |
|
|
|
* conflict between ACT and WAV. */ |
|
|
|
* conflict between ACT and WAV. */ |
|
|
@ -121,6 +126,7 @@ static void handle_stream_probing(AVStream *st) |
|
|
|
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) |
|
|
|
static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) |
|
|
|
{ |
|
|
|
{ |
|
|
|
AVIOContext *pb = s->pb; |
|
|
|
AVIOContext *pb = s->pb; |
|
|
|
|
|
|
|
WAVDemuxContext *wav = s->priv_data; |
|
|
|
int ret; |
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
|
|
/* parse fmt header */ |
|
|
|
/* parse fmt header */ |
|
|
@ -128,7 +134,7 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) |
|
|
|
if (!*st) |
|
|
|
if (!*st) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
|
|
|
|
|
|
|
ret = ff_get_wav_header(pb, (*st)->codec, size); |
|
|
|
ret = ff_get_wav_header(pb, (*st)->codec, size, wav->rifx); |
|
|
|
if (ret < 0) |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
handle_stream_probing(*st); |
|
|
|
handle_stream_probing(*st); |
|
|
@ -258,7 +264,8 @@ static int wav_read_header(AVFormatContext *s) |
|
|
|
tag = avio_rl32(pb); |
|
|
|
tag = avio_rl32(pb); |
|
|
|
|
|
|
|
|
|
|
|
rf64 = tag == MKTAG('R', 'F', '6', '4'); |
|
|
|
rf64 = tag == MKTAG('R', 'F', '6', '4'); |
|
|
|
if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F')) |
|
|
|
wav->rifx = tag == MKTAG('R', 'I', 'F', 'X'); |
|
|
|
|
|
|
|
if (!rf64 && !wav->rifx && tag != MKTAG('R', 'I', 'F', 'F')) |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
avio_rl32(pb); /* file size */ |
|
|
|
avio_rl32(pb); /* file size */ |
|
|
|
tag = avio_rl32(pb); |
|
|
|
tag = avio_rl32(pb); |
|
|
@ -288,7 +295,7 @@ static int wav_read_header(AVFormatContext *s) |
|
|
|
|
|
|
|
|
|
|
|
for (;;) { |
|
|
|
for (;;) { |
|
|
|
AVStream *vst; |
|
|
|
AVStream *vst; |
|
|
|
size = next_tag(pb, &tag); |
|
|
|
size = next_tag(pb, &tag, wav->rifx); |
|
|
|
next_tag_ofs = avio_tell(pb) + size; |
|
|
|
next_tag_ofs = avio_tell(pb) + size; |
|
|
|
|
|
|
|
|
|
|
|
if (avio_feof(pb)) |
|
|
|
if (avio_feof(pb)) |
|
|
@ -328,7 +335,7 @@ static int wav_read_header(AVFormatContext *s) |
|
|
|
break; |
|
|
|
break; |
|
|
|
case MKTAG('f', 'a', 'c', 't'): |
|
|
|
case MKTAG('f', 'a', 'c', 't'): |
|
|
|
if (!sample_count) |
|
|
|
if (!sample_count) |
|
|
|
sample_count = avio_rl32(pb); |
|
|
|
sample_count = (!wav->rifx ? avio_rl32(pb) : avio_rb32(pb)); |
|
|
|
break; |
|
|
|
break; |
|
|
|
case MKTAG('b', 'e', 'x', 't'): |
|
|
|
case MKTAG('b', 'e', 'x', 't'): |
|
|
|
if ((ret = wav_parse_bext_tag(s, size)) < 0) |
|
|
|
if ((ret = wav_parse_bext_tag(s, size)) < 0) |
|
|
@ -662,7 +669,7 @@ static int w64_read_header(AVFormatContext *s) |
|
|
|
|
|
|
|
|
|
|
|
if (!memcmp(guid, ff_w64_guid_fmt, 16)) { |
|
|
|
if (!memcmp(guid, ff_w64_guid_fmt, 16)) { |
|
|
|
/* subtract chunk header size - normal wav file doesn't count it */ |
|
|
|
/* subtract chunk header size - normal wav file doesn't count it */ |
|
|
|
ret = ff_get_wav_header(pb, st->codec, size - 24); |
|
|
|
ret = ff_get_wav_header(pb, st->codec, size - 24, 0); |
|
|
|
if (ret < 0) |
|
|
|
if (ret < 0) |
|
|
|
return ret; |
|
|
|
return ret; |
|
|
|
avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); |
|
|
|
avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); |
|
|
|