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