FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/oggdec.c
Date: 2025-03-08 20:38:41
Exec Total Coverage
Lines: 439 548 80.1%
Functions: 19 20 95.0%
Branches: 223 327 68.2%

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