1/* 2** Copyright (C) 2002-2019 Erik de Castro Lopo <erikd@mega-nerd.com> 3** Copyright (C) 2007 John ffitch 4** Copyright (C) 2018 Arthur Taylor <art@ified.ca> 5** 6** This program is free software ; you can redistribute it and/or modify 7** it under the terms of the GNU Lesser General Public License as published by 8** the Free Software Foundation ; either version 2.1 of the License, or 9** (at your option) any later version. 10** 11** This program is distributed in the hope that it will be useful, 12** but WITHOUT ANY WARRANTY ; without even the implied warranty of 13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14** GNU Lesser General Public License for more details. 15** 16** You should have received a copy of the GNU Lesser General Public License 17** along with this program ; if not, write to the Free Software 18** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19*/ 20 21/* 22** This file contains code based on OpusFile and Opus-Tools, both by 23** Xiph.Org. COPYING from each is identical and is as follows: 24** 25** Copyright (c) 1994-2013 Xiph.Org Foundation and contributors 26** 27** Redistribution and use in source and binary forms, with or without 28** modification, are permitted provided that the following conditions 29** are met: 30** 31** - Redistributions of source code must retain the above copyright 32** notice, this list of conditions and the following disclaimer. 33** 34** - Redistributions in binary form must reproduce the above copyright 35** notice, this list of conditions and the following disclaimer in the 36** documentation and/or other materials provided with the distribution. 37** 38** - Neither the name of the Xiph.Org Foundation nor the names of its 39** contributors may be used to endorse or promote products derived from 40** this software without specific prior written permission. 41** 42** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 43** ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 44** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 45** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION 46** OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 47** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 48** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 49** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 50** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 51** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 52** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 53*/ 54 55#include "sfconfig.h" 56 57#include <stdio.h> 58#include <fcntl.h> 59#include <string.h> 60#include <ctype.h> 61#include <time.h> 62#include <math.h> 63 64#if HAVE_UNISTD_H 65#include <unistd.h> 66#else 67#include "sf_unistd.h" 68#endif 69 70#include "sndfile.h" 71#include "sfendian.h" 72#include "common.h" 73 74#if HAVE_EXTERNAL_XIPH_LIBS 75 76#include <ogg/ogg.h> 77 78#include "ogg.h" 79 80#define OGG_SYNC_READ_SIZE (2048) 81#define OGG_PAGE_SIZE_MAX (65307) 82#define OGG_CHUNK_SIZE (65536) 83#define OGG_CHUNK_SIZE_MAX (1024*1024) 84 85/* 86 * The Ogg container may seem overly complicated, particularly when used for a 87 * on-disk audio file format. This is probably because Ogg is designed with 88 * streaming rather than storage as a priority, and can handle multiple codec 89 * payloads multiplexed together, then possibly chained on top of that. 90 * Ogg achieves its goals well, but it does lend to a bit of a learning curve, 91 * with many internal structures to push data around in compared to most sound 92 * file formats which only have a header and raw data. 93 * 94 * See 95 * - [https://xiph.org/ogg/doc/oggstream.html] 96 * - [https://xiph.org/ogg/doc/framing.html] 97 * 98 * libogg Memory Management 99 * =========================================================================== 100 * 101 * libOgg's memory management is documented in code, not in headers or external 102 * documentation. What follows is not an attempt to completely document it, but 103 * an explanation of the basics. 104 * 105 * libOgg has two data structures which allocate and manage data buffers: The 106 * ogg_sync_state structure and the ogg_stream_state structure. The remaining 107 * structures of ogg_page and ogg_packet are views into the buffers managed by 108 * the previous structures. 109 * 110 * ogg_sync_state is used for reading purposes. It takes a physical bitstream 111 * and searches for, validates, and returns complete Ogg Pages. The 112 * ogg_sync_state buffers the returned page data, holding at most one 113 * complete page at a time. A returned Ogg page remains valid until any 114 * operation other than ogg_sync_check() is called. 115 * 116 * ogg_stream_state is used for both reading and writing. For reading, the 117 * contents of an ogg_page is copied into the stream state. This data is 118 * buffered to be split or joined as necessary into complete ogg_packets. If, 119 * after copying an ogg_page into an ogg_stream_state, packets are available to 120 * be read, then all of those packets remain in memory and valid until either 121 * the ogg_stream_state is reset, destroyed, or a new ogg_page is read into it. 122 * As the maximum number of packets an Ogg Page may contain is 255, at most 255 123 * packets may be available from an ogg_stream_state at one time. 124 * 125 * For writing, the life cycle of a buffer pointed to by a ogg_packet is the 126 * responsibility of the caller. Packets written into an ogg_stream_state are 127 * buffered until a complete page is ready for writing. Pages for writing out 128 * remain in the ogg_stream_state's buffer and valid until either the 129 * ogg_stream_state is reset, cleared, destroyed. Writing another packet into 130 * the ogg_stream_state might also invalidate such pages, but writing in 131 * packets when a page is ready to be written out is a caller bug anyways. 132 */ 133 134/*----------------------------------------------------------------------------------------------- 135** Private function prototypes. 136*/ 137 138static int ogg_close (SF_PRIVATE *psf) ; 139static int ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ; 140static int ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ; 141static uint64_t ogg_page_search_do_rescale (uint64_t x, uint64_t from, uint64_t to) ; 142static void ogg_page_search_continued_data (OGG_PRIVATE *odata, ogg_page *page) ; 143 144/*----------------------------------------------------------------------------------------------- 145** Exported functions. 146*/ 147 148int 149ogg_read_first_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) 150{ int ret ; 151 char *buffer ; 152 153 /* 154 ** The ogg standard requires that the first pages of a physical ogg 155 ** bitstream be only the first pages of each logical bitstream. These 156 ** pages MUST have the Beginning-Of-Stream bit set, and must contain 157 ** only the stream's relevant header. Currently we only load the first 158 ** page and check that it contains a codec we support as supporting 159 ** multiplexed streams (video+audio(en)+audio(fs)+subtitles, etc) is 160 ** beyond the scope of this library. 161 */ 162 163 ret = ogg_sync_fseek (psf, psf->header.indx, SEEK_SET) ; 164 if (ret < 0) 165 return SFE_NOT_SEEKABLE ; 166 167 buffer = ogg_sync_buffer (&odata->osync, psf->header.indx) ; 168 if (buffer == NULL) 169 return SFE_MALLOC_FAILED ; 170 memcpy (buffer, psf->header.ptr, psf->header.indx) ; 171 ogg_sync_wrote (&odata->osync, psf->header.indx) ; 172 173 ret = ogg_sync_next_page (psf, &odata->opage, SF_MAX ((sf_count_t) 0, 4096 - psf->header.indx), NULL) ; 174 175 /* Have we simply run out of data? If so, we're done. */ 176 if (ret == 0) 177 return 0 ; 178 if (ret < 0) 179 return psf->error ; 180 181 if (!ogg_page_bos (&odata->opage)) 182 { /* 183 ** Error case. Either must not be an Ogg bitstream, or is in the 184 ** middle of a bitstream (live capture), or in the middle of a 185 ** bitstream and no complete page was in the buffer. 186 */ 187 psf_log_printf (psf, "Input does not appear to be the start of an Ogg bitstream.\n") ; 188 return SFE_MALFORMED_FILE ; 189 } ; 190 191 /* 192 ** Get the serial number and set up the rest of decode. 193 ** Serialno first ; use it to set up a logical stream. 194 */ 195 ogg_stream_reset_serialno (&odata->ostream, ogg_page_serialno (&odata->opage)) ; 196 197 if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0) 198 { /* Error ; stream version mismatch perhaps. */ 199 psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ; 200 return SFE_MALFORMED_FILE ; 201 } ; 202 203 if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1) 204 { /* No page? */ 205 psf_log_printf (psf, "Error reading initial header page packet.\n") ; 206 return SFE_MALFORMED_FILE ; 207 } ; 208 209 return 0 ; 210} /* ogg_read_first_page */ 211 212int 213ogg_write_page (SF_PRIVATE *psf, ogg_page *page) 214{ int bytes ; 215 216 bytes = psf_fwrite (page->header, 1, page->header_len, psf) ; 217 bytes += psf_fwrite (page->body, 1, page->body_len, psf) ; 218 219 return bytes == page->header_len + page->body_len ; 220} /* ogg_write_page */ 221 222sf_count_t 223ogg_sync_ftell (SF_PRIVATE *psf) 224{ OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ; 225 sf_count_t position ; 226 227 position = psf_ftell (psf) ; 228 if (position >= 0) 229 { /* success */ 230 if (position < odata->osync.fill) 231 { /* Really, this should be an assert. */ 232 psf->error = SFE_INTERNAL ; 233 return -1 ; 234 } 235 position += (sf_count_t) (odata->osync.returned - odata->osync.fill) ; 236 } 237 238 return position ; 239} /* ogg_sync_ftell */ 240 241sf_count_t 242ogg_sync_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) 243{ OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ; 244 sf_count_t ret ; 245 246 ret = psf_fseek (psf, offset, whence) ; 247 if (ret >= 0) 248 { /* success */ 249 odata->eos = 0 ; 250 ogg_sync_reset (&odata->osync) ; 251 } 252 253 return ret ; 254} /* ogg_sync_fseek */ 255 256int 257ogg_sync_next_page (SF_PRIVATE * psf, ogg_page *og, sf_count_t readmax, sf_count_t *offset) 258{ OGG_PRIVATE* odata = (OGG_PRIVATE *) psf->container_data ; 259 sf_count_t position, nb_read, read_ret ; 260 unsigned char *buffer ; 261 int synced ; 262 int report_hole = 0 ; 263 264 for (position = 0 ; readmax <= 0 || readmax > position ; ) 265 { synced = ogg_sync_pageseek (&odata->osync, og) ; 266 if (synced < 0) 267 { /* 268 ** Skipped -synced bytes before finding the start of a page. 269 ** If seeking, we have just landed in the middle of a page. 270 ** Otherwise, warn about junk in the bitstream. 271 ** Page might not yet be ready, hence the continue. 272 */ 273 if (!offset) 274 report_hole = 1 ; 275 position -= synced ; 276 continue ; 277 } ; 278 279 if (report_hole) 280 { psf_log_printf (psf, "Ogg : Skipped %d bytes looking for the next page. Corrupted bitstream?!\n", position) ; 281 report_hole = 0 ; 282 } ; 283 284 if (synced > 0) 285 { /* Have a page */ 286 if (offset) 287 *offset += position ; 288 return og->header_len + og->body_len ; 289 } ; 290 291 /* 292 ** Else readmax == 0, Out of data. Try to read more in without 293 ** invalidating our boundary (readmax) constraint. 294 */ 295 if (readmax == 0) 296 return 0 ; 297 if (readmax > 0) 298 nb_read = SF_MIN ((sf_count_t) OGG_SYNC_READ_SIZE, readmax - position) ; 299 else 300 nb_read = OGG_SYNC_READ_SIZE ; 301 buffer = (unsigned char *) ogg_sync_buffer (&odata->osync, nb_read) ; 302 if (buffer == NULL) 303 { psf->error = SFE_MALLOC_FAILED ; 304 return -1 ; 305 } 306 read_ret = psf_fread (buffer, 1, nb_read, psf) ; 307 if (read_ret == 0) 308 return psf->error ? -1 : 0 ; 309 ogg_sync_wrote (&odata->osync, read_ret) ; 310 } ; 311 return 0 ; 312} /* ogg_sync_next_page */ 313 314int 315ogg_stream_next_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) 316{ int nn ; 317 318 if (odata->eos) 319 return 0 ; 320 321 for ( ; ; ) 322 { nn = ogg_sync_next_page (psf, &odata->opage, -1, NULL) ; 323 if (nn == 0) 324 { psf_log_printf (psf, "Ogg : File ended unexpectedly without an End-Of-Stream flag set.\n") ; 325 odata->eos = 1 ; 326 } 327 if (nn <= 0) 328 return nn ; 329 330 if (ogg_page_serialno (&odata->opage) == odata->ostream.serialno) 331 break ; 332 } ; 333 334 if (ogg_page_eos (&odata->opage)) 335 odata->eos = 1 ; 336 337 if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0) 338 { psf->error = SFE_INTERNAL ; 339 return -1 ; 340 } 341 342 return 1 ; 343} /* ogg_stream_next_page */ 344 345int 346ogg_stream_unpack_page (SF_PRIVATE *psf, OGG_PRIVATE *odata) 347{ int nn ; 348 int i ; 349 int found_hole = 0 ; 350 ogg_packet *ppkt = odata->pkt ; 351 352 odata->pkt_indx = 0 ; 353 nn = ogg_stream_packetout (&odata->ostream, ppkt) ; 354 if (nn == 0) 355 { /* 356 ** Steam is out of packets. Read in more pages until there is one, or 357 ** the stream ends, or an error occurs. 358 */ 359 for ( ; nn == 0 ; nn = ogg_stream_packetout (&odata->ostream, ppkt)) 360 { nn = ogg_stream_next_page (psf, odata) ; 361 if (nn <= 0) 362 { odata->pkt_len = 0 ; 363 return nn ; 364 } 365 } 366 /* 367 ** In the case of the for loop exiting because 368 ** ogg_stream_packetout() == -1, fall-through. 369 */ 370 } 371 372 if (nn == -1) 373 { /* 374 ** libOgg found a hole. That is, the next packet found was out of 375 ** sequence. As such, "flush" the hole marker by removing the invalid 376 ** packet, as the valid packets are queued behind it. 377 */ 378 psf_log_printf (psf, "Ogg : Warning, libogg reports a hole at %d bytes.\n", ogg_sync_ftell (psf)) ; 379 nn = ogg_stream_packetout (&odata->ostream, ppkt) ; 380 found_hole = 1 ; 381 } 382 383 /* 384 ** Unpack all the packets on the page. It is undocumented (like much of 385 ** libOgg behavior) but all packets from a page read into the stream are 386 ** guarenteed to remain valid in memory until a new page is read into the 387 ** stream. 388 */ 389 for (i = 1 ; ; i++) 390 { /* Not an off-by-one, there are 255 not 256 packets max. */ 391 if (i == 255) 392 { if (ogg_stream_packetpeek (&odata->ostream, NULL) == 1) 393 { psf->error = SFE_INTERNAL ; 394 return -1 ; 395 } 396 break ; 397 } 398 if (ogg_stream_packetout (&odata->ostream, ++ ppkt) != 1) 399 break ; 400 } 401 odata->pkt_len = i ; 402 403 /* 1 = ok, 2 = ok, and found a hole. */ 404 return 1 + found_hole ; 405} /* ogg_stream_unpack_page */ 406 407sf_count_t 408ogg_sync_last_page_before (SF_PRIVATE *psf, OGG_PRIVATE *odata, uint64_t *gp_out, sf_count_t offset, int32_t serialno) 409{ sf_count_t begin, end, original_end, chunk_size, ret ; 410 sf_count_t position = 0 ; 411 uint64_t gp = -1 ; 412 int left_link ; 413 414 /* Based on code from Xiph.org's Opusfile */ 415 416 original_end = end = begin = offset ; 417 offset = -1 ; 418 chunk_size = OGG_CHUNK_SIZE ; 419 do 420 { begin = SF_MAX (begin - chunk_size, (sf_count_t) 0) ; 421 position = ogg_sync_fseek (psf, begin, SEEK_SET) ; 422 if (position < 0) 423 return position ; 424 left_link = 0 ; 425 while (position < end) 426 { ret = ogg_sync_next_page (psf, &odata->opage, end - position, &position) ; 427 if (ret <= 0) 428 return -1 ; 429 if (ogg_page_serialno (&odata->opage) == serialno) 430 { uint64_t page_gp = ogg_page_granulepos (&odata->opage) ; 431 if (page_gp != (uint64_t) -1) 432 { offset = position ; 433 gp = page_gp ; 434 } 435 } 436 else 437 left_link = 1 ; 438 position += ret ; 439 } 440 441 if ((left_link || !begin) && offset < 0) 442 { psf->error = SFE_MALFORMED_FILE ; 443 return -1 ; 444 } 445 446 chunk_size = SF_MIN (2 * chunk_size, (sf_count_t) OGG_CHUNK_SIZE_MAX) ; 447 end = SF_MIN (begin + OGG_PAGE_SIZE_MAX - 1, original_end) ; 448 } 449 while (offset < 0) ; 450 451 *gp_out = gp ; 452 return offset ; 453} /* ogg_sync_last_page_before */ 454 455int 456ogg_stream_seek_page_search (SF_PRIVATE *psf, OGG_PRIVATE *odata, 457 uint64_t target_gp, uint64_t pcm_start, uint64_t pcm_end, uint64_t *best_gp, 458 sf_count_t begin, sf_count_t end, uint64_t gp_rate) 459{ ogg_page page ; 460 uint64_t gp ; 461 sf_count_t d0, d1, d2 ; 462 sf_count_t best ; 463 sf_count_t best_start ; 464 sf_count_t boundary ; 465 sf_count_t next_boundary ; 466 sf_count_t page_offset = -1 ; 467 sf_count_t seek_pos = -1 ; 468 sf_count_t bisect ; 469 sf_count_t chunk_size ; 470 int buffering = SF_FALSE ; 471 int force_bisect = SF_FALSE ; 472 int ret ; 473 int has_packets ; 474 475 *best_gp = pcm_start ; 476 best = best_start = begin ; 477 boundary = end ; 478 479 ogg_stream_reset_serialno (&odata->ostream, odata->ostream.serialno) ; 480 481 /* 482 ** This code is based on op_pcm_seek_page() from Opusfile, which is in turn 483 ** based on "new search algorithm by Nicholas Vinen" from libvorbisfile. 484 */ 485 486 d2 = d1 = d0 = end - begin ; 487 while (begin < end) 488 { /* 489 ** Figure out if and where to try and seek in the file. 490 */ 491 if (end - begin < OGG_CHUNK_SIZE) 492 bisect = begin ; 493 else 494 { /* Update the interval size history */ 495 d0 = d1 >> 1 ; 496 d1 = d2 >> 1 ; 497 d2 = (end - begin) >> 1 ; 498 if (force_bisect == SF_TRUE) 499 bisect = begin + ((end - begin) >> 1) ; 500 else 501 { /* Take a decent guess. */ 502 bisect = begin + ogg_page_search_do_rescale (target_gp - pcm_start, pcm_end - pcm_start, end - begin) ; 503 } 504 if (bisect - OGG_CHUNK_SIZE < begin) 505 bisect = begin ; 506 else 507 bisect -= OGG_CHUNK_SIZE ; 508 force_bisect = SF_FALSE ; 509 } 510 511 /* 512 ** Avoid an actual fseek if we can (common for final iterations.) 513 */ 514 if (seek_pos != bisect) 515 { if (buffering == SF_TRUE) 516 ogg_stream_reset (&odata->ostream) ; 517 buffering = SF_FALSE ; 518 page_offset = -1 ; 519 seek_pos = ogg_sync_fseek (psf, bisect, SEEK_SET) ; 520 if (seek_pos < 0) 521 return seek_pos ; 522 } 523 524 chunk_size = OGG_CHUNK_SIZE ; 525 next_boundary = boundary ; 526 527 /* 528 ** Scan forward, figure out where we landed. 529 ** The ideal case is we see a page that ends before our target followed 530 ** by a page that ends after our target. 531 ** If we are too far before or after, breaking out will bisect what we 532 ** have found so far. 533 */ 534 while (begin < end) 535 { ret = ogg_sync_next_page (psf, &page, boundary - seek_pos, &seek_pos) ; 536 if (ret <= 0) 537 return ret ; 538 page_offset = seek_pos ; 539 if (ret == 0) 540 { /* 541 ** There are no more pages in this interval from our stream 542 ** with a granulepos less than our target. 543 */ 544 if (bisect <= begin + 1) 545 { /* Scanned the whole interval, so we are done. */ 546 end = begin ; 547 } 548 else 549 { /* 550 ** Otherwise, back up one chunk. First discard any data 551 ** from a continued packet. 552 */ 553 if (buffering) 554 ogg_stream_reset (&odata->ostream) ; 555 buffering = SF_FALSE ; 556 bisect = SF_MAX (bisect - chunk_size, begin) ; 557 seek_pos = ogg_sync_fseek (psf, bisect, SEEK_SET) ; 558 if (seek_pos < 0) 559 return seek_pos ; 560 /* Bump up the chunk size. */ 561 chunk_size = SF_MIN (2 * chunk_size, (sf_count_t) OGG_CHUNK_SIZE_MAX) ; 562 /* 563 ** If we did find a page from another stream or without a 564 ** timestamp, don't read past it. 565 */ 566 boundary = next_boundary ; 567 } 568 continue ; 569 } 570 571 /* Found a page. Advance seek_pos past it */ 572 seek_pos += page.header_len + page.body_len ; 573 /* 574 ** Save the offset of the first page we found after the seek, 575 ** regardless of the stream it came from or whether or not it has a 576 ** timestamp. 577 */ 578 next_boundary = SF_MIN (page_offset, next_boundary) ; 579 580 /* If not from our stream, continue. */ 581 if (odata->ostream.serialno != ogg_page_serialno (&page)) 582 continue ; 583 584 /* 585 ** The Ogg spec says that a page with a granule pos of -1 must not 586 ** contain and packets which complete, but the lack of biconditional 587 ** wording means that /technically/ a packet which does not complete 588 ** any packets can have a granule pos other than -1. To make matters 589 ** worse, older versions of libogg did just that. 590 */ 591 has_packets = ogg_page_packets (&page) > 0 ; 592 gp = has_packets ? ogg_page_granulepos (&page) : -1 ; 593 if (gp == (uint64_t) -1) 594 { if (buffering == SF_TRUE) 595 { if (!has_packets) 596 ogg_stream_pagein (&odata->ostream, &page) ; 597 else 598 { /* 599 ** If packets did end on this page, but we still didn't 600 ** have a valid granule position (in violation of the 601 ** spec!), stop buffering continued packet data. 602 ** Otherwise we might continue past the packet we 603 ** actually wanted. 604 */ 605 ogg_stream_reset (&odata->ostream) ; 606 buffering = SF_FALSE ; 607 } 608 } 609 continue ; 610 } 611 612 if (gp < target_gp) 613 { /* 614 ** We found a page that ends before our target. Advance to 615 ** the raw offset of the next page. 616 */ 617 begin = seek_pos ; 618 if (pcm_start > gp || pcm_end < gp) 619 break ; 620 /* Save the byte offset of after this page. */ 621 best = best_start = begin ; 622 if (buffering) 623 ogg_stream_reset (&odata->ostream) ; 624 /* Check to see if the last packet continues. */ 625 if (ogg_page_continues (&page)) 626 { ogg_page_search_continued_data (odata, &page) ; 627 /* 628 ** If we have a continued packet, remember the offset of 629 ** this page's start, so that if we do wind up having to 630 ** seek back here later, we can prime the stream with the 631 ** continued packet data. With no continued packet, we 632 ** remember the end of the page. 633 */ 634 best_start = page_offset ; 635 /* 636 ** Then force buffering on, so that if a packet starts (but 637 ** does not end) on the next page, we still avoid the extra 638 ** seek back. 639 */ 640 buffering = SF_TRUE ; 641 } ; 642 *best_gp = pcm_start = gp ; 643 if (target_gp - gp > gp_rate) 644 { /* Out by over a second. Try another bisection. */ 645 break ; 646 } 647 /* Otherwise, keep scanning forward (do NOT use begin+1). */ 648 bisect = begin ; 649 } 650 else 651 { /* 652 ** Found a page that ends after our target. If we had just 653 ** scanned the whole interval before we found it, we're good. 654 */ 655 if (bisect <= begin + 1) 656 end = begin ; 657 else 658 { end = bisect ; 659 /* 660 ** In later iterations, don't read past the first page we 661 ** found. 662 */ 663 boundary = next_boundary ; 664 /* 665 ** If we're not making much progress shrinking the interval 666 ** size, start forcing straight bisection to limit the 667 ** worst case. 668 */ 669 force_bisect = end - begin > d0 * 2 ? SF_TRUE : SF_FALSE ; 670 /* 671 ** Don't let pcm_end get out of range! That could happen 672 ** with an invalid timestamp. 673 */ 674 if (pcm_end > gp && pcm_start <= gp) 675 pcm_end = gp ; 676 } 677 break ; 678 } 679 } 680 } 681 682 /* 683 ** If we are buffering, the page we want is currently buffered in the 684 ** Ogg stream structure, or in the Ogg page which has not been submitted. 685 ** If not, we need to seek back and load it again. 686 */ 687 if (buffering == SF_FALSE) 688 { if (best_start != page_offset) 689 { page_offset = -1 ; 690 seek_pos = ogg_sync_fseek (psf, best_start, SEEK_SET) ; 691 if (seek_pos < 0) 692 return seek_pos ; 693 } 694 if (best_start < best) 695 { if (page_offset < 0) 696 { ret = ogg_sync_next_page (psf, &page, -1, &seek_pos) ; 697 if (seek_pos != best_start) 698 return -1 ; 699 } 700 ogg_page_search_continued_data (odata, &page) ; 701 page_offset = -1 ; 702 } 703 } ; 704 705 if (page_offset >= 0) 706 ogg_stream_pagein (&odata->ostream, &page) ; 707 708 return 0 ; 709} /* ogg_stream_seek_page_search */ 710 711int 712ogg_open (SF_PRIVATE *psf) 713{ OGG_PRIVATE* odata = calloc (1, sizeof (OGG_PRIVATE)) ; 714 sf_count_t pos = psf_ftell (psf) ; 715 int error = 0 ; 716 717 psf->container_data = odata ; 718 psf->container_close = ogg_close ; 719 720 if (psf->file.mode == SFM_RDWR) 721 return SFE_BAD_MODE_RW ; 722 723 if (psf->file.mode == SFM_READ) 724 if ((error = ogg_stream_classify (psf, odata)) != 0) 725 return error ; 726 727 if (SF_ENDIAN (psf->sf.format) != 0) 728 return SFE_BAD_ENDIAN ; 729 730 switch (psf->sf.format) 731 { case SF_FORMAT_OGG | SF_FORMAT_VORBIS : 732 return ogg_vorbis_open (psf) ; 733 734 case SF_FORMAT_OGGFLAC : 735 /* Reset everything to an initial state. */ 736 ogg_sync_clear (&odata->osync) ; 737 ogg_stream_clear (&odata->ostream) ; 738 psf_fseek (psf, pos, SEEK_SET) ; 739 free (psf->container_data) ; 740 psf->container_data = NULL ; 741 psf->container_close = NULL ; 742 return flac_open (psf) ; 743 744 case SF_FORMAT_OGG | SF_FORMAT_OPUS : 745 return ogg_opus_open (psf) ; 746 747#if ENABLE_EXPERIMENTAL_CODE 748 case SF_FORMAT_OGG | SF_FORMAT_SPEEX : 749 return ogg_speex_open (psf) ; 750 751 case SF_FORMAT_OGG | SF_FORMAT_PCM_16 : 752 case SF_FORMAT_OGG | SF_FORMAT_PCM_24 : 753 return ogg_pcm_open (psf) ; 754#endif 755 756 default : 757 break ; 758 } ; 759 760 psf_log_printf (psf, "%s : bad psf->sf.format 0x%x.\n", __func__, psf->sf.format) ; 761 return SFE_INTERNAL ; 762} /* ogg_open */ 763 764/*============================================================================== 765** Private functions. 766*/ 767 768static int 769ogg_close (SF_PRIVATE *psf) 770{ OGG_PRIVATE* odata = psf->container_data ; 771 772 ogg_sync_clear (&odata->osync) ; 773 ogg_stream_clear (&odata->ostream) ; 774 775 return 0 ; 776} /* ogg_close */ 777 778static int 779ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata) 780{ int error ; 781 782 /* Call this here so it only gets called once, so no memory is leaked. */ 783 ogg_sync_init (&odata->osync) ; 784 ogg_stream_init (&odata->ostream, 0) ; 785 786 /* Load the first page in the physical bitstream. */ 787 if ((error = ogg_read_first_page (psf, odata)) != 0) 788 return error ; 789 790 odata->codec = ogg_page_classify (psf, &odata->opage) ; 791 792 switch (odata->codec) 793 { case OGG_VORBIS : 794 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ; 795 return 0 ; 796 797 case OGG_FLAC : 798 case OGG_FLAC0 : 799 psf->sf.format = SF_FORMAT_OGGFLAC ; 800 return 0 ; 801 802 case OGG_SPEEX : 803 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ; 804 return 0 ; 805 806 case OGG_OPUS : 807 psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_OPUS ; 808 return 0 ; 809 810 case OGG_PCM : 811 psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ; 812 return SFE_UNIMPLEMENTED ; 813 814 default : 815 break ; 816 } ; 817 818 psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ; 819 return SFE_UNIMPLEMENTED ; 820} /* ogg_stream_classify */ 821 822/*============================================================================== 823*/ 824 825static struct 826{ const char *str, *name ; 827 int len, codec ; 828} codec_lookup [] = 829{ { "Annodex", "Annodex", 8, OGG_ANNODEX }, 830 { "AnxData", "AnxData", 7, OGG_ANXDATA }, 831 { "\177FLAC", "Flac1", 5, OGG_FLAC }, 832 { "fLaC", "Flac0", 4, OGG_FLAC0 }, 833 { "PCM ", "PCM", 8, OGG_PCM }, 834 { "Speex", "Speex", 5, OGG_SPEEX }, 835 { "\001vorbis", "Vorbis", 7, OGG_VORBIS }, 836 { "OpusHead", "Opus", 8, OGG_OPUS }, 837} ; 838 839static int 840ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) 841{ int k, len ; 842 843 for (k = 0 ; k < ARRAY_LEN (codec_lookup) ; k++) 844 { if (codec_lookup [k].len > og->body_len) 845 continue ; 846 847 if (memcmp (og->body, codec_lookup [k].str, codec_lookup [k].len) == 0) 848 { psf_log_printf (psf, "Ogg stream data : %s\n", codec_lookup [k].name) ; 849 psf_log_printf (psf, "Stream serialno : %u\n", (uint32_t) ogg_page_serialno (og)) ; 850 return codec_lookup [k].codec ; 851 } ; 852 } ; 853 854 len = og->body_len < 8 ? og->body_len : 8 ; 855 856 psf_log_printf (psf, "Ogg_stream data : '") ; 857 for (k = 0 ; k < len ; k++) 858 psf_log_printf (psf, "%c", isprint (og->body [k]) ? og->body [k] : '.') ; 859 psf_log_printf (psf, "' ") ; 860 for (k = 0 ; k < len ; k++) 861 psf_log_printf (psf, " %02x", og->body [k] & 0xff) ; 862 psf_log_printf (psf, "\n") ; 863 864 return 0 ; 865} /* ogg_page_classify */ 866 867/* 868** Scale x from the range [0, from] to the range [0, to] 869*/ 870static uint64_t 871ogg_page_search_do_rescale (uint64_t x, uint64_t from, uint64_t to) 872{ uint64_t frac ; 873 uint64_t ret ; 874 int i ; 875 876 /* I should have paid more attention in CSc 349A: Numerical Analysis */ 877 if (x >= from) 878 return to ; 879 if (x == 0) 880 return 0 ; 881 frac = 0 ; 882 for (i = 0 ; i < 63 ; i++) 883 { frac <<= 1 ; 884 if (x >= from >> 1) 885 { x -= from - x ; 886 frac |= 1 ; 887 } 888 else 889 x <<= 1 ; 890 } 891 ret = 0 ; 892 for (i = 0 ; i < 63 ; i++) 893 { if (frac & 1) 894 ret = (ret & to & 1) + (ret >> 1) + (to >> 1) ; 895 else 896 ret >>= 1 ; 897 frac >>= 1 ; 898 } 899 return ret ; 900} /* ogg_page_search_do_rescale */ 901 902static void 903ogg_page_search_continued_data (OGG_PRIVATE *odata, ogg_page *page) 904{ ogg_stream_pagein (&odata->ostream, page) ; 905 while (ogg_stream_packetout (&odata->ostream, &odata->opacket)) ; 906} /* ogg_page_search_continued_data */ 907 908#else /* HAVE_EXTERNAL_XIPH_LIBS */ 909 910int 911ogg_open (SF_PRIVATE *psf) 912{ 913 psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Vorbis support.\n") ; 914 return SFE_UNIMPLEMENTED ; 915} /* ogg_open */ 916 917#endif 918