FFmpeg
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
Examples
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
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 FFmpeg.
6
*
7
* FFmpeg 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
* FFmpeg 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 FFmpeg; 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/channel_layout.h
"
23
#include "
libavutil/intreadwrite.h
"
24
#include "
avformat.h
"
25
#include "
internal.h
"
26
#include "
avio_internal.h
"
27
28
enum
SIFFTags
{
29
TAG_SIFF
=
MKTAG
(
'S'
,
'I'
,
'F'
,
'F'
),
30
TAG_BODY
=
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
),
31
TAG_VBHD
=
MKTAG
(
'V'
,
'B'
,
'H'
,
'D'
),
32
TAG_SHDR
=
MKTAG
(
'S'
,
'H'
,
'D'
,
'R'
),
33
TAG_VBV1
=
MKTAG
(
'V'
,
'B'
,
'V'
,
'1'
),
34
TAG_SOUN
=
MKTAG
(
'S'
,
'O'
,
'U'
,
'N'
),
35
};
36
37
enum
VBFlags
{
38
VB_HAS_GMC
= 0x01,
39
VB_HAS_AUDIO
= 0x04,
40
VB_HAS_VIDEO
= 0x08,
41
VB_HAS_PALETTE
= 0x10,
42
VB_HAS_LENGTH
= 0x20
43
};
44
45
typedef
struct
SIFFContext
{
46
int
frames
;
47
int
cur_frame
;
48
int
rate
;
49
int
bits
;
50
int
block_align
;
51
52
int
has_video
;
53
int
has_audio
;
54
55
int
curstrm
;
56
int
pktsize
;
57
int
gmcsize
;
58
int
sndsize
;
59
60
int
flags
;
61
uint8_t
gmc
[4];
62
}
SIFFContext
;
63
64
static
int
siff_probe
(
AVProbeData
*p)
65
{
66
uint32_t
tag
=
AV_RL32
(p->
buf
+ 8);
67
/* check file header */
68
if
(
AV_RL32
(p->
buf
) !=
TAG_SIFF
||
69
(tag !=
TAG_VBV1
&& tag !=
TAG_SOUN
))
70
return
0;
71
return
AVPROBE_SCORE_MAX
;
72
}
73
74
static
int
create_audio_stream
(
AVFormatContext
*
s
,
SIFFContext
*
c
)
75
{
76
AVStream
*ast;
77
ast =
avformat_new_stream
(s, NULL);
78
if
(!ast)
79
return
AVERROR
(ENOMEM);
80
ast->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
81
ast->
codec
->
codec_id
=
AV_CODEC_ID_PCM_U8
;
82
ast->
codec
->
channels
= 1;
83
ast->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
84
ast->
codec
->
bits_per_coded_sample
= 8;
85
ast->
codec
->
sample_rate
= c->
rate
;
86
avpriv_set_pts_info
(ast, 16, 1, c->
rate
);
87
ast->
start_time
= 0;
88
return
0;
89
}
90
91
static
int
siff_parse_vbv1
(
AVFormatContext
*
s
,
SIFFContext
*
c
,
AVIOContext
*pb)
92
{
93
AVStream
*st;
94
int
width
,
height
;
95
96
if
(
avio_rl32
(pb) !=
TAG_VBHD
){
97
av_log
(s,
AV_LOG_ERROR
,
"Header chunk is missing\n"
);
98
return
AVERROR_INVALIDDATA
;
99
}
100
if
(
avio_rb32
(pb) != 32){
101
av_log
(s,
AV_LOG_ERROR
,
"Header chunk size is incorrect\n"
);
102
return
AVERROR_INVALIDDATA
;
103
}
104
if
(
avio_rl16
(pb) != 1){
105
av_log
(s,
AV_LOG_ERROR
,
"Incorrect header version\n"
);
106
return
AVERROR_INVALIDDATA
;
107
}
108
width =
avio_rl16
(pb);
109
height =
avio_rl16
(pb);
110
avio_skip
(pb, 4);
111
c->
frames
=
avio_rl16
(pb);
112
if
(!c->
frames
){
113
av_log
(s,
AV_LOG_ERROR
,
"File contains no frames ???\n"
);
114
return
AVERROR_INVALIDDATA
;
115
}
116
c->
bits
=
avio_rl16
(pb);
117
c->
rate
=
avio_rl16
(pb);
118
c->
block_align
= c->
rate
* (c->
bits
>> 3);
119
120
avio_skip
(pb, 16);
//zeroes
121
122
st =
avformat_new_stream
(s, NULL);
123
if
(!st)
124
return
AVERROR
(ENOMEM);
125
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
126
st->
codec
->
codec_id
=
AV_CODEC_ID_VB
;
127
st->
codec
->
codec_tag
=
MKTAG
(
'V'
,
'B'
,
'V'
,
'1'
);
128
st->
codec
->
width
=
width
;
129
st->
codec
->
height
=
height
;
130
st->
codec
->
pix_fmt
=
AV_PIX_FMT_PAL8
;
131
st->
nb_frames
=
132
st->
duration
= c->
frames
;
133
avpriv_set_pts_info
(st, 16, 1, 12);
134
135
c->
cur_frame
= 0;
136
c->
has_video
= 1;
137
c->
has_audio
= !!c->
rate
;
138
c->
curstrm
= -1;
139
if
(c->
has_audio
&&
create_audio_stream
(s, c) < 0)
140
return
AVERROR
(ENOMEM);
141
return
0;
142
}
143
144
static
int
siff_parse_soun
(
AVFormatContext
*
s
,
SIFFContext
*
c
,
AVIOContext
*pb)
145
{
146
if
(
avio_rl32
(pb) !=
TAG_SHDR
){
147
av_log
(s,
AV_LOG_ERROR
,
"Header chunk is missing\n"
);
148
return
AVERROR_INVALIDDATA
;
149
}
150
if
(
avio_rb32
(pb) != 8){
151
av_log
(s,
AV_LOG_ERROR
,
"Header chunk size is incorrect\n"
);
152
return
AVERROR_INVALIDDATA
;
153
}
154
avio_skip
(pb, 4);
//unknown value
155
c->
rate
=
avio_rl16
(pb);
156
c->
bits
=
avio_rl16
(pb);
157
c->
block_align
= c->
rate
* (c->
bits
>> 3);
158
return
create_audio_stream
(s, c);
159
}
160
161
static
int
siff_read_header
(
AVFormatContext
*
s
)
162
{
163
AVIOContext
*pb = s->
pb
;
164
SIFFContext
*
c
= s->
priv_data
;
165
uint32_t
tag
;
166
int
ret
;
167
168
if
(
avio_rl32
(pb) !=
TAG_SIFF
)
169
return
AVERROR_INVALIDDATA
;
170
avio_skip
(pb, 4);
//ignore size
171
tag =
avio_rl32
(pb);
172
173
if
(tag !=
TAG_VBV1
&& tag !=
TAG_SOUN
){
174
av_log
(s,
AV_LOG_ERROR
,
"Not a VBV file\n"
);
175
return
AVERROR_INVALIDDATA
;
176
}
177
178
if
(tag ==
TAG_VBV1
&& (ret =
siff_parse_vbv1
(s, c, pb)) < 0)
179
return
ret
;
180
if
(tag ==
TAG_SOUN
&& (ret =
siff_parse_soun
(s, c, pb)) < 0)
181
return
ret
;
182
if
(
avio_rl32
(pb) !=
MKTAG
(
'B'
,
'O'
,
'D'
,
'Y'
)){
183
av_log
(s,
AV_LOG_ERROR
,
"'BODY' chunk is missing\n"
);
184
return
AVERROR_INVALIDDATA
;
185
}
186
avio_skip
(pb, 4);
//ignore size
187
188
return
0;
189
}
190
191
static
int
siff_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
192
{
193
SIFFContext
*
c
= s->
priv_data
;
194
int
size
;
195
196
if
(c->
has_video
){
197
if
(c->
cur_frame
>= c->
frames
)
198
return
AVERROR_EOF
;
199
if
(c->
curstrm
== -1){
200
c->
pktsize
=
avio_rl32
(s->
pb
) - 4;
201
c->
flags
=
avio_rl16
(s->
pb
);
202
c->
gmcsize
= (c->
flags
&
VB_HAS_GMC
) ? 4 : 0;
203
if
(c->
gmcsize
)
204
avio_read
(s->
pb
, c->
gmc
, c->
gmcsize
);
205
c->
sndsize
= (c->
flags
&
VB_HAS_AUDIO
) ?
avio_rl32
(s->
pb
): 0;
206
c->
curstrm
= !!(c->
flags
&
VB_HAS_AUDIO
);
207
}
208
209
if
(!c->
curstrm
){
210
size = c->
pktsize
- c->
sndsize
- c->
gmcsize
- 2;
211
size =
ffio_limit
(s->
pb
, size);
212
if
(
size < 0 || c->
pktsize < c->sndsize)
213
return
AVERROR_INVALIDDATA
;
214
if
(
av_new_packet
(pkt, size + c->
gmcsize
+ 2) < 0)
215
return
AVERROR
(ENOMEM);
216
AV_WL16
(pkt->
data
, c->
flags
);
217
if
(c->
gmcsize
)
218
memcpy(pkt->
data
+ 2, c->
gmc
, c->
gmcsize
);
219
if
(
avio_read
(s->
pb
, pkt->
data
+ 2 + c->
gmcsize
, size) != size) {
220
av_free_packet
(pkt);
221
return
AVERROR_INVALIDDATA
;
222
}
223
pkt->
stream_index
= 0;
224
c->
curstrm
= -1;
225
}
else
{
226
if
((size =
av_get_packet
(s->
pb
, pkt, c->
sndsize
- 4)) < 0)
227
return
AVERROR
(EIO);
228
pkt->
stream_index
= 1;
229
pkt->
duration
=
size
;
230
c->
curstrm
= 0;
231
}
232
if
(!c->
cur_frame
|| c->
curstrm
)
233
pkt->
flags
|=
AV_PKT_FLAG_KEY
;
234
if
(c->
curstrm
== -1)
235
c->
cur_frame
++;
236
}
else
{
237
size =
av_get_packet
(s->
pb
, pkt, c->
block_align
);
238
if
(!size)
239
return
AVERROR_EOF
;
240
if
(size < 0)
241
return
AVERROR
(EIO);
242
pkt->
duration
=
size
;
243
}
244
return
pkt->
size
;
245
}
246
247
AVInputFormat
ff_siff_demuxer
= {
248
.
name
=
"siff"
,
249
.long_name =
NULL_IF_CONFIG_SMALL
(
"Beam Software SIFF"
),
250
.priv_data_size =
sizeof
(
SIFFContext
),
251
.
read_probe
=
siff_probe
,
252
.
read_header
=
siff_read_header
,
253
.
read_packet
=
siff_read_packet
,
254
.extensions =
"vb,son"
,
255
};
Generated on Sun Jul 20 2014 23:06:06 for FFmpeg by
1.8.2