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
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 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
/*
23
* Based on documents from Game Audio Player and own research
24
*/
25
26
#include "
libavutil/channel_layout.h
"
27
#include "
libavutil/intreadwrite.h
"
28
#include "
avformat.h
"
29
#include "
internal.h
"
30
#include "
pcm.h
"
31
32
/* if we don't know the size in advance */
33
#define AU_UNKNOWN_SIZE ((uint32_t)(~0))
34
35
static
int
sol_probe
(
AVProbeData
*p)
36
{
37
/* check file header */
38
uint16_t magic =
AV_RL32
(p->
buf
);
39
if
((magic == 0x0B8D || magic == 0x0C0D || magic == 0x0C8D) &&
40
p->
buf
[2] ==
'S'
&& p->
buf
[3] ==
'O'
&&
41
p->
buf
[4] ==
'L'
&& p->
buf
[5] == 0)
42
return
AVPROBE_SCORE_MAX
;
43
else
44
return
0;
45
}
46
47
#define SOL_DPCM 1
48
#define SOL_16BIT 4
49
#define SOL_STEREO 16
50
51
static
enum
AVCodecID
sol_codec_id
(
int
magic,
int
type
)
52
{
53
if
(magic == 0x0B8D)
54
{
55
if
(type &
SOL_DPCM
)
return
AV_CODEC_ID_SOL_DPCM
;
56
else
return
AV_CODEC_ID_PCM_U8
;
57
}
58
if
(type &
SOL_DPCM
)
59
{
60
if
(type &
SOL_16BIT
)
return
AV_CODEC_ID_SOL_DPCM
;
61
else
if
(magic == 0x0C8D)
return
AV_CODEC_ID_SOL_DPCM
;
62
else
return
AV_CODEC_ID_SOL_DPCM
;
63
}
64
if
(type &
SOL_16BIT
)
return
AV_CODEC_ID_PCM_S16LE
;
65
return
AV_CODEC_ID_PCM_U8
;
66
}
67
68
static
int
sol_codec_type
(
int
magic,
int
type
)
69
{
70
if
(magic == 0x0B8D)
return
1;
//SOL_DPCM_OLD;
71
if
(type &
SOL_DPCM
)
72
{
73
if
(type &
SOL_16BIT
)
return
3;
//SOL_DPCM_NEW16;
74
else
if
(magic == 0x0C8D)
return
1;
//SOL_DPCM_OLD;
75
else
return
2;
//SOL_DPCM_NEW8;
76
}
77
return
-1;
78
}
79
80
static
int
sol_channels
(
int
magic,
int
type
)
81
{
82
if
(magic == 0x0B8D || !(type &
SOL_STEREO
))
return
1;
83
return
2;
84
}
85
86
static
int
sol_read_header
(
AVFormatContext
*
s
)
87
{
88
unsigned
int
magic,
tag
;
89
AVIOContext
*pb = s->
pb
;
90
unsigned
int
id
, channels, rate,
type
;
91
enum
AVCodecID
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 ==
AV_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
->
channel_layout
= channels == 1 ?
AV_CH_LAYOUT_MONO
:
121
AV_CH_LAYOUT_STEREO
;
122
st->
codec
->
sample_rate
= rate;
123
avpriv_set_pts_info
(st, 64, 1, rate);
124
return
0;
125
}
126
127
#define MAX_SIZE 4096
128
129
static
int
sol_read_packet
(
AVFormatContext
*
s
,
130
AVPacket
*
pkt
)
131
{
132
int
ret
;
133
134
if
(
avio_feof
(s->
pb
))
135
return
AVERROR
(EIO);
136
ret=
av_get_packet
(s->
pb
, pkt,
MAX_SIZE
);
137
if
(ret < 0)
138
return
ret
;
139
pkt->
flags
&= ~
AV_PKT_FLAG_CORRUPT
;
140
pkt->
stream_index
= 0;
141
return
0;
142
}
143
144
AVInputFormat
ff_sol_demuxer
= {
145
.
name
=
"sol"
,
146
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sierra SOL"
),
147
.read_probe =
sol_probe
,
148
.read_header =
sol_read_header
,
149
.read_packet =
sol_read_packet
,
150
.read_seek =
ff_pcm_read_seek
,
151
};
Generated on Sun Sep 14 2014 18:56:15 for FFmpeg by
1.8.2