From: Thomas Volkert <tho...@homer-conferencing.com> --- Changelog | 1 + 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 | 36 ++++++++++++++++++++++++-------- libavformat/version.h | 2 +- libavformat/wavdec.c | 53 ++++++++++++++++++++++++++++++++--------------- libavformat/wtvdec.c | 2 +- libavformat/xwma.c | 2 +- 14 files changed, 75 insertions(+), 37 deletions(-)
diff --git a/Changelog b/Changelog index 4c122c4..20341d3 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ releases are sorted from youngest to oldest. version <next>: - nvenc encoder +- RIFX format for *.wav files version 2.5: diff --git a/libavformat/act.c b/libavformat/act.c index 3f223d5..7b6b840 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 7f7bb4d..79a255f 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 a8318ff..a6ef76b 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 6ad1c9f..9da2ffd 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 9c476c1..bdc9c5f 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 17bdb17..06ea7b3 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 939296a..6357b79 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 e925634..15b07a6 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 88e2229..42a9f98 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 { @@ -105,7 +119,11 @@ int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) codec->bits_per_coded_sample); } if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ - int cbSize = avio_rl16(pb); /* cbSize */ + int cbSize = (!big_endian ? avio_rl16(pb) : avio_rb16(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 6664f2b..d39dd5d 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 9c4e2df..3e91417 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); @@ -242,7 +248,7 @@ static int wav_read_header(AVFormatContext *s) { int64_t size, av_uninit(data_size); int64_t sample_count = 0; - int rf64; + int rf64 = 0; uint32_t tag; AVIOContext *pb = s->pb; AVStream *st = NULL; @@ -254,16 +260,29 @@ static int wav_read_header(AVFormatContext *s) 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')) + /* read chunk ID */ + switch (avio_rl32(pb)) { + case MKTAG('R', 'I', 'F', 'F'): + break; + case MKTAG('R', 'I', 'F', 'X'): + wav->rifx = 1; + break; + case MKTAG('R', 'F', '6', '4'): + rf64 = 1; + break; + default: + av_log(s, AV_LOG_ERROR, "invalid start in RIFF header\n"); return AVERROR_INVALIDDATA; - avio_rl32(pb); /* file size */ - tag = avio_rl32(pb); - if (tag != MKTAG('W', 'A', 'V', 'E')) + } + + /* read chunk size */ + avio_rl32(pb); + + /* read format */ + if (avio_rl32(pb) != MKTAG('W', 'A', 'V', 'E')) { + av_log(s, AV_LOG_ERROR, "invalid format in RIFF header\n"); return AVERROR_INVALIDDATA; + } if (rf64) { if (avio_rl32(pb) != MKTAG('d', 's', '6', '4')) @@ -288,7 +307,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 +347,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 +681,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 4009964..7fc5e63 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 5d29d0b..b172120 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; -- 1.9.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel