1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
4  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7  *                                                                  *
8  * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2020           *
9  * by the Xiph.Org Foundation and contributors https://xiph.org/    *
10  *                                                                  *
11  ********************************************************************
12 
13  function: stdio-based convenience library for opening/seeking/decoding
14  last mod: $Id: vorbisfile.c 17573 2010-10-27 14:53:59Z xiphmont $
15 
16  ********************************************************************/
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20 
21 #include "internal.h"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <errno.h>
25 #include <limits.h>
26 #include <string.h>
27 #include <math.h>
28 
29 #include "opusfile.h"
30 
31 /*This implementation is largely based off of libvorbisfile.
32   All of the Ogg bits work roughly the same, though I have made some
33    "improvements" that have not been folded back there, yet.*/
34 
35 /*A 'chained bitstream' is an Ogg Opus bitstream that contains more than one
36    logical bitstream arranged end to end (the only form of Ogg multiplexing
37    supported by this library.
38   Grouping (parallel multiplexing) is not supported, except to the extent that
39    if there are multiple logical Ogg streams in a single link of the chain, we
40    will ignore all but the first Opus stream we find.*/
41 
42 /*An Ogg Opus file can be played beginning to end (streamed) without worrying
43    ahead of time about chaining (see opusdec from the opus-tools package).
44   If we have the whole file, however, and want random access
45    (seeking/scrubbing) or desire to know the total length/time of a file, we
46    need to account for the possibility of chaining.*/
47 
48 /*We can handle things a number of ways.
49   We can determine the entire bitstream structure right off the bat, or find
50    pieces on demand.
51   This library determines and caches structure for the entire bitstream, but
52    builds a virtual decoder on the fly when moving between links in the chain.*/
53 
54 /*There are also different ways to implement seeking.
55   Enough information exists in an Ogg bitstream to seek to sample-granularity
56    positions in the output.
57   Or, one can seek by picking some portion of the stream roughly in the desired
58    area if we only want coarse navigation through the stream.
59   We implement and expose both strategies.*/
60 
61 /*The maximum number of bytes in a page (including the page headers).*/
62 #define OP_PAGE_SIZE_MAX  (65307)
63 /*The default amount to seek backwards per step when trying to find the
64    previous page.
65   This must be at least as large as the maximum size of a page.*/
66 #define OP_CHUNK_SIZE     (65536)
67 /*The maximum amount to seek backwards per step when trying to find the
68    previous page.*/
69 #define OP_CHUNK_SIZE_MAX (1024*(opus_int32)1024)
70 /*A smaller read size is needed for low-rate streaming.*/
71 #define OP_READ_SIZE      (2048)
72 
op_test(OpusHead * _head,const unsigned char * _initial_data,size_t _initial_bytes)73 int op_test(OpusHead *_head,
74  const unsigned char *_initial_data,size_t _initial_bytes){
75   ogg_sync_state  oy;
76   char           *data;
77   int             err;
78   /*The first page of a normal Opus file will be at most 57 bytes (27 Ogg
79      page header bytes + 1 lacing value + 21 Opus header bytes + 8 channel
80      mapping bytes).
81     It will be at least 47 bytes (27 Ogg page header bytes + 1 lacing value +
82      19 Opus header bytes using channel mapping family 0).
83     If we don't have at least that much data, give up now.*/
84   if(_initial_bytes<47)return OP_FALSE;
85   /*Only proceed if we start with the magic OggS string.
86     This is to prevent us spending a lot of time allocating memory and looking
87      for Ogg pages in non-Ogg files.*/
88   if(memcmp(_initial_data,"OggS",4)!=0)return OP_ENOTFORMAT;
89   if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
90   ogg_sync_init(&oy);
91   data=ogg_sync_buffer(&oy,(long)_initial_bytes);
92   if(data!=NULL){
93     ogg_stream_state os;
94     ogg_page         og;
95     int              ret;
96     memcpy(data,_initial_data,_initial_bytes);
97     ogg_sync_wrote(&oy,(long)_initial_bytes);
98     ogg_stream_init(&os,-1);
99     err=OP_FALSE;
100     do{
101       ogg_packet op;
102       ret=ogg_sync_pageout(&oy,&og);
103       /*Ignore holes.*/
104       if(ret<0)continue;
105       /*Stop if we run out of data.*/
106       if(!ret)break;
107       ogg_stream_reset_serialno(&os,ogg_page_serialno(&og));
108       ogg_stream_pagein(&os,&og);
109       /*Only process the first packet on this page (if it's a BOS packet,
110          it's required to be the only one).*/
111       if(ogg_stream_packetout(&os,&op)==1){
112         if(op.b_o_s){
113           ret=opus_head_parse(_head,op.packet,op.bytes);
114           /*If this didn't look like Opus, keep going.*/
115           if(ret==OP_ENOTFORMAT)continue;
116           /*Otherwise we're done, one way or another.*/
117           err=ret;
118         }
119         /*We finished parsing the headers.
120           There is no Opus to be found.*/
121         else err=OP_ENOTFORMAT;
122       }
123     }
124     while(err==OP_FALSE);
125     ogg_stream_clear(&os);
126   }
127   else err=OP_EFAULT;
128   ogg_sync_clear(&oy);
129   return err;
130 }
131 
132 /*Many, many internal helpers.
133   The intention is not to be confusing.
134   Rampant duplication and monolithic function implementation (though we do have
135    some large, omnibus functions still) would be harder to understand anyway.
136   The high level functions are last.
137   Begin grokking near the end of the file if you prefer to read things
138    top-down.*/
139 
140 /*The read/seek functions track absolute position within the stream.*/
141 
142 /*Read a little more data from the file/pipe into the ogg_sync framer.
143   _nbytes: The maximum number of bytes to read.
144   Return: A positive number of bytes read on success, 0 on end-of-file, or a
145            negative value on failure.*/
op_get_data(OggOpusFile * _of,int _nbytes)146 static int op_get_data(OggOpusFile *_of,int _nbytes){
147   unsigned char *buffer;
148   int            nbytes;
149   OP_ASSERT(_nbytes>0);
150   buffer=(unsigned char *)ogg_sync_buffer(&_of->oy,_nbytes);
151   nbytes=(int)(*_of->callbacks.read)(_of->stream,buffer,_nbytes);
152   OP_ASSERT(nbytes<=_nbytes);
153   if(OP_LIKELY(nbytes>0))ogg_sync_wrote(&_of->oy,nbytes);
154   return nbytes;
155 }
156 
157 /*Save a tiny smidge of verbosity to make the code more readable.*/
op_seek_helper(OggOpusFile * _of,opus_int64 _offset)158 static int op_seek_helper(OggOpusFile *_of,opus_int64 _offset){
159   if(_offset==_of->offset)return 0;
160   if(_of->callbacks.seek==NULL
161    ||(*_of->callbacks.seek)(_of->stream,_offset,SEEK_SET)){
162     return OP_EREAD;
163   }
164   _of->offset=_offset;
165   ogg_sync_reset(&_of->oy);
166   return 0;
167 }
168 
169 /*Get the current position indicator of the underlying stream.
170   This should be the same as the value reported by tell().*/
op_position(const OggOpusFile * _of)171 static opus_int64 op_position(const OggOpusFile *_of){
172   /*The current position indicator is _not_ simply offset.
173     We may also have unprocessed, buffered data in the sync state.*/
174   return _of->offset+_of->oy.fill-_of->oy.returned;
175 }
176 
177 /*From the head of the stream, get the next page.
178   _boundary specifies if the function is allowed to fetch more data from the
179    stream (and how much) or only use internally buffered data.
180   _boundary: -1: Unbounded search.
181               0: Read no additional data.
182                  Use only cached data.
183               n: Search for the start of a new page up to file position n.
184   Return: n>=0:       Found a page at absolute offset n.
185           OP_FALSE:   Hit the _boundary limit.
186           OP_EREAD:   An underlying read operation failed.
187           OP_BADLINK: We hit end-of-file before reaching _boundary.*/
op_get_next_page(OggOpusFile * _of,ogg_page * _og,opus_int64 _boundary)188 static opus_int64 op_get_next_page(OggOpusFile *_of,ogg_page *_og,
189  opus_int64 _boundary){
190   while(_boundary<=0||_of->offset<_boundary){
191     int more;
192     more=ogg_sync_pageseek(&_of->oy,_og);
193     /*Skipped (-more) bytes.*/
194     if(OP_UNLIKELY(more<0))_of->offset-=more;
195     else if(more==0){
196       int read_nbytes;
197       int ret;
198       /*Send more paramedics.*/
199       if(!_boundary)return OP_FALSE;
200       if(_boundary<0)read_nbytes=OP_READ_SIZE;
201       else{
202         opus_int64 position;
203         position=op_position(_of);
204         if(position>=_boundary)return OP_FALSE;
205         read_nbytes=(int)OP_MIN(_boundary-position,OP_READ_SIZE);
206       }
207       ret=op_get_data(_of,read_nbytes);
208       if(OP_UNLIKELY(ret<0))return OP_EREAD;
209       if(OP_UNLIKELY(ret==0)){
210         /*Only fail cleanly on EOF if we didn't have a known boundary.
211           Otherwise, we should have been able to reach that boundary, and this
212            is a fatal error.*/
213         return OP_UNLIKELY(_boundary<0)?OP_FALSE:OP_EBADLINK;
214       }
215     }
216     else{
217       /*Got a page.
218         Return the page start offset and advance the internal offset past the
219          page end.*/
220       opus_int64 page_offset;
221       page_offset=_of->offset;
222       _of->offset+=more;
223       OP_ASSERT(page_offset>=0);
224       return page_offset;
225     }
226   }
227   return OP_FALSE;
228 }
229 
op_add_serialno(const ogg_page * _og,ogg_uint32_t ** _serialnos,int * _nserialnos,int * _cserialnos)230 static int op_add_serialno(const ogg_page *_og,
231  ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){
232   ogg_uint32_t *serialnos;
233   int           nserialnos;
234   int           cserialnos;
235   ogg_uint32_t s;
236   s=ogg_page_serialno(_og);
237   serialnos=*_serialnos;
238   nserialnos=*_nserialnos;
239   cserialnos=*_cserialnos;
240   if(OP_UNLIKELY(nserialnos>=cserialnos)){
241     if(OP_UNLIKELY(cserialnos>INT_MAX/(int)sizeof(*serialnos)-1>>1)){
242       return OP_EFAULT;
243     }
244     cserialnos=2*cserialnos+1;
245     OP_ASSERT(nserialnos<cserialnos);
246     serialnos=(ogg_uint32_t *)_ogg_realloc(serialnos,
247      sizeof(*serialnos)*cserialnos);
248     if(OP_UNLIKELY(serialnos==NULL))return OP_EFAULT;
249   }
250   serialnos[nserialnos++]=s;
251   *_serialnos=serialnos;
252   *_nserialnos=nserialnos;
253   *_cserialnos=cserialnos;
254   return 0;
255 }
256 
257 /*Returns nonzero if found.*/
op_lookup_serialno(ogg_uint32_t _s,const ogg_uint32_t * _serialnos,int _nserialnos)258 static int op_lookup_serialno(ogg_uint32_t _s,
259  const ogg_uint32_t *_serialnos,int _nserialnos){
260   int i;
261   for(i=0;i<_nserialnos&&_serialnos[i]!=_s;i++);
262   return i<_nserialnos;
263 }
264 
op_lookup_page_serialno(const ogg_page * _og,const ogg_uint32_t * _serialnos,int _nserialnos)265 static int op_lookup_page_serialno(const ogg_page *_og,
266  const ogg_uint32_t *_serialnos,int _nserialnos){
267   return op_lookup_serialno(ogg_page_serialno(_og),_serialnos,_nserialnos);
268 }
269 
270 typedef struct OpusSeekRecord OpusSeekRecord;
271 
272 /*We use this to remember the pages we found while enumerating the links of a
273    chained stream.
274   We keep track of the starting and ending offsets, as well as the point we
275    started searching from, so we know where to bisect.
276   We also keep the serial number, so we can tell if the page belonged to the
277    current link or not, as well as the granule position, to aid in estimating
278    the start of the link.*/
279 struct OpusSeekRecord{
280   /*The earliest byte we know of such that reading forward from it causes
281      capture to be regained at this page.*/
282   opus_int64   search_start;
283   /*The offset of this page.*/
284   opus_int64   offset;
285   /*The size of this page.*/
286   opus_int32   size;
287   /*The serial number of this page.*/
288   ogg_uint32_t serialno;
289   /*The granule position of this page.*/
290   ogg_int64_t  gp;
291 };
292 
293 /*Find the last page beginning before _offset with a valid granule position.
294   There is no '_boundary' parameter as it will always have to read more data.
295   This is much dirtier than the above, as Ogg doesn't have any backward search
296    linkage.
297   This search prefers pages of the specified serial number.
298   If a page of the specified serial number is spotted during the
299    seek-back-and-read-forward, it will return the info of last page of the
300    matching serial number, instead of the very last page, unless the very last
301    page belongs to a different link than preferred serial number.
302   If no page of the specified serial number is seen, it will return the info of
303    the last page.
304   [out] _sr:   Returns information about the page that was found on success.
305   _offset:     The _offset before which to find a page.
306                Any page returned will consist of data entirely before _offset.
307   _serialno:   The preferred serial number.
308                If a page with this serial number is found, it will be returned
309                 even if another page in the same link is found closer to
310                 _offset.
311                This is purely opportunistic: there is no guarantee such a page
312                 will be found if it exists.
313   _serialnos:  The list of serial numbers in the link that contains the
314                 preferred serial number.
315   _nserialnos: The number of serial numbers in the current link.
316   Return: 0 on success, or a negative value on failure.
317           OP_EREAD:    Failed to read more data (error or EOF).
318           OP_EBADLINK: We couldn't find a page even after seeking back to the
319                         start of the stream.*/
op_get_prev_page_serial(OggOpusFile * _of,OpusSeekRecord * _sr,opus_int64 _offset,ogg_uint32_t _serialno,const ogg_uint32_t * _serialnos,int _nserialnos)320 static int op_get_prev_page_serial(OggOpusFile *_of,OpusSeekRecord *_sr,
321  opus_int64 _offset,ogg_uint32_t _serialno,
322  const ogg_uint32_t *_serialnos,int _nserialnos){
323   OpusSeekRecord preferred_sr;
324   ogg_page       og;
325   opus_int64     begin;
326   opus_int64     end;
327   opus_int64     original_end;
328   opus_int32     chunk_size;
329   int            preferred_found;
330   original_end=end=begin=_offset;
331   preferred_found=0;
332   _offset=-1;
333   chunk_size=OP_CHUNK_SIZE;
334   do{
335     opus_int64 search_start;
336     int        ret;
337     OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX);
338     begin=OP_MAX(begin-chunk_size,0);
339     ret=op_seek_helper(_of,begin);
340     if(OP_UNLIKELY(ret<0))return ret;
341     search_start=begin;
342     while(_of->offset<end){
343       opus_int64   llret;
344       ogg_uint32_t serialno;
345       llret=op_get_next_page(_of,&og,end);
346       if(OP_UNLIKELY(llret<OP_FALSE))return (int)llret;
347       else if(llret==OP_FALSE)break;
348       serialno=ogg_page_serialno(&og);
349       /*Save the information for this page.
350         We're not interested in the page itself... just the serial number, byte
351          offset, page size, and granule position.*/
352       _sr->search_start=search_start;
353       _sr->offset=_offset=llret;
354       _sr->serialno=serialno;
355       OP_ASSERT(_of->offset-_offset>=0);
356       OP_ASSERT(_of->offset-_offset<=OP_PAGE_SIZE_MAX);
357       _sr->size=(opus_int32)(_of->offset-_offset);
358       _sr->gp=ogg_page_granulepos(&og);
359       /*If this page is from the stream we're looking for, remember it.*/
360       if(serialno==_serialno){
361         preferred_found=1;
362         *&preferred_sr=*_sr;
363       }
364       if(!op_lookup_serialno(serialno,_serialnos,_nserialnos)){
365         /*We fell off the end of the link, which means we seeked back too far
366            and shouldn't have been looking in that link to begin with.
367           If we found the preferred serial number, forget that we saw it.*/
368         preferred_found=0;
369       }
370       search_start=llret+1;
371     }
372     /*We started from the beginning of the stream and found nothing.
373       This should be impossible unless the contents of the stream changed out
374        from under us after we read from it.*/
375     if(OP_UNLIKELY(!begin)&&OP_UNLIKELY(_offset<0))return OP_EBADLINK;
376     /*Bump up the chunk size.
377       This is mildly helpful when seeks are very expensive (http).*/
378     chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX);
379     /*Avoid quadratic complexity if we hit an invalid patch of the file.*/
380     end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end);
381   }
382   while(_offset<0);
383   if(preferred_found)*_sr=*&preferred_sr;
384   return 0;
385 }
386 
387 /*Find the last page beginning before _offset with the given serial number and
388    a valid granule position.
389   Unlike the above search, this continues until it finds such a page, but does
390    not stray outside the current link.
391   We could implement it (inefficiently) by calling op_get_prev_page_serial()
392    repeatedly until it returned a page that had both our preferred serial
393    number and a valid granule position, but doing it with a separate function
394    allows us to avoid repeatedly re-scanning valid pages from other streams as
395    we seek-back-and-read-forward.
396   [out] _gp:   Returns the granule position of the page that was found on
397                 success.
398   _offset:     The _offset before which to find a page.
399                Any page returned will consist of data entirely before _offset.
400   _serialno:   The target serial number.
401   _serialnos:  The list of serial numbers in the link that contains the
402                 preferred serial number.
403   _nserialnos: The number of serial numbers in the current link.
404   Return: The offset of the page on success, or a negative value on failure.
405           OP_EREAD:    Failed to read more data (error or EOF).
406           OP_EBADLINK: We couldn't find a page even after seeking back past the
407                         beginning of the link.*/
op_get_last_page(OggOpusFile * _of,ogg_int64_t * _gp,opus_int64 _offset,ogg_uint32_t _serialno,const ogg_uint32_t * _serialnos,int _nserialnos)408 static opus_int64 op_get_last_page(OggOpusFile *_of,ogg_int64_t *_gp,
409  opus_int64 _offset,ogg_uint32_t _serialno,
410  const ogg_uint32_t *_serialnos,int _nserialnos){
411   ogg_page    og;
412   ogg_int64_t gp;
413   opus_int64  begin;
414   opus_int64  end;
415   opus_int64  original_end;
416   opus_int32  chunk_size;
417   /*The target serial number must belong to the current link.*/
418   OP_ASSERT(op_lookup_serialno(_serialno,_serialnos,_nserialnos));
419   original_end=end=begin=_offset;
420   _offset=-1;
421   /*We shouldn't have to initialize gp, but gcc is too dumb to figure out that
422      ret>=0 implies we entered the if(page_gp!=-1) block at least once.*/
423   gp=-1;
424   chunk_size=OP_CHUNK_SIZE;
425   do{
426     int left_link;
427     int ret;
428     OP_ASSERT(chunk_size>=OP_PAGE_SIZE_MAX);
429     begin=OP_MAX(begin-chunk_size,0);
430     ret=op_seek_helper(_of,begin);
431     if(OP_UNLIKELY(ret<0))return ret;
432     left_link=0;
433     while(_of->offset<end){
434       opus_int64   llret;
435       ogg_uint32_t serialno;
436       llret=op_get_next_page(_of,&og,end);
437       if(OP_UNLIKELY(llret<OP_FALSE))return llret;
438       else if(llret==OP_FALSE)break;
439       serialno=ogg_page_serialno(&og);
440       if(serialno==_serialno){
441         ogg_int64_t page_gp;
442         /*The page is from the right stream...*/
443         page_gp=ogg_page_granulepos(&og);
444         if(page_gp!=-1){
445           /*And has a valid granule position.
446             Let's remember it.*/
447           _offset=llret;
448           gp=page_gp;
449         }
450       }
451       else if(OP_UNLIKELY(!op_lookup_serialno(serialno,
452        _serialnos,_nserialnos))){
453         /*We fell off the start of the link, which means we don't need to keep
454            seeking any farther back.*/
455         left_link=1;
456       }
457     }
458     /*We started from at or before the beginning of the link and found nothing.
459       This should be impossible unless the contents of the stream changed out
460        from under us after we read from it.*/
461     if((OP_UNLIKELY(left_link)||OP_UNLIKELY(!begin))&&OP_UNLIKELY(_offset<0)){
462       return OP_EBADLINK;
463     }
464     /*Bump up the chunk size.
465       This is mildly helpful when seeks are very expensive (http).*/
466     chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX);
467     /*Avoid quadratic complexity if we hit an invalid patch of the file.*/
468     end=OP_MIN(begin+OP_PAGE_SIZE_MAX-1,original_end);
469   }
470   while(_offset<0);
471   *_gp=gp;
472   return _offset;
473 }
474 
475 /*Uses the local ogg_stream storage in _of.
476   This is important for non-streaming input sources.*/
op_fetch_headers_impl(OggOpusFile * _of,OpusHead * _head,OpusTags * _tags,ogg_uint32_t ** _serialnos,int * _nserialnos,int * _cserialnos,ogg_page * _og)477 static int op_fetch_headers_impl(OggOpusFile *_of,OpusHead *_head,
478  OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos,
479  int *_cserialnos,ogg_page *_og){
480   ogg_packet op;
481   int        ret;
482   if(_serialnos!=NULL)*_nserialnos=0;
483   /*Extract the serialnos of all BOS pages plus the first set of Opus headers
484      we see in the link.*/
485   while(ogg_page_bos(_og)){
486     if(_serialnos!=NULL){
487       if(OP_UNLIKELY(op_lookup_page_serialno(_og,*_serialnos,*_nserialnos))){
488         /*A dupe serialnumber in an initial header packet set==invalid stream.*/
489         return OP_EBADHEADER;
490       }
491       ret=op_add_serialno(_og,_serialnos,_nserialnos,_cserialnos);
492       if(OP_UNLIKELY(ret<0))return ret;
493     }
494     if(_of->ready_state<OP_STREAMSET){
495       /*We don't have an Opus stream in this link yet, so begin prospective
496          stream setup.
497         We need a stream to get packets.*/
498       ogg_stream_reset_serialno(&_of->os,ogg_page_serialno(_og));
499       ogg_stream_pagein(&_of->os,_og);
500       if(OP_LIKELY(ogg_stream_packetout(&_of->os,&op)>0)){
501         ret=opus_head_parse(_head,op.packet,op.bytes);
502         /*Found a valid Opus header.
503           Continue setup.*/
504         if(OP_LIKELY(ret>=0))_of->ready_state=OP_STREAMSET;
505         /*If it's just a stream type we don't recognize, ignore it.
506           Everything else is fatal.*/
507         else if(ret!=OP_ENOTFORMAT)return ret;
508       }
509       /*TODO: Should a BOS page with no packets be an error?*/
510     }
511     /*Get the next page.
512       No need to clamp the boundary offset against _of->end, as all errors
513        become OP_ENOTFORMAT or OP_EBADHEADER.*/
514     if(OP_UNLIKELY(op_get_next_page(_of,_og,
515      OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){
516       return _of->ready_state<OP_STREAMSET?OP_ENOTFORMAT:OP_EBADHEADER;
517     }
518   }
519   if(OP_UNLIKELY(_of->ready_state!=OP_STREAMSET))return OP_ENOTFORMAT;
520   /*If the first non-header page belonged to our Opus stream, submit it.*/
521   if(_of->os.serialno==ogg_page_serialno(_og))ogg_stream_pagein(&_of->os,_og);
522   /*Loop getting packets.*/
523   for(;;){
524     switch(ogg_stream_packetout(&_of->os,&op)){
525       case 0:{
526         /*Loop getting pages.*/
527         for(;;){
528           /*No need to clamp the boundary offset against _of->end, as all
529              errors become OP_EBADHEADER.*/
530           if(OP_UNLIKELY(op_get_next_page(_of,_og,
531            OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){
532             return OP_EBADHEADER;
533           }
534           /*If this page belongs to the correct stream, go parse it.*/
535           if(_of->os.serialno==ogg_page_serialno(_og)){
536             ogg_stream_pagein(&_of->os,_og);
537             break;
538           }
539           /*If the link ends before we see the Opus comment header, abort.*/
540           if(OP_UNLIKELY(ogg_page_bos(_og)))return OP_EBADHEADER;
541           /*Otherwise, keep looking.*/
542         }
543       }break;
544       /*We shouldn't get a hole in the headers!*/
545       case -1:return OP_EBADHEADER;
546       default:{
547         /*Got a packet.
548           It should be the comment header.*/
549         ret=opus_tags_parse(_tags,op.packet,op.bytes);
550         if(OP_UNLIKELY(ret<0))return ret;
551         /*Make sure the page terminated at the end of the comment header.
552           If there is another packet on the page, or part of a packet, then
553            reject the stream.
554           Otherwise seekable sources won't be able to seek back to the start
555            properly.*/
556         ret=ogg_stream_packetout(&_of->os,&op);
557         if(OP_UNLIKELY(ret!=0)
558          ||OP_UNLIKELY(_og->header[_og->header_len-1]==255)){
559           /*If we fail, the caller assumes our tags are uninitialized.*/
560           opus_tags_clear(_tags);
561           return OP_EBADHEADER;
562         }
563         return 0;
564       }
565     }
566   }
567 }
568 
op_fetch_headers(OggOpusFile * _of,OpusHead * _head,OpusTags * _tags,ogg_uint32_t ** _serialnos,int * _nserialnos,int * _cserialnos,ogg_page * _og)569 static int op_fetch_headers(OggOpusFile *_of,OpusHead *_head,
570  OpusTags *_tags,ogg_uint32_t **_serialnos,int *_nserialnos,
571  int *_cserialnos,ogg_page *_og){
572   ogg_page og;
573   int      ret;
574   if(!_og){
575     /*No need to clamp the boundary offset against _of->end, as all errors
576        become OP_ENOTFORMAT.*/
577     if(OP_UNLIKELY(op_get_next_page(_of,&og,
578      OP_ADV_OFFSET(_of->offset,OP_CHUNK_SIZE))<0)){
579       return OP_ENOTFORMAT;
580     }
581     _og=&og;
582   }
583   _of->ready_state=OP_OPENED;
584   ret=op_fetch_headers_impl(_of,_head,_tags,_serialnos,_nserialnos,
585    _cserialnos,_og);
586   /*Revert back from OP_STREAMSET to OP_OPENED on failure, to prevent
587      double-free of the tags in an unseekable stream.*/
588   if(OP_UNLIKELY(ret<0))_of->ready_state=OP_OPENED;
589   return ret;
590 }
591 
592 /*Granule position manipulation routines.
593   A granule position is defined to be an unsigned 64-bit integer, with the
594    special value -1 in two's complement indicating an unset or invalid granule
595    position.
596   We are not guaranteed to have an unsigned 64-bit type, so we construct the
597    following routines that
598    a) Properly order negative numbers as larger than positive numbers, and
599    b) Check for underflow or overflow past the special -1 value.
600   This lets us operate on the full, valid range of granule positions in a
601    consistent and safe manner.
602   This full range is organized into distinct regions:
603    [ -1 (invalid) ][ 0 ... OP_INT64_MAX ][ OP_INT64_MIN ... -2 ][-1 (invalid) ]
604 
605   No one should actually use granule positions so large that they're negative,
606    even if they are technically valid, as very little software handles them
607    correctly (including most of Xiph.Org's).
608   This library also refuses to support durations so large they won't fit in a
609    signed 64-bit integer (to avoid exposing this mess to the application, and
610    to simplify a good deal of internal arithmetic), so the only way to use them
611    successfully is if pcm_start is very large.
612   This means there isn't anything you can do with negative granule positions
613    that you couldn't have done with purely non-negative ones.
614   The main purpose of these routines is to allow us to think very explicitly
615    about the possible failure cases of all granule position manipulations.*/
616 
617 /*Safely adds a small signed integer to a valid (not -1) granule position.
618   The result can use the full 64-bit range of values (both positive and
619    negative), but will fail on overflow (wrapping past -1; wrapping past
620    OP_INT64_MAX is explicitly okay).
621   [out] _dst_gp: The resulting granule position.
622                  Only modified on success.
623   _src_gp:       The granule position to add to.
624                  This must not be -1.
625   _delta:        The amount to add.
626                  This is allowed to be up to 32 bits to support the maximum
627                   duration of a single Ogg page (255 packets * 120 ms per
628                   packet == 1,468,800 samples at 48 kHz).
629   Return: 0 on success, or OP_EINVAL if the result would wrap around past -1.*/
op_granpos_add(ogg_int64_t * _dst_gp,ogg_int64_t _src_gp,opus_int32 _delta)630 static int op_granpos_add(ogg_int64_t *_dst_gp,ogg_int64_t _src_gp,
631  opus_int32 _delta){
632   /*The code below handles this case correctly, but there's no reason we
633      should ever be called with these values, so make sure we aren't.*/
634   OP_ASSERT(_src_gp!=-1);
635   if(_delta>0){
636     /*Adding this amount to the granule position would overflow its 64-bit
637        range.*/
638     if(OP_UNLIKELY(_src_gp<0)&&OP_UNLIKELY(_src_gp>=-1-_delta))return OP_EINVAL;
639     if(OP_UNLIKELY(_src_gp>OP_INT64_MAX-_delta)){
640       /*Adding this amount to the granule position would overflow the positive
641          half of its 64-bit range.
642         Since signed overflow is undefined in C, do it in a way the compiler
643          isn't allowed to screw up.*/
644       _delta-=(opus_int32)(OP_INT64_MAX-_src_gp)+1;
645       _src_gp=OP_INT64_MIN;
646     }
647   }
648   else if(_delta<0){
649     /*Subtracting this amount from the granule position would underflow its
650        64-bit range.*/
651     if(_src_gp>=0&&OP_UNLIKELY(_src_gp<-_delta))return OP_EINVAL;
652     if(OP_UNLIKELY(_src_gp<OP_INT64_MIN-_delta)){
653       /*Subtracting this amount from the granule position would underflow the
654          negative half of its 64-bit range.
655         Since signed underflow is undefined in C, do it in a way the compiler
656          isn't allowed to screw up.*/
657       _delta+=(opus_int32)(_src_gp-OP_INT64_MIN)+1;
658       _src_gp=OP_INT64_MAX;
659     }
660   }
661   *_dst_gp=_src_gp+_delta;
662   return 0;
663 }
664 
665 /*Safely computes the difference between two granule positions.
666   The difference must fit in a signed 64-bit integer, or the function fails.
667   It correctly handles the case where the granule position has wrapped around
668    from positive values to negative ones.
669   [out] _delta: The difference between the granule positions.
670                 Only modified on success.
671   _gp_a:        The granule position to subtract from.
672                 This must not be -1.
673   _gp_b:        The granule position to subtract.
674                 This must not be -1.
675   Return: 0 on success, or OP_EINVAL if the result would not fit in a signed
676            64-bit integer.*/
op_granpos_diff(ogg_int64_t * _delta,ogg_int64_t _gp_a,ogg_int64_t _gp_b)677 static int op_granpos_diff(ogg_int64_t *_delta,
678  ogg_int64_t _gp_a,ogg_int64_t _gp_b){
679   int gp_a_negative;
680   int gp_b_negative;
681   /*The code below handles these cases correctly, but there's no reason we
682      should ever be called with these values, so make sure we aren't.*/
683   OP_ASSERT(_gp_a!=-1);
684   OP_ASSERT(_gp_b!=-1);
685   gp_a_negative=OP_UNLIKELY(_gp_a<0);
686   gp_b_negative=OP_UNLIKELY(_gp_b<0);
687   if(OP_UNLIKELY(gp_a_negative^gp_b_negative)){
688     ogg_int64_t da;
689     ogg_int64_t db;
690     if(gp_a_negative){
691       /*_gp_a has wrapped to a negative value but _gp_b hasn't: the difference
692          should be positive.*/
693       /*Step 1: Handle wrapping.*/
694       /*_gp_a < 0 => da < 0.*/
695       da=(OP_INT64_MIN-_gp_a)-1;
696       /*_gp_b >= 0  => db >= 0.*/
697       db=OP_INT64_MAX-_gp_b;
698       /*Step 2: Check for overflow.*/
699       if(OP_UNLIKELY(OP_INT64_MAX+da<db))return OP_EINVAL;
700       *_delta=db-da;
701     }
702     else{
703       /*_gp_b has wrapped to a negative value but _gp_a hasn't: the difference
704          should be negative.*/
705       /*Step 1: Handle wrapping.*/
706       /*_gp_a >= 0 => da <= 0*/
707       da=_gp_a+OP_INT64_MIN;
708       /*_gp_b < 0 => db <= 0*/
709       db=OP_INT64_MIN-_gp_b;
710       /*Step 2: Check for overflow.*/
711       if(OP_UNLIKELY(da<OP_INT64_MIN-db))return OP_EINVAL;
712       *_delta=da+db;
713     }
714   }
715   else *_delta=_gp_a-_gp_b;
716   return 0;
717 }
718 
op_granpos_cmp(ogg_int64_t _gp_a,ogg_int64_t _gp_b)719 static int op_granpos_cmp(ogg_int64_t _gp_a,ogg_int64_t _gp_b){
720   /*The invalid granule position -1 should behave like NaN: neither greater
721      than nor less than any other granule position, nor equal to any other
722      granule position, including itself.
723     However, that means there isn't anything we could sensibly return from this
724      function for it.*/
725   OP_ASSERT(_gp_a!=-1);
726   OP_ASSERT(_gp_b!=-1);
727   /*Handle the wrapping cases.*/
728   if(OP_UNLIKELY(_gp_a<0)){
729     if(_gp_b>=0)return 1;
730     /*Else fall through.*/
731   }
732   else if(OP_UNLIKELY(_gp_b<0))return -1;
733   /*No wrapping case.*/
734   return (_gp_a>_gp_b)-(_gp_b>_gp_a);
735 }
736 
737 /*Returns the duration of the packet (in samples at 48 kHz), or a negative
738    value on error.*/
op_get_packet_duration(const unsigned char * _data,int _len)739 static int op_get_packet_duration(const unsigned char *_data,int _len){
740   int nframes;
741   int frame_size;
742   int nsamples;
743   nframes=opus_packet_get_nb_frames(_data,_len);
744   if(OP_UNLIKELY(nframes<0))return OP_EBADPACKET;
745   frame_size=opus_packet_get_samples_per_frame(_data,48000);
746   nsamples=nframes*frame_size;
747   if(OP_UNLIKELY(nsamples>120*48))return OP_EBADPACKET;
748   return nsamples;
749 }
750 
751 /*This function more properly belongs in info.c, but we define it here to allow
752    the static granule position manipulation functions to remain static.*/
opus_granule_sample(const OpusHead * _head,ogg_int64_t _gp)753 ogg_int64_t opus_granule_sample(const OpusHead *_head,ogg_int64_t _gp){
754   opus_int32 pre_skip;
755   pre_skip=_head->pre_skip;
756   if(_gp!=-1&&op_granpos_add(&_gp,_gp,-pre_skip))_gp=-1;
757   return _gp;
758 }
759 
760 /*Grab all the packets currently in the stream state, and compute their
761    durations.
762   _of->op_count is set to the number of packets collected.
763   [out] _durations: Returns the durations of the individual packets.
764   Return: The total duration of all packets, or OP_HOLE if there was a hole.*/
op_collect_audio_packets(OggOpusFile * _of,int _durations[255])765 static opus_int32 op_collect_audio_packets(OggOpusFile *_of,
766  int _durations[255]){
767   opus_int32 total_duration;
768   int        op_count;
769   /*Count the durations of all packets in the page.*/
770   op_count=0;
771   total_duration=0;
772   for(;;){
773     int ret;
774     /*This takes advantage of undocumented libogg behavior that returned
775        ogg_packet buffers are valid at least until the next page is
776        submitted.
777       Relying on this is not too terrible, as _none_ of the Ogg memory
778        ownership/lifetime rules are well-documented.
779       But I can read its code and know this will work.*/
780     ret=ogg_stream_packetout(&_of->os,_of->op+op_count);
781     if(!ret)break;
782     if(OP_UNLIKELY(ret<0)){
783       /*We shouldn't get holes in the middle of pages.*/
784       OP_ASSERT(op_count==0);
785       /*Set the return value and break out of the loop.
786         We want to make sure op_count gets set to 0, because we've ingested a
787          page, so any previously loaded packets are now invalid.*/
788       total_duration=OP_HOLE;
789       break;
790     }
791     /*Unless libogg is broken, we can't get more than 255 packets from a
792        single page.*/
793     OP_ASSERT(op_count<255);
794     _durations[op_count]=op_get_packet_duration(_of->op[op_count].packet,
795      _of->op[op_count].bytes);
796     if(OP_LIKELY(_durations[op_count]>0)){
797       /*With at most 255 packets on a page, this can't overflow.*/
798       total_duration+=_durations[op_count++];
799     }
800     /*Ignore packets with an invalid TOC sequence.*/
801     else if(op_count>0){
802       /*But save the granule position, if there was one.*/
803       _of->op[op_count-1].granulepos=_of->op[op_count].granulepos;
804     }
805   }
806   _of->op_pos=0;
807   _of->op_count=op_count;
808   return total_duration;
809 }
810 
811 /*Starting from current cursor position, get the initial PCM offset of the next
812    page.
813   This also validates the granule position on the first page with a completed
814    audio data packet, as required by the spec.
815   If this link is completely empty (no pages with completed packets), then this
816    function sets pcm_start=pcm_end=0 and returns the BOS page of the next link
817    (if any).
818   In the seekable case, we initialize pcm_end=-1 before calling this function,
819    so that later we can detect that the link was empty before calling
820    op_find_final_pcm_offset().
821   [inout] _link: The link for which to find pcm_start.
822   [out] _og:     Returns the BOS page of the next link if this link was empty.
823                  In the unseekable case, we can then feed this to
824                   op_fetch_headers() to start the next link.
825                  The caller may pass NULL (e.g., for seekable streams), in
826                   which case this page will be discarded.
827   Return: 0 on success, 1 if there is a buffered BOS page available, or a
828            negative value on unrecoverable error.*/
op_find_initial_pcm_offset(OggOpusFile * _of,OggOpusLink * _link,ogg_page * _og)829 static int op_find_initial_pcm_offset(OggOpusFile *_of,
830  OggOpusLink *_link,ogg_page *_og){
831   ogg_page     og;
832   opus_int64   page_offset;
833   ogg_int64_t  pcm_start;
834   ogg_int64_t  prev_packet_gp;
835   ogg_int64_t  cur_page_gp;
836   ogg_uint32_t serialno;
837   opus_int32   total_duration;
838   int          durations[255];
839   int          cur_page_eos;
840   int          op_count;
841   int          pi;
842   if(_og==NULL)_og=&og;
843   serialno=_of->os.serialno;
844   op_count=0;
845   /*We shouldn't have to initialize total_duration, but gcc is too dumb to
846      figure out that op_count>0 implies we've been through the whole loop at
847      least once.*/
848   total_duration=0;
849   do{
850     page_offset=op_get_next_page(_of,_og,_of->end);
851     /*We should get a page unless the file is truncated or mangled.
852       Otherwise there are no audio data packets in the whole logical stream.*/
853     if(OP_UNLIKELY(page_offset<0)){
854       /*Fail if there was a read error.*/
855       if(page_offset<OP_FALSE)return (int)page_offset;
856       /*Fail if the pre-skip is non-zero, since it's asking us to skip more
857          samples than exist.*/
858       if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
859       _link->pcm_file_offset=0;
860       /*Set pcm_end and end_offset so we can skip the call to
861          op_find_final_pcm_offset().*/
862       _link->pcm_start=_link->pcm_end=0;
863       _link->end_offset=_link->data_offset;
864       return 0;
865     }
866     /*Similarly, if we hit the next link in the chain, we've gone too far.*/
867     if(OP_UNLIKELY(ogg_page_bos(_og))){
868       if(_link->head.pre_skip>0)return OP_EBADTIMESTAMP;
869       /*Set pcm_end and end_offset so we can skip the call to
870          op_find_final_pcm_offset().*/
871       _link->pcm_file_offset=0;
872       _link->pcm_start=_link->pcm_end=0;
873       _link->end_offset=_link->data_offset;
874       /*Tell the caller we've got a buffered page for them.*/
875       return 1;
876     }
877     /*Ignore pages from other streams (not strictly necessary, because of the
878        checks in ogg_stream_pagein(), but saves some work).*/
879     if(serialno!=(ogg_uint32_t)ogg_page_serialno(_og))continue;
880     ogg_stream_pagein(&_of->os,_og);
881     /*Bitrate tracking: add the header's bytes here.
882       The body bytes are counted when we consume the packets.*/
883     _of->bytes_tracked+=_og->header_len;
884     /*Count the durations of all packets in the page.*/
885     do total_duration=op_collect_audio_packets(_of,durations);
886     /*Ignore holes.*/
887     while(OP_UNLIKELY(total_duration<0));
888     op_count=_of->op_count;
889   }
890   while(op_count<=0);
891   /*We found the first page with a completed audio data packet: actually look
892      at the granule position.
893     RFC 3533 says, "A special value of -1 (in two's complement) indicates that
894      no packets finish on this page," which does not say that a granule
895      position that is NOT -1 indicates that some packets DO finish on that page
896      (even though this was the intention, libogg itself violated this intention
897      for years before we fixed it).
898     The Ogg Opus specification only imposes its start-time requirements
899      on the granule position of the first page with completed packets,
900      so we ignore any set granule positions until then.*/
901   cur_page_gp=_of->op[op_count-1].granulepos;
902   /*But getting a packet without a valid granule position on the page is not
903      okay.*/
904   if(cur_page_gp==-1)return OP_EBADTIMESTAMP;
905   cur_page_eos=_of->op[op_count-1].e_o_s;
906   if(OP_LIKELY(!cur_page_eos)){
907     /*The EOS flag wasn't set.
908       Work backwards from the provided granule position to get the starting PCM
909        offset.*/
910     if(OP_UNLIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){
911       /*The starting granule position MUST not be smaller than the amount of
912          audio on the first page with completed packets.*/
913       return OP_EBADTIMESTAMP;
914     }
915   }
916   else{
917     /*The first page with completed packets was also the last.*/
918     if(OP_LIKELY(op_granpos_add(&pcm_start,cur_page_gp,-total_duration)<0)){
919       /*If there's less audio on the page than indicated by the granule
920          position, then we're doing end-trimming, and the starting PCM offset
921          is zero by spec mandate.*/
922       pcm_start=0;
923       /*However, the end-trimming MUST not ask us to trim more samples than
924          exist after applying the pre-skip.*/
925       if(OP_UNLIKELY(op_granpos_cmp(cur_page_gp,_link->head.pre_skip)<0)){
926         return OP_EBADTIMESTAMP;
927       }
928     }
929   }
930   /*Timestamp the individual packets.*/
931   prev_packet_gp=pcm_start;
932   for(pi=0;pi<op_count;pi++){
933     if(cur_page_eos){
934       ogg_int64_t diff;
935       OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp));
936       diff=durations[pi]-diff;
937       /*If we have samples to trim...*/
938       if(diff>0){
939         /*If we trimmed the entire packet, stop (the spec says encoders
940            shouldn't do this, but we support it anyway).*/
941         if(OP_UNLIKELY(diff>durations[pi]))break;
942         _of->op[pi].granulepos=prev_packet_gp=cur_page_gp;
943         /*Move the EOS flag to this packet, if necessary, so we'll trim the
944            samples.*/
945         _of->op[pi].e_o_s=1;
946         continue;
947       }
948     }
949     /*Update the granule position as normal.*/
950     OP_ALWAYS_TRUE(!op_granpos_add(&_of->op[pi].granulepos,
951      prev_packet_gp,durations[pi]));
952     prev_packet_gp=_of->op[pi].granulepos;
953   }
954   /*Update the packet count after end-trimming.*/
955   _of->op_count=pi;
956   _of->cur_discard_count=_link->head.pre_skip;
957   _link->pcm_file_offset=0;
958   _of->prev_packet_gp=_link->pcm_start=pcm_start;
959   _of->prev_page_offset=page_offset;
960   return 0;
961 }
962 
963 /*Starting from current cursor position, get the final PCM offset of the
964    previous page.
965   This also validates the duration of the link, which, while not strictly
966    required by the spec, we need to ensure duration calculations don't
967    overflow.
968   This is only done for seekable sources.
969   We must validate that op_find_initial_pcm_offset() succeeded for this link
970    before calling this function, otherwise it will scan the entire stream
971    backwards until it reaches the start, and then fail.*/
op_find_final_pcm_offset(OggOpusFile * _of,const ogg_uint32_t * _serialnos,int _nserialnos,OggOpusLink * _link,opus_int64 _offset,ogg_uint32_t _end_serialno,ogg_int64_t _end_gp,ogg_int64_t * _total_duration)972 static int op_find_final_pcm_offset(OggOpusFile *_of,
973  const ogg_uint32_t *_serialnos,int _nserialnos,OggOpusLink *_link,
974  opus_int64 _offset,ogg_uint32_t _end_serialno,ogg_int64_t _end_gp,
975  ogg_int64_t *_total_duration){
976   ogg_int64_t  total_duration;
977   ogg_int64_t  duration;
978   ogg_uint32_t cur_serialno;
979   /*For the time being, fetch end PCM offset the simple way.*/
980   cur_serialno=_link->serialno;
981   if(_end_serialno!=cur_serialno||_end_gp==-1){
982     _offset=op_get_last_page(_of,&_end_gp,_offset,
983      cur_serialno,_serialnos,_nserialnos);
984     if(OP_UNLIKELY(_offset<0))return (int)_offset;
985   }
986   /*At worst we should have found the first page with completed packets.*/
987   if(OP_UNLIKELY(_offset<_link->data_offset))return OP_EBADLINK;
988   /*This implementation requires that the difference between the first and last
989      granule positions in each link be representable in a signed, 64-bit
990      number, and that each link also have at least as many samples as the
991      pre-skip requires.*/
992   if(OP_UNLIKELY(op_granpos_diff(&duration,_end_gp,_link->pcm_start)<0)
993    ||OP_UNLIKELY(duration<_link->head.pre_skip)){
994     return OP_EBADTIMESTAMP;
995   }
996   /*We also require that the total duration be representable in a signed,
997      64-bit number.*/
998   duration-=_link->head.pre_skip;
999   total_duration=*_total_duration;
1000   if(OP_UNLIKELY(OP_INT64_MAX-duration<total_duration))return OP_EBADTIMESTAMP;
1001   *_total_duration=total_duration+duration;
1002   _link->pcm_end=_end_gp;
1003   _link->end_offset=_offset;
1004   return 0;
1005 }
1006 
1007 /*Rescale the number _x from the range [0,_from] to [0,_to].
1008   _from and _to must be positive.*/
op_rescale64(opus_int64 _x,opus_int64 _from,opus_int64 _to)1009 static opus_int64 op_rescale64(opus_int64 _x,opus_int64 _from,opus_int64 _to){
1010   opus_int64 frac;
1011   opus_int64 ret;
1012   int        i;
1013   if(_x>=_from)return _to;
1014   if(_x<=0)return 0;
1015   frac=0;
1016   for(i=0;i<63;i++){
1017     frac<<=1;
1018     OP_ASSERT(_x<=_from);
1019     if(_x>=_from>>1){
1020       _x-=_from-_x;
1021       frac|=1;
1022     }
1023     else _x<<=1;
1024   }
1025   ret=0;
1026   for(i=0;i<63;i++){
1027     if(frac&1)ret=(ret&_to&1)+(ret>>1)+(_to>>1);
1028     else ret>>=1;
1029     frac>>=1;
1030   }
1031   return ret;
1032 }
1033 
1034 /*The minimum granule position spacing allowed for making predictions.
1035   This corresponds to about 1 second of audio at 48 kHz for both Opus and
1036    Vorbis, or one keyframe interval in Theora with the default keyframe spacing
1037    of 256.*/
1038 #define OP_GP_SPACING_MIN (48000)
1039 
1040 /*Try to estimate the location of the next link using the current seek
1041    records, assuming the initial granule position of any streams we've found is
1042    0.*/
op_predict_link_start(const OpusSeekRecord * _sr,int _nsr,opus_int64 _searched,opus_int64 _end_searched,opus_int32 _bias)1043 static opus_int64 op_predict_link_start(const OpusSeekRecord *_sr,int _nsr,
1044  opus_int64 _searched,opus_int64 _end_searched,opus_int32 _bias){
1045   opus_int64 bisect;
1046   int        sri;
1047   int        srj;
1048   /*Require that we be at least OP_CHUNK_SIZE from the end.
1049     We don't require that we be at least OP_CHUNK_SIZE from the beginning,
1050      because if we are we'll just scan forward without seeking.*/
1051   _end_searched-=OP_CHUNK_SIZE;
1052   if(_searched>=_end_searched)return -1;
1053   bisect=_end_searched;
1054   for(sri=0;sri<_nsr;sri++){
1055     ogg_int64_t  gp1;
1056     ogg_int64_t  gp2_min;
1057     ogg_uint32_t serialno1;
1058     opus_int64   offset1;
1059     /*If the granule position is negative, either it's invalid or we'd cause
1060        overflow.*/
1061     gp1=_sr[sri].gp;
1062     if(gp1<0)continue;
1063     /*We require some minimum distance between granule positions to make an
1064        estimate.
1065       We don't actually know what granule position scheme is being used,
1066        because we have no idea what kind of stream these came from.
1067       Therefore we require a minimum spacing between them, with the
1068        expectation that while bitrates and granule position increments might
1069        vary locally in quite complex ways, they are globally smooth.*/
1070     if(OP_UNLIKELY(op_granpos_add(&gp2_min,gp1,OP_GP_SPACING_MIN)<0)){
1071       /*No granule position would satisfy us.*/
1072       continue;
1073     }
1074     offset1=_sr[sri].offset;
1075     serialno1=_sr[sri].serialno;
1076     for(srj=sri;srj-->0;){
1077       ogg_int64_t gp2;
1078       opus_int64  offset2;
1079       opus_int64  num;
1080       ogg_int64_t den;
1081       ogg_int64_t ipart;
1082       gp2=_sr[srj].gp;
1083       if(gp2<gp2_min)continue;
1084       /*Oh, and also make sure these came from the same stream.*/
1085       if(_sr[srj].serialno!=serialno1)continue;
1086       offset2=_sr[srj].offset;
1087       /*For once, we can subtract with impunity.*/
1088       den=gp2-gp1;
1089       ipart=gp2/den;
1090       num=offset2-offset1;
1091       OP_ASSERT(num>0);
1092       if(ipart>0&&(offset2-_searched)/ipart<num)continue;
1093       offset2-=ipart*num;
1094       gp2-=ipart*den;
1095       offset2-=op_rescale64(gp2,den,num)-_bias;
1096       if(offset2<_searched)continue;
1097       bisect=OP_MIN(bisect,offset2);
1098       break;
1099     }
1100   }
1101   return bisect>=_end_searched?-1:bisect;
1102 }
1103 
1104 /*Finds each bitstream link, one at a time, using a bisection search.
1105   This has to begin by knowing the offset of the first link's initial page.*/
op_bisect_forward_serialno(OggOpusFile * _of,opus_int64 _searched,OpusSeekRecord * _sr,int _csr,ogg_uint32_t ** _serialnos,int * _nserialnos,int * _cserialnos)1106 static int op_bisect_forward_serialno(OggOpusFile *_of,
1107  opus_int64 _searched,OpusSeekRecord *_sr,int _csr,
1108  ogg_uint32_t **_serialnos,int *_nserialnos,int *_cserialnos){
1109   ogg_page      og;
1110   OggOpusLink  *links;
1111   int           nlinks;
1112   int           clinks;
1113   ogg_uint32_t *serialnos;
1114   int           nserialnos;
1115   ogg_int64_t   total_duration;
1116   int           nsr;
1117   int           ret;
1118   links=_of->links;
1119   nlinks=clinks=_of->nlinks;
1120   total_duration=0;
1121   /*We start with one seek record, for the last page in the file.
1122     We build up a list of records for places we seek to during link
1123      enumeration.
1124     This list is kept sorted in reverse order.
1125     We only care about seek locations that were _not_ in the current link,
1126      therefore we can add them one at a time to the end of the list as we
1127      improve the lower bound on the location where the next link starts.*/
1128   nsr=1;
1129   for(;;){
1130     opus_int64  end_searched;
1131     opus_int64  bisect;
1132     opus_int64  next;
1133     opus_int64  last;
1134     ogg_int64_t end_offset;
1135     ogg_int64_t end_gp;
1136     int         sri;
1137     serialnos=*_serialnos;
1138     nserialnos=*_nserialnos;
1139     if(OP_UNLIKELY(nlinks>=clinks)){
1140       if(OP_UNLIKELY(clinks>INT_MAX-1>>1))return OP_EFAULT;
1141       clinks=2*clinks+1;
1142       OP_ASSERT(nlinks<clinks);
1143       links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*clinks);
1144       if(OP_UNLIKELY(links==NULL))return OP_EFAULT;
1145       _of->links=links;
1146     }
1147     /*Invariants:
1148       We have the headers and serial numbers for the link beginning at 'begin'.
1149       We have the offset and granule position of the last page in the file
1150        (potentially not a page we care about).*/
1151     /*Scan the seek records we already have to save us some bisection.*/
1152     for(sri=0;sri<nsr;sri++){
1153       if(op_lookup_serialno(_sr[sri].serialno,serialnos,nserialnos))break;
1154     }
1155     /*Is the last page in our current list of serial numbers?*/
1156     if(sri<=0)break;
1157     /*Last page wasn't found.
1158       We have at least one more link.*/
1159     last=-1;
1160     end_searched=_sr[sri-1].search_start;
1161     next=_sr[sri-1].offset;
1162     end_gp=-1;
1163     if(sri<nsr){
1164       _searched=_sr[sri].offset+_sr[sri].size;
1165       if(_sr[sri].serialno==links[nlinks-1].serialno){
1166         end_gp=_sr[sri].gp;
1167         end_offset=_sr[sri].offset;
1168       }
1169     }
1170     nsr=sri;
1171     bisect=-1;
1172     /*If we've already found the end of at least one link, try to pick the
1173        first bisection point at twice the average link size.
1174       This is a good choice for files with lots of links that are all about the
1175        same size.*/
1176     if(nlinks>1){
1177       opus_int64 last_offset;
1178       opus_int64 avg_link_size;
1179       opus_int64 upper_limit;
1180       last_offset=links[nlinks-1].offset;
1181       avg_link_size=last_offset/(nlinks-1);
1182       upper_limit=end_searched-OP_CHUNK_SIZE-avg_link_size;
1183       if(OP_LIKELY(last_offset>_searched-avg_link_size)
1184        &&OP_LIKELY(last_offset<upper_limit)){
1185         bisect=last_offset+avg_link_size;
1186         if(OP_LIKELY(bisect<upper_limit))bisect+=avg_link_size;
1187       }
1188     }
1189     /*We guard against garbage separating the last and first pages of two
1190        links below.*/
1191     while(_searched<end_searched){
1192       opus_int32 next_bias;
1193       /*If we don't have a better estimate, use simple bisection.*/
1194       if(bisect==-1)bisect=_searched+(end_searched-_searched>>1);
1195       /*If we're within OP_CHUNK_SIZE of the start, scan forward.*/
1196       if(bisect-_searched<OP_CHUNK_SIZE)bisect=_searched;
1197       /*Otherwise we're skipping data.
1198         Forget the end page, if we saw one, as we might miss a later one.*/
1199       else end_gp=-1;
1200       ret=op_seek_helper(_of,bisect);
1201       if(OP_UNLIKELY(ret<0))return ret;
1202       last=op_get_next_page(_of,&og,_sr[nsr-1].offset);
1203       if(OP_UNLIKELY(last<OP_FALSE))return (int)last;
1204       next_bias=0;
1205       if(last==OP_FALSE)end_searched=bisect;
1206       else{
1207         ogg_uint32_t serialno;
1208         ogg_int64_t  gp;
1209         serialno=ogg_page_serialno(&og);
1210         gp=ogg_page_granulepos(&og);
1211         if(!op_lookup_serialno(serialno,serialnos,nserialnos)){
1212           end_searched=bisect;
1213           next=last;
1214           /*In reality we should always have enough room, but be paranoid.*/
1215           if(OP_LIKELY(nsr<_csr)){
1216             _sr[nsr].search_start=bisect;
1217             _sr[nsr].offset=last;
1218             OP_ASSERT(_of->offset-last>=0);
1219             OP_ASSERT(_of->offset-last<=OP_PAGE_SIZE_MAX);
1220             _sr[nsr].size=(opus_int32)(_of->offset-last);
1221             _sr[nsr].serialno=serialno;
1222             _sr[nsr].gp=gp;
1223             nsr++;
1224           }
1225         }
1226         else{
1227           _searched=_of->offset;
1228           next_bias=OP_CHUNK_SIZE;
1229           if(serialno==links[nlinks-1].serialno){
1230             /*This page was from the stream we want, remember it.
1231               If it's the last such page in the link, we won't have to go back
1232                looking for it later.*/
1233             end_gp=gp;
1234             end_offset=last;
1235           }
1236         }
1237       }
1238       bisect=op_predict_link_start(_sr,nsr,_searched,end_searched,next_bias);
1239     }
1240     /*Bisection point found.
1241       Get the final granule position of the previous link, assuming
1242        op_find_initial_pcm_offset() didn't already determine the link was
1243        empty.*/
1244     if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){
1245       if(end_gp==-1){
1246         /*If we don't know where the end page is, we'll have to seek back and
1247            look for it, starting from the end of the link.*/
1248         end_offset=next;
1249         /*Also forget the last page we read.
1250           It won't be available after the seek.*/
1251         last=-1;
1252       }
1253       ret=op_find_final_pcm_offset(_of,serialnos,nserialnos,
1254        links+nlinks-1,end_offset,links[nlinks-1].serialno,end_gp,
1255        &total_duration);
1256       if(OP_UNLIKELY(ret<0))return ret;
1257     }
1258     if(last!=next){
1259       /*The last page we read was not the first page the next link.
1260         Move the cursor position to the offset of that first page.
1261         This only performs an actual seek if the first page of the next link
1262          does not start at the end of the last page from the current Opus
1263          stream with a valid granule position.*/
1264       ret=op_seek_helper(_of,next);
1265       if(OP_UNLIKELY(ret<0))return ret;
1266     }
1267     ret=op_fetch_headers(_of,&links[nlinks].head,&links[nlinks].tags,
1268      _serialnos,_nserialnos,_cserialnos,last!=next?NULL:&og);
1269     if(OP_UNLIKELY(ret<0))return ret;
1270     links[nlinks].offset=next;
1271     links[nlinks].data_offset=_of->offset;
1272     links[nlinks].serialno=_of->os.serialno;
1273     links[nlinks].pcm_end=-1;
1274     /*This might consume a page from the next link, however the next bisection
1275        always starts with a seek.*/
1276     ret=op_find_initial_pcm_offset(_of,links+nlinks,NULL);
1277     if(OP_UNLIKELY(ret<0))return ret;
1278     links[nlinks].pcm_file_offset=total_duration;
1279     _searched=_of->offset;
1280     /*Mark the current link count so it can be cleaned up on error.*/
1281     _of->nlinks=++nlinks;
1282   }
1283   /*Last page is in the starting serialno list, so we've reached the last link.
1284     Now find the last granule position for it (if we didn't the first time we
1285      looked at the end of the stream, and if op_find_initial_pcm_offset()
1286      didn't already determine the link was empty).*/
1287   if(OP_LIKELY(links[nlinks-1].pcm_end==-1)){
1288     ret=op_find_final_pcm_offset(_of,serialnos,nserialnos,
1289      links+nlinks-1,_sr[0].offset,_sr[0].serialno,_sr[0].gp,&total_duration);
1290     if(OP_UNLIKELY(ret<0))return ret;
1291   }
1292   /*Trim back the links array if necessary.*/
1293   links=(OggOpusLink *)_ogg_realloc(links,sizeof(*links)*nlinks);
1294   if(OP_LIKELY(links!=NULL))_of->links=links;
1295   /*We also don't need these anymore.*/
1296   _ogg_free(*_serialnos);
1297   *_serialnos=NULL;
1298   *_cserialnos=*_nserialnos=0;
1299   return 0;
1300 }
1301 
op_update_gain(OggOpusFile * _of)1302 static void op_update_gain(OggOpusFile *_of){
1303   OpusHead   *head;
1304   opus_int32  gain_q8;
1305   int         li;
1306   /*If decode isn't ready, then we'll apply the gain when we initialize the
1307      decoder.*/
1308   if(_of->ready_state<OP_INITSET)return;
1309   gain_q8=_of->gain_offset_q8;
1310   li=_of->seekable?_of->cur_link:0;
1311   head=&_of->links[li].head;
1312   /*We don't have to worry about overflow here because the header gain and
1313      track gain must lie in the range [-32768,32767], and the user-supplied
1314      offset has been pre-clamped to [-98302,98303].*/
1315   switch(_of->gain_type){
1316     case OP_ALBUM_GAIN:{
1317       int album_gain_q8;
1318       album_gain_q8=0;
1319       opus_tags_get_album_gain(&_of->links[li].tags,&album_gain_q8);
1320       gain_q8+=album_gain_q8;
1321       gain_q8+=head->output_gain;
1322     }break;
1323     case OP_TRACK_GAIN:{
1324       int track_gain_q8;
1325       track_gain_q8=0;
1326       opus_tags_get_track_gain(&_of->links[li].tags,&track_gain_q8);
1327       gain_q8+=track_gain_q8;
1328       gain_q8+=head->output_gain;
1329     }break;
1330     case OP_HEADER_GAIN:gain_q8+=head->output_gain;break;
1331     case OP_ABSOLUTE_GAIN:break;
1332     default:OP_ASSERT(0);
1333   }
1334   gain_q8=OP_CLAMP(-32768,gain_q8,32767);
1335   OP_ASSERT(_of->od!=NULL);
1336 #if defined(OPUS_SET_GAIN)
1337   opus_multistream_decoder_ctl(_of->od,OPUS_SET_GAIN(gain_q8));
1338 #else
1339 /*A fallback that works with both float and fixed-point is a bunch of work,
1340    so just force people to use a sufficiently new version.
1341   This is deployed well enough at this point that this shouldn't be a burden.*/
1342 # error "libopus 1.0.1 or later required"
1343 #endif
1344 }
1345 
op_make_decode_ready(OggOpusFile * _of)1346 static int op_make_decode_ready(OggOpusFile *_of){
1347   const OpusHead *head;
1348   int             li;
1349   int             stream_count;
1350   int             coupled_count;
1351   int             channel_count;
1352   if(_of->ready_state>OP_STREAMSET)return 0;
1353   if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET))return OP_EFAULT;
1354   li=_of->seekable?_of->cur_link:0;
1355   head=&_of->links[li].head;
1356   stream_count=head->stream_count;
1357   coupled_count=head->coupled_count;
1358   channel_count=head->channel_count;
1359   /*Check to see if the current decoder is compatible with the current link.*/
1360   if(_of->od!=NULL&&_of->od_stream_count==stream_count
1361    &&_of->od_coupled_count==coupled_count&&_of->od_channel_count==channel_count
1362    &&memcmp(_of->od_mapping,head->mapping,
1363    sizeof(*head->mapping)*channel_count)==0){
1364     opus_multistream_decoder_ctl(_of->od,OPUS_RESET_STATE);
1365   }
1366   else{
1367     int err;
1368     opus_multistream_decoder_destroy(_of->od);
1369     _of->od=opus_multistream_decoder_create(48000,channel_count,
1370      stream_count,coupled_count,head->mapping,&err);
1371     if(_of->od==NULL)return OP_EFAULT;
1372     _of->od_stream_count=stream_count;
1373     _of->od_coupled_count=coupled_count;
1374     _of->od_channel_count=channel_count;
1375     memcpy(_of->od_mapping,head->mapping,sizeof(*head->mapping)*channel_count);
1376   }
1377   _of->ready_state=OP_INITSET;
1378   _of->bytes_tracked=0;
1379   _of->samples_tracked=0;
1380 #if !defined(OP_FIXED_POINT)
1381   _of->state_channel_count=0;
1382   /*Use the serial number for the PRNG seed to get repeatable output for
1383      straight play-throughs.*/
1384   _of->dither_seed=_of->links[li].serialno;
1385 #endif
1386   op_update_gain(_of);
1387   return 0;
1388 }
1389 
op_open_seekable2_impl(OggOpusFile * _of)1390 static int op_open_seekable2_impl(OggOpusFile *_of){
1391   /*64 seek records should be enough for anybody.
1392     Actually, with a bisection search in a 63-bit range down to OP_CHUNK_SIZE
1393      granularity, much more than enough.*/
1394   OpusSeekRecord sr[64];
1395   opus_int64     data_offset;
1396   int            ret;
1397   /*We can seek, so set out learning all about this file.*/
1398   (*_of->callbacks.seek)(_of->stream,0,SEEK_END);
1399   _of->offset=_of->end=(*_of->callbacks.tell)(_of->stream);
1400   if(OP_UNLIKELY(_of->end<0))return OP_EREAD;
1401   data_offset=_of->links[0].data_offset;
1402   if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
1403   /*Get the offset of the last page of the physical bitstream, or, if we're
1404      lucky, the last Opus page of the first link, as most Ogg Opus files will
1405      contain a single logical bitstream.*/
1406   ret=op_get_prev_page_serial(_of,sr,_of->end,
1407    _of->links[0].serialno,_of->serialnos,_of->nserialnos);
1408   if(OP_UNLIKELY(ret<0))return ret;
1409   /*If there's any trailing junk, forget about it.*/
1410   _of->end=sr[0].offset+sr[0].size;
1411   if(OP_UNLIKELY(_of->end<data_offset))return OP_EBADLINK;
1412   /*Now enumerate the bitstream structure.*/
1413   return op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr),
1414    &_of->serialnos,&_of->nserialnos,&_of->cserialnos);
1415 }
1416 
op_open_seekable2(OggOpusFile * _of)1417 static int op_open_seekable2(OggOpusFile *_of){
1418   ogg_sync_state    oy_start;
1419   ogg_stream_state  os_start;
1420   ogg_packet       *op_start;
1421   opus_int64        prev_page_offset;
1422   opus_int64        start_offset;
1423   int               start_op_count;
1424   int               ret;
1425   /*We're partially open and have a first link header state in storage in _of.
1426     Save off that stream state so we can come back to it.
1427     It would be simpler to just dump all this state and seek back to
1428      links[0].data_offset when we're done.
1429     But we do the extra work to allow us to seek back to _exactly_ the same
1430      stream position we're at now.
1431     This allows, e.g., the HTTP backend to continue reading from the original
1432      connection (if it's still available), instead of opening a new one.
1433     This means we can open and start playing a normal Opus file with a single
1434      link and reasonable packet sizes using only two HTTP requests.*/
1435   start_op_count=_of->op_count;
1436   /*This is a bit too large to put on the stack unconditionally.*/
1437   op_start=(ogg_packet *)_ogg_malloc(sizeof(*op_start)*start_op_count);
1438   if(op_start==NULL)return OP_EFAULT;
1439   *&oy_start=_of->oy;
1440   *&os_start=_of->os;
1441   prev_page_offset=_of->prev_page_offset;
1442   start_offset=_of->offset;
1443   memcpy(op_start,_of->op,sizeof(*op_start)*start_op_count);
1444   OP_ASSERT((*_of->callbacks.tell)(_of->stream)==op_position(_of));
1445   ogg_sync_init(&_of->oy);
1446   ogg_stream_init(&_of->os,-1);
1447   ret=op_open_seekable2_impl(_of);
1448   /*Restore the old stream state.*/
1449   ogg_stream_clear(&_of->os);
1450   ogg_sync_clear(&_of->oy);
1451   *&_of->oy=*&oy_start;
1452   *&_of->os=*&os_start;
1453   _of->offset=start_offset;
1454   _of->op_count=start_op_count;
1455   memcpy(_of->op,op_start,sizeof(*_of->op)*start_op_count);
1456   _ogg_free(op_start);
1457   _of->prev_packet_gp=_of->links[0].pcm_start;
1458   _of->prev_page_offset=prev_page_offset;
1459   _of->cur_discard_count=_of->links[0].head.pre_skip;
1460   if(OP_UNLIKELY(ret<0))return ret;
1461   /*And restore the position indicator.*/
1462   ret=(*_of->callbacks.seek)(_of->stream,op_position(_of),SEEK_SET);
1463   return OP_UNLIKELY(ret<0)?OP_EREAD:0;
1464 }
1465 
1466 /*Clear out the current logical bitstream decoder.*/
op_decode_clear(OggOpusFile * _of)1467 static void op_decode_clear(OggOpusFile *_of){
1468   /*We don't actually free the decoder.
1469     We might be able to re-use it for the next link.*/
1470   _of->op_count=0;
1471   _of->od_buffer_size=0;
1472   _of->prev_packet_gp=-1;
1473   _of->prev_page_offset=-1;
1474   if(!_of->seekable){
1475     OP_ASSERT(_of->ready_state>=OP_INITSET);
1476     opus_tags_clear(&_of->links[0].tags);
1477   }
1478   _of->ready_state=OP_OPENED;
1479 }
1480 
op_clear(OggOpusFile * _of)1481 static void op_clear(OggOpusFile *_of){
1482   OggOpusLink *links;
1483   _ogg_free(_of->od_buffer);
1484   if(_of->od!=NULL)opus_multistream_decoder_destroy(_of->od);
1485   links=_of->links;
1486   if(!_of->seekable){
1487     if(_of->ready_state>OP_OPENED||_of->ready_state==OP_PARTOPEN){
1488       opus_tags_clear(&links[0].tags);
1489     }
1490   }
1491   else if(OP_LIKELY(links!=NULL)){
1492     int nlinks;
1493     int link;
1494     nlinks=_of->nlinks;
1495     for(link=0;link<nlinks;link++)opus_tags_clear(&links[link].tags);
1496   }
1497   _ogg_free(links);
1498   _ogg_free(_of->serialnos);
1499   ogg_stream_clear(&_of->os);
1500   ogg_sync_clear(&_of->oy);
1501   if(_of->callbacks.close!=NULL)(*_of->callbacks.close)(_of->stream);
1502 }
1503 
op_open1(OggOpusFile * _of,void * _stream,const OpusFileCallbacks * _cb,const unsigned char * _initial_data,size_t _initial_bytes)1504 static int op_open1(OggOpusFile *_of,
1505  void *_stream,const OpusFileCallbacks *_cb,
1506  const unsigned char *_initial_data,size_t _initial_bytes){
1507   ogg_page  og;
1508   ogg_page *pog;
1509   int       seekable;
1510   int       ret;
1511   memset(_of,0,sizeof(*_of));
1512   if(OP_UNLIKELY(_initial_bytes>(size_t)LONG_MAX))return OP_EFAULT;
1513   _of->end=-1;
1514   _of->stream=_stream;
1515   *&_of->callbacks=*_cb;
1516   /*At a minimum, we need to be able to read data.*/
1517   if(OP_UNLIKELY(_of->callbacks.read==NULL))return OP_EREAD;
1518   /*Initialize the framing state.*/
1519   ogg_sync_init(&_of->oy);
1520   /*Perhaps some data was previously read into a buffer for testing against
1521      other stream types.
1522     Allow initialization from this previously read data (especially as we may
1523      be reading from a non-seekable stream).
1524     This requires copying it into a buffer allocated by ogg_sync_buffer() and
1525      doesn't support seeking, so this is not a good mechanism to use for
1526      decoding entire files from RAM.*/
1527   if(_initial_bytes>0){
1528     char *buffer;
1529     buffer=ogg_sync_buffer(&_of->oy,(long)_initial_bytes);
1530     memcpy(buffer,_initial_data,_initial_bytes*sizeof(*buffer));
1531     ogg_sync_wrote(&_of->oy,(long)_initial_bytes);
1532   }
1533   /*Can we seek?
1534     Stevens suggests the seek test is portable.
1535     It's actually not for files on win32, but we address that by fixing it in
1536      our callback implementation (see stream.c).*/
1537   seekable=_cb->seek!=NULL&&(*_cb->seek)(_stream,0,SEEK_CUR)!=-1;
1538   /*If seek is implemented, tell must also be implemented.*/
1539   if(seekable){
1540     opus_int64 pos;
1541     if(OP_UNLIKELY(_of->callbacks.tell==NULL))return OP_EINVAL;
1542     pos=(*_of->callbacks.tell)(_of->stream);
1543     /*If the current position is not equal to the initial bytes consumed,
1544        absolute seeking will not work.*/
1545     if(OP_UNLIKELY(pos!=(opus_int64)_initial_bytes))return OP_EINVAL;
1546   }
1547   _of->seekable=seekable;
1548   /*Don't seek yet.
1549     Set up a 'single' (current) logical bitstream entry for partial open.*/
1550   _of->links=(OggOpusLink *)_ogg_malloc(sizeof(*_of->links));
1551   /*The serialno gets filled in later by op_fetch_headers().*/
1552   ogg_stream_init(&_of->os,-1);
1553   pog=NULL;
1554   for(;;){
1555     /*Fetch all BOS pages, store the Opus header and all seen serial numbers,
1556       and load subsequent Opus setup headers.*/
1557     ret=op_fetch_headers(_of,&_of->links[0].head,&_of->links[0].tags,
1558      &_of->serialnos,&_of->nserialnos,&_of->cserialnos,pog);
1559     if(OP_UNLIKELY(ret<0))break;
1560     _of->nlinks=1;
1561     _of->links[0].offset=0;
1562     _of->links[0].data_offset=_of->offset;
1563     _of->links[0].pcm_end=-1;
1564     _of->links[0].serialno=_of->os.serialno;
1565     /*Fetch the initial PCM offset.*/
1566     ret=op_find_initial_pcm_offset(_of,_of->links,&og);
1567     if(seekable||OP_LIKELY(ret<=0))break;
1568     /*This link was empty, but we already have the BOS page for the next one in
1569        og.
1570       We can't seek, so start processing the next link right now.*/
1571     opus_tags_clear(&_of->links[0].tags);
1572     _of->nlinks=0;
1573     if(!seekable)_of->cur_link++;
1574     pog=&og;
1575   }
1576   if(OP_LIKELY(ret>=0))_of->ready_state=OP_PARTOPEN;
1577   return ret;
1578 }
1579 
op_open2(OggOpusFile * _of)1580 static int op_open2(OggOpusFile *_of){
1581   int ret;
1582   OP_ASSERT(_of->ready_state==OP_PARTOPEN);
1583   if(_of->seekable){
1584     _of->ready_state=OP_OPENED;
1585     ret=op_open_seekable2(_of);
1586   }
1587   else ret=0;
1588   if(OP_LIKELY(ret>=0)){
1589     /*We have buffered packets from op_find_initial_pcm_offset().
1590       Move to OP_INITSET so we can use them.*/
1591     _of->ready_state=OP_STREAMSET;
1592     ret=op_make_decode_ready(_of);
1593     if(OP_LIKELY(ret>=0))return 0;
1594   }
1595   /*Don't auto-close the stream on failure.*/
1596   _of->callbacks.close=NULL;
1597   op_clear(_of);
1598   return ret;
1599 }
1600 
op_test_callbacks(void * _stream,const OpusFileCallbacks * _cb,const unsigned char * _initial_data,size_t _initial_bytes,int * _error)1601 OggOpusFile *op_test_callbacks(void *_stream,const OpusFileCallbacks *_cb,
1602  const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
1603   OggOpusFile *of;
1604   int          ret;
1605   of=(OggOpusFile *)_ogg_malloc(sizeof(*of));
1606   ret=OP_EFAULT;
1607   if(OP_LIKELY(of!=NULL)){
1608     ret=op_open1(of,_stream,_cb,_initial_data,_initial_bytes);
1609     if(OP_LIKELY(ret>=0)){
1610       if(_error!=NULL)*_error=0;
1611       return of;
1612     }
1613     /*Don't auto-close the stream on failure.*/
1614     of->callbacks.close=NULL;
1615     op_clear(of);
1616     _ogg_free(of);
1617   }
1618   if(_error!=NULL)*_error=ret;
1619   return NULL;
1620 }
1621 
op_open_callbacks(void * _stream,const OpusFileCallbacks * _cb,const unsigned char * _initial_data,size_t _initial_bytes,int * _error)1622 OggOpusFile *op_open_callbacks(void *_stream,const OpusFileCallbacks *_cb,
1623  const unsigned char *_initial_data,size_t _initial_bytes,int *_error){
1624   OggOpusFile *of;
1625   of=op_test_callbacks(_stream,_cb,_initial_data,_initial_bytes,_error);
1626   if(OP_LIKELY(of!=NULL)){
1627     int ret;
1628     ret=op_open2(of);
1629     if(OP_LIKELY(ret>=0))return of;
1630     if(_error!=NULL)*_error=ret;
1631     _ogg_free(of);
1632   }
1633   return NULL;
1634 }
1635 
1636 /*Convenience routine to clean up from failure for the open functions that
1637    create their own streams.*/
op_open_close_on_failure(void * _stream,const OpusFileCallbacks * _cb,int * _error)1638 static OggOpusFile *op_open_close_on_failure(void *_stream,
1639  const OpusFileCallbacks *_cb,int *_error){
1640   OggOpusFile *of;
1641   if(OP_UNLIKELY(_stream==NULL)){
1642     if(_error!=NULL)*_error=OP_EFAULT;
1643     return NULL;
1644   }
1645   of=op_open_callbacks(_stream,_cb,NULL,0,_error);
1646   if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
1647   return of;
1648 }
1649 
op_open_file(const char * _path,int * _error)1650 OggOpusFile *op_open_file(const char *_path,int *_error){
1651   OpusFileCallbacks cb;
1652   return op_open_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error);
1653 }
1654 
op_open_memory(const unsigned char * _data,size_t _size,int * _error)1655 OggOpusFile *op_open_memory(const unsigned char *_data,size_t _size,
1656  int *_error){
1657   OpusFileCallbacks cb;
1658   return op_open_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb,
1659    _error);
1660 }
1661 
1662 /*Convenience routine to clean up from failure for the open functions that
1663    create their own streams.*/
op_test_close_on_failure(void * _stream,const OpusFileCallbacks * _cb,int * _error)1664 static OggOpusFile *op_test_close_on_failure(void *_stream,
1665  const OpusFileCallbacks *_cb,int *_error){
1666   OggOpusFile *of;
1667   if(OP_UNLIKELY(_stream==NULL)){
1668     if(_error!=NULL)*_error=OP_EFAULT;
1669     return NULL;
1670   }
1671   of=op_test_callbacks(_stream,_cb,NULL,0,_error);
1672   if(OP_UNLIKELY(of==NULL))(*_cb->close)(_stream);
1673   return of;
1674 }
1675 
op_test_file(const char * _path,int * _error)1676 OggOpusFile *op_test_file(const char *_path,int *_error){
1677   OpusFileCallbacks cb;
1678   return op_test_close_on_failure(op_fopen(&cb,_path,"rb"),&cb,_error);
1679 }
1680 
op_test_memory(const unsigned char * _data,size_t _size,int * _error)1681 OggOpusFile *op_test_memory(const unsigned char *_data,size_t _size,
1682  int *_error){
1683   OpusFileCallbacks cb;
1684   return op_test_close_on_failure(op_mem_stream_create(&cb,_data,_size),&cb,
1685    _error);
1686 }
1687 
op_test_open(OggOpusFile * _of)1688 int op_test_open(OggOpusFile *_of){
1689   int ret;
1690   if(OP_UNLIKELY(_of->ready_state!=OP_PARTOPEN))return OP_EINVAL;
1691   ret=op_open2(_of);
1692   /*op_open2() will clear this structure on failure.
1693     Reset its contents to prevent double-frees in op_free().*/
1694   if(OP_UNLIKELY(ret<0))memset(_of,0,sizeof(*_of));
1695   return ret;
1696 }
1697 
op_free(OggOpusFile * _of)1698 void op_free(OggOpusFile *_of){
1699   if(OP_LIKELY(_of!=NULL)){
1700     op_clear(_of);
1701     _ogg_free(_of);
1702   }
1703 }
1704 
op_seekable(const OggOpusFile * _of)1705 int op_seekable(const OggOpusFile *_of){
1706   return _of->seekable;
1707 }
1708 
op_link_count(const OggOpusFile * _of)1709 int op_link_count(const OggOpusFile *_of){
1710   return _of->nlinks;
1711 }
1712 
op_serialno(const OggOpusFile * _of,int _li)1713 opus_uint32 op_serialno(const OggOpusFile *_of,int _li){
1714   if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1;
1715   if(!_of->seekable)_li=0;
1716   return _of->links[_li<0?_of->cur_link:_li].serialno;
1717 }
1718 
op_channel_count(const OggOpusFile * _of,int _li)1719 int op_channel_count(const OggOpusFile *_of,int _li){
1720   return op_head(_of,_li)->channel_count;
1721 }
1722 
op_raw_total(const OggOpusFile * _of,int _li)1723 opus_int64 op_raw_total(const OggOpusFile *_of,int _li){
1724   if(OP_UNLIKELY(_of->ready_state<OP_OPENED)
1725    ||OP_UNLIKELY(!_of->seekable)
1726    ||OP_UNLIKELY(_li>=_of->nlinks)){
1727     return OP_EINVAL;
1728   }
1729   if(_li<0)return _of->end;
1730   return (_li+1>=_of->nlinks?_of->end:_of->links[_li+1].offset)
1731    -(_li>0?_of->links[_li].offset:0);
1732 }
1733 
op_pcm_total(const OggOpusFile * _of,int _li)1734 ogg_int64_t op_pcm_total(const OggOpusFile *_of,int _li){
1735   OggOpusLink *links;
1736   ogg_int64_t  pcm_total;
1737   ogg_int64_t  diff;
1738   int          nlinks;
1739   nlinks=_of->nlinks;
1740   if(OP_UNLIKELY(_of->ready_state<OP_OPENED)
1741    ||OP_UNLIKELY(!_of->seekable)
1742    ||OP_UNLIKELY(_li>=nlinks)){
1743     return OP_EINVAL;
1744   }
1745   links=_of->links;
1746   /*We verify that the granule position differences are larger than the
1747      pre-skip and that the total duration does not overflow during link
1748      enumeration, so we don't have to check here.*/
1749   pcm_total=0;
1750   if(_li<0){
1751     pcm_total=links[nlinks-1].pcm_file_offset;
1752     _li=nlinks-1;
1753   }
1754   OP_ALWAYS_TRUE(!op_granpos_diff(&diff,
1755    links[_li].pcm_end,links[_li].pcm_start));
1756   return pcm_total+diff-links[_li].head.pre_skip;
1757 }
1758 
op_head(const OggOpusFile * _of,int _li)1759 const OpusHead *op_head(const OggOpusFile *_of,int _li){
1760   if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1;
1761   if(!_of->seekable)_li=0;
1762   return &_of->links[_li<0?_of->cur_link:_li].head;
1763 }
1764 
op_tags(const OggOpusFile * _of,int _li)1765 const OpusTags *op_tags(const OggOpusFile *_of,int _li){
1766   if(OP_UNLIKELY(_li>=_of->nlinks))_li=_of->nlinks-1;
1767   if(!_of->seekable){
1768     if(_of->ready_state<OP_STREAMSET&&_of->ready_state!=OP_PARTOPEN){
1769       return NULL;
1770     }
1771     _li=0;
1772   }
1773   else if(_li<0)_li=_of->ready_state>=OP_STREAMSET?_of->cur_link:0;
1774   return &_of->links[_li].tags;
1775 }
1776 
op_current_link(const OggOpusFile * _of)1777 int op_current_link(const OggOpusFile *_of){
1778   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
1779   return _of->cur_link;
1780 }
1781 
1782 /*Compute an average bitrate given a byte and sample count.
1783   Return: The bitrate in bits per second.*/
op_calc_bitrate(opus_int64 _bytes,ogg_int64_t _samples)1784 static opus_int32 op_calc_bitrate(opus_int64 _bytes,ogg_int64_t _samples){
1785   if(OP_UNLIKELY(_samples<=0))return OP_INT32_MAX;
1786   /*These rates are absurd, but let's handle them anyway.*/
1787   if(OP_UNLIKELY(_bytes>(OP_INT64_MAX-(_samples>>1))/(48000*8))){
1788     ogg_int64_t den;
1789     if(OP_UNLIKELY(_bytes/(OP_INT32_MAX/(48000*8))>=_samples)){
1790       return OP_INT32_MAX;
1791     }
1792     den=_samples/(48000*8);
1793     return (opus_int32)((_bytes+(den>>1))/den);
1794   }
1795   /*This can't actually overflow in normal operation: even with a pre-skip of
1796      545 2.5 ms frames with 8 streams running at 1282*8+1 bytes per packet
1797      (1275 byte frames + Opus framing overhead + Ogg lacing values), that all
1798      produce a single sample of decoded output, we still don't top 45 Mbps.
1799     The only way to get bitrates larger than that is with excessive Opus
1800      padding, more encoded streams than output channels, or lots and lots of
1801      Ogg pages with no packets on them.*/
1802   return (opus_int32)OP_MIN((_bytes*48000*8+(_samples>>1))/_samples,
1803    OP_INT32_MAX);
1804 }
1805 
op_bitrate(const OggOpusFile * _of,int _li)1806 opus_int32 op_bitrate(const OggOpusFile *_of,int _li){
1807   if(OP_UNLIKELY(_of->ready_state<OP_OPENED)||OP_UNLIKELY(!_of->seekable)
1808    ||OP_UNLIKELY(_li>=_of->nlinks)){
1809     return OP_EINVAL;
1810   }
1811   return op_calc_bitrate(op_raw_total(_of,_li),op_pcm_total(_of,_li));
1812 }
1813 
op_bitrate_instant(OggOpusFile * _of)1814 opus_int32 op_bitrate_instant(OggOpusFile *_of){
1815   ogg_int64_t samples_tracked;
1816   opus_int32  ret;
1817   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
1818   samples_tracked=_of->samples_tracked;
1819   if(OP_UNLIKELY(samples_tracked==0))return OP_FALSE;
1820   ret=op_calc_bitrate(_of->bytes_tracked,samples_tracked);
1821   _of->bytes_tracked=0;
1822   _of->samples_tracked=0;
1823   return ret;
1824 }
1825 
1826 /*Given a serialno, find a link with a corresponding Opus stream, if it exists.
1827   Return: The index of the link to which the page belongs, or a negative number
1828            if it was not a desired Opus bitstream section.*/
op_get_link_from_serialno(const OggOpusFile * _of,int _cur_link,opus_int64 _page_offset,ogg_uint32_t _serialno)1829 static int op_get_link_from_serialno(const OggOpusFile *_of,int _cur_link,
1830  opus_int64 _page_offset,ogg_uint32_t _serialno){
1831   const OggOpusLink *links;
1832   int                nlinks;
1833   int                li_lo;
1834   int                li_hi;
1835   OP_ASSERT(_of->seekable);
1836   links=_of->links;
1837   nlinks=_of->nlinks;
1838   li_lo=0;
1839   /*Start off by guessing we're just a multiplexed page in the current link.*/
1840   li_hi=_cur_link+1<nlinks&&_page_offset<links[_cur_link+1].offset?
1841    _cur_link+1:nlinks;
1842   do{
1843     if(_page_offset>=links[_cur_link].offset)li_lo=_cur_link;
1844     else li_hi=_cur_link;
1845     _cur_link=li_lo+(li_hi-li_lo>>1);
1846   }
1847   while(li_hi-li_lo>1);
1848   /*We've identified the link that should contain this page.
1849     Make sure it's a page we care about.*/
1850   if(links[_cur_link].serialno!=_serialno)return OP_FALSE;
1851   return _cur_link;
1852 }
1853 
1854 /*Fetch and process a page.
1855   This handles the case where we're at a bitstream boundary and dumps the
1856    decoding machine.
1857   If the decoding machine is unloaded, it loads it.
1858   It also keeps prev_packet_gp up to date (seek and read both use this).
1859   Return: <0) Error, OP_HOLE (lost packet), or OP_EOF.
1860            0) Got at least one audio data packet.*/
op_fetch_and_process_page(OggOpusFile * _of,ogg_page * _og,opus_int64 _page_offset,int _spanp,int _ignore_holes)1861 static int op_fetch_and_process_page(OggOpusFile *_of,
1862  ogg_page *_og,opus_int64 _page_offset,int _spanp,int _ignore_holes){
1863   OggOpusLink  *links;
1864   ogg_uint32_t  cur_serialno;
1865   int           seekable;
1866   int           cur_link;
1867   int           ret;
1868   /*We shouldn't get here if we have unprocessed packets.*/
1869   OP_ASSERT(_of->ready_state<OP_INITSET||_of->op_pos>=_of->op_count);
1870   seekable=_of->seekable;
1871   links=_of->links;
1872   cur_link=seekable?_of->cur_link:0;
1873   cur_serialno=links[cur_link].serialno;
1874   /*Handle one page.*/
1875   for(;;){
1876     ogg_page og;
1877     OP_ASSERT(_of->ready_state>=OP_OPENED);
1878     /*If we were given a page to use, use it.*/
1879     if(_og!=NULL){
1880       *&og=*_og;
1881       _og=NULL;
1882     }
1883     /*Keep reading until we get a page with the correct serialno.*/
1884     else _page_offset=op_get_next_page(_of,&og,_of->end);
1885     /*EOF: Leave uninitialized.*/
1886     if(_page_offset<0)return _page_offset<OP_FALSE?(int)_page_offset:OP_EOF;
1887     if(OP_LIKELY(_of->ready_state>=OP_STREAMSET)
1888      &&cur_serialno!=(ogg_uint32_t)ogg_page_serialno(&og)){
1889       /*Two possibilities:
1890          1) Another stream is multiplexed into this logical section, or*/
1891       if(OP_LIKELY(!ogg_page_bos(&og)))continue;
1892       /* 2) Our decoding just traversed a bitstream boundary.*/
1893       if(!_spanp)return OP_EOF;
1894       if(OP_LIKELY(_of->ready_state>=OP_INITSET))op_decode_clear(_of);
1895     }
1896     /*Bitrate tracking: add the header's bytes here.
1897       The body bytes are counted when we consume the packets.*/
1898     else _of->bytes_tracked+=og.header_len;
1899     /*Do we need to load a new machine before submitting the page?
1900       This is different in the seekable and non-seekable cases.
1901       In the seekable case, we already have all the header information loaded
1902        and cached.
1903       We just initialize the machine with it and continue on our merry way.
1904       In the non-seekable (streaming) case, we'll only be at a boundary if we
1905        just left the previous logical bitstream, and we're now nominally at the
1906        header of the next bitstream.*/
1907     if(OP_UNLIKELY(_of->ready_state<OP_STREAMSET)){
1908       if(seekable){
1909         ogg_uint32_t serialno;
1910         serialno=ogg_page_serialno(&og);
1911         /*Match the serialno to bitstream section.*/
1912         OP_ASSERT(cur_link>=0&&cur_link<_of->nlinks);
1913         if(links[cur_link].serialno!=serialno){
1914           /*It wasn't a page from the current link.
1915             Is it from the next one?*/
1916           if(OP_LIKELY(cur_link+1<_of->nlinks&&links[cur_link+1].serialno==
1917            serialno)){
1918             cur_link++;
1919           }
1920           else{
1921             int new_link;
1922             new_link=
1923              op_get_link_from_serialno(_of,cur_link,_page_offset,serialno);
1924             /*Not a desired Opus bitstream section.
1925               Keep trying.*/
1926             if(new_link<0)continue;
1927             cur_link=new_link;
1928           }
1929         }
1930         cur_serialno=serialno;
1931         _of->cur_link=cur_link;
1932         ogg_stream_reset_serialno(&_of->os,serialno);
1933         _of->ready_state=OP_STREAMSET;
1934         /*If we're at the start of this link, initialize the granule position
1935            and pre-skip tracking.*/
1936         if(_page_offset<=links[cur_link].data_offset){
1937           _of->prev_packet_gp=links[cur_link].pcm_start;
1938           _of->prev_page_offset=-1;
1939           _of->cur_discard_count=links[cur_link].head.pre_skip;
1940           /*Ignore a hole at the start of a new link (this is common for
1941              streams joined in the middle) or after seeking.*/
1942           _ignore_holes=1;
1943         }
1944       }
1945       else{
1946         do{
1947           /*We're streaming.
1948             Fetch the two header packets, build the info struct.*/
1949           ret=op_fetch_headers(_of,&links[0].head,&links[0].tags,
1950            NULL,NULL,NULL,&og);
1951           if(OP_UNLIKELY(ret<0))return ret;
1952           /*op_find_initial_pcm_offset() will suppress any initial hole for us,
1953              so no need to set _ignore_holes.*/
1954           ret=op_find_initial_pcm_offset(_of,links,&og);
1955           if(OP_UNLIKELY(ret<0))return ret;
1956           _of->links[0].serialno=cur_serialno=_of->os.serialno;
1957           _of->cur_link++;
1958         }
1959         /*If the link was empty, keep going, because we already have the
1960            BOS page of the next one in og.*/
1961         while(OP_UNLIKELY(ret>0));
1962         /*If we didn't get any packets out of op_find_initial_pcm_offset(),
1963            keep going (this is possible if end-trimming trimmed them all).*/
1964         if(_of->op_count<=0)continue;
1965         /*Otherwise, we're done.
1966           TODO: This resets bytes_tracked, which misses the header bytes
1967            already processed by op_find_initial_pcm_offset().*/
1968         ret=op_make_decode_ready(_of);
1969         if(OP_UNLIKELY(ret<0))return ret;
1970         return 0;
1971       }
1972     }
1973     /*The buffered page is the data we want, and we're ready for it.
1974       Add it to the stream state.*/
1975     if(OP_UNLIKELY(_of->ready_state==OP_STREAMSET)){
1976       ret=op_make_decode_ready(_of);
1977       if(OP_UNLIKELY(ret<0))return ret;
1978     }
1979     /*Extract all the packets from the current page.*/
1980     ogg_stream_pagein(&_of->os,&og);
1981     if(OP_LIKELY(_of->ready_state>=OP_INITSET)){
1982       opus_int32 total_duration;
1983       int        durations[255];
1984       int        op_count;
1985       int        report_hole;
1986       report_hole=0;
1987       total_duration=op_collect_audio_packets(_of,durations);
1988       if(OP_UNLIKELY(total_duration<0)){
1989         /*libogg reported a hole (a gap in the page sequence numbers).
1990           Drain the packets from the page anyway.
1991           If we don't, they'll still be there when we fetch the next page.
1992           Then, when we go to pull out packets, we might get more than 255,
1993            which would overrun our packet buffer.
1994           We repeat this call until we get any actual packets, since we might
1995            have buffered multiple out-of-sequence pages with no packets on
1996            them.*/
1997         do total_duration=op_collect_audio_packets(_of,durations);
1998         while(total_duration<0);
1999         if(!_ignore_holes){
2000           /*Report the hole to the caller after we finish timestamping the
2001              packets.*/
2002           report_hole=1;
2003           /*We had lost or damaged pages, so reset our granule position
2004              tracking.
2005             This makes holes behave the same as a small raw seek.
2006             If the next page is the EOS page, we'll discard it (because we
2007              can't perform end trimming properly), and we'll always discard at
2008              least 80 ms of audio (to allow decoder state to re-converge).
2009             We could try to fill in the gap with PLC by looking at timestamps
2010              in the non-EOS case, but that's complicated and error prone and we
2011              can't rely on the timestamps being valid.*/
2012           _of->prev_packet_gp=-1;
2013         }
2014       }
2015       op_count=_of->op_count;
2016       /*If we found at least one audio data packet, compute per-packet granule
2017          positions for them.*/
2018       if(op_count>0){
2019         ogg_int64_t diff;
2020         ogg_int64_t prev_packet_gp;
2021         ogg_int64_t cur_packet_gp;
2022         ogg_int64_t cur_page_gp;
2023         int         cur_page_eos;
2024         int         pi;
2025         cur_page_gp=_of->op[op_count-1].granulepos;
2026         cur_page_eos=_of->op[op_count-1].e_o_s;
2027         prev_packet_gp=_of->prev_packet_gp;
2028         if(OP_UNLIKELY(prev_packet_gp==-1)){
2029           opus_int32 cur_discard_count;
2030           /*This is the first call after a raw seek.
2031             Try to reconstruct prev_packet_gp from scratch.*/
2032           OP_ASSERT(seekable);
2033           if(OP_UNLIKELY(cur_page_eos)){
2034             /*If the first page we hit after our seek was the EOS page, and
2035                we didn't start from data_offset or before, we don't have
2036                enough information to do end-trimming.
2037               Proceed to the next link, rather than risk playing back some
2038                samples that shouldn't have been played.*/
2039             _of->op_count=0;
2040             if(report_hole)return OP_HOLE;
2041             continue;
2042           }
2043           /*By default discard 80 ms of data after a seek, unless we seek
2044              into the pre-skip region.*/
2045           cur_discard_count=80*48;
2046           cur_page_gp=_of->op[op_count-1].granulepos;
2047           /*Try to initialize prev_packet_gp.
2048             If the current page had packets but didn't have a granule
2049              position, or the granule position it had was too small (both
2050              illegal), just use the starting granule position for the link.*/
2051           prev_packet_gp=links[cur_link].pcm_start;
2052           if(OP_LIKELY(cur_page_gp!=-1)){
2053             op_granpos_add(&prev_packet_gp,cur_page_gp,-total_duration);
2054           }
2055           if(OP_LIKELY(!op_granpos_diff(&diff,
2056            prev_packet_gp,links[cur_link].pcm_start))){
2057             opus_int32 pre_skip;
2058             /*If we start at the beginning of the pre-skip region, or we're
2059                at least 80 ms from the end of the pre-skip region, we discard
2060                to the end of the pre-skip region.
2061               Otherwise, we still use the 80 ms default, which will discard
2062                past the end of the pre-skip region.*/
2063             pre_skip=links[cur_link].head.pre_skip;
2064             if(diff>=0&&diff<=OP_MAX(0,pre_skip-80*48)){
2065               cur_discard_count=pre_skip-(int)diff;
2066             }
2067           }
2068           _of->cur_discard_count=cur_discard_count;
2069         }
2070         if(OP_UNLIKELY(cur_page_gp==-1)){
2071           /*This page had completed packets but didn't have a valid granule
2072              position.
2073             This is illegal, but we'll try to handle it by continuing to count
2074              forwards from the previous page.*/
2075           if(op_granpos_add(&cur_page_gp,prev_packet_gp,total_duration)<0){
2076             /*The timestamp for this page overflowed.*/
2077             cur_page_gp=links[cur_link].pcm_end;
2078           }
2079         }
2080         /*If we hit the last page, handle end-trimming.*/
2081         if(OP_UNLIKELY(cur_page_eos)
2082          &&OP_LIKELY(!op_granpos_diff(&diff,cur_page_gp,prev_packet_gp))
2083          &&OP_LIKELY(diff<total_duration)){
2084           cur_packet_gp=prev_packet_gp;
2085           for(pi=0;pi<op_count;pi++){
2086             /*Check for overflow.*/
2087             if(diff<0&&OP_UNLIKELY(OP_INT64_MAX+diff<durations[pi])){
2088               diff=durations[pi]+1;
2089             }
2090             else diff=durations[pi]-diff;
2091             /*If we have samples to trim...*/
2092             if(diff>0){
2093               /*If we trimmed the entire packet, stop (the spec says encoders
2094                  shouldn't do this, but we support it anyway).*/
2095               if(OP_UNLIKELY(diff>durations[pi]))break;
2096               cur_packet_gp=cur_page_gp;
2097               /*Move the EOS flag to this packet, if necessary, so we'll trim
2098                  the samples during decode.*/
2099               _of->op[pi].e_o_s=1;
2100             }
2101             else{
2102               /*Update the granule position as normal.*/
2103               OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp,
2104                cur_packet_gp,durations[pi]));
2105             }
2106             _of->op[pi].granulepos=cur_packet_gp;
2107             OP_ALWAYS_TRUE(!op_granpos_diff(&diff,cur_page_gp,cur_packet_gp));
2108           }
2109         }
2110         else{
2111           /*Propagate timestamps to earlier packets.
2112             op_granpos_add(&prev_packet_gp,prev_packet_gp,total_duration)
2113              should succeed and give prev_packet_gp==cur_page_gp.
2114             But we don't bother to check that, as there isn't much we can do
2115              if it's not true, and it actually will not be true on the first
2116              page after a seek, if there was a continued packet.
2117             The only thing we guarantee is that the start and end granule
2118              positions of the packets are valid, and that they are monotonic
2119              within a page.
2120             They might be completely out of range for this link (we'll check
2121              that elsewhere), or non-monotonic between pages.*/
2122           if(OP_UNLIKELY(op_granpos_add(&prev_packet_gp,
2123            cur_page_gp,-total_duration)<0)){
2124             /*The starting timestamp for the first packet on this page
2125                underflowed.
2126               This is illegal, but we ignore it.*/
2127             prev_packet_gp=0;
2128           }
2129           for(pi=0;pi<op_count;pi++){
2130             if(OP_UNLIKELY(op_granpos_add(&cur_packet_gp,
2131              cur_page_gp,-total_duration)<0)){
2132               /*The start timestamp for this packet underflowed.
2133                 This is illegal, but we ignore it.*/
2134               cur_packet_gp=0;
2135             }
2136             total_duration-=durations[pi];
2137             OP_ASSERT(total_duration>=0);
2138             OP_ALWAYS_TRUE(!op_granpos_add(&cur_packet_gp,
2139              cur_packet_gp,durations[pi]));
2140             _of->op[pi].granulepos=cur_packet_gp;
2141           }
2142           OP_ASSERT(total_duration==0);
2143         }
2144         _of->prev_packet_gp=prev_packet_gp;
2145         _of->prev_page_offset=_page_offset;
2146         _of->op_count=op_count=pi;
2147       }
2148       if(report_hole)return OP_HOLE;
2149       /*If end-trimming didn't trim all the packets, we're done.*/
2150       if(op_count>0)return 0;
2151     }
2152   }
2153 }
2154 
op_raw_seek(OggOpusFile * _of,opus_int64 _pos)2155 int op_raw_seek(OggOpusFile *_of,opus_int64 _pos){
2156   int ret;
2157   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
2158   /*Don't dump the decoder state if we can't seek.*/
2159   if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK;
2160   if(OP_UNLIKELY(_pos<0)||OP_UNLIKELY(_pos>_of->end))return OP_EINVAL;
2161   /*Clear out any buffered, decoded data.*/
2162   op_decode_clear(_of);
2163   _of->bytes_tracked=0;
2164   _of->samples_tracked=0;
2165   ret=op_seek_helper(_of,_pos);
2166   if(OP_UNLIKELY(ret<0))return OP_EREAD;
2167   ret=op_fetch_and_process_page(_of,NULL,-1,1,1);
2168   /*If we hit EOF, op_fetch_and_process_page() leaves us uninitialized.
2169     Instead, jump to the end.*/
2170   if(ret==OP_EOF){
2171     int cur_link;
2172     op_decode_clear(_of);
2173     cur_link=_of->nlinks-1;
2174     _of->cur_link=cur_link;
2175     _of->prev_packet_gp=_of->links[cur_link].pcm_end;
2176     _of->cur_discard_count=0;
2177     ret=0;
2178   }
2179   return ret;
2180 }
2181 
2182 /*Convert a PCM offset relative to the start of the whole stream to a granule
2183    position in an individual link.*/
op_get_granulepos(const OggOpusFile * _of,ogg_int64_t _pcm_offset,int * _li)2184 static ogg_int64_t op_get_granulepos(const OggOpusFile *_of,
2185  ogg_int64_t _pcm_offset,int *_li){
2186   const OggOpusLink *links;
2187   ogg_int64_t        duration;
2188   ogg_int64_t        pcm_start;
2189   opus_int32         pre_skip;
2190   int                nlinks;
2191   int                li_lo;
2192   int                li_hi;
2193   OP_ASSERT(_pcm_offset>=0);
2194   nlinks=_of->nlinks;
2195   links=_of->links;
2196   li_lo=0;
2197   li_hi=nlinks;
2198   do{
2199     int li;
2200     li=li_lo+(li_hi-li_lo>>1);
2201     if(links[li].pcm_file_offset<=_pcm_offset)li_lo=li;
2202     else li_hi=li;
2203   }
2204   while(li_hi-li_lo>1);
2205   _pcm_offset-=links[li_lo].pcm_file_offset;
2206   pcm_start=links[li_lo].pcm_start;
2207   pre_skip=links[li_lo].head.pre_skip;
2208   OP_ALWAYS_TRUE(!op_granpos_diff(&duration,links[li_lo].pcm_end,pcm_start));
2209   duration-=pre_skip;
2210   if(_pcm_offset>=duration)return -1;
2211   _pcm_offset+=pre_skip;
2212   if(OP_UNLIKELY(pcm_start>OP_INT64_MAX-_pcm_offset)){
2213     /*Adding this amount to the granule position would overflow the positive
2214        half of its 64-bit range.
2215       Since signed overflow is undefined in C, do it in a way the compiler
2216        isn't allowed to screw up.*/
2217     _pcm_offset-=OP_INT64_MAX-pcm_start+1;
2218     pcm_start=OP_INT64_MIN;
2219   }
2220   pcm_start+=_pcm_offset;
2221   *_li=li_lo;
2222   return pcm_start;
2223 }
2224 
2225 /*A small helper to determine if an Ogg page contains data that continues onto
2226    a subsequent page.*/
op_page_continues(const ogg_page * _og)2227 static int op_page_continues(const ogg_page *_og){
2228   int nlacing;
2229   OP_ASSERT(_og->header_len>=27);
2230   nlacing=_og->header[26];
2231   OP_ASSERT(_og->header_len>=27+nlacing);
2232   /*This also correctly handles the (unlikely) case of nlacing==0, because
2233      0!=255.*/
2234   return _og->header[27+nlacing-1]==255;
2235 }
2236 
2237 /*A small helper to buffer the continued packet data from a page.*/
op_buffer_continued_data(OggOpusFile * _of,ogg_page * _og)2238 static void op_buffer_continued_data(OggOpusFile *_of,ogg_page *_og){
2239   ogg_packet op;
2240   ogg_stream_pagein(&_of->os,_og);
2241   /*Drain any packets that did end on this page (and ignore holes).
2242     We only care about the continued packet data.*/
2243   while(ogg_stream_packetout(&_of->os,&op));
2244 }
2245 
2246 /*This controls how close the target has to be to use the current stream
2247    position to subdivide the initial range.
2248   Two minutes seems to be a good default.*/
2249 #define OP_CUR_TIME_THRESH (120*48*(opus_int32)1000)
2250 
2251 /*Note: The OP_SMALL_FOOTPRINT #define doesn't (currently) save much code size,
2252    but it's meant to serve as documentation for portions of the seeking
2253    algorithm that are purely optional, to aid others learning from/porting this
2254    code to other contexts.*/
2255 /*#define OP_SMALL_FOOTPRINT (1)*/
2256 
2257 /*Search within link _li for the page with the highest granule position
2258    preceding (or equal to) _target_gp.
2259   There is a danger here: missing pages or incorrect frame number information
2260    in the bitstream could make our task impossible.
2261   Account for that (and report it as an error condition).*/
op_pcm_seek_page(OggOpusFile * _of,ogg_int64_t _target_gp,int _li)2262 static int op_pcm_seek_page(OggOpusFile *_of,
2263  ogg_int64_t _target_gp,int _li){
2264   const OggOpusLink *link;
2265   ogg_page           og;
2266   ogg_int64_t        pcm_pre_skip;
2267   ogg_int64_t        pcm_start;
2268   ogg_int64_t        pcm_end;
2269   ogg_int64_t        best_gp;
2270   ogg_int64_t        diff;
2271   ogg_uint32_t       serialno;
2272   opus_int32         pre_skip;
2273   opus_int64         begin;
2274   opus_int64         end;
2275   opus_int64         boundary;
2276   opus_int64         best;
2277   opus_int64         best_start;
2278   opus_int64         page_offset;
2279   opus_int64         d0;
2280   opus_int64         d1;
2281   opus_int64         d2;
2282   int                force_bisect;
2283   int                buffering;
2284   int                ret;
2285   _of->bytes_tracked=0;
2286   _of->samples_tracked=0;
2287   link=_of->links+_li;
2288   best_gp=pcm_start=link->pcm_start;
2289   pcm_end=link->pcm_end;
2290   serialno=link->serialno;
2291   best=best_start=begin=link->data_offset;
2292   page_offset=-1;
2293   buffering=0;
2294   /*We discard the first 80 ms of data after a seek, so seek back that much
2295      farther.
2296     If we can't, simply seek to the beginning of the link.*/
2297   if(OP_UNLIKELY(op_granpos_add(&_target_gp,_target_gp,-80*48)<0)
2298    ||OP_UNLIKELY(op_granpos_cmp(_target_gp,pcm_start)<0)){
2299     _target_gp=pcm_start;
2300   }
2301   /*Special case seeking to the start of the link.*/
2302   pre_skip=link->head.pre_skip;
2303   OP_ALWAYS_TRUE(!op_granpos_add(&pcm_pre_skip,pcm_start,pre_skip));
2304   if(op_granpos_cmp(_target_gp,pcm_pre_skip)<0)end=boundary=begin;
2305   else{
2306     end=boundary=link->end_offset;
2307 #if !defined(OP_SMALL_FOOTPRINT)
2308     /*If we were decoding from this link, we can narrow the range a bit.*/
2309     if(_li==_of->cur_link&&_of->ready_state>=OP_INITSET){
2310       opus_int64 offset;
2311       int        op_count;
2312       op_count=_of->op_count;
2313       /*The only way the offset can be invalid _and_ we can fail the granule
2314          position checks below is if someone changed the contents of the last
2315          page since we read it.
2316         We'd be within our rights to just return OP_EBADLINK in that case, but
2317          we'll simply ignore the current position instead.*/
2318       offset=_of->offset;
2319       if(op_count>0&&OP_LIKELY(offset<=end)){
2320         ogg_int64_t gp;
2321         /*Make sure the timestamp is valid.
2322           The granule position might be -1 if we collected the packets from a
2323            page without a granule position after reporting a hole.*/
2324         gp=_of->op[op_count-1].granulepos;
2325         if(OP_LIKELY(gp!=-1)&&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<0)
2326          &&OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0)){
2327           OP_ALWAYS_TRUE(!op_granpos_diff(&diff,gp,_target_gp));
2328           /*We only actually use the current time if either
2329             a) We can cut off at least half the range, or
2330             b) We're seeking sufficiently close to the current position that
2331                 it's likely to be informative.
2332             Otherwise it appears using the whole link range to estimate the
2333              first seek location gives better results, on average.*/
2334           if(diff<0){
2335             OP_ASSERT(offset>=begin);
2336             if(offset-begin>=end-begin>>1||diff>-OP_CUR_TIME_THRESH){
2337               best=begin=offset;
2338               best_gp=pcm_start=gp;
2339               /*If we have buffered data from a continued packet, remember the
2340                  offset of the previous page's start, so that if we do wind up
2341                  having to seek back here later, we can prime the stream with
2342                  the continued packet data.
2343                 With no continued packet, we remember the end of the page.*/
2344               best_start=_of->os.body_returned<_of->os.body_fill?
2345                _of->prev_page_offset:best;
2346               /*If there's completed packets and data in the stream state,
2347                  prev_page_offset should always be set.*/
2348               OP_ASSERT(best_start>=0);
2349               /*Buffer any continued packet data starting from here.*/
2350               buffering=1;
2351             }
2352           }
2353           else{
2354             ogg_int64_t prev_page_gp;
2355             /*We might get lucky and already have the packet with the target
2356                buffered.
2357               Worth checking.
2358               For very small files (with all of the data in a single page,
2359                generally 1 second or less), we can loop them continuously
2360                without seeking at all.*/
2361             OP_ALWAYS_TRUE(!op_granpos_add(&prev_page_gp,_of->op[0].granulepos,
2362              -op_get_packet_duration(_of->op[0].packet,_of->op[0].bytes)));
2363             if(op_granpos_cmp(prev_page_gp,_target_gp)<=0){
2364               /*Don't call op_decode_clear(), because it will dump our
2365                  packets.*/
2366               _of->op_pos=0;
2367               _of->od_buffer_size=0;
2368               _of->prev_packet_gp=prev_page_gp;
2369               /*_of->prev_page_offset already points to the right place.*/
2370               _of->ready_state=OP_STREAMSET;
2371               return op_make_decode_ready(_of);
2372             }
2373             /*No such luck.
2374               Check if we can cut off at least half the range, though.*/
2375             if(offset-begin<=end-begin>>1||diff<OP_CUR_TIME_THRESH){
2376               /*We really want the page start here, but this will do.*/
2377               end=boundary=offset;
2378               pcm_end=gp;
2379             }
2380           }
2381         }
2382       }
2383     }
2384 #endif
2385   }
2386   /*This code was originally based on the "new search algorithm by HB (Nicholas
2387      Vinen)" from libvorbisfile.
2388     It has been modified substantially since.*/
2389   op_decode_clear(_of);
2390   if(!buffering)ogg_stream_reset_serialno(&_of->os,serialno);
2391   _of->cur_link=_li;
2392   _of->ready_state=OP_STREAMSET;
2393   /*Initialize the interval size history.*/
2394   d2=d1=d0=end-begin;
2395   force_bisect=0;
2396   while(begin<end){
2397     opus_int64 bisect;
2398     opus_int64 next_boundary;
2399     opus_int32 chunk_size;
2400     if(end-begin<OP_CHUNK_SIZE)bisect=begin;
2401     else{
2402       /*Update the interval size history.*/
2403       d0=d1>>1;
2404       d1=d2>>1;
2405       d2=end-begin>>1;
2406       if(force_bisect)bisect=begin+(end-begin>>1);
2407       else{
2408         ogg_int64_t diff2;
2409         OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start));
2410         OP_ALWAYS_TRUE(!op_granpos_diff(&diff2,pcm_end,pcm_start));
2411         /*Take a (pretty decent) guess.*/
2412         bisect=begin+op_rescale64(diff,diff2,end-begin)-OP_CHUNK_SIZE;
2413       }
2414       if(bisect-OP_CHUNK_SIZE<begin)bisect=begin;
2415       force_bisect=0;
2416     }
2417     if(bisect!=_of->offset){
2418       /*Discard any buffered continued packet data.*/
2419       if(buffering)ogg_stream_reset(&_of->os);
2420       buffering=0;
2421       page_offset=-1;
2422       ret=op_seek_helper(_of,bisect);
2423       if(OP_UNLIKELY(ret<0))return ret;
2424     }
2425     chunk_size=OP_CHUNK_SIZE;
2426     next_boundary=boundary;
2427     /*Now scan forward and figure out where we landed.
2428       In the ideal case, we will see a page with a granule position at or
2429        before our target, followed by a page with a granule position after our
2430        target (or the end of the search interval).
2431       Then we can just drop out and will have all of the data we need with no
2432        additional seeking.
2433       If we landed too far before, or after, we'll break out and do another
2434        bisection.*/
2435     while(begin<end){
2436       page_offset=op_get_next_page(_of,&og,boundary);
2437       if(page_offset<0){
2438         if(page_offset<OP_FALSE)return (int)page_offset;
2439         /*There are no more pages in our interval from our stream with a valid
2440            timestamp that start at position bisect or later.*/
2441         /*If we scanned the whole interval, we're done.*/
2442         if(bisect<=begin+1)end=begin;
2443         else{
2444           /*Otherwise, back up one chunk.
2445             First, discard any data from a continued packet.*/
2446           if(buffering)ogg_stream_reset(&_of->os);
2447           buffering=0;
2448           bisect=OP_MAX(bisect-chunk_size,begin);
2449           ret=op_seek_helper(_of,bisect);
2450           if(OP_UNLIKELY(ret<0))return ret;
2451           /*Bump up the chunk size.*/
2452           chunk_size=OP_MIN(2*chunk_size,OP_CHUNK_SIZE_MAX);
2453           /*If we did find a page from another stream or without a timestamp,
2454              don't read past it.*/
2455           boundary=next_boundary;
2456         }
2457       }
2458       else{
2459         ogg_int64_t gp;
2460         int         has_packets;
2461         /*Save the offset of the first page we found after the seek, regardless
2462            of the stream it came from or whether or not it has a timestamp.*/
2463         next_boundary=OP_MIN(page_offset,next_boundary);
2464         if(serialno!=(ogg_uint32_t)ogg_page_serialno(&og))continue;
2465         has_packets=ogg_page_packets(&og)>0;
2466         /*Force the gp to -1 (as it should be per spec) if no packets end on
2467            this page.
2468           Otherwise we might get confused when we try to pull out a packet
2469            with that timestamp and can't find it.*/
2470         gp=has_packets?ogg_page_granulepos(&og):-1;
2471         if(gp==-1){
2472           if(buffering){
2473             if(OP_LIKELY(!has_packets))ogg_stream_pagein(&_of->os,&og);
2474             else{
2475               /*If packets did end on this page, but we still didn't have a
2476                  valid granule position (in violation of the spec!), stop
2477                  buffering continued packet data.
2478                 Otherwise we might continue past the packet we actually
2479                  wanted.*/
2480               ogg_stream_reset(&_of->os);
2481               buffering=0;
2482             }
2483           }
2484           continue;
2485         }
2486         if(op_granpos_cmp(gp,_target_gp)<0){
2487           /*We found a page that ends before our target.
2488             Advance to the raw offset of the next page.*/
2489           begin=_of->offset;
2490           if(OP_UNLIKELY(op_granpos_cmp(pcm_start,gp)>0)
2491            ||OP_UNLIKELY(op_granpos_cmp(pcm_end,gp)<0)){
2492             /*Don't let pcm_start get out of range!
2493               That could happen with an invalid timestamp.*/
2494             break;
2495           }
2496           /*Save the byte offset of the end of the page with this granule
2497              position.*/
2498           best=best_start=begin;
2499           /*Buffer any data from a continued packet, if necessary.
2500             This avoids the need to seek back here if the next timestamp we
2501              encounter while scanning forward lies after our target.*/
2502           if(buffering)ogg_stream_reset(&_of->os);
2503           if(op_page_continues(&og)){
2504             op_buffer_continued_data(_of,&og);
2505             /*If we have a continued packet, remember the offset of this
2506                page's start, so that if we do wind up having to seek back here
2507                later, we can prime the stream with the continued packet data.
2508               With no continued packet, we remember the end of the page.*/
2509             best_start=page_offset;
2510           }
2511           /*Then force buffering on, so that if a packet starts (but does not
2512              end) on the next page, we still avoid the extra seek back.*/
2513           buffering=1;
2514           best_gp=pcm_start=gp;
2515           OP_ALWAYS_TRUE(!op_granpos_diff(&diff,_target_gp,pcm_start));
2516           /*If we're more than a second away from our target, break out and
2517              do another bisection.*/
2518           if(diff>48000)break;
2519           /*Otherwise, keep scanning forward (do NOT use begin+1).*/
2520           bisect=begin;
2521         }
2522         else{
2523           /*We found a page that ends after our target.*/
2524           /*If we scanned the whole interval before we found it, we're done.*/
2525           if(bisect<=begin+1)end=begin;
2526           else{
2527             end=bisect;
2528             /*In later iterations, don't read past the first page we found.*/
2529             boundary=next_boundary;
2530             /*If we're not making much progress shrinking the interval size,
2531                start forcing straight bisection to limit the worst case.*/
2532             force_bisect=end-begin>d0*2;
2533             /*Don't let pcm_end get out of range!
2534               That could happen with an invalid timestamp.*/
2535             if(OP_LIKELY(op_granpos_cmp(pcm_end,gp)>0)
2536              &&OP_LIKELY(op_granpos_cmp(pcm_start,gp)<=0)){
2537               pcm_end=gp;
2538             }
2539             break;
2540           }
2541         }
2542       }
2543     }
2544   }
2545   /*Found our page.*/
2546   OP_ASSERT(op_granpos_cmp(best_gp,pcm_start)>=0);
2547   /*Seek, if necessary.
2548     If we were buffering data from a continued packet, we should be able to
2549      continue to scan forward to get the rest of the data (even if
2550      page_offset==-1).
2551     Otherwise, we need to seek back to best_start.*/
2552   if(!buffering){
2553     if(best_start!=page_offset){
2554       page_offset=-1;
2555       ret=op_seek_helper(_of,best_start);
2556       if(OP_UNLIKELY(ret<0))return ret;
2557     }
2558     if(best_start<best){
2559       /*Retrieve the page at best_start, if we do not already have it.*/
2560       if(page_offset<0){
2561         page_offset=op_get_next_page(_of,&og,link->end_offset);
2562         if(OP_UNLIKELY(page_offset<OP_FALSE))return (int)page_offset;
2563         if(OP_UNLIKELY(page_offset!=best_start))return OP_EBADLINK;
2564       }
2565       op_buffer_continued_data(_of,&og);
2566       page_offset=-1;
2567     }
2568   }
2569   /*Update prev_packet_gp to allow per-packet granule position assignment.*/
2570   _of->prev_packet_gp=best_gp;
2571   _of->prev_page_offset=best_start;
2572   ret=op_fetch_and_process_page(_of,page_offset<0?NULL:&og,page_offset,0,1);
2573   if(OP_UNLIKELY(ret<0))return OP_EBADLINK;
2574   /*Verify result.*/
2575   if(OP_UNLIKELY(op_granpos_cmp(_of->prev_packet_gp,_target_gp)>0)){
2576     return OP_EBADLINK;
2577   }
2578   /*Our caller will set cur_discard_count to handle pre-roll.*/
2579   return 0;
2580 }
2581 
op_pcm_seek(OggOpusFile * _of,ogg_int64_t _pcm_offset)2582 int op_pcm_seek(OggOpusFile *_of,ogg_int64_t _pcm_offset){
2583   const OggOpusLink *link;
2584   ogg_int64_t        pcm_start;
2585   ogg_int64_t        target_gp;
2586   ogg_int64_t        prev_packet_gp;
2587   ogg_int64_t        skip;
2588   ogg_int64_t        diff;
2589   int                op_count;
2590   int                op_pos;
2591   int                ret;
2592   int                li;
2593   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
2594   if(OP_UNLIKELY(!_of->seekable))return OP_ENOSEEK;
2595   if(OP_UNLIKELY(_pcm_offset<0))return OP_EINVAL;
2596   target_gp=op_get_granulepos(_of,_pcm_offset,&li);
2597   if(OP_UNLIKELY(target_gp==-1))return OP_EINVAL;
2598   link=_of->links+li;
2599   pcm_start=link->pcm_start;
2600   OP_ALWAYS_TRUE(!op_granpos_diff(&_pcm_offset,target_gp,pcm_start));
2601 #if !defined(OP_SMALL_FOOTPRINT)
2602   /*For small (90 ms or less) forward seeks within the same link, just decode
2603      forward.
2604     This also optimizes the case of seeking to the current position.*/
2605   if(li==_of->cur_link&&_of->ready_state>=OP_INITSET){
2606     ogg_int64_t gp;
2607     gp=_of->prev_packet_gp;
2608     if(OP_LIKELY(gp!=-1)){
2609       ogg_int64_t discard_count;
2610       int         nbuffered;
2611       nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0);
2612       OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered));
2613       /*We do _not_ add cur_discard_count to gp.
2614         Otherwise the total amount to discard could grow without bound, and it
2615          would be better just to do a full seek.*/
2616       if(OP_LIKELY(!op_granpos_diff(&discard_count,target_gp,gp))){
2617         /*We use a threshold of 90 ms instead of 80, since 80 ms is the
2618            _minimum_ we would have discarded after a full seek.
2619           Assuming 20 ms frames (the default), we'd discard 90 ms on average.*/
2620         if(discard_count>=0&&OP_UNLIKELY(discard_count<90*48)){
2621           _of->cur_discard_count=(opus_int32)discard_count;
2622           return 0;
2623         }
2624       }
2625     }
2626   }
2627 #endif
2628   ret=op_pcm_seek_page(_of,target_gp,li);
2629   if(OP_UNLIKELY(ret<0))return ret;
2630   /*Now skip samples until we actually get to our target.*/
2631   /*Figure out where we should skip to.*/
2632   if(_pcm_offset<=link->head.pre_skip)skip=0;
2633   else skip=OP_MAX(_pcm_offset-80*48,0);
2634   OP_ASSERT(_pcm_offset-skip>=0);
2635   OP_ASSERT(_pcm_offset-skip<OP_INT32_MAX-120*48);
2636   /*Skip packets until we find one with samples past our skip target.*/
2637   for(;;){
2638     op_count=_of->op_count;
2639     prev_packet_gp=_of->prev_packet_gp;
2640     for(op_pos=_of->op_pos;op_pos<op_count;op_pos++){
2641       ogg_int64_t cur_packet_gp;
2642       cur_packet_gp=_of->op[op_pos].granulepos;
2643       if(OP_LIKELY(!op_granpos_diff(&diff,cur_packet_gp,pcm_start))
2644        &&diff>skip){
2645         break;
2646       }
2647       prev_packet_gp=cur_packet_gp;
2648     }
2649     _of->prev_packet_gp=prev_packet_gp;
2650     _of->op_pos=op_pos;
2651     if(op_pos<op_count)break;
2652     /*We skipped all the packets on this page.
2653       Fetch another.*/
2654     ret=op_fetch_and_process_page(_of,NULL,-1,0,1);
2655     if(OP_UNLIKELY(ret<0))return OP_EBADLINK;
2656   }
2657   /*We skipped too far, or couldn't get within 2 billion samples of the target.
2658     Either the timestamps were illegal or there was a hole in the data.*/
2659   if(op_granpos_diff(&diff,prev_packet_gp,pcm_start)||diff>skip
2660    ||_pcm_offset-diff>=OP_INT32_MAX){
2661     return OP_EBADLINK;
2662   }
2663   /*TODO: If there are further holes/illegal timestamps, we still won't decode
2664      to the correct sample.
2665     However, at least op_pcm_tell() will report the correct value immediately
2666      after returning.*/
2667   _of->cur_discard_count=(opus_int32)(_pcm_offset-diff);
2668   return 0;
2669 }
2670 
op_raw_tell(const OggOpusFile * _of)2671 opus_int64 op_raw_tell(const OggOpusFile *_of){
2672   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
2673   return _of->offset;
2674 }
2675 
2676 /*Convert a granule position from a given link to a PCM offset relative to the
2677    start of the whole stream.
2678   For unseekable sources, this gets reset to 0 at the beginning of each link.*/
op_get_pcm_offset(const OggOpusFile * _of,ogg_int64_t _gp,int _li)2679 static ogg_int64_t op_get_pcm_offset(const OggOpusFile *_of,
2680  ogg_int64_t _gp,int _li){
2681   const OggOpusLink *links;
2682   ogg_int64_t        pcm_offset;
2683   links=_of->links;
2684   OP_ASSERT(_li>=0&&_li<_of->nlinks);
2685   pcm_offset=links[_li].pcm_file_offset;
2686   if(_of->seekable&&OP_UNLIKELY(op_granpos_cmp(_gp,links[_li].pcm_end)>0)){
2687     _gp=links[_li].pcm_end;
2688   }
2689   if(OP_LIKELY(op_granpos_cmp(_gp,links[_li].pcm_start)>0)){
2690     ogg_int64_t delta;
2691     if(OP_UNLIKELY(op_granpos_diff(&delta,_gp,links[_li].pcm_start)<0)){
2692       /*This means an unseekable stream claimed to have a page from more than
2693          2 billion days after we joined.*/
2694       OP_ASSERT(!_of->seekable);
2695       return OP_INT64_MAX;
2696     }
2697     if(delta<links[_li].head.pre_skip)delta=0;
2698     else delta-=links[_li].head.pre_skip;
2699     /*In the seekable case, _gp was limited by pcm_end.
2700       In the unseekable case, pcm_offset should be 0.*/
2701     OP_ASSERT(pcm_offset<=OP_INT64_MAX-delta);
2702     pcm_offset+=delta;
2703   }
2704   return pcm_offset;
2705 }
2706 
op_pcm_tell(const OggOpusFile * _of)2707 ogg_int64_t op_pcm_tell(const OggOpusFile *_of){
2708   ogg_int64_t gp;
2709   int         nbuffered;
2710   int         li;
2711   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
2712   gp=_of->prev_packet_gp;
2713   if(gp==-1)return 0;
2714   nbuffered=OP_MAX(_of->od_buffer_size-_of->od_buffer_pos,0);
2715   OP_ALWAYS_TRUE(!op_granpos_add(&gp,gp,-nbuffered));
2716   li=_of->seekable?_of->cur_link:0;
2717   if(op_granpos_add(&gp,gp,_of->cur_discard_count)<0){
2718     gp=_of->links[li].pcm_end;
2719   }
2720   return op_get_pcm_offset(_of,gp,li);
2721 }
2722 
op_set_decode_callback(OggOpusFile * _of,op_decode_cb_func _decode_cb,void * _ctx)2723 void op_set_decode_callback(OggOpusFile *_of,
2724  op_decode_cb_func _decode_cb,void *_ctx){
2725   _of->decode_cb=_decode_cb;
2726   _of->decode_cb_ctx=_ctx;
2727 }
2728 
op_set_gain_offset(OggOpusFile * _of,int _gain_type,opus_int32 _gain_offset_q8)2729 int op_set_gain_offset(OggOpusFile *_of,
2730  int _gain_type,opus_int32 _gain_offset_q8){
2731   if(_gain_type!=OP_HEADER_GAIN&&_gain_type!=OP_ALBUM_GAIN
2732    &&_gain_type!=OP_TRACK_GAIN&&_gain_type!=OP_ABSOLUTE_GAIN){
2733     return OP_EINVAL;
2734   }
2735   _of->gain_type=_gain_type;
2736   /*The sum of header gain and track gain lies in the range [-65536,65534].
2737     These bounds allow the offset to set the final value to anywhere in the
2738      range [-32768,32767], which is what we'll clamp it to before applying.*/
2739   _of->gain_offset_q8=OP_CLAMP(-98302,_gain_offset_q8,98303);
2740   op_update_gain(_of);
2741   return 0;
2742 }
2743 
op_set_dither_enabled(OggOpusFile * _of,int _enabled)2744 void op_set_dither_enabled(OggOpusFile *_of,int _enabled){
2745 #if !defined(OP_FIXED_POINT)
2746   _of->dither_disabled=!_enabled;
2747   if(!_enabled)_of->dither_mute=65;
2748 #endif
2749 }
2750 
2751 /*Allocate the decoder scratch buffer.
2752   This is done lazily, since if the user provides large enough buffers, we'll
2753    never need it.*/
op_init_buffer(OggOpusFile * _of)2754 static int op_init_buffer(OggOpusFile *_of){
2755   int nchannels_max;
2756   if(_of->seekable){
2757     const OggOpusLink *links;
2758     int                nlinks;
2759     int                li;
2760     links=_of->links;
2761     nlinks=_of->nlinks;
2762     nchannels_max=1;
2763     for(li=0;li<nlinks;li++){
2764       nchannels_max=OP_MAX(nchannels_max,links[li].head.channel_count);
2765     }
2766   }
2767   else nchannels_max=OP_NCHANNELS_MAX;
2768   _of->od_buffer=(op_sample *)_ogg_malloc(
2769    sizeof(*_of->od_buffer)*nchannels_max*120*48);
2770   if(_of->od_buffer==NULL)return OP_EFAULT;
2771   return 0;
2772 }
2773 
2774 /*Decode a single packet into the target buffer.*/
op_decode(OggOpusFile * _of,op_sample * _pcm,const ogg_packet * _op,int _nsamples,int _nchannels)2775 static int op_decode(OggOpusFile *_of,op_sample *_pcm,
2776  const ogg_packet *_op,int _nsamples,int _nchannels){
2777   int ret;
2778   /*First we try using the application-provided decode callback.*/
2779   if(_of->decode_cb!=NULL){
2780 #if defined(OP_FIXED_POINT)
2781     ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op,
2782      _nsamples,_nchannels,OP_DEC_FORMAT_SHORT,_of->cur_link);
2783 #else
2784     ret=(*_of->decode_cb)(_of->decode_cb_ctx,_of->od,_pcm,_op,
2785      _nsamples,_nchannels,OP_DEC_FORMAT_FLOAT,_of->cur_link);
2786 #endif
2787   }
2788   else ret=OP_DEC_USE_DEFAULT;
2789   /*If the application didn't want to handle decoding, do it ourselves.*/
2790   if(ret==OP_DEC_USE_DEFAULT){
2791 #if defined(OP_FIXED_POINT)
2792     ret=opus_multistream_decode(_of->od,
2793      _op->packet,_op->bytes,_pcm,_nsamples,0);
2794 #else
2795     ret=opus_multistream_decode_float(_of->od,
2796      _op->packet,_op->bytes,_pcm,_nsamples,0);
2797 #endif
2798     OP_ASSERT(ret<0||ret==_nsamples);
2799   }
2800   /*If the application returned a positive value other than 0 or
2801      OP_DEC_USE_DEFAULT, fail.*/
2802   else if(OP_UNLIKELY(ret>0))return OP_EBADPACKET;
2803   if(OP_UNLIKELY(ret<0))return OP_EBADPACKET;
2804   return ret;
2805 }
2806 
2807 /*Read more samples from the stream, using the same API as op_read() or
2808    op_read_float().*/
op_read_native(OggOpusFile * _of,op_sample * _pcm,int _buf_size,int * _li)2809 static int op_read_native(OggOpusFile *_of,
2810  op_sample *_pcm,int _buf_size,int *_li){
2811   if(OP_UNLIKELY(_of->ready_state<OP_OPENED))return OP_EINVAL;
2812   for(;;){
2813     int ret;
2814     if(OP_LIKELY(_of->ready_state>=OP_INITSET)){
2815       int nchannels;
2816       int od_buffer_pos;
2817       int nsamples;
2818       int op_pos;
2819       nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count;
2820       od_buffer_pos=_of->od_buffer_pos;
2821       nsamples=_of->od_buffer_size-od_buffer_pos;
2822       /*If we have buffered samples, return them.*/
2823       if(nsamples>0){
2824         if(nsamples*nchannels>_buf_size)nsamples=_buf_size/nchannels;
2825         OP_ASSERT(_pcm!=NULL||nsamples<=0);
2826         /*Check nsamples again so we don't pass NULL to memcpy() if _buf_size
2827            is zero.
2828           That would technically be undefined behavior, even if the number of
2829            bytes to copy were zero.*/
2830         if(nsamples>0){
2831           memcpy(_pcm,_of->od_buffer+nchannels*od_buffer_pos,
2832            sizeof(*_pcm)*nchannels*nsamples);
2833           od_buffer_pos+=nsamples;
2834           _of->od_buffer_pos=od_buffer_pos;
2835         }
2836         if(_li!=NULL)*_li=_of->cur_link;
2837         return nsamples;
2838       }
2839       /*If we have buffered packets, decode one.*/
2840       op_pos=_of->op_pos;
2841       if(OP_LIKELY(op_pos<_of->op_count)){
2842         const ogg_packet *pop;
2843         ogg_int64_t       diff;
2844         opus_int32        cur_discard_count;
2845         int               duration;
2846         int               trimmed_duration;
2847         pop=_of->op+op_pos++;
2848         _of->op_pos=op_pos;
2849         cur_discard_count=_of->cur_discard_count;
2850         duration=op_get_packet_duration(pop->packet,pop->bytes);
2851         /*We don't buffer packets with an invalid TOC sequence.*/
2852         OP_ASSERT(duration>0);
2853         trimmed_duration=duration;
2854         /*Perform end-trimming.*/
2855         if(OP_UNLIKELY(pop->e_o_s)){
2856           if(OP_UNLIKELY(op_granpos_cmp(pop->granulepos,
2857            _of->prev_packet_gp)<=0)){
2858             trimmed_duration=0;
2859           }
2860           else if(OP_LIKELY(!op_granpos_diff(&diff,
2861            pop->granulepos,_of->prev_packet_gp))){
2862             trimmed_duration=(int)OP_MIN(diff,trimmed_duration);
2863           }
2864         }
2865         _of->prev_packet_gp=pop->granulepos;
2866         if(OP_UNLIKELY(duration*nchannels>_buf_size)){
2867           op_sample *buf;
2868           /*If the user's buffer is too small, decode into a scratch buffer.*/
2869           buf=_of->od_buffer;
2870           if(OP_UNLIKELY(buf==NULL)){
2871             ret=op_init_buffer(_of);
2872             if(OP_UNLIKELY(ret<0))return ret;
2873             buf=_of->od_buffer;
2874           }
2875           ret=op_decode(_of,buf,pop,duration,nchannels);
2876           if(OP_UNLIKELY(ret<0))return ret;
2877           /*Perform pre-skip/pre-roll.*/
2878           od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count);
2879           cur_discard_count-=od_buffer_pos;
2880           _of->cur_discard_count=cur_discard_count;
2881           _of->od_buffer_pos=od_buffer_pos;
2882           _of->od_buffer_size=trimmed_duration;
2883           /*Update bitrate tracking based on the actual samples we used from
2884              what was decoded.*/
2885           _of->bytes_tracked+=pop->bytes;
2886           _of->samples_tracked+=trimmed_duration-od_buffer_pos;
2887         }
2888         else{
2889           OP_ASSERT(_pcm!=NULL);
2890           /*Otherwise decode directly into the user's buffer.*/
2891           ret=op_decode(_of,_pcm,pop,duration,nchannels);
2892           if(OP_UNLIKELY(ret<0))return ret;
2893           if(OP_LIKELY(trimmed_duration>0)){
2894             /*Perform pre-skip/pre-roll.*/
2895             od_buffer_pos=(int)OP_MIN(trimmed_duration,cur_discard_count);
2896             cur_discard_count-=od_buffer_pos;
2897             _of->cur_discard_count=cur_discard_count;
2898             trimmed_duration-=od_buffer_pos;
2899             if(OP_LIKELY(trimmed_duration>0)
2900              &&OP_UNLIKELY(od_buffer_pos>0)){
2901               memmove(_pcm,_pcm+od_buffer_pos*nchannels,
2902                sizeof(*_pcm)*trimmed_duration*nchannels);
2903             }
2904             /*Update bitrate tracking based on the actual samples we used from
2905                what was decoded.*/
2906             _of->bytes_tracked+=pop->bytes;
2907             _of->samples_tracked+=trimmed_duration;
2908             if(OP_LIKELY(trimmed_duration>0)){
2909               if(_li!=NULL)*_li=_of->cur_link;
2910               return trimmed_duration;
2911             }
2912           }
2913         }
2914         /*Don't grab another page yet.
2915           This one might have more packets, or might have buffered data now.*/
2916         continue;
2917       }
2918     }
2919     /*Suck in another page.*/
2920     ret=op_fetch_and_process_page(_of,NULL,-1,1,0);
2921     if(OP_UNLIKELY(ret==OP_EOF)){
2922       if(_li!=NULL)*_li=_of->cur_link;
2923       return 0;
2924     }
2925     if(OP_UNLIKELY(ret<0))return ret;
2926   }
2927 }
2928 
2929 /*A generic filter to apply to the decoded audio data.
2930   _src is non-const because we will destructively modify the contents of the
2931    source buffer that we consume in some cases.*/
2932 typedef int (*op_read_filter_func)(OggOpusFile *_of,void *_dst,int _dst_sz,
2933  op_sample *_src,int _nsamples,int _nchannels);
2934 
2935 /*Decode some samples and then apply a custom filter to them.
2936   This is used to convert to different output formats.*/
op_filter_read_native(OggOpusFile * _of,void * _dst,int _dst_sz,op_read_filter_func _filter,int * _li)2937 static int op_filter_read_native(OggOpusFile *_of,void *_dst,int _dst_sz,
2938  op_read_filter_func _filter,int *_li){
2939   int ret;
2940   /*Ensure we have some decoded samples in our buffer.*/
2941   ret=op_read_native(_of,NULL,0,_li);
2942   /*Now apply the filter to them.*/
2943   if(OP_LIKELY(ret>=0)&&OP_LIKELY(_of->ready_state>=OP_INITSET)){
2944     int od_buffer_pos;
2945     od_buffer_pos=_of->od_buffer_pos;
2946     ret=_of->od_buffer_size-od_buffer_pos;
2947     if(OP_LIKELY(ret>0)){
2948       int nchannels;
2949       nchannels=_of->links[_of->seekable?_of->cur_link:0].head.channel_count;
2950       ret=(*_filter)(_of,_dst,_dst_sz,
2951        _of->od_buffer+nchannels*od_buffer_pos,ret,nchannels);
2952       OP_ASSERT(ret>=0);
2953       OP_ASSERT(ret<=_of->od_buffer_size-od_buffer_pos);
2954       od_buffer_pos+=ret;
2955       _of->od_buffer_pos=od_buffer_pos;
2956     }
2957   }
2958   return ret;
2959 }
2960 
2961 #if !defined(OP_FIXED_POINT)||!defined(OP_DISABLE_FLOAT_API)
2962 
2963 /*Matrices for downmixing from the supported channel counts to stereo.
2964   The matrices with 5 or more channels are normalized to a total volume of 2.0,
2965    since most mixes sound too quiet if normalized to 1.0 (as there is generally
2966    little volume in the side/rear channels).*/
2967 static const float OP_STEREO_DOWNMIX[OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={
2968   /*3.0*/
2969   {
2970     {0.5858F,0.0F},{0.4142F,0.4142F},{0.0F,0.5858F}
2971   },
2972   /*quadrophonic*/
2973   {
2974     {0.4226F,0.0F},{0.0F,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F}
2975   },
2976   /*5.0*/
2977   {
2978     {0.651F,0.0F},{0.46F,0.46F},{0.0F,0.651F},{0.5636F,0.3254F},
2979     {0.3254F,0.5636F}
2980   },
2981   /*5.1*/
2982   {
2983     {0.529F,0.0F},{0.3741F,0.3741F},{0.0F,0.529F},{0.4582F,0.2645F},
2984     {0.2645F,0.4582F},{0.3741F,0.3741F}
2985   },
2986   /*6.1*/
2987   {
2988     {0.4553F,0.0F},{0.322F,0.322F},{0.0F,0.4553F},{0.3943F,0.2277F},
2989     {0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F}
2990   },
2991   /*7.1*/
2992   {
2993     {0.3886F,0.0F},{0.2748F,0.2748F},{0.0F,0.3886F},{0.3366F,0.1943F},
2994     {0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F}
2995   }
2996 };
2997 
2998 #endif
2999 
3000 #if defined(OP_FIXED_POINT)
3001 
3002 /*Matrices for downmixing from the supported channel counts to stereo.
3003   The matrices with 5 or more channels are normalized to a total volume of 2.0,
3004    since most mixes sound too quiet if normalized to 1.0 (as there is generally
3005    little volume in the side/rear channels).
3006   Hence we keep the coefficients in Q14, so the downmix values won't overflow a
3007    32-bit number.*/
3008 static const opus_int16 OP_STEREO_DOWNMIX_Q14
3009  [OP_NCHANNELS_MAX-2][OP_NCHANNELS_MAX][2]={
3010   /*3.0*/
3011   {
3012     {9598,0},{6786,6786},{0,9598}
3013   },
3014   /*quadrophonic*/
3015   {
3016     {6924,0},{0,6924},{5996,3464},{3464,5996}
3017   },
3018   /*5.0*/
3019   {
3020     {10666,0},{7537,7537},{0,10666},{9234,5331},{5331,9234}
3021   },
3022   /*5.1*/
3023   {
3024     {8668,0},{6129,6129},{0,8668},{7507,4335},{4335,7507},{6129,6129}
3025   },
3026   /*6.1*/
3027   {
3028     {7459,0},{5275,5275},{0,7459},{6460,3731},{3731,6460},{4568,4568},
3029     {5275,5275}
3030   },
3031   /*7.1*/
3032   {
3033     {6368,0},{4502,4502},{0,6368},{5515,3183},{3183,5515},{5515,3183},
3034     {3183,5515},{4502,4502}
3035   }
3036 };
3037 
op_read(OggOpusFile * _of,opus_int16 * _pcm,int _buf_size,int * _li)3038 int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){
3039   return op_read_native(_of,_pcm,_buf_size,_li);
3040 }
3041 
op_stereo_filter(OggOpusFile * _of,void * _dst,int _dst_sz,op_sample * _src,int _nsamples,int _nchannels)3042 static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
3043  op_sample *_src,int _nsamples,int _nchannels){
3044   (void)_of;
3045   _nsamples=OP_MIN(_nsamples,_dst_sz>>1);
3046   if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src));
3047   else{
3048     opus_int16 *dst;
3049     int         i;
3050     dst=(opus_int16 *)_dst;
3051     if(_nchannels==1){
3052       for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i];
3053     }
3054     else{
3055       for(i=0;i<_nsamples;i++){
3056         opus_int32 l;
3057         opus_int32 r;
3058         int        ci;
3059         l=r=0;
3060         for(ci=0;ci<_nchannels;ci++){
3061           opus_int32 s;
3062           s=_src[_nchannels*i+ci];
3063           l+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][0]*s;
3064           r+=OP_STEREO_DOWNMIX_Q14[_nchannels-3][ci][1]*s;
3065         }
3066         /*TODO: For 5 or more channels, we should do soft clipping here.*/
3067         dst[2*i+0]=(opus_int16)OP_CLAMP(-32768,l+8192>>14,32767);
3068         dst[2*i+1]=(opus_int16)OP_CLAMP(-32768,r+8192>>14,32767);
3069       }
3070     }
3071   }
3072   return _nsamples;
3073 }
3074 
op_read_stereo(OggOpusFile * _of,opus_int16 * _pcm,int _buf_size)3075 int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){
3076   return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL);
3077 }
3078 
3079 # if !defined(OP_DISABLE_FLOAT_API)
3080 
op_short2float_filter(OggOpusFile * _of,void * _dst,int _dst_sz,op_sample * _src,int _nsamples,int _nchannels)3081 static int op_short2float_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
3082  op_sample *_src,int _nsamples,int _nchannels){
3083   float *dst;
3084   int    i;
3085   (void)_of;
3086   dst=(float *)_dst;
3087   if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels;
3088   _dst_sz=_nsamples*_nchannels;
3089   for(i=0;i<_dst_sz;i++)dst[i]=(1.0F/32768)*_src[i];
3090   return _nsamples;
3091 }
3092 
op_read_float(OggOpusFile * _of,float * _pcm,int _buf_size,int * _li)3093 int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){
3094   return op_filter_read_native(_of,_pcm,_buf_size,op_short2float_filter,_li);
3095 }
3096 
op_short2float_stereo_filter(OggOpusFile * _of,void * _dst,int _dst_sz,op_sample * _src,int _nsamples,int _nchannels)3097 static int op_short2float_stereo_filter(OggOpusFile *_of,
3098  void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){
3099   float *dst;
3100   int    i;
3101   dst=(float *)_dst;
3102   _nsamples=OP_MIN(_nsamples,_dst_sz>>1);
3103   if(_nchannels==1){
3104     _nsamples=op_short2float_filter(_of,dst,_nsamples,_src,_nsamples,1);
3105     for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i];
3106   }
3107   else if(_nchannels<5){
3108     /*For 3 or 4 channels, we can downmix in fixed point without risk of
3109        clipping.*/
3110     if(_nchannels>2){
3111       _nsamples=op_stereo_filter(_of,_src,_nsamples*2,
3112        _src,_nsamples,_nchannels);
3113     }
3114     return op_short2float_filter(_of,dst,_dst_sz,_src,_nsamples,2);
3115   }
3116   else{
3117     /*For 5 or more channels, we convert to floats and then downmix (so that we
3118        don't risk clipping).*/
3119     for(i=0;i<_nsamples;i++){
3120       float l;
3121       float r;
3122       int   ci;
3123       l=r=0;
3124       for(ci=0;ci<_nchannels;ci++){
3125         float s;
3126         s=(1.0F/32768)*_src[_nchannels*i+ci];
3127         l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*s;
3128         r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*s;
3129       }
3130       dst[2*i+0]=l;
3131       dst[2*i+1]=r;
3132     }
3133   }
3134   return _nsamples;
3135 }
3136 
op_read_float_stereo(OggOpusFile * _of,float * _pcm,int _buf_size)3137 int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){
3138   return op_filter_read_native(_of,_pcm,_buf_size,
3139    op_short2float_stereo_filter,NULL);
3140 }
3141 
3142 # endif
3143 
3144 #else
3145 
3146 # if defined(OP_HAVE_LRINTF)
3147 #  include <math.h>
3148 #  define op_float2int(_x) (lrintf(_x))
3149 # else
3150 #  define op_float2int(_x) ((int)((_x)+((_x)<0?-0.5F:0.5F)))
3151 # endif
3152 
3153 /*The dithering code here is adapted from opusdec, part of opus-tools.
3154   It was originally written by Greg Maxwell.*/
3155 
op_rand(opus_uint32 _seed)3156 static opus_uint32 op_rand(opus_uint32 _seed){
3157   return _seed*96314165+907633515&0xFFFFFFFFU;
3158 }
3159 
3160 /*This implements 16-bit quantization with full triangular dither and IIR noise
3161    shaping.
3162   The noise shaping filters were designed by Sebastian Gesemann, and are based
3163    on the LAME ATH curves with flattening to limit their peak gain to 20 dB.
3164   Everyone else's noise shaping filters are mildly crazy.
3165   The 48 kHz version of this filter is just a warped version of the 44.1 kHz
3166    filter and probably could be improved by shifting the HF shelf up in
3167    frequency a little bit, since 48 kHz has a bit more room and being more
3168    conservative against bat-ears is probably more important than more noise
3169    suppression.
3170   This process can increase the peak level of the signal (in theory by the peak
3171    error of 1.5 +20 dB, though that is unobservably rare).
3172   To avoid clipping, the signal is attenuated by a couple thousandths of a dB.
3173   Initially, the approach taken here was to only attenuate by the 99.9th
3174    percentile, making clipping rare but not impossible (like SoX), but the
3175    limited gain of the filter means that the worst case was only two
3176    thousandths of a dB more, so this just uses the worst case.
3177   The attenuation is probably also helpful to prevent clipping in the DAC
3178    reconstruction filters or downstream resampling, in any case.*/
3179 
3180 # define OP_GAIN (32753.0F)
3181 
3182 # define OP_PRNG_GAIN (1.0F/(float)0xFFFFFFFF)
3183 
3184 /*48 kHz noise shaping filter, sd=2.34.*/
3185 
3186 static const float OP_FCOEF_B[4]={
3187   2.2374F,-0.7339F,-0.1251F,-0.6033F
3188 };
3189 
3190 static const float OP_FCOEF_A[4]={
3191   0.9030F,0.0116F,-0.5853F,-0.2571F
3192 };
3193 
op_float2short_filter(OggOpusFile * _of,void * _dst,int _dst_sz,float * _src,int _nsamples,int _nchannels)3194 static int op_float2short_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
3195  float *_src,int _nsamples,int _nchannels){
3196   opus_int16 *dst;
3197   int         ci;
3198   int         i;
3199   dst=(opus_int16 *)_dst;
3200   if(OP_UNLIKELY(_nsamples*_nchannels>_dst_sz))_nsamples=_dst_sz/_nchannels;
3201 # if defined(OP_SOFT_CLIP)
3202   if(_of->state_channel_count!=_nchannels){
3203     for(ci=0;ci<_nchannels;ci++)_of->clip_state[ci]=0;
3204   }
3205   opus_pcm_soft_clip(_src,_nsamples,_nchannels,_of->clip_state);
3206 # endif
3207   if(_of->dither_disabled){
3208     for(i=0;i<_nchannels*_nsamples;i++){
3209       dst[i]=op_float2int(OP_CLAMP(-32768,32768.0F*_src[i],32767));
3210     }
3211   }
3212   else{
3213     opus_uint32 seed;
3214     int         mute;
3215     seed=_of->dither_seed;
3216     mute=_of->dither_mute;
3217     if(_of->state_channel_count!=_nchannels)mute=65;
3218     /*In order to avoid replacing digital silence with quiet dither noise, we
3219        mute if the output has been silent for a while.*/
3220     if(mute>64)memset(_of->dither_a,0,sizeof(*_of->dither_a)*4*_nchannels);
3221     for(i=0;i<_nsamples;i++){
3222       int silent;
3223       silent=1;
3224       for(ci=0;ci<_nchannels;ci++){
3225         float r;
3226         float s;
3227         float err;
3228         int   si;
3229         int   j;
3230         s=_src[_nchannels*i+ci];
3231         silent&=s==0;
3232         s*=OP_GAIN;
3233         err=0;
3234         for(j=0;j<4;j++){
3235           err+=OP_FCOEF_B[j]*_of->dither_b[ci*4+j]
3236            -OP_FCOEF_A[j]*_of->dither_a[ci*4+j];
3237         }
3238         for(j=3;j-->0;)_of->dither_a[ci*4+j+1]=_of->dither_a[ci*4+j];
3239         for(j=3;j-->0;)_of->dither_b[ci*4+j+1]=_of->dither_b[ci*4+j];
3240         _of->dither_a[ci*4]=err;
3241         s-=err;
3242         if(mute>16)r=0;
3243         else{
3244           seed=op_rand(seed);
3245           r=seed*OP_PRNG_GAIN;
3246           seed=op_rand(seed);
3247           r-=seed*OP_PRNG_GAIN;
3248         }
3249         /*Clamp in float out of paranoia that the input will be > 96 dBFS and
3250            wrap if the integer is clamped.*/
3251         si=op_float2int(OP_CLAMP(-32768,s+r,32767));
3252         dst[_nchannels*i+ci]=(opus_int16)si;
3253         /*Including clipping in the noise shaping is generally disastrous: the
3254            futile effort to restore the clipped energy results in more clipping.
3255           However, small amounts---at the level which could normally be created
3256            by dither and rounding---are harmless and can even reduce clipping
3257            somewhat due to the clipping sometimes reducing the dither + rounding
3258            error.*/
3259         _of->dither_b[ci*4]=mute>16?0:OP_CLAMP(-1.5F,si-s,1.5F);
3260       }
3261       mute++;
3262       if(!silent)mute=0;
3263     }
3264     _of->dither_mute=OP_MIN(mute,65);
3265     _of->dither_seed=seed;
3266   }
3267   _of->state_channel_count=_nchannels;
3268   return _nsamples;
3269 }
3270 
op_read(OggOpusFile * _of,opus_int16 * _pcm,int _buf_size,int * _li)3271 int op_read(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size,int *_li){
3272   return op_filter_read_native(_of,_pcm,_buf_size,op_float2short_filter,_li);
3273 }
3274 
op_read_float(OggOpusFile * _of,float * _pcm,int _buf_size,int * _li)3275 int op_read_float(OggOpusFile *_of,float *_pcm,int _buf_size,int *_li){
3276   _of->state_channel_count=0;
3277   return op_read_native(_of,_pcm,_buf_size,_li);
3278 }
3279 
op_stereo_filter(OggOpusFile * _of,void * _dst,int _dst_sz,op_sample * _src,int _nsamples,int _nchannels)3280 static int op_stereo_filter(OggOpusFile *_of,void *_dst,int _dst_sz,
3281  op_sample *_src,int _nsamples,int _nchannels){
3282   (void)_of;
3283   _nsamples=OP_MIN(_nsamples,_dst_sz>>1);
3284   if(_nchannels==2)memcpy(_dst,_src,_nsamples*2*sizeof(*_src));
3285   else{
3286     float *dst;
3287     int    i;
3288     dst=(float *)_dst;
3289     if(_nchannels==1){
3290       for(i=0;i<_nsamples;i++)dst[2*i+0]=dst[2*i+1]=_src[i];
3291     }
3292     else{
3293       for(i=0;i<_nsamples;i++){
3294         float l;
3295         float r;
3296         int   ci;
3297         l=r=0;
3298         for(ci=0;ci<_nchannels;ci++){
3299           l+=OP_STEREO_DOWNMIX[_nchannels-3][ci][0]*_src[_nchannels*i+ci];
3300           r+=OP_STEREO_DOWNMIX[_nchannels-3][ci][1]*_src[_nchannels*i+ci];
3301         }
3302         dst[2*i+0]=l;
3303         dst[2*i+1]=r;
3304       }
3305     }
3306   }
3307   return _nsamples;
3308 }
3309 
op_float2short_stereo_filter(OggOpusFile * _of,void * _dst,int _dst_sz,op_sample * _src,int _nsamples,int _nchannels)3310 static int op_float2short_stereo_filter(OggOpusFile *_of,
3311  void *_dst,int _dst_sz,op_sample *_src,int _nsamples,int _nchannels){
3312   opus_int16 *dst;
3313   dst=(opus_int16 *)_dst;
3314   if(_nchannels==1){
3315     int i;
3316     _nsamples=op_float2short_filter(_of,dst,_dst_sz>>1,_src,_nsamples,1);
3317     for(i=_nsamples;i-->0;)dst[2*i+0]=dst[2*i+1]=dst[i];
3318   }
3319   else{
3320     if(_nchannels>2){
3321       _nsamples=OP_MIN(_nsamples,_dst_sz>>1);
3322       _nsamples=op_stereo_filter(_of,_src,_nsamples*2,
3323        _src,_nsamples,_nchannels);
3324     }
3325     _nsamples=op_float2short_filter(_of,dst,_dst_sz,_src,_nsamples,2);
3326   }
3327   return _nsamples;
3328 }
3329 
op_read_stereo(OggOpusFile * _of,opus_int16 * _pcm,int _buf_size)3330 int op_read_stereo(OggOpusFile *_of,opus_int16 *_pcm,int _buf_size){
3331   return op_filter_read_native(_of,_pcm,_buf_size,
3332    op_float2short_stereo_filter,NULL);
3333 }
3334 
op_read_float_stereo(OggOpusFile * _of,float * _pcm,int _buf_size)3335 int op_read_float_stereo(OggOpusFile *_of,float *_pcm,int _buf_size){
3336   _of->state_channel_count=0;
3337   return op_filter_read_native(_of,_pcm,_buf_size,op_stereo_filter,NULL);
3338 }
3339 
3340 #endif
3341