FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/lafdec.c
Date: 2025-04-25 22:50:00
Exec Total Coverage
Lines: 3 163 1.8%
Functions: 1 5 20.0%
Branches: 1 92 1.1%

Line Branch Exec Source
1 /*
2 * Limitless Audio Format demuxer
3 * Copyright (c) 2022 Paul B Mahol
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "libavutil/intfloat.h"
23 #include "libavutil/intreadwrite.h"
24 #include "libavutil/mem.h"
25 #include "avformat.h"
26 #include "avio_internal.h"
27 #include "demux.h"
28 #include "internal.h"
29
30 #define MAX_STREAMS 4096
31
32 typedef struct StreamParams {
33 AVChannelLayout layout;
34 float horizontal;
35 float vertical;
36 int lfe;
37 int stored;
38 } StreamParams;
39
40 typedef struct LAFContext {
41 uint8_t *data;
42 unsigned nb_stored;
43 unsigned stored_index;
44 unsigned index;
45 unsigned bpp;
46
47 StreamParams p[MAX_STREAMS];
48
49 int header_len;
50 uint8_t header[(MAX_STREAMS + 7) / 8];
51 } LAFContext;
52
53 7211 static int laf_probe(const AVProbeData *p)
54 {
55
1/2
✓ Branch 0 taken 7211 times.
✗ Branch 1 not taken.
7211 if (memcmp(p->buf, "LIMITLESS", 9))
56 7211 return 0;
57 if (memcmp(p->buf + 9, "HEAD", 4))
58 return 0;
59 return AVPROBE_SCORE_MAX;
60 }
61
62 static int laf_read_header(AVFormatContext *ctx)
63 {
64 LAFContext *s = ctx->priv_data;
65 AVIOContext *pb = ctx->pb;
66 unsigned st_count, mode;
67 unsigned sample_rate;
68 int64_t duration;
69 int codec_id;
70 int quality;
71 int bpp;
72
73 avio_skip(pb, 9);
74 if (avio_rb32(pb) != MKBETAG('H','E','A','D'))
75 return AVERROR_INVALIDDATA;
76
77 quality = avio_r8(pb);
78 if (quality > 3)
79 return AVERROR_INVALIDDATA;
80 mode = avio_r8(pb);
81 if (mode > 1)
82 return AVERROR_INVALIDDATA;
83 st_count = avio_rl32(pb);
84 if (st_count == 0 || st_count > MAX_STREAMS)
85 return AVERROR_INVALIDDATA;
86
87 for (int i = 0; i < st_count; i++) {
88 StreamParams *stp = &s->p[i];
89
90 stp->vertical = av_int2float(avio_rl32(pb));
91 stp->horizontal = av_int2float(avio_rl32(pb));
92 stp->lfe = avio_r8(pb);
93 if (stp->lfe) {
94 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_LOW_FREQUENCY));
95 } else if (stp->vertical == 0.f &&
96 stp->horizontal == 0.f) {
97 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_FRONT_CENTER));
98 } else if (stp->vertical == 0.f &&
99 stp->horizontal == -30.f) {
100 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_FRONT_LEFT));
101 } else if (stp->vertical == 0.f &&
102 stp->horizontal == 30.f) {
103 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_FRONT_RIGHT));
104 } else if (stp->vertical == 0.f &&
105 stp->horizontal == -110.f) {
106 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_SIDE_LEFT));
107 } else if (stp->vertical == 0.f &&
108 stp->horizontal == 110.f) {
109 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MASK(1, (AV_CH_SIDE_RIGHT));
110 } else {
111 stp->layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_MONO;
112 }
113 }
114
115 sample_rate = avio_rl32(pb);
116 duration = avio_rl64(pb) / st_count;
117
118 if (avio_feof(pb))
119 return AVERROR_INVALIDDATA;
120
121 switch (quality) {
122 case 0:
123 codec_id = AV_CODEC_ID_PCM_U8;
124 bpp = 1;
125 break;
126 case 1:
127 codec_id = AV_CODEC_ID_PCM_S16LE;
128 bpp = 2;
129 break;
130 case 2:
131 codec_id = AV_CODEC_ID_PCM_F32LE;
132 bpp = 4;
133 break;
134 case 3:
135 codec_id = AV_CODEC_ID_PCM_S24LE;
136 bpp = 3;
137 break;
138 default:
139 return AVERROR_INVALIDDATA;
140 }
141
142 s->index = 0;
143 s->stored_index = 0;
144 s->bpp = bpp;
145 if ((int64_t)bpp * st_count * (int64_t)sample_rate >= INT32_MAX ||
146 (int64_t)bpp * st_count * (int64_t)sample_rate == 0
147 )
148 return AVERROR_INVALIDDATA;
149 s->data = av_calloc(st_count * sample_rate, bpp);
150 if (!s->data)
151 return AVERROR(ENOMEM);
152
153 for (unsigned i = 0; i < st_count; i++) {
154 StreamParams *stp = &s->p[i];
155 AVCodecParameters *par;
156 AVStream *st = avformat_new_stream(ctx, NULL);
157 if (!st)
158 return AVERROR(ENOMEM);
159
160 par = st->codecpar;
161 par->codec_id = codec_id;
162 par->codec_type = AVMEDIA_TYPE_AUDIO;
163 par->ch_layout.nb_channels = 1;
164 par->ch_layout = stp->layout;
165 par->sample_rate = sample_rate;
166 st->duration = duration;
167
168 avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
169 }
170
171 s->header_len = (ctx->nb_streams + 7) / 8;
172
173 return 0;
174 }
175
176 static int laf_read_packet(AVFormatContext *ctx, AVPacket *pkt)
177 {
178 AVIOContext *pb = ctx->pb;
179 LAFContext *s = ctx->priv_data;
180 AVStream *st = ctx->streams[0];
181 const int bpp = s->bpp;
182 StreamParams *stp;
183 int64_t pos;
184 int ret;
185
186 pos = avio_tell(pb);
187
188 again:
189 if (avio_feof(pb))
190 return AVERROR_EOF;
191
192 if (s->index >= ctx->nb_streams) {
193 int cur_st = 0, st_count = 0, st_index = 0;
194
195 ret = ffio_read_size(pb, s->header, s->header_len);
196 if (ret < 0)
197 return ret;
198 for (int i = 0; i < s->header_len; i++) {
199 uint8_t val = s->header[i];
200
201 for (int j = 0; j < 8 && cur_st < ctx->nb_streams; j++, cur_st++) {
202 StreamParams *stp = &s->p[st_index];
203
204 stp->stored = 0;
205 if (val & 1) {
206 stp->stored = 1;
207 st_count++;
208 }
209 val >>= 1;
210 st_index++;
211 }
212 }
213
214 s->index = s->stored_index = 0;
215 s->nb_stored = st_count;
216 if (!st_count)
217 return AVERROR_INVALIDDATA;
218 ret = ffio_read_size(pb, s->data, st_count * st->codecpar->sample_rate * bpp);
219 if (ret < 0)
220 return ret;
221 }
222
223 st = ctx->streams[s->index];
224 stp = &s->p[s->index];
225 while (!stp->stored) {
226 s->index++;
227 if (s->index >= ctx->nb_streams)
228 goto again;
229 stp = &s->p[s->index];
230 }
231 st = ctx->streams[s->index];
232
233 ret = av_new_packet(pkt, st->codecpar->sample_rate * bpp);
234 if (ret < 0)
235 return ret;
236
237 switch (bpp) {
238 case 1:
239 for (int n = 0; n < st->codecpar->sample_rate; n++)
240 pkt->data[n] = s->data[n * s->nb_stored + s->stored_index];
241 break;
242 case 2:
243 for (int n = 0; n < st->codecpar->sample_rate; n++)
244 AV_WN16(pkt->data + n * 2, AV_RN16(s->data + n * s->nb_stored * 2 + s->stored_index * 2));
245 break;
246 case 3:
247 for (int n = 0; n < st->codecpar->sample_rate; n++)
248 AV_WL24(pkt->data + n * 3, AV_RL24(s->data + n * s->nb_stored * 3 + s->stored_index * 3));
249 break;
250 case 4:
251 for (int n = 0; n < st->codecpar->sample_rate; n++)
252 AV_WN32(pkt->data + n * 4, AV_RN32(s->data + n * s->nb_stored * 4 + s->stored_index * 4));
253 break;
254 }
255
256 pkt->stream_index = s->index;
257 pkt->pos = pos;
258 s->index++;
259 s->stored_index++;
260
261 return 0;
262 }
263
264 static int laf_read_close(AVFormatContext *ctx)
265 {
266 LAFContext *s = ctx->priv_data;
267
268 av_freep(&s->data);
269
270 return 0;
271 }
272
273 static int laf_read_seek(AVFormatContext *ctx, int stream_index,
274 int64_t timestamp, int flags)
275 {
276 LAFContext *s = ctx->priv_data;
277
278 s->stored_index = s->index = s->nb_stored = 0;
279
280 return -1;
281 }
282
283 const FFInputFormat ff_laf_demuxer = {
284 .p.name = "laf",
285 .p.long_name = NULL_IF_CONFIG_SMALL("LAF (Limitless Audio Format)"),
286 .p.extensions = "laf",
287 .p.flags = AVFMT_GENERIC_INDEX,
288 .priv_data_size = sizeof(LAFContext),
289 .read_probe = laf_probe,
290 .read_header = laf_read_header,
291 .read_packet = laf_read_packet,
292 .read_close = laf_read_close,
293 .read_seek = laf_read_seek,
294 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
295 };
296