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