FFmpeg
Main Page
Related Pages
Modules
Data Structures
Files
Examples
File List
Globals
•
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
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 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
* @file
24
* PSX STR file demuxer
25
* by Mike Melanson (melanson@pcisys.net)
26
* This module handles streams that have been ripped from Sony Playstation
27
* CD games. This demuxer can handle either raw STR files (which are just
28
* concatenations of raw compact disc sectors) or STR files with 0x2C-byte
29
* RIFF headers, followed by CD sectors.
30
*/
31
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
uint8_t
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
const
uint8_t
*sector= p->
buf
;
73
const
uint8_t
*
end
= sector + p->
buf_size
;
74
int
aud=0, vid=0;
75
76
if
(p->
buf_size
<
RAW_CD_SECTOR_SIZE
)
77
return
0;
78
79
if
((
AV_RL32
(&p->
buf
[0]) ==
RIFF_TAG
) &&
80
(
AV_RL32
(&p->
buf
[8]) ==
CDXA_TAG
)) {
81
82
/* RIFF header seen; skip 0x2C bytes */
83
sector +=
RIFF_HEADER_SIZE
;
84
}
85
86
while
(end - sector >=
RAW_CD_SECTOR_SIZE
) {
87
/* look for CD sync header (00, 0xFF x 10, 00) */
88
if
(memcmp(sector,
sync_header
,
sizeof
(
sync_header
)))
89
return
0;
90
91
if
(sector[0x11] >= 32)
92
return
0;
93
94
switch
(sector[0x12] &
CDXA_TYPE_MASK
) {
95
case
CDXA_TYPE_DATA
:
96
case
CDXA_TYPE_VIDEO
: {
97
int
current_sector =
AV_RL16
(§or[0x1C]);
98
int
sector_count =
AV_RL16
(§or[0x1E]);
99
int
frame_size
=
AV_RL32
(§or[0x24]);
100
101
if
(!( frame_size>=0
102
&& current_sector < sector_count
103
&& sector_count*
VIDEO_DATA_CHUNK_SIZE
>=frame_size)){
104
return
0;
105
}
106
107
/*st->codec->width = AV_RL16(§or[0x28]);
108
st->codec->height = AV_RL16(§or[0x2A]);*/
109
110
// if (current_sector == sector_count-1) {
111
vid++;
112
// }
113
114
}
115
break
;
116
case
CDXA_TYPE_AUDIO
:
117
if
(sector[0x13]&0x2A)
118
return
0;
119
aud++;
120
break
;
121
default
:
122
if
(sector[0x12] & CDXA_TYPE_MASK)
123
return
0;
124
}
125
sector +=
RAW_CD_SECTOR_SIZE
;
126
}
127
/* MPEG files (like those ripped from VCDs) can also look like this;
128
* only return half certainty */
129
if
(vid+aud > 3)
return
50;
130
else
if
(vid+aud)
return
1;
131
else
return
0;
132
}
133
134
static
int
str_read_header
(
AVFormatContext
*s)
135
{
136
AVIOContext
*pb = s->
pb
;
137
StrDemuxContext
*str = s->
priv_data
;
138
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
139
int
start;
140
int
i;
141
142
/* skip over any RIFF header */
143
if
(
avio_read
(pb, sector,
RIFF_HEADER_SIZE
) !=
RIFF_HEADER_SIZE
)
144
return
AVERROR
(EIO);
145
if
(
AV_RL32
(§or[0]) ==
RIFF_TAG
)
146
start =
RIFF_HEADER_SIZE
;
147
else
148
start = 0;
149
150
avio_seek
(pb, start, SEEK_SET);
151
152
for
(i=0; i<32; i++){
153
str->
channels
[i].
video_stream_index
=
154
str->
channels
[i].
audio_stream_index
= -1;
155
}
156
157
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
158
159
return
0;
160
}
161
162
static
int
str_read_packet
(
AVFormatContext
*s,
163
AVPacket
*ret_pkt)
164
{
165
AVIOContext
*pb = s->
pb
;
166
StrDemuxContext
*str = s->
priv_data
;
167
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
168
int
channel;
169
AVPacket
*
pkt
;
170
AVStream
*st;
171
172
while
(1) {
173
174
if
(
avio_read
(pb, sector,
RAW_CD_SECTOR_SIZE
) !=
RAW_CD_SECTOR_SIZE
)
175
return
AVERROR
(EIO);
176
177
channel = sector[0x11];
178
if
(channel >= 32)
179
return
AVERROR_INVALIDDATA
;
180
181
switch
(sector[0x12] &
CDXA_TYPE_MASK
) {
182
183
case
CDXA_TYPE_DATA
:
184
case
CDXA_TYPE_VIDEO
:
185
{
186
187
int
current_sector =
AV_RL16
(§or[0x1C]);
188
int
sector_count =
AV_RL16
(§or[0x1E]);
189
int
frame_size
=
AV_RL32
(§or[0x24]);
190
191
if
(!( frame_size>=0
192
&& current_sector < sector_count
193
&& sector_count*
VIDEO_DATA_CHUNK_SIZE
>=frame_size)){
194
av_log
(s,
AV_LOG_ERROR
,
"Invalid parameters %d %d %d\n"
, current_sector, sector_count, frame_size);
195
break
;
196
}
197
198
if
(str->
channels
[channel].
video_stream_index
< 0){
199
/* allocate a new AVStream */
200
st =
avformat_new_stream
(s,
NULL
);
201
if
(!st)
202
return
AVERROR
(ENOMEM);
203
avpriv_set_pts_info
(st, 64, 1, 15);
204
205
str->
channels
[channel].
video_stream_index
= st->
index
;
206
207
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
208
st->
codec
->
codec_id
=
AV_CODEC_ID_MDEC
;
209
st->
codec
->
codec_tag
= 0;
/* no fourcc */
210
st->
codec
->
width
=
AV_RL16
(§or[0x28]);
211
st->
codec
->
height
=
AV_RL16
(§or[0x2A]);
212
}
213
214
/* if this is the first sector of the frame, allocate a pkt */
215
pkt = &str->
channels
[channel].
tmp_pkt
;
216
217
if
(pkt->
size
!= sector_count*
VIDEO_DATA_CHUNK_SIZE
){
218
if
(pkt->
data
)
219
av_log
(s,
AV_LOG_ERROR
,
"missmatching sector_count\n"
);
220
av_free_packet
(pkt);
221
if
(
av_new_packet
(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE))
222
return
AVERROR
(EIO);
223
224
pkt->
pos
=
avio_tell
(pb) -
RAW_CD_SECTOR_SIZE
;
225
pkt->
stream_index
=
226
str->
channels
[channel].
video_stream_index
;
227
}
228
229
memcpy(pkt->
data
+ current_sector*VIDEO_DATA_CHUNK_SIZE,
230
sector +
VIDEO_DATA_HEADER_SIZE
,
231
VIDEO_DATA_CHUNK_SIZE);
232
233
if
(current_sector == sector_count-1) {
234
pkt->
size
=
frame_size
;
235
*ret_pkt = *
pkt
;
236
pkt->
data
=
NULL
;
237
pkt->
size
= -1;
238
return
0;
239
}
240
241
}
242
break
;
243
244
case
CDXA_TYPE_AUDIO
:
245
if
(str->
channels
[channel].
audio_stream_index
< 0){
246
int
fmt
= sector[0x13];
247
/* allocate a new AVStream */
248
st =
avformat_new_stream
(s,
NULL
);
249
if
(!st)
250
return
AVERROR
(ENOMEM);
251
252
str->
channels
[channel].
audio_stream_index
= st->
index
;
253
254
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
255
st->
codec
->
codec_id
=
AV_CODEC_ID_ADPCM_XA
;
256
st->
codec
->
codec_tag
= 0;
/* no fourcc */
257
if
(fmt & 1) {
258
st->
codec
->
channels
= 2;
259
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
260
}
else
{
261
st->
codec
->
channels
= 1;
262
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
263
}
264
st->
codec
->
sample_rate
= (fmt&4)?18900:37800;
265
// st->codec->bit_rate = 0; //FIXME;
266
st->
codec
->
block_align
= 128;
267
268
avpriv_set_pts_info
(st, 64, 18 * 224 / st->
codec
->
channels
,
269
st->
codec
->
sample_rate
);
270
st->
start_time
= 0;
271
}
272
pkt = ret_pkt;
273
if
(
av_new_packet
(pkt, 2304))
274
return
AVERROR
(EIO);
275
memcpy(pkt->
data
,sector+24,2304);
276
277
pkt->
stream_index
=
278
str->
channels
[channel].
audio_stream_index
;
279
pkt->
duration
= 1;
280
return
0;
281
default
:
282
av_log
(s,
AV_LOG_WARNING
,
"Unknown sector type %02X\n"
, sector[0x12]);
283
/* drop the sector and move on */
284
break
;
285
}
286
287
if
(
url_feof
(pb))
288
return
AVERROR
(EIO);
289
}
290
}
291
292
static
int
str_read_close
(
AVFormatContext
*s)
293
{
294
StrDemuxContext
*str = s->
priv_data
;
295
int
i;
296
for
(i=0; i<32; i++){
297
if
(str->
channels
[i].
tmp_pkt
.
data
)
298
av_free_packet
(&str->
channels
[i].
tmp_pkt
);
299
}
300
301
return
0;
302
}
303
304
AVInputFormat
ff_str_demuxer
= {
305
.
name
=
"psxstr"
,
306
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sony Playstation STR"
),
307
.priv_data_size =
sizeof
(
StrDemuxContext
),
308
.
read_probe
=
str_probe
,
309
.
read_header
=
str_read_header
,
310
.
read_packet
=
str_read_packet
,
311
.
read_close
=
str_read_close
,
312
.
flags
=
AVFMT_NO_BYTE_SEEK
,
313
};
Generated on Sat May 25 2013 03:58:48 for FFmpeg by
1.8.2