Libav 0.7.1
|
00001 /* 00002 * Wing Commander III Movie (.mve) File Demuxer 00003 * Copyright (c) 2003 The ffmpeg Project 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 "libavutil/dict.h" 00032 #include "avformat.h" 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 /* video resolution unless otherwise specified */ 00049 #define WC3_DEFAULT_WIDTH 320 00050 #define WC3_DEFAULT_HEIGHT 165 00051 00052 /* always use the same PCM audio parameters */ 00053 #define WC3_SAMPLE_RATE 22050 00054 #define WC3_AUDIO_CHANNELS 1 00055 #define WC3_AUDIO_BITS 16 00056 00057 /* nice, constant framerate */ 00058 #define WC3_FRAME_FPS 15 00059 00060 #define PALETTE_SIZE (256 * 3) 00061 00062 typedef struct Wc3DemuxContext { 00063 int width; 00064 int height; 00065 int64_t pts; 00066 int video_stream_index; 00067 int audio_stream_index; 00068 00069 AVPacket vpkt; 00070 00071 } Wc3DemuxContext; 00072 00073 static int wc3_probe(AVProbeData *p) 00074 { 00075 if (p->buf_size < 12) 00076 return 0; 00077 00078 if ((AV_RL32(&p->buf[0]) != FORM_TAG) || 00079 (AV_RL32(&p->buf[8]) != MOVE_TAG)) 00080 return 0; 00081 00082 return AVPROBE_SCORE_MAX; 00083 } 00084 00085 static int wc3_read_header(AVFormatContext *s, 00086 AVFormatParameters *ap) 00087 { 00088 Wc3DemuxContext *wc3 = s->priv_data; 00089 AVIOContext *pb = s->pb; 00090 unsigned int fourcc_tag; 00091 unsigned int size; 00092 AVStream *st; 00093 int ret = 0; 00094 char *buffer; 00095 00096 /* default context members */ 00097 wc3->width = WC3_DEFAULT_WIDTH; 00098 wc3->height = WC3_DEFAULT_HEIGHT; 00099 wc3->pts = 0; 00100 wc3->video_stream_index = wc3->audio_stream_index = 0; 00101 av_init_packet(&wc3->vpkt); 00102 wc3->vpkt.data = NULL; wc3->vpkt.size = 0; 00103 00104 /* skip the first 3 32-bit numbers */ 00105 avio_skip(pb, 12); 00106 00107 /* traverse through the chunks and load the header information before 00108 * the first BRCH tag */ 00109 fourcc_tag = avio_rl32(pb); 00110 size = (avio_rb32(pb) + 1) & (~1); 00111 00112 do { 00113 switch (fourcc_tag) { 00114 00115 case SOND_TAG: 00116 case INDX_TAG: 00117 /* SOND unknown, INDX unnecessary; ignore both */ 00118 avio_skip(pb, size); 00119 break; 00120 00121 case PC__TAG: 00122 /* number of palettes, unneeded */ 00123 avio_skip(pb, 12); 00124 break; 00125 00126 case BNAM_TAG: 00127 /* load up the name */ 00128 buffer = av_malloc(size+1); 00129 if (!buffer) 00130 return AVERROR(ENOMEM); 00131 if ((ret = avio_read(pb, buffer, size)) != size) 00132 return AVERROR(EIO); 00133 buffer[size] = 0; 00134 av_dict_set(&s->metadata, "title", buffer, 00135 AV_DICT_DONT_STRDUP_VAL); 00136 break; 00137 00138 case SIZE_TAG: 00139 /* video resolution override */ 00140 wc3->width = avio_rl32(pb); 00141 wc3->height = avio_rl32(pb); 00142 break; 00143 00144 case PALT_TAG: 00145 /* one of several palettes */ 00146 avio_seek(pb, -8, SEEK_CUR); 00147 av_append_packet(pb, &wc3->vpkt, 8 + PALETTE_SIZE); 00148 break; 00149 00150 default: 00151 av_log(s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n", 00152 (uint8_t)fourcc_tag, (uint8_t)(fourcc_tag >> 8), (uint8_t)(fourcc_tag >> 16), (uint8_t)(fourcc_tag >> 24), 00153 (uint8_t)fourcc_tag, (uint8_t)(fourcc_tag >> 8), (uint8_t)(fourcc_tag >> 16), (uint8_t)(fourcc_tag >> 24)); 00154 return AVERROR_INVALIDDATA; 00155 break; 00156 } 00157 00158 fourcc_tag = avio_rl32(pb); 00159 /* chunk sizes are 16-bit aligned */ 00160 size = (avio_rb32(pb) + 1) & (~1); 00161 if (pb->eof_reached) 00162 return AVERROR(EIO); 00163 00164 } while (fourcc_tag != BRCH_TAG); 00165 00166 /* initialize the decoder streams */ 00167 st = av_new_stream(s, 0); 00168 if (!st) 00169 return AVERROR(ENOMEM); 00170 av_set_pts_info(st, 33, 1, WC3_FRAME_FPS); 00171 wc3->video_stream_index = st->index; 00172 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; 00173 st->codec->codec_id = CODEC_ID_XAN_WC3; 00174 st->codec->codec_tag = 0; /* no fourcc */ 00175 st->codec->width = wc3->width; 00176 st->codec->height = wc3->height; 00177 00178 st = av_new_stream(s, 0); 00179 if (!st) 00180 return AVERROR(ENOMEM); 00181 av_set_pts_info(st, 33, 1, WC3_FRAME_FPS); 00182 wc3->audio_stream_index = st->index; 00183 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 00184 st->codec->codec_id = CODEC_ID_PCM_S16LE; 00185 st->codec->codec_tag = 1; 00186 st->codec->channels = WC3_AUDIO_CHANNELS; 00187 st->codec->bits_per_coded_sample = WC3_AUDIO_BITS; 00188 st->codec->sample_rate = WC3_SAMPLE_RATE; 00189 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * 00190 st->codec->bits_per_coded_sample; 00191 st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS; 00192 00193 return 0; 00194 } 00195 00196 static int wc3_read_packet(AVFormatContext *s, 00197 AVPacket *pkt) 00198 { 00199 Wc3DemuxContext *wc3 = s->priv_data; 00200 AVIOContext *pb = s->pb; 00201 unsigned int fourcc_tag; 00202 unsigned int size; 00203 int packet_read = 0; 00204 int ret = 0; 00205 unsigned char text[1024]; 00206 00207 while (!packet_read) { 00208 00209 fourcc_tag = avio_rl32(pb); 00210 /* chunk sizes are 16-bit aligned */ 00211 size = (avio_rb32(pb) + 1) & (~1); 00212 if (pb->eof_reached) 00213 return AVERROR(EIO); 00214 00215 switch (fourcc_tag) { 00216 00217 case BRCH_TAG: 00218 /* no-op */ 00219 break; 00220 00221 case SHOT_TAG: 00222 /* load up new palette */ 00223 avio_seek(pb, -8, SEEK_CUR); 00224 av_append_packet(pb, &wc3->vpkt, 8 + 4); 00225 break; 00226 00227 case VGA__TAG: 00228 /* send out video chunk */ 00229 avio_seek(pb, -8, SEEK_CUR); 00230 ret= av_append_packet(pb, &wc3->vpkt, 8 + size); 00231 // ignore error if we have some data 00232 if (wc3->vpkt.size > 0) 00233 ret = 0; 00234 *pkt = wc3->vpkt; 00235 wc3->vpkt.data = NULL; wc3->vpkt.size = 0; 00236 pkt->stream_index = wc3->video_stream_index; 00237 pkt->pts = wc3->pts; 00238 packet_read = 1; 00239 break; 00240 00241 case TEXT_TAG: 00242 /* subtitle chunk */ 00243 #if 0 00244 avio_skip(pb, size); 00245 #else 00246 if ((unsigned)size > sizeof(text) || (ret = avio_read(pb, text, size)) != size) 00247 ret = AVERROR(EIO); 00248 else { 00249 int i = 0; 00250 av_log (s, AV_LOG_DEBUG, "Subtitle time!\n"); 00251 av_log (s, AV_LOG_DEBUG, " inglish: %s\n", &text[i + 1]); 00252 i += text[i] + 1; 00253 av_log (s, AV_LOG_DEBUG, " doytsch: %s\n", &text[i + 1]); 00254 i += text[i] + 1; 00255 av_log (s, AV_LOG_DEBUG, " fronsay: %s\n", &text[i + 1]); 00256 } 00257 #endif 00258 break; 00259 00260 case AUDI_TAG: 00261 /* send out audio chunk */ 00262 ret= av_get_packet(pb, pkt, size); 00263 pkt->stream_index = wc3->audio_stream_index; 00264 pkt->pts = wc3->pts; 00265 00266 /* time to advance pts */ 00267 wc3->pts++; 00268 00269 packet_read = 1; 00270 break; 00271 00272 default: 00273 av_log (s, AV_LOG_ERROR, " unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n", 00274 (uint8_t)fourcc_tag, (uint8_t)(fourcc_tag >> 8), (uint8_t)(fourcc_tag >> 16), (uint8_t)(fourcc_tag >> 24), 00275 (uint8_t)fourcc_tag, (uint8_t)(fourcc_tag >> 8), (uint8_t)(fourcc_tag >> 16), (uint8_t)(fourcc_tag >> 24)); 00276 ret = AVERROR_INVALIDDATA; 00277 packet_read = 1; 00278 break; 00279 } 00280 } 00281 00282 return ret; 00283 } 00284 00285 static int wc3_read_close(AVFormatContext *s) 00286 { 00287 Wc3DemuxContext *wc3 = s->priv_data; 00288 00289 if (wc3->vpkt.size > 0) 00290 av_free_packet(&wc3->vpkt); 00291 00292 return 0; 00293 } 00294 00295 AVInputFormat ff_wc3_demuxer = { 00296 "wc3movie", 00297 NULL_IF_CONFIG_SMALL("Wing Commander III movie format"), 00298 sizeof(Wc3DemuxContext), 00299 wc3_probe, 00300 wc3_read_header, 00301 wc3_read_packet, 00302 wc3_read_close, 00303 };