blob: 6a09eb0e31631d0c295151faae2c45ed3b036495
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 <inttypes.h> |
32 | |
33 | #include "libavutil/avassert.h" |
34 | #include "libavutil/channel_layout.h" |
35 | #include "libavutil/intreadwrite.h" |
36 | #include "libavutil/dict.h" |
37 | #include "libavcodec/bytestream.h" |
38 | #include "avformat.h" |
39 | #include "id3v2.h" |
40 | #include "internal.h" |
41 | |
42 | #define ID_8SVX MKTAG('8','S','V','X') |
43 | #define ID_16SV MKTAG('1','6','S','V') |
44 | #define ID_MAUD MKTAG('M','A','U','D') |
45 | #define ID_MHDR MKTAG('M','H','D','R') |
46 | #define ID_MDAT MKTAG('M','D','A','T') |
47 | #define ID_VHDR MKTAG('V','H','D','R') |
48 | #define ID_ATAK MKTAG('A','T','A','K') |
49 | #define ID_RLSE MKTAG('R','L','S','E') |
50 | #define ID_CHAN MKTAG('C','H','A','N') |
51 | #define ID_PBM MKTAG('P','B','M',' ') |
52 | #define ID_ILBM MKTAG('I','L','B','M') |
53 | #define ID_BMHD MKTAG('B','M','H','D') |
54 | #define ID_DGBL MKTAG('D','G','B','L') |
55 | #define ID_CAMG MKTAG('C','A','M','G') |
56 | #define ID_CMAP MKTAG('C','M','A','P') |
57 | #define ID_ACBM MKTAG('A','C','B','M') |
58 | #define ID_DEEP MKTAG('D','E','E','P') |
59 | #define ID_RGB8 MKTAG('R','G','B','8') |
60 | #define ID_RGBN MKTAG('R','G','B','N') |
61 | #define ID_DSD MKTAG('D','S','D',' ') |
62 | #define ID_DST MKTAG('D','S','T',' ') |
63 | #define ID_DSTC MKTAG('D','S','T','C') |
64 | #define ID_DSTF MKTAG('D','S','T','F') |
65 | #define ID_FRTE MKTAG('F','R','T','E') |
66 | #define ID_ANIM MKTAG('A','N','I','M') |
67 | #define ID_ANHD MKTAG('A','N','H','D') |
68 | #define ID_DLTA MKTAG('D','L','T','A') |
69 | #define ID_DPAN MKTAG('D','P','A','N') |
70 | |
71 | #define ID_FORM MKTAG('F','O','R','M') |
72 | #define ID_FRM8 MKTAG('F','R','M','8') |
73 | #define ID_ANNO MKTAG('A','N','N','O') |
74 | #define ID_AUTH MKTAG('A','U','T','H') |
75 | #define ID_CHRS MKTAG('C','H','R','S') |
76 | #define ID_COPYRIGHT MKTAG('(','c',')',' ') |
77 | #define ID_CSET MKTAG('C','S','E','T') |
78 | #define ID_FVER MKTAG('F','V','E','R') |
79 | #define ID_NAME MKTAG('N','A','M','E') |
80 | #define ID_TEXT MKTAG('T','E','X','T') |
81 | #define ID_ABIT MKTAG('A','B','I','T') |
82 | #define ID_BODY MKTAG('B','O','D','Y') |
83 | #define ID_DBOD MKTAG('D','B','O','D') |
84 | #define ID_DPEL MKTAG('D','P','E','L') |
85 | #define ID_DLOC MKTAG('D','L','O','C') |
86 | #define ID_TVDC MKTAG('T','V','D','C') |
87 | |
88 | #define LEFT 2 |
89 | #define RIGHT 4 |
90 | #define STEREO 6 |
91 | |
92 | /** |
93 | * This number of bytes if added at the beginning of each AVPacket |
94 | * which contain additional information about video properties |
95 | * which has to be shared between demuxer and decoder. |
96 | * This number may change between frames, e.g. the demuxer might |
97 | * set it to smallest possible size of 2 to indicate that there's |
98 | * no extradata changing in this frame. |
99 | */ |
100 | #define IFF_EXTRA_VIDEO_SIZE 41 |
101 | |
102 | typedef enum { |
103 | COMP_NONE, |
104 | COMP_FIB, |
105 | COMP_EXP |
106 | } svx8_compression_type; |
107 | |
108 | typedef struct IffDemuxContext { |
109 | int is_64bit; ///< chunk size is 64-bit |
110 | int64_t body_pos; |
111 | int64_t body_end; |
112 | uint32_t body_size; |
113 | svx8_compression_type svx8_compression; |
114 | unsigned maud_bits; |
115 | unsigned maud_compression; |
116 | unsigned bitmap_compression; ///< delta compression method used |
117 | unsigned bpp; ///< bits per plane to decode (differs from bits_per_coded_sample if HAM) |
118 | unsigned ham; ///< 0 if non-HAM or number of hold bits (6 for bpp > 6, 4 otherwise) |
119 | unsigned flags; ///< 1 for EHB, 0 is no extra half darkening |
120 | unsigned transparency; ///< transparency color index in palette |
121 | unsigned masking; ///< masking method used |
122 | uint8_t tvdc[32]; ///< TVDC lookup table |
123 | int64_t pts; |
124 | } IffDemuxContext; |
125 | |
126 | /* Metadata string read */ |
127 | static int get_metadata(AVFormatContext *s, |
128 | const char *const tag, |
129 | const unsigned data_size) |
130 | { |
131 | uint8_t *buf = ((data_size + 1) == 0) ? NULL : av_malloc(data_size + 1); |
132 | |
133 | if (!buf) |
134 | return AVERROR(ENOMEM); |
135 | |
136 | if (avio_read(s->pb, buf, data_size) != data_size) { |
137 | av_free(buf); |
138 | return AVERROR(EIO); |
139 | } |
140 | buf[data_size] = 0; |
141 | av_dict_set(&s->metadata, tag, buf, AV_DICT_DONT_STRDUP_VAL); |
142 | return 0; |
143 | } |
144 | |
145 | static int iff_probe(AVProbeData *p) |
146 | { |
147 | const uint8_t *d = p->buf; |
148 | |
149 | if ( (AV_RL32(d) == ID_FORM && |
150 | (AV_RL32(d+8) == ID_8SVX || |
151 | AV_RL32(d+8) == ID_16SV || |
152 | AV_RL32(d+8) == ID_MAUD || |
153 | AV_RL32(d+8) == ID_PBM || |
154 | AV_RL32(d+8) == ID_ACBM || |
155 | AV_RL32(d+8) == ID_DEEP || |
156 | AV_RL32(d+8) == ID_ILBM || |
157 | AV_RL32(d+8) == ID_RGB8 || |
158 | AV_RL32(d+8) == ID_ANIM || |
159 | AV_RL32(d+8) == ID_RGBN)) || |
160 | (AV_RL32(d) == ID_FRM8 && AV_RL32(d+12) == ID_DSD)) |
161 | return AVPROBE_SCORE_MAX; |
162 | return 0; |
163 | } |
164 | |
165 | static const AVCodecTag dsd_codec_tags[] = { |
166 | { AV_CODEC_ID_DSD_MSBF, ID_DSD }, |
167 | { AV_CODEC_ID_DST, ID_DST }, |
168 | { AV_CODEC_ID_NONE, 0 }, |
169 | }; |
170 | |
171 | |
172 | #define DSD_SLFT MKTAG('S','L','F','T') |
173 | #define DSD_SRGT MKTAG('S','R','G','T') |
174 | #define DSD_MLFT MKTAG('M','L','F','T') |
175 | #define DSD_MRGT MKTAG('M','R','G','T') |
176 | #define DSD_C MKTAG('C',' ',' ',' ') |
177 | #define DSD_LS MKTAG('L','S',' ',' ') |
178 | #define DSD_RS MKTAG('R','S',' ',' ') |
179 | #define DSD_LFE MKTAG('L','F','E',' ') |
180 | |
181 | static const uint32_t dsd_stereo[] = { DSD_SLFT, DSD_SRGT }; |
182 | static const uint32_t dsd_5point0[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LS, DSD_RS }; |
183 | static const uint32_t dsd_5point1[] = { DSD_MLFT, DSD_MRGT, DSD_C, DSD_LFE, DSD_LS, DSD_RS }; |
184 | |
185 | typedef struct { |
186 | uint64_t layout; |
187 | const uint32_t * dsd_layout; |
188 | } DSDLayoutDesc; |
189 | |
190 | static const DSDLayoutDesc dsd_channel_layout[] = { |
191 | { AV_CH_LAYOUT_STEREO, dsd_stereo }, |
192 | { AV_CH_LAYOUT_5POINT0, dsd_5point0 }, |
193 | { AV_CH_LAYOUT_5POINT1, dsd_5point1 }, |
194 | }; |
195 | |
196 | static const uint64_t dsd_loudspeaker_config[] = { |
197 | AV_CH_LAYOUT_STEREO, |
198 | 0, 0, |
199 | AV_CH_LAYOUT_5POINT0, AV_CH_LAYOUT_5POINT1, |
200 | }; |
201 | |
202 | static const char * dsd_source_comment[] = { |
203 | "dsd_source_comment", |
204 | "analogue_source_comment", |
205 | "pcm_source_comment", |
206 | }; |
207 | |
208 | static const char * dsd_history_comment[] = { |
209 | "general_remark", |
210 | "operator_name", |
211 | "creating_machine", |
212 | "timezone", |
213 | "file_revision" |
214 | }; |
215 | |
216 | static int parse_dsd_diin(AVFormatContext *s, AVStream *st, uint64_t eof) |
217 | { |
218 | AVIOContext *pb = s->pb; |
219 | |
220 | while (avio_tell(pb) + 12 <= eof && !avio_feof(pb)) { |
221 | uint32_t tag = avio_rl32(pb); |
222 | uint64_t size = avio_rb64(pb); |
223 | uint64_t orig_pos = avio_tell(pb); |
224 | const char * metadata_tag = NULL; |
225 | |
226 | switch(tag) { |
227 | case MKTAG('D','I','A','R'): metadata_tag = "artist"; break; |
228 | case MKTAG('D','I','T','I'): metadata_tag = "title"; break; |
229 | } |
230 | |
231 | if (metadata_tag && size > 4) { |
232 | unsigned int tag_size = avio_rb32(pb); |
233 | int ret = get_metadata(s, metadata_tag, FFMIN(tag_size, size - 4)); |
234 | if (ret < 0) { |
235 | av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag); |
236 | return ret; |
237 | } |
238 | } |
239 | |
240 | avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1)); |
241 | } |
242 | |
243 | return 0; |
244 | } |
245 | |
246 | static int parse_dsd_prop(AVFormatContext *s, AVStream *st, uint64_t eof) |
247 | { |
248 | AVIOContext *pb = s->pb; |
249 | char abss[24]; |
250 | int hour, min, sec, i, ret, config; |
251 | int dsd_layout[6]; |
252 | ID3v2ExtraMeta *id3v2_extra_meta; |
253 | |
254 | while (avio_tell(pb) + 12 <= eof && !avio_feof(pb)) { |
255 | uint32_t tag = avio_rl32(pb); |
256 | uint64_t size = avio_rb64(pb); |
257 | uint64_t orig_pos = avio_tell(pb); |
258 | |
259 | switch(tag) { |
260 | case MKTAG('A','B','S','S'): |
261 | if (size < 8) |
262 | return AVERROR_INVALIDDATA; |
263 | hour = avio_rb16(pb); |
264 | min = avio_r8(pb); |
265 | sec = avio_r8(pb); |
266 | snprintf(abss, sizeof(abss), "%02dh:%02dm:%02ds:%d", hour, min, sec, avio_rb32(pb)); |
267 | av_dict_set(&st->metadata, "absolute_start_time", abss, 0); |
268 | break; |
269 | |
270 | case MKTAG('C','H','N','L'): |
271 | if (size < 2) |
272 | return AVERROR_INVALIDDATA; |
273 | st->codecpar->channels = avio_rb16(pb); |
274 | if (size < 2 + st->codecpar->channels * 4) |
275 | return AVERROR_INVALIDDATA; |
276 | st->codecpar->channel_layout = 0; |
277 | if (st->codecpar->channels > FF_ARRAY_ELEMS(dsd_layout)) { |
278 | avpriv_request_sample(s, "channel layout"); |
279 | break; |
280 | } |
281 | for (i = 0; i < st->codecpar->channels; i++) |
282 | dsd_layout[i] = avio_rl32(pb); |
283 | for (i = 0; i < FF_ARRAY_ELEMS(dsd_channel_layout); i++) { |
284 | const DSDLayoutDesc * d = &dsd_channel_layout[i]; |
285 | if (av_get_channel_layout_nb_channels(d->layout) == st->codecpar->channels && |
286 | !memcmp(d->dsd_layout, dsd_layout, st->codecpar->channels * sizeof(uint32_t))) { |
287 | st->codecpar->channel_layout = d->layout; |
288 | break; |
289 | } |
290 | } |
291 | break; |
292 | |
293 | case MKTAG('C','M','P','R'): |
294 | if (size < 4) |
295 | return AVERROR_INVALIDDATA; |
296 | st->codecpar->codec_tag = tag = avio_rl32(pb); |
297 | st->codecpar->codec_id = ff_codec_get_id(dsd_codec_tags, tag); |
298 | if (!st->codecpar->codec_id) { |
299 | av_log(s, AV_LOG_ERROR, "'%s' compression is not supported\n", |
300 | av_fourcc2str(tag)); |
301 | return AVERROR_PATCHWELCOME; |
302 | } |
303 | break; |
304 | |
305 | case MKTAG('F','S',' ',' '): |
306 | if (size < 4) |
307 | return AVERROR_INVALIDDATA; |
308 | st->codecpar->sample_rate = avio_rb32(pb) / 8; |
309 | break; |
310 | |
311 | case MKTAG('I','D','3',' '): |
312 | id3v2_extra_meta = NULL; |
313 | ff_id3v2_read(s, ID3v2_DEFAULT_MAGIC, &id3v2_extra_meta, size); |
314 | if (id3v2_extra_meta) { |
315 | if ((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) { |
316 | ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
317 | return ret; |
318 | } |
319 | ff_id3v2_free_extra_meta(&id3v2_extra_meta); |
320 | } |
321 | |
322 | if (size < avio_tell(pb) - orig_pos) { |
323 | av_log(s, AV_LOG_ERROR, "id3 exceeds chunk size\n"); |
324 | return AVERROR_INVALIDDATA; |
325 | } |
326 | break; |
327 | |
328 | case MKTAG('L','S','C','O'): |
329 | if (size < 2) |
330 | return AVERROR_INVALIDDATA; |
331 | config = avio_rb16(pb); |
332 | if (config != 0xFFFF) { |
333 | if (config < FF_ARRAY_ELEMS(dsd_loudspeaker_config)) |
334 | st->codecpar->channel_layout = dsd_loudspeaker_config[config]; |
335 | if (!st->codecpar->channel_layout) |
336 | avpriv_request_sample(s, "loudspeaker configuration %d", config); |
337 | } |
338 | break; |
339 | } |
340 | |
341 | avio_skip(pb, size - (avio_tell(pb) - orig_pos) + (size & 1)); |
342 | } |
343 | |
344 | return 0; |
345 | } |
346 | |
347 | static int read_dst_frame(AVFormatContext *s, AVPacket *pkt) |
348 | { |
349 | IffDemuxContext *iff = s->priv_data; |
350 | AVIOContext *pb = s->pb; |
351 | uint32_t chunk_id; |
352 | uint64_t chunk_pos, data_pos, data_size; |
353 | int ret = AVERROR_EOF; |
354 | |
355 | while (!avio_feof(pb)) { |
356 | chunk_pos = avio_tell(pb); |
357 | if (chunk_pos >= iff->body_end) |
358 | return AVERROR_EOF; |
359 | |
360 | chunk_id = avio_rl32(pb); |
361 | data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); |
362 | data_pos = avio_tell(pb); |
363 | |
364 | if (data_size < 1) |
365 | return AVERROR_INVALIDDATA; |
366 | |
367 | switch (chunk_id) { |
368 | case ID_DSTF: |
369 | if (!pkt) { |
370 | iff->body_pos = avio_tell(pb) - (iff->is_64bit ? 12 : 8); |
371 | iff->body_size = iff->body_end - iff->body_pos; |
372 | return 0; |
373 | } |
374 | ret = av_get_packet(pb, pkt, data_size); |
375 | if (ret < 0) |
376 | return ret; |
377 | if (data_size & 1) |
378 | avio_skip(pb, 1); |
379 | pkt->flags |= AV_PKT_FLAG_KEY; |
380 | pkt->stream_index = 0; |
381 | pkt->duration = 588 * s->streams[0]->codecpar->sample_rate / 44100; |
382 | pkt->pos = chunk_pos; |
383 | |
384 | chunk_pos = avio_tell(pb); |
385 | if (chunk_pos >= iff->body_end) |
386 | return 0; |
387 | |
388 | avio_seek(pb, chunk_pos, SEEK_SET); |
389 | return 0; |
390 | |
391 | case ID_FRTE: |
392 | if (data_size < 4) |
393 | return AVERROR_INVALIDDATA; |
394 | s->streams[0]->duration = avio_rb32(pb) * 588LL * s->streams[0]->codecpar->sample_rate / 44100; |
395 | break; |
396 | } |
397 | |
398 | avio_skip(pb, data_size - (avio_tell(pb) - data_pos) + (data_size & 1)); |
399 | } |
400 | |
401 | return ret; |
402 | } |
403 | |
404 | static const uint8_t deep_rgb24[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8}; |
405 | static const uint8_t deep_rgba[] = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8}; |
406 | static const uint8_t deep_bgra[] = {0, 0, 0, 4, 0, 3, 0, 8, 0, 2, 0, 8, 0, 1, 0, 8}; |
407 | static const uint8_t deep_argb[] = {0, 0, 0, 4, 0,17, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8}; |
408 | static const uint8_t deep_abgr[] = {0, 0, 0, 4, 0,17, 0, 8, 0, 3, 0, 8, 0, 2, 0, 8}; |
409 | |
410 | static int iff_read_header(AVFormatContext *s) |
411 | { |
412 | IffDemuxContext *iff = s->priv_data; |
413 | AVIOContext *pb = s->pb; |
414 | AVStream *st; |
415 | uint8_t *buf; |
416 | uint32_t chunk_id; |
417 | uint64_t data_size; |
418 | uint32_t screenmode = 0, num, den; |
419 | unsigned transparency = 0; |
420 | unsigned masking = 0; // no mask |
421 | uint8_t fmt[16]; |
422 | int fmt_size; |
423 | |
424 | st = avformat_new_stream(s, NULL); |
425 | if (!st) |
426 | return AVERROR(ENOMEM); |
427 | |
428 | st->codecpar->channels = 1; |
429 | st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; |
430 | iff->is_64bit = avio_rl32(pb) == ID_FRM8; |
431 | avio_skip(pb, iff->is_64bit ? 8 : 4); |
432 | // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content |
433 | st->codecpar->codec_tag = avio_rl32(pb); |
434 | if (st->codecpar->codec_tag == ID_ANIM) { |
435 | avio_skip(pb, 12); |
436 | } |
437 | iff->bitmap_compression = -1; |
438 | iff->svx8_compression = -1; |
439 | iff->maud_bits = -1; |
440 | iff->maud_compression = -1; |
441 | |
442 | while(!avio_feof(pb)) { |
443 | uint64_t orig_pos; |
444 | int res; |
445 | const char *metadata_tag = NULL; |
446 | int version, nb_comments, i; |
447 | chunk_id = avio_rl32(pb); |
448 | data_size = iff->is_64bit ? avio_rb64(pb) : avio_rb32(pb); |
449 | orig_pos = avio_tell(pb); |
450 | |
451 | switch(chunk_id) { |
452 | case ID_VHDR: |
453 | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
454 | |
455 | if (data_size < 14) |
456 | return AVERROR_INVALIDDATA; |
457 | avio_skip(pb, 12); |
458 | st->codecpar->sample_rate = avio_rb16(pb); |
459 | if (data_size >= 16) { |
460 | avio_skip(pb, 1); |
461 | iff->svx8_compression = avio_r8(pb); |
462 | } |
463 | break; |
464 | |
465 | case ID_MHDR: |
466 | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
467 | |
468 | if (data_size < 32) |
469 | return AVERROR_INVALIDDATA; |
470 | avio_skip(pb, 4); |
471 | iff->maud_bits = avio_rb16(pb); |
472 | avio_skip(pb, 2); |
473 | num = avio_rb32(pb); |
474 | den = avio_rb16(pb); |
475 | if (!den) |
476 | return AVERROR_INVALIDDATA; |
477 | avio_skip(pb, 2); |
478 | st->codecpar->sample_rate = num / den; |
479 | st->codecpar->channels = avio_rb16(pb); |
480 | iff->maud_compression = avio_rb16(pb); |
481 | if (st->codecpar->channels == 1) |
482 | st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; |
483 | else if (st->codecpar->channels == 2) |
484 | st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; |
485 | break; |
486 | |
487 | case ID_ABIT: |
488 | case ID_BODY: |
489 | case ID_DBOD: |
490 | case ID_DSD: |
491 | case ID_DST: |
492 | case ID_MDAT: |
493 | iff->body_pos = avio_tell(pb); |
494 | iff->body_end = iff->body_pos + data_size; |
495 | iff->body_size = data_size; |
496 | if (chunk_id == ID_DST) { |
497 | int ret = read_dst_frame(s, NULL); |
498 | if (ret < 0) |
499 | return ret; |
500 | } |
501 | break; |
502 | |
503 | case ID_CHAN: |
504 | if (data_size < 4) |
505 | return AVERROR_INVALIDDATA; |
506 | if (avio_rb32(pb) < 6) { |
507 | st->codecpar->channels = 1; |
508 | st->codecpar->channel_layout = AV_CH_LAYOUT_MONO; |
509 | } else { |
510 | st->codecpar->channels = 2; |
511 | st->codecpar->channel_layout = AV_CH_LAYOUT_STEREO; |
512 | } |
513 | break; |
514 | |
515 | case ID_CAMG: |
516 | if (data_size < 4) |
517 | return AVERROR_INVALIDDATA; |
518 | screenmode = avio_rb32(pb); |
519 | break; |
520 | |
521 | case ID_CMAP: |
522 | if (data_size < 3 || data_size > 768 || data_size % 3) { |
523 | av_log(s, AV_LOG_ERROR, "Invalid CMAP chunk size %"PRIu64"\n", |
524 | data_size); |
525 | return AVERROR_INVALIDDATA; |
526 | } |
527 | st->codecpar->extradata_size = data_size + IFF_EXTRA_VIDEO_SIZE; |
528 | st->codecpar->extradata = av_malloc(data_size + IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); |
529 | if (!st->codecpar->extradata) |
530 | return AVERROR(ENOMEM); |
531 | if (avio_read(pb, st->codecpar->extradata + IFF_EXTRA_VIDEO_SIZE, data_size) < 0) |
532 | return AVERROR(EIO); |
533 | break; |
534 | |
535 | case ID_BMHD: |
536 | st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
537 | if (data_size <= 8) |
538 | return AVERROR_INVALIDDATA; |
539 | st->codecpar->width = avio_rb16(pb); |
540 | st->codecpar->height = avio_rb16(pb); |
541 | avio_skip(pb, 4); // x, y offset |
542 | st->codecpar->bits_per_coded_sample = avio_r8(pb); |
543 | if (data_size >= 10) |
544 | masking = avio_r8(pb); |
545 | if (data_size >= 11) |
546 | iff->bitmap_compression = avio_r8(pb); |
547 | if (data_size >= 14) { |
548 | avio_skip(pb, 1); // padding |
549 | transparency = avio_rb16(pb); |
550 | } |
551 | if (data_size >= 16) { |
552 | st->sample_aspect_ratio.num = avio_r8(pb); |
553 | st->sample_aspect_ratio.den = avio_r8(pb); |
554 | } |
555 | break; |
556 | |
557 | case ID_ANHD: |
558 | break; |
559 | |
560 | case ID_DPAN: |
561 | avio_skip(pb, 2); |
562 | st->duration = avio_rb16(pb); |
563 | break; |
564 | |
565 | case ID_DPEL: |
566 | if (data_size < 4 || (data_size & 3)) |
567 | return AVERROR_INVALIDDATA; |
568 | if ((fmt_size = avio_read(pb, fmt, sizeof(fmt))) < 0) |
569 | return fmt_size; |
570 | if (fmt_size == sizeof(deep_rgb24) && !memcmp(fmt, deep_rgb24, sizeof(deep_rgb24))) |
571 | st->codecpar->format = AV_PIX_FMT_RGB24; |
572 | else if (fmt_size == sizeof(deep_rgba) && !memcmp(fmt, deep_rgba, sizeof(deep_rgba))) |
573 | st->codecpar->format = AV_PIX_FMT_RGBA; |
574 | else if (fmt_size == sizeof(deep_bgra) && !memcmp(fmt, deep_bgra, sizeof(deep_bgra))) |
575 | st->codecpar->format = AV_PIX_FMT_BGRA; |
576 | else if (fmt_size == sizeof(deep_argb) && !memcmp(fmt, deep_argb, sizeof(deep_argb))) |
577 | st->codecpar->format = AV_PIX_FMT_ARGB; |
578 | else if (fmt_size == sizeof(deep_abgr) && !memcmp(fmt, deep_abgr, sizeof(deep_abgr))) |
579 | st->codecpar->format = AV_PIX_FMT_ABGR; |
580 | else { |
581 | avpriv_request_sample(s, "color format %.16s", fmt); |
582 | return AVERROR_PATCHWELCOME; |
583 | } |
584 | break; |
585 | |
586 | case ID_DGBL: |
587 | st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; |
588 | if (data_size < 8) |
589 | return AVERROR_INVALIDDATA; |
590 | st->codecpar->width = avio_rb16(pb); |
591 | st->codecpar->height = avio_rb16(pb); |
592 | iff->bitmap_compression = avio_rb16(pb); |
593 | st->sample_aspect_ratio.num = avio_r8(pb); |
594 | st->sample_aspect_ratio.den = avio_r8(pb); |
595 | st->codecpar->bits_per_coded_sample = 24; |
596 | break; |
597 | |
598 | case ID_DLOC: |
599 | if (data_size < 4) |
600 | return AVERROR_INVALIDDATA; |
601 | st->codecpar->width = avio_rb16(pb); |
602 | st->codecpar->height = avio_rb16(pb); |
603 | break; |
604 | |
605 | case ID_TVDC: |
606 | if (data_size < sizeof(iff->tvdc)) |
607 | return AVERROR_INVALIDDATA; |
608 | res = avio_read(pb, iff->tvdc, sizeof(iff->tvdc)); |
609 | if (res < 0) |
610 | return res; |
611 | break; |
612 | |
613 | case ID_ANNO: |
614 | case ID_TEXT: metadata_tag = "comment"; break; |
615 | case ID_AUTH: metadata_tag = "artist"; break; |
616 | case ID_COPYRIGHT: metadata_tag = "copyright"; break; |
617 | case ID_NAME: metadata_tag = "title"; break; |
618 | |
619 | /* DSD tags */ |
620 | |
621 | case MKTAG('F','V','E','R'): |
622 | if (data_size < 4) |
623 | return AVERROR_INVALIDDATA; |
624 | version = avio_rb32(pb); |
625 | av_log(s, AV_LOG_DEBUG, "DSIFF v%d.%d.%d.%d\n",version >> 24, (version >> 16) & 0xFF, (version >> 8) & 0xFF, version & 0xFF); |
626 | st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO; |
627 | break; |
628 | |
629 | case MKTAG('D','I','I','N'): |
630 | res = parse_dsd_diin(s, st, orig_pos + data_size); |
631 | if (res < 0) |
632 | return res; |
633 | break; |
634 | |
635 | case MKTAG('P','R','O','P'): |
636 | if (data_size < 4) |
637 | return AVERROR_INVALIDDATA; |
638 | if (avio_rl32(pb) != MKTAG('S','N','D',' ')) { |
639 | avpriv_request_sample(s, "unknown property type"); |
640 | break; |
641 | } |
642 | res = parse_dsd_prop(s, st, orig_pos + data_size); |
643 | if (res < 0) |
644 | return res; |
645 | break; |
646 | |
647 | case MKTAG('C','O','M','T'): |
648 | if (data_size < 2) |
649 | return AVERROR_INVALIDDATA; |
650 | nb_comments = avio_rb16(pb); |
651 | for (i = 0; i < nb_comments; i++) { |
652 | int year, mon, day, hour, min, type, ref; |
653 | char tmp[24]; |
654 | const char *tag; |
655 | int metadata_size; |
656 | |
657 | year = avio_rb16(pb); |
658 | mon = avio_r8(pb); |
659 | day = avio_r8(pb); |
660 | hour = avio_r8(pb); |
661 | min = avio_r8(pb); |
662 | snprintf(tmp, sizeof(tmp), "%04d-%02d-%02d %02d:%02d", year, mon, day, hour, min); |
663 | av_dict_set(&st->metadata, "comment_time", tmp, 0); |
664 | |
665 | type = avio_rb16(pb); |
666 | ref = avio_rb16(pb); |
667 | switch (type) { |
668 | case 1: |
669 | if (!i) |
670 | tag = "channel_comment"; |
671 | else { |
672 | snprintf(tmp, sizeof(tmp), "channel%d_comment", ref); |
673 | tag = tmp; |
674 | } |
675 | break; |
676 | case 2: |
677 | tag = ref < FF_ARRAY_ELEMS(dsd_source_comment) ? dsd_source_comment[ref] : "source_comment"; |
678 | break; |
679 | case 3: |
680 | tag = ref < FF_ARRAY_ELEMS(dsd_history_comment) ? dsd_history_comment[ref] : "file_history"; |
681 | break; |
682 | default: |
683 | tag = "comment"; |
684 | } |
685 | |
686 | metadata_size = avio_rb32(pb); |
687 | if ((res = get_metadata(s, tag, metadata_size)) < 0) { |
688 | av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", tag); |
689 | return res; |
690 | } |
691 | |
692 | if (metadata_size & 1) |
693 | avio_skip(pb, 1); |
694 | } |
695 | break; |
696 | } |
697 | |
698 | if (metadata_tag) { |
699 | if ((res = get_metadata(s, metadata_tag, data_size)) < 0) { |
700 | av_log(s, AV_LOG_ERROR, "cannot allocate metadata tag %s!\n", metadata_tag); |
701 | return res; |
702 | } |
703 | } |
704 | avio_skip(pb, data_size - (avio_tell(pb) - orig_pos) + (data_size & 1)); |
705 | } |
706 | |
707 | if (st->codecpar->codec_tag == ID_ANIM) |
708 | avio_seek(pb, 12, SEEK_SET); |
709 | else |
710 | avio_seek(pb, iff->body_pos, SEEK_SET); |
711 | |
712 | switch(st->codecpar->codec_type) { |
713 | case AVMEDIA_TYPE_AUDIO: |
714 | avpriv_set_pts_info(st, 32, 1, st->codecpar->sample_rate); |
715 | |
716 | if (st->codecpar->codec_tag == ID_16SV) |
717 | st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE_PLANAR; |
718 | else if (st->codecpar->codec_tag == ID_MAUD) { |
719 | if (iff->maud_bits == 8 && !iff->maud_compression) { |
720 | st->codecpar->codec_id = AV_CODEC_ID_PCM_U8; |
721 | } else if (iff->maud_bits == 16 && !iff->maud_compression) { |
722 | st->codecpar->codec_id = AV_CODEC_ID_PCM_S16BE; |
723 | } else if (iff->maud_bits == 8 && iff->maud_compression == 2) { |
724 | st->codecpar->codec_id = AV_CODEC_ID_PCM_ALAW; |
725 | } else if (iff->maud_bits == 8 && iff->maud_compression == 3) { |
726 | st->codecpar->codec_id = AV_CODEC_ID_PCM_MULAW; |
727 | } else { |
728 | avpriv_request_sample(s, "compression %d and bit depth %d", iff->maud_compression, iff->maud_bits); |
729 | return AVERROR_PATCHWELCOME; |
730 | } |
731 | } else if (st->codecpar->codec_tag != ID_DSD && |
732 | st->codecpar->codec_tag != ID_DST) { |
733 | switch (iff->svx8_compression) { |
734 | case COMP_NONE: |
735 | st->codecpar->codec_id = AV_CODEC_ID_PCM_S8_PLANAR; |
736 | break; |
737 | case COMP_FIB: |
738 | st->codecpar->codec_id = AV_CODEC_ID_8SVX_FIB; |
739 | break; |
740 | case COMP_EXP: |
741 | st->codecpar->codec_id = AV_CODEC_ID_8SVX_EXP; |
742 | break; |
743 | default: |
744 | av_log(s, AV_LOG_ERROR, |
745 | "Unknown SVX8 compression method '%d'\n", iff->svx8_compression); |
746 | return -1; |
747 | } |
748 | } |
749 | |
750 | st->codecpar->bits_per_coded_sample = av_get_bits_per_sample(st->codecpar->codec_id); |
751 | st->codecpar->bit_rate = (int64_t)st->codecpar->channels * st->codecpar->sample_rate * st->codecpar->bits_per_coded_sample; |
752 | st->codecpar->block_align = st->codecpar->channels * st->codecpar->bits_per_coded_sample; |
753 | if (st->codecpar->codec_tag == ID_DSD && st->codecpar->block_align <= 0) |
754 | return AVERROR_INVALIDDATA; |
755 | break; |
756 | |
757 | case AVMEDIA_TYPE_VIDEO: |
758 | iff->bpp = st->codecpar->bits_per_coded_sample; |
759 | if (st->codecpar->codec_tag == ID_ANIM) |
760 | avpriv_set_pts_info(st, 32, 1, 60); |
761 | if ((screenmode & 0x800 /* Hold And Modify */) && iff->bpp <= 8) { |
762 | iff->ham = iff->bpp > 6 ? 6 : 4; |
763 | st->codecpar->bits_per_coded_sample = 24; |
764 | } |
765 | iff->flags = (screenmode & 0x80 /* Extra HalfBrite */) && iff->bpp <= 8; |
766 | iff->masking = masking; |
767 | iff->transparency = transparency; |
768 | |
769 | if (!st->codecpar->extradata) { |
770 | st->codecpar->extradata_size = IFF_EXTRA_VIDEO_SIZE; |
771 | st->codecpar->extradata = av_malloc(IFF_EXTRA_VIDEO_SIZE + AV_INPUT_BUFFER_PADDING_SIZE); |
772 | if (!st->codecpar->extradata) |
773 | return AVERROR(ENOMEM); |
774 | } |
775 | av_assert0(st->codecpar->extradata_size >= IFF_EXTRA_VIDEO_SIZE); |
776 | buf = st->codecpar->extradata; |
777 | bytestream_put_be16(&buf, IFF_EXTRA_VIDEO_SIZE); |
778 | bytestream_put_byte(&buf, iff->bitmap_compression); |
779 | bytestream_put_byte(&buf, iff->bpp); |
780 | bytestream_put_byte(&buf, iff->ham); |
781 | bytestream_put_byte(&buf, iff->flags); |
782 | bytestream_put_be16(&buf, iff->transparency); |
783 | bytestream_put_byte(&buf, iff->masking); |
784 | bytestream_put_buffer(&buf, iff->tvdc, sizeof(iff->tvdc)); |
785 | st->codecpar->codec_id = AV_CODEC_ID_IFF_ILBM; |
786 | break; |
787 | default: |
788 | return -1; |
789 | } |
790 | |
791 | return 0; |
792 | } |
793 | |
794 | static unsigned get_anim_duration(uint8_t *buf, int size) |
795 | { |
796 | GetByteContext gb; |
797 | |
798 | bytestream2_init(&gb, buf, size); |
799 | bytestream2_skip(&gb, 4); |
800 | while (bytestream2_get_bytes_left(&gb) > 8) { |
801 | unsigned chunk = bytestream2_get_le32(&gb); |
802 | unsigned size = bytestream2_get_be32(&gb); |
803 | |
804 | if (chunk == ID_ANHD) { |
805 | if (size < 40) |
806 | break; |
807 | bytestream2_skip(&gb, 14); |
808 | return bytestream2_get_be32(&gb); |
809 | } else { |
810 | bytestream2_skip(&gb, size + size & 1); |
811 | } |
812 | } |
813 | return 10; |
814 | } |
815 | |
816 | static int iff_read_packet(AVFormatContext *s, |
817 | AVPacket *pkt) |
818 | { |
819 | IffDemuxContext *iff = s->priv_data; |
820 | AVIOContext *pb = s->pb; |
821 | AVStream *st = s->streams[0]; |
822 | int ret; |
823 | int64_t pos = avio_tell(pb); |
824 | |
825 | if (avio_feof(pb)) |
826 | return AVERROR_EOF; |
827 | if (st->codecpar->codec_tag != ID_ANIM && pos >= iff->body_end) |
828 | return AVERROR_EOF; |
829 | |
830 | if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { |
831 | if (st->codecpar->codec_tag == ID_DSD || st->codecpar->codec_tag == ID_MAUD) { |
832 | ret = av_get_packet(pb, pkt, FFMIN(iff->body_end - pos, 1024 * st->codecpar->block_align)); |
833 | } else if (st->codecpar->codec_tag == ID_DST) { |
834 | return read_dst_frame(s, pkt); |
835 | } else { |
836 | if (iff->body_size > INT_MAX) |
837 | return AVERROR_INVALIDDATA; |
838 | ret = av_get_packet(pb, pkt, iff->body_size); |
839 | } |
840 | } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && |
841 | st->codecpar->codec_tag == ID_ANIM) { |
842 | uint64_t data_size, orig_pos; |
843 | uint32_t chunk_id, chunk_id2; |
844 | |
845 | while (!avio_feof(pb)) { |
846 | if (avio_feof(pb)) |
847 | return AVERROR_EOF; |
848 | |
849 | orig_pos = avio_tell(pb); |
850 | chunk_id = avio_rl32(pb); |
851 | data_size = avio_rb32(pb); |
852 | chunk_id2 = avio_rl32(pb); |
853 | |
854 | if (chunk_id == ID_FORM && |
855 | chunk_id2 == ID_ILBM) { |
856 | avio_skip(pb, -4); |
857 | break; |
858 | } else if (chunk_id == ID_FORM && |
859 | chunk_id2 == ID_ANIM) { |
860 | continue; |
861 | } else { |
862 | avio_skip(pb, data_size); |
863 | } |
864 | } |
865 | ret = av_get_packet(pb, pkt, data_size); |
866 | pkt->pos = orig_pos; |
867 | pkt->duration = get_anim_duration(pkt->data, pkt->size); |
868 | if (pos == 12) |
869 | pkt->flags |= AV_PKT_FLAG_KEY; |
870 | } else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && |
871 | st->codecpar->codec_tag != ID_ANIM) { |
872 | ret = av_get_packet(pb, pkt, iff->body_size); |
873 | pkt->pos = pos; |
874 | if (pos == iff->body_pos) |
875 | pkt->flags |= AV_PKT_FLAG_KEY; |
876 | } else { |
877 | av_assert0(0); |
878 | } |
879 | |
880 | if (ret < 0) |
881 | return ret; |
882 | pkt->stream_index = 0; |
883 | return ret; |
884 | } |
885 | |
886 | AVInputFormat ff_iff_demuxer = { |
887 | .name = "iff", |
888 | .long_name = NULL_IF_CONFIG_SMALL("IFF (Interchange File Format)"), |
889 | .priv_data_size = sizeof(IffDemuxContext), |
890 | .read_probe = iff_probe, |
891 | .read_header = iff_read_header, |
892 | .read_packet = iff_read_packet, |
893 | .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, |
894 | }; |
895 |