]> git.sesse.net Git - ffmpeg/blob - libavformat/sga.c
avformat: add Digital Pictures SGA game demuxer
[ffmpeg] / libavformat / sga.c
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 {
34     int video_stream_index;
35     int audio_stream_index;
36
37     uint8_t sector[65536 * 2];
38     int sector_headers;
39     int sample_rate;
40     int first_audio_size;
41     int payload_size;
42     int packet_type;
43     int flags;
44     int idx;
45     int left;
46     int64_t pkt_pos;
47 } SGADemuxContext;
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 (left <= 8)
79                 return 0;
80             last_left = left;
81         } else if (sectors && header) {
82             left = header;
83             last_left -= left;
84             if (header != 0x7FE && left < 7)
85                 return 0;
86         } else if (sectors) {
87             if (left <= 8)
88                 return 0;
89             i += sectors ? 2048 : left + 4;
90             last_left = 0;
91             continue;
92         }
93
94         if (sectors && (i > 0 && left < 0x7fe) &&
95             (i + left + 14 < p->buf_size)) {
96             offset = i + left + 2;
97         } else if (sectors && i > 0) {
98             i += 2048;
99             last_left -= FFMIN(last_left, 2046);
100             continue;
101         } else {
102             offset = 0;
103             last_left = left;
104         }
105
106         header = AV_RB16(src + offset);
107         size   = AV_RB16(src + offset + 2) + 4;
108
109         while ((header & 0xFF00) == 0) {
110             offset++;
111             if (offset + 4 >= p->buf_size)
112                 break;
113             header = AV_RB16(src + offset);
114             size   = AV_RB16(src + offset + 2) + 4;
115         }
116
117         if (offset + 12 >= p->buf_size)
118             break;
119         if ((header & 0xFF) > 1)
120             return 0;
121         type = header >> 8;
122
123         if (type == 0xAA ||
124             type == 0xA1 ||
125             type == 0xA2 ||
126             type == 0xA3) {
127             int new_rate;
128
129             if (size <= 12)
130                 return 0;
131             new_rate = AV_RB16(src + offset + 8);
132             if (sample_rate < 0)
133                 sample_rate = new_rate;
134             if (sample_rate == 0 || new_rate != sample_rate)
135                 return 0;
136             if (src[offset + 10] != 1)
137                 return 0;
138
139             score += 10;
140         } else if (type == 0xC1 ||
141                    type == 0xC6 ||
142                    type == 0xC7 ||
143                    type == 0xC8 ||
144                    type == 0xC9 ||
145                    type == 0xCB ||
146                    type == 0xCD ||
147                    type == 0xE7) {
148             int nb_pals = src[offset + 9];
149             int tiles_w = src[offset + 10];
150             int tiles_h = src[offset + 11];
151
152             if (size <= 12)
153                 return 0;
154             if (nb_pals == 0 || nb_pals > 4)
155                 return 0;
156             if (tiles_w == 0 || tiles_w > 80)
157                 return 0;
158             if (tiles_h == 0 || tiles_h > 60)
159                 return 0;
160
161             score += 10;
162         } else if (header == 0x7FE) {
163             ;
164         } else {
165             return 0;
166         }
167
168         i += sectors ? 2048 : size + 4;
169         last_left -= FFMIN(last_left, 2046);
170
171         if (score < 0)
172             break;
173     }
174
175     return av_clip(score, 0, AVPROBE_SCORE_MAX);
176 }
177
178 static int sga_read_header(AVFormatContext *s)
179 {
180     SGADemuxContext *sga = s->priv_data;
181     AVIOContext *pb = s->pb;
182
183     sga->sector_headers = 1;
184     sga->first_audio_size = 0;
185     sga->video_stream_index = -1;
186     sga->audio_stream_index = -1;
187     sga->left = 2048;
188     sga->idx = 0;
189
190     s->ctx_flags |= AVFMTCTX_NOHEADER;
191
192     if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
193         while (!avio_feof(pb)) {
194             int header = avio_rb16(pb);
195             int type = header >> 8;
196             int skip = 2046;
197             int clock;
198
199             if (!sga->first_audio_size &&
200                 (type == 0xAA ||
201                  type == 0xA1 ||
202                  type == 0xA2 ||
203                  type == 0xA3)) {
204                 sga->first_audio_size = avio_rb16(pb);
205                 avio_skip(pb, 4);
206                 clock = avio_rb16(pb);
207                 sga->sample_rate = av_rescale(clock,
208                                               SEGA_CD_PCM_NUM,
209                                               SEGA_CD_PCM_DEN);
210                 skip -= 8;
211             }
212             if ((header > 0x07FE && header < 0x8100) ||
213                 (header > 0x8200 && header < 0xA100) ||
214                 (header > 0xA200 && header < 0xC100)) {
215                 sga->sector_headers = 0;
216                 break;
217             }
218
219             avio_skip(pb, skip);
220         }
221
222         avio_seek(pb, 0, SEEK_SET);
223     }
224
225     return 0;
226 }
227
228 static void print_stats(AVFormatContext *s, const char *where)
229 {
230     SGADemuxContext *sga = s->priv_data;
231
232     av_log(s, AV_LOG_DEBUG, "START %s\n", where);
233     av_log(s, AV_LOG_DEBUG, "pos: %lX\n", avio_tell(s->pb));
234     av_log(s, AV_LOG_DEBUG, "idx: %X\n", sga->idx);
235     av_log(s, AV_LOG_DEBUG, "packet_type: %X\n", sga->packet_type);
236     av_log(s, AV_LOG_DEBUG, "payload_size: %X\n", sga->payload_size);
237     av_log(s, AV_LOG_DEBUG, "SECTOR: %016lX\n", AV_RB64(sga->sector));
238     av_log(s, AV_LOG_DEBUG, "stream: %X\n", sga->sector[1]);
239     av_log(s, AV_LOG_DEBUG, "END %s\n", where);
240 }
241
242 static void update_type_size(AVFormatContext *s)
243 {
244     SGADemuxContext *sga = s->priv_data;
245
246     if (sga->idx >= 4) {
247         sga->packet_type  = sga->sector[0];
248         sga->payload_size = AV_RB16(sga->sector + 2);
249     } else {
250         sga->packet_type  = 0;
251         sga->payload_size = 0;
252     }
253 }
254
255 static int sga_video_packet(AVFormatContext *s, AVPacket *pkt)
256 {
257     SGADemuxContext *sga = s->priv_data;
258     int ret;
259
260     if (sga->payload_size <= 8)
261         return AVERROR_INVALIDDATA;
262
263     if (sga->video_stream_index == -1) {
264         AVRational frame_rate;
265
266         AVStream *st = avformat_new_stream(s, NULL);
267         if (!st)
268             return AVERROR(ENOMEM);
269
270         st->start_time              = 0;
271         st->codecpar->codec_type    = AVMEDIA_TYPE_VIDEO;
272         st->codecpar->codec_tag     = 0;
273         st->codecpar->codec_id      = AV_CODEC_ID_SGA_VIDEO;
274         sga->video_stream_index     = st->index;
275
276         if (sga->first_audio_size > 0 && sga->sample_rate > 0) {
277             frame_rate.num = sga->sample_rate;
278             frame_rate.den = sga->first_audio_size;
279         } else {
280             frame_rate.num = 15;
281             frame_rate.den = 1;
282         }
283         avpriv_set_pts_info(st, 64, frame_rate.den, frame_rate.num);
284     }
285
286     ret = av_new_packet(pkt, sga->payload_size + 4);
287     if (ret < 0)
288         return AVERROR(ENOMEM);
289     memcpy(pkt->data, sga->sector, sga->payload_size + 4);
290     av_assert0(sga->idx >= sga->payload_size + 4);
291     memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4);
292
293     pkt->stream_index = sga->video_stream_index;
294     pkt->duration = 1;
295     pkt->pos = sga->pkt_pos;
296     pkt->flags |= sga->flags;
297     sga->idx -= sga->payload_size + 4;
298     sga->flags = 0;
299     update_type_size(s);
300
301     av_log(s, AV_LOG_DEBUG, "VIDEO PACKET: %d:%016lX i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx);
302
303     return 0;
304 }
305
306 static int sga_audio_packet(AVFormatContext *s, AVPacket *pkt)
307 {
308     SGADemuxContext *sga = s->priv_data;
309     int ret;
310
311     if (sga->payload_size <= 8)
312         return AVERROR_INVALIDDATA;
313
314     if (sga->audio_stream_index == -1) {
315         AVStream *st = avformat_new_stream(s, NULL);
316         if (!st)
317             return AVERROR(ENOMEM);
318
319         st->start_time              = 0;
320         st->codecpar->codec_type    = AVMEDIA_TYPE_AUDIO;
321         st->codecpar->codec_tag     = 0;
322         st->codecpar->codec_id      = AV_CODEC_ID_PCM_SGA;
323         st->codecpar->channels      = 1;
324         st->codecpar->channel_layout= AV_CH_LAYOUT_MONO;
325         st->codecpar->sample_rate   = av_rescale(AV_RB16(sga->sector + 8),
326                                                  SEGA_CD_PCM_NUM,
327                                                  SEGA_CD_PCM_DEN);
328         sga->audio_stream_index     = st->index;
329
330         avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
331     }
332
333     ret = av_new_packet(pkt, sga->payload_size - 8);
334     if (ret < 0)
335         return AVERROR(ENOMEM);
336     memcpy(pkt->data, sga->sector + 12, sga->payload_size - 8);
337     av_assert0(sga->idx >= sga->payload_size + 4);
338     memmove(sga->sector, sga->sector + sga->payload_size + 4, sga->idx - sga->payload_size - 4);
339
340     pkt->stream_index = sga->audio_stream_index;
341     pkt->duration = pkt->size;
342     pkt->pos = sga->pkt_pos;
343     pkt->flags |= sga->flags;
344     sga->idx -= sga->payload_size + 4;
345     sga->flags = 0;
346     update_type_size(s);
347
348     av_log(s, AV_LOG_DEBUG, "AUDIO PACKET: %d:%016lX i:%X\n", pkt->size, AV_RB64(sga->sector), sga->idx);
349
350     return 0;
351 }
352
353 static int sga_packet(AVFormatContext *s, AVPacket *pkt)
354 {
355     SGADemuxContext *sga = s->priv_data;
356     int ret = 0;
357
358     if (sga->packet_type == 0xCD ||
359         sga->packet_type == 0xCB ||
360         sga->packet_type == 0xC9 ||
361         sga->packet_type == 0xC8 ||
362         sga->packet_type == 0xC7 ||
363         sga->packet_type == 0xC6 ||
364         sga->packet_type == 0xC1 ||
365         sga->packet_type == 0xE7) {
366         ret = sga_video_packet(s, pkt);
367     } else if (sga->packet_type == 0xA1 ||
368                sga->packet_type == 0xA2 ||
369                sga->packet_type == 0xA3 ||
370                sga->packet_type == 0xAA) {
371         ret = sga_audio_packet(s, pkt);
372     } else {
373         if (sga->idx == 0)
374             return AVERROR_EOF;
375         if (sga->sector[0])
376             return AVERROR_INVALIDDATA;
377         memmove(sga->sector, sga->sector + 1, sga->idx - 1);
378         sga->idx--;
379         return AVERROR(EAGAIN);
380     }
381
382     return ret;
383 }
384
385 static int try_packet(AVFormatContext *s, AVPacket *pkt)
386 {
387     SGADemuxContext *sga = s->priv_data;
388     int ret = AVERROR(EAGAIN);
389
390     update_type_size(s);
391     if (sga->idx >= sga->payload_size + 4) {
392         print_stats(s, "before sga_packet");
393         ret = sga_packet(s, pkt);
394         print_stats(s,  "after sga_packet");
395         if (ret != AVERROR(EAGAIN))
396             return ret;
397     }
398
399     return sga->idx < sga->payload_size + 4 ? AVERROR(EAGAIN) : ret;
400 }
401
402 static int sga_read_packet(AVFormatContext *s, AVPacket *pkt)
403 {
404     SGADemuxContext *sga = s->priv_data;
405     AVIOContext *pb = s->pb;
406     int header, ret = 0;
407
408     sga->pkt_pos = avio_tell(pb);
409
410 retry:
411     update_type_size(s);
412
413     print_stats(s, "start");
414     if (avio_feof(pb) &&
415         (!sga->payload_size || sga->idx < sga->payload_size + 4))
416         return AVERROR_EOF;
417
418     if (sga->idx < sga->payload_size + 4) {
419         ret = ffio_ensure_seekback(pb, 2);
420         if (ret < 0)
421             return ret;
422
423         print_stats(s, "before read header");
424         header = avio_rb16(pb);
425         if (!header) {
426             avio_skip(pb, 2046);
427             sga->left = 0;
428         } else if (!avio_feof(pb) &&
429                    ((header >> 15) ||
430                     !sga->sector_headers)) {
431             avio_seek(pb, -2, SEEK_CUR);
432             sga->flags = AV_PKT_FLAG_KEY;
433             sga->left = 2048;
434         } else {
435             sga->left = 2046;
436         }
437
438         av_assert0(sga->idx + sga->left < sizeof(sga->sector));
439         ret = avio_read(pb, sga->sector + sga->idx, sga->left);
440         if (ret > 0)
441             sga->idx += ret;
442         else if (ret != AVERROR_EOF && ret)
443             return ret;
444         print_stats(s, "after read header");
445
446         update_type_size(s);
447     }
448
449     ret = try_packet(s, pkt);
450     if (ret == AVERROR(EAGAIN))
451         goto retry;
452
453     return ret;
454 }
455
456 static int sga_seek(AVFormatContext *s, int stream_index,
457                      int64_t timestamp, int flags)
458 {
459     SGADemuxContext *sga = s->priv_data;
460
461     sga->packet_type = sga->payload_size = sga->idx = 0;
462     memset(sga->sector, 0, sizeof(sga->sector));
463
464     return -1;
465 }
466
467 AVInputFormat ff_sga_demuxer = {
468     .name           = "sga",
469     .long_name      = NULL_IF_CONFIG_SMALL("Digital Pictures SGA"),
470     .priv_data_size = sizeof(SGADemuxContext),
471     .read_probe     = sga_probe,
472     .read_header    = sga_read_header,
473     .read_packet    = sga_read_packet,
474     .read_seek      = sga_seek,
475     .extensions     = "sga",
476     .flags          = AVFMT_GENERIC_INDEX,
477 };