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