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