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
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
AVPROBE_SCORE_EXTENSION
;
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
pkt->
buf
= NULL;
239
#if FF_API_DESTRUCT_PACKET
240
pkt->destruct = NULL;
241
#endif
242
return
0;
243
}
244
245
}
246
break
;
247
248
case
CDXA_TYPE_AUDIO
:
249
if
(str->
channels
[channel].
audio_stream_index
< 0){
250
int
fmt
= sector[0x13];
251
/* allocate a new AVStream */
252
st =
avformat_new_stream
(s, NULL);
253
if
(!st)
254
return
AVERROR
(ENOMEM);
255
256
str->
channels
[channel].
audio_stream_index
= st->
index
;
257
258
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
259
st->
codec
->
codec_id
=
AV_CODEC_ID_ADPCM_XA
;
260
st->
codec
->
codec_tag
= 0;
/* no fourcc */
261
if
(fmt & 1) {
262
st->
codec
->
channels
= 2;
263
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
264
}
else
{
265
st->
codec
->
channels
= 1;
266
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
267
}
268
st->
codec
->
sample_rate
= (fmt&4)?18900:37800;
269
// st->codec->bit_rate = 0; //FIXME;
270
st->
codec
->
block_align
= 128;
271
272
avpriv_set_pts_info
(st, 64, 18 * 224 / st->
codec
->
channels
,
273
st->
codec
->
sample_rate
);
274
st->
start_time
= 0;
275
}
276
pkt = ret_pkt;
277
if
(
av_new_packet
(pkt, 2304))
278
return
AVERROR
(EIO);
279
memcpy(pkt->
data
,sector+24,2304);
280
281
pkt->
stream_index
=
282
str->
channels
[channel].
audio_stream_index
;
283
pkt->
duration
= 1;
284
return
0;
285
default
:
286
av_log
(s,
AV_LOG_WARNING
,
"Unknown sector type %02X\n"
, sector[0x12]);
287
/* drop the sector and move on */
288
break
;
289
}
290
291
if
(
url_feof
(pb))
292
return
AVERROR
(EIO);
293
}
294
}
295
296
static
int
str_read_close
(
AVFormatContext
*
s
)
297
{
298
StrDemuxContext
*str = s->
priv_data
;
299
int
i;
300
for
(i=0; i<32; i++){
301
if
(str->
channels
[i].
tmp_pkt
.
data
)
302
av_free_packet
(&str->
channels
[i].
tmp_pkt
);
303
}
304
305
return
0;
306
}
307
308
AVInputFormat
ff_str_demuxer
= {
309
.
name
=
"psxstr"
,
310
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sony Playstation STR"
),
311
.priv_data_size =
sizeof
(
StrDemuxContext
),
312
.
read_probe
=
str_probe
,
313
.
read_header
=
str_read_header
,
314
.
read_packet
=
str_read_packet
,
315
.
read_close
=
str_read_close
,
316
.
flags
=
AVFMT_NO_BYTE_SEEK
,
317
};
Generated on Wed Jul 10 2013 23:48:13 for FFmpeg by
1.8.2