From 00d7555f3468193a761c0534df6742646b15829c Mon Sep 17 00:00:00 2001 From: Thomas Volkert Date: Wed, 17 Dec 2014 12:04:37 +0100 Subject: wavdec: RIFX file format support Signed-off-by: Michael Niedermayer --- libavformat/act.c | 2 +- libavformat/asfdec.c | 2 +- libavformat/avidec.c | 2 +- libavformat/dxa.c | 2 +- libavformat/matroskadec.c | 2 +- libavformat/mlvdec.c | 2 +- libavformat/mov.c | 2 +- libavformat/riff.h | 2 +- libavformat/riffdec.c | 34 ++++++++++++++++++++++++++-------- libavformat/version.h | 2 +- libavformat/wavdec.c | 25 ++++++++++++++++--------- libavformat/wtvdec.c | 2 +- libavformat/xwma.c | 2 +- 13 files changed, 53 insertions(+), 28 deletions(-) (limited to 'libavformat') diff --git a/libavformat/act.c b/libavformat/act.c index 3f223d57b6..7b6b8406fc 100644 --- a/libavformat/act.c +++ b/libavformat/act.c @@ -75,7 +75,7 @@ static int read_header(AVFormatContext *s) avio_skip(pb, 16); size=avio_rl32(pb); - ff_get_wav_header(pb, st->codec, size); + ff_get_wav_header(pb, st->codec, size, 0); /* 8000Hz (Fine-rec) file format has 10 bytes long diff --git a/libavformat/asfdec.c b/libavformat/asfdec.c index 7f7bb4d5d4..79a255f475 100644 --- a/libavformat/asfdec.c +++ b/libavformat/asfdec.c @@ -423,7 +423,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) st->codec->codec_type = type; if (type == AVMEDIA_TYPE_AUDIO) { - int ret = ff_get_wav_header(pb, st->codec, type_specific_size); + int ret = ff_get_wav_header(pb, st->codec, type_specific_size, 0); if (ret < 0) return ret; if (is_dvr_ms_audio) { diff --git a/libavformat/avidec.c b/libavformat/avidec.c index f5f727889a..03c05a748c 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -794,7 +794,7 @@ static int avi_read_header(AVFormatContext *s) // avio_skip(pb, size - 5 * 4); break; case AVMEDIA_TYPE_AUDIO: - ret = ff_get_wav_header(pb, st->codec, size); + ret = ff_get_wav_header(pb, st->codec, size, 0); if (ret < 0) return ret; ast->dshow_block_align = st->codec->block_align; diff --git a/libavformat/dxa.c b/libavformat/dxa.c index 6ad1c9ffac..9da2ffdc2d 100644 --- a/libavformat/dxa.c +++ b/libavformat/dxa.c @@ -106,7 +106,7 @@ static int dxa_read_header(AVFormatContext *s) ast = avformat_new_stream(s, NULL); if (!ast) return AVERROR(ENOMEM); - ret = ff_get_wav_header(pb, ast->codec, fsize); + ret = ff_get_wav_header(pb, ast->codec, fsize, 0); if (ret < 0) return ret; if (ast->codec->sample_rate > 0) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 9c476c12b2..bdc9c5f384 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -1715,7 +1715,7 @@ static int matroska_parse_tracks(AVFormatContext *s) ffio_init_context(&b, track->codec_priv.data, track->codec_priv.size, 0, NULL, NULL, NULL, NULL); - ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size); + ret = ff_get_wav_header(&b, st->codec, track->codec_priv.size, 0); if (ret < 0) return ret; codec_id = st->codec->codec_id; diff --git a/libavformat/mlvdec.c b/libavformat/mlvdec.c index 17bdb17e72..06ea7b3ea5 100644 --- a/libavformat/mlvdec.c +++ b/libavformat/mlvdec.c @@ -142,7 +142,7 @@ static int scan_file(AVFormatContext *avctx, AVStream *vst, AVStream *ast, int f vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16); size -= 164; } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) { - ret = ff_get_wav_header(pb, ast->codec, 16); + ret = ff_get_wav_header(pb, ast->codec, 16, 0); if (ret < 0) return ret; size -= 16; diff --git a/libavformat/mov.c b/libavformat/mov.c index 0282ac4d0d..2ce6f9c664 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -714,7 +714,7 @@ static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; st = c->fc->streams[c->fc->nb_streams-1]; - if ((ret = ff_get_wav_header(pb, st->codec, atom.size)) < 0) + if ((ret = ff_get_wav_header(pb, st->codec, atom.size, 0)) < 0) av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n"); return ret; diff --git a/libavformat/riff.h b/libavformat/riff.h index e9256344f8..15b07a66e0 100644 --- a/libavformat/riff.h +++ b/libavformat/riff.h @@ -62,7 +62,7 @@ void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, const AVCodecTag *t int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags); enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps); -int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size); +int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size, int big_endian); extern const AVCodecTag ff_codec_bmp_tags[]; // exposed through avformat_get_riff_video_tags() extern const AVCodecTag ff_codec_wav_tags[]; diff --git a/libavformat/riffdec.c b/libavformat/riffdec.c index 88e2229a77..edaf146d1c 100644 --- a/libavformat/riffdec.c +++ b/libavformat/riffdec.c @@ -80,23 +80,37 @@ static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) } } -int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) +/* "big_endian" values are needed for RIFX file format */ +int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size, int big_endian) { int id; if (size < 14) avpriv_request_sample(codec, "wav header size < 14"); - id = avio_rl16(pb); codec->codec_type = AVMEDIA_TYPE_AUDIO; - codec->channels = avio_rl16(pb); - codec->sample_rate = avio_rl32(pb); - codec->bit_rate = avio_rl32(pb) * 8; - codec->block_align = avio_rl16(pb); + if (!big_endian) { + id = avio_rl16(pb); + codec->channels = avio_rl16(pb); + codec->sample_rate = avio_rl32(pb); + codec->bit_rate = avio_rl32(pb) * 8; + codec->block_align = avio_rl16(pb); + } else { + id = avio_rb16(pb); + codec->channels = avio_rb16(pb); + codec->sample_rate = avio_rb32(pb); + codec->bit_rate = avio_rb32(pb) * 8; + codec->block_align = avio_rb16(pb); + } if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ codec->bits_per_coded_sample = 8; - } else - codec->bits_per_coded_sample = avio_rl16(pb); + } else { + if (!big_endian) { + codec->bits_per_coded_sample = avio_rl16(pb); + } else { + codec->bits_per_coded_sample = avio_rb16(pb); + } + } if (id == 0xFFFE) { codec->codec_tag = 0; } else { @@ -106,6 +120,10 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) } if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ int cbSize = avio_rl16(pb); /* cbSize */ + if (big_endian) { + avpriv_report_missing_feature(codec, "WAVEFORMATEX support for RIFX files\n"); + return AVERROR_PATCHWELCOME; + } size -= 18; cbSize = FFMIN(size, cbSize); if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ diff --git a/libavformat/version.h b/libavformat/version.h index 6664f2b1d7..d39dd5d783 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -31,7 +31,7 @@ #define LIBAVFORMAT_VERSION_MAJOR 56 #define LIBAVFORMAT_VERSION_MINOR 15 -#define LIBAVFORMAT_VERSION_MICRO 105 +#define LIBAVFORMAT_VERSION_MICRO 106 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ diff --git a/libavformat/wavdec.c b/libavformat/wavdec.c index 9c4e2dfa14..8a7f84b17c 100644 --- a/libavformat/wavdec.c +++ b/libavformat/wavdec.c @@ -57,14 +57,19 @@ typedef struct WAVDemuxContext { int smv_cur_pt; int smv_given_first; 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; #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); - return avio_rl32(pb); + if (!big_endian) { + return avio_rl32(pb); + } else { + return avio_rb32(pb); + } } /* 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 (;;) { if (avio_feof(pb)) return AVERROR_EOF; - size = next_tag(pb, &tag); + size = next_tag(pb, &tag, wav->rifx); if (tag == tag1) break; wav_seek_tag(wav, pb, size, SEEK_CUR); @@ -98,7 +103,7 @@ static int wav_probe(AVProbeData *p) if (p->buf_size <= 32) return 0; 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 * its own, the returned score is decreased to avoid a probe * 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) { AVIOContext *pb = s->pb; + WAVDemuxContext *wav = s->priv_data; int ret; /* parse fmt header */ @@ -128,7 +134,7 @@ static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream **st) if (!*st) 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) return ret; handle_stream_probing(*st); @@ -258,7 +264,8 @@ static int wav_read_header(AVFormatContext *s) tag = avio_rl32(pb); 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; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); @@ -288,7 +295,7 @@ static int wav_read_header(AVFormatContext *s) for (;;) { AVStream *vst; - size = next_tag(pb, &tag); + size = next_tag(pb, &tag, wav->rifx); next_tag_ofs = avio_tell(pb) + size; if (avio_feof(pb)) @@ -328,7 +335,7 @@ static int wav_read_header(AVFormatContext *s) break; case MKTAG('f', 'a', 'c', 't'): if (!sample_count) - sample_count = avio_rl32(pb); + sample_count = (!wav->rifx ? avio_rl32(pb) : avio_rb32(pb)); break; case MKTAG('b', 'e', 'x', 't'): 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)) { /* 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) return ret; avio_skip(pb, FFALIGN(size, INT64_C(8)) - size); diff --git a/libavformat/wtvdec.c b/libavformat/wtvdec.c index 4009964824..7fc5e6377c 100644 --- a/libavformat/wtvdec.c +++ b/libavformat/wtvdec.c @@ -670,7 +670,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, if (!st) return NULL; if (!ff_guidcmp(formattype, ff_format_waveformatex)) { - int ret = ff_get_wav_header(pb, st->codec, size); + int ret = ff_get_wav_header(pb, st->codec, size, 0); if (ret < 0) return NULL; } else { diff --git a/libavformat/xwma.c b/libavformat/xwma.c index 5d29d0b99e..b1721207e7 100644 --- a/libavformat/xwma.c +++ b/libavformat/xwma.c @@ -75,7 +75,7 @@ static int xwma_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - ret = ff_get_wav_header(pb, st->codec, size); + ret = ff_get_wav_header(pb, st->codec, size, 0); if (ret < 0) return ret; st->need_parsing = AVSTREAM_PARSE_NONE; -- cgit v1.2.3