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; | ||||