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