Mercurial > libavformat.hg
annotate iff.c @ 5985:35c3858d457f libavformat
Reindent after rr22977.
Patch by Sebastian Vater <cdgs.basty googlemail com>.
author | rbultje |
---|---|
date | Tue, 27 Apr 2010 14:04:11 +0000 |
parents | 55c714a8fb00 |
children | 672248acc077 |
rev | line source |
---|---|
3189 | 1 /* |
3198 | 2 * IFF (.iff) file demuxer |
3189 | 3 * Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net> |
5625 | 4 * Copyright (c) 2010 Peter Ross <pross@xvid.org> |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
5 * Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com> |
3189 | 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 /** | |
5969
178de7695c6c
Remove explicit filename from Doxygen @file commands.
diego
parents:
5913
diff
changeset
|
25 * @file |
3198 | 26 * IFF file demuxer |
3189 | 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 | |
4201
7d2f3f1b68d8
Fix build: Add intreadwrite.h and bswap.h #includes where necessary.
diego
parents:
4090
diff
changeset
|
32 #include "libavutil/intreadwrite.h" |
5773
fd3b7b9b63a8
IFF: move ff_cmap_read_palette() prototype to a header file
mru
parents:
5660
diff
changeset
|
33 #include "libavcodec/iff.h" |
3189 | 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') | |
5625 | 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_CMAP MKTAG('C','M','A','P') | |
3189 | 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') | |
5660 | 56 #define ID_ANNO MKTAG('A','N','N','O') |
3189 | 57 |
58 #define LEFT 2 | |
59 #define RIGHT 4 | |
60 #define STEREO 6 | |
61 | |
62 #define PACKET_SIZE 1024 | |
63 | |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
64 typedef enum { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
65 COMP_NONE, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
66 COMP_FIB, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
67 COMP_EXP |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
68 } svx8_compression_type; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
69 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
70 typedef enum { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
71 BITMAP_RAW, |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
72 BITMAP_BYTERUN1 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
73 } bitmap_compression_type; |
3189 | 74 |
75 typedef struct { | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
76 uint64_t body_pos; |
3189 | 77 uint32_t body_size; |
78 uint32_t sent_bytes; | |
79 uint32_t audio_frame_count; | |
80 } IffDemuxContext; | |
81 | |
3285 | 82 |
83 static void interleave_stereo(const uint8_t *src, uint8_t *dest, int size) | |
84 { | |
85 uint8_t *end = dest + size; | |
86 size = size>>1; | |
87 | |
88 while(dest < end) { | |
89 *dest++ = *src; | |
90 *dest++ = *(src+size); | |
91 src++; | |
92 } | |
93 } | |
94 | |
3189 | 95 static int iff_probe(AVProbeData *p) |
96 { | |
97 const uint8_t *d = p->buf; | |
98 | |
99 if ( AV_RL32(d) == ID_FORM && | |
5625 | 100 (AV_RL32(d+8) == ID_8SVX || AV_RL32(d+8) == ID_PBM || AV_RL32(d+8) == ID_ILBM) ) |
3189 | 101 return AVPROBE_SCORE_MAX; |
102 return 0; | |
103 } | |
104 | |
105 static int iff_read_header(AVFormatContext *s, | |
106 AVFormatParameters *ap) | |
107 { | |
108 IffDemuxContext *iff = s->priv_data; | |
109 ByteIOContext *pb = s->pb; | |
110 AVStream *st; | |
111 uint32_t chunk_id, data_size; | |
5625 | 112 int compression = -1; |
5660 | 113 char *buf; |
3189 | 114 |
115 st = av_new_stream(s, 0); | |
116 if (!st) | |
5985 | 117 return AVERROR(ENOMEM); |
3189 | 118 |
119 st->codec->channels = 1; | |
5625 | 120 url_fskip(pb, 8); |
121 // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content | |
122 st->codec->codec_tag = get_le32(pb); | |
3189 | 123 |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
124 while(!url_feof(pb)) { |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
125 uint64_t orig_pos; |
3189 | 126 chunk_id = get_le32(pb); |
127 data_size = get_be32(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
128 orig_pos = url_ftell(pb); |
3189 | 129 |
130 switch(chunk_id) { | |
131 case ID_VHDR: | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
132 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
133 |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
134 if (data_size < 14) |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
135 return AVERROR_INVALIDDATA; |
3189 | 136 url_fskip(pb, 12); |
137 st->codec->sample_rate = get_be16(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
138 if (data_size >= 16) { |
5985 | 139 url_fskip(pb, 1); |
140 compression = get_byte(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
141 } |
3189 | 142 break; |
143 | |
144 case ID_BODY: | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
145 iff->body_pos = url_ftell(pb); |
3189 | 146 iff->body_size = data_size; |
147 break; | |
148 | |
149 case ID_CHAN: | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
150 if (data_size < 4) |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
151 return AVERROR_INVALIDDATA; |
3189 | 152 st->codec->channels = (get_be32(pb) < 6) ? 1 : 2; |
153 break; | |
154 | |
5625 | 155 case ID_CMAP: |
156 st->codec->extradata_size = data_size; | |
157 st->codec->extradata = av_malloc(data_size); | |
158 if (!st->codec->extradata) | |
159 return AVERROR(ENOMEM); | |
160 if (get_buffer(pb, st->codec->extradata, data_size) < 0) | |
161 return AVERROR(EIO); | |
162 break; | |
163 | |
164 case ID_BMHD: | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
165 st->codec->codec_type = AVMEDIA_TYPE_VIDEO; |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
166 if (data_size <= 8) |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
167 return AVERROR_INVALIDDATA; |
5625 | 168 st->codec->width = get_be16(pb); |
169 st->codec->height = get_be16(pb); | |
170 url_fskip(pb, 4); // x, y offset | |
171 st->codec->bits_per_coded_sample = get_byte(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
172 if (data_size >= 11) { |
5985 | 173 url_fskip(pb, 1); // masking |
174 compression = get_byte(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
175 } |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
176 if (data_size >= 16) { |
5985 | 177 url_fskip(pb, 3); // paddding, transparent |
178 st->sample_aspect_ratio.num = get_byte(pb); | |
179 st->sample_aspect_ratio.den = get_byte(pb); | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
180 } |
5625 | 181 break; |
182 | |
5660 | 183 case ID_ANNO: |
184 buf = av_malloc(data_size + 1); | |
185 if (!buf) | |
186 break; | |
187 get_buffer(pb, buf, data_size); | |
188 buf[data_size] = 0; | |
189 av_metadata_set2(&s->metadata, "comment", buf, AV_METADATA_DONT_STRDUP_VAL); | |
190 break; | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
191 } |
5660 | 192 |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
193 url_fskip(pb, data_size - (url_ftell(pb) - orig_pos) + (data_size & 1)); |
3189 | 194 } |
195 | |
5984
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
196 url_fseek(pb, iff->body_pos, SEEK_SET); |
55c714a8fb00
Make the IFF demuxer a little more standards-compliant, e.g. respect the size
rbultje
parents:
5971
diff
changeset
|
197 |
5625 | 198 switch(st->codec->codec_type) { |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
199 case AVMEDIA_TYPE_AUDIO: |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
200 av_set_pts_info(st, 32, 1, st->codec->sample_rate); |
3189 | 201 |
5971
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
202 switch(compression) { |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
203 case COMP_NONE: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
204 st->codec->codec_id = CODEC_ID_PCM_S8; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
205 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
206 case COMP_FIB: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
207 st->codec->codec_id = CODEC_ID_8SVX_FIB; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
208 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
209 case COMP_EXP: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
210 st->codec->codec_id = CODEC_ID_8SVX_EXP; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
211 break; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
212 default: |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
213 av_log(s, AV_LOG_ERROR, "iff: unknown compression method\n"); |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
214 return -1; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
215 } |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
216 |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
217 st->codec->bits_per_coded_sample = 8; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
218 st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * st->codec->bits_per_coded_sample; |
43548500ffbc
Reindent / reformat some code with broken indenting.
rbultje
parents:
5969
diff
changeset
|
219 st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; |
3189 | 220 break; |
5625 | 221 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
222 case AVMEDIA_TYPE_VIDEO: |
5625 | 223 switch (compression) { |
224 case BITMAP_RAW: | |
225 if (st->codec->codec_tag == ID_ILBM) { | |
226 st->codec->codec_id = CODEC_ID_IFF_ILBM; | |
227 } else { | |
228 st->codec->codec_id = CODEC_ID_RAWVIDEO; | |
229 st->codec->pix_fmt = PIX_FMT_PAL8; | |
230 st->codec->codec_tag = 0; | |
231 } | |
232 break; | |
233 case BITMAP_BYTERUN1: | |
234 st->codec->codec_id = CODEC_ID_IFF_BYTERUN1; | |
235 break; | |
236 default: | |
237 av_log(s, AV_LOG_ERROR, "unknown compression method\n"); | |
238 return AVERROR_INVALIDDATA; | |
239 } | |
240 break; | |
241 default: | |
242 return -1; | |
243 } | |
3189 | 244 |
245 return 0; | |
246 } | |
247 | |
248 static int iff_read_packet(AVFormatContext *s, | |
249 AVPacket *pkt) | |
250 { | |
251 IffDemuxContext *iff = s->priv_data; | |
252 ByteIOContext *pb = s->pb; | |
5625 | 253 AVStream *st = s->streams[0]; |
3189 | 254 int ret; |
255 | |
5625 | 256 if(iff->sent_bytes >= iff->body_size) |
3189 | 257 return AVERROR(EIO); |
3285 | 258 |
259 if(s->streams[0]->codec->channels == 2) { | |
260 uint8_t sample_buffer[PACKET_SIZE]; | |
261 | |
262 ret = get_buffer(pb, sample_buffer, PACKET_SIZE); | |
263 if(av_new_packet(pkt, PACKET_SIZE) < 0) { | |
264 av_log(s, AV_LOG_ERROR, "iff: cannot allocate packet \n"); | |
265 return AVERROR(ENOMEM); | |
266 } | |
267 interleave_stereo(sample_buffer, pkt->data, PACKET_SIZE); | |
5625 | 268 } else if (s->streams[0]->codec->codec_id == CODEC_ID_RAWVIDEO) { |
269 if(av_new_packet(pkt, iff->body_size + AVPALETTE_SIZE) < 0) { | |
270 return AVERROR(ENOMEM); | |
271 } | |
272 | |
273 ret = ff_cmap_read_palette(st->codec, (uint32_t*)(pkt->data + iff->body_size)); | |
274 if (ret < 0) | |
275 return ret; | |
276 av_freep(&st->codec->extradata); | |
277 st->codec->extradata_size = 0; | |
278 | |
279 ret = get_buffer(pb, pkt->data, iff->body_size); | |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
280 } else if (s->streams[0]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { |
5625 | 281 ret = av_get_packet(pb, pkt, iff->body_size); |
282 } else { | |
3285 | 283 ret = av_get_packet(pb, pkt, PACKET_SIZE); |
284 } | |
3189 | 285 |
286 if(iff->sent_bytes == 0) | |
5913
11bb10c37225
Replace all occurences of PKT_FLAG_KEY with AV_PKT_FLAG_KEY.
cehoyos
parents:
5910
diff
changeset
|
287 pkt->flags |= AV_PKT_FLAG_KEY; |
3189 | 288 |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
289 if(s->streams[0]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
5626 | 290 iff->sent_bytes += PACKET_SIZE; |
5625 | 291 } else { |
292 iff->sent_bytes = iff->body_size; | |
293 } | |
3189 | 294 pkt->stream_index = 0; |
5910
536e5527c1e0
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
5773
diff
changeset
|
295 if(s->streams[0]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { |
5626 | 296 pkt->pts = iff->audio_frame_count; |
297 iff->audio_frame_count += ret / s->streams[0]->codec->channels; | |
5625 | 298 } |
3189 | 299 return ret; |
300 } | |
301 | |
302 AVInputFormat iff_demuxer = { | |
303 "IFF", | |
3424
7a0230981402
Make long_names in lavf/lavdev optional depending on CONFIG_SMALL.
diego
parents:
3285
diff
changeset
|
304 NULL_IF_CONFIG_SMALL("IFF format"), |
3189 | 305 sizeof(IffDemuxContext), |
306 iff_probe, | |
307 iff_read_header, | |
308 iff_read_packet, | |
309 }; |