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/channel_layout.h"
26 #include "libavutil/internal.h"
27 #include "avformat.h"
28 #include "internal.h"
29 #include "avio_internal.h"
30
31 #define SEGA_CD_PCM_NUM 12500000
32 #define SEGA_CD_PCM_DEN 786432
33
34 typedef struct SGADemuxContext {
35 int video_stream_index;
36 int audio_stream_index;
37
38 uint8_t sector[65536 * 2];
39 int sector_headers;
40 int sample_rate;
41 int first_audio_size;
42 int payload_size;
43 int packet_type;
44 int flags;
45 int idx;
46 int left;
47 int64_t pkt_pos;
48 } SGADemuxContext;
49
sga_probe(const AVProbeData * p)50 static int sga_probe(const AVProbeData *p)
51 {
52 const uint8_t *src = p->buf;
53 int score = 0, sectors = 1;
54 int last_left = 0;
55 int sample_rate = -1;
56
57 if (p->buf_size < 2048)
58 return 0;
59
60 for (int i = 0; i + 2 < p->buf_size; i += 2048) {
61 int header = AV_RB16(src + i);
62
63 if ((header > 0x07FE && header < 0x8100) ||
64 (header > 0x8200 && header < 0xA100) ||
65 (header > 0xA200 && header < 0xC100)) {
66 sectors = 0;
67 break;
68 }
69 }
70
71 for (int i = 0; i + 4 < p->buf_size;) {
72 int header = AV_RB16(src + i);
73 int left = AV_RB16(src + i + 2);
74 int offset, type, size;
75
76 if (last_left < 0)
77 return 0;
78 if (sectors && header && last_left == 0) {
79 if (header >> 12) {
80 last_left = left;
81 } else {
82 last_left = left = header;
83 }
84 } else if (sectors && header) {
85 left = header;
86 last_left -= left;
87 if (header != 0x7FE && left < 7)
88 return 0;
89 } else if (sectors) {
90 if (left <= 8)
91 return 0;
92 i += sectors ? 2048 : left + 4;
93 last_left = 0;
94 continue;
95 }
96
97 if (sectors && (i > 0 && left < 0x7fe) &&
98 (i + left + 14 < p->buf_size)) {
99 offset = i + left + 2;
100 } else if (sectors && i > 0) {
101 i += 2048;
102 last_left -= FFMIN(last_left, 2046);
103 continue;
104 } else {
105 offset = 0;
106 last_left = left;
107 }
108
109 header = AV_RB16(src + offset);
110 size = AV_RB16(src + offset + 2) + 4;
111
112 while ((header & 0xFF00) == 0) {
113 offset++;
114 if (offset + 4 >= p->buf_size)
115 break;
116 header = AV_RB16(src + offset);
117 size = AV_RB16(src + offset + 2) + 4;
118 }
119
120 if (offset + 12 >= p->buf_size)
121 break;
122 if ((header & 0xFF) > 1)
123 return 0;
124 type = header >> 8;
125
126 if (type == 0xAA ||
127 type == 0xA1 ||
128 type == 0xA2 ||
129 type == 0xA3) {
130 int new_rate;
131
132 if (size <= 12)
133 return 0;
134 new_rate = AV_RB16(src + offset + 8);
135 if (sample_rate < 0)
136 sample_rate = new_rate;
137 if (sample_rate == 0 || new_rate != sample_rate)
138 return 0;
139 if (src[offset + 10] != 1)
140 return 0;
141
142 score += 10;
143 } else if (type == 0xC1 ||
144 type == 0xC6 ||
145 type == 0xC7 ||
146 type == 0xC8 ||
147 type == 0xC9 ||
148 type == 0xCB ||
149 type == 0xCD ||
150 type == 0xE7) {
151 int nb_pals = src[offset + 9];
152 int tiles_w = src[offset + 10];
153 int tiles_h = src[offset + 11];
154
155 if (size <= 12)
156 return 0;
157 if (nb_pals == 0 || nb_pals > 4)
158 return 0;
159 if (tiles_w == 0 || tiles_w > 80)
160 return 0;
161 if (tiles_h == 0 || tiles_h > 60)
162 return 0;
163
164 score += 10;
165 } else if (header == 0x7FE) {
166 ;
167 } else {
168 return 0;
169 }
170
171 i += sectors ? 2048 : size + 4;
172 last_left -= FFMIN(last_left, 2046);
173
174 if (score < 0)
175 break;
176 }
177
178 return av_clip(score, 0, AVPROBE_SCORE_MAX);
179 }
180
sga_read_header(AVFormatContext * s)181 static int sga_read_header(AVFormatContext *s)
182 {
183 SGADemuxContext *sga = s->priv_data;
184 AVIOContext *pb = s->pb;
185
186 sga->sector_headers = 1;
187 sga->first_audio_size = 0;
188 sga->video_stream_index = -1;
189 sga->audio_stream_index = -1;
190 sga->left = 2048;
191 sga->idx = 0;
192
193 s->ctx_flags |= AVFMTCTX_NOHEADER;
194
195 if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
196 while (!avio_feof(pb)) {
197 int header = avio_rb16(pb);
198 int type = header >> 8;
199 int skip = 2046;
200 int clock;
201
202 if (!sga->first_audio_size &&
203 (type == 0xAA ||
204 type == 0xA1 ||
205 type == 0xA2 ||
206 type == 0xA3)) {
207 sga->first_audio_size = avio_rb16(pb);
208 avio_skip(pb, 4);
209 clock = avio_rb16(pb);
210 sga->sample_rate = av_rescale(clock,
211 SEGA_CD_PCM_NUM,
212 SEGA_CD_PCM_DEN);
213 skip -= 8;
214 }
215 if ((header > 0x07FE && header < 0x8100) ||
216 (header > 0x8200 && header < 0xA100) ||
217 (header > 0xA200 && header < 0xC100)) {
218 sga->sector_headers = 0;
219 break;
220 }
221
222 avio_skip(pb, skip);
223 }
224
225 avio_seek(pb, 0, SEEK_SET);
226 }
227
228 return 0;
229 }
230
print_stats(AVFormatContext * s,const char * where)231 static void print_stats(AVFormatContext *s, const char *where)
232 {
233 SGADemuxContext *sga = s->priv_data;
234
235 av_log(s, AV_LOG_DEBUG, "START %s\n", where);
236 av_log(s, AV_LOG_DEBUG, "pos: %"PRIX64"\n", avio_tell(s->pb));
237 av_log(s, AV_LOG_DEBUG, "idx: %X\n", sga->idx);
238 av_log(s, AV_LOG_DEBUG, "packet_type: %X\n", sga->packet_type);
239 av_log(s, AV_LOG_DEBUG, "payload_size: %X\n", sga->payload_size);
240 av_log(s, AV_LOG_DEBUG, "SECTOR: %016"PRIX64"\n", AV_RB64(sga->sector));
241 av_log(s, AV_LOG_DEBUG, "stream: %X\n", sga->sector[1]);
242 av_log(s, AV_LOG_DEBUG, "END %s\n", where);
243 }
244
update_type_size(AVFormatContext * s)245 static void update_type_size(AVFormatContext *s)
246 {
247 SGADemuxContext *sga = s->priv_data;
248
249 if (sga->idx >= 4) {
250 sga->packet_type = sga->sector[0];
251 sga->payload_size = AV_RB16(sga->sector + 2);
252 } else {
253 sga->packet_type = 0;
254 sga->payload_size = 0;
255 }
256 }
257
sga_video_packet(AVFormatContext * s,AVPacket * pkt)258 static int sga_video_packet(AVFormatContext *s, AVPacket *pkt)
259 {
260 SGADemuxContext *sga = s->priv_data;
261 int ret;
262
263 if (sga->payload_size <= 8)
264 return AVERROR_INVALIDDATA;
265
266 if (sga->video_stream_index == -1) {
267 AVRational frame_rate;
268
269 AVStream *st = avformat_new_stream(s, NULL);
270 if (!st)
271 return AVERROR(ENOMEM);
272
273 st->start_time = 0;
274 st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
275 st->codecpar->codec_tag = 0;
276 st->codecpar->codec_id = AV_CODEC_ID_SGA_VIDEO;
277 sga->video_stream_index = st->index;
278
279 if (sga->first_audio_size > 0 && sga->sample_rate > 0) {
280 frame_rate.num = sga->sample_rate;
281 frame_rate.den = sga->first_audio_size;
282 } else {
283 frame_rate.num = 15;
284 frame_rate.den = 1;
285 }
286 avpriv_set_pts_info(st, 64, frame_rate.den, frame_rate.num);
287 }
288
289 ret = av_new_packet(pkt, sga->payload_size + 4);
290 if (ret < 0)
291 return AVERROR(ENOMEM);
292 memcpy(pkt->data, sga->sector, sga->payload_size + 4);
293 av_assert0(sga->idx >= sga->payload_size + 4);
294 memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4);
295
296 pkt->stream_index = sga->video_stream_index;
297 pkt->duration = 1;
298 pkt->pos = sga->pkt_pos;
299 pkt->flags |= sga->flags;
300 sga->idx -= sga->payload_size + 4;
301 sga->flags = 0;
302 update_type_size(s);
303
304 av_log(s, AV_LOG_DEBUG, "VIDEO PACKET: %d:%016"PRIX64" i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx);
305
306 return 0;
307 }
308
sga_audio_packet(AVFormatContext * s,AVPacket * pkt)309 static int sga_audio_packet(AVFormatContext *s, AVPacket *pkt)
310 {
311 SGADemuxContext *sga = s->priv_data;
312 int ret;
313
314 if (sga->payload_size <= 8)
315 return AVERROR_INVALIDDATA;
316
317 if (sga->audio_stream_index == -1) {
318 AVStream *st = avformat_new_stream(s, NULL);
319 if (!st)
320 return AVERROR(ENOMEM);
321
322 st->start_time = 0;
323 st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
324 st->codecpar->codec_tag = 0;
325 st->codecpar->codec_id = AV_CODEC_ID_PCM_SGA;
326 st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
327 st->codecpar->sample_rate = av_rescale(AV_RB16(sga->sector + 8),
328 SEGA_CD_PCM_NUM,
329 SEGA_CD_PCM_DEN);
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
342 pkt->stream_index = sga->audio_stream_index;
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;
348 update_type_size(s);
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
sga_packet(AVFormatContext * s,AVPacket * pkt)355 static int sga_packet(AVFormatContext *s, AVPacket *pkt)
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
try_packet(AVFormatContext * s,AVPacket * pkt)387 static int try_packet(AVFormatContext *s, AVPacket *pkt)
388 {
389 SGADemuxContext *sga = s->priv_data;
390 int ret = AVERROR(EAGAIN);
391
392 update_type_size(s);
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
sga_read_packet(AVFormatContext * s,AVPacket * pkt)404 static int sga_read_packet(AVFormatContext *s, AVPacket *pkt)
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:
413 update_type_size(s);
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
448 update_type_size(s);
449 }
450
451 ret = try_packet(s, pkt);
452 if (ret == AVERROR(EAGAIN))
453 goto retry;
454
455 return ret;
456 }
457
sga_seek(AVFormatContext * s,int stream_index,int64_t timestamp,int flags)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
469 const AVInputFormat ff_sga_demuxer = {
470 .name = "sga",
471 .long_name = NULL_IF_CONFIG_SMALL("Digital Pictures SGA"),
472 .priv_data_size = sizeof(SGADemuxContext),
473 .read_probe = sga_probe,
474 .read_header = sga_read_header,
475 .read_packet = sga_read_packet,
476 .read_seek = sga_seek,
477 .extensions = "sga",
478 .flags = AVFMT_GENERIC_INDEX,
479 };
480