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