aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2003-10-04 17:41:56 +0000
committerMike Melanson <mike@multimedia.cx>2003-10-04 17:41:56 +0000
commit20f269dc288ddb3654558979787ce1907acceb5a (patch)
tree02f70568868517884a26aefad7aa7ea31c5050be /libavformat
parent77a416e8aab77058b542030870fd7178b62d2a62 (diff)
downloadffmpeg-20f269dc288ddb3654558979787ce1907acceb5a.tar.gz
handle a wider variety of VQA files, including silent files
Originally committed as revision 2343 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/westwood.c83
1 files changed, 60 insertions, 23 deletions
diff --git a/libavformat/westwood.c b/libavformat/westwood.c
index 4254f8a8ba..55dd61bfb9 100644
--- a/libavformat/westwood.c
+++ b/libavformat/westwood.c
@@ -61,6 +61,14 @@
#define SND2_TAG FOURCC_TAG('S', 'N', 'D', '2')
#define VQFR_TAG FOURCC_TAG('V', 'Q', 'F', 'R')
+/* don't know what these tags are for, but acknowledge their existence */
+#define CINF_TAG FOURCC_TAG('C', 'I', 'N', 'F')
+#define CINH_TAG FOURCC_TAG('C', 'I', 'N', 'H')
+#define CIND_TAG FOURCC_TAG('C', 'I', 'N', 'D')
+#define PINF_TAG FOURCC_TAG('P', 'I', 'N', 'F')
+#define PINH_TAG FOURCC_TAG('P', 'I', 'N', 'H')
+#define PIND_TAG FOURCC_TAG('P', 'I', 'N', 'D')
+
#define VQA_HEADER_SIZE 0x2A
#define VQA_FRAMERATE 15
#define VQA_VIDEO_PTS_INC (90000 / VQA_FRAMERATE)
@@ -227,6 +235,8 @@ static int wsvqa_read_header(AVFormatContext *s,
AVStream *st;
unsigned char *header;
unsigned char scratch[VQA_PREAMBLE_SIZE];
+ unsigned int chunk_tag;
+ unsigned int chunk_size;
/* set the pts reference (1 pts = 1/90000) */
s->pts_num = 1;
@@ -256,31 +266,58 @@ static int wsvqa_read_header(AVFormatContext *s,
st->codec.width = LE_16(&header[6]);
st->codec.height = LE_16(&header[8]);
- /* initialize the audio decoder stream */
- st = av_new_stream(s, 0);
- if (!st)
- return AVERROR_NOMEM;
- st->codec.codec_type = CODEC_TYPE_AUDIO;
- st->codec.codec_id = CODEC_ID_ADPCM_IMA_WS;
- st->codec.codec_tag = 0; /* no tag */
- st->codec.sample_rate = LE_16(&header[24]);
- st->codec.channels = header[26];
- st->codec.bits_per_sample = 16;
- st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
- st->codec.bits_per_sample / 4;
- st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
+ /* initialize the audio decoder stream is sample rate is non-zero */
+ if (LE_16(&header[24])) {
+ st = av_new_stream(s, 0);
+ if (!st)
+ return AVERROR_NOMEM;
+ st->codec.codec_type = CODEC_TYPE_AUDIO;
+ st->codec.codec_id = CODEC_ID_ADPCM_IMA_WS;
+ st->codec.codec_tag = 0; /* no tag */
+ st->codec.sample_rate = LE_16(&header[24]);
+ st->codec.channels = header[26];
+ st->codec.bits_per_sample = 16;
+ st->codec.bit_rate = st->codec.channels * st->codec.sample_rate *
+ st->codec.bits_per_sample / 4;
+ st->codec.block_align = st->codec.channels * st->codec.bits_per_sample;
+
+ wsvqa->audio_stream_index = st->index;
+ wsvqa->audio_samplerate = st->codec.sample_rate;
+ wsvqa->audio_channels = st->codec.channels;
+ wsvqa->audio_frame_counter = 0;
+ }
- wsvqa->audio_stream_index = st->index;
- wsvqa->audio_samplerate = st->codec.sample_rate;
- wsvqa->audio_channels = st->codec.channels;
- wsvqa->audio_frame_counter = 0;
+ /* there are 0 or more chunks before the FINF chunk; iterate until
+ * FINF has been skipped and the file will be ready to be demuxed */
+ do {
+ if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
+ av_free(st->codec.extradata);
+ return -EIO;
+ }
+ chunk_tag = BE_32(&scratch[0]);
+ chunk_size = BE_32(&scratch[4]);
+
+ /* catch any unknown header tags, for curiousity */
+ switch (chunk_tag) {
+ case CINF_TAG:
+ case CINH_TAG:
+ case CIND_TAG:
+ case PINF_TAG:
+ case PINH_TAG:
+ case PIND_TAG:
+ case FINF_TAG:
+ break;
+
+ default:
+ printf (" note: unknown chunk seen (%c%c%c%c)\n",
+ scratch[0], scratch[1],
+ scratch[2], scratch[3]);
+ break;
+ }
+
+ url_fseek(pb, chunk_size, SEEK_CUR);
+ } while (chunk_tag != FINF_TAG);
- /* skip the useless FINF chunk index */
- if (get_buffer(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) {
- av_free(st->codec.extradata);
- return -EIO;
- }
- url_fseek(pb, BE_32(&scratch[4]), SEEK_CUR);
wsvqa->video_pts = wsvqa->audio_frame_counter = 0;
return 0;