annotate ffmpeg/libavformat/westwood_vqa.c @ 13:844d341cf643 tip

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