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