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