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