Signed-off-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.6
| @@ -5,6 +5,7 @@ version <next>: | |||||
| - nvenc encoder | - nvenc encoder | ||||
| - 10bit spp filter | - 10bit spp filter | ||||
| - colorlevels filter | - colorlevels filter | ||||
| - RIFX format for *.wav files | |||||
| version 2.5: | version 2.5: | ||||
| @@ -75,7 +75,7 @@ static int read_header(AVFormatContext *s) | |||||
| avio_skip(pb, 16); | avio_skip(pb, 16); | ||||
| size=avio_rl32(pb); | 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 | 8000Hz (Fine-rec) file format has 10 bytes long | ||||
| @@ -423,7 +423,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) | |||||
| st->codec->codec_type = type; | st->codec->codec_type = type; | ||||
| if (type == AVMEDIA_TYPE_AUDIO) { | 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) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| if (is_dvr_ms_audio) { | if (is_dvr_ms_audio) { | ||||
| @@ -794,7 +794,7 @@ static int avi_read_header(AVFormatContext *s) | |||||
| // avio_skip(pb, size - 5 * 4); | // avio_skip(pb, size - 5 * 4); | ||||
| break; | break; | ||||
| case AVMEDIA_TYPE_AUDIO: | 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) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| ast->dshow_block_align = st->codec->block_align; | ast->dshow_block_align = st->codec->block_align; | ||||
| @@ -106,7 +106,7 @@ static int dxa_read_header(AVFormatContext *s) | |||||
| ast = avformat_new_stream(s, NULL); | ast = avformat_new_stream(s, NULL); | ||||
| if (!ast) | if (!ast) | ||||
| return AVERROR(ENOMEM); | 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) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| if (ast->codec->sample_rate > 0) | if (ast->codec->sample_rate > 0) | ||||
| @@ -1715,7 +1715,7 @@ static int matroska_parse_tracks(AVFormatContext *s) | |||||
| ffio_init_context(&b, track->codec_priv.data, | ffio_init_context(&b, track->codec_priv.data, | ||||
| track->codec_priv.size, | track->codec_priv.size, | ||||
| 0, NULL, NULL, NULL, NULL); | 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) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| codec_id = st->codec->codec_id; | codec_id = st->codec->codec_id; | ||||
| @@ -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); | vst->codec->codec_tag = MKTAG('B', 'I', 'T', 16); | ||||
| size -= 164; | size -= 164; | ||||
| } else if (ast && type == MKTAG('W', 'A', 'V', 'I') && size >= 16) { | } 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) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| size -= 16; | size -= 16; | ||||
| @@ -714,7 +714,7 @@ static int mov_read_wfex(MOVContext *c, AVIOContext *pb, MOVAtom atom) | |||||
| return 0; | return 0; | ||||
| st = c->fc->streams[c->fc->nb_streams-1]; | 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"); | av_log(c->fc, AV_LOG_WARNING, "get_wav_header failed\n"); | ||||
| return ret; | return ret; | ||||
| @@ -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); | int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc, int flags); | ||||
| enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps); | 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_bmp_tags[]; // exposed through avformat_get_riff_video_tags() | ||||
| extern const AVCodecTag ff_codec_wav_tags[]; | extern const AVCodecTag ff_codec_wav_tags[]; | ||||
| @@ -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; | int id; | ||||
| if (size < 14) | if (size < 14) | ||||
| avpriv_request_sample(codec, "wav header size < 14"); | avpriv_request_sample(codec, "wav header size < 14"); | ||||
| id = avio_rl16(pb); | |||||
| codec->codec_type = AVMEDIA_TYPE_AUDIO; | 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 */ | if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ | ||||
| codec->bits_per_coded_sample = 8; | 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) { | if (id == 0xFFFE) { | ||||
| codec->codec_tag = 0; | codec->codec_tag = 0; | ||||
| } else { | } 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 */ | if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ | ||||
| int cbSize = avio_rl16(pb); /* cbSize */ | 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; | size -= 18; | ||||
| cbSize = FFMIN(size, cbSize); | cbSize = FFMIN(size, cbSize); | ||||
| if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ | if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ | ||||
| @@ -31,7 +31,7 @@ | |||||
| #define LIBAVFORMAT_VERSION_MAJOR 56 | #define LIBAVFORMAT_VERSION_MAJOR 56 | ||||
| #define LIBAVFORMAT_VERSION_MINOR 15 | #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, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||
| LIBAVFORMAT_VERSION_MINOR, \ | LIBAVFORMAT_VERSION_MINOR, \ | ||||
| @@ -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); | ||||
| 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. */ | /* 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); | ||||
| @@ -670,7 +670,7 @@ static AVStream * parse_media_type(AVFormatContext *s, AVStream *st, int sid, | |||||
| if (!st) | if (!st) | ||||
| return NULL; | return NULL; | ||||
| if (!ff_guidcmp(formattype, ff_format_waveformatex)) { | 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) | if (ret < 0) | ||||
| return NULL; | return NULL; | ||||
| } else { | } else { | ||||
| @@ -75,7 +75,7 @@ static int xwma_read_header(AVFormatContext *s) | |||||
| 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, 0); | |||||
| if (ret < 0) | if (ret < 0) | ||||
| return ret; | return ret; | ||||
| st->need_parsing = AVSTREAM_PARSE_NONE; | st->need_parsing = AVSTREAM_PARSE_NONE; | ||||