Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
sol.c
Go to the documentation of this file.
1
/*
2
* Sierra SOL demuxer
3
* Copyright 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
/*
23
* Based on documents from Game Audio Player and own research
24
*/
25
26
#include "
libavutil/intreadwrite.h
"
27
#include "
avformat.h
"
28
#include "
internal.h
"
29
#include "
pcm.h
"
30
31
/* if we don't know the size in advance */
32
#define AU_UNKNOWN_SIZE ((uint32_t)(~0))
33
34
static
int
sol_probe
(
AVProbeData
*p)
35
{
36
/* check file header */
37
uint16_t magic =
AV_RL32
(p->
buf
);
38
if
((magic == 0x0B8D || magic == 0x0C0D || magic == 0x0C8D) &&
39
p->
buf
[2] ==
'S'
&& p->
buf
[3] ==
'O'
&&
40
p->
buf
[4] ==
'L'
&& p->
buf
[5] == 0)
41
return
AVPROBE_SCORE_MAX
;
42
else
43
return
0;
44
}
45
46
#define SOL_DPCM 1
47
#define SOL_16BIT 4
48
#define SOL_STEREO 16
49
50
static
enum
CodecID
sol_codec_id
(
int
magic,
int
type)
51
{
52
if
(magic == 0x0B8D)
53
{
54
if
(type &
SOL_DPCM
)
return
CODEC_ID_SOL_DPCM
;
55
else
return
CODEC_ID_PCM_U8
;
56
}
57
if
(type &
SOL_DPCM
)
58
{
59
if
(type &
SOL_16BIT
)
return
CODEC_ID_SOL_DPCM
;
60
else
if
(magic == 0x0C8D)
return
CODEC_ID_SOL_DPCM
;
61
else
return
CODEC_ID_SOL_DPCM
;
62
}
63
if
(type &
SOL_16BIT
)
return
CODEC_ID_PCM_S16LE
;
64
return
CODEC_ID_PCM_U8
;
65
}
66
67
static
int
sol_codec_type
(
int
magic,
int
type)
68
{
69
if
(magic == 0x0B8D)
return
1;
//SOL_DPCM_OLD;
70
if
(type &
SOL_DPCM
)
71
{
72
if
(type &
SOL_16BIT
)
return
3;
//SOL_DPCM_NEW16;
73
else
if
(magic == 0x0C8D)
return
1;
//SOL_DPCM_OLD;
74
else
return
2;
//SOL_DPCM_NEW8;
75
}
76
return
-1;
77
}
78
79
static
int
sol_channels
(
int
magic,
int
type)
80
{
81
if
(magic == 0x0B8D || !(type &
SOL_STEREO
))
return
1;
82
return
2;
83
}
84
85
static
int
sol_read_header
(
AVFormatContext
*s,
86
AVFormatParameters
*ap)
87
{
88
unsigned
int
magic,
tag
;
89
AVIOContext
*pb = s->
pb
;
90
unsigned
int
id
, channels, rate, type;
91
enum
CodecID
codec;
92
AVStream
*st;
93
94
/* check ".snd" header */
95
magic =
avio_rl16
(pb);
96
tag =
avio_rl32
(pb);
97
if
(tag !=
MKTAG
(
'S'
,
'O'
,
'L'
, 0))
98
return
-1;
99
rate =
avio_rl16
(pb);
100
type =
avio_r8
(pb);
101
avio_skip
(pb, 4);
/* size */
102
if
(magic != 0x0B8D)
103
avio_r8
(pb);
/* newer SOLs contain padding byte */
104
105
codec =
sol_codec_id
(magic, type);
106
channels =
sol_channels
(magic, type);
107
108
if
(codec ==
CODEC_ID_SOL_DPCM
)
109
id
=
sol_codec_type
(magic, type);
110
else
id
= 0;
111
112
/* now we are ready: build format streams */
113
st =
avformat_new_stream
(s,
NULL
);
114
if
(!st)
115
return
-1;
116
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
117
st->
codec
->
codec_tag
=
id
;
118
st->
codec
->
codec_id
= codec;
119
st->
codec
->
channels
= channels;
120
st->
codec
->
sample_rate
= rate;
121
avpriv_set_pts_info
(st, 64, 1, rate);
122
return
0;
123
}
124
125
#define MAX_SIZE 4096
126
127
static
int
sol_read_packet
(
AVFormatContext
*s,
128
AVPacket
*pkt)
129
{
130
int
ret;
131
132
if
(s->
pb
->
eof_reached
)
133
return
AVERROR
(EIO);
134
ret=
av_get_packet
(s->
pb
, pkt,
MAX_SIZE
);
135
if
(ret < 0)
136
return
ret;
137
pkt->
stream_index
= 0;
138
139
/* note: we need to modify the packet size here to handle the last
140
packet */
141
pkt->
size
= ret;
142
return
0;
143
}
144
145
AVInputFormat
ff_sol_demuxer
= {
146
.
name
=
"sol"
,
147
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sierra SOL format"
),
148
.read_probe =
sol_probe
,
149
.read_header =
sol_read_header
,
150
.read_packet =
sol_read_packet
,
151
.read_seek =
pcm_read_seek
,
152
};