From 2e7973bbe7c8c98acb0bd9cdd828a6f8cba02e98 Mon Sep 17 00:00:00 2001 From: Roman Shaposhnik Date: Wed, 12 Mar 2003 01:35:47 +0000 Subject: [PATCH] correct AUDIO strf parsing patch by (Roman Shaposhnick ) Originally committed as revision 1664 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/asf.c | 6 +++--- libavformat/avi.h | 3 +-- libavformat/avidec.c | 2 +- libavformat/wav.c | 32 +++++++++++++++++++++++++------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/libavformat/asf.c b/libavformat/asf.c index 5edde52ca5..b9cd71e432 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -806,7 +806,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) asf->packet_size = asf->hdr.max_pktsize; asf->nb_packets = asf->hdr.packets_count; } else if (!memcmp(&g, &stream_header, sizeof(GUID))) { - int type, total_size; + int type, total_size, type_specific_size; unsigned int tag1; int64_t pos1, pos2; @@ -832,7 +832,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) } get_guid(pb, &g); total_size = get_le64(pb); - get_le32(pb); + type_specific_size = get_le32(pb); get_le32(pb); st->id = get_le16(pb) & 0x7f; /* stream id */ // mapping of asf ID to AV stream ID; @@ -842,7 +842,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) st->codec.codec_type = type; st->codec.frame_rate = 15 * s->pts_den / s->pts_num; // 15 fps default if (type == CODEC_TYPE_AUDIO) { - get_wav_header(pb, &st->codec, 1); + get_wav_header(pb, &st->codec, type_specific_size); /* We have to init the frame size at some point .... */ pos2 = url_ftell(pb); if (gsize > (pos2 + 8 - pos1 + 24)) { diff --git a/libavformat/avi.h b/libavformat/avi.h index d1b5eb5789..741781d8df 100644 --- a/libavformat/avi.h +++ b/libavformat/avi.h @@ -18,8 +18,7 @@ typedef struct CodecTag { void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc, const CodecTag *tags, int for_asf); int put_wav_header(ByteIOContext *pb, AVCodecContext *enc); int wav_codec_get_id(unsigned int tag, int bps); -void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, - int has_extra_data); +void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, int size); extern const CodecTag codec_bmp_tags[]; extern const CodecTag codec_wav_tags[]; diff --git a/libavformat/avidec.c b/libavformat/avidec.c index ccf8f6e9ba..6d23f07079 100644 --- a/libavformat/avidec.c +++ b/libavformat/avidec.c @@ -187,7 +187,7 @@ static int avi_read_header(AVFormatContext *s, AVFormatParameters *ap) // url_fskip(pb, size - 5 * 4); break; case CODEC_TYPE_AUDIO: - get_wav_header(pb, &st->codec, (size >= 18)); + get_wav_header(pb, &st->codec, size); if (size%2) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ url_fskip(pb, 1); break; diff --git a/libavformat/wav.c b/libavformat/wav.c index 7fe2f8e73b..81301122d5 100644 --- a/libavformat/wav.c +++ b/libavformat/wav.c @@ -103,26 +103,44 @@ int put_wav_header(ByteIOContext *pb, AVCodecContext *enc) return hdrsize; } -void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, - int has_extra_data) +/* We could be given one of the three possible structures here: + * WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure + * is an expansion of the previous one with the fields added + * at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and + * WAVEFORMATEX adds 'WORD cbSize' and basically makes itself + * an openended structure. + */ +void get_wav_header(ByteIOContext *pb, AVCodecContext *codec, int size) { int id; id = get_le16(pb); + codec->codec_id = wav_codec_get_id(id, codec->frame_bits); codec->codec_type = CODEC_TYPE_AUDIO; codec->codec_tag = id; codec->channels = get_le16(pb); codec->sample_rate = get_le32(pb); codec->bit_rate = get_le32(pb) * 8; codec->block_align = get_le16(pb); - codec->bits_per_sample = get_le16(pb); /* bits per sample */ - codec->codec_id = wav_codec_get_id(id, codec->frame_bits); - if (has_extra_data) { + if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ + codec->bits_per_sample = 8; + return; + } + + codec->bits_per_sample = get_le16(pb); + if (size > 16) { /* We're obviously dealing with WAVEFORMATEX */ codec->extradata_size = get_le16(pb); if (codec->extradata_size > 0) { + if (codec->extradata_size > size - 18) + codec->extradata_size = size - 18; codec->extradata = av_mallocz(codec->extradata_size); get_buffer(pb, codec->extradata, codec->extradata_size); - } + } else + codec->extradata_size = 0; + + /* It is possible for the chunk to contain garbage at the end */ + if (size - codec->extradata_size - 18 > 0) + url_fskip(pb, size - codec->extradata_size - 18); } } @@ -259,7 +277,7 @@ static int wav_read_header(AVFormatContext *s, if (!st) return AVERROR_NOMEM; - get_wav_header(pb, &st->codec, (size >= 18)); + get_wav_header(pb, &st->codec, size); size = find_tag(pb, MKTAG('d', 'a', 't', 'a')); if (size < 0)