Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
libavformat
psxstr.c
Go to the documentation of this file.
1
/*
2
* Sony Playstation (PSX) STR File Demuxer
3
* Copyright (c) 2003 The ffmpeg Project
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
32
#include "
libavutil/channel_layout.h
"
33
#include "
libavutil/intreadwrite.h
"
34
#include "
avformat.h
"
35
#include "
internal.h
"
36
37
#define RIFF_TAG MKTAG('R', 'I', 'F', 'F')
38
#define CDXA_TAG MKTAG('C', 'D', 'X', 'A')
39
40
#define RAW_CD_SECTOR_SIZE 2352
41
#define RAW_CD_SECTOR_DATA_SIZE 2304
42
#define VIDEO_DATA_CHUNK_SIZE 0x7E0
43
#define VIDEO_DATA_HEADER_SIZE 0x38
44
#define RIFF_HEADER_SIZE 0x2C
45
46
#define CDXA_TYPE_MASK 0x0E
47
#define CDXA_TYPE_DATA 0x08
48
#define CDXA_TYPE_AUDIO 0x04
49
#define CDXA_TYPE_VIDEO 0x02
50
51
#define STR_MAGIC (0x80010160)
52
53
typedef
struct
StrChannel
{
54
/* video parameters */
55
int
video_stream_index
;
56
AVPacket
tmp_pkt
;
57
58
/* audio parameters */
59
int
audio_stream_index
;
60
}
StrChannel
;
61
62
typedef
struct
StrDemuxContext
{
63
64
/* a STR file can contain up to 32 channels of data */
65
StrChannel
channels
[32];
66
}
StrDemuxContext
;
67
68
static
const
char
sync_header
[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
69
70
static
int
str_probe
(
AVProbeData
*p)
71
{
72
uint8_t
*sector= p->
buf
;
73
74
if
(p->
buf_size
<
RAW_CD_SECTOR_SIZE
)
75
return
0;
76
77
if
((
AV_RL32
(&p->
buf
[0]) ==
RIFF_TAG
) &&
78
(
AV_RL32
(&p->
buf
[8]) ==
CDXA_TAG
)) {
79
80
/* RIFF header seen; skip 0x2C bytes */
81
sector +=
RIFF_HEADER_SIZE
;
82
}
83
84
/* look for CD sync header (00, 0xFF x 10, 00) */
85
if
(memcmp(sector,
sync_header
,
sizeof
(
sync_header
)))
86
return
0;
87
88
if
(sector[0x11] >= 32)
89
return
0;
90
if
( (sector[0x12] &
CDXA_TYPE_MASK
) !=
CDXA_TYPE_VIDEO
91
&& (sector[0x12] & CDXA_TYPE_MASK) !=
CDXA_TYPE_AUDIO
92
&& (sector[0x12] & CDXA_TYPE_MASK) !=
CDXA_TYPE_DATA
)
93
return
0;
94
95
/* MPEG files (like those ripped from VCDs) can also look like this;
96
* only return half certainty */
97
return
50;
98
}
99
100
static
int
str_read_header
(
AVFormatContext
*s)
101
{
102
AVIOContext
*pb = s->
pb
;
103
StrDemuxContext
*str = s->
priv_data
;
104
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
105
int
start;
106
int
i;
107
108
/* skip over any RIFF header */
109
if
(
avio_read
(pb, sector,
RIFF_HEADER_SIZE
) !=
RIFF_HEADER_SIZE
)
110
return
AVERROR
(EIO);
111
if
(
AV_RL32
(§or[0]) ==
RIFF_TAG
)
112
start =
RIFF_HEADER_SIZE
;
113
else
114
start = 0;
115
116
avio_seek
(pb, start, SEEK_SET);
117
118
for
(i=0; i<32; i++){
119
str->
channels
[i].
video_stream_index
=
120
str->
channels
[i].
audio_stream_index
= -1;
121
}
122
123
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
124
125
return
0;
126
}
127
128
static
int
str_read_packet
(
AVFormatContext
*s,
129
AVPacket
*ret_pkt)
130
{
131
AVIOContext
*pb = s->
pb
;
132
StrDemuxContext
*str = s->
priv_data
;
133
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
134
int
channel;
135
AVPacket
*pkt;
136
AVStream
*st;
137
138
while
(1) {
139
140
if
(
avio_read
(pb, sector,
RAW_CD_SECTOR_SIZE
) !=
RAW_CD_SECTOR_SIZE
)
141
return
AVERROR
(EIO);
142
143
channel = sector[0x11];
144
if
(channel >= 32)
145
return
AVERROR_INVALIDDATA
;
146
147
switch
(sector[0x12] &
CDXA_TYPE_MASK
) {
148
149
case
CDXA_TYPE_DATA
:
150
case
CDXA_TYPE_VIDEO
:
151
{
152
153
int
current_sector =
AV_RL16
(§or[0x1C]);
154
int
sector_count =
AV_RL16
(§or[0x1E]);
155
int
frame_size
=
AV_RL32
(§or[0x24]);
156
157
if
(!( frame_size>=0
158
&& current_sector < sector_count
159
&& sector_count*
VIDEO_DATA_CHUNK_SIZE
>=frame_size)){
160
av_log
(s,
AV_LOG_ERROR
,
"Invalid parameters %d %d %d\n"
, current_sector, sector_count, frame_size);
161
break
;
162
}
163
164
if
(str->
channels
[channel].
video_stream_index
< 0){
165
/* allocate a new AVStream */
166
st =
avformat_new_stream
(s,
NULL
);
167
if
(!st)
168
return
AVERROR
(ENOMEM);
169
avpriv_set_pts_info
(st, 64, 1, 15);
170
171
str->
channels
[channel].
video_stream_index
= st->
index
;
172
173
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
174
st->
codec
->
codec_id
=
AV_CODEC_ID_MDEC
;
175
st->
codec
->
codec_tag
= 0;
/* no fourcc */
176
st->
codec
->
width
=
AV_RL16
(§or[0x28]);
177
st->
codec
->
height
=
AV_RL16
(§or[0x2A]);
178
}
179
180
/* if this is the first sector of the frame, allocate a pkt */
181
pkt = &str->
channels
[channel].
tmp_pkt
;
182
183
if
(pkt->
size
!= sector_count*
VIDEO_DATA_CHUNK_SIZE
){
184
if
(pkt->
data
)
185
av_log
(s,
AV_LOG_ERROR
,
"missmatching sector_count\n"
);
186
av_free_packet
(pkt);
187
if
(
av_new_packet
(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE))
188
return
AVERROR
(EIO);
189
190
pkt->
pos
=
avio_tell
(pb) -
RAW_CD_SECTOR_SIZE
;
191
pkt->
stream_index
=
192
str->
channels
[channel].
video_stream_index
;
193
}
194
195
memcpy(pkt->
data
+ current_sector*VIDEO_DATA_CHUNK_SIZE,
196
sector +
VIDEO_DATA_HEADER_SIZE
,
197
VIDEO_DATA_CHUNK_SIZE);
198
199
if
(current_sector == sector_count-1) {
200
pkt->
size
=
frame_size
;
201
*ret_pkt = *pkt;
202
pkt->
data
=
NULL
;
203
pkt->
size
= -1;
204
return
0;
205
}
206
207
}
208
break
;
209
210
case
CDXA_TYPE_AUDIO
:
211
if
(str->
channels
[channel].
audio_stream_index
< 0){
212
int
fmt = sector[0x13];
213
/* allocate a new AVStream */
214
st =
avformat_new_stream
(s,
NULL
);
215
if
(!st)
216
return
AVERROR
(ENOMEM);
217
218
str->
channels
[channel].
audio_stream_index
= st->
index
;
219
220
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
221
st->
codec
->
codec_id
=
AV_CODEC_ID_ADPCM_XA
;
222
st->
codec
->
codec_tag
= 0;
/* no fourcc */
223
if
(fmt & 1) {
224
st->
codec
->
channels
= 2;
225
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
226
}
else
{
227
st->
codec
->
channels
= 1;
228
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
229
}
230
st->
codec
->
sample_rate
= (fmt&4)?18900:37800;
231
// st->codec->bit_rate = 0; //FIXME;
232
st->
codec
->
block_align
= 128;
233
234
avpriv_set_pts_info
(st, 64, 18 * 224 / st->
codec
->
channels
,
235
st->
codec
->
sample_rate
);
236
st->
start_time
= 0;
237
}
238
pkt = ret_pkt;
239
if
(
av_new_packet
(pkt, 2304))
240
return
AVERROR
(EIO);
241
memcpy(pkt->
data
,sector+24,2304);
242
243
pkt->
stream_index
=
244
str->
channels
[channel].
audio_stream_index
;
245
pkt->
duration
= 1;
246
return
0;
247
default
:
248
av_log
(s,
AV_LOG_WARNING
,
"Unknown sector type %02X\n"
, sector[0x12]);
249
/* drop the sector and move on */
250
break
;
251
}
252
253
if
(pb->
eof_reached
)
254
return
AVERROR
(EIO);
255
}
256
}
257
258
static
int
str_read_close
(
AVFormatContext
*s)
259
{
260
StrDemuxContext
*str = s->
priv_data
;
261
int
i;
262
for
(i=0; i<32; i++){
263
if
(str->
channels
[i].
tmp_pkt
.
data
)
264
av_free_packet
(&str->
channels
[i].
tmp_pkt
);
265
}
266
267
return
0;
268
}
269
270
AVInputFormat
ff_str_demuxer
= {
271
.
name
=
"psxstr"
,
272
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sony Playstation STR"
),
273
.priv_data_size =
sizeof
(
StrDemuxContext
),
274
.
read_probe
=
str_probe
,
275
.
read_header
=
str_read_header
,
276
.
read_packet
=
str_read_packet
,
277
.
read_close
=
str_read_close
,
278
.
flags
=
AVFMT_NO_BYTE_SEEK
,
279
};