00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00031 #include "libavutil/intreadwrite.h"
00032 #include "avformat.h"
00033 #include "internal.h"
00034
00035 #define FORM_TAG MKBETAG('F', 'O', 'R', 'M')
00036 #define WVQA_TAG MKBETAG('W', 'V', 'Q', 'A')
00037 #define VQHD_TAG MKBETAG('V', 'Q', 'H', 'D')
00038 #define FINF_TAG MKBETAG('F', 'I', 'N', 'F')
00039 #define SND0_TAG MKBETAG('S', 'N', 'D', '0')
00040 #define SND1_TAG MKBETAG('S', 'N', 'D', '1')
00041 #define SND2_TAG MKBETAG('S', 'N', 'D', '2')
00042 #define VQFR_TAG MKBETAG('V', 'Q', 'F', 'R')
00043
00044
00045 #define CINF_TAG MKBETAG('C', 'I', 'N', 'F')
00046 #define CINH_TAG MKBETAG('C', 'I', 'N', 'H')
00047 #define CIND_TAG MKBETAG('C', 'I', 'N', 'D')
00048 #define PINF_TAG MKBETAG('P', 'I', 'N', 'F')
00049 #define PINH_TAG MKBETAG('P', 'I', 'N', 'H')
00050 #define PIND_TAG MKBETAG('P', 'I', 'N', 'D')
00051 #define CMDS_TAG MKBETAG('C', 'M', 'D', 'S')
00052
00053 #define VQA_HEADER_SIZE 0x2A
00054 #define VQA_PREAMBLE_SIZE 8
00055
00056 typedef struct WsVqaDemuxContext {
00057 int version;
00058 int bps;
00059 int channels;
00060 int sample_rate;
00061 int audio_stream_index;
00062 int video_stream_index;
00063 } WsVqaDemuxContext;
00064
00065 static int wsvqa_probe(AVProbeData *p)
00066 {
00067
00068 if (p->buf_size < 12)
00069 return 0;
00070
00071
00072 if ((AV_RB32(&p->buf[0]) != FORM_TAG) ||
00073 (AV_RB32(&p->buf[8]) != WVQA_TAG))
00074 return 0;
00075
00076 return AVPROBE_SCORE_MAX;
00077 }
00078
00079 static int wsvqa_read_header(AVFormatContext *s)
00080 {
00081 WsVqaDemuxContext *wsvqa = s->priv_data;
00082 AVIOContext *pb = s->pb;
00083 AVStream *st;
00084 unsigned char *header;
00085 unsigned char scratch[VQA_PREAMBLE_SIZE];
00086 unsigned int chunk_tag;
00087 unsigned int chunk_size;
00088 int fps;
00089
00090
00091 st = avformat_new_stream(s, NULL);
00092 if (!st)
00093 return AVERROR(ENOMEM);
00094 st->start_time = 0;
00095 wsvqa->video_stream_index = st->index;
00096 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00097 st->codec->codec_id = CODEC_ID_WS_VQA;
00098 st->codec->codec_tag = 0;
00099
00100
00101 avio_seek(pb, 20, SEEK_SET);
00102
00103
00104 st->codec->extradata_size = VQA_HEADER_SIZE;
00105 st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
00106 header = (unsigned char *)st->codec->extradata;
00107 if (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) !=
00108 VQA_HEADER_SIZE) {
00109 av_free(st->codec->extradata);
00110 return AVERROR(EIO);
00111 }
00112 st->codec->width = AV_RL16(&header[6]);
00113 st->codec->height = AV_RL16(&header[8]);
00114 fps = header[12];
00115 st->nb_frames =
00116 st->duration = AV_RL16(&header[4]);
00117 if (fps < 1 || fps > 30) {
00118 av_log(s, AV_LOG_ERROR, "invalid fps: %d\n", fps);
00119 return AVERROR_INVALIDDATA;
00120 }
00121 avpriv_set_pts_info(st, 64, 1, fps);
00122
00123 wsvqa->version = AV_RL16(&header[ 0]);
00124 wsvqa->sample_rate = AV_RL16(&header[24]);
00125 wsvqa->channels = header[26];
00126 wsvqa->bps = header[27];
00127 wsvqa->audio_stream_index = -1;
00128
00129 s->ctx_flags |= AVFMTCTX_NOHEADER;
00130
00131
00132
00133 do {
00134 if (avio_read(pb, scratch, VQA_PREAMBLE_SIZE) != VQA_PREAMBLE_SIZE)
00135 return AVERROR(EIO);
00136 chunk_tag = AV_RB32(&scratch[0]);
00137 chunk_size = AV_RB32(&scratch[4]);
00138
00139
00140 switch (chunk_tag) {
00141 case CINF_TAG:
00142 case CINH_TAG:
00143 case CIND_TAG:
00144 case PINF_TAG:
00145 case PINH_TAG:
00146 case PIND_TAG:
00147 case FINF_TAG:
00148 case CMDS_TAG:
00149 break;
00150
00151 default:
00152 av_log (s, AV_LOG_ERROR, " note: unknown chunk seen (%c%c%c%c)\n",
00153 scratch[0], scratch[1],
00154 scratch[2], scratch[3]);
00155 break;
00156 }
00157
00158 avio_skip(pb, chunk_size);
00159 } while (chunk_tag != FINF_TAG);
00160
00161 return 0;
00162 }
00163
00164 static int wsvqa_read_packet(AVFormatContext *s,
00165 AVPacket *pkt)
00166 {
00167 WsVqaDemuxContext *wsvqa = s->priv_data;
00168 AVIOContext *pb = s->pb;
00169 int ret = -1;
00170 unsigned char preamble[VQA_PREAMBLE_SIZE];
00171 unsigned int chunk_type;
00172 unsigned int chunk_size;
00173 int skip_byte;
00174
00175 while (avio_read(pb, preamble, VQA_PREAMBLE_SIZE) == VQA_PREAMBLE_SIZE) {
00176 chunk_type = AV_RB32(&preamble[0]);
00177 chunk_size = AV_RB32(&preamble[4]);
00178
00179 skip_byte = chunk_size & 0x01;
00180
00181 if ((chunk_type == SND0_TAG) || (chunk_type == SND1_TAG) ||
00182 (chunk_type == SND2_TAG) || (chunk_type == VQFR_TAG)) {
00183
00184 ret= av_get_packet(pb, pkt, chunk_size);
00185 if (ret<0)
00186 return AVERROR(EIO);
00187
00188 switch (chunk_type) {
00189 case SND0_TAG:
00190 case SND1_TAG:
00191 case SND2_TAG:
00192 if (wsvqa->audio_stream_index == -1) {
00193 AVStream *st = avformat_new_stream(s, NULL);
00194 if (!st)
00195 return AVERROR(ENOMEM);
00196
00197 wsvqa->audio_stream_index = st->index;
00198 if (!wsvqa->sample_rate)
00199 wsvqa->sample_rate = 22050;
00200 if (!wsvqa->channels)
00201 wsvqa->channels = 1;
00202 if (!wsvqa->bps)
00203 wsvqa->bps = 8;
00204 st->codec->sample_rate = wsvqa->sample_rate;
00205 st->codec->bits_per_coded_sample = wsvqa->bps;
00206 st->codec->channels = wsvqa->channels;
00207 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00208
00209 avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate);
00210
00211 switch (chunk_type) {
00212 case SND0_TAG:
00213 if (wsvqa->bps == 16)
00214 st->codec->codec_id = CODEC_ID_PCM_S16LE;
00215 else
00216 st->codec->codec_id = CODEC_ID_PCM_U8;
00217 break;
00218 case SND1_TAG:
00219 st->codec->codec_id = CODEC_ID_WESTWOOD_SND1;
00220 break;
00221 case SND2_TAG:
00222 st->codec->codec_id = CODEC_ID_ADPCM_IMA_WS;
00223 st->codec->extradata_size = 2;
00224 st->codec->extradata = av_mallocz(2 + FF_INPUT_BUFFER_PADDING_SIZE);
00225 if (!st->codec->extradata)
00226 return AVERROR(ENOMEM);
00227 AV_WL16(st->codec->extradata, wsvqa->version);
00228 break;
00229 }
00230 }
00231
00232 pkt->stream_index = wsvqa->audio_stream_index;
00233 switch (chunk_type) {
00234 case SND1_TAG:
00235
00236 pkt->duration = AV_RL16(pkt->data) / wsvqa->channels;
00237 break;
00238 case SND2_TAG:
00239
00240 pkt->duration = (chunk_size * 2) / wsvqa->channels;
00241 break;
00242 }
00243 break;
00244 case VQFR_TAG:
00245 pkt->stream_index = wsvqa->video_stream_index;
00246 pkt->duration = 1;
00247 break;
00248 }
00249
00250
00251 if (skip_byte)
00252 avio_skip(pb, 1);
00253
00254 return ret;
00255 } else {
00256 switch(chunk_type){
00257 case CMDS_TAG:
00258 break;
00259 default:
00260 av_log(s, AV_LOG_INFO, "Skipping unknown chunk 0x%08X\n", chunk_type);
00261 }
00262 avio_skip(pb, chunk_size + skip_byte);
00263 }
00264 }
00265
00266 return ret;
00267 }
00268
00269 AVInputFormat ff_wsvqa_demuxer = {
00270 .name = "wsvqa",
00271 .long_name = NULL_IF_CONFIG_SMALL("Westwood Studios VQA format"),
00272 .priv_data_size = sizeof(WsVqaDemuxContext),
00273 .read_probe = wsvqa_probe,
00274 .read_header = wsvqa_read_header,
00275 .read_packet = wsvqa_read_packet,
00276 };