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