]> git.sesse.net Git - ffmpeg/blob - libavformat/apm.c
avformat/mov: Don't allow negative sample sizes.
[ffmpeg] / libavformat / apm.c
1 /*
2  * Rayman 2 APM Demuxer
3  *
4  * Copyright (C) 2020 Zane van Iperen (zane@zanevaniperen.com)
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 #include "avformat.h"
23 #include "internal.h"
24 #include "riff.h"
25 #include "libavutil/internal.h"
26 #include "libavutil/intreadwrite.h"
27
28 #define APM_FILE_HEADER_SIZE    20
29 #define APM_VS12_CHUNK_SIZE     76
30 #define APM_MAX_READ_SIZE       4096
31
32 #define APM_TAG_VS12            MKTAG('v', 's', '1', '2')
33 #define APM_TAG_DATA            MKTAG('D', 'A', 'T', 'A')
34
35 typedef struct APMState {
36     int32_t     has_saved;
37     int32_t     predictor_r;
38     int32_t     step_index_r;
39     int32_t     saved_r;
40     int32_t     predictor_l;
41     int32_t     step_index_l;
42     int32_t     saved_l;
43 } APMState;
44
45 typedef struct APMVS12Chunk {
46     uint32_t    magic;
47     uint32_t    file_size;
48     uint32_t    data_size;
49     uint32_t    unk1;
50     uint32_t    unk2;
51     APMState    state;
52     uint32_t    pad[7];
53 } APMVS12Chunk;
54
55 static void apm_parse_vs12(APMVS12Chunk *vs12, const uint8_t *buf)
56 {
57     vs12->magic                 = AV_RL32(buf + 0);
58     vs12->file_size             = AV_RL32(buf + 4);
59     vs12->data_size             = AV_RL32(buf + 8);
60     vs12->unk1                  = AV_RL32(buf + 12);
61     vs12->unk2                  = AV_RL32(buf + 16);
62
63     vs12->state.has_saved       = AV_RL32(buf + 20);
64     vs12->state.predictor_r     = AV_RL32(buf + 24);
65     vs12->state.step_index_r    = AV_RL32(buf + 28);
66     vs12->state.saved_r         = AV_RL32(buf + 32);
67     vs12->state.predictor_l     = AV_RL32(buf + 36);
68     vs12->state.step_index_l    = AV_RL32(buf + 40);
69     vs12->state.saved_l         = AV_RL32(buf + 44);
70
71     for (int i = 0; i < FF_ARRAY_ELEMS(vs12->pad); i++)
72         vs12->pad[i]            = AV_RL32(buf + 48 + (i * 4));
73 }
74
75 static int apm_probe(const AVProbeData *p)
76 {
77     if (p->buf_size < 100)
78         return 0;
79
80     if (AV_RL32(p->buf + 20) != APM_TAG_VS12)
81         return 0;
82
83     if (AV_RL32(p->buf + 96) != APM_TAG_DATA)
84         return 0;
85
86     return AVPROBE_SCORE_MAX - 1;
87 }
88
89 static int apm_read_header(AVFormatContext *s)
90 {
91     int64_t ret;
92     AVStream *st;
93     APMVS12Chunk vs12;
94     uint8_t buf[APM_VS12_CHUNK_SIZE];
95
96     if (!(st = avformat_new_stream(s, NULL)))
97         return AVERROR(ENOMEM);
98
99     /* The header starts with a WAVEFORMATEX */
100     if ((ret = ff_get_wav_header(s, s->pb, st->codecpar, APM_FILE_HEADER_SIZE, 0)) < 0)
101         return ret;
102
103     if (st->codecpar->bits_per_coded_sample != 4)
104         return AVERROR_INVALIDDATA;
105
106     if (st->codecpar->codec_tag != 0x2000)
107         return AVERROR_INVALIDDATA;
108
109     /* ff_get_wav_header() does most of the work, but we need to fix a few things. */
110     st->codecpar->codec_id              = AV_CODEC_ID_ADPCM_IMA_APM;
111     st->codecpar->codec_tag             = 0;
112
113     if (st->codecpar->channels == 2)
114         st->codecpar->channel_layout    = AV_CH_LAYOUT_STEREO;
115     else if (st->codecpar->channels == 1)
116         st->codecpar->channel_layout    = AV_CH_LAYOUT_MONO;
117     else
118         return AVERROR_INVALIDDATA;
119
120     st->codecpar->format                = AV_SAMPLE_FMT_S16;
121     st->codecpar->bits_per_raw_sample   = 16;
122     st->codecpar->bit_rate              = st->codecpar->channels *
123                                           st->codecpar->sample_rate *
124                                           st->codecpar->bits_per_coded_sample;
125
126     if ((ret = avio_read(s->pb, buf, APM_VS12_CHUNK_SIZE)) < 0)
127         return ret;
128     else if (ret != APM_VS12_CHUNK_SIZE)
129         return AVERROR(EIO);
130
131     apm_parse_vs12(&vs12, buf);
132
133     if (vs12.magic != APM_TAG_VS12) {
134         return AVERROR_INVALIDDATA;
135     }
136
137     if (vs12.state.has_saved) {
138         avpriv_request_sample(s, "Saved Samples");
139         return AVERROR_PATCHWELCOME;
140     }
141
142     if (avio_rl32(s->pb) != APM_TAG_DATA)
143         return AVERROR_INVALIDDATA;
144
145     if ((ret = ff_alloc_extradata(st->codecpar, 16)) < 0)
146         return ret;
147
148     AV_WL32(st->codecpar->extradata +  0, vs12.state.predictor_l);
149     AV_WL32(st->codecpar->extradata +  4, vs12.state.step_index_l);
150     AV_WL32(st->codecpar->extradata +  8, vs12.state.predictor_r);
151     AV_WL32(st->codecpar->extradata + 12, vs12.state.step_index_r);
152
153     avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
154     st->start_time  = 0;
155     st->duration    = vs12.data_size *
156                       (8 / st->codecpar->bits_per_coded_sample) /
157                       st->codecpar->channels;
158     return 0;
159 }
160
161 static int apm_read_packet(AVFormatContext *s, AVPacket *pkt)
162 {
163     int ret;
164     AVCodecParameters *par = s->streams[0]->codecpar;
165
166     /*
167      * For future reference: if files with the `has_saved` field set ever
168      * surface, `saved_l`, and `saved_r` will each contain 8 "saved" samples
169      * that should be sent to the decoder before the actual data.
170      */
171
172     if ((ret = av_get_packet(s->pb, pkt, APM_MAX_READ_SIZE)) < 0)
173         return ret;
174
175     pkt->flags          &= ~AV_PKT_FLAG_CORRUPT;
176     pkt->stream_index   = 0;
177     pkt->duration       = ret * (8 / par->bits_per_coded_sample) / par->channels;
178
179     return 0;
180 }
181
182 AVInputFormat ff_apm_demuxer = {
183     .name           = "apm",
184     .long_name      = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"),
185     .read_probe     = apm_probe,
186     .read_header    = apm_read_header,
187     .read_packet    = apm_read_packet
188 };