Libav
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
iff.c
Go to the documentation of this file.
1
/*
2
* IFF (.iff) file demuxer
3
* Copyright (c) 2008 Jaikrishnan Menon <realityman@gmx.net>
4
* Copyright (c) 2010 Peter Ross <pross@xvid.org>
5
* Copyright (c) 2010 Sebastian Vater <cdgs.basty@googlemail.com>
6
*
7
* This file is part of Libav.
8
*
9
* Libav is free software; you can redistribute it and/or
10
* modify it under the terms of the GNU Lesser General Public
11
* License as published by the Free Software Foundation; either
12
* version 2.1 of the License, or (at your option) any later version.
13
*
14
* Libav is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17
* Lesser General Public License for more details.
18
*
19
* You should have received a copy of the GNU Lesser General Public
20
* License along with Libav; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
*/
23
32
#include "
libavutil/channel_layout.h
"
33
#include "
libavutil/intreadwrite.h
"
34
#include "
libavutil/dict.h
"
35
#include "
avformat.h
"
36
#include "
internal.h
"
37
38
#define ID_8SVX MKTAG('8','S','V','X')
39
#define ID_VHDR MKTAG('V','H','D','R')
40
#define ID_ATAK MKTAG('A','T','A','K')
41
#define ID_RLSE MKTAG('R','L','S','E')
42
#define ID_CHAN MKTAG('C','H','A','N')
43
#define ID_PBM MKTAG('P','B','M',' ')
44
#define ID_ILBM MKTAG('I','L','B','M')
45
#define ID_BMHD MKTAG('B','M','H','D')
46
#define ID_CMAP MKTAG('C','M','A','P')
47
48
#define ID_FORM MKTAG('F','O','R','M')
49
#define ID_ANNO MKTAG('A','N','N','O')
50
#define ID_AUTH MKTAG('A','U','T','H')
51
#define ID_CHRS MKTAG('C','H','R','S')
52
#define ID_COPYRIGHT MKTAG('(','c',')',' ')
53
#define ID_CSET MKTAG('C','S','E','T')
54
#define ID_FVER MKTAG('F','V','E','R')
55
#define ID_NAME MKTAG('N','A','M','E')
56
#define ID_TEXT MKTAG('T','E','X','T')
57
#define ID_BODY MKTAG('B','O','D','Y')
58
#define ID_ANNO MKTAG('A','N','N','O')
59
60
#define LEFT 2
61
#define RIGHT 4
62
#define STEREO 6
63
64
typedef
enum
{
65
COMP_NONE
,
66
COMP_FIB
,
67
COMP_EXP
68
}
svx8_compression_type
;
69
70
typedef
enum
{
71
BITMAP_RAW
,
72
BITMAP_BYTERUN1
73
}
bitmap_compression_type
;
74
75
typedef
struct
{
76
uint64_t
body_pos
;
77
uint32_t
body_size
;
78
uint32_t
sent_bytes
;
79
}
IffDemuxContext
;
80
81
82
/* Metadata string read */
83
static
int
get_metadata
(
AVFormatContext
*s,
84
const
char
*
const
tag
,
85
const
unsigned
data_size)
86
{
87
uint8_t
*buf = ((data_size + 1) == 0) ?
NULL
:
av_malloc
(data_size + 1);
88
89
if
(!buf)
90
return
AVERROR
(ENOMEM);
91
92
if
(
avio_read
(s->
pb
, buf, data_size) < 0) {
93
av_free
(buf);
94
return
AVERROR
(EIO);
95
}
96
buf[data_size] = 0;
97
av_dict_set
(&s->
metadata
, tag, buf,
AV_DICT_DONT_STRDUP_VAL
);
98
return
0;
99
}
100
101
static
int
iff_probe
(
AVProbeData
*p)
102
{
103
const
uint8_t
*d = p->
buf
;
104
105
if
(
AV_RL32
(d) ==
ID_FORM
&&
106
(
AV_RL32
(d+8) ==
ID_8SVX
||
AV_RL32
(d+8) ==
ID_PBM
||
AV_RL32
(d+8) ==
ID_ILBM
) )
107
return
AVPROBE_SCORE_MAX
;
108
return
0;
109
}
110
111
static
int
iff_read_header
(
AVFormatContext
*s)
112
{
113
IffDemuxContext
*iff = s->
priv_data
;
114
AVIOContext
*pb = s->
pb
;
115
AVStream
*st;
116
uint32_t chunk_id, data_size;
117
int
compression = -1;
118
119
st =
avformat_new_stream
(s,
NULL
);
120
if
(!st)
121
return
AVERROR
(ENOMEM);
122
123
st->
codec
->
channels
= 1;
124
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
125
avio_skip
(pb, 8);
126
// codec_tag used by ByteRun1 decoder to distinguish progressive (PBM) and interlaced (ILBM) content
127
st->
codec
->
codec_tag
=
avio_rl32
(pb);
128
129
while
(!pb->
eof_reached
) {
130
uint64_t orig_pos;
131
int
res;
132
const
char
*metadata_tag =
NULL
;
133
chunk_id =
avio_rl32
(pb);
134
data_size =
avio_rb32
(pb);
135
orig_pos =
avio_tell
(pb);
136
137
switch
(chunk_id) {
138
case
ID_VHDR
:
139
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
140
141
if
(data_size < 14)
142
return
AVERROR_INVALIDDATA
;
143
avio_skip
(pb, 12);
144
st->
codec
->
sample_rate
=
avio_rb16
(pb);
145
if
(data_size >= 16) {
146
avio_skip
(pb, 1);
147
compression =
avio_r8
(pb);
148
}
149
break
;
150
151
case
ID_BODY
:
152
iff->
body_pos
=
avio_tell
(pb);
153
iff->
body_size
= data_size;
154
break
;
155
156
case
ID_CHAN
:
157
if
(data_size < 4)
158
return
AVERROR_INVALIDDATA
;
159
if
(
avio_rb32
(pb) < 6) {
160
st->
codec
->
channels
= 1;
161
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
162
}
else
{
163
st->
codec
->
channels
= 2;
164
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
165
}
166
break
;
167
168
case
ID_CMAP
:
169
if
(data_size < 3 || data_size > 768 || data_size % 3) {
170
av_log
(s,
AV_LOG_ERROR
,
"Invalid CMAP chunk size %d\n"
,
171
data_size);
172
return
AVERROR_INVALIDDATA
;
173
}
174
st->
codec
->
extradata_size
= data_size;
175
st->
codec
->
extradata
=
av_malloc
(data_size);
176
if
(!st->
codec
->
extradata
)
177
return
AVERROR
(ENOMEM);
178
if
(
avio_read
(pb, st->
codec
->
extradata
, data_size) < 0)
179
return
AVERROR
(EIO);
180
break
;
181
182
case
ID_BMHD
:
183
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
184
if
(data_size <= 8)
185
return
AVERROR_INVALIDDATA
;
186
st->
codec
->
width
=
avio_rb16
(pb);
187
st->
codec
->
height
=
avio_rb16
(pb);
188
avio_skip
(pb, 4);
// x, y offset
189
st->
codec
->
bits_per_coded_sample
=
avio_r8
(pb);
190
if
(data_size >= 11) {
191
avio_skip
(pb, 1);
// masking
192
compression =
avio_r8
(pb);
193
}
194
if
(data_size >= 16) {
195
avio_skip
(pb, 3);
// paddding, transparent
196
st->
sample_aspect_ratio
.
num
=
avio_r8
(pb);
197
st->
sample_aspect_ratio
.
den
=
avio_r8
(pb);
198
}
199
break
;
200
201
case
ID_ANNO
:
202
case
ID_TEXT
:
203
metadata_tag =
"comment"
;
204
break
;
205
206
case
ID_AUTH
:
207
metadata_tag =
"artist"
;
208
break
;
209
210
case
ID_COPYRIGHT
:
211
metadata_tag =
"copyright"
;
212
break
;
213
214
case
ID_NAME
:
215
metadata_tag =
"title"
;
216
break
;
217
}
218
219
if
(metadata_tag) {
220
if
((res =
get_metadata
(s, metadata_tag, data_size)) < 0) {
221
av_log
(s,
AV_LOG_ERROR
,
"cannot allocate metadata tag %s!"
, metadata_tag);
222
return
res;
223
}
224
}
225
avio_skip
(pb, data_size - (
avio_tell
(pb) - orig_pos) + (data_size & 1));
226
}
227
228
avio_seek
(pb, iff->
body_pos
, SEEK_SET);
229
230
switch
(st->
codec
->
codec_type
) {
231
case
AVMEDIA_TYPE_AUDIO
:
232
avpriv_set_pts_info
(st, 32, 1, st->
codec
->
sample_rate
);
233
234
switch
(compression) {
235
case
COMP_NONE
:
236
st->
codec
->
codec_id
=
AV_CODEC_ID_PCM_S8_PLANAR
;
237
break
;
238
case
COMP_FIB
:
239
st->
codec
->
codec_id
=
AV_CODEC_ID_8SVX_FIB
;
240
break
;
241
case
COMP_EXP
:
242
st->
codec
->
codec_id
=
AV_CODEC_ID_8SVX_EXP
;
243
break
;
244
default
:
245
av_log
(s,
AV_LOG_ERROR
,
"unknown compression method\n"
);
246
return
-1;
247
}
248
249
st->
codec
->
bits_per_coded_sample
= 8;
250
st->
codec
->
bit_rate
= st->
codec
->
channels
* st->
codec
->
sample_rate
* st->
codec
->
bits_per_coded_sample
;
251
st->
codec
->
block_align
= st->
codec
->
channels
* st->
codec
->
bits_per_coded_sample
;
252
break
;
253
254
case
AVMEDIA_TYPE_VIDEO
:
255
switch
(compression) {
256
case
BITMAP_RAW
:
257
st->
codec
->
codec_id
=
AV_CODEC_ID_IFF_ILBM
;
258
break
;
259
case
BITMAP_BYTERUN1
:
260
st->
codec
->
codec_id
=
AV_CODEC_ID_IFF_BYTERUN1
;
261
break
;
262
default
:
263
av_log
(s,
AV_LOG_ERROR
,
"unknown compression method\n"
);
264
return
AVERROR_INVALIDDATA
;
265
}
266
break
;
267
default
:
268
return
-1;
269
}
270
271
return
0;
272
}
273
274
static
int
iff_read_packet
(
AVFormatContext
*s,
275
AVPacket
*pkt)
276
{
277
IffDemuxContext
*iff = s->
priv_data
;
278
AVIOContext
*pb = s->
pb
;
279
int
ret;
280
281
if
(iff->
sent_bytes
>= iff->
body_size
)
282
return
AVERROR_EOF
;
283
284
ret =
av_get_packet
(pb, pkt, iff->
body_size
);
285
if
(ret < 0)
286
return
ret;
287
288
if
(iff->
sent_bytes
== 0)
289
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
290
iff->
sent_bytes
= iff->
body_size
;
291
292
pkt->
stream_index
= 0;
293
return
ret;
294
}
295
296
AVInputFormat
ff_iff_demuxer
= {
297
.
name
=
"iff"
,
298
.long_name =
NULL_IF_CONFIG_SMALL
(
"IFF (Interchange File Format)"
),
299
.priv_data_size =
sizeof
(
IffDemuxContext
),
300
.
read_probe
=
iff_probe
,
301
.
read_header
=
iff_read_header
,
302
.
read_packet
=
iff_read_packet
,
303
};
Generated on Thu Sep 30 2021 23:03:11 for Libav by
1.8.1.2