Libav
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/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
char
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
uint8_t
*sector= p->
buf
;
74
75
if
(p->
buf_size
<
RAW_CD_SECTOR_SIZE
)
76
return
0;
77
78
if
((
AV_RL32
(&p->
buf
[0]) ==
RIFF_TAG
) &&
79
(
AV_RL32
(&p->
buf
[8]) ==
CDXA_TAG
)) {
80
81
/* RIFF header seen; skip 0x2C bytes */
82
sector +=
RIFF_HEADER_SIZE
;
83
}
84
85
/* look for CD sync header (00, 0xFF x 10, 00) */
86
if
(memcmp(sector,
sync_header
,
sizeof
(
sync_header
)))
87
return
0;
88
89
if
(sector[0x11] >= 32)
90
return
0;
91
if
( (sector[0x12] &
CDXA_TYPE_MASK
) !=
CDXA_TYPE_VIDEO
92
&& (sector[0x12] & CDXA_TYPE_MASK) !=
CDXA_TYPE_AUDIO
93
&& (sector[0x12] & CDXA_TYPE_MASK) !=
CDXA_TYPE_DATA
)
94
return
0;
95
96
/* MPEG files (like those ripped from VCDs) can also look like this;
97
* only return half certainty */
98
return
AVPROBE_SCORE_EXTENSION
;
99
}
100
101
static
int
str_read_header
(
AVFormatContext
*s)
102
{
103
AVIOContext
*pb = s->
pb
;
104
StrDemuxContext
*str = s->
priv_data
;
105
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
106
int
start;
107
int
i;
108
109
/* skip over any RIFF header */
110
if
(
avio_read
(pb, sector,
RIFF_HEADER_SIZE
) !=
RIFF_HEADER_SIZE
)
111
return
AVERROR
(EIO);
112
if
(
AV_RL32
(§or[0]) ==
RIFF_TAG
)
113
start =
RIFF_HEADER_SIZE
;
114
else
115
start = 0;
116
117
avio_seek
(pb, start, SEEK_SET);
118
119
for
(i=0; i<32; i++){
120
str->
channels
[i].
video_stream_index
=
121
str->
channels
[i].
audio_stream_index
= -1;
122
}
123
124
s->
ctx_flags
|=
AVFMTCTX_NOHEADER
;
125
126
return
0;
127
}
128
129
static
int
str_read_packet
(
AVFormatContext
*s,
130
AVPacket
*ret_pkt)
131
{
132
AVIOContext
*pb = s->
pb
;
133
StrDemuxContext
*str = s->
priv_data
;
134
unsigned
char
sector[
RAW_CD_SECTOR_SIZE
];
135
int
channel;
136
AVPacket
*pkt;
137
AVStream
*st;
138
139
while
(1) {
140
141
if
(
avio_read
(pb, sector,
RAW_CD_SECTOR_SIZE
) !=
RAW_CD_SECTOR_SIZE
)
142
return
AVERROR
(EIO);
143
144
channel = sector[0x11];
145
if
(channel >= 32)
146
return
AVERROR_INVALIDDATA
;
147
148
switch
(sector[0x12] &
CDXA_TYPE_MASK
) {
149
150
case
CDXA_TYPE_DATA
:
151
case
CDXA_TYPE_VIDEO
:
152
{
153
154
int
current_sector =
AV_RL16
(§or[0x1C]);
155
int
sector_count =
AV_RL16
(§or[0x1E]);
156
int
frame_size
=
AV_RL32
(§or[0x24]);
157
158
if
(!( frame_size>=0
159
&& current_sector < sector_count
160
&& sector_count*
VIDEO_DATA_CHUNK_SIZE
>=frame_size)){
161
av_log
(s,
AV_LOG_ERROR
,
"Invalid parameters %d %d %d\n"
, current_sector, sector_count, frame_size);
162
break
;
163
}
164
165
if
(str->
channels
[channel].
video_stream_index
< 0){
166
/* allocate a new AVStream */
167
st =
avformat_new_stream
(s,
NULL
);
168
if
(!st)
169
return
AVERROR
(ENOMEM);
170
avpriv_set_pts_info
(st, 64, 1, 15);
171
172
str->
channels
[channel].
video_stream_index
= st->
index
;
173
174
st->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
175
st->
codec
->
codec_id
=
AV_CODEC_ID_MDEC
;
176
st->
codec
->
codec_tag
= 0;
/* no fourcc */
177
st->
codec
->
width
=
AV_RL16
(§or[0x28]);
178
st->
codec
->
height
=
AV_RL16
(§or[0x2A]);
179
}
180
181
/* if this is the first sector of the frame, allocate a pkt */
182
pkt = &str->
channels
[channel].
tmp_pkt
;
183
184
if
(pkt->
size
!= sector_count*
VIDEO_DATA_CHUNK_SIZE
){
185
if
(pkt->
data
)
186
av_log
(s,
AV_LOG_ERROR
,
"missmatching sector_count\n"
);
187
av_free_packet
(pkt);
188
if
(
av_new_packet
(pkt, sector_count*VIDEO_DATA_CHUNK_SIZE))
189
return
AVERROR
(EIO);
190
191
pkt->
pos
=
avio_tell
(pb) -
RAW_CD_SECTOR_SIZE
;
192
pkt->
stream_index
=
193
str->
channels
[channel].
video_stream_index
;
194
}
195
196
memcpy(pkt->
data
+ current_sector*VIDEO_DATA_CHUNK_SIZE,
197
sector +
VIDEO_DATA_HEADER_SIZE
,
198
VIDEO_DATA_CHUNK_SIZE);
199
200
if
(current_sector == sector_count-1) {
201
pkt->
size
=
frame_size
;
202
*ret_pkt = *pkt;
203
pkt->
data
=
NULL
;
204
pkt->
size
= -1;
205
pkt->
buf
=
NULL
;
206
#if FF_API_DESTRUCT_PACKET
207
FF_DISABLE_DEPRECATION_WARNINGS
208
pkt->
destruct
=
NULL
;
209
FF_ENABLE_DEPRECATION_WARNINGS
210
#endif
211
return
0;
212
}
213
214
}
215
break
;
216
217
case
CDXA_TYPE_AUDIO
:
218
if
(str->
channels
[channel].
audio_stream_index
< 0){
219
int
fmt = sector[0x13];
220
/* allocate a new AVStream */
221
st =
avformat_new_stream
(s,
NULL
);
222
if
(!st)
223
return
AVERROR
(ENOMEM);
224
225
str->
channels
[channel].
audio_stream_index
= st->
index
;
226
227
st->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
228
st->
codec
->
codec_id
=
AV_CODEC_ID_ADPCM_XA
;
229
st->
codec
->
codec_tag
= 0;
/* no fourcc */
230
if
(fmt & 1) {
231
st->
codec
->
channels
= 2;
232
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_STEREO
;
233
}
else
{
234
st->
codec
->
channels
= 1;
235
st->
codec
->
channel_layout
=
AV_CH_LAYOUT_MONO
;
236
}
237
st->
codec
->
sample_rate
= (fmt&4)?18900:37800;
238
// st->codec->bit_rate = 0; //FIXME;
239
st->
codec
->
block_align
= 128;
240
241
avpriv_set_pts_info
(st, 64, 18 * 224 / st->
codec
->
channels
,
242
st->
codec
->
sample_rate
);
243
st->
start_time
= 0;
244
}
245
pkt = ret_pkt;
246
if
(
av_new_packet
(pkt, 2304))
247
return
AVERROR
(EIO);
248
memcpy(pkt->
data
,sector+24,2304);
249
250
pkt->
stream_index
=
251
str->
channels
[channel].
audio_stream_index
;
252
pkt->
duration
= 1;
253
return
0;
254
default
:
255
av_log
(s,
AV_LOG_WARNING
,
"Unknown sector type %02X\n"
, sector[0x12]);
256
/* drop the sector and move on */
257
break
;
258
}
259
260
if
(pb->
eof_reached
)
261
return
AVERROR
(EIO);
262
}
263
}
264
265
static
int
str_read_close
(
AVFormatContext
*s)
266
{
267
StrDemuxContext
*str = s->
priv_data
;
268
int
i;
269
for
(i=0; i<32; i++){
270
if
(str->
channels
[i].
tmp_pkt
.
data
)
271
av_free_packet
(&str->
channels
[i].
tmp_pkt
);
272
}
273
274
return
0;
275
}
276
277
AVInputFormat
ff_str_demuxer
= {
278
.
name
=
"psxstr"
,
279
.long_name =
NULL_IF_CONFIG_SMALL
(
"Sony Playstation STR"
),
280
.priv_data_size =
sizeof
(
StrDemuxContext
),
281
.
read_probe
=
str_probe
,
282
.
read_header
=
str_read_header
,
283
.
read_packet
=
str_read_packet
,
284
.
read_close
=
str_read_close
,
285
.
flags
=
AVFMT_NO_BYTE_SEEK
,
286
};
Generated on Tue Mar 1 2016 21:14:50 for Libav by
1.8.4