2 * Sony Playstation (PSX) STR File Demuxer
3 * Copyright (c) 2003 The ffmpeg Project
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * PSX STR file demuxer
23 * by Mike Melanson (melanson@pcisys.net)
24 * This module handles streams that have been ripped from Sony Playstation
25 * CD games. This demuxer can handle either raw STR files (which are just
26 * concatenations of raw compact disc sectors) or STR files with 0x2C-byte
27 * RIFF headers, followed by CD sectors.
34 #define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0])
35 #define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \
36 (((uint8_t*)(x))[2] << 16) | \
37 (((uint8_t*)(x))[1] << 8) | \
40 #define FOURCC_TAG( ch0, ch1, ch2, ch3 ) \
41 ( (long)(unsigned char)(ch0) | \
42 ( (long)(unsigned char)(ch1) << 8 ) | \
43 ( (long)(unsigned char)(ch2) << 16 ) | \
44 ( (long)(unsigned char)(ch3) << 24 ) )
46 #define RIFF_TAG FOURCC_TAG('R', 'I', 'F', 'F')
47 #define CDXA_TAG FOURCC_TAG('C', 'D', 'X', 'A')
49 #define RAW_CD_SECTOR_SIZE 2352
50 #define RAW_CD_SECTOR_DATA_SIZE 2304
51 #define VIDEO_DATA_CHUNK_SIZE 0x7E0
52 #define VIDEO_DATA_HEADER_SIZE 0x38
53 #define RIFF_HEADER_SIZE 0x2C
55 #define CDXA_TYPE_MASK 0x0E
56 #define CDXA_TYPE_DATA 0x08
57 #define CDXA_TYPE_AUDIO 0x04
58 #define CDXA_TYPE_VIDEO 0x02
60 #define STR_MAGIC (0x80010160)
62 typedef struct StrChannel
{
68 /* video parameters */
71 int video_stream_index
;
73 /* audio parameters */
77 int audio_stream_index
;
80 typedef struct StrDemuxContext
{
82 /* a STR file can contain up to 32 channels of data */
83 StrChannel channels
[32];
85 /* only decode the first audio and video channels encountered */
91 unsigned char *video_chunk
;
95 const static char sync_header
[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
97 static int str_probe(AVProbeData
*p
)
101 /* need at least 0x38 bytes to validate */
102 if (p
->buf_size
< 0x38)
105 if ((LE_32(&p
->buf
[0]) == RIFF_TAG
) &&
106 (LE_32(&p
->buf
[8]) == CDXA_TAG
)) {
108 /* RIFF header seen; skip 0x2C bytes */
109 start
= RIFF_HEADER_SIZE
;
113 /* look for CD sync header (00, 0xFF x 10, 00) */
114 if (memcmp(p
->buf
+start
,sync_header
,sizeof(sync_header
)))
117 /* MPEG files (like those ripped from VCDs) can also look like this;
118 * only return half certainty */
122 static void dump(unsigned char *buf
,size_t len
)
126 if ((i
&15)==0) av_log(NULL
, AV_LOG_DEBUG
, "%04x ",i
);
127 av_log(NULL
, AV_LOG_DEBUG
, "%02x ",buf
[i
]);
128 if ((i
&15)==15) av_log(NULL
, AV_LOG_DEBUG
, "\n");
130 av_log(NULL
, AV_LOG_DEBUG
, "\n");
133 static int str_read_header(AVFormatContext
*s
,
134 AVFormatParameters
*ap
)
136 ByteIOContext
*pb
= &s
->pb
;
137 StrDemuxContext
*str
= (StrDemuxContext
*)s
->priv_data
;
139 unsigned char sector
[RAW_CD_SECTOR_SIZE
];
144 /* initialize context members */
146 str
->audio_channel
= -1; /* assume to audio or video */
147 str
->video_channel
= -1;
148 str
->video_chunk
= NULL
;
150 /* set the pts reference (1 pts = 1/90000) */
154 /* skip over any RIFF header */
155 if (get_buffer(pb
, sector
, RIFF_HEADER_SIZE
) != RIFF_HEADER_SIZE
)
157 if (LE_32(§or
[0]) == RIFF_TAG
)
158 start
= RIFF_HEADER_SIZE
;
162 url_fseek(pb
, start
, SEEK_SET
);
164 /* check through the first 32 sectors for individual channels */
165 for (i
= 0; i
< 32; i
++) {
166 if (get_buffer(pb
, sector
, RAW_CD_SECTOR_SIZE
) != RAW_CD_SECTOR_SIZE
)
169 //printf("%02x %02x %02x %02x\n",sector[0x10],sector[0x11],sector[0x12],sector[0x13]);
171 channel
= sector
[0x11];
173 return AVERROR_INVALIDDATA
;
175 switch (sector
[0x12] & CDXA_TYPE_MASK
) {
178 case CDXA_TYPE_VIDEO
:
179 /* check if this channel gets to be the dominant video channel */
180 if (str
->video_channel
== -1) {
181 /* qualify the magic number */
182 if (LE_32(§or
[0x18]) != STR_MAGIC
)
184 str
->video_channel
= channel
;
185 str
->channels
[channel
].type
= STR_VIDEO
;
186 str
->channels
[channel
].width
= LE_16(§or
[0x28]);
187 str
->channels
[channel
].height
= LE_16(§or
[0x2A]);
189 /* allocate a new AVStream */
190 st
= av_new_stream(s
, 0);
192 return AVERROR_NOMEM
;
194 str
->channels
[channel
].video_stream_index
= st
->index
;
196 st
->codec
.codec_type
= CODEC_TYPE_VIDEO
;
197 st
->codec
.codec_id
= CODEC_ID_MDEC
;
198 st
->codec
.codec_tag
= 0; /* no fourcc */
199 st
->codec
.width
= str
->channels
[channel
].width
;
200 st
->codec
.height
= str
->channels
[channel
].height
;
204 case CDXA_TYPE_AUDIO
:
205 /* check if this channel gets to be the dominant audio channel */
206 if (str
->audio_channel
== -1) {
208 str
->audio_channel
= channel
;
209 str
->channels
[channel
].type
= STR_AUDIO
;
210 str
->channels
[channel
].channels
=
211 (sector
[0x13] & 0x01) ?
2 : 1;
212 str
->channels
[channel
].sample_rate
=
213 (sector
[0x13] & 0x04) ?
18900 : 37800;
214 str
->channels
[channel
].bits
=
215 (sector
[0x13] & 0x10) ?
8 : 4;
217 /* allocate a new AVStream */
218 st
= av_new_stream(s
, 0);
220 return AVERROR_NOMEM
;
222 str
->channels
[channel
].audio_stream_index
= st
->index
;
225 st
->codec
.codec_type
= CODEC_TYPE_AUDIO
;
226 st
->codec
.codec_id
= CODEC_ID_ADPCM_XA
;
227 st
->codec
.codec_tag
= 0; /* no fourcc */
228 st
->codec
.channels
= (fmt
&1)?
2:1;
229 st
->codec
.sample_rate
= (fmt
&4)?
18900:37800;
230 // st->codec.bit_rate = 0; //FIXME;
231 st
->codec
.block_align
= 128;
241 if (str
->video_channel
!= -1)
242 av_log (s
, AV_LOG_DEBUG
, " video channel = %d, %d x %d %d\n", str
->video_channel
,
243 str
->channels
[str
->video_channel
].width
,
244 str
->channels
[str
->video_channel
].height
,str
->channels
[str
->video_channel
].video_stream_index
);
245 if (str
->audio_channel
!= -1)
246 av_log (s
, AV_LOG_DEBUG
, " audio channel = %d, %d Hz, %d channels, %d bits/sample %d\n",
248 str
->channels
[str
->audio_channel
].sample_rate
,
249 str
->channels
[str
->audio_channel
].channels
,
250 str
->channels
[str
->audio_channel
].bits
,str
->channels
[str
->audio_channel
].audio_stream_index
);
252 /* back to the start */
253 url_fseek(pb
, start
, SEEK_SET
);
258 static int str_read_packet(AVFormatContext
*s
,
261 ByteIOContext
*pb
= &s
->pb
;
262 StrDemuxContext
*str
= (StrDemuxContext
*)s
->priv_data
;
263 unsigned char sector
[RAW_CD_SECTOR_SIZE
];
269 while (!packet_read
) {
271 if (get_buffer(pb
, sector
, RAW_CD_SECTOR_SIZE
) != RAW_CD_SECTOR_SIZE
)
274 channel
= sector
[0x11];
276 return AVERROR_INVALIDDATA
;
278 switch (sector
[0x12] & CDXA_TYPE_MASK
) {
281 case CDXA_TYPE_VIDEO
:
282 /* check if this the video channel we care about */
283 if (channel
== str
->video_channel
) {
285 int current_sector
= LE_16(§or
[0x1C]);
286 int sector_count
= LE_16(§or
[0x1E]);
287 int frame_size
= LE_32(§or
[0x24]);
289 // printf("%d %d %d\n",current_sector,sector_count,frame_size);
290 /* if this is the first sector of the frame, allocate a pkt */
292 if (current_sector
== 0) {
293 if (av_new_packet(pkt
, frame_size
))
297 str
->channels
[channel
].video_stream_index
;
298 // pkt->pts = str->pts;
300 /* if there is no audio, adjust the pts after every video
301 * frame; assume 15 fps */
302 if (str
->audio_channel
!= -1)
303 str
->pts
+= (90000 / 15);
306 /* load all the constituent chunks in the video packet */
307 bytes_to_copy
= frame_size
- current_sector
*VIDEO_DATA_CHUNK_SIZE
;
308 if (bytes_to_copy
>0) {
309 if (bytes_to_copy
>VIDEO_DATA_CHUNK_SIZE
) bytes_to_copy
=VIDEO_DATA_CHUNK_SIZE
;
310 memcpy(pkt
->data
+ current_sector
*VIDEO_DATA_CHUNK_SIZE
,
311 sector
+ VIDEO_DATA_HEADER_SIZE
, bytes_to_copy
);
313 if (current_sector
== sector_count
-1) {
321 case CDXA_TYPE_AUDIO
:
323 printf (" dropping audio sector\n");
326 /* check if this the video channel we care about */
327 if (channel
== str
->audio_channel
) {
329 if (av_new_packet(pkt
, 2304))
331 memcpy(pkt
->data
,sector
+24,2304);
334 str
->channels
[channel
].audio_stream_index
;
335 //pkt->pts = str->pts;
341 /* drop the sector and move on */
343 printf (" dropping other sector\n");
355 static int str_read_close(AVFormatContext
*s
)
357 StrDemuxContext
*str
= (StrDemuxContext
*)s
->priv_data
;
359 av_free(str
->video_chunk
);
364 static AVInputFormat str_iformat
= {
366 "Sony Playstation STR format",
367 sizeof(StrDemuxContext
),
376 av_register_input_format(&str_iformat
);