FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/sbgdec.c
Date: 2026-09-28 17:50:41
Exec Total Coverage
Lines: 246 865 28.4%
Functions: 27 48 56.2%
Branches: 147 640 23.0%

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