137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang/************************************************************************ 22da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2002-2009, Xiph.org Foundation 32da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Copyright (C) 2010, Robin Watts for Pinknoise Productions Ltd 437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * All rights reserved. 537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * Redistribution and use in source and binary forms, with or without 72da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * modification, are permitted provided that the following conditions 82da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * are met: 937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 1037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * * Redistributions of source code must retain the above copyright 1137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * notice, this list of conditions and the following disclaimer. 1237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * * Redistributions in binary form must reproduce the above 1337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * copyright notice, this list of conditions and the following disclaimer 1437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * in the documentation and/or other materials provided with the 1537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * distribution. 162da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * * Neither the names of the Xiph.org Foundation nor Pinknoise 172da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * Productions Ltd nor the names of its contributors may be used to 182da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * endorse or promote products derived from this software without 192da723a953a18e3c7fec194cec1216cf31130c86Gloria Wang * specific prior written permission. 2037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * 2137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2337fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2437fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2537fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2637fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2837fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2937fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3037fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3137fe158a8611dd11ec0253ab1552399b780988dcGloria Wang * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3237fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************ 337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang function: stdio-based convenience library for opening/seeking/decoding 357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang last mod: $Id: vorbisfile.c,v 1.6.2.5 2003/11/20 06:16:17 xiphmont Exp $ 367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3737fe158a8611dd11ec0253ab1552399b780988dcGloria Wang ************************************************************************/ 387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <stdlib.h> 407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <stdio.h> 41d75baf2eee5ddd155009e7f0a79b175ae6026762Gloria Wang//#include <gerrno.h> 427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <string.h> 437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include <math.h> 447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "codec_internal.h" 467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "ivorbisfile.h" 477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "os.h" 497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#include "misc.h" 507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 51d75baf2eee5ddd155009e7f0a79b175ae6026762Gloria Wangint gerrno; 527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define NOTOPEN 0 547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define PARTOPEN 1 557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define OPENED 2 567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define STREAMSET 3 /* serialno and link set, but not to current link */ 577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define LINKSET 4 /* serialno and link set to current link */ 587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#define INITSET 5 597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* A 'chained bitstream' is a Vorbis bitstream that contains more than 617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang one logical bitstream arranged end to end (the only form of Ogg 627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang multiplexing allowed in a Vorbis bitstream; grouping [parallel 637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang multiplexing] is not allowed in Vorbis) */ 647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* A Vorbis file can be played beginning to end (streamed) without 667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang worrying ahead of time about chaining (see decoder_example.c). If 677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang we have the whole file, however, and want random access 687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (seeking/scrubbing) or desire to know the total length/time of a 697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang file, we need to account for the possibility of chaining. */ 707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* We can handle things a number of ways; we can determine the entire 727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream structure right off the bat, or find pieces on demand. 737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang This example determines and caches structure for the entire 747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream, but builds a virtual decoder on the fly when moving 757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang between links in the chain. */ 767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* There are also different ways to implement seeking. Enough 787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang information exists in an Ogg bitstream to seek to 797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang sample-granularity positions in the output. Or, one can seek by 807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang picking some portion of the stream roughly in the desired area if 817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang we only want coarse navigation through the stream. */ 827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/************************************************************************* 847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * Many, many internal helpers. The intention is not to be confusing; 857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * rampant duplication and monolithic function implementation would be 867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * harder to understand anyway. The high level functions are last. Begin 877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * grokking near the end of the file */ 887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* read a little more data from the file/pipe into the ogg_sync framer */ 917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic long _get_data(OggVorbis_File *vf){ 92d75baf2eee5ddd155009e7f0a79b175ae6026762Gloria Wang gerrno=0; 937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->datasource){ 947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang unsigned char *buffer=ogg_sync_bufferin(vf->oy,CHUNKSIZE); 957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long bytes=(vf->callbacks.read_func)(buffer,1,CHUNKSIZE,vf->datasource); 967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bytes>0)ogg_sync_wrote(vf->oy,bytes); 97d75baf2eee5ddd155009e7f0a79b175ae6026762Gloria Wang if(bytes==0 && gerrno)return -1; 987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return bytes; 997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else 1007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 1017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* save a tiny smidge of verbosity to make the code more readable */ 1047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void _seek_helper(OggVorbis_File *vf,ogg_int64_t offset){ 1057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->datasource){ 1067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (vf->callbacks.seek_func)(vf->datasource, offset, SEEK_SET); 1077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset=offset; 1087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_sync_reset(vf->oy); 1097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 1107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* shouldn't happen unless someone writes a broken callback */ 1117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return; 1127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* The read/seek functions track absolute position within the stream */ 1167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* from the head of the stream, get the next page. boundary specifies 1187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if the function is allowed to fetch more data from the stream (and 1197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang how much) or only use internally buffered data. 1207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang boundary: -1) unbounded search 1227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 0) read no additional data; use cached only 1237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang n) search for a new page beginning for n bytes 1247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return: <0) did not find a page (OV_FALSE, OV_EOF, OV_EREAD) 1267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang n) found a page at absolute offset n 1277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang produces a refcounted page */ 1297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic ogg_int64_t _get_next_page(OggVorbis_File *vf,ogg_page *og, 1317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t boundary){ 1327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(boundary>0)boundary+=vf->offset; 1337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 1347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long more; 1357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(boundary>0 && vf->offset>=boundary)return OV_FALSE; 1377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang more=ogg_sync_pageseek(vf->oy,og); 1387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(more<0){ 1407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* skipped n bytes */ 1417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset-=more; 1427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 1437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(more==0){ 1447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* send more paramedics */ 1457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!boundary)return OV_FALSE; 1467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 1477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long ret=_get_data(vf); 1487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==0)return OV_EOF; 1497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0)return OV_EREAD; 1507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 1527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* got a page. Return the offset at the page beginning, 1537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang advance the internal offset past the page end */ 1547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t ret=vf->offset; 1557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset+=more; 1567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 1577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* find the latest page beginning before the current stream cursor 1647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang position. Much dirtier than the above as Ogg doesn't have any 1657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang backward search linkage. no 'readp' as it will certainly have to 1667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang read. */ 1677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns offset or OV_EREAD, OV_FAULT and produces a refcounted page */ 1687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic ogg_int64_t _get_prev_page(OggVorbis_File *vf,ogg_page *og){ 1707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t begin=vf->offset; 1717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t end=begin; 1727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t ret; 1737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t offset=-1; 1747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(offset==-1){ 1767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang begin-=CHUNKSIZE; 1777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(begin<0) 1787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang begin=0; 1797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,begin); 1807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(vf->offset<end){ 1817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_next_page(vf,og,end-vf->offset); 1827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==OV_EREAD)return OV_EREAD; 1837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0){ 1847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 1857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 1867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang offset=ret; 1877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 1907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we have the offset. Actually snork and hold the page now */ 1927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,offset); 1937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_next_page(vf,og,CHUNKSIZE); 1947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0) 1957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* this shouldn't be possible */ 1967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_EFAULT; 1977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return offset; 1997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* finds each bitstream link one at a time using a bisection search 2027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (has to begin by knowing the offset of the lb's initial page). 2037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Recurses for each link so it can alloc the link storage after 2047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang finding them all, then unroll and fill the cache at the same time */ 2057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _bisect_forward_serialno(OggVorbis_File *vf, 2067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t begin, 2077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t searched, 2087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t end, 2097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_uint32_t currentno, 2107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long m){ 2117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t endsearched=end; 2127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t next=end; 2137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 2147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t ret; 2157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* the below guards against garbage seperating the last and 2177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang first pages of two links. */ 2187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(searched<endsearched){ 2197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t bisect; 2207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(endsearched-searched<CHUNKSIZE){ 2227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=searched; 2237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 2247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=(searched+endsearched)/2; 2257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,bisect); 2287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_next_page(vf,&og,-1); 2297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==OV_EREAD)return OV_EREAD; 2307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0 || ogg_page_serialno(&og)!=currentno){ 2317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang endsearched=bisect; 2327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret>=0)next=ret; 2337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 2347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang searched=ret+og.header_len+og.body_len; 2357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 2377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,next); 2407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_next_page(vf,&og,-1); 2417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==OV_EREAD)return OV_EREAD; 2427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(searched>=end || ret<0){ 2447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 2457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->links=m+1; 2467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offsets=_ogg_malloc((vf->links+1)*sizeof(*vf->offsets)); 2477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->serialnos=_ogg_malloc(vf->links*sizeof(*vf->serialnos)); 2487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offsets[m+1]=searched; 2497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 2507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_bisect_forward_serialno(vf,next,vf->offset, 2517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end,ogg_page_serialno(&og),m+1); 2527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 2537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==OV_EREAD)return OV_EREAD; 2547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offsets[m]=begin; 2577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->serialnos[m]=currentno; 2587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 2597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _decode_clear(OggVorbis_File *vf){ 2627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state==INITSET){ 2637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_destroy(vf->vd); 2647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->vd=0; 2657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=STREAMSET; 2667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state>=STREAMSET){ 2697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_clear(&vf->vi); 2707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment_clear(&vf->vc); 2717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=OPENED; 2727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 2747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 2757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* uses the local ogg_stream storage in vf; this is important for 2777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang non-streaming input sources */ 2787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* consumes the page that's passed in (if any) */ 2797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* state is LINKSET upon successful return */ 2807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _fetch_headers(OggVorbis_File *vf, 2827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info *vi, 2837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment *vc, 2847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_uint32_t *serialno, 2857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page *og_ptr){ 2867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 2877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 2887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i,ret; 2897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state>OPENED)_decode_clear(vf); 2917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!og_ptr){ 2937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t llret=_get_next_page(vf,&og,CHUNKSIZE); 2947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(llret==OV_EREAD)return OV_EREAD; 2957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(llret<0)return OV_ENOTVORBIS; 2967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang og_ptr=&og; 2977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 2987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 2997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os,ogg_page_serialno(og_ptr)); 3007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(serialno)*serialno=vf->os->serialno; 3017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* extract the initial header from the first page and verify that the 3037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Ogg bitstream is in fact Vorbis data */ 3047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_init(vi); 3067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment_init(vc); 3077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang i=0; 3097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(i<3){ 3107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,og_ptr); 3117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(i<3){ 3127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int result=ogg_stream_packetout(vf->os,&op); 3137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result==0)break; 3147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result==-1){ 3157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_EBADHEADER; 3167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto bail_header; 3177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if((ret=vorbis_dsp_headerin(vi,vc,&op))){ 3197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto bail_header; 3207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang i++; 3227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<3) 3247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_get_next_page(vf,og_ptr,CHUNKSIZE)<0){ 3257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_EBADHEADER; 3267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto bail_header; 3277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 3317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 3327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=LINKSET; 3337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 3347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bail_header: 3367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 3377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 3387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_clear(vi); 3397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment_clear(vc); 3407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=OPENED; 3417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 3437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 3447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* we no longer preload all vorbis_info (and the associated 3467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang codec_setup) structs. Call this to seek and fetch the info from 3477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the bitstream, if needed */ 3487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _set_link_number(OggVorbis_File *vf,int link){ 3497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link != vf->current_link) _decode_clear(vf); 3507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<STREAMSET){ 3517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,vf->offsets[link]); 3527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os,vf->serialnos[link]); 3537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_serialno=vf->serialnos[link]; 3547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_link=link; 3557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return _fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL); 3567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 3577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 3587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 3597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _set_link_number_preserve_pos(OggVorbis_File *vf,int link){ 3617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t pos=vf->offset; 3627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number(vf,link); 3637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return ret; 3647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,pos); 3657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(pos<vf->offsets[link] || pos>=vf->offsets[link+1]) 3667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=STREAMSET; 3677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 3687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 3697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* last step of the OggVorbis_File initialization; get all the offset 3717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang positions. Only called by the seekable initialization (local 3727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang stream storage is hacked slightly; pay attention to how that's 3737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang done) */ 3747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* this is void and does not propogate errors up because we want to be 3767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang able to open and use damaged bitstreams as well as we can. Just 3777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang watch out for missing information for links in the OggVorbis_File 3787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang struct */ 3797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic void _prefetch_all_offsets(OggVorbis_File *vf, ogg_int64_t dataoffset){ 3807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 3817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 3827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t ret; 3837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets)); 3857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths)); 3867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++){ 3887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i==0){ 3897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we already grabbed the initial header earlier. Just set the offset */ 3907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->dataoffsets[i]=dataoffset; 3917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,dataoffset); 3927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 3947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* seek to the location of the initial header */ 3967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 3977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,vf->offsets[i]); 3987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_fetch_headers(vf,&vf->vi,&vf->vc,NULL,NULL)<0){ 3997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->dataoffsets[i]=-1; 4007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 4017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->dataoffsets[i]=vf->offset; 4027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* fetch beginning PCM offset */ 4067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->dataoffsets[i]!=-1){ 4087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t accumulated=0,pos; 4097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long lastblock=-1; 4107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int result; 4117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os,vf->serialnos[i]); 4137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 4157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 4167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_next_page(vf,&og,-1); 4187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0) 4197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* this should not be possible unless the file is 4207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang truncated/mangled */ 4217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 4227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ogg_page_serialno(&og)!=vf->serialnos[i]) 4247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 4257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pos=ogg_page_granulepos(&og); 4277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* count blocksizes of all frames in the page */ 4297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,&og); 4307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while((result=ogg_stream_packetout(vf->os,&op))){ 4317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result>0){ /* ignore holes */ 4327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long thisblock=vorbis_packet_blocksize(&vf->vi,&op); 4337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(lastblock!=-1) 4347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang accumulated+=(lastblock+thisblock)>>2; 4357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lastblock=thisblock; 4367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 4397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(pos!=-1){ 4417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* pcm offset of last packet on the first audio page */ 4427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang accumulated= pos-accumulated; 4437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 4447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* less than zero? This is a stream with samples trimmed off 4487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the beginning, a normal occurrence; set the offset to zero */ 4497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(accumulated<0)accumulated=0; 4507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcmlengths[i*2]=accumulated; 4527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* get the PCM length of this link. To do this, 4557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang get the last page of the stream */ 4567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 4577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t end=vf->offsets[i+1]; 4587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,end); 4597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 4617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_get_prev_page(vf,&og); 4627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0){ 4637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* this should not be possible */ 4647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_clear(&vf->vi); 4657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment_clear(&vf->vc); 4667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 4677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ogg_page_granulepos(&og)!=-1){ 4697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcmlengths[i*2+1]=ogg_page_granulepos(&og)-vf->pcmlengths[i*2]; 4707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 4717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset=ret; 4737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 4767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 4777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 4787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 4797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _make_decode_ready(OggVorbis_File *vf){ 4807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 4817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang switch(vf->ready_state){ 4827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang case OPENED: 4837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang case STREAMSET: 4847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++) 4857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->offsets[i+1]>=vf->offset)break; 4867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i==vf->links)return -1; 4877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang i=_set_link_number_preserve_pos(vf,i); 4887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i)return i; 4897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* fall through */ 4907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang case LINKSET: 4917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->vd=vorbis_dsp_create(&vf->vi); 4927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=INITSET; 4937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack=0; 4947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack=0; 4957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang case INITSET: 4967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 4977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang default: 4987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return -1; 4997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 5007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 5027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _open_seekable2(OggVorbis_File *vf){ 5047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_uint32_t serialno=vf->current_serialno; 5057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_uint32_t tempserialno; 5067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t dataoffset=vf->offset, end; 5077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 5087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we're partially open and have a first link header state in 5107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang storage in vf */ 5117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we can seek, so set out learning all about this file */ 5127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (vf->callbacks.seek_func)(vf->datasource,0,SEEK_END); 5137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset=vf->end=(vf->callbacks.tell_func)(vf->datasource); 5147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* We get the offset for the last page of the physical bitstream. 5167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Most OggVorbis files will contain a single logical bitstream */ 5177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end=_get_prev_page(vf,&og); 5187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(end<0)return (int)end; 5197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* more than one logical bitstream? */ 5217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang tempserialno=ogg_page_serialno(&og); 5227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 5237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(tempserialno!=serialno){ 5257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* Chained bitstream. Bisect-search each logical bitstream 5277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang section. Do so based on serial number only */ 5287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_bisect_forward_serialno(vf,0,0,end+1,serialno,0)<0)return OV_EREAD; 5297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 5317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* Only one logical bitstream */ 5337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_bisect_forward_serialno(vf,0,end,end+1,serialno,0))return OV_EREAD; 5347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 5367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* the initial header memory is referenced by vf after; don't free it */ 5387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _prefetch_all_offsets(vf,dataoffset); 5397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ov_raw_seek(vf,0); 5407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 5417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* fetch and process a packet. Handles the case where we're at a 5437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream boundary and dumps the decoding machine. If the decoding 5447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang machine is unloaded, it loads it. It also keeps pcm_offset up to 5457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang date (seek and read both use this. seek uses a special hack with 5467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang readp). 5477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return: <0) error, OV_HOLE (lost packet) or OV_EOF 5497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 0) need more data (only if readp==0) 5507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 1) got a packet 5517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 5527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _fetch_and_process_packet(OggVorbis_File *vf, 5547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int readp, 5557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int spanp){ 5567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 5577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 5587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=0; 5597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* handle one packet. Try to fetch it from current stream state */ 5617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* extract packets from page */ 5627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 5637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* process a packet if we can. If the machine isn't loaded, 5657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang neither is a page */ 5667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state==INITSET){ 5677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1) { 5687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int result=ogg_stream_packetout(vf->os,&op); 5697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t granulepos; 5707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result<0){ 5727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_HOLE; /* hole in the data. */ 5737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 5747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 5757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result>0){ 5767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* got a packet. process it */ 5777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos=op.granulepos; 5787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vorbis_dsp_synthesis(vf->vd,&op,1)){ /* lazy check for lazy 5797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang header handling. The 5807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang header packets aren't 5817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang audio, so if/when we 5827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang submit them, 5837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_synthesis will 5847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang reject them */ 5857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack+=vorbis_dsp_pcmout(vf->vd,NULL,0); 5877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack+=op.bytes*8; 5887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* update the pcm offset. */ 5907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(granulepos!=-1 && !op.e_o_s){ 5917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link=(vf->seekable?vf->current_link:0); 5927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i,samples; 5937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* this packet has a pcm_offset on it (the last packet 5957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang completed on a page carries the offset) After processing 5967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (above), we know the pcm position of the *last* sample 5977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ready to be returned. Find the offset of the *first* 5987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 5997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang As an aside, this trick is inaccurate if we begin 6007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang reading anew right at the last page; the end-of-stream 6017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos declares the last frame in the stream, and the 6027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang last packet of the last page may be a partial frame. 6037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang So, we need a previous granulepos from an in-sequence page 6047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang to have a reference point. Thus the !op.e_o_s clause 6057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang above */ 6067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable && link>0) 6087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos-=vf->pcmlengths[link*2]; 6097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(granulepos<0)granulepos=0; /* actually, this 6107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang shouldn't be possible 6117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang here unless the stream 6127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang is very broken */ 6137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang samples=vorbis_dsp_pcmout(vf->vd,NULL,0); 6157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos-=samples; 6177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<link;i++) 6187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos+=vf->pcmlengths[i*2+1]; 6197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=granulepos; 6207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=1; 6227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 6237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang else 6267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 6277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state>=OPENED){ 6317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret; 6327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!readp){ 6337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=0; 6347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 6357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=(int)_get_next_page(vf,&og,-1); 6377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0){ 6387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_EOF; /* eof. leave unitialized */ 6397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 6407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* bitrate tracking; add the header's bytes here, the body bytes 6437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang are done by packet above */ 6447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack+=og.header_len*8; 6457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* has our decoding just traversed a bitstream boundary? */ 6477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state==INITSET){ 6487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->current_serialno!=ogg_page_serialno(&og)){ 6497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!spanp){ 6507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_EOF; 6517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 6527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _decode_clear(vf); 6557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* Do we need to load a new machine before submitting the page? */ 6607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* This is different in the seekable and non-seekable cases. 6617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang In the seekable case, we already have all the header 6637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang information loaded and cached; we just initialize the machine 6647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang with it and continue on our merry way. 6657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang In the non-seekable (streaming) case, we'll only be at a 6677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang boundary if we just left the previous logical bitstream and 6687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang we're now nominally at the header of the next bitstream 6697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 6707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state!=INITSET){ 6727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link,ret; 6737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<STREAMSET){ 6757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 6767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_serialno=ogg_page_serialno(&og); 6777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* match the serialno to bitstream section. We use this rather than 6797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang offset positions to avoid problems near logical bitstream 6807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang boundaries */ 6817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=0;link<vf->links;link++) 6827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->serialnos[link]==vf->current_serialno)break; 6837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link==vf->links){ 6847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=OV_EBADLINK; /* sign of a bogus stream. error out, 6857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang leave machine uninitialized */ 6867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto cleanup; 6877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 6887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_link=link; 6907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); 6917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret) goto cleanup; 6927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 6947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we're streaming */ 6957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* fetch the three header packets, build the info struct */ 6967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 6977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); 6987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret) goto cleanup; 6997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_link++; 7007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_make_decode_ready(vf)) return OV_EBADLINK; 7047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,&og); 7067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang cleanup: 7087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 7097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 7107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 7117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 7127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* if, eg, 64 bit stdio is configured by default, this will build with 7147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang fseek64 */ 7157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){ 7167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(f==NULL)return -1; 7177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return fseek(f,(long)off,whence); 7187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 7197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _ov_open1(void *f,OggVorbis_File *vf,char *initial, 7217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long ibytes, ov_callbacks callbacks){ 7227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int offsettest=(f?callbacks.seek_func(f,0,SEEK_CUR):-1); 7237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret; 7247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang memset(vf,0,sizeof(*vf)); 7267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* Tremor assumes in multiple places that right shift of a signed 7287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang integer is an arithmetic shift */ 7297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if( (-1>>1) != -1) return OV_EIMPL; 7307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->datasource=f; 7327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->callbacks = callbacks; 7337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* init the framing state */ 7357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->oy=ogg_sync_create(); 7367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* perhaps some data was previously read into a buffer for testing 7387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang against other stream types. Allow initialization from this 7397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang previously read data (as we may be reading from a non-seekable 7407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang stream) */ 7417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(initial){ 7427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang unsigned char *buffer=ogg_sync_bufferin(vf->oy,ibytes); 7437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang memcpy(buffer,initial,ibytes); 7447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_sync_wrote(vf->oy,ibytes); 7457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* can we seek? Stevens suggests the seek test was portable */ 7487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(offsettest!=-1)vf->seekable=1; 7497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* No seeking yet; Set up a 'single' (current) logical bitstream 7517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang entry for partial open */ 7527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->links=1; 7537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->os=ogg_stream_create(-1); /* fill in the serialno later */ 7547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* Try to fetch the headers, maintaining all the storage */ 7567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if((ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,NULL))<0){ 7577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->datasource=NULL; 7587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_clear(vf); 7597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else if(vf->ready_state < PARTOPEN) 7607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=PARTOPEN; 7617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 7627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 7637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangstatic int _ov_open2(OggVorbis_File *vf){ 7657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state < OPENED) 7667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->ready_state=OPENED; 7677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 7687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_open_seekable2(vf); 7697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret){ 7707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->datasource=NULL; 7717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_clear(vf); 7727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 7747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 7767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 7777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* clear out the OggVorbis_File struct */ 7807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_clear(OggVorbis_File *vf){ 7817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf){ 7827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_destroy(vf->vd); 7837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->vd=0; 7847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_destroy(vf->os); 7857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_clear(&vf->vi); 7867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_comment_clear(&vf->vc); 7877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->dataoffsets)_ogg_free(vf->dataoffsets); 7887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcmlengths)_ogg_free(vf->pcmlengths); 7897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->serialnos)_ogg_free(vf->serialnos); 7907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->offsets)_ogg_free(vf->offsets); 7917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_sync_destroy(vf->oy); 7927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 7937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->datasource)(vf->callbacks.close_func)(vf->datasource); 7947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang memset(vf,0,sizeof(*vf)); 7957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 7967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#ifdef DEBUG_LEAKS 7977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _VDBG_dump(); 7987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang#endif 7997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 8007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* inspects the OggVorbis file and finds/documents all the logical 8037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstreams contained in it. Tries to be tolerant of logical 8047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream sections that are truncated/woogie. 8057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return: -1) error 8077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 0) OK 8087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 8097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_open_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, 8117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_callbacks callbacks){ 8127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_ov_open1(f,vf,initial,ibytes,callbacks); 8137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return ret; 8147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return _ov_open2(vf); 8157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_open(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ 8187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_callbacks callbacks = { 8197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (size_t (*)(void *, size_t, size_t, void *)) fread, 8207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, 8217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (int (*)(void *)) fclose, 8227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (long (*)(void *)) ftell 8237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }; 8247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ov_open_callbacks((void *)f, vf, initial, ibytes, callbacks); 8267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* Only partially open the vorbis file; test for Vorbisness, and load 8297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the headers for the first chain. Do not seek (although test for 8307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang seekability). Use ov_test_open to finish opening the file, else 8317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_clear to close/free it. Same return codes as open. */ 8327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_test_callbacks(void *f,OggVorbis_File *vf,char *initial,long ibytes, 8347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_callbacks callbacks) 8357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang{ 8367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return _ov_open1(f,vf,initial,ibytes,callbacks); 8377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_test(FILE *f,OggVorbis_File *vf,char *initial,long ibytes){ 8407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_callbacks callbacks = { 8417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (size_t (*)(void *, size_t, size_t, void *)) fread, 8427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (int (*)(void *, ogg_int64_t, int)) _fseek64_wrap, 8437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (int (*)(void *)) fclose, 8447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (long (*)(void *)) ftell 8457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }; 8467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ov_test_callbacks((void *)f, vf, initial, ibytes, callbacks); 8487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_test_open(OggVorbis_File *vf){ 8517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state!=PARTOPEN)return OV_EINVAL; 8527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return _ov_open2(vf); 8537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* How many logical bitstreams in this physical bitstream? */ 8567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_streams(OggVorbis_File *vf){ 8577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->links; 8587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* Is the FILE * associated with vf seekable? */ 8617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_seekable(OggVorbis_File *vf){ 8627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->seekable; 8637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 8647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns the bitrate for a given logical bitstream or the entire 8667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang physical bitstream. If the file is open for random access, it will 8677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang find the *actual* average bitrate. If the file is streaming, it 8687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang returns the nominal bitrate (if set) else the average of the 8697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang upper/lower bounds (if set) else -1 (unset). 8707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang If you want the actual bitrate field settings, get them from the 8727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info structs */ 8737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 8747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_bitrate(OggVorbis_File *vf,int i){ 8757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 8767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i>=vf->links)return OV_EINVAL; 8777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable && i!=0)return ov_bitrate(vf,0); 8787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<0){ 8797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t bits=0; 8807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 8817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++) 8827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bits+=(vf->offsets[i+1]-vf->dataoffsets[i])*8; 8837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* This once read: return(rint(bits/ov_time_total(vf,-1))); 8847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * gcc 3.x on x86 miscompiled this at optimisation level 2 and above, 8857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang * so this is slightly transformed to make it work. 8867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 8877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (long)(bits*1000/ov_time_total(vf,-1)); 8887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 8897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 8907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* return the actual bitrate */ 8917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (long)((vf->offsets[i+1]-vf->dataoffsets[i])*8000/ov_time_total(vf,i)); 8927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 8937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* return nominal if set */ 8947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->vi.bitrate_nominal>0){ 8957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->vi.bitrate_nominal; 8967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 8977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->vi.bitrate_upper>0){ 8987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->vi.bitrate_lower>0){ 8997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (vf->vi.bitrate_upper+vf->vi.bitrate_lower)/2; 9007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 9017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->vi.bitrate_upper; 9027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_FALSE; 9057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns the actual bitrate since last call. returns -1 if no 9117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang additional data to offer since last call (or at beginning of stream), 9127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang EINVAL if stream is only partially open 9137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 9147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_bitrate_instant(OggVorbis_File *vf){ 9157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long ret; 9167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 9177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->samptrack==0)return OV_FALSE; 9187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=(long)(vf->bittrack/vf->samptrack*vf->vi.rate); 9197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack=0; 9207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack=0; 9217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 9227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* Guess */ 9257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_serialnumber(OggVorbis_File *vf,int i){ 9267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i>=vf->links)return ov_serialnumber(vf,vf->links-1); 9277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable && i>=0)return ov_serialnumber(vf,-1); 9287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<0){ 9297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->current_serialno; 9307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 9317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->serialnos[i]; 9327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns: total raw (compressed) length of content if i==-1 9367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang raw (compressed) length of that logical bitstream for i==0 to n 9377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang OV_EINVAL if the stream is not seekable (we can't know the length) 9387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang or if stream is only partially open 9397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 9407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_raw_total(OggVorbis_File *vf,int i){ 9417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 9427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable || i>=vf->links)return OV_EINVAL; 9437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<0){ 9447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t acc=0; 9457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 9467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++) 9477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang acc+=ov_raw_total(vf,i); 9487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return acc; 9497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 9507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->offsets[i+1]-vf->offsets[i]; 9517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns: total PCM length (samples) of content if i==-1 PCM length 9557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (samples) of that logical bitstream for i==0 to n 9567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang OV_EINVAL if the stream is not seekable (we can't know the 9577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length) or only partially open 9587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 9597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i){ 9607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 9617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable || i>=vf->links)return OV_EINVAL; 9627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<0){ 9637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t acc=0; 9647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 9657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++) 9667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang acc+=ov_pcm_total(vf,i); 9677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return acc; 9687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 9697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->pcmlengths[i*2+1]; 9707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* returns: total milliseconds of content if i==-1 9747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang milliseconds in that logical bitstream for i==0 to n 9757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang OV_EINVAL if the stream is not seekable (we can't know the 9767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length) or only partially open 9777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang*/ 9787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_time_total(OggVorbis_File *vf,int i){ 9797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 9807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable || i>=vf->links)return OV_EINVAL; 9817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(i<0){ 9827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t acc=0; 9837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 9847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->links;i++) 9857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang acc+=ov_time_total(vf,i); 9867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return acc; 9877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 9887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ((ogg_int64_t)vf->pcmlengths[i*2+1])*1000/vf->vi.rate; 9897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 9907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 9917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* seek to an offset relative to the *compressed* data. This also 9937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang scans packets to update the PCM cursor. It will cross a logical 9947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream boundary, but only if it can't get any packets out of the 9957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang tail of the bitstream we seek to (so no surprises). 9967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang returns zero on success, nonzero on failure */ 9987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 9997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos){ 10007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_state *work_os=NULL; 10017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 10027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 10037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 10057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable) 10067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_ENOSEEK; /* don't dump machine if we can't seek */ 10077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(pos<0 || pos>vf->end)return OV_EINVAL; 10097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* don't yet clear out decoding machine (if it's initialized), in 10117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the case we're in the same link. Restart the decode lapping, and 10127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang let _fetch_and_process_packet deal with a potential bitstream 10137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang boundary */ 10147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=-1; 10157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os, 10167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_serialno); /* must set serialno */ 10177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_restart(vf->vd); 10187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,pos); 10207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* we need to make sure the pcm_offset is set, but we don't want to 10227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang advance the raw cursor past good packets just to get to the first 10237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang with a granulepos. That's not equivalent behavior to beginning 10247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang decoding as immediately after the seek position as possible. 10257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang So, a hack. We use two stream states; a local scratch state and 10277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the shared vf->os stream state. We use the local state to 10287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang scan, and the shared state as a buffer for later decode. 10297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Unfortuantely, on the last page we still advance to last packet 10317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang because the granulepos on the last page is not necessarily on a 10327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang packet boundary, and we need to make sure the granpos is 10337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang correct. 10347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang */ 10357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 10377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int lastblock=0; 10387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int accblock=0; 10397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int thisblock; 10407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int eosflag; 10417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang work_os=ogg_stream_create(vf->current_serialno); /* get the memory ready */ 10437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 10447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state>=STREAMSET){ 10457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* snarf/scan a packet if we can */ 10467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int result=ogg_stream_packetout(work_os,&op); 10477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result>0){ 10497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->vi.codec_setup){ 10517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang thisblock=vorbis_packet_blocksize(&vf->vi,&op); 10527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(thisblock<0){ 10537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_packetout(vf->os,NULL); 10547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang thisblock=0; 10557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 10567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(eosflag) 10587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_packetout(vf->os,NULL); 10597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang else 10607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(lastblock)accblock+=(lastblock+thisblock)>>2; 10617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(op.granulepos!=-1){ 10647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i,link=vf->current_link; 10657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2]; 10667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(granulepos<0)granulepos=0; 10677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<link;i++) 10697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang granulepos+=vf->pcmlengths[i*2+1]; 10707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=granulepos-accblock; 10717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 10727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lastblock=thisblock; 10747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang continue; 10757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else 10767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_packetout(vf->os,NULL); 10777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!lastblock){ 10817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_get_next_page(vf,&og,-1)<0){ 10827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=ov_pcm_total(vf,-1); 10837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 10847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 10867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* huh? Bogus stream with packets but no granulepos */ 10877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=-1; 10887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 10897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* did we just grab a page from other than current link? */ 10927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state>=STREAMSET) 10937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->current_serialno!=ogg_page_serialno(&og)){ 10947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _decode_clear(vf); /* clear out stream state */ 10957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_destroy(work_os); 10967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 10977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 10987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<STREAMSET){ 10997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link; 11007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_serialno=ogg_page_serialno(&og); 11027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=0;link<vf->links;link++) 11037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->serialnos[link]==vf->current_serialno)break; 11047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link==vf->links) 11057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto seek_error; /* sign of a bogus stream. error out, 11067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang leave machine uninitialized */ 11077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* need to initialize machine to this link */ 11097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 11107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number_preserve_pos(vf,link); 11117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret) goto seek_error; 11127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os,vf->current_serialno); 11147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(work_os,vf->current_serialno); 11157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 11207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page dup; 11217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_dup(&dup,&og); 11227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang eosflag=ogg_page_eos(&og); 11237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,&og); 11247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(work_os,&dup); 11257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 11307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 11317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_destroy(work_os); 11327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack=0; 11337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack=0; 11347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 11357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang seek_error: 11377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 11387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 11397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* dump the machine so we're in a known state */ 11417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=-1; 11427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_destroy(work_os); 11437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _decode_clear(vf); 11447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_EBADLINK; 11457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 11467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* Page granularity seek (faster than sample granularity because we 11487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang don't do the last bit of decode to find a specific sample). 11497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang Seek to the last [granule marked] page preceeding the specified pos 11517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang location, such that decoding past the returned point will quickly 11527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang arrive at the requested position. */ 11537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){ 11547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link=-1; 11557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t result=0; 11567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t total=ov_pcm_total(vf,-1); 11577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 11587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 11597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 11617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable)return OV_ENOSEEK; 11627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(pos<0 || pos>total)return OV_EINVAL; 11637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* which bitstream section does this pcm offset occur in? */ 11657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=vf->links-1;link>=0;link--){ 11667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang total-=vf->pcmlengths[link*2+1]; 11677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(pos>=total)break; 11687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link!=vf->current_link){ 11727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number(vf,link); 11737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret) goto seek_error; 11747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 11757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_restart(vf->vd); 11767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 11777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_reset_serialno(vf->os,vf->serialnos[link]); 11797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* search within the logical bitstream for the page with the highest 11817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_pos preceeding (or equal to) pos. There is a danger here; 11827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang missing pages or incorrect frame number information in the 11837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bitstream could make our task impossible. Account for that (it 11847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang would be an error condition) */ 11857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* new search algorithm by HB (Nicholas Vinen) */ 11877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 11887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t end=vf->offsets[link+1]; 11897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t begin=vf->offsets[link]; 11907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t begintime = vf->pcmlengths[link*2]; 11917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime; 11927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t target=pos-total+begintime; 11937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t best=begin; 11947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(begin<end){ 11967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t bisect; 11977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 11987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(end-begin<CHUNKSIZE){ 11997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=begin; 12007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 12017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* take a (pretty decent) guess. */ 12027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=begin + 12037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE; 12047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect<=begin) 12057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=begin+1; 12067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,bisect); 12097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(begin<end){ 12117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result=_get_next_page(vf,&og,end-vf->offset); 12127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result==OV_EREAD) goto seek_error; 12137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result<0){ 12147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect<=begin+1) 12157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end=begin; /* found it */ 12167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang else{ 12177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect==0) goto seek_error; 12187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect-=CHUNKSIZE; 12197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect<=begin)bisect=begin+1; 12207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,bisect); 12217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 12237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t granulepos=ogg_page_granulepos(&og); 12247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(granulepos==-1)continue; 12257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(granulepos<target){ 12267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang best=result; /* raw offset of packet with granulepos */ 12277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang begin=vf->offset; /* raw offset of next page */ 12287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang begintime=granulepos; 12297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(target-begintime>44100)break; 12317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect=begin; /* *not* begin + 1 */ 12327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 12337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect<=begin+1) 12347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end=begin; /* found it */ 12357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang else{ 12367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(end==vf->offset){ /* we're pretty close - we'd be stuck in */ 12377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end=result; 12387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang bisect-=CHUNKSIZE; /* an endless loop otherwise. */ 12397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bisect<=begin)bisect=begin+1; 12407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,bisect); 12417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 12427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang end=result; 12437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang endtime=granulepos; 12447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 12457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* found our page. seek to it, update pcm offset. Easier case than 12537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang raw_seek, don't keep packets preceeding granulepos. */ 12547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 12557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* seek */ 12577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,best); 12587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=-1; 12597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_get_next_page(vf,&og,-1)<0){ 12617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 12627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_EOF; /* shouldn't happen */ 12637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,&og); 12667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* pull out all but last packet; the one with granulepos */ 12687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 12697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result=ogg_stream_packetpeek(vf->os,&op); 12707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result==0){ 12717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* !!! the packet finishing this page originated on a 12727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang preceeding page. Keep fetching previous pages until we 12737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang get one with a granulepos or without the 'continued' flag 12747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang set. Then just use raw_seek for simplicity. */ 12757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _seek_helper(vf,best); 12777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 12787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 12797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result=_get_prev_page(vf,&og); 12807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result<0) goto seek_error; 12817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ogg_page_granulepos(&og)>-1 || 12827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang !ogg_page_continued(&og)){ 12837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ov_raw_seek(vf,result); 12847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->offset=result; 12867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(result<0){ 12897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result = OV_EBADPACKET; 12907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto seek_error; 12917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 12927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(op.granulepos!=-1){ 12937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; 12947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcm_offset<0)vf->pcm_offset=0; 12957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset+=total; 12967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang break; 12977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else 12987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result=ogg_stream_packetout(vf->os,NULL); 12997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* verify result */ 13047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){ 13057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang result=OV_EFAULT; 13067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang goto seek_error; 13077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack=0; 13097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack=0; 13107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 13127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 13137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 13147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang seek_error: 13167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 13187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 13197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* dump machine so we're in a known state */ 13217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=-1; 13227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang _decode_clear(vf); 13237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return (int)result; 13247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 13257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* seek to a sample offset relative to the decompressed pcm stream 13277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang returns zero on success, nonzero on failure */ 13287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){ 13307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet op={0,0,0,0,0,0}; 13317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page og={0,0,0,0}; 13327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int thisblock,lastblock=0; 13337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=ov_pcm_seek_page(vf,pos); 13347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0)return ret; 13357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_make_decode_ready(vf))return OV_EBADLINK; 13367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* discard leading packets we don't need for the lapping of the 13387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang position we want; don't decode them */ 13397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 13417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=ogg_stream_packetpeek(vf->os,&op); 13437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret>0){ 13447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang thisblock=vorbis_packet_blocksize(&vf->vi,&op); 13457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(thisblock<0){ 13467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_packetout(vf->os,NULL); 13477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang continue; /* non audio packet */ 13487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2; 13507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcm_offset+((thisblock+ 13527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_info_blocksize(&vf->vi,1))>>2)>=pos)break; 13537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* remove the packet from packet queue and track its granulepos */ 13557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_packetout(vf->os,NULL); 13567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_synthesis(vf->vd,&op,0); /* set up a vb with 13577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang only tracking, no 13587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_decode */ 13597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* end of logical stream case is hard, especially with exact 13617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length positioning. */ 13627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(op.granulepos>-1){ 13647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int i; 13657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* always believe the stream markers */ 13667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2]; 13677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcm_offset<0)vf->pcm_offset=0; 13687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(i=0;i<vf->current_link;i++) 13697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset+=vf->pcmlengths[i*2+1]; 13707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lastblock=thisblock; 13737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang }else{ 13757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<0 && ret!=OV_HOLE)break; 13767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* suck in a new page */ 13787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_get_next_page(vf,&og,-1)<0)break; 13797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf); 13807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<STREAMSET){ 13827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link,ret; 13837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_serialno=ogg_page_serialno(&og); 13857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=0;link<vf->links;link++) 13867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->serialnos[link]==vf->current_serialno)break; 13877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link==vf->links){ 13887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 13897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 13907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return OV_EBADLINK; 13917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 13927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 13947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->current_link=link; 13957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ret=_fetch_headers(vf,&vf->vi,&vf->vc,&vf->current_serialno,&og); 13967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret) return ret; 13977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_make_decode_ready(vf))return OV_EBADLINK; 13987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang lastblock=0; 13997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_stream_pagein(vf->os,&og); 14027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->bittrack=0; 14067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->samptrack=0; 14077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* discard samples until we reach the desired position. Crossing a 14087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang logical bitstream boundary with abandon is OK. */ 14097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(vf->pcm_offset<pos){ 14107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t target=pos-vf->pcm_offset; 14117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long samples=vorbis_dsp_pcmout(vf->vd,NULL,0); 14127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(samples>target)samples=(long)target; 14147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_read(vf->vd,samples); 14157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset+=samples; 14167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(samples<target) 14187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(_fetch_and_process_packet(vf,1,1)<=0) 14197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */ 14207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_page_release(&og); 14237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_packet_release(&op); 14247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 14257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 14267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* seek to a playback time relative to the decompressed pcm stream 14287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang returns zero on success, nonzero on failure */ 14297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_time_seek(OggVorbis_File *vf,ogg_int64_t milliseconds){ 14307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* translate time to PCM position and call ov_pcm_seek */ 14317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link=-1; 14337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t pcm_total=ov_pcm_total(vf,-1); 14347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t time_total=ov_time_total(vf,-1); 14357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 14377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable)return OV_ENOSEEK; 14387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; 14397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* which bitstream section does this time offset occur in? */ 14417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=vf->links-1;link>=0;link--){ 14427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_total-=vf->pcmlengths[link*2+1]; 14437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang time_total-=ov_time_total(vf,link); 14447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(milliseconds>=time_total)break; 14457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* enough information to convert time offset to pcm offset */ 14487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 14497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number(vf,link); 14507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return ret; 14517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 14527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_pcm_seek(vf,pcm_total+(milliseconds-time_total)* 14537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->vi.rate/1000); 14547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 14567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* page-granularity version of ov_time_seek 14587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang returns zero on success, nonzero on failure */ 14597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangint ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t milliseconds){ 14607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* translate time to PCM position and call ov_pcm_seek */ 14617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link=-1; 14637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t pcm_total=ov_pcm_total(vf,-1); 14647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t time_total=ov_time_total(vf,-1); 14657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 14677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(!vf->seekable)return OV_ENOSEEK; 14687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(milliseconds<0 || milliseconds>time_total)return OV_EINVAL; 14697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* which bitstream section does this time offset occur in? */ 14717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=vf->links-1;link>=0;link--){ 14727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_total-=vf->pcmlengths[link*2+1]; 14737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang time_total-=ov_time_total(vf,link); 14747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(milliseconds>=time_total)break; 14757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* enough information to convert time offset to pcm offset */ 14787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 14797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number(vf,link); 14807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return ret; 14817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 14827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_pcm_seek_page(vf,pcm_total+(milliseconds-time_total)* 14837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->vi.rate/1000); 14847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 14857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 14867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* tell the current stream offset cursor. Note that seek followed by 14887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang tell will likely not give the set offset due to caching */ 14897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_raw_tell(OggVorbis_File *vf){ 14907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 14917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->offset; 14927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 14937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 14947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* return PCM offset (sample) of next PCM sample to be read */ 14957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_pcm_tell(OggVorbis_File *vf){ 14967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 14977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return vf->pcm_offset; 14987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 14997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* return time offset (milliseconds) of next PCM sample to be read */ 15017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangogg_int64_t ov_time_tell(OggVorbis_File *vf){ 15027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int link=0; 15037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t pcm_total=0; 15047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ogg_int64_t time_total=0; 15057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 15077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 15087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_total=ov_pcm_total(vf,-1); 15097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang time_total=ov_time_total(vf,-1); 15107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* which bitstream section does this time offset occur in? */ 15127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang for(link=vf->links-1;link>=0;link--){ 15137913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang pcm_total-=vf->pcmlengths[link*2+1]; 15147913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang time_total-=ov_time_total(vf,link); 15157913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->pcm_offset>=pcm_total)break; 15167913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15177913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15187913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15197913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return time_total+(1000*vf->pcm_offset-pcm_total)/vf->vi.rate; 15207913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 15217913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15227913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* link: -1) return the vorbis_info struct for the bitstream section 15237913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang currently being decoded 15247913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 0-n) to request information for a specific bitstream section 15257913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15267913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang In the case of a non-seekable bitstream, any call returns the 15277913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang current bitstream. NULL in the case that the machine is not 15287913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang initialized */ 15297913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15307913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvorbis_info *ov_info(OggVorbis_File *vf,int link){ 15317913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 15327913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link>=vf->links)return NULL; 15337913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link>=0){ 15347913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number_preserve_pos(vf,link); 15357913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return NULL; 15367913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15377913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15387913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return &vf->vi; 15397913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 15407913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15417913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* grr, strong typing, grr, no templates/inheritence, grr */ 15427913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wangvorbis_comment *ov_comment(OggVorbis_File *vf,int link){ 15437913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->seekable){ 15447913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link>=vf->links)return NULL; 15457913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(link>=0){ 15467913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_set_link_number_preserve_pos(vf,link); 15477913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret)return NULL; 15487913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15497913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15507913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return &vf->vc; 15517913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 15527913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15537913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang/* up to this point, everything could more or less hide the multiple 15547913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang logical bitstream nature of chaining from the toplevel application 15557913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if the toplevel application didn't particularly care. However, at 15567913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang the point that we actually read audio back, the multiple-section 15577913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang nature must surface: Multiple bitstream sections do not necessarily 15587913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang have to have the same number of channels or sampling rate. 15597913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15607913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang ov_read returns the sequential logical bitstream number currently 15617913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang being decoded along with the PCM data in order that the toplevel 15627913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang application can take action on channel/sample rate changes. This 15637913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang number will be incremented even for streamed (non-seekable) streams 15647913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang (for seekable streams, it represents the actual logical bitstream 15657913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang index within the physical bitstream. Note that the accessor 15667913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang functions above are aware of this dichotomy). 15677913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15687913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang input values: buffer) a buffer to hold packed PCM data for return 15697913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang length) the byte length requested to be placed into buffer 15707913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15717913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return values: <0) error/hole in data (OV_HOLE), partial open (OV_EINVAL) 15727913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 0) EOF 15737913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang n) number of bytes of PCM actually returned. The 15747913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang below works on a packet-by-packet basis, so the 15757913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return length is not related to the 'length' passed 15767913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang in, just guaranteed to fit. 15777913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15787913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang *section) set to the logical bitstream number */ 15797913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15807913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wanglong ov_read(OggVorbis_File *vf,void *buffer,int bytes_req,int *bitstream){ 15817913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15827913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long samples; 15837913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang long channels; 15847913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15857913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state<OPENED)return OV_EINVAL; 15867913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 15877913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang while(1){ 15887913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(vf->ready_state==INITSET){ 15897913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang channels=vf->vi.channels; 15907913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang samples=vorbis_dsp_pcmout(vf->vd,buffer,(bytes_req>>1)/channels); 15917913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(samples){ 15927913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(samples>0){ 15937913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vorbis_dsp_read(vf->vd,samples); 15947913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang vf->pcm_offset+=samples; 15957913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(bitstream)*bitstream=vf->current_link; 15967913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return samples*2*channels; 15977913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 15987913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return samples; 15997913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 16007913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 16017913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 16027913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang /* suck in another packet */ 16037913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang { 16047913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang int ret=_fetch_and_process_packet(vf,1,1); 16057913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret==OV_EOF) 16067913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return 0; 16077913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang if(ret<=0) 16087913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang return ret; 16097913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 16107913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang 16117913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang } 16127913073ddf11ca3dd7b0439998e1b17d443bb0baGloria Wang} 1613