summaryrefslogtreecommitdiff
path: root/libavformat/westwood_aud.c
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2012-01-24 11:09:05 -0500
committerJustin Ruggles <justin.ruggles@gmail.com>2012-01-24 14:13:46 -0500
commitd481227c549aece0bc4a05819a771806b6cd7507 (patch)
tree2c43328cc3c5bc61907ff3c81b7cc3755c7dde68 /libavformat/westwood_aud.c
parent02e7dbf5adc6aa702472010c33aec9bfd904702f (diff)
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/westwood_aud.c')
-rw-r--r--libavformat/westwood_aud.c32
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;
}