1. 19 May, 2017 3 commits
    • Timothy B. Terriberry's avatar
      Harmonize op_raw_total() and op_raw_seek() · 37f83754
      Timothy B. Terriberry authored
      op_raw_seek() will fail if you try to seek to a byte position
       beyond the end of the file.
      However, the "end" is defined in terms of _of->end, which is
       specifically the end of the last Ogg page found in the underlying
       source (excluding any trailing non-Ogg data).
      op_raw_total(_of,-1) returns the total size of the stream by using
       _of->end, but it was also subtracting the offset of the first Opus
       page in the first link.
      Since there might have been other Ogg streams concurrently
       multiplexed with the first Opus stream whose BOS pages appear
       first, or there might simply be non-Ogg junk at the start, that
       left the caller with no way to determine the valid range of byte
       offsets that could be passed to op_raw_seek().
      Instead, make op_raw_total() pretend the first link starts at
       offset 0, and explicitly document that it's what defines the range
       of valid values to op_raw_seek().
      This is how our own seeking_example.c was using it, anyway.
    • Timothy B. Terriberry's avatar
      Improve handling of holes (corrupt pages). · fd65b94f
      Timothy B. Terriberry authored
      Previously, when we encountered a hole (a gap in the page sequence
       numbers), we would save off all of the packets from the first page
       after the hole, but not timestamp them.
      That meant when they were actually decoded, op_pcm_tell() would
       report a timestamp of 0 until reaching the last packet on that
      Instead, handle holes just like a raw seek.
      We reset the granule position tracking, and attempt to timestamp
       packets backwards from the end of the page.
      If the first page after the hole is an EOS page, we just throw it
       away (rather than risk playing invalid samples due to incorrect
      We also throw away the first 80 ms of audio after a hole, to allow
       the decoder state to reconverge.
      This patch also updates the example to report the hole and
       continue decoding, rather than immediately stopping when a hole is
       encountered, in order to test the above features.
    • Timothy B. Terriberry's avatar
      Avoid operations linear in the number of links. · f83675eb
      Timothy B. Terriberry authored
      Just in case some bozo makes a chained stream with 272,389 links
       with 16 samples in each (coded at 16 Mbps, including overheads).
      This avoids quadratic behavior for simple straight-through
       playback: we no longer do a linear search on each chain boundary
       or each call to op_pcm_tell().
      N seeks with M chains still requires O(N*log(M)) work.
  2. 10 Mar, 2017 1 commit
  3. 16 Sep, 2016 1 commit
    • Timothy B. Terriberry's avatar
      Fix MSVC warnings. · d0c82543
      Timothy B. Terriberry authored
      Some of these pointed to real potential overflows (given arbitrary
       inputs by the calling application).
      I was sad about stripping const qualifiers from the struct addrinfo
       pointers, but MSVC seems to erroneously think that an array of
       pointers to constant data is itself a pointer to constant data (or
       maybe that it is not compatible with a const void *?), and
       converting the memmove()s to for loops triggered an erroneous
       warning about out-of-bounds array accesses in gcc (but on only one
       of the two identical loops).
  4. 04 Jul, 2016 3 commits
    • Timothy B. Terriberry's avatar
      Fix skipping logic for multiplexed non-Opus pages. · 78cd9bcf
      Timothy B. Terriberry authored
      This bug appears to have been present since the original code
      This was a "clever" rearrangement of the control flow from the
       _fetch_and_process_packet() in vorbisfile to use a do ... while(0)
       instead of a "while(1)".
      However, this also makes "continue" equivalent to "break": it does
       not actually go back to the top of the loop, because the loop
       condition is false.
      This bug was harmless, because ogg_stream_pagein() then refuses to
       ingest a page with the wrong serialno, but we can simplify things
       by fixing it.
      The "not strictly necessary" loop is now completely unnecessary.
      The extra checks that existed in vorbisfile have all been moved to
       later in the main loop, so we can just continue that one directly,
       with no wasted work, instead of embedding a smaller loop inside.
      Fixes Coverity CID 149875.
    • Timothy B. Terriberry's avatar
      Note small inaccuracy in bitrate tracking. · 73909d7d
      Timothy B. Terriberry authored
      In the non-seekable case, we'll undercount some bytes at the start
       of a new link.
      Still thinking about the best way to address this, but leaving a
       comment so I don't forget.
    • Timothy B. Terriberry's avatar
      Should a BOS page with no packets be an error? · 3abc3541
      Timothy B. Terriberry authored
      Going with "no" for now, but leave a reminder in the source code
       that this is a debatable question.
  5. 16 Jun, 2016 1 commit
  6. 29 Dec, 2015 1 commit
  7. 15 Dec, 2015 2 commits
    • Timothy B. Terriberry's avatar
      Buffer continued packet data to reduce seeking. · 661459b4
      Timothy B. Terriberry authored
      In commit 41c29626 I claimed that it was not worth the
       machinery to buffer an extra page to avoid a seek when we have
       continued packet data.
      That was a little unsatisfying, considering how much effort we make
       to avoid unnecessary seeking elsewhere, but in the general case,
       we might have to buffer an arbitrary number of pages, since a
       packet can span several.
      However, we already have the mechanism to do this buffering: the
      There are a number of potentially nasty corner-cases, but libogg's
       page sequence number tracking prevents us from accidentally gluing
       extraneous packet data onto some other unsuspecting packet, so I
       believe the chance of introducing new bugs here is manageable.
      This reduces the number of seeks in Simon Jackson's continued-page
       test case by over 23%.
      This also means we can handle pages without useful timestamps
       (including those multiplexed from another stream) between the last
       timestamped page at or before our target and the first timestamped
       page after our target without any additional seeks.
      Previously we would scan all of this data, see that the
       'page_offset' of the most recent page we read was way beyond
       'best' (the end of the last timestamped page before our target),
       and then seek back and scan it all again.
      This should greatly reduce the number of seeks we need in
       multiplexed streams, even if there are no continued packets.
    • Timothy B. Terriberry's avatar
      Fix timestamp check for seek-free seek. · 33d17971
      Timothy B. Terriberry authored
      We avoid seeking when the seek target lies within the packets
       buffered from the current page.
      However, the calculation of the page start time was _adding_ the
       first packet's duration to its end time, instead of subtracting
  8. 07 Dec, 2015 1 commit
  9. 06 Dec, 2015 2 commits
    • Timothy B. Terriberry's avatar
      Handle continued packets in bisection search. · 41c29626
      Timothy B. Terriberry authored
      If the packet where we wanted to start decoding was continued from
       a previous page, and _other_ packets ended on that previous page,
       we wouldn't feed the previous page to the ogg_stream_state.
      That meant we wouldn't get the packet we wanted, and would fail with
       OP_EBADLINK (because the starting PCM offset of the first packet we
       did decode would already be after the one we wanted).
      Instead, check for continued packet data and feed in an extra page
       to prime the stream state.
      Thanks to Simon Jackson for the report and the excellent test case.
    • Timothy B. Terriberry's avatar
  10. 26 Mar, 2014 1 commit
    • Timothy B. Terriberry's avatar
      Minor cleanups. · 6f482ef4
      Timothy B. Terriberry authored
      Makes style slightly more consistent.
      Also fixes the return code of op_fetch_headers() to make it
       consistently return OP_EBADHEADER if the stream runs out of pages
       after a valid OpusHead packet is found.
      Previously, if a valid OpusHead was found, it would return
       OP_ENOTFORMAT if it ran out of pages before finding one without
       its BOS flag set, and OP_EBADHEADER if it ran out of pages after
       finding one without its BOS flag set.
  11. 16 Mar, 2014 1 commit
  12. 12 Mar, 2014 1 commit
  13. 03 Sep, 2013 11 commits
    • Timothy B. Terriberry's avatar
      Fix a granpos calculation we assumed couldn't fail. · d6697905
      Timothy B. Terriberry authored
      It was only guaranteed to work in the seekable case.
      Thanks to Radio Stadtfilter 96.3Mhz for sending a stream which
       triggered this failure.
    • Timothy B. Terriberry's avatar
      %s/op_read_native_filter/op_filter_read_native/g · 2ab13b78
      Timothy B. Terriberry authored
      All the actual filters are named op_foo_filter(), so
       op_read_native_filter() looked like another one.
      Changing the word order should remove the ambiguity.
    • Timothy B. Terriberry's avatar
      Mark more internal pointers const. · e6e2b83b
      Timothy B. Terriberry authored
      Don't know if this actually leads to any better code generation,
       but it may make the code a little clearer.
    • Timothy B. Terriberry's avatar
      Mark a bunch of API functions const. · 23c8a83d
      Timothy B. Terriberry authored
      This makes it clear they don't modify the state, which is a useful
       indicator of what is safe to call from the application decode
    • Timothy B. Terriberry's avatar
      Minor simplification to end-trimming logic. · 4d75f855
      Timothy B. Terriberry authored
      This is a little easier to read, and allows us to save some
       subtractions and a comparison.
    • Timothy B. Terriberry's avatar
      Get rid of the op_float2short_filter() wrapper. · 80751579
      Timothy B. Terriberry authored
      The increasingly-inaccurately named op_shaped_dither16() can serve
       this role instead, without much additional complexity (perhaps
       less, once you consider the required shuffling around of the
       function parameters).
    • Timothy B. Terriberry's avatar
      Add an API to disable dithering. · 8396a1f8
      Timothy B. Terriberry authored
      This is to correspond to the feature in opus-tools's opusdec.
      opusdec itself probably won't be able to use it, because it still
       wants to do dithering after resampling, but the motivation for the
       feature is the same.
    • Timothy B. Terriberry's avatar
      Avoid clipping in short->float stereo downmixing. · a88a90f9
      Timothy B. Terriberry authored
      Previously I'd said this would require a large stack buffer, which
       was true if you simply wanted to re-use the existing
       op_short2float_filter() and floating-point op_stereo_filter().
      But the latter is not normally compiled for fixed-point anyway, so
       we can instead write new code that doesn't need the stack buffer
       without harming anything.
    • Timothy B. Terriberry's avatar
      Remove some OP_UNLIKELY macros. · 49233ebf
      Timothy B. Terriberry authored
      These were unlikely when I originally expected applications to
       normally provide a decode buffer in the right format of sufficient
      However, the decode filter API works by asking to decode into a
       0-byte buffer, which will trigger both of these tests on every
      Since this is how three of the four decoding APIs are implemented,
       this is not really that unlikely anymore.
    • Timothy B. Terriberry's avatar
      Minor decode control flow updates. · e0ab29d4
      Timothy B. Terriberry authored
      This makes op_fetch_and_process_page() always try to fetch another
       page, like it used to (and like its name implies).
      There was only one place where we needed the early return for
       unprocessed packets, and getting rid of that actually simplifies
       the logic there (replacing a conditional continue with an
       unconditional one in a slightly different location).
    • Timothy B. Terriberry's avatar
      Add an application decoding callback API. · 1b114a82
      Timothy B. Terriberry authored
      This is needed to allow advanced usage, like that of opusdec in
       opus-tools, which can simulate packet loss or save the range coder
       state for decoder verification.
      It could also be used in a pinch to use libopusfile for access to
       the raw Ogg packets, though this is somewhat of a hack.
  14. 24 Aug, 2013 1 commit
  15. 21 Aug, 2013 1 commit
  16. 15 Jul, 2013 2 commits
    • Timothy B. Terriberry's avatar
      Add a gain control API. · 7aea3cae
      Timothy B. Terriberry authored
      A new op_set_gain_offset() allows the application to provide its own
       offset to the current decoder gain setting, as well as specify what
       offsets should be applied.
      The header gain alone is still the default, but the application may
       also request that the track gain be applied, or that neither be
      In addition, an op_get_track_gain() function can parse the track
       gain out of a set of comment tags.
      This is mainly provided as a convenience for applications that need
       this information, so they don't have to write their own parser.
    • Timothy B. Terriberry's avatar
      Plug possible memory leak on stream open failure. · 68f18feb
      Timothy B. Terriberry authored
      Not all the failure paths cleaned up after themselves properly.
      Thanks to tangobravo for complaining about similar issues in
       libvorbisfile, which prompted me to audit this code.
  17. 28 Jun, 2013 1 commit
  18. 13 May, 2013 1 commit
    • Timothy B. Terriberry's avatar
      Move last few URL functions into http.c · 5e3c66ce
      Timothy B. Terriberry authored
      This makes it easier to split http.c and friends into their own
      This allows distributions to ship a libopusfile with generic Opus
       parsing support, and a libopusurl with http/https support.
      Keeping the latter in a separate library means that GPL
       applications don't have to link against the GPL-incompatible
       openssl, and distributions don't have to disable http support to
       allow GPL applications to use libopusfile.
  19. 08 May, 2013 1 commit
    • Timothy B. Terriberry's avatar
      Fix 255 packet assertion. · efc0d57a
      Timothy B. Terriberry authored
      If we actually have 255 packets on a page, this assertion always
       triggers, because ogg_stream_packetout doesn't fail until we ask
       for the _next_ packet.
  20. 07 May, 2013 1 commit
    • Timothy B. Terriberry's avatar
      Fix seeking near the start of saved live streams. · 2862e2ea
      Timothy B. Terriberry authored
      If a stream starts with a non-zero granpos, we would subtract 80 ms
       from the target time, and then report failure when the best page
       we could find (the first page in the link) had a granpos larger
       than that.
      This worked for normal streams because the subtraction would fail
       (granpos can't wrap past -1) and we checked for that.
  21. 30 Apr, 2013 1 commit
  22. 06 Apr, 2013 1 commit
    • Timothy B. Terriberry's avatar
      Small cleanups of the soft clipping code. · 7b499048
      Timothy B. Terriberry authored
      - Made OP_SOFT_CLIP defined only when using floating point (libopus
         handles clipping when using the fixed-point API).
      - Struct rearrangement for theoretically better packing on some
      - Reset the state tracking channel count when re-initializing a
         decoder (and not the dither mute, because that gets reset for
  23. 25 Mar, 2013 1 commit
    • Timothy B. Terriberry's avatar
      Use clipping prevention on 16-bit decode paths. · bf06c4f2
      Timothy B. Terriberry authored
      When we decode using libopus's fixed-point APIs, libopus internally
       applies soft clipping prevention.
      When we decode using libopus's floating-point APIs, this behavior
       is disabled.
      If we're ultimately planning to output the data to the user in
       fixed-point, we need to apply the clipping prevention ourselves.