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 43static 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 62static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts); 63static int ogg_new_stream(AVFormatContext *s, uint32_t serial); 64static int ogg_restore(AVFormatContext *s); 65 66static 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 82static 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 118static 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 struct ogg_stream *stream = &ogg->streams[i]; 132 av_freep(&stream->buf); 133 av_freep(&stream->new_metadata); 134 135 if (i >= ost->nstreams || !ost->streams[i].private) { 136 free_stream(s, i); 137 } 138 } 139 140 avio_seek(bc, ost->pos, SEEK_SET); 141 ogg->page_pos = -1; 142 ogg->curidx = ost->curidx; 143 ogg->nstreams = ost->nstreams; 144 if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams, 145 sizeof(*ogg->streams))) < 0) { 146 ogg->nstreams = 0; 147 return err; 148 } else 149 memcpy(ogg->streams, ost->streams, 150 ost->nstreams * sizeof(*ogg->streams)); 151 152 av_free(ost); 153 154 return 0; 155} 156 157static int ogg_reset(AVFormatContext *s) 158{ 159 struct ogg *ogg = s->priv_data; 160 int i; 161 int64_t start_pos = avio_tell(s->pb); 162 163 for (i = 0; i < ogg->nstreams; i++) { 164 struct ogg_stream *os = ogg->streams + i; 165 os->bufpos = 0; 166 os->pstart = 0; 167 os->psize = 0; 168 os->granule = -1; 169 os->lastpts = AV_NOPTS_VALUE; 170 os->lastdts = AV_NOPTS_VALUE; 171 os->sync_pos = -1; 172 os->page_pos = 0; 173 os->nsegs = 0; 174 os->segp = 0; 175 os->incomplete = 0; 176 os->got_data = 0; 177 if (start_pos <= ffformatcontext(s)->data_offset) { 178 os->lastpts = 0; 179 } 180 os->start_trimming = 0; 181 os->end_trimming = 0; 182 av_freep(&os->new_metadata); 183 os->new_metadata_size = 0; 184 } 185 186 ogg->page_pos = -1; 187 ogg->curidx = -1; 188 189 return 0; 190} 191 192static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) 193{ 194 int i; 195 196 for (i = 0; ogg_codecs[i]; i++) 197 if (size >= ogg_codecs[i]->magicsize && 198 !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize)) 199 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 */ 209static 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 248static int ogg_new_stream(AVFormatContext *s, uint32_t serial) 249{ 250 struct ogg *ogg = s->priv_data; 251 int idx = ogg->nstreams; 252 AVStream *st; 253 struct ogg_stream *os; 254 255 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 if (!(os = av_realloc_array(ogg->streams, ogg->nstreams + 1, 263 sizeof(*ogg->streams)))) 264 return AVERROR(ENOMEM); 265 ogg->streams = os; 266 os = ogg->streams + idx; 267 memset(os, 0, sizeof(*os)); 268 os->serial = serial; 269 os->bufsize = DECODER_BUFFER_SIZE; 270 os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); 271 os->header = -1; 272 os->start_granule = OGG_NOGRANULE_VALUE; 273 if (!os->buf) 274 return AVERROR(ENOMEM); 275 276 /* Create the associated AVStream */ 277 st = avformat_new_stream(s, NULL); 278 if (!st) { 279 av_freep(&os->buf); 280 return AVERROR(ENOMEM); 281 } 282 st->id = idx; 283 avpriv_set_pts_info(st, 64, 1, 1000000); 284 285 ogg->nstreams++; 286 return idx; 287} 288 289static int data_packets_seen(const struct ogg *ogg) 290{ 291 int i; 292 293 for (i = 0; i < ogg->nstreams; i++) 294 if (ogg->streams[i].got_data) 295 return 1; 296 return 0; 297} 298 299static int buf_realloc(struct ogg_stream *os, int size) 300{ 301 /* Even if invalid guarantee there's enough memory to read the page */ 302 if (os->bufsize - os->bufpos < size) { 303 uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); 304 if (!nb) 305 return AVERROR(ENOMEM); 306 os->buf = nb; 307 os->bufsize *= 2; 308 } 309 310 return 0; 311} 312 313static int ogg_read_page(AVFormatContext *s, int *sid, int probing) 314{ 315 AVIOContext *bc = s->pb; 316 struct ogg *ogg = s->priv_data; 317 struct ogg_stream *os; 318 int ret, i = 0; 319 int flags, nsegs; 320 uint64_t gp; 321 uint32_t serial; 322 uint32_t crc, crc_tmp; 323 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 int sp = 0; 330 331 ret = avio_read(bc, sync, 4); 332 if (ret < 4) 333 return ret < 0 ? ret : AVERROR_EOF; 334 335 do { 336 int c; 337 338 if (sync[sp & 3] == 'O' && 339 sync[(sp + 1) & 3] == 'g' && 340 sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S') 341 break; 342 343 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 c = avio_r8(bc); 350 351 if (avio_feof(bc)) 352 return AVERROR_EOF; 353 354 sync[sp++ & 3] = c; 355 } while (i++ < MAX_PAGE_SIZE); 356 357 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 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 ffio_ensure_seekback(bc, MAX_PAGE_SIZE); 367 start_pos = avio_tell(bc); 368 369 version = avio_r8(bc); 370 flags = avio_r8(bc); 371 gp = avio_rl64(bc); 372 serial = avio_rl32(bc); 373 avio_skip(bc, 4); /* seq */ 374 375 crc_tmp = ffio_get_checksum(bc); 376 crc = avio_rb32(bc); 377 crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4); 378 ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp); 379 380 nsegs = avio_r8(bc); 381 page_pos = avio_tell(bc) - 27; 382 383 ret = avio_read(bc, segments, nsegs); 384 if (ret < nsegs) 385 return ret < 0 ? ret : AVERROR_EOF; 386 387 for (i = 0; i < nsegs; i++) 388 size += segments[i]; 389 390 idx = ogg_find_stream(ogg, serial); 391 if (idx >= 0) { 392 os = ogg->streams + idx; 393 394 ret = buf_realloc(os, size); 395 if (ret < 0) 396 return ret; 397 398 readout_buf = os->buf + os->bufpos; 399 } else { 400 readout_buf = av_malloc(size); 401 } 402 403 ret = avio_read(bc, readout_buf, size); 404 if (ret < size) { 405 if (idx < 0) 406 av_free(readout_buf); 407 return ret < 0 ? ret : AVERROR_EOF; 408 } 409 410 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 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 if (idx < 0) { 432 if (data_packets_seen(ogg)) 433 idx = ogg_replace_stream(s, serial, readout_buf, size, probing); 434 else 435 idx = ogg_new_stream(s, serial); 436 437 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 os = ogg->streams + idx; 444 445 ret = buf_realloc(os, size); 446 if (ret < 0) { 447 av_free(readout_buf); 448 return ret; 449 } 450 451 memcpy(os->buf + os->bufpos, readout_buf, size); 452 av_free(readout_buf); 453 } 454 455 ogg->page_pos = page_pos; 456 os->page_pos = page_pos; 457 os->nsegs = nsegs; 458 os->segp = 0; 459 os->got_data = !(flags & OGG_FLAG_BOS); 460 os->bufpos += size; 461 os->granule = gp; 462 os->flags = flags; 463 memcpy(os->segments, segments, nsegs); 464 memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE); 465 466 if (flags & OGG_FLAG_CONT || os->incomplete) { 467 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 while (os->segp < os->nsegs) { 472 int seg = os->segments[os->segp++]; 473 os->pstart += seg; 474 if (seg < 255) 475 break; 476 } 477 os->sync_pos = os->page_pos; 478 } 479 } else { 480 os->psize = 0; 481 os->sync_pos = os->page_pos; 482 } 483 484 /* This function is always called with sid != NULL */ 485 *sid = idx; 486 487 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 */ 497static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, 498 int64_t *fpos) 499{ 500 FFFormatContext *const si = ffformatcontext(s); 501 struct ogg *ogg = s->priv_data; 502 int idx, i, ret; 503 struct ogg_stream *os; 504 int complete = 0; 505 int segp = 0, psize = 0; 506 507 av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx); 508 if (sid) 509 *sid = -1; 510 511 do { 512 idx = ogg->curidx; 513 514 while (idx < 0) { 515 ret = ogg_read_page(s, &idx, 0); 516 if (ret < 0) 517 return ret; 518 } 519 520 os = ogg->streams + idx; 521 522 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 if (!os->codec) { 526 if (os->header < 0) { 527 os->codec = ogg_find_codec(os->buf, os->bufpos); 528 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 segp = os->segp; 539 psize = os->psize; 540 541 while (os->segp < os->nsegs) { 542 int ss = os->segments[os->segp++]; 543 os->psize += ss; 544 if (ss < 255) { 545 complete = 1; 546 break; 547 } 548 } 549 550 if (!complete && os->segp == os->nsegs) { 551 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 os->incomplete = !!os->psize; 557 } 558 } while (!complete); 559 560 561 if (os->granule == -1) 562 av_log(s, AV_LOG_WARNING, 563 "Page at %"PRId64" is missing granule\n", 564 os->page_pos); 565 566 ogg->curidx = idx; 567 os->incomplete = 0; 568 569 if (os->header) { 570 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 os->header = ret; 575 if (!os->header) { 576 os->segp = segp; 577 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 ogg->headers = 1; 583 584 // Update the header state for all streams and 585 // compute the data_offset. 586 if (!si->data_offset) 587 si->data_offset = os->sync_pos; 588 589 for (i = 0; i < ogg->nstreams; i++) { 590 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 if (cur_os->incomplete) 595 si->data_offset = FFMIN(si->data_offset, cur_os->sync_pos); 596 } 597 } else { 598 os->nb_header++; 599 os->pstart += os->psize; 600 os->psize = 0; 601 } 602 } else { 603 os->pflags = 0; 604 os->pduration = 0; 605 if (os->codec && os->codec->packet) { 606 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 if (sid) 612 *sid = idx; 613 if (dstart) 614 *dstart = os->pstart; 615 if (dsize) 616 *dsize = os->psize; 617 if (fpos) 618 *fpos = os->sync_pos; 619 os->pstart += os->psize; 620 os->psize = 0; 621 if(os->pstart == os->bufpos) 622 os->bufpos = os->pstart = 0; 623 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 os->page_end = 1; 629 for (i = os->segp; i < os->nsegs; i++) 630 if (os->segments[i] < 255) { 631 os->page_end = 0; 632 break; 633 } 634 635 if (os->segp == os->nsegs) 636 ogg->curidx = -1; 637 638 return 0; 639} 640 641static int ogg_get_length(AVFormatContext *s) 642{ 643 struct ogg *ogg = s->priv_data; 644 int i, ret; 645 int64_t size, end; 646 int streams_left=0; 647 648 if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) 649 return 0; 650 651// already set 652 if (s->duration != AV_NOPTS_VALUE) 653 return 0; 654 655 size = avio_size(s->pb); 656 if (size < 0) 657 return 0; 658 end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0; 659 660 ret = ogg_save(s); 661 if (ret < 0) 662 return ret; 663 avio_seek(s->pb, end, SEEK_SET); 664 ogg->page_pos = -1; 665 666 while (!ogg_read_page(s, &i, 1)) { 667 if (i >= 0 && ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && 668 ogg->streams[i].codec) { 669 s->streams[i]->duration = 670 ogg_gptopts(s, i, ogg->streams[i].granule, NULL); 671 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 } else if(!ogg->streams[i].got_start) { 676 ogg->streams[i].got_start= -1; 677 streams_left++; 678 } 679 } 680 } 681 682 ogg_restore(s); 683 684 ret = ogg_save(s); 685 if (ret < 0) 686 return ret; 687 688 avio_seek (s->pb, ffformatcontext(s)->data_offset, SEEK_SET); 689 ogg_reset(s); 690 while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) { 691 int64_t pts; 692 if (i < 0) continue; 693 pts = ogg_calc_pts(s, i, NULL); 694 if (s->streams[i]->duration == AV_NOPTS_VALUE) 695 continue; 696 if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) { 697 s->streams[i]->duration -= pts; 698 ogg->streams[i].got_start= 1; 699 streams_left--; 700 }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) { 701 ogg->streams[i].got_start= 1; 702 streams_left--; 703 } 704 } 705 ogg_restore (s); 706 707 return 0; 708} 709 710static int ogg_read_close(AVFormatContext *s) 711{ 712 struct ogg *ogg = s->priv_data; 713 int i; 714 715 for (i = 0; i < ogg->nstreams; i++) { 716 free_stream(s, i); 717 } 718 719 ogg->nstreams = 0; 720 721 av_freep(&ogg->streams); 722 return 0; 723} 724 725static int ogg_read_header(AVFormatContext *s) 726{ 727 struct ogg *ogg = s->priv_data; 728 int ret, i; 729 730 ogg->curidx = -1; 731 732 //linear headers seek from start 733 do { 734 ret = ogg_packet(s, NULL, NULL, NULL, NULL); 735 if (ret < 0) 736 return ret; 737 } while (!ogg->headers); 738 av_log(s, AV_LOG_TRACE, "found headers\n"); 739 740 for (i = 0; i < ogg->nstreams; i++) { 741 struct ogg_stream *os = ogg->streams + i; 742 743 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 } 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 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 ret = ogg_get_length(s); 762 if (ret < 0) 763 return ret; 764 765 return 0; 766} 767 768static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts) 769{ 770 struct ogg *ogg = s->priv_data; 771 struct ogg_stream *os = ogg->streams + idx; 772 int64_t pts = AV_NOPTS_VALUE; 773 774 if (dts) 775 *dts = AV_NOPTS_VALUE; 776 777 if (os->lastpts != AV_NOPTS_VALUE) { 778 pts = os->lastpts; 779 os->lastpts = AV_NOPTS_VALUE; 780 } 781 if (os->lastdts != AV_NOPTS_VALUE) { 782 if (dts) 783 *dts = os->lastdts; 784 os->lastdts = AV_NOPTS_VALUE; 785 } 786 if (os->page_end) { 787 if (os->granule != -1LL) { 788 if (os->codec && os->codec->granule_is_start) 789 pts = ogg_gptopts(s, idx, os->granule, dts); 790 else 791 os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts); 792 os->granule = -1LL; 793 } 794 } 795 return pts; 796} 797 798static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize) 799{ 800 struct ogg *ogg = s->priv_data; 801 struct ogg_stream *os = ogg->streams + idx; 802 int invalid = 0; 803 if (psize) { 804 switch (s->streams[idx]->codecpar->codec_id) { 805 case AV_CODEC_ID_THEORA: 806 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40); 807 break; 808 case AV_CODEC_ID_VP8: 809 invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1); 810 } 811 if (invalid) { 812 os->pflags ^= AV_PKT_FLAG_KEY; 813 av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n", 814 (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-"); 815 } 816 } 817} 818 819static 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 if (s->io_repositioned) { 828 ogg_reset(s); 829 s->io_repositioned = 0; 830 } 831 832 //Get an ogg packet 833retry: 834 do { 835 ret = ogg_packet(s, &idx, &pstart, &psize, &fpos); 836 if (ret < 0) 837 return ret; 838 } while (idx < 0 || !s->streams[idx]); 839 840 ogg = s->priv_data; 841 os = ogg->streams + idx; 842 843 // pflags might not be set until after this 844 pts = ogg_calc_pts(s, idx, &dts); 845 ogg_validate_keyframe(s, idx, pstart, psize); 846 847 if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY)) 848 goto retry; 849 os->keyframe_seek = 0; 850 851 //Alloc a pkt 852 ret = av_new_packet(pkt, psize); 853 if (ret < 0) 854 return ret; 855 pkt->stream_index = idx; 856 memcpy(pkt->data, os->buf + pstart, psize); 857 858 pkt->pts = pts; 859 pkt->dts = dts; 860 pkt->flags = os->pflags; 861 pkt->duration = os->pduration; 862 pkt->pos = fpos; 863 864 if (os->start_trimming || os->end_trimming) { 865 uint8_t *side_data = av_packet_new_side_data(pkt, 866 AV_PKT_DATA_SKIP_SAMPLES, 867 10); 868 if(!side_data) 869 return AVERROR(ENOMEM); 870 AV_WL32(side_data + 0, os->start_trimming); 871 AV_WL32(side_data + 4, os->end_trimming); 872 os->start_trimming = 0; 873 os->end_trimming = 0; 874 } 875 876 if (os->new_metadata) { 877 ret = av_packet_add_side_data(pkt, AV_PKT_DATA_METADATA_UPDATE, 878 os->new_metadata, os->new_metadata_size); 879 if (ret < 0) 880 return ret; 881 882 os->new_metadata = NULL; 883 os->new_metadata_size = 0; 884 } 885 886 return psize; 887} 888 889static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, 890 int64_t *pos_arg, int64_t pos_limit) 891{ 892 struct ogg *ogg = s->priv_data; 893 AVIOContext *bc = s->pb; 894 int64_t pts = AV_NOPTS_VALUE; 895 int64_t keypos = -1; 896 int i; 897 int pstart, psize; 898 avio_seek(bc, *pos_arg, SEEK_SET); 899 ogg_reset(s); 900 901 while ( avio_tell(bc) <= pos_limit 902 && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { 903 if (i == stream_index) { 904 struct ogg_stream *os = ogg->streams + stream_index; 905 // Do not trust the last timestamps of an ogm video 906 if ( (os->flags & OGG_FLAG_EOS) 907 && !(os->flags & OGG_FLAG_BOS) 908 && os->codec == &ff_ogm_video_codec) 909 continue; 910 pts = ogg_calc_pts(s, i, NULL); 911 ogg_validate_keyframe(s, i, pstart, psize); 912 if (os->pflags & AV_PKT_FLAG_KEY) { 913 keypos = *pos_arg; 914 } 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 if (pts != AV_NOPTS_VALUE) 924 break; 925 } 926 ogg_reset(s); 927 return pts; 928} 929 930static int ogg_read_seek(AVFormatContext *s, int stream_index, 931 int64_t timestamp, int flags) 932{ 933 struct ogg *ogg = s->priv_data; 934 struct ogg_stream *os = ogg->streams + stream_index; 935 int ret; 936 937 av_assert0(stream_index < ogg->nstreams); 938 // Ensure everything is reset even when seeking via 939 // the generated index. 940 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 if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO 945 && !(flags & AVSEEK_FLAG_ANY)) 946 os->keyframe_seek = 1; 947 948 ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); 949 ogg_reset(s); 950 os = ogg->streams + stream_index; 951 if (ret < 0) 952 os->keyframe_seek = 0; 953 return ret; 954} 955 956static int ogg_probe(const AVProbeData *p) 957{ 958 if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7) 959 return AVPROBE_SCORE_MAX; 960 return 0; 961} 962 963const 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