]> git.sesse.net Git - ffmpeg/blob - libavformat/psxstr.c
hook up the XA ADPCM decoder
[ffmpeg] / libavformat / psxstr.c
1 /*
2  * Sony Playstation (PSX) STR File Demuxer
3  * Copyright (c) 2003 The ffmpeg Project
4  *
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.
9  *
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.
14  *
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
18  */
19
20 /**
21  * @file psxstr.c
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.
28  */
29
30 #include "avformat.h"
31
32 //#define PRINTSTUFF
33
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) | \
38                     ((uint8_t*)(x))[0])
39
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 ) )
45
46 #define RIFF_TAG FOURCC_TAG('R', 'I', 'F', 'F')
47 #define CDXA_TAG FOURCC_TAG('C', 'D', 'X', 'A')
48
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
54
55 #define CDXA_TYPE_MASK     0x0E
56 #define CDXA_TYPE_DATA     0x08
57 #define CDXA_TYPE_AUDIO    0x04
58 #define CDXA_TYPE_VIDEO    0x02
59
60 #define STR_MAGIC (0x80010160)
61
62 typedef struct StrChannel {
63
64     int type;
65 #define STR_AUDIO 0
66 #define STR_VIDEO 1
67
68     /* video parameters */
69     int width;
70     int height;
71     int video_stream_index;
72
73     /* audio parameters */
74     int sample_rate;
75     int channels;
76     int bits;
77     int audio_stream_index;
78 } StrChannel;
79
80 typedef struct StrDemuxContext {
81
82     /* a STR file can contain up to 32 channels of data */
83     StrChannel channels[32];
84
85     /* only decode the first audio and video channels encountered */
86     int video_channel;
87     int audio_channel;
88
89     int64_t pts;
90
91     unsigned char *video_chunk;
92     AVPacket tmp_pkt;
93 } StrDemuxContext;
94
95 const static char sync_header[12] = {0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00};
96
97 static int str_probe(AVProbeData *p)
98 {
99     int start;
100
101     /* need at least 0x38 bytes to validate */
102     if (p->buf_size < 0x38)
103         return 0;
104
105     if ((LE_32(&p->buf[0]) == RIFF_TAG) &&
106         (LE_32(&p->buf[8]) == CDXA_TAG)) {
107
108         /* RIFF header seen; skip 0x2C bytes */
109         start = RIFF_HEADER_SIZE;
110     } else
111         start = 0;
112
113     /* look for CD sync header (00, 0xFF x 10, 00) */
114     if (memcmp(p->buf+start,sync_header,sizeof(sync_header)))
115         return 0;
116
117     /* MPEG files (like those ripped from VCDs) can also look like this;
118      * only return half certainty */
119     return 50;
120 }
121
122 static void dump(unsigned char *buf,size_t len)
123 {
124     int i;
125     for(i=0;i<len;i++) {
126         if ((i&15)==0) printf("%04x  ",i);
127         printf("%02x ",buf[i]);
128         if ((i&15)==15) printf("\n");
129     }
130     printf("\n");
131 }
132
133 static int str_read_header(AVFormatContext *s,
134                            AVFormatParameters *ap)
135 {
136     ByteIOContext *pb = &s->pb;
137     StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
138     AVStream *st;
139     unsigned char sector[RAW_CD_SECTOR_SIZE];
140     int start;
141     int i;
142     int channel;
143
144     /* initialize context members */
145     str->pts = 0;
146     str->audio_channel = -1;  /* assume to audio or video */
147     str->video_channel = -1;
148     str->video_chunk = NULL;
149
150     /* set the pts reference (1 pts = 1/90000) */
151     s->pts_num = 1;
152     s->pts_den = 90000;
153
154     /* skip over any RIFF header */
155     if (get_buffer(pb, sector, RIFF_HEADER_SIZE) != RIFF_HEADER_SIZE)
156         return AVERROR_IO;
157     if (LE_32(&sector[0]) == RIFF_TAG)
158         start = RIFF_HEADER_SIZE;
159     else
160         start = 0;
161
162     url_fseek(pb, start, SEEK_SET);
163
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)
167             return AVERROR_IO;
168
169 //printf("%02x %02x %02x %02x\n",sector[0x10],sector[0x11],sector[0x12],sector[0x13]);
170
171         channel = sector[0x11];
172         if (channel >= 32)
173             return AVERROR_INVALIDDATA;
174
175         switch (sector[0x12] & CDXA_TYPE_MASK) {
176
177         case CDXA_TYPE_DATA:
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(&sector[0x18]) != STR_MAGIC)
183                     break;
184                 str->video_channel = channel;
185                 str->channels[channel].type = STR_VIDEO;
186                 str->channels[channel].width = LE_16(&sector[0x28]);
187                 str->channels[channel].height = LE_16(&sector[0x2A]);
188
189                 /* allocate a new AVStream */
190                 st = av_new_stream(s, 0);
191                 if (!st)
192                     return AVERROR_NOMEM;
193
194                 str->channels[channel].video_stream_index = st->index;
195
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;
201             }
202             break;
203
204         case CDXA_TYPE_AUDIO:
205             /* check if this channel gets to be the dominant audio channel */
206             if (str->audio_channel == -1) {
207                 int fmt;
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;
216
217                 /* allocate a new AVStream */
218                 st = av_new_stream(s, 0);
219                 if (!st)
220                     return AVERROR_NOMEM;
221
222                 str->channels[channel].audio_stream_index = st->index;
223
224                 fmt = sector[0x13];
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;
232             }
233             break;
234
235         default:
236             /* ignore */
237             break;
238         }
239     }
240
241 if (str->video_channel != -1)
242   printf (" 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   printf (" audio channel = %d, %d Hz, %d channels, %d bits/sample %d\n", 
247     str->audio_channel,
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);
251
252     /* back to the start */
253     url_fseek(pb, start, SEEK_SET);
254
255     return 0;
256 }
257
258 static int str_read_packet(AVFormatContext *s,
259                            AVPacket *ret_pkt)
260 {
261     ByteIOContext *pb = &s->pb;
262     StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
263     unsigned char sector[RAW_CD_SECTOR_SIZE];
264     int channel;
265     int packet_read = 0;
266     int ret = 0;
267     AVPacket *pkt;
268
269     while (!packet_read) {
270
271         if (get_buffer(pb, sector, RAW_CD_SECTOR_SIZE) != RAW_CD_SECTOR_SIZE)
272             return -EIO;
273
274         channel = sector[0x11];
275         if (channel >= 32)
276             return AVERROR_INVALIDDATA;
277
278         switch (sector[0x12] & CDXA_TYPE_MASK) {
279
280         case CDXA_TYPE_DATA:
281         case CDXA_TYPE_VIDEO:
282             /* check if this the video channel we care about */
283             if (channel == str->video_channel) {
284
285                 int current_sector = LE_16(&sector[0x1C]);
286                 int sector_count   = LE_16(&sector[0x1E]);
287                 int frame_size = LE_32(&sector[0x24]);
288                 int bytes_to_copy;
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 */
291                 pkt = &str->tmp_pkt;
292                 if (current_sector == 0) {
293                     if (av_new_packet(pkt, frame_size))
294                         return -EIO;
295
296                     pkt->stream_index = 
297                         str->channels[channel].video_stream_index;
298                //     pkt->pts = str->pts;
299
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);
304                 }
305
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);
312                 }
313                 if (current_sector == sector_count-1) {
314                     *ret_pkt = *pkt;
315                     return 0;
316                 }
317
318             }
319             break;
320
321         case CDXA_TYPE_AUDIO:
322 #ifdef PRINTSTUFF
323 printf (" dropping audio sector\n");
324 #endif
325 #if 1
326             /* check if this the video channel we care about */
327             if (channel == str->audio_channel) {
328                 pkt = ret_pkt;
329                 if (av_new_packet(pkt, 2304))
330                     return -EIO;
331                 memcpy(pkt->data,sector+24,2304);
332
333                 pkt->stream_index = 
334                     str->channels[channel].audio_stream_index;
335                 //pkt->pts = str->pts;
336                 return 0;
337             }
338 #endif
339             break;
340         default:
341             /* drop the sector and move on */
342 #ifdef PRINTSTUFF
343 printf (" dropping other sector\n");
344 #endif
345             break;
346         }
347
348         if (url_feof(pb))
349             return -EIO;
350     }
351
352     return ret;
353 }
354
355 static int str_read_close(AVFormatContext *s)
356 {
357     StrDemuxContext *str = (StrDemuxContext *)s->priv_data;
358
359     av_free(str->video_chunk);
360
361     return 0;
362 }
363
364 static AVInputFormat str_iformat = {
365     "psxstr",
366     "Sony Playstation STR format",
367     sizeof(StrDemuxContext),
368     str_probe,
369     str_read_header,
370     str_read_packet,
371     str_read_close,
372 };
373
374 int str_init(void)
375 {
376     av_register_input_format(&str_iformat);
377     return 0;
378 }