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