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_CAMG MKTAG('C','A','M','G')
00046 #define ID_CMAP MKTAG('C','M','A','P')
00047 #define ID_ACBM MKTAG('A','C','B','M')
00048
00049 #define ID_FORM MKTAG('F','O','R','M')
00050 #define ID_ANNO MKTAG('A','N','N','O')
00051 #define ID_AUTH MKTAG('A','U','T','H')
00052 #define ID_CHRS MKTAG('C','H','R','S')
00053 #define ID_COPYRIGHT MKTAG('(','c',')',' ')
00054 #define ID_CSET MKTAG('C','S','E','T')
00055 #define ID_FVER MKTAG('F','V','E','R')
00056 #define ID_NAME MKTAG('N','A','M','E')
00057 #define ID_TEXT MKTAG('T','E','X','T')
00058 #define ID_ABIT MKTAG('A','B','I','T')
00059 #define ID_BODY MKTAG('B','O','D','Y')
00060 #define ID_ANNO MKTAG('A','N','N','O')
00061
00062 #define LEFT 2
00063 #define RIGHT 4
00064 #define STEREO 6
00065
00074 #define IFF_EXTRA_VIDEO_SIZE 9
00075
00076 typedef enum {
00077 COMP_NONE,
00078 COMP_FIB,
00079 COMP_EXP
00080 } svx8_compression_type;
00081
00082 typedef enum {
00083 BITMAP_RAW,
00084 BITMAP_BYTERUN1
00085 } bitmap_compression_type;
00086
00087 typedef struct {
00088 uint64_t body_pos;
00089 uint32_t body_size;
00090 uint32_t sent_bytes;
00091 svx8_compression_type svx8_compression;
00092 bitmap_compression_type bitmap_compression;
00093 unsigned bpp;
00094 unsigned ham;
00095 unsigned flags;
00096 unsigned transparency;
00097 unsigned masking;
00098 } IffDemuxContext;
00099
00100
00101 static int get_metadata(AVFormatContext *s,
00102 const char *const tag,
00103 const unsigned data_size)
00104 {
00105 uint8_t *buf = ((data_size + 1) == 0) ? NULL : av_malloc(data_size + 1);
00106
00107 if (!buf)
00108 return AVERROR(ENOMEM);
00109
00110 if (avio_read(s->pb, buf, data_size) < 0) {
00111 av_free(buf);
00112 return AVERROR(EIO);
00113 }
00114 buf[data_size] = 0;
00115 av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL);
00116 return 0;
00117 }
00118
00119 static int iff_probe(AVProbeData *p)
00120 {
00121 const uint8_t *d = p->buf;
00122
00123 if ( AV_RL32(d) == ID_FORM &&
00124 (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_PBM || AV_RL32(d+8) == ID_ILBM || AV_RL32(d+8) == ID_ACBM) )
00125 return AVPROBE_SCORE_MAX;
00126 return 0;
00127 }
00128
00129 static int iff_read_header(AVFormatContext *s,
00130 AVFormatParameters *ap)
00131 {
00132 IffDemuxContext *iff = s->priv_data;
00133 AVIOContext *pb = s->pb;
00134 AVStream *st;
00135 uint8_t *buf;
00136 uint32_t chunk_id, data_size;
00137 uint32_t screenmode = 0;
00138 unsigned transparency = 0;
00139 unsigned masking = 0;
00140
00141 st = avformat_new_stream(s, NULL);
00142 if (!st)
00143 return AVERROR(ENOMEM);
00144
00145 st->codec->channels = 1;
00146 avio_skip(pb, 8);
00147
00148 st->codec->codec_tag = avio_rl32(pb);
00149
00150 while(!url_feof(pb)) {
00151 uint64_t orig_pos;
00152 int res;
00153 const char *metadata_tag = NULL;
00154 chunk_id = avio_rl32(pb);
00155 data_size = avio_rb32(pb);
00156 orig_pos = avio_tell(pb);
00157
00158 switch(chunk_id) {
00159 case ID_VHDR:
00160 st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
00161
00162 if (data_size < 14)
00163 return AVERROR_INVALIDDATA;
00164 avio_skip(pb, 12);
00165 st->codec->sample_rate = avio_rb16(pb);
00166 if (data_size >= 16) {
00167 avio_skip(pb, 1);
00168 iff->svx8_compression = avio_r8(pb);
00169 }
00170 break;
00171
00172 case ID_ABIT:
00173 case ID_BODY:
00174 iff->body_pos = avio_tell(pb);
00175 iff->body_size = data_size;
00176 break;
00177
00178 case ID_CHAN:
00179 if (data_size < 4)
00180 return AVERROR_INVALIDDATA;
00181 st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2;
00182 break;
00183
00184 case ID_CAMG:
00185 if (data_size < 4)
00186 return AVERROR_INVALIDDATA;
00187 screenmode = avio_rb32(pb);
00188 break;
00189
00190 case ID_CMAP:
00191 st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
00192 st->codec->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
00193 if (!st->codec->extradata)
00194 return AVERROR(ENOMEM);
00195 if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
00196 return AVERROR(EIO);
00197 break;
00198
00199 case ID_BMHD:
00200 iff->bitmap_compression = -1;
00201 st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
00202 if (data_size <= 8)
00203 return AVERROR_INVALIDDATA;
00204 st->codec->width = avio_rb16(pb);
00205 st->codec->height = avio_rb16(pb);
00206 avio_skip(pb, 4);
00207 st->codec->bits_per_coded_sample = avio_r8(pb);
00208 if (data_size >= 10)
00209 masking = avio_r8(pb);
00210 if (data_size >= 11)
00211 iff->bitmap_compression = avio_r8(pb);
00212 if (data_size >= 14) {
00213 avio_skip(pb, 1);
00214 transparency = avio_rb16(pb);
00215 }
00216 if (data_size >= 16) {
00217 st->sample_aspect_ratio.num = avio_r8(pb);
00218 st->sample_aspect_ratio.den = avio_r8(pb);
00219 }
00220 break;
00221
00222 case ID_ANNO:
00223 case ID_TEXT: metadata_tag = "comment"; break;
00224 case ID_AUTH: metadata_tag = "artist"; break;
00225 case ID_COPYRIGHT: metadata_tag = "copyright"; break;
00226 case ID_NAME: metadata_tag = "title"; break;
00227 }
00228
00229 if (metadata_tag) {
00230 if ((res = get_metadata(s, metadata_tag, data_size)) < 0) {
00231 av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!", metadata_tag);
00232 return res;
00233 }
00234 }
00235 avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1));
00236 }
00237
00238 avio_seek(pb, iff->body_pos, SEEK_SET);
00239
00240 switch(st->codec->codec_type) {
00241 case AVMEDIA_TYPE_AUDIO:
00242 avpriv_set_pts_info(st, 32, 1, st->codec->sample_rate);
00243
00244 switch (iff->svx8_compression) {
00245 case COMP_NONE:
00246 st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR;
00247 break;
00248 case COMP_FIB:
00249 st->codec->codec_id = CODEC_ID_8SVX_FIB;
00250 break;
00251 case COMP_EXP:
00252 st->codec->codec_id = CODEC_ID_8SVX_EXP;
00253 break;
00254 default:
00255 av_log(s, AV_LOG_ERROR,
00256 "Unknown SVX8 compression method '%d'\n", iff->svx8_compression);
00257 return -1;
00258 }
00259
00260 st->codec->bits_per_coded_sample = iff->svx8_compression == COMP_NONE ? 8 : 4;
00261 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
00262 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
00263 break;
00264
00265 case AVMEDIA_TYPE_VIDEO:
00266 iff->bpp = st->codec->bits_per_coded_sample;
00267 if ((screenmode & 0x800 ) && iff->bpp <= 8) {
00268 iff->ham = iff->bpp > 6 ? 6 : 4;
00269 st->codec->bits_per_coded_sample = 24;
00270 }
00271 iff->flags = (screenmode & 0x80 ) && iff->bpp <= 8;
00272 iff->masking = masking;
00273 iff->transparency = transparency;
00274
00275 if (!st->codec->extradata) {
00276 st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
00277 st->codec->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
00278 if (!st->codec->extradata)
00279 return AVERROR(ENOMEM);
00280 }
00281 buf = st->codec->extradata;
00282 bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
00283 bytestream_put_byte(&buf, iff->bitmap_compression);
00284 bytestream_put_byte(&buf, iff->bpp);
00285 bytestream_put_byte(&buf, iff->ham);
00286 bytestream_put_byte(&buf, iff->flags);
00287 bytestream_put_be16(&buf, iff->transparency);
00288 bytestream_put_byte(&buf, iff->masking);
00289
00290 switch (iff->bitmap_compression) {
00291 case BITMAP_RAW:
00292 st->codec->codec_id = CODEC_ID_IFF_ILBM;
00293 break;
00294 case BITMAP_BYTERUN1:
00295 st->codec->codec_id = CODEC_ID_IFF_BYTERUN1;
00296 break;
00297 default:
00298 av_log(s, AV_LOG_ERROR,
00299 "Unknown bitmap compression method '%d'\n", iff->bitmap_compression);
00300 return AVERROR_INVALIDDATA;
00301 }
00302 break;
00303 default:
00304 return -1;
00305 }
00306
00307 return 0;
00308 }
00309
00310 static int iff_read_packet(AVFormatContext *s,
00311 AVPacket *pkt)
00312 {
00313 IffDemuxContext *iff = s->priv_data;
00314 AVIOContext *pb = s->pb;
00315 AVStream *st = s->streams[0];
00316 int ret;
00317
00318 if(iff->sent_bytes >= iff->body_size)
00319 return AVERROR_EOF;
00320
00321 if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
00322 ret = av_get_packet(pb, pkt, iff->body_size);
00323 } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
00324 uint8_t *buf;
00325
00326 if (av_new_packet(pkt, iff->body_size + 2) < 0) {
00327 return AVERROR(ENOMEM);
00328 }
00329
00330 buf = pkt->data;
00331 bytestream_put_be16(&buf, 2);
00332 ret = avio_read(pb, buf, iff->body_size);
00333 } else {
00334 av_abort();
00335 }
00336
00337 if(iff->sent_bytes == 0)
00338 pkt->flags |= AV_PKT_FLAG_KEY;
00339 iff->sent_bytes = iff->body_size;
00340
00341 pkt->stream_index = 0;
00342 return ret;
00343 }
00344
00345 AVInputFormat ff_iff_demuxer = {
00346 .name = "IFF",
00347 .long_name = NULL_IF_CONFIG_SMALL("IFF format"),
00348 .priv_data_size = sizeof(IffDemuxContext),
00349 .read_probe = iff_probe,
00350 .read_header = iff_read_header,
00351 .read_packet = iff_read_packet,
00352 };