00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00030 #include "libavutil/intreadwrite.h"
00031 #include "avformat.h"
00032
00033 #define WC3_PREAMBLE_SIZE 8
00034
00035 #define FORM_TAG MKTAG('F', 'O', 'R', 'M')
00036 #define MOVE_TAG MKTAG('M', 'O', 'V', 'E')
00037 #define PC__TAG MKTAG('_', 'P', 'C', '_')
00038 #define SOND_TAG MKTAG('S', 'O', 'N', 'D')
00039 #define BNAM_TAG MKTAG('B', 'N', 'A', 'M')
00040 #define SIZE_TAG MKTAG('S', 'I', 'Z', 'E')
00041 #define PALT_TAG MKTAG('P', 'A', 'L', 'T')
00042 #define INDX_TAG MKTAG('I', 'N', 'D', 'X')
00043 #define BRCH_TAG MKTAG('B', 'R', 'C', 'H')
00044 #define SHOT_TAG MKTAG('S', 'H', 'O', 'T')
00045 #define VGA__TAG MKTAG('V', 'G', 'A', ' ')
00046 #define TEXT_TAG MKTAG('T', 'E', 'X', 'T')
00047 #define AUDI_TAG MKTAG('A', 'U', 'D', 'I')
00048
00049
00050 #define WC3_DEFAULT_WIDTH 320
00051 #define WC3_DEFAULT_HEIGHT 165
00052
00053
00054 #define WC3_SAMPLE_RATE 22050
00055 #define WC3_AUDIO_CHANNELS 1
00056 #define WC3_AUDIO_BITS 16
00057
00058
00059 #define WC3_FRAME_FPS 15
00060
00061 #define PALETTE_SIZE (256 * 3)
00062 #define PALETTE_COUNT 256
00063
00064 typedef struct Wc3DemuxContext {
00065 int width;
00066 int height;
00067 unsigned char *palettes;
00068 int palette_count;
00069 int64_t pts;
00070 int video_stream_index;
00071 int audio_stream_index;
00072
00073 AVPaletteControl palette_control;
00074
00075 } Wc3DemuxContext;
00076
00077
00078 static const unsigned char wc3_pal_lookup[] = {
00079 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E,
00080 0x10, 0x12, 0x13, 0x15, 0x16, 0x18, 0x19, 0x1A,
00081 0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25,
00082 0x27, 0x28, 0x29, 0x2A, 0x2C, 0x2D, 0x2E, 0x2F,
00083 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x38, 0x39,
00084 0x3A, 0x3B, 0x3C, 0x3D, 0x3F, 0x40, 0x41, 0x42,
00085 0x43, 0x44, 0x45, 0x46, 0x48, 0x49, 0x4A, 0x4B,
00086 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
00087 0x54, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C,
00088 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64,
00089 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C,
00090 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74,
00091 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C,
00092 0x7D, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
00093 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B,
00094 0x8C, 0x8D, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92,
00095 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x99,
00096 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1,
00097 0xA2, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8,
00098 0xA9, 0xAA, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
00099 0xB0, 0xB1, 0xB2, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
00100 0xB7, 0xB8, 0xB9, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD,
00101 0xBE, 0xBF, 0xBF, 0xC0, 0xC1, 0xC2, 0xC3, 0xC4,
00102 0xC5, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
00103 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD0, 0xD1,
00104 0xD2, 0xD3, 0xD4, 0xD5, 0xD5, 0xD6, 0xD7, 0xD8,
00105 0xD9, 0xDA, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
00106 0xDF, 0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE4, 0xE5,
00107 0xE6, 0xE7, 0xE8, 0xE9, 0xE9, 0xEA, 0xEB, 0xEC,
00108 0xED, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF1, 0xF2,
00109 0xF3, 0xF4, 0xF5, 0xF6, 0xF6, 0xF7, 0xF8, 0xF9,
00110 0xFA, 0xFA, 0xFB, 0xFC, 0xFD, 0xFD, 0xFD, 0xFD
00111 };
00112
00113
00114 static int wc3_probe(AVProbeData *p)
00115 {
00116 if (p->buf_size < 12)
00117 return 0;
00118
00119 if ((AV_RL32(&p->buf[0]) != FORM_TAG) ||
00120 (AV_RL32(&p->buf[8]) != MOVE_TAG))
00121 return 0;
00122
00123 return AVPROBE_SCORE_MAX;
00124 }
00125
00126 static int wc3_read_header(AVFormatContext *s,
00127 AVFormatParameters *ap)
00128 {
00129 Wc3DemuxContext *wc3 = s->priv_data;
00130 ByteIOContext *pb = s->pb;
00131 unsigned int fourcc_tag;
00132 unsigned int size;
00133 AVStream *st;
00134 unsigned char preamble[WC3_PREAMBLE_SIZE];
00135 char buffer[513];
00136 int ret = 0;
00137 int current_palette = 0;
00138 int bytes_to_read;
00139 int i;
00140 unsigned char rotate;
00141
00142
00143 wc3->width = WC3_DEFAULT_WIDTH;
00144 wc3->height = WC3_DEFAULT_HEIGHT;
00145 wc3->palettes = NULL;
00146 wc3->palette_count = 0;
00147 wc3->pts = 0;
00148 wc3->video_stream_index = wc3->audio_stream_index = 0;
00149
00150
00151 url_fseek(pb, 12, SEEK_CUR);
00152
00153
00154
00155 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
00156 WC3_PREAMBLE_SIZE)
00157 return AVERROR(EIO);
00158 fourcc_tag = AV_RL32(&preamble[0]);
00159 size = (AV_RB32(&preamble[4]) + 1) & (~1);
00160
00161 do {
00162 switch (fourcc_tag) {
00163
00164 case SOND_TAG:
00165 case INDX_TAG:
00166
00167 url_fseek(pb, size, SEEK_CUR);
00168 break;
00169
00170 case PC__TAG:
00171
00172 url_fseek(pb, 8, SEEK_CUR);
00173 if ((ret = get_buffer(pb, preamble, 4)) != 4)
00174 return AVERROR(EIO);
00175 wc3->palette_count = AV_RL32(&preamble[0]);
00176 if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
00177 wc3->palette_count= 0;
00178 return -1;
00179 }
00180 wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
00181 break;
00182
00183 case BNAM_TAG:
00184
00185 if ((unsigned)size < 512)
00186 bytes_to_read = size;
00187 else
00188 bytes_to_read = 512;
00189 if ((ret = get_buffer(pb, buffer, bytes_to_read)) != bytes_to_read)
00190 return AVERROR(EIO);
00191 buffer[bytes_to_read] = 0;
00192 av_metadata_set(&s->metadata, "title", buffer);
00193 break;
00194
00195 case SIZE_TAG:
00196
00197 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
00198 WC3_PREAMBLE_SIZE)
00199 return AVERROR(EIO);
00200 wc3->width = AV_RL32(&preamble[0]);
00201 wc3->height = AV_RL32(&preamble[4]);
00202 break;
00203
00204 case PALT_TAG:
00205
00206 if ((unsigned)current_palette >= wc3->palette_count)
00207 return AVERROR_INVALIDDATA;
00208 if ((ret = get_buffer(pb,
00209 &wc3->palettes[current_palette * PALETTE_SIZE],
00210 PALETTE_SIZE)) != PALETTE_SIZE)
00211 return AVERROR(EIO);
00212
00213
00214 for (i = current_palette * PALETTE_SIZE;
00215 i < (current_palette + 1) * PALETTE_SIZE; i++) {
00216
00217
00218 rotate = ((wc3->palettes[i] << 2) & 0xFF) |
00219 ((wc3->palettes[i] >> 6) & 0xFF);
00220 wc3->palettes[i] = wc3_pal_lookup[rotate];
00221 }
00222 current_palette++;
00223 break;
00224
00225 default:
00226 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
00227 preamble[0], preamble[1], preamble[2], preamble[3],
00228 preamble[0], preamble[1], preamble[2], preamble[3]);
00229 return AVERROR_INVALIDDATA;
00230 break;
00231 }
00232
00233 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
00234 WC3_PREAMBLE_SIZE)
00235 return AVERROR(EIO);
00236 fourcc_tag = AV_RL32(&preamble[0]);
00237
00238 size = (AV_RB32(&preamble[4]) + 1) & (~1);
00239
00240 } while (fourcc_tag != BRCH_TAG);
00241
00242
00243 st = av_new_stream(s, 0);
00244 if (!st)
00245 return AVERROR(ENOMEM);
00246 av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
00247 wc3->video_stream_index = st->index;
00248 st->codec->codec_type = CODEC_TYPE_VIDEO;
00249 st->codec->codec_id = CODEC_ID_XAN_WC3;
00250 st->codec->codec_tag = 0;
00251 st->codec->width = wc3->width;
00252 st->codec->height = wc3->height;
00253
00254
00255 st->codec->palctrl = &wc3->palette_control;
00256
00257 st = av_new_stream(s, 0);
00258 if (!st)
00259 return AVERROR(ENOMEM);
00260 av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
00261 wc3->audio_stream_index = st->index;
00262 st->codec->codec_type = CODEC_TYPE_AUDIO;
00263 st->codec->codec_id = CODEC_ID_PCM_S16LE;
00264 st->codec->codec_tag = 1;
00265 st->codec->channels = WC3_AUDIO_CHANNELS;
00266 st->codec->bits_per_coded_sample = WC3_AUDIO_BITS;
00267 st->codec->sample_rate = WC3_SAMPLE_RATE;
00268 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
00269 st->codec->bits_per_coded_sample;
00270 st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
00271
00272 return 0;
00273 }
00274
00275 static int wc3_read_packet(AVFormatContext *s,
00276 AVPacket *pkt)
00277 {
00278 Wc3DemuxContext *wc3 = s->priv_data;
00279 ByteIOContext *pb = s->pb;
00280 unsigned int fourcc_tag;
00281 unsigned int size;
00282 int packet_read = 0;
00283 int ret = 0;
00284 unsigned char preamble[WC3_PREAMBLE_SIZE];
00285 unsigned char text[1024];
00286 unsigned int palette_number;
00287 int i;
00288 unsigned char r, g, b;
00289 int base_palette_index;
00290
00291 while (!packet_read) {
00292
00293
00294 if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
00295 WC3_PREAMBLE_SIZE)
00296 ret = AVERROR(EIO);
00297
00298 fourcc_tag = AV_RL32(&preamble[0]);
00299
00300 size = (AV_RB32(&preamble[4]) + 1) & (~1);
00301
00302 switch (fourcc_tag) {
00303
00304 case BRCH_TAG:
00305
00306 break;
00307
00308 case SHOT_TAG:
00309
00310 if ((ret = get_buffer(pb, preamble, 4)) != 4)
00311 return AVERROR(EIO);
00312 palette_number = AV_RL32(&preamble[0]);
00313 if (palette_number >= wc3->palette_count)
00314 return AVERROR_INVALIDDATA;
00315 base_palette_index = palette_number * PALETTE_COUNT * 3;
00316 for (i = 0; i < PALETTE_COUNT; i++) {
00317 r = wc3->palettes[base_palette_index + i * 3 + 0];
00318 g = wc3->palettes[base_palette_index + i * 3 + 1];
00319 b = wc3->palettes[base_palette_index + i * 3 + 2];
00320 wc3->palette_control.palette[i] = (r << 16) | (g << 8) | (b);
00321 }
00322 wc3->palette_control.palette_changed = 1;
00323 break;
00324
00325 case VGA__TAG:
00326
00327 ret= av_get_packet(pb, pkt, size);
00328 pkt->stream_index = wc3->video_stream_index;
00329 pkt->pts = wc3->pts;
00330 if (ret != size)
00331 ret = AVERROR(EIO);
00332 packet_read = 1;
00333 break;
00334
00335 case TEXT_TAG:
00336
00337 #if 0
00338 url_fseek(pb, size, SEEK_CUR);
00339 #else
00340 if ((unsigned)size > sizeof(text) || (ret = get_buffer(pb, text, size)) != size)
00341 ret = AVERROR(EIO);
00342 else {
00343 int i = 0;
00344 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n");
00345 av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]);
00346 i += text[i] + 1;
00347 av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]);
00348 i += text[i] + 1;
00349 av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]);
00350 }
00351 #endif
00352 break;
00353
00354 case AUDI_TAG:
00355
00356 ret= av_get_packet(pb, pkt, size);
00357 pkt->stream_index = wc3->audio_stream_index;
00358 pkt->pts = wc3->pts;
00359 if (ret != size)
00360 ret = AVERROR(EIO);
00361
00362
00363 wc3->pts++;
00364
00365 packet_read = 1;
00366 break;
00367
00368 default:
00369 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
00370 preamble[0], preamble[1], preamble[2], preamble[3],
00371 preamble[0], preamble[1], preamble[2], preamble[3]);
00372 ret = AVERROR_INVALIDDATA;
00373 packet_read = 1;
00374 break;
00375 }
00376 }
00377
00378 return ret;
00379 }
00380
00381 static int wc3_read_close(AVFormatContext *s)
00382 {
00383 Wc3DemuxContext *wc3 = s->priv_data;
00384
00385 av_free(wc3->palettes);
00386
00387 return 0;
00388 }
00389
00390 AVInputFormat wc3_demuxer = {
00391 "wc3movie",
00392 NULL_IF_CONFIG_SMALL("Wing Commander III movie format"),
00393 sizeof(Wc3DemuxContext),
00394 wc3_probe,
00395 wc3_read_header,
00396 wc3_read_packet,
00397 wc3_read_close,
00398 };