• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavformat/wc3movie.c

Go to the documentation of this file.
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 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 /* video resolution unless otherwise specified */
00050 #define WC3_DEFAULT_WIDTH 320
00051 #define WC3_DEFAULT_HEIGHT 165
00052 
00053 /* always use the same PCM audio parameters */
00054 #define WC3_SAMPLE_RATE 22050
00055 #define WC3_AUDIO_CHANNELS 1
00056 #define WC3_AUDIO_BITS 16
00057 
00058 /* nice, constant framerate */
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 /* bizarre palette lookup table */
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     /* default context members */
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     /* skip the first 3 32-bit numbers */
00151     url_fseek(pb, 12, SEEK_CUR);
00152 
00153     /* traverse through the chunks and load the header information before
00154      * the first BRCH tag */
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             /* SOND unknown, INDX unnecessary; ignore both */
00167             url_fseek(pb, size, SEEK_CUR);
00168             break;
00169 
00170         case PC__TAG:
00171             /* need the number of palettes */
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             /* load up the name */
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             /* video resolution override */
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             /* one of several palettes */
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             /* transform the current palette in place */
00214             for (i = current_palette * PALETTE_SIZE;
00215                  i < (current_palette + 1) * PALETTE_SIZE; i++) {
00216                 /* rotate each palette component left by 2 and use the result
00217                  * as an index into the color component table */
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         /* chunk sizes are 16-bit aligned */
00238         size = (AV_RB32(&preamble[4]) + 1) & (~1);
00239 
00240     } while (fourcc_tag != BRCH_TAG);
00241 
00242     /* initialize the decoder streams */
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;  /* no fourcc */
00251     st->codec->width = wc3->width;
00252     st->codec->height = wc3->height;
00253 
00254     /* palette considerations */
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         /* get the next chunk preamble */
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         /* chunk sizes are 16-bit aligned */
00300         size = (AV_RB32(&preamble[4]) + 1) & (~1);
00301 
00302         switch (fourcc_tag) {
00303 
00304         case BRCH_TAG:
00305             /* no-op */
00306             break;
00307 
00308         case SHOT_TAG:
00309             /* load up new palette */
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             /* send out video chunk */
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             /* subtitle chunk */
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             /* send out audio chunk */
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             /* time to advance pts */
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 };

Generated on Tue Nov 4 2014 12:59:24 for ffmpeg by  doxygen 1.7.1