00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00031 #include "libavcodec/bytestream.h"
00032 #include "libavutil/avassert.h"
00033 #include "libavutil/intreadwrite.h"
00034 #include "libavutil/dict.h"
00035 #include "avformat.h"
00036 #include "internal.h"
00037
00038 #define ID_8SVX MKTAG('8','S','V','X')
00039 #define ID_VHDR MKTAG('V','H','D','R')
00040 #define ID_ATAK MKTAG('A','T','A','K')
00041 #define ID_RLSE MKTAG('R','L','S','E')
00042 #define ID_CHAN MKTAG('C','H','A','N')
00043 #define ID_PBM MKTAG('P','B','M',' ')
00044 #define ID_ILBM MKTAG('I','L','B','M')
00045 #define ID_BMHD MKTAG('B','M','H','D')
00046 #define ID_DGBL MKTAG('D','G','B','L')
00047 #define ID_CAMG MKTAG('C','A','M','G')
00048 #define ID_CMAP MKTAG('C','M','A','P')
00049 #define ID_ACBM MKTAG('A','C','B','M')
00050 #define ID_DEEP MKTAG('D','E','E','P')
00051
00052 #define ID_FORM MKTAG('F','O','R','M')
00053 #define ID_ANNO MKTAG('A','N','N','O')
00054 #define ID_AUTH MKTAG('A','U','T','H')
00055 #define ID_CHRS MKTAG('C','H','R','S')
00056 #define ID_COPYRIGHT MKTAG('(','c',')',' ')
00057 #define ID_CSET MKTAG('C','S','E','T')
00058 #define ID_FVER MKTAG('F','V','E','R')
00059 #define ID_NAME MKTAG('N','A','M','E')
00060 #define ID_TEXT MKTAG('T','E','X','T')
00061 #define ID_ABIT MKTAG('A','B','I','T')
00062 #define ID_BODY MKTAG('B','O','D','Y')
00063 #define ID_DBOD MKTAG('D','B','O','D')
00064 #define ID_DPEL MKTAG('D','P','E','L')
00065
00066 #define LEFT 2
00067 #define RIGHT 4
00068 #define STEREO 6
00069
00078 #define IFF_EXTRA_VIDEO_SIZE 9
00079
00080 typedef enum {
00081 COMP_NONE,
00082 COMP_FIB,
00083 COMP_EXP
00084 } svx8_compression_type;
00085
00086 typedef enum {
00087 BITMAP_RAW,
00088 BITMAP_BYTERUN1
00089 } bitmap_compression_type;
00090
00091 typedef struct {
00092 uint64_t body_pos;
00093 uint32_t body_size;
00094 uint32_t sent_bytes;
00095 svx8_compression_type svx8_compression;
00096 bitmap_compression_type bitmap_compression;
00097 unsigned bpp;
00098 unsigned ham;
00099 unsigned flags;
00100 unsigned transparency;
00101 unsigned masking;
00102 } IffDemuxContext;
00103
00104
00105 static int get_metadata(AVFormatContext *s,
00106 const char *const tag,
00107 const unsigned data_size)
00108 {
00109 uint8_t *buf = ((data_size + 1) == 0) ? NULL : av_malloc(data_size + 1);
00110
00111 if (!buf)
00112 return AVERROR(ENOMEM);
00113
00114 if (avio_read(s->pb, buf, data_size) < 0) {
00115 av_free(buf);
00116 return AVERROR(EIO);
00117 }
00118 buf[data_size] = 0;
00119 av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL);
00120 return 0;
00121 }
00122
00123 static int iff_probe(AVProbeData *p)
00124 {
00125 const uint8_t *d = p->buf;
00126
00127 if ( AV_RL32(d) == ID_FORM &&
00128 (AV_RL32(d+8) == ID_8SVX ||
00129 AV_RL32(d+8) == ID_PBM ||
00130 AV_RL32(d+8) == ID_ACBM ||
00131 AV_RL32(d+8) == ID_DEEP ||
00132 AV_RL32(d+8) == ID_ILBM) )
00133 return AVPROBE_SCORE_MAX;
00134 return 0;
00135 }
00136
00137 static const uint8_t deep_rgb24[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
00138 static const uint8_t deep_rgba[] = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
00139
00140 static int iff_read_header(AVFormatContext *s)
00141 {
00142 IffDemuxContext *iff = s->priv_data;
00143 AVIOContext *pb = s->pb;
00144 AVStream *st;
00145 uint8_t *buf;
00146 uint32_t chunk_id, data_size;
00147 uint32_t screenmode = 0;
00148 unsigned transparency = 0;
00149 unsigned masking = 0;
00150 uint8_t fmt[16];
00151 int fmt_size;
00152
00153 st = avformat_new_stream(s, NULL);
00154 if (!st)
00155 return AVERROR(ENOMEM);
00156
00157 st->codec->channels = 1;
00158 avio_skip(pb, 8);
00159
00160 st->codec->codec_tag = avio_rl32(pb);
00161
00162 while(!url_feof(pb)) {
00163 uint64_t orig_pos;
00164 int res;
00165 const char *metadata_tag = NULL;
00166 chunk_id = avio_rl32(pb);
00167 data_size = avio_rb32(pb);
00168 orig_pos = avio_tell(pb);
00169
00170 switch(chunk_id) {
00171 case ID_VHDR:
00172 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00173
00174 if (data_size < 14)
00175 return AVERROR_INVALIDDATA;
00176 avio_skip(pb, 12);
00177 st->codec->sample_rate = avio_rb16(pb);
00178 if (data_size >= 16) {
00179 avio_skip(pb, 1);
00180 iff->svx8_compression = avio_r8(pb);
00181 }
00182 break;
00183
00184 case ID_ABIT:
00185 case ID_BODY:
00186 case ID_DBOD:
00187 iff->body_pos = avio_tell(pb);
00188 iff->body_size = data_size;
00189 break;
00190
00191 case ID_CHAN:
00192 if (data_size < 4)
00193 return AVERROR_INVALIDDATA;
00194 st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2;
00195 break;
00196
00197 case ID_CAMG:
00198 if (data_size < 4)
00199 return AVERROR_INVALIDDATA;
00200 screenmode = avio_rb32(pb);
00201 break;
00202
00203 case ID_CMAP:
00204 st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
00205 st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
00206 if (!st->codec->extradata)
00207 return AVERROR(ENOMEM);
00208 if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
00209 return AVERROR(EIO);
00210 break;
00211
00212 case ID_BMHD:
00213 iff->bitmap_compression = -1;
00214 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00215 if (data_size <= 8)
00216 return AVERROR_INVALIDDATA;
00217 st->codec->width = avio_rb16(pb);
00218 st->codec->height = avio_rb16(pb);
00219 avio_skip(pb, 4);
00220 st->codec->bits_per_coded_sample = avio_r8(pb);
00221 if (data_size >= 10)
00222 masking = avio_r8(pb);
00223 if (data_size >= 11)
00224 iff->bitmap_compression = avio_r8(pb);
00225 if (data_size >= 14) {
00226 avio_skip(pb, 1);
00227 transparency = avio_rb16(pb);
00228 }
00229 if (data_size >= 16) {
00230 st->sample_aspect_ratio.num = avio_r8(pb);
00231 st->sample_aspect_ratio.den = avio_r8(pb);
00232 }
00233 break;
00234
00235 case ID_DPEL:
00236 if (data_size < 4 || (data_size & 3))
00237 return AVERROR_INVALIDDATA;
00238 if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0)
00239 return fmt_size;
00240 if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24)))
00241 st->codec->pix_fmt = PIX_FMT_RGB24;
00242 else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba)))
00243 st->codec->pix_fmt = PIX_FMT_RGBA;
00244 else {
00245 av_log_ask_for_sample(s, "unsupported color format\n");
00246 return AVERROR_PATCHWELCOME;
00247 }
00248 break;
00249
00250 case ID_DGBL:
00251 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00252 if (data_size < 8)
00253 return AVERROR_INVALIDDATA;
00254 st->codec->width = avio_rb16(pb);
00255 st->codec->height = avio_rb16(pb);
00256 iff->bitmap_compression = avio_rb16(pb);
00257 if (iff->bitmap_compression != 0) {
00258 av_log(s, AV_LOG_ERROR,
00259 "compression %i not supported\n", iff->bitmap_compression);
00260 return AVERROR_PATCHWELCOME;
00261 }
00262 st->sample_aspect_ratio.num = avio_r8(pb);
00263 st->sample_aspect_ratio.den = avio_r8(pb);
00264 st->codec->bits_per_coded_sample = 24;
00265 break;
00266
00267 case ID_ANNO:
00268 case ID_TEXT: metadata_tag = "comment"; break;
00269 case ID_AUTH: metadata_tag = "artist"; break;
00270 case ID_COPYRIGHT: metadata_tag = "copyright"; break;
00271 case ID_NAME: metadata_tag = "title"; break;
00272 }
00273
00274 if (metadata_tag) {
00275 if ((res = get_metadata(s, metadata_tag, data_size)) < 0) {
00276 av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag);
00277 return res;
00278 }
00279 }
00280 avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1));
00281 }
00282
00283 avio_seek(pb, iff->body_pos, SEEK_SET);
00284
00285 switch(st->codec->codec_type) {
00286 case AVMEDIA_TYPE_AUDIO:
00287 avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
00288
00289 switch (iff->svx8_compression) {
00290 case COMP_NONE:
00291 st->codec->codec_id = AV_CODEC_ID_PCM_S8_PLANAR;
00292 break;
00293 case COMP_FIB:
00294 st->codec->codec_id = AV_CODEC_ID_8SVX_FIB;
00295 break;
00296 case COMP_EXP:
00297 st->codec->codec_id = AV_CODEC_ID_8SVX_EXP;
00298 break;
00299 default:
00300 av_log(s, AV_LOG_ERROR,
00301 "Unknown SVX8 compression method '%d'\n", iff->svx8_compression);
00302 return -1;
00303 }
00304
00305 st->codec->bits_per_coded_sample = iff->svx8_compression == COMP_NONE ? 8 : 4;
00306 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
00307 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00308 break;
00309
00310 case AVMEDIA_TYPE_VIDEO:
00311 iff->bpp = st->codec->bits_per_coded_sample;
00312 if ((screenmode & 0x800 ) && iff->bpp <= 8) {
00313 iff->ham = iff->bpp > 6 ? 6 : 4;
00314 st->codec->bits_per_coded_sample = 24;
00315 }
00316 iff->flags = (screenmode & 0x80 ) && iff->bpp <= 8;
00317 iff->masking = masking;
00318 iff->transparency = transparency;
00319
00320 if (!st->codec->extradata) {
00321 st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
00322 st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
00323 if (!st->codec->extradata)
00324 return AVERROR(ENOMEM);
00325 }
00326 buf = st->codec->extradata;
00327 bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
00328 bytestream_put_byte(&buf, iff->bitmap_compression);
00329 bytestream_put_byte(&buf, iff->bpp);
00330 bytestream_put_byte(&buf, iff->ham);
00331 bytestream_put_byte(&buf, iff->flags);
00332 bytestream_put_be16(&buf, iff->transparency);
00333 bytestream_put_byte(&buf, iff->masking);
00334
00335 switch (iff->bitmap_compression) {
00336 case BITMAP_RAW:
00337 st->codec->codec_id = AV_CODEC_ID_IFF_ILBM;
00338 break;
00339 case BITMAP_BYTERUN1:
00340 st->codec->codec_id = AV_CODEC_ID_IFF_BYTERUN1;
00341 break;
00342 default:
00343 av_log(s, AV_LOG_ERROR,
00344 "Unknown bitmap compression method '%d'\n", iff->bitmap_compression);
00345 return AVERROR_INVALIDDATA;
00346 }
00347 break;
00348 default:
00349 return -1;
00350 }
00351
00352 return 0;
00353 }
00354
00355 static int iff_read_packet(AVFormatContext *s,
00356 AVPacket *pkt)
00357 {
00358 IffDemuxContext *iff = s->priv_data;
00359 AVIOContext *pb = s->pb;
00360 AVStream *st = s->streams[0];
00361 int ret;
00362
00363 if(iff->sent_bytes >= iff->body_size)
00364 return AVERROR_EOF;
00365
00366 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00367 ret = av_get_packet(pb, pkt, iff->body_size);
00368 } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00369 uint8_t *buf;
00370
00371 if (av_new_packet(pkt, iff->body_size + 2) < 0) {
00372 return AVERROR(ENOMEM);
00373 }
00374
00375 buf = pkt->data;
00376 bytestream_put_be16(&buf, 2);
00377 ret = avio_read(pb, buf, iff->body_size);
00378 } else {
00379 av_assert0(0);
00380 }
00381
00382 if(iff->sent_bytes == 0)
00383 pkt->flags |= AV_PKT_FLAG_KEY;
00384 iff->sent_bytes = iff->body_size;
00385
00386 pkt->stream_index = 0;
00387 return ret;
00388 }
00389
00390 AVInputFormat ff_iff_demuxer = {
00391 .name = "iff",
00392 .long_name = NULL_IF_CONFIG_SMALL("IFF (Interchange File Format)"),
00393 .priv_data_size = sizeof(IffDemuxContext),
00394 .read_probe = iff_probe,
00395 .read_header = iff_read_header,
00396 .read_packet = iff_read_packet,
00397 };