FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavformat/oggdec.c
Date: 2022-11-26 13:19:19
Exec Total Coverage
Lines: 438 546 80.2%
Branches: 221 325 68.0%

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