FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/sbgdec.c
Date: 2026-10-16 04:22:46
Exec Total Coverage
Lines: 246 871 28.2%
Functions: 27 48 56.2%
Branches: 148 646 22.9%

Line Branch Exec Source
1 /*
2 * SBG (SBaGen) file format decoder
3 * Copyright (c) 2011 Nicolas George
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 <stdio.h>
23 #include <stdlib.h>
24 #include <time.h>
25 #include "libavutil/attributes.h"
26 #include "libavutil/bprint.h"
27 #include "libavutil/channel_layout.h"
28 #include "libavutil/intreadwrite.h"
29 #include "libavutil/log.h"
30 #include "libavutil/mem.h"
31 #include "libavutil/opt.h"
32 #include "libavutil/time_internal.h"
33 #include "avformat.h"
34 #include "demux.h"
35 #include "internal.h"
36
37 #define SBG_SCALE (1 << 16)
38 #define DAY (24 * 60 * 60)
39 #define DAY_TS ((int64_t)DAY * AV_TIME_BASE)
40 #define SBG_MAX_CHANNELS 16
41
42 struct sbg_demuxer {
43 AVClass *class;
44 int sample_rate;
45 int frame_size;
46 int max_file_size;
47 };
48
49 struct sbg_string {
50 char *s;
51 char *e;
52 };
53
54 enum sbg_fade_type {
55 SBG_FADE_SILENCE = 0,
56 SBG_FADE_SAME = 1,
57 SBG_FADE_ADAPT = 3,
58 };
59
60 struct sbg_fade {
61 int8_t in, out, slide;
62 };
63
64 enum sbg_synth_type {
65 SBG_TYPE_NONE,
66 SBG_TYPE_SINE,
67 SBG_TYPE_NOISE,
68 SBG_TYPE_BELL,
69 SBG_TYPE_MIX,
70 SBG_TYPE_SPIN,
71 };
72
73 /* bell: freq constant, ampl decreases exponentially, can be approx lin */
74
75 struct sbg_timestamp {
76 int64_t t;
77 char type; /* 0 for relative, 'N' for now, 'T' for absolute */
78 };
79
80 struct sbg_script_definition {
81 char *name;
82 int name_len;
83 int elements, nb_elements;
84 char type; /* 'S' or 'B' */
85 };
86
87 struct sbg_script_synth {
88 int carrier;
89 int beat;
90 int vol;
91 enum sbg_synth_type type;
92 struct {
93 int l, r;
94 } ref;
95 };
96
97 struct sbg_script_tseq {
98 struct sbg_timestamp ts;
99 char *name;
100 int name_len;
101 int lock;
102 struct sbg_fade fade;
103 };
104
105 struct sbg_script_event {
106 int64_t ts;
107 int64_t ts_int, ts_trans, ts_next;
108 int elements, nb_elements;
109 struct sbg_fade fade;
110 };
111
112 struct sbg_script {
113 struct sbg_script_definition *def;
114 struct sbg_script_synth *synth;
115 struct sbg_script_tseq *tseq;
116 struct sbg_script_tseq *block_tseq;
117 struct sbg_script_event *events;
118 int nb_def;
119 int nb_tseq;
120 int nb_events;
121 int nb_synth;
122 int64_t start_ts;
123 int64_t end_ts;
124 int64_t opt_fade_time;
125 int64_t opt_duration;
126 char *opt_mix;
127 int sample_rate;
128 uint8_t opt_start_at_first;
129 uint8_t opt_end_at_last;
130 };
131
132 struct sbg_parser {
133 void *log;
134 char *script, *end;
135 char *cursor;
136 struct sbg_script scs;
137 struct sbg_timestamp current_time;
138 int nb_block_tseq;
139 int nb_def_max, nb_synth_max, nb_tseq_max, nb_block_tseq_max;
140 int line_no;
141 char err_msg[128];
142 };
143
144 enum ws_interval_type {
145 WS_SINE = MKTAG('S','I','N','E'),
146 WS_NOISE = MKTAG('N','O','I','S'),
147 };
148
149 struct ws_interval {
150 int64_t ts1, ts2;
151 enum ws_interval_type type;
152 uint32_t channels;
153 int32_t f1, f2;
154 int32_t a1, a2;
155 uint32_t phi;
156 };
157
158 struct ws_intervals {
159 struct ws_interval *inter;
160 int nb_inter;
161 int max_inter;
162 };
163
164 5 static void *alloc_array_elem(void **array, size_t elsize,
165 int *size, int *max_size)
166 {
167 void *ret;
168
169
1/2
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
5 if (*size == *max_size) {
170 5 int m = FFMAX(32, FFMIN(*max_size, INT_MAX / 2) * 2);
171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (*size >= m)
172 ✗ return NULL;
173 5 *array = av_realloc_f(*array, m, elsize);
174
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!*array)
175 ✗ return NULL;
176 5 *max_size = m;
177 }
178 5 ret = (char *)*array + elsize * *size;
179 5 memset(ret, 0, elsize);
180 5 (*size)++;
181 5 return ret;
182 }
183
184 8163 static int str_to_time(const char *str, int64_t *rtime)
185 {
186 8163 const char *cur = str;
187 char *end;
188 int hours, minutes;
189 8163 double seconds = 0;
190 8163 int64_t ts = 0;
191
192
4/4
✓ Branch 0 taken 2112 times.
✓ Branch 1 taken 6051 times.
✓ Branch 2 taken 2044 times.
✓ Branch 3 taken 68 times.
8163 if (*cur < '0' || *cur > '9')
193 8095 return 0;
194 68 hours = strtol(cur, &end, 10);
195
5/8
✓ Branch 0 taken 68 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 64 times.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
68 if (end == cur || *end != ':' || end[1] < '0' || end[1] > '9')
196 64 return 0;
197 4 cur = end + 1;
198 4 minutes = strtol(cur, &end, 10);
199
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (end == cur)
200 ✗ return 0;
201 4 cur = end;
202
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (*end == ':'){
203 4 seconds = strtod(cur + 1, &end);
204
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 if (end > cur + 1)
205 4 cur = end;
206 4 ts = av_clipd(seconds * AV_TIME_BASE, INT64_MIN/2, INT64_MAX/2);
207 }
208 4 *rtime = av_sat_add64((hours * 3600LL + minutes * 60LL) * AV_TIME_BASE, ts);
209 4 return cur - str;
210 }
211
212 8340 static inline int is_space(char c)
213 {
214
6/6
✓ Branch 0 taken 8332 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8330 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 8329 times.
8340 return c == ' ' || c == '\t' || c == '\r';
215 }
216
217 ✗ static inline int scale_double(void *log, double d, double m, int *r)
218 {
219 ✗ m *= d * SBG_SCALE;
220 ✗ if (m < INT_MIN || m >= INT_MAX) {
221 ✗ if (log)
222 ✗ av_log(log, AV_LOG_ERROR, "%g is too large\n", d);
223 ✗ return AVERROR(EDOM);
224 }
225 ✗ *r = m;
226 ✗ return 0;
227 }
228
229 8322 static int lex_space(struct sbg_parser *p)
230 {
231 8322 char *c = p->cursor;
232
233
3/4
✓ Branch 0 taken 8332 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 10 times.
✓ Branch 4 taken 8322 times.
8332 while (p->cursor < p->end && is_space(*p->cursor))
234 10 p->cursor++;
235 8322 return p->cursor > c;
236 }
237
238 10230 static int lex_char(struct sbg_parser *p, char c)
239 {
240
3/4
✓ Branch 0 taken 10230 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 10215 times.
10230 int r = p->cursor < p->end && *p->cursor == c;
241
242 10230 p->cursor += r;
243 10230 return r;
244 }
245
246 4 static int lex_double(struct sbg_parser *p, double *r)
247 {
248 double d;
249 char *end;
250
251
3/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
4 if (p->cursor == p->end || is_space(*p->cursor) || *p->cursor == '\n')
252 ✗ return 0;
253 4 d = strtod(p->cursor, &end);
254
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
4 if (end > p->cursor) {
255 2 *r = d;
256 2 p->cursor = end;
257 2 return 1;
258 }
259 2 return 0;
260 }
261
262 8172 static int lex_fixed(struct sbg_parser *p, const char *t, int l)
263 {
264
2/4
✓ Branch 0 taken 8172 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8172 times.
✗ Branch 3 not taken.
8172 if (p->end - p->cursor < l || memcmp(p->cursor, t, l))
265 8172 return 0;
266 ✗ p->cursor += l;
267 ✗ return 1;
268 }
269
270 16455 static int lex_line_end(struct sbg_parser *p)
271 {
272
3/4
✓ Branch 0 taken 16455 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 133 times.
✓ Branch 3 taken 16322 times.
16455 if (p->cursor < p->end && *p->cursor == '#') {
273 133 p->cursor++;
274
3/4
✓ Branch 0 taken 11998 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11865 times.
✓ Branch 3 taken 133 times.
11998 while (p->cursor < p->end && *p->cursor != '\n')
275 11865 p->cursor++;
276 }
277
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16455 times.
16455 if (p->cursor == p->end)
278 /* simulate final LF for files lacking it */
279 ✗ return 1;
280
2/2
✓ Branch 0 taken 16319 times.
✓ Branch 1 taken 136 times.
16455 if (*p->cursor != '\n')
281 16319 return 0;
282 136 p->cursor++;
283 136 p->line_no++;
284 136 lex_space(p);
285 136 return 1;
286 }
287
288 1 static int lex_wsword(struct sbg_parser *p, struct sbg_string *rs)
289 {
290 1 char *s = p->cursor, *c = s;
291
292
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (s == p->end || *s == '\n')
293 ✗ return 0;
294
4/6
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 1 times.
4 while (c < p->end && *c != '\n' && !is_space(*c))
295 3 c++;
296 1 rs->s = s;
297 1 rs->e = p->cursor = c;
298 1 lex_space(p);
299 1 return 1;
300 }
301
302 8166 static int lex_name(struct sbg_parser *p, struct sbg_string *rs)
303 {
304 8166 char *s = p->cursor, *c = s;
305
306
9/10
✓ Branch 0 taken 16287 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1338 times.
✓ Branch 3 taken 14949 times.
✓ Branch 4 taken 1287 times.
✓ Branch 5 taken 51 times.
✓ Branch 6 taken 6593 times.
✓ Branch 7 taken 8407 times.
✓ Branch 8 taken 6473 times.
✓ Branch 9 taken 120 times.
16287 while (c < p->end && ((*c >= 'a' && *c <= 'z') || (*c >= 'A' && *c <= 'Z')
307
8/8
✓ Branch 0 taken 603 times.
✓ Branch 1 taken 7924 times.
✓ Branch 2 taken 303 times.
✓ Branch 3 taken 300 times.
✓ Branch 4 taken 37 times.
✓ Branch 5 taken 8187 times.
✓ Branch 6 taken 21 times.
✓ Branch 7 taken 8166 times.
8527 || (*c >= '0' && *c <= '9') || *c == '_' || *c == '-'))
308 8121 c++;
309
2/2
✓ Branch 0 taken 6110 times.
✓ Branch 1 taken 2056 times.
8166 if (c == s)
310 6110 return 0;
311 2056 rs->s = s;
312 2056 rs->e = p->cursor = c;
313 2056 return 1;
314 }
315
316 8163 static int lex_time(struct sbg_parser *p, int64_t *rt)
317 {
318 8163 int r = str_to_time(p->cursor, rt);
319 8163 p->cursor += r;
320 8163 return r > 0;
321 }
322
323 #define FORWARD_ERROR(c) \
324 do { \
325 int errcode = c; \
326 if (errcode <= 0) \
327 return errcode ? errcode : AVERROR_INVALIDDATA; \
328 } while (0)
329
330 ✗ static int parse_immediate(struct sbg_parser *p)
331 {
332 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
333 "immediate sequences not yet implemented");
334 ✗ return AVERROR_PATCHWELCOME;
335 }
336
337 ✗ static int parse_preprogrammed(struct sbg_parser *p)
338 {
339 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
340 "preprogrammed sequences not yet implemented");
341 ✗ return AVERROR_PATCHWELCOME;
342 }
343
344 ✗ static int parse_optarg(struct sbg_parser *p, char o, struct sbg_string *r)
345 {
346 ✗ if (!lex_wsword(p, r)) {
347 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
348 "option '%c' requires an argument", o);
349 ✗ return AVERROR_INVALIDDATA;
350 }
351 ✗ return 1;
352 }
353
354 8298 static int parse_options(struct sbg_parser *p)
355 {
356 struct sbg_string ostr, oarg;
357 8298 char mode = 0;
358 int r;
359 char *tptr;
360 double v;
361
362
3/4
✓ Branch 0 taken 8298 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 8297 times.
✓ Branch 3 taken 1 times.
8298 if (p->cursor == p->end || *p->cursor != '-')
363 8297 return 0;
364
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 while (lex_char(p, '-') && lex_wsword(p, &ostr)) {
365
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 for (; ostr.s < ostr.e; ostr.s++) {
366 1 char opt = *ostr.s;
367
1/11
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 times.
1 switch (opt) {
368 ✗ case 'S':
369 ✗ p->scs.opt_start_at_first = 1;
370 ✗ break;
371 ✗ case 'E':
372 ✗ p->scs.opt_end_at_last = 1;
373 ✗ break;
374 ✗ case 'i':
375 ✗ mode = 'i';
376 ✗ break;
377 ✗ case 'p':
378 ✗ mode = 'p';
379 ✗ break;
380 ✗ case 'F':
381 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
382 ✗ v = strtod(oarg.s, &tptr);
383 ✗ if (oarg.e != tptr) {
384 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
385 "syntax error for option -F");
386 ✗ return AVERROR_INVALIDDATA;
387 }
388 ✗ p->scs.opt_fade_time = v * AV_TIME_BASE / 1000;
389 ✗ break;
390 ✗ case 'L':
391 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
392 ✗ r = str_to_time(oarg.s, &p->scs.opt_duration);
393 ✗ if (oarg.e != oarg.s + r || p->scs.opt_duration < 0) {
394 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
395 "syntax error for option -L");
396 ✗ return AVERROR_INVALIDDATA;
397 }
398 ✗ break;
399 ✗ case 'T':
400 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
401 ✗ r = str_to_time(oarg.s, &p->scs.start_ts);
402 ✗ if (oarg.e != oarg.s + r) {
403 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
404 "syntax error for option -T");
405 ✗ return AVERROR_INVALIDDATA;
406 }
407 ✗ break;
408 ✗ case 'm':
409 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
410 ✗ tptr = av_malloc(oarg.e - oarg.s + 1);
411 ✗ if (!tptr)
412 ✗ return AVERROR(ENOMEM);
413 ✗ memcpy(tptr, oarg.s, oarg.e - oarg.s);
414 ✗ tptr[oarg.e - oarg.s] = 0;
415 ✗ av_free(p->scs.opt_mix);
416 ✗ p->scs.opt_mix = tptr;
417 ✗ break;
418 ✗ case 'q':
419 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
420 ✗ v = strtod(oarg.s, &tptr);
421 ✗ if (oarg.e != tptr) {
422 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
423 "syntax error for option -q");
424 ✗ return AVERROR_INVALIDDATA;
425 }
426 ✗ if (v != 1) {
427 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
428 "speed factor other than 1 not supported");
429 ✗ return AVERROR_PATCHWELCOME;
430 }
431 ✗ break;
432 ✗ case 'r':
433 ✗ FORWARD_ERROR(parse_optarg(p, opt, &oarg));
434 ✗ r = strtol(oarg.s, &tptr, 10);
435 ✗ if (oarg.e != tptr) {
436 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
437 "syntax error for option -r");
438 ✗ return AVERROR_INVALIDDATA;
439 }
440 ✗ if (r < 40) {
441 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
442 "invalid sample rate");
443 ✗ return AVERROR_PATCHWELCOME;
444 }
445 ✗ p->scs.sample_rate = r;
446 ✗ break;
447 1 default:
448 1 snprintf(p->err_msg, sizeof(p->err_msg),
449 1 "unknown option: '%c'", *ostr.s);
450 1 return AVERROR_INVALIDDATA;
451 }
452 }
453 }
454 ✗ switch (mode) {
455 ✗ case 'i':
456 ✗ return parse_immediate(p);
457 ✗ case 'p':
458 ✗ return parse_preprogrammed(p);
459 ✗ case 0:
460 ✗ if (!lex_line_end(p))
461 ✗ return AVERROR_INVALIDDATA;
462 ✗ return 1;
463 }
464 ✗ return AVERROR_BUG;
465 }
466
467 8161 static int parse_timestamp(struct sbg_parser *p,
468 struct sbg_timestamp *rts, int64_t *rrel)
469 {
470 8161 int64_t abs = 0, rel = 0, dt;
471 8161 char type = 0;
472 int r;
473
474
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8161 times.
8161 if (lex_fixed(p, "NOW", 3)) {
475 ✗ type = 'N';
476 ✗ r = 1;
477 } else {
478 8161 r = lex_time(p, &abs);
479
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8157 times.
8161 if (r)
480 4 type = 'T';
481 }
482
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 8159 times.
8161 while (lex_char(p, '+')) {
483
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_time(p, &dt))
484 2 return AVERROR_INVALIDDATA;
485 ✗ if (av_sat_add64(rel, dt) - dt != rel)
486 ✗ return AVERROR_INVALIDDATA;
487 ✗ rel += dt;
488 ✗ r = 1;
489 }
490
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 8155 times.
8159 if (r) {
491
2/2
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
4 if (!lex_space(p))
492 1 return AVERROR_INVALIDDATA;
493 3 rts->type = type;
494 3 rts->t = abs;
495 3 *rrel = rel;
496 }
497 8158 return r;
498 }
499
500 3 static int parse_fade(struct sbg_parser *p, struct sbg_fade *fr)
501 {
502 3 struct sbg_fade f = {0};
503
504
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (lex_char(p, '<'))
505 ✗ f.in = SBG_FADE_SILENCE;
506
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 else if (lex_char(p, '-'))
507 ✗ f.in = SBG_FADE_SAME;
508
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 else if (lex_char(p, '='))
509 ✗ f.in = SBG_FADE_ADAPT;
510 else
511 3 return 0;
512 ✗ if (lex_char(p, '>'))
513 ✗ f.out = SBG_FADE_SILENCE;
514 ✗ else if (lex_char(p, '-'))
515 ✗ f.out = SBG_FADE_SAME;
516 ✗ else if (lex_char(p, '='))
517 ✗ f.out = SBG_FADE_ADAPT;
518 else
519 ✗ return AVERROR_INVALIDDATA;
520 ✗ *fr = f;
521 ✗ return 1;
522 }
523
524 8161 static int parse_time_sequence(struct sbg_parser *p, int inblock)
525 {
526 struct sbg_timestamp ts;
527 int64_t rel_ts;
528 int r;
529 8161 struct sbg_fade fade = { SBG_FADE_SAME, SBG_FADE_SAME, 0 };
530 struct sbg_string name;
531 struct sbg_script_tseq *tseq;
532
533 8161 r = parse_timestamp(p, &ts, &rel_ts);
534
2/2
✓ Branch 0 taken 8155 times.
✓ Branch 1 taken 6 times.
8161 if (!r)
535 8155 return 0;
536
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
6 if (r < 0)
537 3 return r;
538
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (ts.type) {
539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (inblock)
540 ✗ return AVERROR_INVALIDDATA;
541 3 p->current_time.type = ts.type;
542 3 p->current_time.t = ts.t;
543 ✗ } else if(!inblock && !p->current_time.type) {
544 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
545 "relative time without previous absolute time");
546 ✗ return AVERROR_INVALIDDATA;
547 }
548 3 ts.type = p->current_time.type;
549
550
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (av_sat_add64(p->current_time.t, rel_ts) != p->current_time.t + (uint64_t)rel_ts)
551 ✗ return AVERROR_INVALIDDATA;
552
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 ts.t = inblock ? rel_ts : p->current_time.t + rel_ts;
553 3 r = parse_fade(p, &fade);
554
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (r < 0)
555 ✗ return r;
556 3 lex_space(p);
557
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (!lex_name(p, &name))
558 ✗ return AVERROR_INVALIDDATA;
559 3 lex_space(p);
560
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (lex_fixed(p, "->", 2)) {
561 ✗ fade.slide = SBG_FADE_ADAPT;
562 ✗ lex_space(p);
563 }
564
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1 times.
3 if (!lex_line_end(p))
565 2 return AVERROR_INVALIDDATA;
566
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 tseq = inblock ?
567 ✗ alloc_array_elem((void **)&p->scs.block_tseq, sizeof(*tseq),
568 &p->nb_block_tseq, &p->nb_block_tseq_max) :
569 1 alloc_array_elem((void **)&p->scs.tseq, sizeof(*tseq),
570 &p->scs.nb_tseq, &p->nb_tseq_max);
571
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!tseq)
572 ✗ return AVERROR(ENOMEM);
573 1 tseq->ts = ts;
574 1 tseq->name = name.s;
575 1 tseq->name_len = name.e - name.s;
576 1 tseq->fade = fade;
577 1 return 1;
578 }
579
580 ✗ static int parse_wave_def(struct sbg_parser *p, int wavenum)
581 {
582 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
583 "waveform definitions not yet implemented");
584 ✗ return AVERROR_PATCHWELCOME;
585 }
586
587 ✗ static int parse_block_def(struct sbg_parser *p,
588 struct sbg_script_definition *def)
589 {
590 int r, tseq;
591
592 ✗ lex_space(p);
593 ✗ if (!lex_line_end(p))
594 ✗ return AVERROR_INVALIDDATA;
595 ✗ tseq = p->nb_block_tseq;
596 while (1) {
597 ✗ r = parse_time_sequence(p, 1);
598 ✗ if (r < 0)
599 ✗ return r;
600 ✗ if (!r)
601 ✗ break;
602 }
603 ✗ if (!lex_char(p, '}'))
604 ✗ return AVERROR_INVALIDDATA;
605 ✗ lex_space(p);
606 ✗ if (!lex_line_end(p))
607 ✗ return AVERROR_INVALIDDATA;
608 ✗ def->type = 'B';
609 ✗ def->elements = tseq;
610 ✗ def->nb_elements = p->nb_block_tseq - tseq;
611 ✗ if (!def->nb_elements)
612 ✗ return AVERROR_INVALIDDATA;
613 ✗ return 1;
614 }
615
616 2 static int parse_volume(struct sbg_parser *p, int *vol)
617 {
618 double v;
619
620
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_char(p, '/'))
621 2 return 0;
622 ✗ if (!lex_double(p, &v))
623 ✗ return AVERROR_INVALIDDATA;
624 ✗ if (scale_double(p->log, v, 0.01, vol))
625 ✗ return AVERROR(ERANGE);
626 ✗ return 1;
627 }
628
629 2 static int parse_synth_channel_sine(struct sbg_parser *p,
630 struct sbg_script_synth *synth)
631 {
632 double carrierf, beatf;
633 int carrier, beat, vol;
634
635
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (!lex_double(p, &carrierf))
636 ✗ return 0;
637
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_double(p, &beatf))
638 2 beatf = 0;
639
2/4
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 FORWARD_ERROR(parse_volume(p, &vol));
640 ✗ if (scale_double(p->log, carrierf, 1, &carrier) < 0 ||
641 ✗ scale_double(p->log, beatf, 1, &beat) < 0)
642 ✗ return AVERROR(EDOM);
643 ✗ synth->type = SBG_TYPE_SINE;
644 ✗ synth->carrier = carrier;
645 ✗ synth->beat = beat;
646 ✗ synth->vol = vol;
647 ✗ return 1;
648 }
649
650 2 static int parse_synth_channel_pink(struct sbg_parser *p,
651 struct sbg_script_synth *synth)
652 {
653 int vol;
654
655
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_fixed(p, "pink", 4))
656 2 return 0;
657 ✗ FORWARD_ERROR(parse_volume(p, &vol));
658 ✗ synth->type = SBG_TYPE_NOISE;
659 ✗ synth->vol = vol;
660 ✗ return 1;
661 }
662
663 2 static int parse_synth_channel_bell(struct sbg_parser *p,
664 struct sbg_script_synth *synth)
665 {
666 double carrierf;
667 int carrier, vol;
668
669
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_fixed(p, "bell", 4))
670 2 return 0;
671 ✗ if (!lex_double(p, &carrierf))
672 ✗ return AVERROR_INVALIDDATA;
673 ✗ FORWARD_ERROR(parse_volume(p, &vol));
674 ✗ if (scale_double(p->log, carrierf, 1, &carrier) < 0)
675 ✗ return AVERROR(EDOM);
676 ✗ synth->type = SBG_TYPE_BELL;
677 ✗ synth->carrier = carrier;
678 ✗ synth->vol = vol;
679 ✗ return 1;
680 }
681
682 2 static int parse_synth_channel_mix(struct sbg_parser *p,
683 struct sbg_script_synth *synth)
684 {
685 int vol;
686
687
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_fixed(p, "mix", 3))
688 2 return 0;
689 ✗ FORWARD_ERROR(parse_volume(p, &vol));
690 ✗ synth->type = SBG_TYPE_MIX;
691 ✗ synth->vol = vol;
692 ✗ return 1;
693 }
694
695 2 static int parse_synth_channel_spin(struct sbg_parser *p,
696 struct sbg_script_synth *synth)
697 {
698 double carrierf, beatf;
699 int carrier, beat, vol;
700
701
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 if (!lex_fixed(p, "spin:", 5))
702 2 return 0;
703 ✗ if (!lex_double(p, &carrierf))
704 ✗ return AVERROR_INVALIDDATA;
705 ✗ if (!lex_double(p, &beatf))
706 ✗ return AVERROR_INVALIDDATA;
707 ✗ FORWARD_ERROR(parse_volume(p, &vol));
708 ✗ if (scale_double(p->log, carrierf, 1, &carrier) < 0 ||
709 ✗ scale_double(p->log, beatf, 1, &beat) < 0)
710 ✗ return AVERROR(EDOM);
711 ✗ synth->type = SBG_TYPE_SPIN;
712 ✗ synth->carrier = carrier;
713 ✗ synth->beat = beat;
714 ✗ synth->vol = vol;
715 ✗ return 1;
716 }
717
718 2 static int parse_synth_channel(struct sbg_parser *p)
719 {
720 int r;
721 struct sbg_script_synth *synth;
722
723 2 synth = alloc_array_elem((void **)&p->scs.synth, sizeof(*synth),
724 &p->scs.nb_synth, &p->nb_synth_max);
725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!synth)
726 ✗ return AVERROR(ENOMEM);
727 2 r = lex_char(p, '-');
728
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!r)
729 2 r = parse_synth_channel_pink(p, synth);
730
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!r)
731 2 r = parse_synth_channel_bell(p, synth);
732
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!r)
733 2 r = parse_synth_channel_mix(p, synth);
734
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!r)
735 2 r = parse_synth_channel_spin(p, synth);
736 /* Unimplemented: wave%d:%f%f/vol (carrier, beat) */
737
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!r)
738 2 r = parse_synth_channel_sine(p, synth);
739
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (r <= 0)
740 2 p->scs.nb_synth--;
741 2 return r;
742 }
743
744 2 static int parse_synth_def(struct sbg_parser *p,
745 struct sbg_script_definition *def)
746 {
747 int r, synth;
748
749 2 synth = p->scs.nb_synth;
750 while (1) {
751 2 r = parse_synth_channel(p);
752
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (r < 0)
753 2 return r;
754 ✗ if (!r || !lex_space(p))
755 break;
756 }
757 ✗ lex_space(p);
758 ✗ if (synth == p->scs.nb_synth)
759 ✗ return AVERROR_INVALIDDATA;
760 ✗ if (p->scs.nb_synth - synth > SBG_MAX_CHANNELS) {
761 ✗ snprintf(p->err_msg, sizeof(p->err_msg),
762 "too many channels in tone-set");
763 ✗ return AVERROR_INVALIDDATA;
764 }
765 ✗ if (!lex_line_end(p))
766 ✗ return AVERROR_INVALIDDATA;
767 ✗ def->type = 'S';
768 ✗ def->elements = synth;
769 ✗ def->nb_elements = p->scs.nb_synth - synth;
770 ✗ return 1;
771 }
772
773 8163 static int parse_named_def(struct sbg_parser *p)
774 {
775 8163 char *cursor_save = p->cursor;
776 struct sbg_string name;
777 struct sbg_script_definition *def;
778
779
6/6
✓ Branch 1 taken 2053 times.
✓ Branch 2 taken 6110 times.
✓ Branch 4 taken 12 times.
✓ Branch 5 taken 2041 times.
✓ Branch 7 taken 10 times.
✓ Branch 8 taken 2 times.
8163 if (!lex_name(p, &name) || !lex_char(p, ':') || !lex_space(p)) {
780 8161 p->cursor = cursor_save;
781 8161 return 0;
782 }
783
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
2 if (name.e - name.s == 6 && !memcmp(name.s, "wave", 4) &&
784 ✗ name.s[4] >= '0' && name.s[4] <= '9' &&
785 ✗ name.s[5] >= '0' && name.s[5] <= '9') {
786 ✗ int wavenum = (name.s[4] - '0') * 10 + (name.s[5] - '0');
787 ✗ return parse_wave_def(p, wavenum);
788 }
789 2 def = alloc_array_elem((void **)&p->scs.def, sizeof(*def),
790 &p->scs.nb_def, &p->nb_def_max);
791
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!def)
792 ✗ return AVERROR(ENOMEM);
793 2 def->name = name.s;
794 2 def->name_len = name.e - name.s;
795
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if (lex_char(p, '{'))
796 ✗ return parse_block_def(p, def);
797 2 return parse_synth_def(p, def);
798 }
799
800 16326 static void free_script(struct sbg_script *s)
801 {
802 16326 av_freep(&s->def);
803 16326 av_freep(&s->synth);
804 16326 av_freep(&s->tseq);
805 16326 av_freep(&s->block_tseq);
806 16326 av_freep(&s->events);
807 16326 av_freep(&s->opt_mix);
808 16326 }
809
810 8163 static int parse_script(void *log, char *script, int script_len,
811 struct sbg_script *rscript)
812 {
813 8163 struct sbg_parser sp = {
814 .log = log,
815 .script = script,
816 8163 .end = script + script_len,
817 .cursor = script,
818 .line_no = 1,
819 .err_msg = "",
820 .scs = {
821 /* default values */
822 .start_ts = AV_NOPTS_VALUE,
823 .sample_rate = 44100,
824 .opt_fade_time = 60 * AV_TIME_BASE,
825 },
826 };
827 int r;
828
829 8163 lex_space(&sp);
830
1/2
✓ Branch 0 taken 8298 times.
✗ Branch 1 not taken.
16461 while (sp.cursor < sp.end) {
831 8298 r = parse_options(&sp);
832
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8297 times.
8298 if (r < 0)
833 1 goto fail;
834
3/4
✓ Branch 0 taken 8297 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 8162 times.
✓ Branch 4 taken 135 times.
8297 if (!r && !lex_line_end(&sp))
835 8162 break;
836 }
837
1/2
✓ Branch 0 taken 8163 times.
✗ Branch 1 not taken.
8163 while (sp.cursor < sp.end) {
838 8163 r = parse_named_def(&sp);
839
2/2
✓ Branch 0 taken 8161 times.
✓ Branch 1 taken 2 times.
8163 if (!r)
840 8161 r = parse_time_sequence(&sp, 0);
841
2/2
✓ Branch 0 taken 8155 times.
✓ Branch 1 taken 8 times.
8163 if (!r)
842
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8155 times.
8155 r = lex_line_end(&sp) ? 1 : AVERROR_INVALIDDATA;
843
2/2
✓ Branch 0 taken 8162 times.
✓ Branch 1 taken 1 times.
8163 if (r < 0)
844 8162 goto fail;
845 }
846 ✗ *rscript = sp.scs;
847 ✗ return 1;
848 8163 fail:
849 8163 free_script(&sp.scs);
850
2/2
✓ Branch 0 taken 8162 times.
✓ Branch 1 taken 1 times.
8163 if (!*sp.err_msg)
851
1/2
✓ Branch 0 taken 8162 times.
✗ Branch 1 not taken.
8162 if (r == AVERROR_INVALIDDATA)
852 8162 snprintf(sp.err_msg, sizeof(sp.err_msg), "syntax error");
853
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8163 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
8163 if (log && *sp.err_msg) {
854 ✗ const char *ctx = sp.cursor;
855 ✗ const char *ectx = av_x_if_null(memchr(ctx, '\n', sp.end - sp.cursor),
856 ✗ sp.end);
857 ✗ int lctx = ectx - ctx;
858 ✗ const char *quote = "\"";
859 ✗ if (lctx > 0 && ctx[lctx - 1] == '\r')
860 ✗ lctx--;
861 ✗ if (lctx == 0) {
862 ✗ ctx = "the end of line";
863 ✗ lctx = strlen(ctx);
864 ✗ quote = "";
865 }
866 ✗ av_log(log, AV_LOG_ERROR, "Error line %d: %s near %s%.*s%s.\n",
867 sp.line_no, sp.err_msg, quote, lctx, ctx, quote);
868 }
869 8163 return r;
870 }
871
872 ✗ static int read_whole_file(AVIOContext *io, int max_size, AVBPrint *rbuf)
873 {
874 ✗ int ret = avio_read_to_bprint(io, rbuf, max_size);
875 ✗ if (ret < 0)
876 ✗ return ret;
877 ✗ if (!av_bprint_is_complete(rbuf))
878 ✗ return AVERROR(ENOMEM);
879 /* Check if we have read the whole file. AVIOContext.eof_reached is only
880 * set after a read failed due to EOF, so this check is incorrect in case
881 * max_size equals the actual file size, but checking for that would
882 * require attempting to read beyond max_size. */
883 ✗ if (!io->eof_reached)
884 ✗ return AVERROR(EFBIG);
885 ✗ return 0;
886 }
887
888 ✗ static int expand_timestamps(void *log, struct sbg_script *s)
889 {
890 ✗ int i, nb_rel = 0;
891 ✗ int64_t now, cur_ts, delta = 0;
892
893 ✗ for (i = 0; i < s->nb_tseq; i++)
894 ✗ nb_rel += s->tseq[i].ts.type == 'N';
895 ✗ if (nb_rel == s->nb_tseq) {
896 /* All ts are relative to NOW: consider NOW = 0 */
897 ✗ now = 0;
898 ✗ if (s->start_ts != AV_NOPTS_VALUE)
899 ✗ av_log(log, AV_LOG_WARNING,
900 "Start time ignored in a purely relative script.\n");
901 ✗ } else if (nb_rel == 0 && s->start_ts != AV_NOPTS_VALUE ||
902 ✗ s->opt_start_at_first) {
903 /* All ts are absolute and start time is specified */
904 ✗ if (s->start_ts == AV_NOPTS_VALUE)
905 ✗ s->start_ts = s->tseq[0].ts.t;
906 ✗ now = s->start_ts;
907 } else {
908 /* Mixed relative/absolute ts: expand */
909 time_t now0;
910 struct tm *tm, tmpbuf;
911
912 ✗ av_log(log, AV_LOG_WARNING,
913 "Scripts with mixed absolute and relative timestamps can give "
914 "unexpected results (pause, seeking, time zone change).\n");
915 ✗ time(&now0);
916 ✗ tm = localtime_r(&now0, &tmpbuf);
917 ✗ now = tm ? tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec :
918 ✗ now0 % DAY;
919 ✗ av_log(log, AV_LOG_INFO, "Using %02d:%02d:%02d as NOW.\n",
920 ✗ (int)(now / 3600), (int)(now / 60) % 60, (int)now % 60);
921 ✗ now *= AV_TIME_BASE;
922 ✗ for (i = 0; i < s->nb_tseq; i++) {
923 ✗ if (s->tseq[i].ts.type == 'N') {
924 ✗ s->tseq[i].ts.t += now;
925 ✗ s->tseq[i].ts.type = 'T'; /* not necessary */
926 }
927 }
928 }
929 ✗ if (s->start_ts == AV_NOPTS_VALUE)
930 ✗ s->start_ts = (s->opt_start_at_first && s->tseq) ? s->tseq[0].ts.t : now;
931 ✗ if (s->start_ts > INT64_MAX - s->opt_duration)
932 ✗ return AVERROR_INVALIDDATA;
933
934 ✗ s->end_ts = s->opt_duration ? s->start_ts + s->opt_duration :
935 AV_NOPTS_VALUE; /* may be overridden later by -E option */
936 ✗ cur_ts = now;
937 ✗ for (i = 0; i < s->nb_tseq; i++) {
938 ✗ if (av_sat_add64(s->tseq[i].ts.t, delta) != s->tseq[i].ts.t + (uint64_t)delta)
939 ✗ return AVERROR_INVALIDDATA;
940 ✗ if (s->tseq[i].ts.t + delta < cur_ts)
941 ✗ delta += DAY_TS;
942 ✗ cur_ts = s->tseq[i].ts.t += delta;
943 }
944 ✗ return 0;
945 }
946
947 ✗ static int expand_tseq(void *log, struct sbg_script *s, int *nb_ev_max,
948 int64_t max_events, int64_t t0,
949 struct sbg_script_tseq *tseq)
950 {
951 int i, r;
952 struct sbg_script_definition *def;
953 struct sbg_script_tseq *be;
954 struct sbg_script_event *ev;
955
956 ✗ if (tseq->lock++) {
957 ✗ av_log(log, AV_LOG_ERROR, "Recursion loop on \"%.*s\"\n",
958 tseq->name_len, tseq->name);
959 ✗ return AVERROR(EINVAL);
960 }
961 ✗ if (t0 + (uint64_t)tseq->ts.t != av_sat_add64(t0, tseq->ts.t))
962 ✗ return AVERROR(EINVAL);
963
964 ✗ t0 += tseq->ts.t;
965 ✗ for (i = 0; i < s->nb_def; i++) {
966 ✗ if (s->def[i].name_len == tseq->name_len &&
967 ✗ !memcmp(s->def[i].name, tseq->name, tseq->name_len))
968 ✗ break;
969 }
970 ✗ if (i >= s->nb_def) {
971 ✗ av_log(log, AV_LOG_ERROR, "Tone-set \"%.*s\" not defined\n",
972 tseq->name_len, tseq->name);
973 ✗ return AVERROR(EINVAL);
974 }
975 ✗ def = &s->def[i];
976 ✗ if (def->type == 'B') {
977 ✗ be = s->block_tseq + def->elements;
978 ✗ for (i = 0; i < def->nb_elements; i++) {
979 ✗ r = expand_tseq(log, s, nb_ev_max, max_events, t0, &be[i]);
980 ✗ if (r < 0)
981 ✗ return r;
982 }
983 } else {
984 ✗ if (s->nb_events >= max_events) {
985 ✗ av_log(log, AV_LOG_ERROR, "Too many events\n");
986 ✗ return AVERROR_INVALIDDATA;
987 }
988 ✗ ev = alloc_array_elem((void **)&s->events, sizeof(*ev),
989 &s->nb_events, nb_ev_max);
990 ✗ if (!ev)
991 ✗ return AVERROR(ENOMEM);
992 ✗ ev->ts = t0;
993 ✗ ev->elements = def->elements;
994 ✗ ev->nb_elements = def->nb_elements;
995 ✗ ev->fade = tseq->fade;
996 }
997 ✗ tseq->lock--;
998 ✗ return 0;
999 }
1000
1001 ✗ static int expand_script(void *log, struct sbg_script *s, int64_t max_events)
1002 {
1003 ✗ int i, r, nb_events_max = 0;
1004
1005 ✗ r = expand_timestamps(log, s);
1006 ✗ if (r < 0)
1007 ✗ return r;
1008 ✗ for (i = 0; i < s->nb_tseq; i++) {
1009 ✗ r = expand_tseq(log, s, &nb_events_max, max_events, 0, &s->tseq[i]);
1010 ✗ if (r < 0)
1011 ✗ return r;
1012 }
1013 ✗ if (!s->nb_events) {
1014 ✗ av_log(log, AV_LOG_ERROR, "No events in script\n");
1015 ✗ return AVERROR_INVALIDDATA;
1016 }
1017 ✗ if (s->opt_end_at_last)
1018 ✗ s->end_ts = s->events[s->nb_events - 1].ts;
1019 ✗ return 0;
1020 }
1021
1022 ✗ static int add_interval(struct ws_intervals *inter,
1023 enum ws_interval_type type, uint32_t channels, int ref,
1024 int64_t ts1, int32_t f1, int32_t a1,
1025 int64_t ts2, int32_t f2, int32_t a2)
1026 {
1027 struct ws_interval *i, *ri;
1028
1029 ✗ if (ref >= 0) {
1030 ✗ ri = &inter->inter[ref];
1031 /* ref and new intervals are constant, identical and adjacent */
1032 ✗ if (ri->type == type && ri->channels == channels &&
1033 ✗ ri->f1 == ri->f2 && ri->f2 == f1 && f1 == f2 &&
1034 ✗ ri->a1 == ri->a2 && ri->a2 == a1 && a1 == a2 &&
1035 ✗ ri->ts2 == ts1) {
1036 ✗ ri->ts2 = ts2;
1037 ✗ return ref;
1038 }
1039 }
1040 ✗ i = alloc_array_elem((void **)&inter->inter, sizeof(*i),
1041 &inter->nb_inter, &inter->max_inter);
1042 ✗ if (!i)
1043 ✗ return AVERROR(ENOMEM);
1044 ✗ i->ts1 = ts1;
1045 ✗ i->ts2 = ts2;
1046 ✗ i->type = type;
1047 ✗ i->channels = channels;
1048 ✗ i->f1 = f1;
1049 ✗ i->f2 = f2;
1050 ✗ i->a1 = a1;
1051 ✗ i->a2 = a2;
1052 ✗ i->phi = ref >= 0 ? ref | 0x80000000 : 0;
1053 ✗ return i - inter->inter;
1054 }
1055
1056 ✗ static int add_bell(struct ws_intervals *inter, struct sbg_script *s,
1057 int64_t ts1, int64_t ts2, int32_t f, int32_t a)
1058 {
1059 /* SBaGen uses an exponential decrease every 50ms.
1060 We approximate it with piecewise affine segments. */
1061 ✗ int32_t cpoints[][2] = {
1062 { 2, a },
1063 ✗ { 4, a - a / 4 },
1064 ✗ { 8, a / 2 },
1065 ✗ { 16, a / 4 },
1066 ✗ { 25, a / 10 },
1067 ✗ { 50, a / 80 },
1068 { 75, 0 },
1069 };
1070 int i, r;
1071 ✗ int64_t dt = s->sample_rate / 20, ts3 = ts1, ts4;
1072 ✗ for (i = 0; i < FF_ARRAY_ELEMS(cpoints); i++) {
1073 ✗ ts4 = FFMIN(ts2, ts1 + cpoints[i][0] * dt);
1074 ✗ r = add_interval(inter, WS_SINE, 3, -1,
1075 ts3, f, a, ts4, f, cpoints[i][1]);
1076 ✗ if (r < 0)
1077 ✗ return r;
1078 ✗ ts3 = ts4;
1079 ✗ a = cpoints[i][1];
1080 }
1081 ✗ return 0;
1082 }
1083
1084 ✗ static int generate_interval(void *log, struct sbg_script *s,
1085 struct ws_intervals *inter,
1086 int64_t ts1, int64_t ts2,
1087 struct sbg_script_synth *s1,
1088 struct sbg_script_synth *s2,
1089 int transition)
1090 {
1091 int r;
1092
1093 ✗ if (ts2 <= ts1 || (s1->vol == 0 && s2->vol == 0))
1094 ✗ return 0;
1095 ✗ switch (s1->type) {
1096 ✗ case SBG_TYPE_NONE:
1097 ✗ break;
1098 ✗ case SBG_TYPE_SINE:
1099 ✗ if (s1->beat == 0 && s2->beat == 0) {
1100 ✗ r = add_interval(inter, WS_SINE, 3, s1->ref.l,
1101 ts1, s1->carrier, s1->vol,
1102 ts2, s2->carrier, s2->vol);
1103 ✗ if (r < 0)
1104 ✗ return r;
1105 ✗ s2->ref.l = s2->ref.r = r;
1106 } else {
1107 ✗ r = add_interval(inter, WS_SINE, 1, s1->ref.l,
1108 ✗ ts1, s1->carrier + s1->beat / 2, s1->vol,
1109 ✗ ts2, s2->carrier + s2->beat / 2, s2->vol);
1110 ✗ if (r < 0)
1111 ✗ return r;
1112 ✗ s2->ref.l = r;
1113 ✗ r = add_interval(inter, WS_SINE, 2, s1->ref.r,
1114 ✗ ts1, s1->carrier - s1->beat / 2, s1->vol,
1115 ✗ ts2, s2->carrier - s2->beat / 2, s2->vol);
1116 ✗ if (r < 0)
1117 ✗ return r;
1118 ✗ s2->ref.r = r;
1119 }
1120 ✗ break;
1121
1122 ✗ case SBG_TYPE_BELL:
1123 ✗ if (transition == 2) {
1124 ✗ r = add_bell(inter, s, ts1, ts2, s1->carrier, s2->vol);
1125 ✗ if (r < 0)
1126 ✗ return r;
1127 }
1128 ✗ break;
1129
1130 ✗ case SBG_TYPE_SPIN:
1131 ✗ av_log(log, AV_LOG_WARNING, "Spinning noise not implemented, "
1132 "using pink noise instead.\n");
1133 av_fallthrough;
1134 ✗ case SBG_TYPE_NOISE:
1135 /* SBaGen's pink noise generator uses:
1136 - 1 band of white noise, mean square: 1/3;
1137 - 9 bands of subsampled white noise with linear
1138 interpolation, mean square: 2/3 each;
1139 with 1/10 weight each: the total mean square is 7/300.
1140 Our pink noise generator uses 8 bands of white noise with
1141 rectangular subsampling: the total mean square is 1/24.
1142 Therefore, to match SBaGen's volume, we must multiply vol by
1143 sqrt((7/300) / (1/24)) = sqrt(14/25) =~ 0.748
1144 */
1145 ✗ r = add_interval(inter, WS_NOISE, 3, s1->ref.l,
1146 ✗ ts1, 0, s1->vol - s1->vol / 4,
1147 ✗ ts2, 0, s2->vol - s2->vol / 4);
1148 ✗ if (r < 0)
1149 ✗ return r;
1150 ✗ s2->ref.l = s2->ref.r = r;
1151 ✗ break;
1152
1153 ✗ case SBG_TYPE_MIX:
1154 /* Unimplemented: silence; warning present elsewhere */
1155 default:
1156 ✗ av_log(log, AV_LOG_ERROR,
1157 ✗ "Type %d is not implemented\n", s1->type);
1158 ✗ return AVERROR_PATCHWELCOME;
1159 }
1160 ✗ return 0;
1161 }
1162
1163 ✗ static int generate_plateau(void *log, struct sbg_script *s,
1164 struct ws_intervals *inter,
1165 struct sbg_script_event *ev1)
1166 {
1167 ✗ int64_t ts1 = ev1->ts_int, ts2 = ev1->ts_trans;
1168 int i, r;
1169 struct sbg_script_synth *s1;
1170
1171 ✗ for (i = 0; i < ev1->nb_elements; i++) {
1172 ✗ s1 = &s->synth[ev1->elements + i];
1173 ✗ r = generate_interval(log, s, inter, ts1, ts2, s1, s1, 0);
1174 ✗ if (r < 0)
1175 ✗ return r;
1176 }
1177 ✗ return 0;
1178 }
1179
1180 /*
1181
1182 ts1 ts2 ts1 tsmid ts2
1183 | | | | |
1184 v v v | v
1185 ____ ____ v ____
1186 ''''.... ''.. ..''
1187 ''''....____ ''....''
1188
1189 compatible transition incompatible transition
1190 */
1191
1192 ✗ static int generate_transition(void *log, struct sbg_script *s,
1193 struct ws_intervals *inter,
1194 struct sbg_script_event *ev1,
1195 struct sbg_script_event *ev2)
1196 {
1197 ✗ int64_t ts1 = ev1->ts_trans, ts2 = ev1->ts_next;
1198 /* (ts1 + ts2) / 2 without overflow */
1199 ✗ int64_t tsmid = (ts1 >> 1) + (ts2 >> 1) + (ts1 & ts2 & 1);
1200 ✗ enum sbg_fade_type type = ev1->fade.slide | (ev1->fade.out & ev2->fade.in);
1201 ✗ int nb_elements = FFMAX(ev1->nb_elements, ev2->nb_elements);
1202 struct sbg_script_synth *s1, *s2, s1mod, s2mod, smid;
1203 int pass, i, r;
1204
1205 ✗ for (pass = 0; pass < 2; pass++) {
1206 /* pass = 0 -> compatible and first half of incompatible
1207 pass = 1 -> second half of incompatible
1208 Using two passes like that ensures that the intervals are generated
1209 in increasing order according to their start timestamp.
1210 Otherwise it would be necessary to sort them
1211 while keeping the mutual references.
1212 */
1213 ✗ for (i = 0; i < nb_elements; i++) {
1214 ✗ s1 = i < ev1->nb_elements ? &s->synth[ev1->elements + i] : &s1mod;
1215 ✗ s2 = i < ev2->nb_elements ? &s->synth[ev2->elements + i] : &s2mod;
1216 ✗ s1mod = s1 != &s1mod ? *s1 : (struct sbg_script_synth){ 0 };
1217 ✗ s2mod = s2 != &s2mod ? *s2 : (struct sbg_script_synth){ 0 };
1218 ✗ if (ev1->fade.slide) {
1219 /* for slides, and only for slides, silence ("-") is equivalent
1220 to anything with volume 0 */
1221 ✗ if (s1mod.type == SBG_TYPE_NONE) {
1222 ✗ s1mod = s2mod;
1223 ✗ s1mod.vol = 0;
1224 ✗ } else if (s2mod.type == SBG_TYPE_NONE) {
1225 ✗ s2mod = s1mod;
1226 ✗ s2mod.vol = 0;
1227 }
1228 }
1229 ✗ if (s1mod.type == s2mod.type &&
1230 ✗ s1mod.type != SBG_TYPE_BELL &&
1231 ✗ (type == SBG_FADE_ADAPT ||
1232 ✗ (s1mod.carrier == s2mod.carrier &&
1233 ✗ s1mod.beat == s2mod.beat))) {
1234 /* compatible: single transition */
1235 ✗ if (!pass) {
1236 ✗ r = generate_interval(log, s, inter,
1237 ts1, ts2, &s1mod, &s2mod, 3);
1238 ✗ if (r < 0)
1239 ✗ return r;
1240 ✗ s2->ref = s2mod.ref;
1241 }
1242 } else {
1243 /* incompatible: silence at midpoint */
1244 ✗ if (!pass) {
1245 ✗ smid = s1mod;
1246 ✗ smid.vol = 0;
1247 ✗ r = generate_interval(log, s, inter,
1248 ts1, tsmid, &s1mod, &smid, 1);
1249 ✗ if (r < 0)
1250 ✗ return r;
1251 } else {
1252 ✗ smid = s2mod;
1253 ✗ smid.vol = 0;
1254 ✗ r = generate_interval(log, s, inter,
1255 tsmid, ts2, &smid, &s2mod, 2);
1256 ✗ if (r < 0)
1257 ✗ return r;
1258 ✗ s2->ref = s2mod.ref;
1259 }
1260 }
1261 }
1262 }
1263 ✗ return 0;
1264 }
1265
1266 /*
1267 ev1 trats ev2 intts endts ev3
1268 | | | | | |
1269 v v v v v v
1270 ________________
1271 .... .... ....
1272 '''....________________....''' '''...._______________
1273
1274 \_________/\______________/\_________/\______________/\_________/\_____________/
1275 tr x->1 int1 tr 1->2 int2 tr 2->3 int3
1276 */
1277
1278 ✗ static int generate_intervals(void *log, struct sbg_script *s, int sample_rate,
1279 struct ws_intervals *inter)
1280 {
1281 ✗ int64_t trans_time = s->opt_fade_time / 2;
1282 struct sbg_script_event ev0, *ev1, *ev2;
1283 int64_t period;
1284 int i, r;
1285
1286 /* SBaGen handles the time before and after the extremal events,
1287 and the corresponding transitions, as if the sequence were cyclic
1288 with a 24-hours period. */
1289 ✗ period = s->events[s->nb_events - 1].ts - (uint64_t)s->events[0].ts;
1290 ✗ if (period < 0)
1291 ✗ return AVERROR_INVALIDDATA;
1292
1293 ✗ period = (period + (DAY_TS - 1)) / DAY_TS * DAY_TS;
1294 ✗ period = FFMAX(period, DAY_TS);
1295
1296 /* Prepare timestamps for transitions */
1297 ✗ for (i = 0; i < s->nb_events; i++) {
1298 ✗ ev1 = &s->events[i];
1299 ✗ ev2 = &s->events[(i + 1) % s->nb_events];
1300 ✗ ev1->ts_int = ev1->ts;
1301
1302 ✗ if (!ev1->fade.slide && ev1 >= ev2 && ev2->ts > INT64_MAX - period)
1303 ✗ return AVERROR_INVALIDDATA;
1304
1305 ✗ ev1->ts_trans = ev1->fade.slide ? ev1->ts
1306 ✗ : ev2->ts + (ev1 < ev2 ? 0 : period);
1307 }
1308 ✗ for (i = 0; i < s->nb_events; i++) {
1309 ✗ ev1 = &s->events[i];
1310 ✗ ev2 = &s->events[(i + 1) % s->nb_events];
1311 ✗ if (!ev1->fade.slide) {
1312 ✗ ev1->ts_trans = FFMAX(ev1->ts_int, ev1->ts_trans - trans_time);
1313 ✗ ev2->ts_int = FFMIN(ev2->ts_trans, ev2->ts_int + trans_time);
1314 }
1315 ✗ ev1->ts_next = ev2->ts_int + (ev1 < ev2 ? 0 : period);
1316 }
1317
1318 /* Pseudo event before the first one */
1319 ✗ ev0 = s->events[s->nb_events - 1];
1320 ✗ if (av_sat_sub64(ev0.ts_int, period) != (uint64_t)ev0.ts_int - period)
1321 ✗ return AVERROR_INVALIDDATA;
1322 ✗ ev0.ts_int -= period;
1323 ✗ ev0.ts_trans -= period;
1324 ✗ ev0.ts_next -= period;
1325
1326 /* Convert timestamps */
1327 ✗ for (i = -1; i < s->nb_events; i++) {
1328 ✗ ev1 = i < 0 ? &ev0 : &s->events[i];
1329 ✗ ev1->ts_int = av_rescale(ev1->ts_int, sample_rate, AV_TIME_BASE);
1330 ✗ ev1->ts_trans = av_rescale(ev1->ts_trans, sample_rate, AV_TIME_BASE);
1331 ✗ ev1->ts_next = av_rescale(ev1->ts_next, sample_rate, AV_TIME_BASE);
1332 }
1333
1334 /* Generate intervals */
1335 ✗ for (i = 0; i < s->nb_synth; i++)
1336 ✗ s->synth[i].ref.l = s->synth[i].ref.r = -1;
1337 ✗ for (i = -1; i < s->nb_events; i++) {
1338 ✗ ev1 = i < 0 ? &ev0 : &s->events[i];
1339 ✗ ev2 = &s->events[(i + 1) % s->nb_events];
1340 ✗ r = generate_plateau(log, s, inter, ev1);
1341 ✗ if (r < 0)
1342 ✗ return r;
1343 ✗ r = generate_transition(log, s, inter, ev1, ev2);
1344 ✗ if (r < 0)
1345 ✗ return r;
1346 }
1347 ✗ if (!inter->nb_inter)
1348 ✗ av_log(log, AV_LOG_WARNING, "Completely silent script.\n");
1349 ✗ return 0;
1350 }
1351
1352 ✗ static int encode_intervals(struct sbg_script *s, AVCodecParameters *par,
1353 struct ws_intervals *inter)
1354 {
1355 int i, ret;
1356 ✗ int64_t edata_size = 4;
1357 uint8_t *edata;
1358
1359 ✗ for (i = 0; i < inter->nb_inter; i++)
1360 ✗ edata_size += inter->inter[i].type == WS_SINE ? 44 :
1361 ✗ inter->inter[i].type == WS_NOISE ? 32 : 0;
1362 ✗ if (edata_size > INT_MAX)
1363 ✗ return AVERROR(ENOMEM);
1364 ✗ if ((ret = ff_alloc_extradata(par, edata_size)) < 0)
1365 ✗ return ret;
1366 ✗ edata = par->extradata;
1367
1368 #define ADD_EDATA32(v) do { AV_WL32(edata, (v)); edata += 4; } while(0)
1369 #define ADD_EDATA64(v) do { AV_WL64(edata, (v)); edata += 8; } while(0)
1370 ✗ ADD_EDATA32(inter->nb_inter);
1371 ✗ for (i = 0; i < inter->nb_inter; i++) {
1372 ✗ ADD_EDATA64(inter->inter[i].ts1);
1373 ✗ ADD_EDATA64(inter->inter[i].ts2);
1374 ✗ ADD_EDATA32(inter->inter[i].type);
1375 ✗ ADD_EDATA32(inter->inter[i].channels);
1376 ✗ switch (inter->inter[i].type) {
1377 ✗ case WS_SINE:
1378 ✗ ADD_EDATA32(inter->inter[i].f1);
1379 ✗ ADD_EDATA32(inter->inter[i].f2);
1380 ✗ ADD_EDATA32(inter->inter[i].a1);
1381 ✗ ADD_EDATA32(inter->inter[i].a2);
1382 ✗ ADD_EDATA32(inter->inter[i].phi);
1383 ✗ break;
1384 ✗ case WS_NOISE:
1385 ✗ ADD_EDATA32(inter->inter[i].a1);
1386 ✗ ADD_EDATA32(inter->inter[i].a2);
1387 ✗ break;
1388 }
1389 }
1390 ✗ if (edata != par->extradata + edata_size)
1391 ✗ return AVERROR_BUG;
1392 ✗ return 0;
1393 }
1394
1395 8163 static av_cold int sbg_read_probe(const AVProbeData *p)
1396 {
1397 int r, score;
1398 8163 struct sbg_script script = { 0 };
1399
1400 8163 r = parse_script(NULL, p->buf, p->buf_size, &script);
1401
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 8163 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8163 score = r < 0 || !script.nb_def || !script.nb_tseq ? 0 :
1402 AVPROBE_SCORE_MAX / 3;
1403 8163 free_script(&script);
1404 8163 return score;
1405 }
1406
1407 ✗ static av_cold int sbg_read_header(AVFormatContext *avf)
1408 {
1409 ✗ struct sbg_demuxer *sbg = avf->priv_data;
1410 AVBPrint bprint;
1411 int r;
1412 ✗ struct sbg_script script = { 0 };
1413 AVStream *st;
1414 FFStream *sti;
1415 ✗ struct ws_intervals inter = { 0 };
1416
1417 ✗ av_bprint_init(&bprint, 0, sbg->max_file_size + 1U);
1418 ✗ r = read_whole_file(avf->pb, sbg->max_file_size, &bprint);
1419 ✗ if (r < 0)
1420 ✗ goto fail2;
1421
1422 ✗ r = parse_script(avf, bprint.str, bprint.len, &script);
1423 ✗ if (r < 0)
1424 ✗ goto fail2;
1425 ✗ if (!sbg->sample_rate)
1426 ✗ sbg->sample_rate = script.sample_rate;
1427 else
1428 ✗ script.sample_rate = sbg->sample_rate;
1429 ✗ if (!sbg->frame_size)
1430 ✗ sbg->frame_size = FFMAX(1, sbg->sample_rate / 10);
1431 ✗ if (script.opt_mix)
1432 ✗ av_log(avf, AV_LOG_WARNING, "Mix feature not implemented: "
1433 "-m is ignored and mix channels will be silent.\n");
1434 ✗ r = expand_script(avf, &script, 4 * (int64_t)bprint.len + 16384);
1435 ✗ if (r < 0)
1436 ✗ goto fail2;
1437 ✗ av_bprint_finalize(&bprint, NULL);
1438 ✗ r = generate_intervals(avf, &script, sbg->sample_rate, &inter);
1439 ✗ if (r < 0)
1440 ✗ goto fail;
1441
1442 ✗ if (script.end_ts != AV_NOPTS_VALUE && script.end_ts < script.start_ts) {
1443 ✗ r = AVERROR_INVALIDDATA;
1444 ✗ goto fail;
1445 }
1446
1447 ✗ st = avformat_new_stream(avf, NULL);
1448 ✗ if (!st) {
1449 ✗ r = AVERROR(ENOMEM);
1450 ✗ goto fail;
1451 }
1452 ✗ sti = ffstream(st);
1453 ✗ st->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
1454 ✗ st->codecpar->codec_id = AV_CODEC_ID_FFWAVESYNTH;
1455 ✗ st->codecpar->ch_layout = (AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO;
1456 ✗ st->codecpar->sample_rate = sbg->sample_rate;
1457 ✗ st->codecpar->frame_size = sbg->frame_size;
1458 ✗ avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);
1459 ✗ sti->probe_packets = 0;
1460 ✗ st->start_time = av_rescale(script.start_ts,
1461 ✗ sbg->sample_rate, AV_TIME_BASE);
1462 ✗ st->duration = script.end_ts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
1463 ✗ av_rescale(script.end_ts - script.start_ts,
1464 ✗ sbg->sample_rate, AV_TIME_BASE);
1465
1466 ✗ if (st->duration != AV_NOPTS_VALUE && (
1467 ✗ st->duration < 0 || st->start_time > INT64_MAX - st->duration)) {
1468 ✗ r = AVERROR_INVALIDDATA;
1469 ✗ goto fail;
1470 }
1471
1472 ✗ sti->cur_dts = st->start_time;
1473 ✗ r = encode_intervals(&script, st->codecpar, &inter);
1474 ✗ if (r < 0)
1475 ✗ goto fail;
1476
1477 ✗ av_free(inter.inter);
1478 ✗ free_script(&script);
1479 ✗ return 0;
1480
1481 ✗ fail2:
1482 ✗ av_bprint_finalize(&bprint, NULL);
1483 ✗ fail:
1484 ✗ av_free(inter.inter);
1485 ✗ free_script(&script);
1486 ✗ return r;
1487 }
1488
1489 ✗ static int sbg_read_packet(AVFormatContext *avf, AVPacket *packet)
1490 {
1491 int64_t ts, end_ts;
1492 int ret;
1493
1494 ✗ ts = ffstream(avf->streams[0])->cur_dts;
1495 ✗ end_ts = av_sat_add64(ts, avf->streams[0]->codecpar->frame_size);
1496 ✗ if (avf->streams[0]->duration != AV_NOPTS_VALUE)
1497 ✗ end_ts = FFMIN(avf->streams[0]->start_time + avf->streams[0]->duration,
1498 end_ts);
1499 ✗ if (end_ts <= ts)
1500 ✗ return AVERROR_EOF;
1501 ✗ if ((ret = av_new_packet(packet, 12)) < 0)
1502 ✗ return ret;
1503 ✗ packet->dts = packet->pts = ts;
1504 ✗ packet->duration = end_ts - ts;
1505 ✗ AV_WL64(packet->data + 0, ts);
1506 ✗ AV_WL32(packet->data + 8, packet->duration);
1507 ✗ return packet->size;
1508 }
1509
1510 ✗ static int sbg_read_seek2(AVFormatContext *avf, int stream_index,
1511 int64_t min_ts, int64_t ts, int64_t max_ts, int flags)
1512 {
1513 ✗ if (flags || stream_index > 0)
1514 ✗ return AVERROR(EINVAL);
1515 ✗ if (stream_index < 0)
1516 ✗ ts = av_rescale_q(ts, AV_TIME_BASE_Q, avf->streams[0]->time_base);
1517 ✗ ffstream(avf->streams[0])->cur_dts = ts;
1518 ✗ return 0;
1519 }
1520
1521 ✗ static int sbg_read_seek(AVFormatContext *avf, int stream_index,
1522 int64_t ts, int flags)
1523 {
1524 ✗ return sbg_read_seek2(avf, stream_index, ts, ts, ts, 0);
1525 }
1526
1527 static const AVOption sbg_options[] = {
1528 { "sample_rate", "", offsetof(struct sbg_demuxer, sample_rate),
1529 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
1530 AV_OPT_FLAG_DECODING_PARAM },
1531 { "frame_size", "", offsetof(struct sbg_demuxer, frame_size),
1532 AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX,
1533 AV_OPT_FLAG_DECODING_PARAM },
1534 { "max_file_size", "", offsetof(struct sbg_demuxer, max_file_size),
1535 AV_OPT_TYPE_INT, { .i64 = 5000000 }, 0, INT_MAX,
1536 AV_OPT_FLAG_DECODING_PARAM },
1537 { NULL },
1538 };
1539
1540 static const AVClass sbg_demuxer_class = {
1541 .class_name = "sbg_demuxer",
1542 .item_name = av_default_item_name,
1543 .option = sbg_options,
1544 .version = LIBAVUTIL_VERSION_INT,
1545 };
1546
1547 const FFInputFormat ff_sbg_demuxer = {
1548 .p.name = "sbg",
1549 .p.long_name = NULL_IF_CONFIG_SMALL("SBaGen binaural beats script"),
1550 .p.extensions = "sbg",
1551 .p.priv_class = &sbg_demuxer_class,
1552 .priv_data_size = sizeof(struct sbg_demuxer),
1553 .read_probe = sbg_read_probe,
1554 .read_header = sbg_read_header,
1555 .read_packet = sbg_read_packet,
1556 .read_seek = sbg_read_seek,
1557 .read_seek2 = sbg_read_seek2,
1558 };
1559