Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
siff.c
Go to the documentation of this file.
1
/*
2
* Beam Software SIFF demuxer
3
* Copyright (c) 2007 Konstantin Shishkov
4
*
5
* This file is part of Libav.
6
*
7
* Libav is free software; you can redistribute it and/or
8
* modify it under the terms of the GNU Lesser General Public
9
* License as published by the Free Software Foundation; either
10
* version 2.1 of the License, or (at your option) any later version.
11
*
12
* Libav is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
16
*
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with Libav; if not, write to the Free Software
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
*/
21
22
#include "
libavutil/intreadwrite.h
"
23
#include "
avformat.h
"
24
#include "
internal.h
"
25
26
enum
SIFFTags
{
27
TAG_SIFF
=
MKTAG
(
'S'
,
'I'
,
'F'
,
'F'
),
28
TAG_BODY
=
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
),
29
TAG_VBHD
=
MKTAG
(
'V'
,
'B'
,
'H'
,
'D'
),
30
TAG_SHDR
=
MKTAG
(
'S'
,
'H'
,
'D'
,
'R'
),
31
TAG_VBV1
=
MKTAG
(
'V'
,
'B'
,
'V'
,
'1'
),
32
TAG_SOUN
=
MKTAG
(
'S'
,
'O'
,
'U'
,
'N'
),
33
};
34
35
enum
VBFlags
{
36
VB_HAS_GMC
= 0x01,
37
VB_HAS_AUDIO
= 0x04,
38
VB_HAS_VIDEO
= 0x08,
39
VB_HAS_PALETTE
= 0x10,
40
VB_HAS_LENGTH
= 0x20
41
};
42
43
typedef
struct
SIFFContext
{
44
int
frames
;
45
int
cur_frame
;
46
int
rate
;
47
int
bits
;
48
int
block_align
;
49
50
int
has_video
;
51
int
has_audio
;
52
53
int
curstrm
;
54
int
pktsize
;
55
int
gmcsize
;
56
int
sndsize
;
57
58
int
flags
;
59
uint8_t
gmc
[4];
60
}
SIFFContext
;
61
62
static
int
siff_probe
(
AVProbeData
*p)
63
{
64
uint32_t
tag
=
AV_RL32
(p->
buf
+ 8);
65
/* check file header */
66
if
(
AV_RL32
(p->
buf
) !=
TAG_SIFF
||
67
(tag !=
TAG_VBV1
&& tag !=
TAG_SOUN
))
68
return
0;
69
return
AVPROBE_SCORE_MAX
;
70
}
71
72
static
int
create_audio_stream
(
AVFormatContext
*s,
SIFFContext
*c)
73
{
74
AVStream
*ast;
75
ast =
avformat_new_stream
(s,
NULL
);
76
if
(!ast)
77
return
-1;
78
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
79
ast->
codec
->
codec_id
=
CODEC_ID_PCM_U8
;
80
ast->
codec
->
channels
= 1;
81
ast->
codec
->
bits_per_coded_sample
= c->
bits
;
82
ast->
codec
->
sample_rate
= c->
rate
;
83
ast->
codec
->
frame_size
= c->
block_align
;
84
avpriv_set_pts_info
(ast, 16, 1, c->
rate
);
85
return
0;
86
}
87
88
static
int
siff_parse_vbv1
(
AVFormatContext
*s,
SIFFContext
*c,
AVIOContext
*pb)
89
{
90
AVStream
*st;
91
int
width
,
height
;
92
93
if
(
avio_rl32
(pb) !=
TAG_VBHD
){
94
av_log
(s,
AV_LOG_ERROR
,
"Header chunk is missing\n"
);
95
return
-1;
96
}
97
if
(
avio_rb32
(pb) != 32){
98
av_log
(s,
AV_LOG_ERROR
,
"Header chunk size is incorrect\n"
);
99
return
-1;
100
}
101
if
(
avio_rl16
(pb) != 1){
102
av_log
(s,
AV_LOG_ERROR
,
"Incorrect header version\n"
);
103
return
-1;
104
}
105
width =
avio_rl16
(pb);
106
height =
avio_rl16
(pb);
107
avio_skip
(pb, 4);
108
c->
frames
=
avio_rl16
(pb);
109
if
(!c->
frames
){
110
av_log
(s,
AV_LOG_ERROR
,
"File contains no frames ???\n"
);
111
return
-1;
112
}
113
c->
bits
=
avio_rl16
(pb);
114
c->
rate
=
avio_rl16
(pb);
115
c->
block_align
= c->
rate
* (c->
bits
>> 3);
116
117
avio_skip
(pb, 16);
//zeroes
118
119
st =
avformat_new_stream
(s,
NULL
);
120
if
(!st)
121
return
-1;
122
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
123
st->
codec
->
codec_id
=
CODEC_ID_VB
;
124
st->
codec
->
codec_tag
=
MKTAG
(
'V'
,
'B'
,
'V'
,
'1'
);
125
st->
codec
->
width
=
width
;
126
st->
codec
->
height
=
height
;
127
st->
codec
->
pix_fmt
=
PIX_FMT_PAL8
;
128
avpriv_set_pts_info
(st, 16, 1, 12);
129
130
c->
cur_frame
= 0;
131
c->
has_video
= 1;
132
c->
has_audio
= !!c->
rate
;
133
c->
curstrm
= -1;
134
if
(c->
has_audio
&&
create_audio_stream
(s, c) < 0)
135
return
-1;
136
return
0;
137
}
138
139
static
int
siff_parse_soun
(
AVFormatContext
*s,
SIFFContext
*c,
AVIOContext
*pb)
140
{
141
if
(
avio_rl32
(pb) !=
TAG_SHDR
){
142
av_log
(s,
AV_LOG_ERROR
,
"Header chunk is missing\n"
);
143
return
-1;
144
}
145
if
(
avio_rb32
(pb) != 8){
146
av_log
(s,
AV_LOG_ERROR
,
"Header chunk size is incorrect\n"
);
147
return
-1;
148
}
149
avio_skip
(pb, 4);
//unknown value
150
c->
rate
=
avio_rl16
(pb);
151
c->
bits
=
avio_rl16
(pb);
152
c->
block_align
= c->
rate
* (c->
bits
>> 3);
153
return
create_audio_stream
(s, c);
154
}
155
156
static
int
siff_read_header
(
AVFormatContext
*s,
AVFormatParameters
*ap)
157
{
158
AVIOContext
*pb = s->
pb
;
159
SIFFContext
*c = s->
priv_data
;
160
uint32_t
tag
;
161
162
if
(
avio_rl32
(pb) !=
TAG_SIFF
)
163
return
-1;
164
avio_skip
(pb, 4);
//ignore size
165
tag =
avio_rl32
(pb);
166
167
if
(tag !=
TAG_VBV1
&& tag !=
TAG_SOUN
){
168
av_log
(s,
AV_LOG_ERROR
,
"Not a VBV file\n"
);
169
return
-1;
170
}
171
172
if
(tag ==
TAG_VBV1
&&
siff_parse_vbv1
(s, c, pb) < 0)
173
return
-1;
174
if
(tag ==
TAG_SOUN
&&
siff_parse_soun
(s, c, pb) < 0)
175
return
-1;
176
if
(
avio_rl32
(pb) !=
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
)){
177
av_log
(s,
AV_LOG_ERROR
,
"'BODY' chunk is missing\n"
);
178
return
-1;
179
}
180
avio_skip
(pb, 4);
//ignore size
181
182
return
0;
183
}
184
185
static
int
siff_read_packet
(
AVFormatContext
*s,
AVPacket
*pkt)
186
{
187
SIFFContext
*c = s->
priv_data
;
188
int
size
;
189
190
if
(c->
has_video
){
191
if
(c->
cur_frame
>= c->
frames
)
192
return
AVERROR
(EIO);
193
if
(c->
curstrm
== -1){
194
c->
pktsize
=
avio_rl32
(s->
pb
) - 4;
195
c->
flags
=
avio_rl16
(s->
pb
);
196
c->
gmcsize
= (c->
flags
&
VB_HAS_GMC
) ? 4 : 0;
197
if
(c->
gmcsize
)
198
avio_read
(s->
pb
, c->
gmc
, c->
gmcsize
);
199
c->
sndsize
= (c->
flags
&
VB_HAS_AUDIO
) ?
avio_rl32
(s->
pb
): 0;
200
c->
curstrm
= !!(c->
flags
&
VB_HAS_AUDIO
);
201
}
202
203
if
(!c->
curstrm
){
204
size = c->
pktsize
- c->
sndsize
;
205
if
(
av_new_packet
(pkt, size) < 0)
206
return
AVERROR
(ENOMEM);
207
AV_WL16
(pkt->
data
, c->
flags
);
208
if
(c->
gmcsize
)
209
memcpy(pkt->
data
+ 2, c->
gmc
, c->
gmcsize
);
210
avio_read
(s->
pb
, pkt->
data
+ 2 + c->
gmcsize
, size - c->
gmcsize
- 2);
211
pkt->
stream_index
= 0;
212
c->
curstrm
= -1;
213
}
else
{
214
if
(
av_get_packet
(s->
pb
, pkt, c->
sndsize
- 4) < 0)
215
return
AVERROR
(EIO);
216
pkt->
stream_index
= 1;
217
c->
curstrm
= 0;
218
}
219
if
(!c->
cur_frame
|| c->
curstrm
)
220
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
221
if
(c->
curstrm
== -1)
222
c->
cur_frame
++;
223
}
else
{
224
size =
av_get_packet
(s->
pb
, pkt, c->
block_align
);
225
if
(size <= 0)
226
return
AVERROR
(EIO);
227
}
228
return
pkt->
size
;
229
}
230
231
AVInputFormat
ff_siff_demuxer
= {
232
.
name
=
"siff"
,
233
.long_name =
NULL_IF_CONFIG_SMALL
(
"Beam Software SIFF"
),
234
.priv_data_size =
sizeof
(
SIFFContext
),
235
.
read_probe
=
siff_probe
,
236
.
read_header
=
siff_read_header
,
237
.
read_packet
=
siff_read_packet
,
238
.extensions =
"vb,son"
239
};