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