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>
6 * This file is part of FFmpeg.
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.
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.
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
26 * by Jaikrishnan Menon
27 * for more information on the .iff file format, visit:
28 * http://wiki.multimedia.cx/index.php?title=IFF
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"
40 #include "avio_internal.h"
45 #define ID_8SVX MKTAG('8','S','V','X')
46 #define ID_16SV MKTAG('1','6','S','V')
47 #define ID_MAUD MKTAG('M','A','U','D')
48 #define ID_MHDR MKTAG('M','H','D','R')
49 #define ID_MDAT MKTAG('M','D','A','T')
50 #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 #define ID_CHAN MKTAG('C','H','A','N')
54 #define ID_PBM MKTAG('P','B','M',' ')
55 #define ID_ILBM MKTAG('I','L','B','M')
56 #define ID_BMHD MKTAG('B','M','H','D')
57 #define ID_DGBL MKTAG('D','G','B','L')
58 #define ID_CAMG MKTAG('C','A','M','G')
59 #define ID_CMAP MKTAG('C','M','A','P')
60 #define ID_ACBM MKTAG('A','C','B','M')
61 #define ID_DEEP MKTAG('D','E','E','P')
62 #define ID_RGB8 MKTAG('R','G','B','8')
63 #define ID_RGBN MKTAG('R','G','B','N')
64 #define ID_DSD MKTAG('D','S','D',' ')
65 #define ID_DST MKTAG('D','S','T',' ')
66 #define ID_DSTC MKTAG('D','S','T','C')
67 #define ID_DSTF MKTAG('D','S','T','F')
68 #define ID_FRTE MKTAG('F','R','T','E')
69 #define ID_ANIM MKTAG('A','N','I','M')
70 #define ID_ANHD MKTAG('A','N','H','D')
71 #define ID_DLTA MKTAG('D','L','T','A')
72 #define ID_DPAN MKTAG('D','P','A','N')
74 #define ID_FORM MKTAG('F','O','R','M')
75 #define ID_FRM8 MKTAG('F','R','M','8')
76 #define ID_ANNO MKTAG('A','N','N','O')
77 #define ID_AUTH MKTAG('A','U','T','H')
78 #define ID_CHRS MKTAG('C','H','R','S')
79 #define ID_COPYRIGHT MKTAG('(','c',')',' ')
80 #define ID_CSET MKTAG('C','S','E','T')
81 #define ID_FVER MKTAG('F','V','E','R')
82 #define ID_NAME MKTAG('N','A','M','E')
83 #define ID_TEXT MKTAG('T','E','X','T')
84 #define ID_ABIT MKTAG('A','B','I','T')
85 #define ID_BODY MKTAG('B','O','D','Y')
86 #define ID_DBOD MKTAG('D','B','O','D')
87 #define ID_DPEL MKTAG('D','P','E','L')
88 #define ID_DLOC MKTAG('D','L','O','C')
89 #define ID_TVDC MKTAG('T','V','D','C')
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.
103 #define IFF_EXTRA_VIDEO_SIZE 41
109 } svx8_compression_type
;
111 typedef struct IffDemuxContext
{
112 int is_64bit
; ///< chunk size is 64-bit
118 svx8_compression_type svx8_compression
;
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
129 int audio_stream_index
;
130 int video_stream_index
;
133 /* Metadata string read */
134 static int get_metadata(AVFormatContext
*s
,
135 const char *const tag
,
136 const unsigned data_size
)
138 uint8_t *buf
= ((data_size
+ 1) == 0) ? NULL
: av_malloc(data_size
+ 1);
142 return AVERROR(ENOMEM
);
144 if ((res
= ffio_read_size(s
->pb
, buf
, data_size
)) < 0) {
149 av_dict_set(&s
->metadata
, tag
, buf
, AV_DICT_DONT_STRDUP_VAL
);
153 static int iff_probe(const AVProbeData
*p
)
155 const uint8_t *d
= p
->buf
;
157 if ( (AV_RL32(d
) == ID_FORM
&&
158 (AV_RL32(d
+8) == ID_8SVX
||
159 AV_RL32(d
+8) == ID_16SV
||
160 AV_RL32(d
+8) == ID_MAUD
||
161 AV_RL32(d
+8) == ID_PBM
||
162 AV_RL32(d
+8) == ID_ACBM
||
163 AV_RL32(d
+8) == ID_DEEP
||
164 AV_RL32(d
+8) == ID_ILBM
||
165 AV_RL32(d
+8) == ID_RGB8
||
166 AV_RL32(d
+8) == ID_ANIM
||
167 AV_RL32(d
+8) == ID_RGBN
)) ||
168 (AV_RL32(d
) == ID_FRM8
&& AV_RL32(d
+12) == ID_DSD
))
169 return AVPROBE_SCORE_MAX
;
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 },
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',' ')
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
};
194 AVChannelLayout layout
;
195 const uint32_t * dsd_layout
;
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
},
204 static const AVChannelLayout dsd_loudspeaker_config
[] = {
205 AV_CHANNEL_LAYOUT_STEREO
,
207 AV_CHANNEL_LAYOUT_5POINT0
, AV_CHANNEL_LAYOUT_5POINT1
,
210 static const char * dsd_source_comment
[] = {
211 "dsd_source_comment",
212 "analogue_source_comment",
213 "pcm_source_comment",
216 static const char * dsd_history_comment
[] = {
224 static int parse_dsd_diin(AVFormatContext
*s
, AVStream
*st
, uint64_t eof
)
226 AVIOContext
*pb
= s
->pb
;
228 while (av_sat_add64(avio_tell(pb
), 12) <= eof
&& !avio_feof(pb
)) {
229 uint32_t tag
= avio_rl32(pb
);
230 uint64_t size
= avio_rb64(pb
);
231 uint64_t orig_pos
= avio_tell(pb
);
232 const char * metadata_tag
= NULL
;
234 if (size
>= INT64_MAX
)
235 return AVERROR_INVALIDDATA
;
238 case MKTAG('D','I','A','R'): metadata_tag
= "artist"; break;
239 case MKTAG('D','I','T','I'): metadata_tag
= "title"; break;
242 if (metadata_tag
&& size
> 4) {
243 unsigned int tag_size
= avio_rb32(pb
);
244 int ret
= get_metadata(s
, metadata_tag
, FFMIN(tag_size
, size
- 4));
246 av_log(s
, AV_LOG_ERROR
, "cannot allocate metadata tag %s!\n", metadata_tag
);
251 avio_skip(pb
, size
- (avio_tell(pb
) - orig_pos
) + (size
& 1));
257 static int parse_dsd_prop(AVFormatContext
*s
, AVStream
*st
, uint64_t eof
)
259 AVIOContext
*pb
= s
->pb
;
261 int hour
, min
, sec
, i
, ret
, config
;
263 ID3v2ExtraMeta
*id3v2_extra_meta
;
265 while (av_sat_add64(avio_tell(pb
), 12) <= eof
&& !avio_feof(pb
)) {
266 uint32_t tag
= avio_rl32(pb
);
267 uint64_t size
= avio_rb64(pb
);
268 uint64_t orig_pos
= avio_tell(pb
);
270 if (size
>= INT64_MAX
)
271 return AVERROR_INVALIDDATA
;
274 case MKTAG('A','B','S','S'):
276 return AVERROR_INVALIDDATA
;
277 hour
= avio_rb16(pb
);
280 snprintf(abss
, sizeof(abss
), "%02dh:%02dm:%02ds:%d", hour
, min
, sec
, avio_rb32(pb
));
281 av_dict_set(&st
->metadata
, "absolute_start_time", abss
, 0);
284 case MKTAG('C','H','N','L'):
286 return AVERROR_INVALIDDATA
;
287 st
->codecpar
->ch_layout
.order
= AV_CHANNEL_ORDER_UNSPEC
;
288 st
->codecpar
->ch_layout
.nb_channels
= avio_rb16(pb
);
289 if (size
< 2 + st
->codecpar
->ch_layout
.nb_channels
* 4 || !st
->codecpar
->ch_layout
.nb_channels
)
290 return AVERROR_INVALIDDATA
;
291 if (st
->codecpar
->ch_layout
.nb_channels
> FF_ARRAY_ELEMS(dsd_layout
)) {
292 avpriv_request_sample(s
, "channel layout");
295 for (i
= 0; i
< st
->codecpar
->ch_layout
.nb_channels
; i
++)
296 dsd_layout
[i
] = avio_rl32(pb
);
297 for (i
= 0; i
< FF_ARRAY_ELEMS(dsd_channel_layout
); i
++) {
298 const DSDLayoutDesc
* d
= &dsd_channel_layout
[i
];
299 if (d
->layout
.nb_channels
== st
->codecpar
->ch_layout
.nb_channels
&&
300 !memcmp(d
->dsd_layout
, dsd_layout
, d
->layout
.nb_channels
* sizeof(uint32_t))) {
301 st
->codecpar
->ch_layout
= d
->layout
;
307 case MKTAG('C','M','P','R'):
309 return AVERROR_INVALIDDATA
;
310 st
->codecpar
->codec_tag
= tag
= avio_rl32(pb
);
311 st
->codecpar
->codec_id
= ff_codec_get_id(dsd_codec_tags
, tag
);
312 if (!st
->codecpar
->codec_id
) {
313 av_log(s
, AV_LOG_ERROR
, "'%s' compression is not supported\n",
315 return AVERROR_PATCHWELCOME
;
319 case MKTAG('F','S',' ',' '):
321 return AVERROR_INVALIDDATA
;
322 st
->codecpar
->sample_rate
= avio_rb32(pb
) / 8;
325 case MKTAG('I','D','3',' '):
326 ff_id3v2_read(s
, ID3v2_DEFAULT_MAGIC
, &id3v2_extra_meta
, size
);
327 if (id3v2_extra_meta
) {
328 if ((ret
= ff_id3v2_parse_apic(s
, id3v2_extra_meta
)) < 0 ||
329 (ret
= ff_id3v2_parse_chapters(s
, id3v2_extra_meta
)) < 0) {
330 ff_id3v2_free_extra_meta(&id3v2_extra_meta
);
333 ff_id3v2_free_extra_meta(&id3v2_extra_meta
);
336 if (size
< avio_tell(pb
) - orig_pos
) {
337 av_log(s
, AV_LOG_ERROR
, "id3 exceeds chunk size\n");
338 return AVERROR_INVALIDDATA
;
342 case MKTAG('L','S','C','O'):
344 return AVERROR_INVALIDDATA
;
345 config
= avio_rb16(pb
);
346 if (config
!= 0xFFFF) {
347 if (config
< FF_ARRAY_ELEMS(dsd_loudspeaker_config
))
348 st
->codecpar
->ch_layout
= dsd_loudspeaker_config
[config
];
349 if (!st
->codecpar
->ch_layout
.nb_channels
)
350 avpriv_request_sample(s
, "loudspeaker configuration %d", config
);
355 avio_skip(pb
, size
- (avio_tell(pb
) - orig_pos
) + (size
& 1));
361 static int read_dst_frame(AVFormatContext
*s
, AVPacket
*pkt
)
363 IffDemuxContext
*iff
= s
->priv_data
;
364 AVIOContext
*pb
= s
->pb
;
366 uint64_t chunk_pos
, data_pos
, data_size
;
367 int ret
= AVERROR_EOF
;
369 if (s
->nb_streams
< 1)
370 return AVERROR_INVALIDDATA
;
372 while (!avio_feof(pb
)) {
373 chunk_pos
= avio_tell(pb
);
374 if (chunk_pos
>= iff
->body_end
)
377 chunk_id
= avio_rl32(pb
);
378 data_size
= iff
->is_64bit
? avio_rb64(pb
) : avio_rb32(pb
);
379 data_pos
= avio_tell(pb
);
381 if (data_size
< 1 || data_size
>= INT64_MAX
)
382 return AVERROR_INVALIDDATA
;
387 iff
->body_pos
= avio_tell(pb
) - (iff
->is_64bit
? 12 : 8);
388 iff
->body_size
= iff
->body_end
- iff
->body_pos
;
391 ret
= av_get_packet(pb
, pkt
, data_size
);
396 pkt
->flags
|= AV_PKT_FLAG_KEY
;
397 pkt
->stream_index
= iff
->audio_stream_index
;
398 pkt
->duration
= s
->streams
[0]->codecpar
->sample_rate
/ 75;
399 pkt
->pos
= chunk_pos
;
401 chunk_pos
= avio_tell(pb
);
402 if (chunk_pos
>= iff
->body_end
)
405 avio_seek(pb
, chunk_pos
, SEEK_SET
);
410 return AVERROR_INVALIDDATA
;
411 s
->streams
[0]->duration
= avio_rb32(pb
) * (uint64_t)s
->streams
[0]->codecpar
->sample_rate
/ 75;
416 avio_skip(pb
, data_size
- (avio_tell(pb
) - data_pos
) + (data_size
& 1));
422 static const uint8_t deep_rgb24
[] = {0, 0, 0, 3, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
423 static const uint8_t deep_rgba
[] = {0, 0, 0, 4, 0, 1, 0, 8, 0, 2, 0, 8, 0, 3, 0, 8};
424 static const uint8_t deep_bgra
[] = {0, 0, 0, 4, 0, 3, 0, 8, 0, 2, 0, 8, 0, 1, 0, 8};
425 static const uint8_t deep_argb
[] = {0, 0, 0, 4, 0,17, 0, 8, 0, 1, 0, 8, 0, 2, 0, 8};
426 static const uint8_t deep_abgr
[] = {0, 0, 0, 4, 0,17, 0, 8, 0, 3, 0, 8, 0, 2, 0, 8};
428 static AVStream
* new_stream(AVFormatContext
*s
, AVStream
**st_ptr
, int *index_ptr
, enum AVMediaType codec_type
)
431 *st_ptr
= avformat_new_stream(s
, NULL
);
434 (*st_ptr
)->codecpar
->codec_type
= codec_type
;
435 (*index_ptr
) = (*st_ptr
)->index
;
440 static int iff_read_header(AVFormatContext
*s
)
442 IffDemuxContext
*iff
= s
->priv_data
;
443 AVIOContext
*pb
= s
->pb
;
444 AVStream
*sta
= NULL
, *stv
= NULL
;
448 uint32_t screenmode
= 0, num
, den
;
449 unsigned transparency
= 0;
450 unsigned masking
= 0; // no mask
454 iff
->audio_stream_index
= -1;
455 iff
->video_stream_index
= -1;
456 iff
->is_64bit
= avio_rl32(pb
) == ID_FRM8
;
457 avio_skip(pb
, iff
->is_64bit
? 8 : 4);
458 iff
->form_tag
= avio_rl32(pb
);
459 if (iff
->form_tag
== ID_ANIM
) {
462 iff
->bitmap_compression
= -1;
463 iff
->svx8_compression
= -1;
465 iff
->maud_compression
= -1;
467 while(!avio_feof(pb
)) {
470 const char *metadata_tag
= NULL
;
471 int version
, nb_comments
, i
;
472 chunk_id
= avio_rl32(pb
);
473 data_size
= iff
->is_64bit
? avio_rb64(pb
) : avio_rb32(pb
);
474 orig_pos
= avio_tell(pb
);
476 if (data_size
>= INT64_MAX
)
477 return AVERROR_INVALIDDATA
;
482 return AVERROR_INVALIDDATA
;
483 if (!new_stream(s
, &sta
, &iff
->audio_stream_index
, AVMEDIA_TYPE_AUDIO
))
484 return AVERROR(ENOMEM
);
486 sta
->codecpar
->sample_rate
= avio_rb16(pb
);
487 if (data_size
>= 16) {
489 iff
->svx8_compression
= avio_r8(pb
);
491 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
496 return AVERROR_INVALIDDATA
;
497 if (!new_stream(s
, &sta
, &iff
->audio_stream_index
, AVMEDIA_TYPE_AUDIO
))
498 return AVERROR(ENOMEM
);
500 iff
->maud_bits
= avio_rb16(pb
);
505 return AVERROR_INVALIDDATA
;
507 sta
->codecpar
->sample_rate
= num
/ den
;
508 sta
->codecpar
->ch_layout
.order
= AV_CHANNEL_ORDER_UNSPEC
;
509 sta
->codecpar
->ch_layout
.nb_channels
= avio_rb16(pb
);
510 iff
->maud_compression
= avio_rb16(pb
);
511 if (sta
->codecpar
->ch_layout
.nb_channels
== 1)
512 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
513 else if (sta
->codecpar
->ch_layout
.nb_channels
== 2)
514 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_STEREO
;
515 else if (sta
->codecpar
->ch_layout
.nb_channels
== 0)
516 return AVERROR_INVALIDDATA
;
525 iff
->body_pos
= avio_tell(pb
);
526 if (iff
->body_pos
< 0 || iff
->body_pos
+ data_size
> INT64_MAX
)
527 return AVERROR_INVALIDDATA
;
529 iff
->body_end
= iff
->body_pos
+ data_size
;
530 iff
->body_size
= data_size
;
531 if (chunk_id
== ID_DST
) {
532 int ret
= read_dst_frame(s
, NULL
);
540 return AVERROR_INVALIDDATA
;
542 return AVERROR_INVALIDDATA
;
543 if (avio_rb32(pb
) < 6) {
544 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
546 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_STEREO
;
552 return AVERROR_INVALIDDATA
;
553 screenmode
= avio_rb32(pb
);
557 if (data_size
< 3 || data_size
> 768 || data_size
% 3) {
558 av_log(s
, AV_LOG_ERROR
, "Invalid CMAP chunk size %"PRIu64
"\n",
560 return AVERROR_INVALIDDATA
;
563 return AVERROR_INVALIDDATA
;
564 res
= ff_alloc_extradata(stv
->codecpar
,
565 data_size
+ IFF_EXTRA_VIDEO_SIZE
);
568 if ((res
= avio_read(pb
, stv
->codecpar
->extradata
+ IFF_EXTRA_VIDEO_SIZE
, data_size
)) < 0) {
569 av_freep(&stv
->codecpar
->extradata
);
570 stv
->codecpar
->extradata_size
= 0;
577 return AVERROR_INVALIDDATA
;
578 if (!new_stream(s
, &stv
, &iff
->video_stream_index
, AVMEDIA_TYPE_VIDEO
))
579 return AVERROR(ENOMEM
);
580 stv
->codecpar
->width
= avio_rb16(pb
);
581 stv
->codecpar
->height
= avio_rb16(pb
);
582 avio_skip(pb
, 4); // x, y offset
583 stv
->codecpar
->bits_per_coded_sample
= avio_r8(pb
);
585 masking
= avio_r8(pb
);
587 iff
->bitmap_compression
= avio_r8(pb
);
588 if (data_size
>= 14) {
589 avio_skip(pb
, 1); // padding
590 transparency
= avio_rb16(pb
);
592 if (data_size
>= 16) {
593 stv
->sample_aspect_ratio
.num
= avio_r8(pb
);
594 stv
->sample_aspect_ratio
.den
= avio_r8(pb
);
603 return AVERROR_INVALIDDATA
;
605 stv
->duration
= avio_rb16(pb
);
609 if (data_size
< 4 || (data_size
& 3))
610 return AVERROR_INVALIDDATA
;
612 return AVERROR_INVALIDDATA
;
613 if ((fmt_size
= avio_read(pb
, fmt
, sizeof(fmt
))) < 0)
615 if (fmt_size
== sizeof(deep_rgb24
) && !memcmp(fmt
, deep_rgb24
, sizeof(deep_rgb24
)))
616 stv
->codecpar
->format
= AV_PIX_FMT_RGB24
;
617 else if (fmt_size
== sizeof(deep_rgba
) && !memcmp(fmt
, deep_rgba
, sizeof(deep_rgba
)))
618 stv
->codecpar
->format
= AV_PIX_FMT_RGBA
;
619 else if (fmt_size
== sizeof(deep_bgra
) && !memcmp(fmt
, deep_bgra
, sizeof(deep_bgra
)))
620 stv
->codecpar
->format
= AV_PIX_FMT_BGRA
;
621 else if (fmt_size
== sizeof(deep_argb
) && !memcmp(fmt
, deep_argb
, sizeof(deep_argb
)))
622 stv
->codecpar
->format
= AV_PIX_FMT_ARGB
;
623 else if (fmt_size
== sizeof(deep_abgr
) && !memcmp(fmt
, deep_abgr
, sizeof(deep_abgr
)))
624 stv
->codecpar
->format
= AV_PIX_FMT_ABGR
;
626 avpriv_request_sample(s
, "color format %.16s", fmt
);
627 return AVERROR_PATCHWELCOME
;
633 return AVERROR_INVALIDDATA
;
634 if (!new_stream(s
, &stv
, &iff
->video_stream_index
, AVMEDIA_TYPE_VIDEO
))
635 return AVERROR(ENOMEM
);
636 stv
->codecpar
->width
= avio_rb16(pb
);
637 stv
->codecpar
->height
= avio_rb16(pb
);
638 iff
->bitmap_compression
= avio_rb16(pb
);
639 stv
->sample_aspect_ratio
.num
= avio_r8(pb
);
640 stv
->sample_aspect_ratio
.den
= avio_r8(pb
);
641 stv
->codecpar
->bits_per_coded_sample
= 24;
646 return AVERROR_INVALIDDATA
;
647 if (!new_stream(s
, &stv
, &iff
->video_stream_index
, AVMEDIA_TYPE_VIDEO
))
648 return AVERROR(ENOMEM
);
649 stv
->codecpar
->width
= avio_rb16(pb
);
650 stv
->codecpar
->height
= avio_rb16(pb
);
654 if (data_size
< sizeof(iff
->tvdc
))
655 return AVERROR_INVALIDDATA
;
656 res
= avio_read(pb
, iff
->tvdc
, sizeof(iff
->tvdc
));
661 case MKTAG('S','X','H','D'):
663 return AVERROR_INVALIDDATA
;
664 if (!new_stream(s
, &sta
, &iff
->audio_stream_index
, AVMEDIA_TYPE_AUDIO
))
665 return AVERROR(ENOMEM
);
666 sta
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
667 switch(avio_r8(pb
)) {
669 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_S8_PLANAR
;
672 avpriv_request_sample(s
, "sound bitdepth");
673 return AVERROR_INVALIDDATA
;
677 avpriv_request_sample(s
, "sound compression");
678 return AVERROR_INVALIDDATA
;
681 sta
->codecpar
->ch_layout
.nb_channels
= avio_r8(pb
);
682 if (!sta
->codecpar
->ch_layout
.nb_channels
)
683 return AVERROR_INVALIDDATA
;
684 if (sta
->codecpar
->ch_layout
.nb_channels
== 1)
685 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_MONO
;
686 else if (sta
->codecpar
->ch_layout
.nb_channels
== 2)
687 sta
->codecpar
->ch_layout
= (AVChannelLayout
)AV_CHANNEL_LAYOUT_STEREO
;
688 sta
->codecpar
->sample_rate
= avio_rb32(pb
);
689 avpriv_set_pts_info(sta
, 64, 1, sta
->codecpar
->sample_rate
);
694 case ID_TEXT
: metadata_tag
= "comment"; break;
695 case ID_AUTH
: metadata_tag
= "artist"; break;
696 case ID_COPYRIGHT
: metadata_tag
= "copyright"; break;
697 case ID_NAME
: metadata_tag
= "title"; break;
701 case MKTAG('F','V','E','R'):
702 if (iff
->form_tag
== ID_DSD
|| iff
->form_tag
== ID_DST
) {
704 return AVERROR_INVALIDDATA
;
705 version
= avio_rb32(pb
);
706 av_log(s
, AV_LOG_DEBUG
, "DSIFF v%d.%d.%d.%d\n",version
>> 24, (version
>> 16) & 0xFF, (version
>> 8) & 0xFF, version
& 0xFF);
707 if (!new_stream(s
, &sta
, &iff
->audio_stream_index
, AVMEDIA_TYPE_AUDIO
))
708 return AVERROR(ENOMEM
);
709 sta
->codecpar
->codec_type
= AVMEDIA_TYPE_AUDIO
;
713 case MKTAG('D','I','I','N'):
715 return AVERROR_INVALIDDATA
;
716 res
= parse_dsd_diin(s
, sta
, orig_pos
+ data_size
);
721 case MKTAG('P','R','O','P'):
723 return AVERROR_INVALIDDATA
;
724 if (avio_rl32(pb
) != MKTAG('S','N','D',' ')) {
725 avpriv_request_sample(s
, "unknown property type");
729 return AVERROR_INVALIDDATA
;
730 res
= parse_dsd_prop(s
, sta
, orig_pos
+ data_size
);
735 case MKTAG('C','O','M','T'):
737 return AVERROR_INVALIDDATA
;
739 return AVERROR_INVALIDDATA
;
740 nb_comments
= avio_rb16(pb
);
741 for (i
= 0; i
< nb_comments
; i
++) {
742 int year
, mon
, day
, hour
, min
, type
, ref
;
747 year
= avio_rb16(pb
);
752 snprintf(tmp
, sizeof(tmp
), "%04d-%02d-%02d %02d:%02d", year
, mon
, day
, hour
, min
);
753 av_dict_set(&sta
->metadata
, "comment_time", tmp
, 0);
755 type
= avio_rb16(pb
);
760 tag
= "channel_comment";
762 snprintf(tmp
, sizeof(tmp
), "channel%d_comment", ref
);
767 tag
= ref
< FF_ARRAY_ELEMS(dsd_source_comment
) ? dsd_source_comment
[ref
] : "source_comment";
770 tag
= ref
< FF_ARRAY_ELEMS(dsd_history_comment
) ? dsd_history_comment
[ref
] : "file_history";
776 metadata_size
= avio_rb32(pb
);
777 if ((res
= get_metadata(s
, tag
, metadata_size
)) < 0) {
778 av_log(s
, AV_LOG_ERROR
, "cannot allocate metadata tag %s!\n", tag
);
782 if (metadata_size
& 1)
789 if ((res
= get_metadata(s
, metadata_tag
, data_size
)) < 0) {
790 av_log(s
, AV_LOG_ERROR
, "cannot allocate metadata tag %s!\n", metadata_tag
);
794 avio_skip(pb
, data_size
- (avio_tell(pb
) - orig_pos
) + (data_size
& 1));
797 if ((!sta
&& !stv
) ||
798 (iff
->form_tag
== ID_ANIM
&& !stv
) ||
799 (iff
->form_tag
!= ID_ANIM
&& sta
&& stv
))
800 return AVERROR_INVALIDDATA
;
802 if (iff
->form_tag
== ID_ANIM
)
803 avio_seek(pb
, 12, SEEK_SET
);
805 avio_seek(pb
, iff
->body_pos
, SEEK_SET
);
808 avpriv_set_pts_info(sta
, 32, 1, sta
->codecpar
->sample_rate
);
810 if (sta
->codecpar
->codec_id
!= AV_CODEC_ID_NONE
) {
811 /* codec_id already set by PROP or SXHD chunk */
812 } else if (iff
->form_tag
== ID_16SV
)
813 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_S16BE_PLANAR
;
814 else if (iff
->form_tag
== ID_MAUD
) {
815 if (iff
->maud_bits
== 8 && !iff
->maud_compression
) {
816 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_U8
;
817 } else if (iff
->maud_bits
== 16 && !iff
->maud_compression
) {
818 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_S16BE
;
819 } else if (iff
->maud_bits
== 8 && iff
->maud_compression
== 2) {
820 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_ALAW
;
821 } else if (iff
->maud_bits
== 8 && iff
->maud_compression
== 3) {
822 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_MULAW
;
824 avpriv_request_sample(s
, "compression %d and bit depth %d", iff
->maud_compression
, iff
->maud_bits
);
825 return AVERROR_PATCHWELCOME
;
828 switch (iff
->svx8_compression
) {
830 sta
->codecpar
->codec_id
= AV_CODEC_ID_PCM_S8_PLANAR
;
833 sta
->codecpar
->codec_id
= AV_CODEC_ID_8SVX_FIB
;
836 sta
->codecpar
->codec_id
= AV_CODEC_ID_8SVX_EXP
;
839 av_log(s
, AV_LOG_ERROR
,
840 "Unknown SVX8 compression method '%d'\n", iff
->svx8_compression
);
845 sta
->codecpar
->bits_per_coded_sample
= av_get_bits_per_sample(sta
->codecpar
->codec_id
);
846 sta
->codecpar
->bit_rate
= (int64_t)sta
->codecpar
->ch_layout
.nb_channels
*
847 sta
->codecpar
->sample_rate
*
848 sta
->codecpar
->bits_per_coded_sample
;
849 sta
->codecpar
->block_align
= sta
->codecpar
->ch_layout
.nb_channels
*
850 sta
->codecpar
->bits_per_coded_sample
;
851 if ((sta
->codecpar
->codec_tag
== ID_DSD
|| iff
->form_tag
== ID_MAUD
) && sta
->codecpar
->block_align
<= 0)
852 return AVERROR_INVALIDDATA
;
856 iff
->bpp
= stv
->codecpar
->bits_per_coded_sample
;
857 if (iff
->form_tag
== ID_ANIM
)
858 avpriv_set_pts_info(stv
, 32, 1, 60);
859 if ((screenmode
& 0x800 /* Hold And Modify */) && iff
->bpp
<= 8) {
860 iff
->ham
= iff
->bpp
> 6 ? 6 : 4;
861 stv
->codecpar
->bits_per_coded_sample
= 24;
863 iff
->flags
= (screenmode
& 0x80 /* Extra HalfBrite */) && iff
->bpp
<= 8;
864 iff
->masking
= masking
;
865 iff
->transparency
= transparency
;
867 if (!stv
->codecpar
->extradata
) {
868 int ret
= ff_alloc_extradata(stv
->codecpar
, IFF_EXTRA_VIDEO_SIZE
);
872 av_assert0(stv
->codecpar
->extradata_size
>= IFF_EXTRA_VIDEO_SIZE
);
873 buf
= stv
->codecpar
->extradata
;
874 bytestream_put_be16(&buf
, IFF_EXTRA_VIDEO_SIZE
);
875 bytestream_put_byte(&buf
, iff
->bitmap_compression
);
876 bytestream_put_byte(&buf
, iff
->bpp
);
877 bytestream_put_byte(&buf
, iff
->ham
);
878 bytestream_put_byte(&buf
, iff
->flags
);
879 bytestream_put_be16(&buf
, iff
->transparency
);
880 bytestream_put_byte(&buf
, iff
->masking
);
881 bytestream_put_buffer(&buf
, iff
->tvdc
, sizeof(iff
->tvdc
));
882 stv
->codecpar
->codec_id
= AV_CODEC_ID_IFF_ILBM
;
883 stv
->codecpar
->codec_tag
= iff
->form_tag
; // codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
889 static unsigned get_anim_duration(uint8_t *buf
, int size
)
893 bytestream2_init(&gb
, buf
, size
);
894 bytestream2_skip(&gb
, 4);
895 while (bytestream2_get_bytes_left(&gb
) > 8) {
896 unsigned chunk
= bytestream2_get_le32(&gb
);
897 unsigned size
= bytestream2_get_be32(&gb
);
899 if (chunk
== ID_ANHD
) {
902 bytestream2_skip(&gb
, 14);
903 return bytestream2_get_be32(&gb
);
905 bytestream2_skip(&gb
, size
+ size
& 1);
911 static int64_t get_sbdy_offset(uint8_t *buf
, int size
)
915 bytestream2_init(&gb
, buf
, size
);
916 bytestream2_skip(&gb
, 4);
917 while (bytestream2_get_bytes_left(&gb
) > 8) {
918 unsigned chunk
= bytestream2_get_le32(&gb
);
919 unsigned size
= bytestream2_get_be32(&gb
);
921 if (chunk
== MKTAG('S','B','D','Y'))
922 return bytestream2_tell(&gb
);
924 bytestream2_skip(&gb
, size
+ size
& 1);
930 static int iff_read_packet(AVFormatContext
*s
,
933 IffDemuxContext
*iff
= s
->priv_data
;
934 AVIOContext
*pb
= s
->pb
;
936 int64_t pos
= avio_tell(pb
);
940 if (iff
->form_tag
!= ID_ANIM
&& pos
>= iff
->body_end
)
945 avio_seek(pb
, iff
->sbdy_pos
, SEEK_SET
);
946 data_size
= iff
->is_64bit
? avio_rb64(pb
) : avio_rb32(pb
);
947 ret
= av_get_packet(pb
, pkt
, data_size
);
948 pkt
->stream_index
= iff
->audio_stream_index
;
949 pkt
->duration
= data_size
/ s
->streams
[iff
->audio_stream_index
]->codecpar
->ch_layout
.nb_channels
;
950 pkt
->pos
= INT_MAX
; /* not seekable */
953 avio_seek(pb
, iff
->resume_pos
, SEEK_SET
);
957 if (iff
->audio_stream_index
>= 0 && iff
->video_stream_index
< 0) { /* audio only */
958 AVStream
*sta
= s
->streams
[iff
->audio_stream_index
];
959 if (sta
->codecpar
->codec_tag
== ID_DSD
|| iff
->form_tag
== ID_MAUD
) {
960 ret
= av_get_packet(pb
, pkt
, FFMIN(iff
->body_end
- pos
, 1024 * sta
->codecpar
->block_align
));
961 } else if (sta
->codecpar
->codec_tag
== ID_DST
) {
962 return read_dst_frame(s
, pkt
);
964 if (iff
->body_size
> INT_MAX
|| !iff
->body_size
)
965 return AVERROR_INVALIDDATA
;
966 ret
= av_get_packet(pb
, pkt
, iff
->body_size
);
968 pkt
->stream_index
= iff
->audio_stream_index
;
969 } else if (iff
->form_tag
== ID_ANIM
) {
970 uint64_t data_size
, orig_pos
;
971 uint32_t chunk_id
, chunk_id2
;
973 while (!avio_feof(pb
)) {
974 orig_pos
= avio_tell(pb
);
975 chunk_id
= avio_rl32(pb
);
976 data_size
= avio_rb32(pb
);
977 chunk_id2
= avio_rl32(pb
);
979 if (chunk_id
== ID_FORM
&&
980 chunk_id2
== ID_ILBM
) {
983 } else if (chunk_id
== ID_FORM
&&
984 chunk_id2
== ID_ANIM
) {
987 avio_skip(pb
, data_size
);
993 ret
= av_get_packet(pb
, pkt
, data_size
);
994 pkt
->stream_index
= iff
->video_stream_index
;
996 pkt
->duration
= get_anim_duration(pkt
->data
, pkt
->size
);
998 pkt
->flags
|= AV_PKT_FLAG_KEY
;
1000 if (iff
->audio_stream_index
>= 0) {
1001 iff
->sbdy_pos
= get_sbdy_offset(pkt
->data
, pkt
->size
);
1002 if (iff
->sbdy_pos
) {
1003 iff
->sbdy_pos
+= orig_pos
+ 4;
1004 iff
->resume_pos
= avio_tell(pb
);
1007 } else if (iff
->video_stream_index
>= 0 && iff
->audio_stream_index
< 0) { /* video only */
1008 if (iff
->body_size
> INT_MAX
|| !iff
->body_size
)
1009 return AVERROR_INVALIDDATA
;
1010 ret
= av_get_packet(pb
, pkt
, iff
->body_size
);
1011 pkt
->stream_index
= iff
->video_stream_index
;
1013 if (pos
== iff
->body_pos
)
1014 pkt
->flags
|= AV_PKT_FLAG_KEY
;
1022 const FFInputFormat ff_iff_demuxer
= {
1024 .p
.long_name
= NULL_IF_CONFIG_SMALL("IFF (Interchange File Format)"),
1025 .p
.flags
= AVFMT_GENERIC_INDEX
| AVFMT_NO_BYTE_SEEK
,
1026 .priv_data_size
= sizeof(IffDemuxContext
),
1027 .read_probe
= iff_probe
,
1028 .read_header
= iff_read_header
,
1029 .read_packet
= iff_read_packet
,