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 Fri Dec 5 2014 04:42:14 for FFmpeg by
1.8.2