mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-21 10:55:51 +02:00
avformat/wavdec: parse XMA2 tag
Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
parent
3df9ec5ce7
commit
a0f75c46d3
@ -146,6 +146,49 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wav_parse_xma2_tag(AVFormatContext *s, int64_t size, AVStream **st)
|
||||
{
|
||||
AVIOContext *pb = s->pb;
|
||||
int num_streams, i, channels = 0;
|
||||
|
||||
if (size < 44)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
*st = avformat_new_stream(s, NULL);
|
||||
if (!*st)
|
||||
return AVERROR(ENOMEM);
|
||||
|
||||
(*st)->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||
(*st)->codec->codec_id = AV_CODEC_ID_XMA2;
|
||||
(*st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;
|
||||
|
||||
avio_skip(pb, 1);
|
||||
num_streams = avio_r8(pb);
|
||||
if (size < 40 + num_streams * 4)
|
||||
return AVERROR_INVALIDDATA;
|
||||
avio_skip(pb, 10);
|
||||
(*st)->codec->sample_rate = avio_rb32(pb);
|
||||
avio_skip(pb, 12);
|
||||
(*st)->duration = avio_rb32(pb);
|
||||
avio_skip(pb, 8);
|
||||
|
||||
for (i = 0; i < num_streams; i++) {
|
||||
channels += avio_r8(pb);
|
||||
avio_skip(pb, 3);
|
||||
}
|
||||
(*st)->codec->channels = channels;
|
||||
|
||||
if ((*st)->codec->channels <= 0 || (*st)->codec->sample_rate <= 0)
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
||||
avpriv_set_pts_info(*st, 64, 1, (*st)->codec->sample_rate);
|
||||
if (ff_alloc_extradata((*st)->codec, 34))
|
||||
return AVERROR(ENOMEM);
|
||||
memset((*st)->codec->extradata, 0, 34);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wav_parse_bext_string(AVFormatContext *s, const char *key,
|
||||
int length)
|
||||
{
|
||||
@ -254,7 +297,7 @@ static int wav_read_header(AVFormatContext *s)
|
||||
AVIOContext *pb = s->pb;
|
||||
AVStream *st = NULL;
|
||||
WAVDemuxContext *wav = s->priv_data;
|
||||
int ret, got_fmt = 0;
|
||||
int ret, got_fmt = 0, got_xma2 = 0;
|
||||
int64_t next_tag_ofs, data_ofs = -1;
|
||||
|
||||
wav->unaligned = avio_tell(s->pb) & 1;
|
||||
@ -319,15 +362,24 @@ static int wav_read_header(AVFormatContext *s)
|
||||
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) {
|
||||
if (!got_xma2 && !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('X', 'M', 'A', '2'):
|
||||
/* only parse the first 'XMA2' tag found */
|
||||
if (!got_fmt && !got_xma2 && (ret = wav_parse_xma2_tag(s, size, &st)) < 0) {
|
||||
return ret;
|
||||
} else if (got_xma2)
|
||||
av_log(s, AV_LOG_WARNING, "found more than one 'XMA2' tag\n");
|
||||
|
||||
got_xma2 = 1;
|
||||
break;
|
||||
case MKTAG('d', 'a', 't', 'a'):
|
||||
if (!got_fmt) {
|
||||
if (!got_fmt && !got_xma2) {
|
||||
av_log(s, AV_LOG_ERROR,
|
||||
"found no 'fmt ' tag before the 'data' tag\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
|
Loading…
Reference in New Issue
Block a user