Libav
|
00001 /* 00002 * Wing Commander III Movie (.mve) File Demuxer 00003 * Copyright (c) 2003 The ffmpeg Project 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 /* video resolution unless otherwise specified */ 00048 #define WC3_DEFAULT_WIDTH 320 00049 #define WC3_DEFAULT_HEIGHT 165 00050 00051 /* always use the same PCM audio parameters */ 00052 #define WC3_SAMPLE_RATE 22050 00053 #define WC3_AUDIO_CHANNELS 1 00054 #define WC3_AUDIO_BITS 16 00055 00056 /* nice, constant framerate */ 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 /* default context members */ 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 /* skip the first 3 32-bit numbers */ 00158 url_fseek(pb, 12, SEEK_CUR); 00159 00160 /* traverse through the chunks and load the header information before 00161 * the first BRCH tag */ 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 /* SOND unknown, INDX unnecessary; ignore both */ 00171 url_fseek(pb, size, SEEK_CUR); 00172 break; 00173 00174 case PC__TAG: 00175 /* need the number of palettes */ 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 /* load up the name */ 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 /* video resolution override */ 00199 wc3->width = get_le32(pb); 00200 wc3->height = get_le32(pb); 00201 break; 00202 00203 case PALT_TAG: 00204 /* one of several palettes */ 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 /* transform the current palette in place */ 00213 for (i = current_palette * PALETTE_SIZE; 00214 i < (current_palette + 1) * PALETTE_SIZE; i++) { 00215 /* rotate each palette component left by 2 and use the result 00216 * as an index into the color component table */ 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 /* chunk sizes are 16-bit aligned */ 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 /* initialize the decoder streams */ 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; /* no fourcc */ 00249 st->codec->width = wc3->width; 00250 st->codec->height = wc3->height; 00251 00252 /* palette considerations */ 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 /* chunk sizes are 16-bit aligned */ 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 /* no-op */ 00300 break; 00301 00302 case SHOT_TAG: 00303 /* load up new palette */ 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 /* send out video chunk */ 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 /* subtitle chunk */ 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 /* send out audio chunk */ 00346 ret= av_get_packet(pb, pkt, size); 00347 pkt->stream_index = wc3->audio_stream_index; 00348 pkt->pts = wc3->pts; 00349 00350 /* time to advance pts */ 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 };