FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/oggdec.c
Date: 2025-06-01 09:29:47
Exec Total Coverage
Lines: 461 555 83.1%
Functions: 20 20 100.0%
Branches: 232 331 70.1%

Line Branch Exec Source
1 /*
2 * Ogg bitstream support
3 * Luca Barbato <lu_zero@gentoo.org>
4 * Based on tcvp implementation
5 */
6
7 /*
8 Copyright (C) 2005 Michael Ahlberg, Måns Rullgård
9
10 Permission is hereby granted, free of charge, to any person
11 obtaining a copy of this software and associated documentation
12 files (the "Software"), to deal in the Software without
13 restriction, including without limitation the rights to use, copy,
14 modify, merge, publish, distribute, sublicense, and/or sell copies
15 of the Software, and to permit persons to whom the Software is
16 furnished to do so, subject to the following conditions:
17
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 */
30
31 #include <stdio.h>
32 #include "libavutil/avassert.h"
33 #include "libavutil/intreadwrite.h"
34 #include "libavutil/mem.h"
35 #include "avio_internal.h"
36 #include "demux.h"
37 #include "oggdec.h"
38 #include "avformat.h"
39 #include "internal.h"
40
41 #define MAX_PAGE_SIZE 65307
42 #define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
43
44 static const struct ogg_codec * const ogg_codecs[] = {
45 &ff_skeleton_codec,
46 &ff_dirac_codec,
47 &ff_speex_codec,
48 &ff_vorbis_codec,
49 &ff_theora_codec,
50 &ff_flac_codec,
51 &ff_celt_codec,
52 &ff_opus_codec,
53 &ff_vp8_codec,
54 &ff_old_dirac_codec,
55 &ff_old_flac_codec,
56 &ff_ogm_video_codec,
57 &ff_ogm_audio_codec,
58 &ff_ogm_text_codec,
59 &ff_ogm_old_codec,
60 NULL
61 };
62
63 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
64 static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
65 static int ogg_restore(AVFormatContext *s);
66
67 52 static void free_stream(AVFormatContext *s, int i)
68 {
69 52 struct ogg *ogg = s->priv_data;
70 52 struct ogg_stream *stream = &ogg->streams[i];
71
72 52 av_freep(&stream->buf);
73
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 if (stream->codec &&
74
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 24 times.
52 stream->codec->cleanup) {
75 28 stream->codec->cleanup(s, i);
76 }
77
78 52 av_freep(&stream->private);
79 52 av_freep(&stream->new_metadata);
80 52 av_freep(&stream->new_extradata);
81 52 }
82
83 //FIXME We could avoid some structure duplication
84 82 static int ogg_save(AVFormatContext *s)
85 {
86 82 struct ogg *ogg = s->priv_data;
87 struct ogg_state *ost =
88 82 av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
89 int i;
90 82 int ret = 0;
91
92
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (!ost)
93 return AVERROR(ENOMEM);
94
95 82 ost->pos = avio_tell(s->pb);
96 82 ost->curidx = ogg->curidx;
97 82 ost->next = ogg->state;
98 82 ost->nstreams = ogg->nstreams;
99 82 memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
100
101
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 82 times.
166 for (i = 0; i < ogg->nstreams; i++) {
102 84 struct ogg_stream *os = ogg->streams + i;
103 84 os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
104
1/2
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
84 if (os->buf)
105 84 memcpy(os->buf, ost->streams[i].buf, os->bufpos);
106 else
107 ret = AVERROR(ENOMEM);
108 84 os->new_metadata = NULL;
109 84 os->new_metadata_size = 0;
110 }
111
112 82 ogg->state = ost;
113
114
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (ret < 0)
115 ogg_restore(s);
116
117 82 return ret;
118 }
119
120 82 static int ogg_restore(AVFormatContext *s)
121 {
122 82 struct ogg *ogg = s->priv_data;
123 82 AVIOContext *bc = s->pb;
124 82 struct ogg_state *ost = ogg->state;
125 int i, err;
126
127
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
82 if (!ost)
128 return 0;
129
130 82 ogg->state = ost->next;
131
132
2/2
✓ Branch 0 taken 84 times.
✓ Branch 1 taken 82 times.
166 for (i = 0; i < ogg->nstreams; i++) {
133 84 struct ogg_stream *stream = &ogg->streams[i];
134 84 av_freep(&stream->buf);
135 84 av_freep(&stream->new_metadata);
136
137
3/4
✓ Branch 0 taken 84 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✓ Branch 3 taken 74 times.
84 if (i >= ost->nstreams || !ost->streams[i].private) {
138 10 free_stream(s, i);
139 }
140 }
141
142 82 avio_seek(bc, ost->pos, SEEK_SET);
143 82 ogg->page_pos = -1;
144 82 ogg->curidx = ost->curidx;
145 82 ogg->nstreams = ost->nstreams;
146
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
147 sizeof(*ogg->streams))) < 0) {
148 ogg->nstreams = 0;
149 return err;
150 } else
151 82 memcpy(ogg->streams, ost->streams,
152 82 ost->nstreams * sizeof(*ogg->streams));
153
154 82 av_free(ost);
155
156 82 return 0;
157 }
158
159 329 static int ogg_reset(AVFormatContext *s)
160 {
161 329 struct ogg *ogg = s->priv_data;
162 int i;
163 329 int64_t start_pos = avio_tell(s->pb);
164
165
2/2
✓ Branch 0 taken 330 times.
✓ Branch 1 taken 329 times.
659 for (i = 0; i < ogg->nstreams; i++) {
166 330 struct ogg_stream *os = ogg->streams + i;
167 330 os->bufpos = 0;
168 330 os->pstart = 0;
169 330 os->psize = 0;
170 330 os->granule = -1;
171 330 os->lastpts = AV_NOPTS_VALUE;
172 330 os->lastdts = AV_NOPTS_VALUE;
173 330 os->sync_pos = -1;
174 330 os->page_pos = 0;
175 330 os->nsegs = 0;
176 330 os->segp = 0;
177 330 os->incomplete = 0;
178 330 os->got_data = 0;
179
2/2
✓ Branch 1 taken 94 times.
✓ Branch 2 taken 236 times.
330 if (start_pos <= ffformatcontext(s)->data_offset) {
180 94 os->lastpts = 0;
181 }
182 330 os->start_trimming = 0;
183 330 os->end_trimming = 0;
184 330 av_freep(&os->new_metadata);
185 330 os->new_metadata_size = 0;
186 }
187
188 329 ogg->page_pos = -1;
189 329 ogg->curidx = -1;
190
191 329 return 0;
192 }
193
194 48 static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
195 {
196 int i;
197
198
1/2
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
244 for (i = 0; ogg_codecs[i]; i++)
199
1/2
✓ Branch 0 taken 244 times.
✗ Branch 1 not taken.
244 if (size >= ogg_codecs[i]->magicsize &&
200
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 196 times.
244 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
201 48 return ogg_codecs[i];
202
203 return NULL;
204 }
205
206 /**
207 * Replace the current stream with a new one. This is a typical webradio
208 * situation where a new audio stream spawn (identified with a new serial) and
209 * must replace the previous one (track switch).
210 */
211 6 static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic, int page_size,
212 int probing)
213 {
214 6 struct ogg *ogg = s->priv_data;
215 struct ogg_stream *os;
216 const struct ogg_codec *codec;
217 6 int i = 0;
218
219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (ogg->nstreams != 1) {
220 avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
221 return AVERROR_PATCHWELCOME;
222 }
223
224 /* Check for codecs */
225 6 codec = ogg_find_codec(magic, page_size);
226
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
6 if (!codec && !probing) {
227 av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
228 return AVERROR_INVALIDDATA;
229 }
230
231 6 os = &ogg->streams[0];
232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 if (os->codec != codec)
233 return AVERROR(EINVAL);
234
235 6 os->serial = serial;
236 6 os->codec = codec;
237 6 os->serial = serial;
238 6 os->lastpts = 0;
239 6 os->lastdts = 0;
240 6 os->start_trimming = 0;
241 6 os->end_trimming = 0;
242
243 6 return i;
244 }
245
246 42 static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
247 {
248 42 struct ogg *ogg = s->priv_data;
249 42 int idx = ogg->nstreams;
250 AVStream *st;
251 struct ogg_stream *os;
252
253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ogg->state) {
254 av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
255 "in between Ogg context save/restore operations.\n");
256 return AVERROR_BUG;
257 }
258
259 /* Allocate and init a new Ogg Stream */
260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
42 if (!(os = av_realloc_array(ogg->streams, ogg->nstreams + 1,
261 sizeof(*ogg->streams))))
262 return AVERROR(ENOMEM);
263 42 ogg->streams = os;
264 42 os = ogg->streams + idx;
265 42 memset(os, 0, sizeof(*os));
266 42 os->serial = serial;
267 42 os->bufsize = DECODER_BUFFER_SIZE;
268 42 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
269 42 os->header = -1;
270 42 os->start_granule = OGG_NOGRANULE_VALUE;
271
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!os->buf)
272 return AVERROR(ENOMEM);
273
274 /* Create the associated AVStream */
275 42 st = avformat_new_stream(s, NULL);
276
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!st) {
277 av_freep(&os->buf);
278 return AVERROR(ENOMEM);
279 }
280 42 st->id = idx;
281 42 avpriv_set_pts_info(st, 64, 1, 1000000);
282
283 42 ogg->nstreams++;
284 42 return idx;
285 }
286
287 48 static int data_packets_seen(const struct ogg *ogg)
288 {
289 int i;
290
291
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 42 times.
49 for (i = 0; i < ogg->nstreams; i++)
292
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
7 if (ogg->streams[i].got_data)
293 6 return 1;
294 42 return 0;
295 }
296
297 1551 static int buf_realloc(struct ogg_stream *os, int size)
298 {
299 /* Even if invalid guarantee there's enough memory to read the page */
300
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1513 times.
1551 if (os->bufsize - os->bufpos < size) {
301 38 uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
302
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (!nb)
303 return AVERROR(ENOMEM);
304 38 os->buf = nb;
305 38 os->bufsize *= 2;
306 }
307
308 1551 return 0;
309 }
310
311 1663 static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
312 {
313 1663 AVIOContext *bc = s->pb;
314 1663 struct ogg *ogg = s->priv_data;
315 struct ogg_stream *os;
316 1663 int ret, i = 0;
317 int flags, nsegs;
318 uint64_t gp;
319 uint32_t serial;
320 uint32_t crc, crc_tmp;
321 1663 int size = 0, idx;
322 int64_t version, page_pos;
323 int64_t start_pos;
324 uint8_t sync[4];
325 uint8_t segments[255];
326 uint8_t *readout_buf;
327 1663 int sp = 0;
328
329 1663 ret = avio_read(bc, sync, 4);
330
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1625 times.
1663 if (ret < 4)
331
1/2
✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
38 return ret < 0 ? ret : AVERROR_EOF;
332
333 do {
334 int c;
335
336
2/2
✓ Branch 0 taken 4169 times.
✓ Branch 1 taken 665066 times.
669235 if (sync[sp & 3] == 'O' &&
337
2/2
✓ Branch 0 taken 1564 times.
✓ Branch 1 taken 2605 times.
4169 sync[(sp + 1) & 3] == 'g' &&
338
3/4
✓ Branch 0 taken 1551 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 1551 times.
✗ Branch 3 not taken.
1564 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
339 1551 break;
340
341
4/6
✓ Branch 0 taken 123 times.
✓ Branch 1 taken 667561 times.
✓ Branch 2 taken 123 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 123 times.
667684 if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
342 memset(sync, 0, 4);
343 avio_seek(bc, ogg->page_pos+4, SEEK_SET);
344 ogg->page_pos = -1;
345 }
346
347 667684 c = avio_r8(bc);
348
349
2/2
✓ Branch 1 taken 74 times.
✓ Branch 2 taken 667610 times.
667684 if (avio_feof(bc))
350 74 return AVERROR_EOF;
351
352 667610 sync[sp++ & 3] = c;
353
1/2
✓ Branch 0 taken 667610 times.
✗ Branch 1 not taken.
667610 } while (i++ < MAX_PAGE_SIZE);
354
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1551 times.
1551 if (i >= MAX_PAGE_SIZE) {
356 av_log(s, AV_LOG_INFO, "cannot find sync word\n");
357 return AVERROR_INVALIDDATA;
358 }
359
360 /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
361 1551 ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
362
363 /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
364 1551 ret = ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1551 times.
1551 if (ret < 0)
366 return ret;
367 1551 start_pos = avio_tell(bc);
368
369 1551 version = avio_r8(bc);
370 1551 flags = avio_r8(bc);
371 1551 gp = avio_rl64(bc);
372 1551 serial = avio_rl32(bc);
373 1551 avio_skip(bc, 4); /* seq */
374
375 1551 crc_tmp = ffio_get_checksum(bc);
376 1551 crc = avio_rb32(bc);
377 1551 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
378 1551 ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
379
380 1551 nsegs = avio_r8(bc);
381 1551 page_pos = avio_tell(bc) - 27;
382
383 1551 ret = avio_read(bc, segments, nsegs);
384
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1551 times.
1551 if (ret < nsegs)
385 return ret < 0 ? ret : AVERROR_EOF;
386
387
2/2
✓ Branch 0 taken 43895 times.
✓ Branch 1 taken 1551 times.
45446 for (i = 0; i < nsegs; i++)
388 43895 size += segments[i];
389
390 1551 idx = ogg_find_stream(ogg, serial);
391
2/2
✓ Branch 0 taken 1503 times.
✓ Branch 1 taken 48 times.
1551 if (idx >= 0) {
392 1503 os = ogg->streams + idx;
393
394 1503 ret = buf_realloc(os, size);
395
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1503 times.
1503 if (ret < 0)
396 return ret;
397
398 1503 readout_buf = os->buf + os->bufpos;
399 } else {
400 48 readout_buf = av_malloc(size);
401 }
402
403 1551 ret = avio_read(bc, readout_buf, size);
404
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 1507 times.
1551 if (ret < size) {
405
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 if (idx < 0)
406 av_free(readout_buf);
407
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 return ret < 0 ? ret : AVERROR_EOF;
408 }
409
410
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1507 times.
1507 if (crc ^ ffio_get_checksum(bc)) {
411 av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
412 if (idx < 0)
413 av_free(readout_buf);
414 avio_seek(bc, start_pos, SEEK_SET);
415 *sid = -1;
416 return 0;
417 }
418
419 /* Since we're almost sure its a valid packet, checking the version after
420 * the checksum lets the demuxer be more tolerant */
421
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1507 times.
1507 if (version) {
422 av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
423 if (idx < 0)
424 av_free(readout_buf);
425 avio_seek(bc, start_pos, SEEK_SET);
426 *sid = -1;
427 return 0;
428 }
429
430 /* CRC is correct so we can be 99% sure there's an actual change here */
431
2/2
✓ Branch 0 taken 48 times.
✓ Branch 1 taken 1459 times.
1507 if (idx < 0) {
432
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 42 times.
48 if (data_packets_seen(ogg))
433 6 idx = ogg_replace_stream(s, serial, readout_buf, size, probing);
434 else
435 42 idx = ogg_new_stream(s, serial);
436
437
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (idx < 0) {
438 av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
439 av_free(readout_buf);
440 return idx;
441 }
442
443 48 os = ogg->streams + idx;
444
445 48 ret = buf_realloc(os, size);
446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 48 times.
48 if (ret < 0) {
447 av_free(readout_buf);
448 return ret;
449 }
450
451 48 memcpy(os->buf + os->bufpos, readout_buf, size);
452 48 av_free(readout_buf);
453 }
454
455 1507 ogg->page_pos = page_pos;
456 1507 os->page_pos = page_pos;
457 1507 os->nsegs = nsegs;
458 1507 os->segp = 0;
459 1507 os->got_data = !(flags & OGG_FLAG_BOS);
460 1507 os->bufpos += size;
461 1507 os->granule = gp;
462 1507 os->flags = flags;
463 1507 memcpy(os->segments, segments, nsegs);
464 1507 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
465
466
3/4
✓ Branch 0 taken 883 times.
✓ Branch 1 taken 624 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 883 times.
1507 if (flags & OGG_FLAG_CONT || os->incomplete) {
467
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 462 times.
624 if (!os->psize) {
468 // If this is the very first segment we started
469 // playback in the middle of a continuation packet.
470 // Discard it since we missed the start of it.
471
1/2
✓ Branch 0 taken 394 times.
✗ Branch 1 not taken.
394 while (os->segp < os->nsegs) {
472 394 int seg = os->segments[os->segp++];
473 394 os->pstart += seg;
474
2/2
✓ Branch 0 taken 162 times.
✓ Branch 1 taken 232 times.
394 if (seg < 255)
475 162 break;
476 }
477 162 os->sync_pos = os->page_pos;
478 }
479 } else {
480 883 os->psize = 0;
481 883 os->sync_pos = os->page_pos;
482 }
483
484 /* This function is always called with sid != NULL */
485 1507 *sid = idx;
486
487 1507 return 0;
488 }
489
490 /**
491 * @brief find the next Ogg packet
492 * @param *sid is set to the stream for the packet or -1 if there is
493 * no matching stream, in that case assume all other return
494 * values to be uninitialized.
495 * @return negative value on error or EOF.
496 */
497 12191 static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
498 int64_t *fpos)
499 {
500 12191 FFFormatContext *const si = ffformatcontext(s);
501 12191 struct ogg *ogg = s->priv_data;
502 int idx, i, ret;
503 struct ogg_stream *os;
504 12191 int complete = 0;
505 12191 int segp = 0, psize = 0;
506
507 12191 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
508
2/2
✓ Branch 0 taken 12035 times.
✓ Branch 1 taken 156 times.
12191 if (sid)
509 12035 *sid = -1;
510
511 do {
512 12633 idx = ogg->curidx;
513
514
2/2
✓ Branch 0 taken 1143 times.
✓ Branch 1 taken 12518 times.
13661 while (idx < 0) {
515 1143 ret = ogg_read_page(s, &idx, 0);
516
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 1028 times.
1143 if (ret < 0)
517 115 return ret;
518 }
519
520 12518 os = ogg->streams + idx;
521
522 12518 av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
523 idx, os->pstart, os->psize, os->segp, os->nsegs);
524
525
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 12476 times.
12518 if (!os->codec) {
526
1/2
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
42 if (os->header < 0) {
527 42 os->codec = ogg_find_codec(os->buf, os->bufpos);
528
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (!os->codec) {
529 av_log(s, AV_LOG_WARNING, "Codec not found\n");
530 os->header = 0;
531 return 0;
532 }
533 } else {
534 return 0;
535 }
536 }
537
538 12518 segp = os->segp;
539 12518 psize = os->psize;
540
541
2/2
✓ Branch 0 taken 25586 times.
✓ Branch 1 taken 442 times.
26028 while (os->segp < os->nsegs) {
542 25586 int ss = os->segments[os->segp++];
543 25586 os->psize += ss;
544
2/2
✓ Branch 0 taken 12076 times.
✓ Branch 1 taken 13510 times.
25586 if (ss < 255) {
545 12076 complete = 1;
546 12076 break;
547 }
548 }
549
550
3/4
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 12076 times.
✓ Branch 2 taken 442 times.
✗ Branch 3 not taken.
12518 if (!complete && os->segp == os->nsegs) {
551 442 ogg->curidx = -1;
552 // Do not set incomplete for empty packets.
553 // Together with the code in ogg_read_page
554 // that discards all continuation of empty packets
555 // we would get an infinite loop.
556 442 os->incomplete = !!os->psize;
557 }
558
2/2
✓ Branch 0 taken 442 times.
✓ Branch 1 taken 12076 times.
12518 } while (!complete);
559
560
561
2/2
✓ Branch 0 taken 178 times.
✓ Branch 1 taken 11898 times.
12076 if (os->granule == -1)
562 178 av_log(s, AV_LOG_WARNING,
563 "Page at %"PRId64" is missing granule\n",
564 os->page_pos);
565
566 12076 ogg->curidx = idx;
567 12076 os->incomplete = 0;
568
569
2/2
✓ Branch 0 taken 158 times.
✓ Branch 1 taken 11918 times.
12076 if (os->header) {
570
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 158 times.
158 if ((ret = os->codec->header(s, idx)) < 0) {
571 av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
572 return ret;
573 }
574 158 os->header = ret;
575
2/2
✓ Branch 0 taken 43 times.
✓ Branch 1 taken 115 times.
158 if (!os->header) {
576 43 os->segp = segp;
577 43 os->psize = psize;
578
579 // We have reached the first non-header packet in this stream.
580 // Unfortunately more header packets may still follow for others,
581 // but if we continue with header parsing we may lose data packets.
582 43 ogg->headers = 1;
583
584 // Update the header state for all streams and
585 // compute the data_offset.
586
2/2
✓ Branch 0 taken 41 times.
✓ Branch 1 taken 2 times.
43 if (!si->data_offset)
587 41 si->data_offset = os->sync_pos;
588
589
2/2
✓ Branch 0 taken 46 times.
✓ Branch 1 taken 43 times.
89 for (i = 0; i < ogg->nstreams; i++) {
590 46 struct ogg_stream *cur_os = ogg->streams + i;
591
592 // if we have a partial non-header packet, its start is
593 // obviously at or after the data start
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46 times.
46 if (cur_os->incomplete)
595 si->data_offset = FFMIN(si->data_offset, cur_os->sync_pos);
596 }
597 } else {
598 115 os->nb_header++;
599 115 os->pstart += os->psize;
600 115 os->psize = 0;
601 }
602 } else {
603 11918 os->pflags = 0;
604 11918 os->pduration = 0;
605
606 11918 ret = 0;
607
2/4
✓ Branch 0 taken 11918 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11918 times.
✗ Branch 3 not taken.
11918 if (os->codec && os->codec->packet) {
608
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11918 times.
11918 if ((ret = os->codec->packet(s, idx)) < 0) {
609 av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
610 return ret;
611 }
612 }
613
614
2/2
✓ Branch 0 taken 11878 times.
✓ Branch 1 taken 40 times.
11918 if (!ret) {
615
1/2
✓ Branch 0 taken 11878 times.
✗ Branch 1 not taken.
11878 if (sid)
616 11878 *sid = idx;
617
2/2
✓ Branch 0 taken 11812 times.
✓ Branch 1 taken 66 times.
11878 if (dstart)
618 11812 *dstart = os->pstart;
619
2/2
✓ Branch 0 taken 11812 times.
✓ Branch 1 taken 66 times.
11878 if (dsize)
620 11812 *dsize = os->psize;
621
2/2
✓ Branch 0 taken 11812 times.
✓ Branch 1 taken 66 times.
11878 if (fpos)
622 11812 *fpos = os->sync_pos;
623 }
624
625 11918 os->pstart += os->psize;
626 11918 os->psize = 0;
627
2/2
✓ Branch 0 taken 528 times.
✓ Branch 1 taken 11390 times.
11918 if(os->pstart == os->bufpos)
628 528 os->bufpos = os->pstart = 0;
629 11918 os->sync_pos = os->page_pos;
630 }
631
632 // determine whether there are more complete packets in this page
633 // if not, the page's granule will apply to this packet
634 12076 os->page_end = 1;
635
2/2
✓ Branch 0 taken 17489 times.
✓ Branch 1 taken 713 times.
18202 for (i = os->segp; i < os->nsegs; i++)
636
2/2
✓ Branch 0 taken 11363 times.
✓ Branch 1 taken 6126 times.
17489 if (os->segments[i] < 255) {
637 11363 os->page_end = 0;
638 11363 break;
639 }
640
641
2/2
✓ Branch 0 taken 477 times.
✓ Branch 1 taken 11599 times.
12076 if (os->segp == os->nsegs)
642 477 ogg->curidx = -1;
643
644 12076 return 0;
645 }
646
647 41 static int ogg_get_length(AVFormatContext *s)
648 {
649 41 struct ogg *ogg = s->priv_data;
650 int i, ret;
651 int64_t size, end;
652 41 int streams_left=0;
653
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
655 return 0;
656
657 // already set
658
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (s->duration != AV_NOPTS_VALUE)
659 return 0;
660
661 41 size = avio_size(s->pb);
662
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (size < 0)
663 return 0;
664 41 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
665
666 41 ret = ogg_save(s);
667
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
668 return ret;
669 41 avio_seek(s->pb, end, SEEK_SET);
670 41 ogg->page_pos = -1;
671
672
2/2
✓ Branch 1 taken 479 times.
✓ Branch 2 taken 41 times.
520 while (!ogg_read_page(s, &i, 1)) {
673
5/6
✓ Branch 0 taken 479 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 444 times.
✓ Branch 3 taken 35 times.
✓ Branch 4 taken 420 times.
✓ Branch 5 taken 24 times.
479 if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
674
1/2
✓ Branch 0 taken 420 times.
✗ Branch 1 not taken.
420 ogg->streams[i].codec) {
675 420 s->streams[i]->duration =
676 420 ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
677
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 420 times.
420 if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
678 s->streams[i]->duration -= s->streams[i]->start_time;
679 streams_left-= (ogg->streams[i].got_start==-1);
680 ogg->streams[i].got_start= 1;
681
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 378 times.
420 } else if(!ogg->streams[i].got_start) {
682 42 ogg->streams[i].got_start= -1;
683 42 streams_left++;
684 }
685 }
686 }
687
688 41 ogg_restore(s);
689
690 41 ret = ogg_save(s);
691
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
692 return ret;
693
694 41 avio_seek (s->pb, ffformatcontext(s)->data_offset, SEEK_SET);
695 41 ogg_reset(s);
696
3/4
✓ Branch 0 taken 67 times.
✓ Branch 1 taken 41 times.
✓ Branch 3 taken 67 times.
✗ Branch 4 not taken.
108 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
697 int64_t pts;
698
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 66 times.
67 if (i < 0) continue;
699 66 pts = ogg_calc_pts(s, i, NULL);
700
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (s->streams[i]->duration == AV_NOPTS_VALUE)
701 continue;
702
4/6
✓ Branch 0 taken 66 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 60 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
66 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
703 6 s->streams[i]->duration -= pts;
704 6 ogg->streams[i].got_start= 1;
705 6 streams_left--;
706
3/4
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 36 times.
✓ Branch 3 taken 24 times.
60 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
707 36 ogg->streams[i].got_start= 1;
708 36 streams_left--;
709 }
710 }
711 41 ogg_restore (s);
712
713 41 return 0;
714 }
715
716 41 static int ogg_read_close(AVFormatContext *s)
717 {
718 41 struct ogg *ogg = s->priv_data;
719 int i;
720
721
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 41 times.
83 for (i = 0; i < ogg->nstreams; i++) {
722 42 free_stream(s, i);
723 }
724
725 41 ogg->nstreams = 0;
726
727 41 av_freep(&ogg->streams);
728 41 return 0;
729 }
730
731 41 static int ogg_read_header(AVFormatContext *s)
732 {
733 41 struct ogg *ogg = s->priv_data;
734 int ret, i;
735
736 41 ogg->curidx = -1;
737
738 //linear headers seek from start
739 do {
740 156 ret = ogg_packet(s, NULL, NULL, NULL, NULL);
741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 156 times.
156 if (ret < 0)
742 return ret;
743
2/2
✓ Branch 0 taken 115 times.
✓ Branch 1 taken 41 times.
156 } while (!ogg->headers);
744 41 av_log(s, AV_LOG_TRACE, "found headers\n");
745
746
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 41 times.
83 for (i = 0; i < ogg->nstreams; i++) {
747 42 struct ogg_stream *os = ogg->streams + i;
748
749
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ogg->streams[i].header < 0) {
750 av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
751 ogg->streams[i].codec = NULL;
752 av_freep(&ogg->streams[i].private);
753
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 42 times.
42 } else if (os->codec && os->nb_header < os->codec->nb_header) {
754 av_log(s, AV_LOG_WARNING,
755 "Headers mismatch for stream %d: "
756 "expected %d received %d.\n",
757 i, os->codec->nb_header, os->nb_header);
758 if (s->error_recognition & AV_EF_EXPLODE)
759 return AVERROR_INVALIDDATA;
760 }
761
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (os->start_granule != OGG_NOGRANULE_VALUE)
762 os->lastpts = s->streams[i]->start_time =
763 ogg_gptopts(s, i, os->start_granule, NULL);
764 }
765
766 //linear granulepos seek from end
767 41 ret = ogg_get_length(s);
768
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
41 if (ret < 0)
769 return ret;
770
771 41 return 0;
772 }
773
774 11878 static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
775 {
776 11878 struct ogg *ogg = s->priv_data;
777 11878 struct ogg_stream *os = ogg->streams + idx;
778 11878 int64_t pts = AV_NOPTS_VALUE;
779
780
2/2
✓ Branch 0 taken 11774 times.
✓ Branch 1 taken 104 times.
11878 if (dts)
781 11774 *dts = AV_NOPTS_VALUE;
782
783
2/2
✓ Branch 0 taken 11432 times.
✓ Branch 1 taken 446 times.
11878 if (os->lastpts != AV_NOPTS_VALUE) {
784 11432 pts = os->lastpts;
785 11432 os->lastpts = AV_NOPTS_VALUE;
786 }
787
2/2
✓ Branch 0 taken 11374 times.
✓ Branch 1 taken 504 times.
11878 if (os->lastdts != AV_NOPTS_VALUE) {
788
2/2
✓ Branch 0 taken 11302 times.
✓ Branch 1 taken 72 times.
11374 if (dts)
789 11302 *dts = os->lastdts;
790 11374 os->lastdts = AV_NOPTS_VALUE;
791 }
792
2/2
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 11302 times.
11878 if (os->page_end) {
793
2/2
✓ Branch 0 taken 567 times.
✓ Branch 1 taken 9 times.
576 if (os->granule != -1LL) {
794
2/4
✓ Branch 0 taken 567 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 567 times.
567 if (os->codec && os->codec->granule_is_start)
795 pts = ogg_gptopts(s, idx, os->granule, dts);
796 else
797 567 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
798 567 os->granule = -1LL;
799 }
800 }
801 11878 return pts;
802 }
803
804 11812 static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
805 {
806 11812 struct ogg *ogg = s->priv_data;
807 11812 struct ogg_stream *os = ogg->streams + idx;
808 11812 int invalid = 0;
809
2/2
✓ Branch 0 taken 11664 times.
✓ Branch 1 taken 148 times.
11812 if (psize) {
810
3/3
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 181 times.
✓ Branch 2 taken 11446 times.
11664 switch (s->streams[idx]->codecpar->codec_id) {
811 37 case AV_CODEC_ID_THEORA:
812 37 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
813 37 break;
814 181 case AV_CODEC_ID_VP8:
815 181 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
816 }
817
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 11661 times.
11664 if (invalid) {
818 3 os->pflags ^= AV_PKT_FLAG_KEY;
819 3 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
820
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
821 }
822 }
823 11812 }
824
825 11811 static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
826 {
827 struct ogg *ogg;
828 struct ogg_stream *os;
829 int idx, ret;
830 int pstart, psize;
831 int64_t fpos, pts, dts;
832
833
1/2
✓ Branch 0 taken 11811 times.
✗ Branch 1 not taken.
11811 if (s->io_repositioned) {
834 ogg_reset(s);
835 s->io_repositioned = 0;
836 }
837
838 //Get an ogg packet
839 11811 retry:
840 do {
841 11816 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
842
2/2
✓ Branch 0 taken 37 times.
✓ Branch 1 taken 11779 times.
11816 if (ret < 0)
843 37 return ret;
844
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 11774 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 11774 times.
11779 } while (idx < 0 || !s->streams[idx]);
845
846 11774 ogg = s->priv_data;
847 11774 os = ogg->streams + idx;
848
849 // pflags might not be set until after this
850 11774 pts = ogg_calc_pts(s, idx, &dts);
851 11774 ogg_validate_keyframe(s, idx, pstart, psize);
852
853
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11774 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
11774 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
854 goto retry;
855 11774 os->keyframe_seek = 0;
856
857 //Alloc a pkt
858 11774 ret = av_new_packet(pkt, psize);
859
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11774 times.
11774 if (ret < 0)
860 return ret;
861 11774 pkt->stream_index = idx;
862 11774 memcpy(pkt->data, os->buf + pstart, psize);
863
864 11774 pkt->pts = pts;
865 11774 pkt->dts = dts;
866 11774 pkt->flags = os->pflags;
867 11774 pkt->duration = os->pduration;
868 11774 pkt->pos = fpos;
869
870
4/4
✓ Branch 0 taken 11768 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 11 times.
✓ Branch 3 taken 11757 times.
11774 if (os->start_trimming || os->end_trimming) {
871 17 uint8_t *side_data = av_packet_new_side_data(pkt,
872 AV_PKT_DATA_SKIP_SAMPLES,
873 10);
874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
17 if(!side_data)
875 return AVERROR(ENOMEM);
876 17 AV_WL32(side_data + 0, os->start_trimming);
877 17 AV_WL32(side_data + 4, os->end_trimming);
878 17 os->start_trimming = 0;
879 17 os->end_trimming = 0;
880 }
881
882
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 11745 times.
11774 if (os->new_metadata) {
883 29 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE,
884 os->new_metadata, os->new_metadata_size);
885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (ret < 0)
886 return ret;
887
888 29 os->new_metadata = NULL;
889 29 os->new_metadata_size = 0;
890 }
891
892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11774 times.
11774 if (os->new_extradata) {
893 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
894 os->new_extradata, os->new_extradata_size);
895 if (ret < 0)
896 return ret;
897
898 os->new_extradata = NULL;
899 os->new_extradata_size = 0;
900 }
901
902 11774 return psize;
903 }
904
905 116 static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
906 int64_t *pos_arg, int64_t pos_limit)
907 {
908 116 struct ogg *ogg = s->priv_data;
909 116 AVIOContext *bc = s->pb;
910 116 int64_t pts = AV_NOPTS_VALUE;
911 116 int64_t keypos = -1;
912 int i;
913 int pstart, psize;
914 116 avio_seek(bc, *pos_arg, SEEK_SET);
915 116 ogg_reset(s);
916
917 152 while ( avio_tell(bc) <= pos_limit
918
3/4
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 74 times.
✓ Branch 4 taken 78 times.
152 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
919
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 36 times.
74 if (i == stream_index) {
920 38 struct ogg_stream *os = ogg->streams + stream_index;
921 // Do not trust the last timestamps of an ogm video
922
2/2
✓ Branch 0 taken 26 times.
✓ Branch 1 taken 12 times.
38 if ( (os->flags & OGG_FLAG_EOS)
923
1/2
✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
26 && !(os->flags & OGG_FLAG_BOS)
924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 26 times.
26 && os->codec == &ff_ogm_video_codec)
925 continue;
926 38 pts = ogg_calc_pts(s, i, NULL);
927 38 ogg_validate_keyframe(s, i, pstart, psize);
928
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 if (os->pflags & AV_PKT_FLAG_KEY) {
929 keypos = *pos_arg;
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
38 } else if (os->keyframe_seek) {
931 // if we had a previous keyframe but no pts for it,
932 // return that keyframe with this pts value.
933 if (keypos >= 0)
934 *pos_arg = keypos;
935 else
936 pts = AV_NOPTS_VALUE;
937 }
938 }
939
2/2
✓ Branch 0 taken 38 times.
✓ Branch 1 taken 36 times.
74 if (pts != AV_NOPTS_VALUE)
940 38 break;
941 }
942 116 ogg_reset(s);
943 116 return pts;
944 }
945
946 28 static int ogg_read_seek(AVFormatContext *s, int stream_index,
947 int64_t timestamp, int flags)
948 {
949 28 struct ogg *ogg = s->priv_data;
950 28 struct ogg_stream *os = ogg->streams + stream_index;
951 int ret;
952
953
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 av_assert0(stream_index < ogg->nstreams);
954 // Ensure everything is reset even when seeking via
955 // the generated index.
956 28 ogg_reset(s);
957
958 // Try seeking to a keyframe first. If this fails (very possible),
959 // av_seek_frame will fall back to ignoring keyframes
960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
961 && !(flags & AVSEEK_FLAG_ANY))
962 os->keyframe_seek = 1;
963
964 28 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
965 28 ogg_reset(s);
966 28 os = ogg->streams + stream_index;
967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (ret < 0)
968 os->keyframe_seek = 0;
969 28 return ret;
970 }
971
972 7235 static int ogg_probe(const AVProbeData *p)
973 {
974
3/4
✓ Branch 0 taken 36 times.
✓ Branch 1 taken 7199 times.
✓ Branch 2 taken 36 times.
✗ Branch 3 not taken.
7235 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
975 36 return AVPROBE_SCORE_MAX;
976 7199 return 0;
977 }
978
979 const FFInputFormat ff_ogg_demuxer = {
980 .p.name = "ogg",
981 .p.long_name = NULL_IF_CONFIG_SMALL("Ogg"),
982 .p.extensions = "ogg",
983 .p.flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
984 .priv_data_size = sizeof(struct ogg),
985 .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP,
986 .read_probe = ogg_probe,
987 .read_header = ogg_read_header,
988 .read_packet = ogg_read_packet,
989 .read_close = ogg_read_close,
990 .read_seek = ogg_read_seek,
991 .read_timestamp = ogg_read_timestamp,
992 };
993