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 
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 */
57 
58  /* audio parameters */
60 } StrChannel;
61 
62 typedef struct StrDemuxContext {
63 
64  /* a STR file can contain up to 32 channels of data */
65  StrChannel channels[32];
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 
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(&sector[0x1C]);
98  int sector_count = AV_RL16(&sector[0x1E]);
99  int frame_size = AV_RL32(&sector[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(&sector[0x28]);
108  st->codec->height = AV_RL16(&sector[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 50;
130  else if(vid+aud) return 1;
131  else return 0;
132 }
133 
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(&sector[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++){
154  str->channels[i].audio_stream_index= -1;
155  }
156 
158 
159  return 0;
160 }
161 
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(&sector[0x1C]);
188  int sector_count = AV_RL16(&sector[0x1E]);
189  int frame_size = AV_RL32(&sector[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 
209  st->codec->codec_tag = 0; /* no fourcc */
210  st->codec->width = AV_RL16(&sector[0x28]);
211  st->codec->height = AV_RL16(&sector[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 
260  st->codec->codec_tag = 0; /* no fourcc */
261  if (fmt & 1) {
262  st->codec->channels = 2;
264  } else {
265  st->codec->channels = 1;
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 
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 
309  .name = "psxstr",
310  .long_name = NULL_IF_CONFIG_SMALL("Sony Playstation STR"),
311  .priv_data_size = sizeof(StrDemuxContext),
317 };
StrChannel channels[32]
Definition: psxstr.c:65
const char * s
Definition: avisynth_c.h:668
Bytestream IO Context.
Definition: avio.h:68
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void av_free_packet(AVPacket *pkt)
Free a packet.
Definition: avpacket.c:242
const char * fmt
Definition: avisynth_c.h:669
int64_t pos
byte position in stream, -1 if unknown
void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, unsigned int pts_num, unsigned int pts_den)
Set the time base and wrapping info for a given stream.
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:154
int index
stream index in AVFormatContext
Definition: avformat.h:644
static int str_read_header(AVFormatContext *s)
Definition: psxstr.c:134
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:199
#define AV_RL16
#define CDXA_TYPE_DATA
Definition: psxstr.c:47
int audio_stream_index
Definition: psxstr.c:59
#define AV_CH_LAYOUT_STEREO
int ctx_flags
Format-specific flags, see AVFMTCTX_xx.
Definition: avformat.h:980
int block_align
number of bytes per packet if constant and known or 0 Used by some WAV based audio codecs...
Format I/O context.
Definition: avformat.h:944
uint8_t
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:914
#define CDXA_TAG
Definition: psxstr.c:38
AVInputFormat ff_str_demuxer
Definition: psxstr.c:308
static AVPacket pkt
Definition: demuxing.c:56
end end
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
#define VIDEO_DATA_HEADER_SIZE
Definition: psxstr.c:43
uint8_t * data
static av_cold int read_close(AVFormatContext *ctx)
Definition: libcdio.c:145
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:248
int duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:478
static const uint8_t frame_size[4]
Definition: g723_1_data.h:58
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:73
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
AVBufferRef * buf
A reference to the reference-counted buffer where the packet data is stored.
#define RIFF_TAG
Definition: psxstr.c:37
void av_log(void *avcl, int level, const char *fmt,...)
Definition: log.c:246
#define RAW_CD_SECTOR_SIZE
Definition: psxstr.c:40
uint64_t channel_layout
Audio channel layout.
AVCodecContext * codec
Codec context associated with this stream.
Definition: avformat.h:662
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:337
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:336
#define VIDEO_DATA_CHUNK_SIZE
Definition: psxstr.c:42
audio channel layout utility functions
struct StrDemuxContext StrDemuxContext
static int read_probe(AVProbeData *pd)
int width
picture width / height.
#define CDXA_TYPE_VIDEO
Definition: psxstr.c:49
#define AV_RL32
#define RIFF_HEADER_SIZE
Definition: psxstr.c:44
int url_feof(AVIOContext *s)
feof() equivalent for AVIOContext.
Definition: aviobuf.c:280
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:517
Stream structure.
Definition: avformat.h:643
AVPacket tmp_pkt
Definition: psxstr.c:56
static int str_read_packet(AVFormatContext *s, AVPacket *ret_pkt)
Definition: psxstr.c:162
NULL
Definition: eval.c:55
static int str_probe(AVProbeData *p)
Definition: psxstr.c:70
enum AVMediaType codec_type
enum AVCodecID codec_id
int sample_rate
samples per second
AVIOContext * pb
I/O context.
Definition: avformat.h:977
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:148
unsigned int codec_tag
fourcc (LSB first, so "ABCD" -> (&#39;D&#39;<<24) + (&#39;C&#39;<<16) + (&#39;B&#39;<<8) + &#39;A&#39;).
static int read_packet(AVFormatContext *ctx, AVPacket *pkt)
Definition: libcdio.c:114
static const uint8_t sync_header[12]
Definition: psxstr.c:68
synthesis window for stochastic i
This structure contains the data a format has to probe a file.
Definition: avformat.h:334
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFilterBuffer structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Buffer references ownership and permissions
static int flags
Definition: cpu.c:23
int video_stream_index
Definition: psxstr.c:55
#define CDXA_TYPE_AUDIO
Definition: psxstr.c:48
Main libavformat public API header.
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base...
Definition: avformat.h:689
static int str_read_close(AVFormatContext *s)
Definition: psxstr.c:296
#define AVFMT_NO_BYTE_SEEK
Format does not allow seeking by bytes.
Definition: avformat.h:360
int channels
number of audio channels
void * priv_data
Format private data.
Definition: avformat.h:964
struct StrChannel StrChannel
void INT64 start
Definition: avisynth_c.h:594
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:461
#define CDXA_TYPE_MASK
Definition: psxstr.c:46
#define AV_CH_LAYOUT_MONO
This structure stores compressed data.