]> git.sesse.net Git - ffmpeg/blob - libavformat/iff.c
Merge remote branch 'qatar/master'
[ffmpeg] / libavformat / iff.c
1 /*
2  * IFF (.iff) file demuxer
3  * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
4  * Copyright (c) 2010 Peter Ross <pross@xvid.org>
5  * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
6  *
7  * This file is part of FFmpeg.
8  *
9  * FFmpeg is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * FFmpeg is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with FFmpeg; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  */
23
24 /**
25  * @file
26  * IFF file demuxer
27  * by Jaikrishnan Menon
28  * for more information on the .iff file format, visit:
29  * http://wiki.multimedia.cx/index.php?title=IFF
30  */
31
32 #include "libavcodec/bytestream.h"
33 #include "libavutil/intreadwrite.h"
34 #include "avformat.h"
35
36 #define ID_8SVX       MKTAG('8','S','V','X')
37 #define ID_VHDR       MKTAG('V','H','D','R')
38 #define ID_ATAK       MKTAG('A','T','A','K')
39 #define ID_RLSE       MKTAG('R','L','S','E')
40 #define ID_CHAN       MKTAG('C','H','A','N')
41 #define ID_PBM        MKTAG('P','B','M',' ')
42 #define ID_ILBM       MKTAG('I','L','B','M')
43 #define ID_BMHD       MKTAG('B','M','H','D')
44 #define ID_CAMG       MKTAG('C','A','M','G')
45 #define ID_CMAP       MKTAG('C','M','A','P')
46
47 #define ID_FORM       MKTAG('F','O','R','M')
48 #define ID_ANNO       MKTAG('A','N','N','O')
49 #define ID_AUTH       MKTAG('A','U','T','H')
50 #define ID_CHRS       MKTAG('C','H','R','S')
51 #define ID_COPYRIGHT  MKTAG('(','c',')',' ')
52 #define ID_CSET       MKTAG('C','S','E','T')
53 #define ID_FVER       MKTAG('F','V','E','R')
54 #define ID_NAME       MKTAG('N','A','M','E')
55 #define ID_TEXT       MKTAG('T','E','X','T')
56 #define ID_BODY       MKTAG('B','O','D','Y')
57 #define ID_ANNO       MKTAG('A','N','N','O')
58
59 #define LEFT    2
60 #define RIGHT   4
61 #define STEREO  6
62
63 #define PACKET_SIZE 1024
64
65 /**
66  * This number of bytes if added at the beginning of each AVPacket
67  * which contain additional information about video properties
68  * which has to be shared between demuxer and decoder.
69  * This number may change between frames, e.g. the demuxer might
70  * set it to smallest possible size of 2 to indicate that there's
71  * no extradata changing in this frame.
72  */
73 #define IFF_EXTRA_VIDEO_SIZE 9
74
75 typedef enum {
76     COMP_NONE,
77     COMP_FIB,
78     COMP_EXP
79 } svx8_compression_type;
80
81 typedef enum {
82     BITMAP_RAW,
83     BITMAP_BYTERUN1
84 } bitmap_compression_type;
85
86 typedef struct {
87     uint64_t  body_pos;
88     uint32_t  body_size;
89     uint32_t  sent_bytes;
90     uint32_t  audio_frame_count;
91     unsigned  compression;  ///< delta compression method used
92     unsigned  bpp;          ///< bits per plane to decode (differs from bits_per_coded_sample if HAM)
93     unsigned  ham;          ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise)
94     unsigned  flags;        ///< 1 for EHB, 0 is no extra half darkening
95     unsigned  transparency; ///< transparency color index in palette
96     unsigned  masking;      ///< masking method used
97 } IffDemuxContext;
98
99
100 static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size)
101 {
102     uint8_t *end = dest + size;
103     size = size>>1;
104
105     while(dest < end) {
106         *dest++ = *src;
107         *dest++ = *(src+size);
108         src++;
109     }
110 }
111
112 /* Metadata string read */
113 static int get_metadata(AVFormatContext *s,
114                         const char *const tag,
115                         const unsigned data_size)
116 {
117     uint8_t *buf = ((data_size + 1) == 0) ? NULL : av_malloc(data_size + 1);
118
119     if (!buf)
120         return AVERROR(ENOMEM);
121
122     if (avio_read(s->pb, buf, data_size) < 0) {
123         av_free(buf);
124         return AVERROR(EIO);
125     }
126     buf[data_size] = 0;
127     av_metadata_set2(&s->metadata, tag, buf, AV_METADATA_DONT_STRDUP_VAL);
128     return 0;
129 }
130
131 static int iff_probe(AVProbeData *p)
132 {
133     const uint8_t *d = p->buf;
134
135     if ( AV_RL32(d)   == ID_FORM &&
136          (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_PBM || AV_RL32(d+8) == ID_ILBM) )
137         return AVPROBE_SCORE_MAX;
138     return 0;
139 }
140
141 static int iff_read_header(AVFormatContext *s,
142                            AVFormatParameters *ap)
143 {
144     IffDemuxContext *iff = s->priv_data;
145     AVIOContext *pb = s->pb;
146     AVStream *st;
147     uint8_t *buf;
148     uint32_t chunk_id, data_size;
149     int compression = -1;
150     uint32_t screenmode = 0;
151     unsigned transparency = 0;
152     unsigned masking = 0; // no mask
153
154     st = av_new_stream(s, 0);
155     if (!st)
156         return AVERROR(ENOMEM);
157
158     st->codec->channels = 1;
159     avio_skip(pb, 8);
160     // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
161     st->codec->codec_tag = avio_rl32(pb);
162
163     while(!url_feof(pb)) {
164         uint64_t orig_pos;
165         int res;
166         const char *metadata_tag = NULL;
167         chunk_id = avio_rl32(pb);
168         data_size = avio_rb32(pb);
169         orig_pos = avio_tell(pb);
170
171         switch(chunk_id) {
172         case ID_VHDR:
173             st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
174
175             if (data_size < 14)
176                 return AVERROR_INVALIDDATA;
177             avio_skip(pb, 12);
178             st->codec->sample_rate = avio_rb16(pb);
179             if (data_size >= 16) {
180                 avio_skip(pb, 1);
181                 compression        = avio_r8(pb);
182             }
183             break;
184
185         case ID_BODY:
186             iff->body_pos = avio_tell(pb);
187             iff->body_size = data_size;
188             break;
189
190         case ID_CHAN:
191             if (data_size < 4)
192                 return AVERROR_INVALIDDATA;
193             st->codec->channels = (avio_rb32(pb) < 6) ? 1 : 2;
194             break;
195
196         case ID_CAMG:
197             if (data_size < 4)
198                 return AVERROR_INVALIDDATA;
199             screenmode                = avio_rb32(pb);
200             break;
201
202         case ID_CMAP:
203             st->codec->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE;
204             st->codec->extradata      = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
205             if (!st->codec->extradata)
206                 return AVERROR(ENOMEM);
207             if (avio_read(pb, st->codec->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0)
208                 return AVERROR(EIO);
209             break;
210
211         case ID_BMHD:
212             st->codec->codec_type            = AVMEDIA_TYPE_VIDEO;
213             if (data_size <= 8)
214                 return AVERROR_INVALIDDATA;
215             st->codec->width                 = avio_rb16(pb);
216             st->codec->height                = avio_rb16(pb);
217             avio_skip(pb, 4); // x, y offset
218             st->codec->bits_per_coded_sample = avio_r8(pb);
219             if (data_size >= 10)
220                 masking                      = avio_r8(pb);
221             if (data_size >= 11)
222                 compression                  = avio_r8(pb);
223             if (data_size >= 14) {
224                 avio_skip(pb, 1); // padding
225                 transparency                 = avio_rb16(pb);
226             }
227             if (data_size >= 16) {
228                 st->sample_aspect_ratio.num  = avio_r8(pb);
229                 st->sample_aspect_ratio.den  = avio_r8(pb);
230             }
231             break;
232
233         case ID_ANNO:
234         case ID_TEXT:
235             metadata_tag = "comment";
236             break;
237
238         case ID_AUTH:
239             metadata_tag = "artist";
240             break;
241
242         case ID_COPYRIGHT:
243             metadata_tag = "copyright";
244             break;
245
246         case ID_NAME:
247             metadata_tag = "title";
248             break;
249         }
250
251         if (metadata_tag) {
252             if ((res = get_metadata(s, metadata_tag, data_size)) < 0) {
253                 av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!", metadata_tag);
254                 return res;
255             }
256         }
257         avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1));
258     }
259
260     avio_seek(pb, iff->body_pos, SEEK_SET);
261
262     switch(st->codec->codec_type) {
263     case AVMEDIA_TYPE_AUDIO:
264         av_set_pts_info(st, 32, 1, st->codec->sample_rate);
265
266         switch(compression) {
267         case COMP_NONE:
268             st->codec->codec_id = CODEC_ID_PCM_S8;
269             break;
270         case COMP_FIB:
271             st->codec->codec_id = CODEC_ID_8SVX_FIB;
272             break;
273         case COMP_EXP:
274             st->codec->codec_id = CODEC_ID_8SVX_EXP;
275             break;
276         default:
277             av_log(s, AV_LOG_ERROR, "unknown compression method\n");
278             return -1;
279         }
280
281         st->codec->bits_per_coded_sample = 8;
282         st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample;
283         st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample;
284         break;
285
286     case AVMEDIA_TYPE_VIDEO:
287         iff->compression  = compression;
288         iff->bpp          = st->codec->bits_per_coded_sample;
289         if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) {
290             iff->ham      = iff->bpp > 6 ? 6 : 4;
291             st->codec->bits_per_coded_sample = 24;
292         }
293         iff->flags        = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8;
294         iff->masking      = masking;
295         iff->transparency = transparency;
296
297         if (!st->codec->extradata) {
298             st->codec->extradata_size = IFF_EXTRA_VIDEO_SIZE;
299             st->codec->extradata      = av_malloc(IFF_EXTRA_VIDEO_SIZE + FF_INPUT_BUFFER_PADDING_SIZE);
300             if (!st->codec->extradata)
301                 return AVERROR(ENOMEM);
302         }
303         buf = st->codec->extradata;
304         bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE);
305         bytestream_put_byte(&buf, iff->compression);
306         bytestream_put_byte(&buf, iff->bpp);
307         bytestream_put_byte(&buf, iff->ham);
308         bytestream_put_byte(&buf, iff->flags);
309         bytestream_put_be16(&buf, iff->transparency);
310         bytestream_put_byte(&buf, iff->masking);
311
312         switch (compression) {
313         case BITMAP_RAW:
314             st->codec->codec_id = CODEC_ID_IFF_ILBM;
315             break;
316         case BITMAP_BYTERUN1:
317             st->codec->codec_id = CODEC_ID_IFF_BYTERUN1;
318             break;
319         default:
320             av_log(s, AV_LOG_ERROR, "unknown compression method\n");
321             return AVERROR_INVALIDDATA;
322         }
323         break;
324     default:
325         return -1;
326     }
327
328     return 0;
329 }
330
331 static int iff_read_packet(AVFormatContext *s,
332                            AVPacket *pkt)
333 {
334     IffDemuxContext *iff = s->priv_data;
335     AVIOContext *pb = s->pb;
336     AVStream *st = s->streams[0];
337     int ret;
338
339     if(iff->sent_bytes >= iff->body_size)
340         return AVERROR(EIO);
341
342     if(st->codec->channels == 2) {
343         uint8_t sample_buffer[PACKET_SIZE];
344
345         ret = avio_read(pb, sample_buffer, PACKET_SIZE);
346         if(av_new_packet(pkt, PACKET_SIZE) < 0) {
347             av_log(s, AV_LOG_ERROR, "cannot allocate packet\n");
348             return AVERROR(ENOMEM);
349         }
350         interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE);
351     } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
352         uint8_t *buf;
353
354         if (av_new_packet(pkt, iff->body_size + 2) < 0) {
355             return AVERROR(ENOMEM);
356         }
357
358         buf = pkt->data;
359         bytestream_put_be16(&buf, 2);
360         ret = avio_read(pb, buf, iff->body_size);
361     } else {
362         ret = av_get_packet(pb, pkt, PACKET_SIZE);
363     }
364
365     if(iff->sent_bytes == 0)
366         pkt->flags |= AV_PKT_FLAG_KEY;
367
368     if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
369         iff->sent_bytes += PACKET_SIZE;
370     } else {
371         iff->sent_bytes = iff->body_size;
372     }
373     pkt->stream_index = 0;
374     if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
375         pkt->pts = iff->audio_frame_count;
376         iff->audio_frame_count += ret / st->codec->channels;
377     }
378     return ret;
379 }
380
381 AVInputFormat ff_iff_demuxer = {
382     "IFF",
383     NULL_IF_CONFIG_SMALL("IFF format"),
384     sizeof(IffDemuxContext),
385     iff_probe,
386     iff_read_header,
387     iff_read_packet,
388 };