1/* 2 * Westwood Studios VQA Format Demuxer 3 * Copyright (c) 2003 The ffmpeg Project 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22/** 23 * @file 24 * Westwood Studios VQA file demuxer 25 * by Mike Melanson (melanson@pcisys.net) 26 * for more information on the Westwood file formats, visit: 27 * http://www.pcisys.net/~melanson/codecs/ 28 * http://www.geocities.com/SiliconValley/8682/aud3.txt 29 */ 30 31#include "libavutil/intreadwrite.h" 32#include "avformat.h" 33#include "internal.h" 34 35#define FORM_TAG MKBETAG('F', 'O', 'R', 'M') 36#define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A') 37#define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D') 38#define FINF_TAG MKBETAG('F', 'I', 'N', 'F') 39#define SND0_TAG MKBETAG('S', 'N', 'D', '0') 40#define SND1_TAG MKBETAG('S', 'N', 'D', '1') 41#define SND2_TAG MKBETAG('S', 'N', 'D', '2') 42#define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R') 43 44/* don't know what these tags are for, but acknowledge their existence */ 45#define CINF_TAG MKBETAG('C', 'I', 'N', 'F') 46#define CINH_TAG MKBETAG('C', 'I', 'N', 'H') 47#define CIND_TAG MKBETAG('C', 'I', 'N', 'D') 48#define PINF_TAG MKBETAG('P', 'I', 'N', 'F') 49#define PINH_TAG MKBETAG('P', 'I', 'N', 'H') 50#define PIND_TAG MKBETAG('P', 'I', 'N', 'D') 51#define CMDS_TAG MKBETAG('C', 'M', 'D', 'S') 52 53#define VQA_HEADER_SIZE 0x2A 54#define VQA_PREAMBLE_SIZE 8 55 56typedef struct WsVqaDemuxContext { 57 int version; 58 int bps; 59 int channels; 60 int sample_rate; 61 int audio_stream_index; 62 int video_stream_index; 63} WsVqaDemuxContext; 64 65static int wsvqa_probe(AVProbeData *p) 66{ 67 /* need 12 bytes to qualify */ 68 if (p->buf_size < 12) 69 return 0; 70 71 /* check for the VQA signatures */ 72 if ((AV_RB32(&p->buf[0]) != FORM_TAG) || 73 (AV_RB32(&p->buf[8]) != WVQA_TAG)) 74 return 0; 75 76 return AVPROBE_SCORE_MAX; 77} 78 79static int wsvqa_read_header(AVFormatContext *s) 80{ 81 WsVqaDemuxContext *wsvqa = s->priv_data; 82 AVIOContext *pb = s->pb; 83 AVStream *st; 84 uint8_t *header; 85 uint8_t scratch[VQA_PREAMBLE_SIZE]; 86 uint32_t chunk_tag; 87 uint32_t chunk_size; 88 int fps; 89 90 /* initialize the video decoder stream */ 91 st = avformat_new_stream(s, NULL); 92 if (!st) 93 return AVERROR(ENOMEM); 94 st->start_time = 0; 95 wsvqa->video_stream_index = st->index; 96 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 97 st->codec->codec_id = AV_CODEC_ID_WS_VQA; 98 st->codec->codec_tag = 0; /* no fourcc */ 99 100 /* skip to the start of the VQA header */ 101 avio_seek(pb, 20, SEEK_SET); 102 103 /* the VQA header needs to go to the decoder */ 104 if (ff_get_extradata(st->codec, pb, VQA_HEADER_SIZE) < 0) 105 return AVERROR(ENOMEM); 106 header = (uint8_t *)st->codec->extradata; 107 st->codec->width = AV_RL16(&header[6]); 108 st->codec->height = AV_RL16(&header[8]); 109 fps = header[12]; 110 st->nb_frames = 111 st->duration = AV_RL16(&header[4]); 112 if (fps < 1 || fps > 30) { 113 av_log(s, AV_LOG_ERROR, "invalid fps: %d\n", fps); 114 return AVERROR_INVALIDDATA; 115 } 116 avpriv_set_pts_info(st, 64, 1, fps); 117 118 wsvqa->version = AV_RL16(&header[ 0]); 119 wsvqa->sample_rate = AV_RL16(&header[24]); 120 wsvqa->channels = header[26]; 121 wsvqa->bps = header[27]; 122 wsvqa->audio_stream_index = -1; 123 124 s->ctx_flags |= AVFMTCTX_NOHEADER; 125 126 /* there are 0 or more chunks before the FINF chunk; iterate until 127 * FINF has been skipped and the file will be ready to be demuxed */ 128 do { 129 if (avio_read(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE) 130 return AVERROR(EIO); 131 chunk_tag = AV_RB32(&scratch[0]); 132 chunk_size = AV_RB32(&scratch[4]); 133 134 /* catch any unknown header tags, for curiousity */ 135 switch (chunk_tag) { 136 case CINF_TAG: 137 case CINH_TAG: 138 case CIND_TAG: 139 case PINF_TAG: 140 case PINH_TAG: 141 case PIND_TAG: 142 case FINF_TAG: 143 case CMDS_TAG: 144 break; 145 146 default: 147 av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n", 148 scratch[0], scratch[1], 149 scratch[2], scratch[3]); 150 break; 151 } 152 153 avio_skip(pb, chunk_size); 154 } while (chunk_tag != FINF_TAG); 155 156 return 0; 157} 158 159static int wsvqa_read_packet(AVFormatContext *s, 160 AVPacket *pkt) 161{ 162 WsVqaDemuxContext *wsvqa = s->priv_data; 163 AVIOContext *pb = s->pb; 164 int ret = -1; 165 uint8_t preamble[VQA_PREAMBLE_SIZE]; 166 uint32_t chunk_type; 167 uint32_t chunk_size; 168 int skip_byte; 169 170 while (avio_read(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) { 171 chunk_type = AV_RB32(&preamble[0]); 172 chunk_size = AV_RB32(&preamble[4]); 173 174 skip_byte = chunk_size & 0x01; 175 176 if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) || 177 (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) { 178 179 ret= av_get_packet(pb, pkt, chunk_size); 180 if (ret<0) 181 return AVERROR(EIO); 182 183 switch (chunk_type) { 184 case SND0_TAG: 185 case SND1_TAG: 186 case SND2_TAG: 187 if (wsvqa->audio_stream_index == -1) { 188 AVStream *st = avformat_new_stream(s, NULL); 189 if (!st) 190 return AVERROR(ENOMEM); 191 192 wsvqa->audio_stream_index = st->index; 193 if (!wsvqa->sample_rate) 194 wsvqa->sample_rate = 22050; 195 if (!wsvqa->channels) 196 wsvqa->channels = 1; 197 if (!wsvqa->bps) 198 wsvqa->bps = 8; 199 st->codec->sample_rate = wsvqa->sample_rate; 200 st->codec->bits_per_coded_sample = wsvqa->bps; 201 st->codec->channels = wsvqa->channels; 202 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 203 204 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); 205 206 switch (chunk_type) { 207 case SND0_TAG: 208 if (wsvqa->bps == 16) 209 st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; 210 else 211 st->codec->codec_id = AV_CODEC_ID_PCM_U8; 212 break; 213 case SND1_TAG: 214 st->codec->codec_id = AV_CODEC_ID_WESTWOOD_SND1; 215 break; 216 case SND2_TAG: 217 st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_WS; 218 if (ff_alloc_extradata(st->codec, 2)) 219 return AVERROR(ENOMEM); 220 AV_WL16(st->codec->extradata, wsvqa->version); 221 break; 222 } 223 } 224 225 pkt->stream_index = wsvqa->audio_stream_index; 226 switch (chunk_type) { 227 case SND1_TAG: 228 /* unpacked size is stored in header */ 229 if(pkt->data) 230 pkt->duration = AV_RL16(pkt->data) / wsvqa->channels; 231 break; 232 case SND2_TAG: 233 /* 2 samples/byte, 1 or 2 samples per frame depending on stereo */ 234 pkt->duration = (chunk_size * 2) / wsvqa->channels; 235 break; 236 } 237 break; 238 case VQFR_TAG: 239 pkt->stream_index = wsvqa->video_stream_index; 240 pkt->duration = 1; 241 break; 242 } 243 244 /* stay on 16-bit alignment */ 245 if (skip_byte) 246 avio_skip(pb, 1); 247 248 return ret; 249 } else { 250 switch(chunk_type){ 251 case CMDS_TAG: 252 break; 253 default: 254 av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type); 255 } 256 avio_skip(pb, chunk_size + skip_byte); 257 } 258 } 259 260 return ret; 261} 262 263AVInputFormat ff_wsvqa_demuxer = { 264 .name = "wsvqa", 265 .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA"), 266 .priv_data_size = sizeof(WsVqaDemuxContext), 267 .read_probe = wsvqa_probe, 268 .read_header = wsvqa_read_header, 269 .read_packet = wsvqa_read_packet, 270}; 271