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