avcodec/x86/h264_idct: Fix ff_h264_luma_dc_dequant_idct_sse2 checkasm failures
[ffmpeg.git] / libavformat / apm.c
1 /*
2 * Rayman 2 APM (De)muxer
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
23 #include "config_components.h"
24
25 #include "avformat.h"
26 #include "avio_internal.h"
27 #include "demux.h"
28 #include "internal.h"
29 #include "mux.h"
30 #include "rawenc.h"
31 #include "libavutil/channel_layout.h"
32 #include "libavutil/internal.h"
33 #include "libavutil/intreadwrite.h"
34
35 #define APM_FILE_HEADER_SIZE 20
36 #define APM_FILE_EXTRADATA_SIZE 80
37 #define APM_EXTRADATA_SIZE 28
38
39 #define APM_MAX_READ_SIZE 4096
40
41 #define APM_TAG_CODEC 0x2000
42 #define APM_TAG_VS12 MKTAG('v', 's', '1', '2')
43 #define APM_TAG_DATA MKTAG('D', 'A', 'T', 'A')
44
45 typedef struct APMState {
46 int32_t has_saved;
47 int32_t predictor_r;
48 int32_t step_index_r;
49 int32_t saved_r;
50 int32_t predictor_l;
51 int32_t step_index_l;
52 int32_t saved_l;
53 } APMState;
54
55 typedef struct APMExtraData {
56 uint32_t magic;
57 uint32_t file_size;
58 uint32_t data_size;
59 uint32_t unk1;
60 uint32_t unk2;
61 APMState state;
62 uint32_t unk3[7];
63 uint32_t data;
64 } APMExtraData;
65
66 #if CONFIG_APM_DEMUXER
67 static void apm_parse_extradata(APMExtraData *ext, const uint8_t *buf)
68 {
69 ext->magic = AV_RL32(buf + 0);
70 ext->file_size = AV_RL32(buf + 4);
71 ext->data_size = AV_RL32(buf + 8);
72 ext->unk1 = AV_RL32(buf + 12);
73 ext->unk2 = AV_RL32(buf + 16);
74
75 ext->state.has_saved = AV_RL32(buf + 20);
76 ext->state.predictor_r = AV_RL32(buf + 24);
77 ext->state.step_index_r = AV_RL32(buf + 28);
78 ext->state.saved_r = AV_RL32(buf + 32);
79 ext->state.predictor_l = AV_RL32(buf + 36);
80 ext->state.step_index_l = AV_RL32(buf + 40);
81 ext->state.saved_l = AV_RL32(buf + 44);
82
83 for (int i = 0; i < FF_ARRAY_ELEMS(ext->unk3); i++)
84 ext->unk3[i] = AV_RL32(buf + 48 + (i * 4));
85
86 ext->data = AV_RL32(buf + 76);
87 }
88
89 static int apm_probe(const AVProbeData *p)
90 {
91 if (AV_RL16(p->buf) != APM_TAG_CODEC)
92 return 0;
93
94 if (p->buf_size < 100)
95 return 0;
96
97 if (AV_RL32(p->buf + 20) != APM_TAG_VS12)
98 return 0;
99
100 if (AV_RL32(p->buf + 96) != APM_TAG_DATA)
101 return 0;
102
103 return AVPROBE_SCORE_MAX - 1;
104 }
105
106 static int apm_read_header(AVFormatContext *s)
107 {
108 int64_t ret;
109 AVStream *st;
110 APMExtraData extradata;
111 AVCodecParameters *par;
112 uint8_t buf[APM_FILE_EXTRADATA_SIZE];
113 int channels;
114
115 if (!(st = avformat_new_stream(s, NULL)))
116 return AVERROR(ENOMEM);
117
118 /*
119 * This is 98% a WAVEFORMATEX, but there's something screwy with the extradata
120 * that ff_get_wav_header() can't (and shouldn't) handle properly.
121 */
122 if (avio_rl16(s->pb) != APM_TAG_CODEC)
123 return AVERROR_INVALIDDATA;
124
125 par = st->codecpar;
126 channels = avio_rl16(s->pb);
127 par->sample_rate = avio_rl32(s->pb);
128
129 /* Skip the bitrate, it's usually wrong anyway. */
130 if ((ret = avio_skip(s->pb, 4)) < 0)
131 return ret;
132
133 par->block_align = avio_rl16(s->pb);
134 par->bits_per_coded_sample = avio_rl16(s->pb);
135
136 if (avio_rl32(s->pb) != APM_FILE_EXTRADATA_SIZE)
137 return AVERROR_INVALIDDATA;
138
139 /* 8 = bits per sample * max channels */
140 if (par->sample_rate > (INT_MAX / 8))
141 return AVERROR_INVALIDDATA;
142
143 if (par->bits_per_coded_sample != 4)
144 return AVERROR_INVALIDDATA;
145
146 if (channels > 2 || channels == 0)
147 return AVERROR_INVALIDDATA;
148
149 av_channel_layout_default(&par->ch_layout, channels);
150 par->codec_type = AVMEDIA_TYPE_AUDIO;
151 par->codec_id = AV_CODEC_ID_ADPCM_IMA_APM;
152 par->format = AV_SAMPLE_FMT_S16;
153 par->bit_rate = par->ch_layout.nb_channels *
154 (int64_t)par->sample_rate *
155 par->bits_per_coded_sample;
156
157 if ((ret = ffio_read_size(s->pb, buf, APM_FILE_EXTRADATA_SIZE)) < 0)
158 return ret;
159
160 apm_parse_extradata(&extradata, buf);
161
162 if (extradata.magic != APM_TAG_VS12 || extradata.data != APM_TAG_DATA)
163 return AVERROR_INVALIDDATA;
164
165 if (extradata.state.has_saved) {
166 avpriv_request_sample(s, "Saved Samples");
167 return AVERROR_PATCHWELCOME;
168 }
169
170 if ((ret = ff_alloc_extradata(par, APM_EXTRADATA_SIZE)) < 0)
171 return ret;
172
173 /* Use the entire state as extradata. */
174 memcpy(par->extradata, buf + 20, APM_EXTRADATA_SIZE);
175
176 avpriv_set_pts_info(st, 64, 1, par->sample_rate);
177 st->start_time = 0;
178 st->duration = extradata.data_size *
179 (8 / par->bits_per_coded_sample) /
180 par->ch_layout.nb_channels;
181 return 0;
182 }
183
184 static int apm_read_packet(AVFormatContext *s, AVPacket *pkt)
185 {
186 int ret;
187 AVCodecParameters *par = s->streams[0]->codecpar;
188
189 /*
190 * For future reference: if files with the `has_saved` field set ever
191 * surface, `saved_l`, and `saved_r` will each contain 8 "saved" samples
192 * that should be sent to the decoder before the actual data.
193 */
194
195 if ((ret = av_get_packet(s->pb, pkt, APM_MAX_READ_SIZE)) < 0)
196 return ret;
197
198 pkt->flags &= ~AV_PKT_FLAG_CORRUPT;
199 pkt->stream_index = 0;
200 pkt->duration = ret * (8 / par->bits_per_coded_sample) / par->ch_layout.nb_channels;
201
202 return 0;
203 }
204
205 const FFInputFormat ff_apm_demuxer = {
206 .p.name = "apm",
207 .p.long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"),
208 .read_probe = apm_probe,
209 .read_header = apm_read_header,
210 .read_packet = apm_read_packet
211 };
212 #endif
213
214 #if CONFIG_APM_MUXER
215 static int apm_write_init(AVFormatContext *s)
216 {
217 AVCodecParameters *par = s->streams[0]->codecpar;
218
219 if (par->ch_layout.nb_channels > 2) {
220 av_log(s, AV_LOG_ERROR, "APM files only support up to 2 channels\n");
221 return AVERROR(EINVAL);
222 }
223
224 if (par->sample_rate > (INT_MAX / 8)) {
225 av_log(s, AV_LOG_ERROR, "Sample rate too large\n");
226 return AVERROR(EINVAL);
227 }
228
229 if (par->extradata_size != APM_EXTRADATA_SIZE) {
230 av_log(s, AV_LOG_ERROR, "Invalid/missing extradata\n");
231 return AVERROR(EINVAL);
232 }
233
234 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) {
235 av_log(s, AV_LOG_ERROR, "Stream not seekable, unable to write output file\n");
236 return AVERROR(EINVAL);
237 }
238
239 return 0;
240 }
241
242 static int apm_write_header(AVFormatContext *s)
243 {
244 uint8_t buf[APM_FILE_EXTRADATA_SIZE] = { 0 };
245 AVCodecParameters *par = s->streams[0]->codecpar;
246
247 /*
248 * Bodge a WAVEFORMATEX manually, ff_put_wav_header() can't
249 * be used because of the extra 2 bytes.
250 */
251 avio_wl16(s->pb, APM_TAG_CODEC);
252 avio_wl16(s->pb, par->ch_layout.nb_channels);
253 avio_wl32(s->pb, par->sample_rate);
254 /* This is the wrong calculation, but it's what the original files have. */
255 avio_wl32(s->pb, par->sample_rate * par->ch_layout.nb_channels * 2);
256 avio_wl16(s->pb, par->block_align);
257 avio_wl16(s->pb, par->bits_per_coded_sample);
258 avio_wl32(s->pb, APM_FILE_EXTRADATA_SIZE);
259
260 /*
261 * Build the extradata. Assume the codec's given us correct data.
262 * File and data sizes are fixed later.
263 */
264 AV_WL32(buf + 0, APM_TAG_VS12); /* magic */
265 AV_WL32(buf + 12, 0xFFFFFFFF); /* unk1 */
266 memcpy( buf + 20, par->extradata, APM_EXTRADATA_SIZE);
267 AV_WL32(buf + 76, APM_TAG_DATA); /* data */
268
269 avio_write(s->pb, buf, APM_FILE_EXTRADATA_SIZE);
270 return 0;
271 }
272
273 static int apm_write_trailer(AVFormatContext *s)
274 {
275 int64_t file_size, data_size;
276
277 file_size = avio_tell(s->pb);
278 data_size = file_size - (APM_FILE_HEADER_SIZE + APM_FILE_EXTRADATA_SIZE);
279
280 if (file_size >= UINT32_MAX) {
281 av_log(s, AV_LOG_ERROR,
282 "Filesize %"PRId64" invalid for APM, output file will be broken\n",
283 file_size);
284 return AVERROR(ERANGE);
285 }
286
287 avio_seek(s->pb, 24, SEEK_SET);
288 avio_wl32(s->pb, (uint32_t)file_size);
289 avio_wl32(s->pb, (uint32_t)data_size);
290
291 return 0;
292 }
293
294 const FFOutputFormat ff_apm_muxer = {
295 .p.name = "apm",
296 .p.long_name = NULL_IF_CONFIG_SMALL("Ubisoft Rayman 2 APM"),
297 .p.extensions = "apm",
298 .p.audio_codec = AV_CODEC_ID_ADPCM_IMA_APM,
299 .p.video_codec = AV_CODEC_ID_NONE,
300 .p.subtitle_codec = AV_CODEC_ID_NONE,
301 .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH |
302 FF_OFMT_FLAG_ONLY_DEFAULT_CODECS,
303 .init = apm_write_init,
304 .write_header = apm_write_header,
305 .write_packet = ff_raw_write_packet,
306 .write_trailer = apm_write_trailer
307 };
308 #endif