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 }
|