diff options
author | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-24 11:09:05 -0500 |
---|---|---|
committer | Justin Ruggles <justin.ruggles@gmail.com> | 2012-01-24 14:13:46 -0500 |
commit | d481227c549aece0bc4a05819a771806b6cd7507 (patch) | |
tree | 2c43328cc3c5bc61907ff3c81b7cc3755c7dde68 /libavformat | |
parent | 02e7dbf5adc6aa702472010c33aec9bfd904702f (diff) | |
download | ffmpeg-d481227c549aece0bc4a05819a771806b6cd7507.tar.gz |
aud: support Westwood SND1 audio in AUD files.
Fixes decoding of the handful of "death scream" samples from
"Command and Conquer" that use SND1. e.g.
http://samples.libav.org/game-formats/westwood-aud/nuyell1.aud
http://samples.libav.org/game-formats/westwood-aud/nuyell7.aud
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/westwood_aud.c | 32 |
1 files changed, 26 insertions, 6 deletions
diff --git a/libavformat/westwood_aud.c b/libavformat/westwood_aud.c index b1eb768016..652045f579 100644 --- a/libavformat/westwood_aud.c +++ b/libavformat/westwood_aud.c @@ -79,7 +79,7 @@ static int wsaud_probe(AVProbeData *p) /* note: only check for WS IMA (type 99) right now since there is no * support for type 1 */ - if (p->buf[11] != 99) + if (p->buf[11] != 99 && p->buf[11] != 1) return 0; /* read ahead to the first audio chunk and validate the first header signature */ @@ -103,6 +103,8 @@ static int wsaud_read_header(AVFormatContext *s, wsaud->audio_samplerate = AV_RL16(&header[0]); if (header[11] == 99) wsaud->audio_type = CODEC_ID_ADPCM_IMA_WS; + else if (header[11] == 1) + wsaud->audio_type = CODEC_ID_WESTWOOD_SND1; else return AVERROR_INVALIDDATA; @@ -121,10 +123,10 @@ static int wsaud_read_header(AVFormatContext *s, st->codec->codec_tag = 0; /* no tag */ st->codec->channels = wsaud->audio_channels; st->codec->sample_rate = wsaud->audio_samplerate; - st->codec->bits_per_coded_sample = wsaud->audio_bits; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample / 4; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; + if (st->codec->codec_id == CODEC_ID_ADPCM_IMA_WS) { + st->codec->bits_per_coded_sample = 4; + st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 4; + } wsaud->audio_stream_index = st->index; wsaud->audio_frame_counter = 0; @@ -140,6 +142,7 @@ static int wsaud_read_packet(AVFormatContext *s, unsigned char preamble[AUD_CHUNK_PREAMBLE_SIZE]; unsigned int chunk_size; int ret = 0; + AVStream *st = s->streams[wsaud->audio_stream_index]; if (avio_read(pb, preamble, AUD_CHUNK_PREAMBLE_SIZE) != AUD_CHUNK_PREAMBLE_SIZE) @@ -150,15 +153,32 @@ static int wsaud_read_packet(AVFormatContext *s, return AVERROR_INVALIDDATA; chunk_size = AV_RL16(&preamble[0]); + + if (st->codec->codec_id == CODEC_ID_WESTWOOD_SND1) { + /* For Westwood SND1 audio we need to add the output size and input + size to the start of the packet to match what is in VQA. + Specifically, this is needed to signal when a packet should be + decoding as raw 8-bit pcm or variable-size ADPCM. */ + int out_size = AV_RL16(&preamble[2]); + if ((ret = av_new_packet(pkt, chunk_size + 4))) + return ret; + if ((ret = avio_read(pb, &pkt->data[4], chunk_size)) != chunk_size) + return ret < 0 ? ret : AVERROR(EIO); + AV_WL16(&pkt->data[0], out_size); + AV_WL16(&pkt->data[2], chunk_size); + + pkt->duration = out_size; + } else { ret= av_get_packet(pb, pkt, chunk_size); if (ret != chunk_size) return AVERROR(EIO); - pkt->stream_index = wsaud->audio_stream_index; pkt->pts = wsaud->audio_frame_counter; pkt->pts /= wsaud->audio_samplerate; /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ wsaud->audio_frame_counter += (chunk_size * 2) / wsaud->audio_channels; + } + pkt->stream_index = st->index; return ret; } |