FFmpeg  4.4.4
sga.c
Go to the documentation of this file.
1 /*
2  * Digital Pictures SGA game demuxer
3  *
4  * Copyright (C) 2021 Paul B Mahol
5  *
6  * This file is part of FFmpeg.
7  *
8  * FFmpeg is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * FFmpeg is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with FFmpeg; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22 
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/avassert.h"
25 #include "libavutil/internal.h"
26 #include "avformat.h"
27 #include "internal.h"
28 #include "avio_internal.h"
29 
30 #define SEGA_CD_PCM_NUM 12500000
31 #define SEGA_CD_PCM_DEN 786432
32 
33 typedef struct SGADemuxContext {
36 
37  uint8_t sector[65536 * 2];
43  int flags;
44  int idx;
45  int left;
46  int64_t pkt_pos;
48 
49 static int sga_probe(const AVProbeData *p)
50 {
51  const uint8_t *src = p->buf;
52  int score = 0, sectors = 1;
53  int last_left = 0;
54  int sample_rate = -1;
55 
56  if (p->buf_size < 2048)
57  return 0;
58 
59  for (int i = 0; i + 2 < p->buf_size; i += 2048) {
60  int header = AV_RB16(src + i);
61 
62  if ((header > 0x07FE && header < 0x8100) ||
63  (header > 0x8200 && header < 0xA100) ||
64  (header > 0xA200 && header < 0xC100)) {
65  sectors = 0;
66  break;
67  }
68  }
69 
70  for (int i = 0; i + 4 < p->buf_size;) {
71  int header = AV_RB16(src + i);
72  int left = AV_RB16(src + i + 2);
73  int offset, type, size;
74 
75  if (last_left < 0)
76  return 0;
77  if (sectors && header && last_left == 0) {
78  if (header >> 12) {
79  last_left = left;
80  } else {
81  last_left = left = header;
82  }
83  } else if (sectors && header) {
84  left = header;
85  last_left -= left;
86  if (header != 0x7FE && left < 7)
87  return 0;
88  } else if (sectors) {
89  if (left <= 8)
90  return 0;
91  i += sectors ? 2048 : left + 4;
92  last_left = 0;
93  continue;
94  }
95 
96  if (sectors && (i > 0 && left < 0x7fe) &&
97  (i + left + 14 < p->buf_size)) {
98  offset = i + left + 2;
99  } else if (sectors && i > 0) {
100  i += 2048;
101  last_left -= FFMIN(last_left, 2046);
102  continue;
103  } else {
104  offset = 0;
105  last_left = left;
106  }
107 
108  header = AV_RB16(src + offset);
109  size = AV_RB16(src + offset + 2) + 4;
110 
111  while ((header & 0xFF00) == 0) {
112  offset++;
113  if (offset + 4 >= p->buf_size)
114  break;
115  header = AV_RB16(src + offset);
116  size = AV_RB16(src + offset + 2) + 4;
117  }
118 
119  if (offset + 12 >= p->buf_size)
120  break;
121  if ((header & 0xFF) > 1)
122  return 0;
123  type = header >> 8;
124 
125  if (type == 0xAA ||
126  type == 0xA1 ||
127  type == 0xA2 ||
128  type == 0xA3) {
129  int new_rate;
130 
131  if (size <= 12)
132  return 0;
133  new_rate = AV_RB16(src + offset + 8);
134  if (sample_rate < 0)
135  sample_rate = new_rate;
136  if (sample_rate == 0 || new_rate != sample_rate)
137  return 0;
138  if (src[offset + 10] != 1)
139  return 0;
140 
141  score += 10;
142  } else if (type == 0xC1 ||
143  type == 0xC6 ||
144  type == 0xC7 ||
145  type == 0xC8 ||
146  type == 0xC9 ||
147  type == 0xCB ||
148  type == 0xCD ||
149  type == 0xE7) {
150  int nb_pals = src[offset + 9];
151  int tiles_w = src[offset + 10];
152  int tiles_h = src[offset + 11];
153 
154  if (size <= 12)
155  return 0;
156  if (nb_pals == 0 || nb_pals > 4)
157  return 0;
158  if (tiles_w == 0 || tiles_w > 80)
159  return 0;
160  if (tiles_h == 0 || tiles_h > 60)
161  return 0;
162 
163  score += 10;
164  } else if (header == 0x7FE) {
165  ;
166  } else {
167  return 0;
168  }
169 
170  i += sectors ? 2048 : size + 4;
171  last_left -= FFMIN(last_left, 2046);
172 
173  if (score < 0)
174  break;
175  }
176 
177  return av_clip(score, 0, AVPROBE_SCORE_MAX);
178 }
179 
181 {
182  SGADemuxContext *sga = s->priv_data;
183  AVIOContext *pb = s->pb;
184 
185  sga->sector_headers = 1;
186  sga->first_audio_size = 0;
187  sga->video_stream_index = -1;
188  sga->audio_stream_index = -1;
189  sga->left = 2048;
190  sga->idx = 0;
191 
192  s->ctx_flags |= AVFMTCTX_NOHEADER;
193 
194  if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
195  while (!avio_feof(pb)) {
196  int header = avio_rb16(pb);
197  int type = header >> 8;
198  int skip = 2046;
199  int clock;
200 
201  if (!sga->first_audio_size &&
202  (type == 0xAA ||
203  type == 0xA1 ||
204  type == 0xA2 ||
205  type == 0xA3)) {
206  sga->first_audio_size = avio_rb16(pb);
207  avio_skip(pb, 4);
208  clock = avio_rb16(pb);
209  sga->sample_rate = av_rescale(clock,
212  skip -= 8;
213  }
214  if ((header > 0x07FE && header < 0x8100) ||
215  (header > 0x8200 && header < 0xA100) ||
216  (header > 0xA200 && header < 0xC100)) {
217  sga->sector_headers = 0;
218  break;
219  }
220 
221  avio_skip(pb, skip);
222  }
223 
224  avio_seek(pb, 0, SEEK_SET);
225  }
226 
227  return 0;
228 }
229 
230 static void print_stats(AVFormatContext *s, const char *where)
231 {
232  SGADemuxContext *sga = s->priv_data;
233 
234  av_log(s, AV_LOG_DEBUG, "START %s\n", where);
235  av_log(s, AV_LOG_DEBUG, "pos: %"PRIX64"\n", avio_tell(s->pb));
236  av_log(s, AV_LOG_DEBUG, "idx: %X\n", sga->idx);
237  av_log(s, AV_LOG_DEBUG, "packet_type: %X\n", sga->packet_type);
238  av_log(s, AV_LOG_DEBUG, "payload_size: %X\n", sga->payload_size);
239  av_log(s, AV_LOG_DEBUG, "SECTOR: %016"PRIX64"\n", AV_RB64(sga->sector));
240  av_log(s, AV_LOG_DEBUG, "stream: %X\n", sga->sector[1]);
241  av_log(s, AV_LOG_DEBUG, "END %s\n", where);
242 }
243 
245 {
246  SGADemuxContext *sga = s->priv_data;
247 
248  if (sga->idx >= 4) {
249  sga->packet_type = sga->sector[0];
250  sga->payload_size = AV_RB16(sga->sector + 2);
251  } else {
252  sga->packet_type = 0;
253  sga->payload_size = 0;
254  }
255 }
256 
258 {
259  SGADemuxContext *sga = s->priv_data;
260  int ret;
261 
262  if (sga->payload_size <= 8)
263  return AVERROR_INVALIDDATA;
264 
265  if (sga->video_stream_index == -1) {
266  AVRational frame_rate;
267 
269  if (!st)
270  return AVERROR(ENOMEM);
271 
272  st->start_time = 0;
274  st->codecpar->codec_tag = 0;
276  sga->video_stream_index = st->index;
277 
278  if (sga->first_audio_size > 0 && sga->sample_rate > 0) {
279  frame_rate.num = sga->sample_rate;
280  frame_rate.den = sga->first_audio_size;
281  } else {
282  frame_rate.num = 15;
283  frame_rate.den = 1;
284  }
285  avpriv_set_pts_info(st, 64, frame_rate.den, frame_rate.num);
286  }
287 
288  ret = av_new_packet(pkt, sga->payload_size + 4);
289  if (ret < 0)
290  return AVERROR(ENOMEM);
291  memcpy(pkt->data, sga->sector, sga->payload_size + 4);
292  av_assert0(sga->idx >= sga->payload_size + 4);
293  memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4);
294 
296  pkt->duration = 1;
297  pkt->pos = sga->pkt_pos;
298  pkt->flags |= sga->flags;
299  sga->idx -= sga->payload_size + 4;
300  sga->flags = 0;
302 
303  av_log(s, AV_LOG_DEBUG, "VIDEO PACKET: %d:%016"PRIX64" i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx);
304 
305  return 0;
306 }
307 
309 {
310  SGADemuxContext *sga = s->priv_data;
311  int ret;
312 
313  if (sga->payload_size <= 8)
314  return AVERROR_INVALIDDATA;
315 
316  if (sga->audio_stream_index == -1) {
318  if (!st)
319  return AVERROR(ENOMEM);
320 
321  st->start_time = 0;
323  st->codecpar->codec_tag = 0;
325  st->codecpar->channels = 1;
327  st->codecpar->sample_rate = av_rescale(AV_RB16(sga->sector + 8),
330  sga->audio_stream_index = st->index;
331 
332  avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
333  }
334 
335  ret = av_new_packet(pkt, sga->payload_size - 8);
336  if (ret < 0)
337  return AVERROR(ENOMEM);
338  memcpy(pkt->data, sga->sector + 12, sga->payload_size - 8);
339  av_assert0(sga->idx >= sga->payload_size + 4);
340  memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4);
341 
343  pkt->duration = pkt->size;
344  pkt->pos = sga->pkt_pos;
345  pkt->flags |= sga->flags;
346  sga->idx -= sga->payload_size + 4;
347  sga->flags = 0;
349 
350  av_log(s, AV_LOG_DEBUG, "AUDIO PACKET: %d:%016"PRIX64" i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx);
351 
352  return 0;
353 }
354 
356 {
357  SGADemuxContext *sga = s->priv_data;
358  int ret = 0;
359 
360  if (sga->packet_type == 0xCD ||
361  sga->packet_type == 0xCB ||
362  sga->packet_type == 0xC9 ||
363  sga->packet_type == 0xC8 ||
364  sga->packet_type == 0xC7 ||
365  sga->packet_type == 0xC6 ||
366  sga->packet_type == 0xC1 ||
367  sga->packet_type == 0xE7) {
368  ret = sga_video_packet(s, pkt);
369  } else if (sga->packet_type == 0xA1 ||
370  sga->packet_type == 0xA2 ||
371  sga->packet_type == 0xA3 ||
372  sga->packet_type == 0xAA) {
373  ret = sga_audio_packet(s, pkt);
374  } else {
375  if (sga->idx == 0)
376  return AVERROR_EOF;
377  if (sga->sector[0])
378  return AVERROR_INVALIDDATA;
379  memmove(sga->sector, sga->sector + 1, sga->idx - 1);
380  sga->idx--;
381  return AVERROR(EAGAIN);
382  }
383 
384  return ret;
385 }
386 
388 {
389  SGADemuxContext *sga = s->priv_data;
390  int ret = AVERROR(EAGAIN);
391 
393  if (sga->idx >= sga->payload_size + 4) {
394  print_stats(s, "before sga_packet");
395  ret = sga_packet(s, pkt);
396  print_stats(s, "after sga_packet");
397  if (ret != AVERROR(EAGAIN))
398  return ret;
399  }
400 
401  return sga->idx < sga->payload_size + 4 ? AVERROR(EAGAIN) : ret;
402 }
403 
405 {
406  SGADemuxContext *sga = s->priv_data;
407  AVIOContext *pb = s->pb;
408  int header, ret = 0;
409 
410  sga->pkt_pos = avio_tell(pb);
411 
412 retry:
414 
415  print_stats(s, "start");
416  if (avio_feof(pb) &&
417  (!sga->payload_size || sga->idx < sga->payload_size + 4))
418  return AVERROR_EOF;
419 
420  if (sga->idx < sga->payload_size + 4) {
421  ret = ffio_ensure_seekback(pb, 2);
422  if (ret < 0)
423  return ret;
424 
425  print_stats(s, "before read header");
426  header = avio_rb16(pb);
427  if (!header) {
428  avio_skip(pb, 2046);
429  sga->left = 0;
430  } else if (!avio_feof(pb) &&
431  ((header >> 15) ||
432  !sga->sector_headers)) {
433  avio_seek(pb, -2, SEEK_CUR);
434  sga->flags = AV_PKT_FLAG_KEY;
435  sga->left = 2048;
436  } else {
437  sga->left = 2046;
438  }
439 
440  av_assert0(sga->idx + sga->left < sizeof(sga->sector));
441  ret = avio_read(pb, sga->sector + sga->idx, sga->left);
442  if (ret > 0)
443  sga->idx += ret;
444  else if (ret != AVERROR_EOF && ret)
445  return ret;
446  print_stats(s, "after read header");
447 
449  }
450 
451  ret = try_packet(s, pkt);
452  if (ret == AVERROR(EAGAIN))
453  goto retry;
454 
455  return ret;
456 }
457 
458 static int sga_seek(AVFormatContext *s, int stream_index,
459  int64_t timestamp, int flags)
460 {
461  SGADemuxContext *sga = s->priv_data;
462 
463  sga->packet_type = sga->payload_size = sga->idx = 0;
464  memset(sga->sector, 0, sizeof(sga->sector));
465 
466  return -1;
467 }
468 
470  .name = "sga",
471  .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA"),
472  .priv_data_size = sizeof(SGADemuxContext),
476  .read_seek = sga_seek,
477  .extensions = "sga",
479 };
uint8_t
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Main libavformat public API header.
#define AVPROBE_SCORE_MAX
maximum score
Definition: avformat.h:453
#define AVFMTCTX_NOHEADER
signal that no header is present (streams are added dynamically)
Definition: avformat.h:1177
#define AVFMT_GENERIC_INDEX
Use generic index building code.
Definition: avformat.h:463
int64_t avio_seek(AVIOContext *s, int64_t offset, int whence)
fseek() equivalent for AVIOContext.
Definition: aviobuf.c:253
#define AVIO_SEEKABLE_NORMAL
Seeking works like for a local file.
Definition: avio.h:40
unsigned int avio_rb16(AVIOContext *s)
Definition: aviobuf.c:766
int avio_feof(AVIOContext *s)
Similar to feof() but also returns nonzero on read errors.
Definition: aviobuf.c:364
static av_always_inline int64_t avio_tell(AVIOContext *s)
ftell() equivalent for AVIOContext.
Definition: avio.h:557
int64_t avio_skip(AVIOContext *s, int64_t offset)
Skip given number of bytes forward.
Definition: aviobuf.c:337
int avio_read(AVIOContext *s, unsigned char *buf, int size)
Read size bytes from AVIOContext into buf.
Definition: aviobuf.c:633
int ffio_ensure_seekback(AVIOContext *s, int64_t buf_size)
Ensures that the requested seekback buffer size will be available.
Definition: aviobuf.c:998
static int read_packet(void *opaque, uint8_t *buf, int buf_size)
Definition: avio_reading.c:42
#define AV_RB16
Definition: intreadwrite.h:53
#define AV_RB64
Definition: intreadwrite.h:164
#define flags(name, subs,...)
Definition: cbs_av1.c:561
#define s(width, name)
Definition: cbs_vp9.c:257
#define FFMIN(a, b)
Definition: common.h:105
#define av_clip
Definition: common.h:122
#define NULL
Definition: coverity.c:32
sample_rate
static int read_header(FFV1Context *f)
Definition: ffv1dec.c:545
#define AV_CH_LAYOUT_MONO
@ AV_CODEC_ID_PCM_SGA
Definition: codec_id.h:350
@ AV_CODEC_ID_SGA_VIDEO
Definition: codec_id.h:309
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:410
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:99
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4509
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AVERROR(e)
Definition: error.h:43
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:215
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
Definition: mathematics.c:129
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
cl_device_type type
int i
Definition: input.c:407
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.
Definition: utils.c:4945
static int read_probe(const AVProbeData *pd)
Definition: jvdec.c:55
static int sga_read_header(AVFormatContext *s)
Definition: sga.c:180
AVInputFormat ff_sga_demuxer
Definition: sga.c:469
static int sga_audio_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sga.c:308
static int sga_probe(const AVProbeData *p)
Definition: sga.c:49
static void print_stats(AVFormatContext *s, const char *where)
Definition: sga.c:230
#define SEGA_CD_PCM_NUM
Definition: sga.c:30
static int try_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sga.c:387
static int sga_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sga.c:355
#define SEGA_CD_PCM_DEN
Definition: sga.c:31
static void update_type_size(AVFormatContext *s)
Definition: sga.c:244
static int sga_video_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sga.c:257
static int sga_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags)
Definition: sga.c:458
static int sga_read_packet(AVFormatContext *s, AVPacket *pkt)
Definition: sga.c:404
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
static int read_seek(AVFormatContext *ctx, int stream_index, int64_t timestamp, int flags)
Definition: libcdio.c:153
static const uint8_t header[24]
Definition: sdr2.c:67
uint64_t channel_layout
Audio only.
Definition: codec_par.h:162
int channels
Audio only.
Definition: codec_par.h:166
enum AVMediaType codec_type
General type of the encoded data.
Definition: codec_par.h:56
uint32_t codec_tag
Additional information about the codec (corresponds to the AVI FOURCC).
Definition: codec_par.h:64
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: codec_par.h:60
int sample_rate
Audio only.
Definition: codec_par.h:170
Format I/O context.
Definition: avformat.h:1232
Bytestream IO Context.
Definition: avio.h:161
int seekable
A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.
Definition: avio.h:260
const char * name
A comma separated list of short names for the format.
Definition: avformat.h:645
This structure stores compressed data.
Definition: packet.h:346
int stream_index
Definition: packet.h:371
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:375
int size
Definition: packet.h:370
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:387
uint8_t * data
Definition: packet.h:369
int64_t pos
byte position in stream, -1 if unknown
Definition: packet.h:389
This structure contains the data a format has to probe a file.
Definition: avformat.h:441
int buf_size
Size of buf except extra allocated bytes.
Definition: avformat.h:444
unsigned char * buf
Buffer must have AVPROBE_PADDING_SIZE of extra allocated bytes filled with zero.
Definition: avformat.h:443
Rational number (pair of numerator and denominator).
Definition: rational.h:58
int num
Numerator.
Definition: rational.h:59
int den
Denominator.
Definition: rational.h:60
Stream structure.
Definition: avformat.h:873
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1038
int index
stream index in AVFormatContext
Definition: avformat.h:874
int64_t start_time
Decoding: pts of the first frame of the stream in presentation order, in stream time base.
Definition: avformat.h:912
int video_stream_index
Definition: sga.c:34
int payload_size
Definition: sga.c:41
int packet_type
Definition: sga.c:42
int64_t pkt_pos
Definition: sga.c:46
int sample_rate
Definition: sga.c:39
int first_audio_size
Definition: sga.c:40
int flags
Definition: sga.c:43
int left
Definition: sga.c:45
int sector_headers
Definition: sga.c:38
uint8_t sector[65536 *2]
Definition: sga.c:37
int audio_stream_index
Definition: sga.c:35
int idx
Definition: sga.c:44
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
AVPacket * pkt
Definition: movenc.c:59
int size
static const uint8_t offset[127][2]
Definition: vf_spp.c:107