annotate src/opusfile-0.9/examples/seeking_example.c @ 83:ae30d91d2ffe

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