mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-11-26 19:01:44 +02:00
wavdec: RIFX file format support
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
e8714f6f93
commit
00d7555f34
@ -5,6 +5,7 @@ version <next>:
|
||||
- nvenc encoder
|
||||
- 10bit spp filter
|
||||
- colorlevels filter
|
||||
- RIFX format for *.wav files
|
||||
|
||||
|
||||
version 2.5:
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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[];
|
||||
|
@ -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 */
|
||||
|
@ -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, \
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user