annotate src/opusfile-0.9/examples/seeking_example.c @ 154:4664ac0c1032

Add Opus sources and macOS builds
author Chris Cannam <cannam@all-day-breakfast.com>
date Wed, 23 Jan 2019 13:48:08 +0000
parents
children
rev   line source
cannam@154 1 /********************************************************************
cannam@154 2 * *
cannam@154 3 * THIS FILE IS PART OF THE libopusfile SOFTWARE CODEC SOURCE CODE. *
cannam@154 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
cannam@154 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
cannam@154 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
cannam@154 7 * *
cannam@154 8 * THE libopusfile SOURCE CODE IS (C) COPYRIGHT 1994-2012 *
cannam@154 9 * by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
cannam@154 10 * *
cannam@154 11 ********************************************************************/
cannam@154 12 #ifdef HAVE_CONFIG_H
cannam@154 13 #include "config.h"
cannam@154 14 #endif
cannam@154 15
cannam@154 16 /*For fileno()*/
cannam@154 17 #if !defined(_POSIX_SOURCE)
cannam@154 18 # define _POSIX_SOURCE 1
cannam@154 19 #endif
cannam@154 20 #include <stdio.h>
cannam@154 21 #include <stdlib.h>
cannam@154 22 #include <errno.h>
cannam@154 23 #include <math.h>
cannam@154 24 #include <string.h>
cannam@154 25 #include <opusfile.h>
cannam@154 26 #if defined(_WIN32)
cannam@154 27 # include "win32utf8.h"
cannam@154 28 # undef fileno
cannam@154 29 # define fileno _fileno
cannam@154 30 #endif
cannam@154 31
cannam@154 32 /*Use shorts, they're smaller.*/
cannam@154 33 #if !defined(OP_FIXED_POINT)
cannam@154 34 # define OP_FIXED_POINT (1)
cannam@154 35 #endif
cannam@154 36
cannam@154 37 #if defined(OP_FIXED_POINT)
cannam@154 38
cannam@154 39 typedef opus_int16 op_sample;
cannam@154 40
cannam@154 41 # define op_read_native op_read
cannam@154 42
cannam@154 43 /*TODO: The convergence after 80 ms of preroll is far from exact.
cannam@154 44 Our comparison is very rough.
cannam@154 45 Need to find some way to do this better.*/
cannam@154 46 # define MATCH_TOL (16384)
cannam@154 47
cannam@154 48 # define ABS(_x) ((_x)<0?-(_x):(_x))
cannam@154 49
cannam@154 50 # define MATCH(_a,_b) (ABS((_a)-(_b))<MATCH_TOL)
cannam@154 51
cannam@154 52 /*Don't have fixed-point downmixing code.*/
cannam@154 53 # undef OP_WRITE_SEEK_SAMPLES
cannam@154 54
cannam@154 55 #else
cannam@154 56
cannam@154 57 typedef float op_sample;
cannam@154 58
cannam@154 59 # define op_read_native op_read_float
cannam@154 60
cannam@154 61 /*TODO: The convergence after 80 ms of preroll is far from exact.
cannam@154 62 Our comparison is very rough.
cannam@154 63 Need to find some way to do this better.*/
cannam@154 64 # define MATCH_TOL (16384.0/32768)
cannam@154 65
cannam@154 66 # define FABS(_x) ((_x)<0?-(_x):(_x))
cannam@154 67
cannam@154 68 # define MATCH(_a,_b) (FABS((_a)-(_b))<MATCH_TOL)
cannam@154 69
cannam@154 70 # if defined(OP_WRITE_SEEK_SAMPLES)
cannam@154 71 /*Matrices for downmixing from the supported channel counts to stereo.*/
cannam@154 72 static const float DOWNMIX_MATRIX[8][8][2]={
cannam@154 73 /*mono*/
cannam@154 74 {
cannam@154 75 {1.F,1.F}
cannam@154 76 },
cannam@154 77 /*stereo*/
cannam@154 78 {
cannam@154 79 {1.F,0.F},{0.F,1.F}
cannam@154 80 },
cannam@154 81 /*3.0*/
cannam@154 82 {
cannam@154 83 {0.5858F,0.F},{0.4142F,0.4142F},{0,0.5858F}
cannam@154 84 },
cannam@154 85 /*quadrophonic*/
cannam@154 86 {
cannam@154 87 {0.4226F,0.F},{0,0.4226F},{0.366F,0.2114F},{0.2114F,0.336F}
cannam@154 88 },
cannam@154 89 /*5.0*/
cannam@154 90 {
cannam@154 91 {0.651F,0.F},{0.46F,0.46F},{0,0.651F},{0.5636F,0.3254F},{0.3254F,0.5636F}
cannam@154 92 },
cannam@154 93 /*5.1*/
cannam@154 94 {
cannam@154 95 {0.529F,0.F},{0.3741F,0.3741F},{0.F,0.529F},{0.4582F,0.2645F},
cannam@154 96 {0.2645F,0.4582F},{0.3741F,0.3741F}
cannam@154 97 },
cannam@154 98 /*6.1*/
cannam@154 99 {
cannam@154 100 {0.4553F,0.F},{0.322F,0.322F},{0.F,0.4553F},{0.3943F,0.2277F},
cannam@154 101 {0.2277F,0.3943F},{0.2788F,0.2788F},{0.322F,0.322F}
cannam@154 102 },
cannam@154 103 /*7.1*/
cannam@154 104 {
cannam@154 105 {0.3886F,0.F},{0.2748F,0.2748F},{0.F,0.3886F},{0.3366F,0.1943F},
cannam@154 106 {0.1943F,0.3366F},{0.3366F,0.1943F},{0.1943F,0.3366F},{0.2748F,0.2748F}
cannam@154 107 }
cannam@154 108 };
cannam@154 109
cannam@154 110 static void write_samples(float *_samples,int _nsamples,int _nchannels){
cannam@154 111 float stereo_pcm[120*48*2];
cannam@154 112 int i;
cannam@154 113 for(i=0;i<_nsamples;i++){
cannam@154 114 float l;
cannam@154 115 float r;
cannam@154 116 int ci;
cannam@154 117 l=r=0.F;
cannam@154 118 for(ci=0;ci<_nchannels;ci++){
cannam@154 119 l+=DOWNMIX_MATRIX[_nchannels-1][ci][0]*_samples[i*_nchannels+ci];
cannam@154 120 r+=DOWNMIX_MATRIX[_nchannels-1][ci][1]*_samples[i*_nchannels+ci];
cannam@154 121 }
cannam@154 122 stereo_pcm[2*i+0]=l;
cannam@154 123 stereo_pcm[2*i+1]=r;
cannam@154 124 }
cannam@154 125 fwrite(stereo_pcm,sizeof(*stereo_pcm)*2,_nsamples,stdout);
cannam@154 126 }
cannam@154 127 # endif
cannam@154 128
cannam@154 129 #endif
cannam@154 130
cannam@154 131 static long nfailures;
cannam@154 132
cannam@154 133 static void verify_seek(OggOpusFile *_of,opus_int64 _byte_offset,
cannam@154 134 ogg_int64_t _pcm_offset,ogg_int64_t _pcm_length,op_sample *_bigassbuffer){
cannam@154 135 opus_int64 byte_offset;
cannam@154 136 ogg_int64_t pcm_offset;
cannam@154 137 ogg_int64_t duration;
cannam@154 138 op_sample buffer[120*48*8];
cannam@154 139 int nchannels;
cannam@154 140 int nsamples;
cannam@154 141 int li;
cannam@154 142 int lj;
cannam@154 143 int i;
cannam@154 144 byte_offset=op_raw_tell(_of);
cannam@154 145 if(_byte_offset!=-1&&byte_offset<_byte_offset){
cannam@154 146 fprintf(stderr,"\nRaw position out of tolerance: requested %li, "
cannam@154 147 "got %li.\n",(long)_byte_offset,(long)byte_offset);
cannam@154 148 nfailures++;
cannam@154 149 }
cannam@154 150 pcm_offset=op_pcm_tell(_of);
cannam@154 151 if(_pcm_offset!=-1&&pcm_offset>_pcm_offset){
cannam@154 152 fprintf(stderr,"\nPCM position out of tolerance: requested %li, "
cannam@154 153 "got %li.\n",(long)_pcm_offset,(long)pcm_offset);
cannam@154 154 nfailures++;
cannam@154 155 }
cannam@154 156 if(pcm_offset<0||pcm_offset>_pcm_length){
cannam@154 157 fprintf(stderr,"\nPCM position out of bounds: got %li.\n",
cannam@154 158 (long)pcm_offset);
cannam@154 159 nfailures++;
cannam@154 160 }
cannam@154 161 nsamples=op_read_native(_of,buffer,sizeof(buffer)/sizeof(*buffer),&li);
cannam@154 162 if(nsamples<0){
cannam@154 163 fprintf(stderr,"\nFailed to read PCM data after seek: %i\n",nsamples);
cannam@154 164 nfailures++;
cannam@154 165 li=op_current_link(_of);
cannam@154 166 }
cannam@154 167 for(lj=0;lj<li;lj++){
cannam@154 168 duration=op_pcm_total(_of,lj);
cannam@154 169 if(0<=pcm_offset&&pcm_offset<duration){
cannam@154 170 fprintf(stderr,"\nPCM data after seek came from the wrong link: "
cannam@154 171 "expected %i, got %i.\n",lj,li);
cannam@154 172 nfailures++;
cannam@154 173 }
cannam@154 174 pcm_offset-=duration;
cannam@154 175 if(_bigassbuffer!=NULL)_bigassbuffer+=op_channel_count(_of,lj)*duration;
cannam@154 176 }
cannam@154 177 duration=op_pcm_total(_of,li);
cannam@154 178 if(pcm_offset+nsamples>duration){
cannam@154 179 fprintf(stderr,"\nPCM data after seek exceeded link duration: "
cannam@154 180 "limit %li, got %li.\n",(long)duration,(long)(pcm_offset+nsamples));
cannam@154 181 nfailures++;
cannam@154 182 }
cannam@154 183 nchannels=op_channel_count(_of,li);
cannam@154 184 if(_bigassbuffer!=NULL){
cannam@154 185 for(i=0;i<nsamples*nchannels;i++){
cannam@154 186 if(!MATCH(buffer[i],_bigassbuffer[pcm_offset*nchannels+i])){
cannam@154 187 ogg_int64_t j;
cannam@154 188 fprintf(stderr,"\nData after seek doesn't match declared PCM "
cannam@154 189 "position: mismatch %G\n",
cannam@154 190 (double)buffer[i]-_bigassbuffer[pcm_offset*nchannels+i]);
cannam@154 191 for(j=0;j<duration-nsamples;j++){
cannam@154 192 for(i=0;i<nsamples*nchannels;i++){
cannam@154 193 if(!MATCH(buffer[i],_bigassbuffer[j*nchannels+i]))break;
cannam@154 194 }
cannam@154 195 if(i==nsamples*nchannels){
cannam@154 196 fprintf(stderr,"\nData after seek appears to match position %li.\n",
cannam@154 197 (long)i);
cannam@154 198 }
cannam@154 199 }
cannam@154 200 nfailures++;
cannam@154 201 break;
cannam@154 202 }
cannam@154 203 }
cannam@154 204 }
cannam@154 205 #if defined(OP_WRITE_SEEK_SAMPLES)
cannam@154 206 write_samples(buffer,nsamples,nchannels);
cannam@154 207 #endif
cannam@154 208 }
cannam@154 209
cannam@154 210 #define OP_MIN(_a,_b) ((_a)<(_b)?(_a):(_b))
cannam@154 211
cannam@154 212 /*A simple wrapper that lets us count the number of underlying seek calls.*/
cannam@154 213
cannam@154 214 static op_seek_func real_seek;
cannam@154 215
cannam@154 216 static long nreal_seeks;
cannam@154 217
cannam@154 218 static int seek_stat_counter(void *_stream,opus_int64 _offset,int _whence){
cannam@154 219 if(_whence==SEEK_SET)nreal_seeks++;
cannam@154 220 /*SEEK_CUR with an offset of 0 is free, as is SEEK_END with an offset of 0
cannam@154 221 (assuming we know the file size), so don't count them.*/
cannam@154 222 else if(_offset!=0)nreal_seeks++;
cannam@154 223 return (*real_seek)(_stream,_offset,_whence);
cannam@154 224 }
cannam@154 225
cannam@154 226 #define NSEEK_TESTS (1000)
cannam@154 227
cannam@154 228 static void print_duration(FILE *_fp,ogg_int64_t _nsamples){
cannam@154 229 ogg_int64_t seconds;
cannam@154 230 ogg_int64_t minutes;
cannam@154 231 ogg_int64_t hours;
cannam@154 232 ogg_int64_t days;
cannam@154 233 ogg_int64_t weeks;
cannam@154 234 seconds=_nsamples/48000;
cannam@154 235 _nsamples-=seconds*48000;
cannam@154 236 minutes=seconds/60;
cannam@154 237 seconds-=minutes*60;
cannam@154 238 hours=minutes/60;
cannam@154 239 minutes-=hours*60;
cannam@154 240 days=hours/24;
cannam@154 241 hours-=days*24;
cannam@154 242 weeks=days/7;
cannam@154 243 days-=weeks*7;
cannam@154 244 if(weeks)fprintf(_fp,"%liw",(long)weeks);
cannam@154 245 if(weeks||days)fprintf(_fp,"%id",(int)days);
cannam@154 246 if(weeks||days||hours){
cannam@154 247 if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
cannam@154 248 else fprintf(_fp,"%ih",(int)hours);
cannam@154 249 }
cannam@154 250 if(weeks||days||hours||minutes){
cannam@154 251 if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
cannam@154 252 else fprintf(_fp,"%im",(int)minutes);
cannam@154 253 fprintf(_fp,"%02i",(int)seconds);
cannam@154 254 }
cannam@154 255 else fprintf(_fp,"%i",(int)seconds);
cannam@154 256 fprintf(_fp,".%03is",(int)(_nsamples+24)/48);
cannam@154 257 }
cannam@154 258
cannam@154 259 int main(int _argc,const char **_argv){
cannam@154 260 OpusFileCallbacks cb;
cannam@154 261 OggOpusFile *of;
cannam@154 262 void *fp;
cannam@154 263 #if defined(_WIN32)
cannam@154 264 win32_utf8_setup(&_argc,&_argv);
cannam@154 265 #endif
cannam@154 266 if(_argc!=2){
cannam@154 267 fprintf(stderr,"Usage: %s <file.opus>\n",_argv[0]);
cannam@154 268 return EXIT_FAILURE;
cannam@154 269 }
cannam@154 270 memset(&cb,0,sizeof(cb));
cannam@154 271 if(strcmp(_argv[1],"-")==0)fp=op_fdopen(&cb,fileno(stdin),"rb");
cannam@154 272 else{
cannam@154 273 /*Try to treat the argument as a URL.*/
cannam@154 274 fp=op_url_stream_create(&cb,_argv[1],
cannam@154 275 OP_SSL_SKIP_CERTIFICATE_CHECK(1),NULL);
cannam@154 276 /*Fall back assuming it's a regular file name.*/
cannam@154 277 if(fp==NULL)fp=op_fopen(&cb,_argv[1],"rb");
cannam@154 278 }
cannam@154 279 if(cb.seek!=NULL){
cannam@154 280 real_seek=cb.seek;
cannam@154 281 cb.seek=seek_stat_counter;
cannam@154 282 }
cannam@154 283 of=op_open_callbacks(fp,&cb,NULL,0,NULL);
cannam@154 284 if(of==NULL){
cannam@154 285 fprintf(stderr,"Failed to open file '%s'.\n",_argv[1]);
cannam@154 286 return EXIT_FAILURE;
cannam@154 287 }
cannam@154 288 if(op_seekable(of)){
cannam@154 289 op_sample *bigassbuffer;
cannam@154 290 ogg_int64_t size;
cannam@154 291 ogg_int64_t pcm_offset;
cannam@154 292 ogg_int64_t pcm_length;
cannam@154 293 ogg_int64_t nsamples;
cannam@154 294 long max_seeks;
cannam@154 295 int nlinks;
cannam@154 296 int ret;
cannam@154 297 int li;
cannam@154 298 int i;
cannam@154 299 /*Because we want to do sample-level verification that the seek does what
cannam@154 300 it claimed, decode the entire file into memory.*/
cannam@154 301 nlinks=op_link_count(of);
cannam@154 302 fprintf(stderr,"Opened file containing %i links with %li seeks "
cannam@154 303 "(%0.3f per link).\n",nlinks,nreal_seeks,nreal_seeks/(double)nlinks);
cannam@154 304 /*Reset the seek counter.*/
cannam@154 305 nreal_seeks=0;
cannam@154 306 nsamples=0;
cannam@154 307 for(li=0;li<nlinks;li++){
cannam@154 308 nsamples+=op_pcm_total(of,li)*op_channel_count(of,li);
cannam@154 309 }
cannam@154 310 /*Until we find another way to do the comparisons that solves the MATCH_TOL
cannam@154 311 problem, disable this.*/
cannam@154 312 #if 0
cannam@154 313 bigassbuffer=_ogg_malloc(sizeof(*bigassbuffer)*nsamples);
cannam@154 314 if(bigassbuffer==NULL){
cannam@154 315 fprintf(stderr,
cannam@154 316 "Buffer allocation failed. Seek offset detection disabled.\n");
cannam@154 317 }
cannam@154 318 #else
cannam@154 319 bigassbuffer=NULL;
cannam@154 320 #endif
cannam@154 321 pcm_offset=op_pcm_tell(of);
cannam@154 322 if(pcm_offset!=0){
cannam@154 323 fprintf(stderr,"Initial PCM offset was not 0, got %li instead.!\n",
cannam@154 324 (long)pcm_offset);
cannam@154 325 nfailures++;
cannam@154 326 }
cannam@154 327 /*Disabling the linear scan for now.
cannam@154 328 Only test on non-borken files!*/
cannam@154 329 #if 0
cannam@154 330 {
cannam@154 331 op_sample smallerbuffer[120*48*8];
cannam@154 332 ogg_int64_t pcm_print_offset;
cannam@154 333 ogg_int64_t si;
cannam@154 334 opus_int32 bitrate;
cannam@154 335 int saw_hole;
cannam@154 336 pcm_print_offset=pcm_offset-48000;
cannam@154 337 bitrate=0;
cannam@154 338 saw_hole=0;
cannam@154 339 for(si=0;si<nsamples;){
cannam@154 340 ogg_int64_t next_pcm_offset;
cannam@154 341 opus_int32 next_bitrate;
cannam@154 342 op_sample *buf;
cannam@154 343 int buf_size;
cannam@154 344 buf=bigassbuffer==NULL?smallerbuffer:bigassbuffer+si;
cannam@154 345 buf_size=(int)OP_MIN(nsamples-si,
cannam@154 346 (int)(sizeof(smallerbuffer)/sizeof(*smallerbuffer))),
cannam@154 347 ret=op_read_native(of,buf,buf_size,&li);
cannam@154 348 if(ret==OP_HOLE){
cannam@154 349 /*Only warn once in a row.*/
cannam@154 350 if(saw_hole)continue;
cannam@154 351 saw_hole=1;
cannam@154 352 /*This is just a warning.
cannam@154 353 As long as the timestamps are still contiguous we're okay.*/
cannam@154 354 fprintf(stderr,"\nHole in PCM data at sample %li\n",
cannam@154 355 (long)pcm_offset);
cannam@154 356 continue;
cannam@154 357 }
cannam@154 358 else if(ret<=0){
cannam@154 359 fprintf(stderr,"\nFailed to read PCM data: %i\n",ret);
cannam@154 360 exit(EXIT_FAILURE);
cannam@154 361 }
cannam@154 362 saw_hole=0;
cannam@154 363 /*If we have gaps in the PCM positions, seeking is not likely to work
cannam@154 364 near them.*/
cannam@154 365 next_pcm_offset=op_pcm_tell(of);
cannam@154 366 if(pcm_offset+ret!=next_pcm_offset){
cannam@154 367 fprintf(stderr,"\nGap in PCM offset: expecting %li, got %li\n",
cannam@154 368 (long)(pcm_offset+ret),(long)next_pcm_offset);
cannam@154 369 nfailures++;
cannam@154 370 }
cannam@154 371 pcm_offset=next_pcm_offset;
cannam@154 372 si+=ret*op_channel_count(of,li);
cannam@154 373 if(pcm_offset>=pcm_print_offset+48000){
cannam@154 374 next_bitrate=op_bitrate_instant(of);
cannam@154 375 if(next_bitrate>=0)bitrate=next_bitrate;
cannam@154 376 fprintf(stderr,"\r%s... [%li left] (%0.3f kbps) ",
cannam@154 377 bigassbuffer==NULL?"Scanning":"Loading",nsamples-si,bitrate/1000.0);
cannam@154 378 pcm_print_offset=pcm_offset;
cannam@154 379 }
cannam@154 380 }
cannam@154 381 ret=op_read_native(of,smallerbuffer,8,&li);
cannam@154 382 if(ret<0){
cannam@154 383 fprintf(stderr,"Failed to read PCM data: %i\n",ret);
cannam@154 384 nfailures++;
cannam@154 385 }
cannam@154 386 if(ret>0){
cannam@154 387 fprintf(stderr,"Read too much PCM data!\n");
cannam@154 388 nfailures++;
cannam@154 389 }
cannam@154 390 }
cannam@154 391 #endif
cannam@154 392 pcm_length=op_pcm_total(of,-1);
cannam@154 393 size=op_raw_total(of,-1);
cannam@154 394 fprintf(stderr,"\rLoaded (%0.3f kbps average). \n",
cannam@154 395 op_bitrate(of,-1)/1000.0);
cannam@154 396 fprintf(stderr,"Testing raw seeking to random places in %li bytes...\n",
cannam@154 397 (long)size);
cannam@154 398 max_seeks=0;
cannam@154 399 for(i=0;i<NSEEK_TESTS;i++){
cannam@154 400 long nseeks_tmp;
cannam@154 401 opus_int64 byte_offset;
cannam@154 402 nseeks_tmp=nreal_seeks;
cannam@154 403 byte_offset=(opus_int64)(rand()/(double)RAND_MAX*size);
cannam@154 404 fprintf(stderr,"\r\t%3i [raw position %li]... ",
cannam@154 405 i,(long)byte_offset);
cannam@154 406 ret=op_raw_seek(of,byte_offset);
cannam@154 407 if(ret<0){
cannam@154 408 fprintf(stderr,"\nSeek failed: %i.\n",ret);
cannam@154 409 nfailures++;
cannam@154 410 }
cannam@154 411 if(i==28){
cannam@154 412 i=28;
cannam@154 413 }
cannam@154 414 verify_seek(of,byte_offset,-1,pcm_length,bigassbuffer);
cannam@154 415 nseeks_tmp=nreal_seeks-nseeks_tmp;
cannam@154 416 max_seeks=nseeks_tmp>max_seeks?nseeks_tmp:max_seeks;
cannam@154 417 }
cannam@154 418 fprintf(stderr,"\rTotal seek operations: %li (%.3f per raw seek, %li maximum).\n",
cannam@154 419 nreal_seeks,nreal_seeks/(double)NSEEK_TESTS,max_seeks);
cannam@154 420 nreal_seeks=0;
cannam@154 421 fprintf(stderr,"Testing exact PCM seeking to random places in %li "
cannam@154 422 "samples (",(long)pcm_length);
cannam@154 423 print_duration(stderr,pcm_length);
cannam@154 424 fprintf(stderr,")...\n");
cannam@154 425 max_seeks=0;
cannam@154 426 for(i=0;i<NSEEK_TESTS;i++){
cannam@154 427 ogg_int64_t pcm_offset2;
cannam@154 428 long nseeks_tmp;
cannam@154 429 nseeks_tmp=nreal_seeks;
cannam@154 430 pcm_offset=(ogg_int64_t)(rand()/(double)RAND_MAX*pcm_length);
cannam@154 431 fprintf(stderr,"\r\t%3i [PCM position %li]... ",
cannam@154 432 i,(long)pcm_offset);
cannam@154 433 ret=op_pcm_seek(of,pcm_offset);
cannam@154 434 if(ret<0){
cannam@154 435 fprintf(stderr,"\nSeek failed: %i.\n",ret);
cannam@154 436 nfailures++;
cannam@154 437 }
cannam@154 438 pcm_offset2=op_pcm_tell(of);
cannam@154 439 if(pcm_offset!=pcm_offset2){
cannam@154 440 fprintf(stderr,"\nDeclared PCM position did not perfectly match "
cannam@154 441 "request: requested %li, got %li.\n",
cannam@154 442 (long)pcm_offset,(long)pcm_offset2);
cannam@154 443 nfailures++;
cannam@154 444 }
cannam@154 445 verify_seek(of,-1,pcm_offset,pcm_length,bigassbuffer);
cannam@154 446 nseeks_tmp=nreal_seeks-nseeks_tmp;
cannam@154 447 max_seeks=nseeks_tmp>max_seeks?nseeks_tmp:max_seeks;
cannam@154 448 }
cannam@154 449 fprintf(stderr,"\rTotal seek operations: %li (%.3f per exact seek, %li maximum).\n",
cannam@154 450 nreal_seeks,nreal_seeks/(double)NSEEK_TESTS,max_seeks);
cannam@154 451 nreal_seeks=0;
cannam@154 452 fprintf(stderr,"OK.\n");
cannam@154 453 _ogg_free(bigassbuffer);
cannam@154 454 }
cannam@154 455 else{
cannam@154 456 fprintf(stderr,"Input was not seekable.\n");
cannam@154 457 exit(EXIT_FAILURE);
cannam@154 458 }
cannam@154 459 op_free(of);
cannam@154 460 if(nfailures>0){
cannam@154 461 fprintf(stderr,"FAILED: %li failure conditions encountered.\n",nfailures);
cannam@154 462 }
cannam@154 463 return nfailures!=0?EXIT_FAILURE:EXIT_SUCCESS;
cannam@154 464 }