1 /********************************************************************
2  *                                                                  *
3  * THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE.   *
4  *                                                                  *
5  * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
6  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
7  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
8  *                                                                  *
9  * THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2009    *
10  * BY THE Xiph.Org FOUNDATION http://www.xiph.org/                  *
11  *                                                                  *
12  ********************************************************************
13 
14  function: illustrate seeking, and test it too
15  last mod: $Id$
16 
17  ********************************************************************/
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include "ivorbiscodec.h"
22 #include "ivorbisfile.h"
23 
24 #ifdef _WIN32 /* We need the following two to set stdin/stdout to binary */
25 # include <io.h>
26 # include <fcntl.h>
27 #endif
28 
_verify(OggVorbis_File * ov,ogg_int64_t val,ogg_int64_t pcmval,ogg_int64_t timeval,ogg_int64_t pcmlength,char * bigassbuffer)29 void _verify(OggVorbis_File *ov,
30              ogg_int64_t val,
31              ogg_int64_t pcmval,
32              ogg_int64_t timeval,
33              ogg_int64_t pcmlength,
34              char *bigassbuffer){
35   int j;
36   long bread;
37   char buffer[4096];
38   int dummy;
39   ogg_int64_t pos;
40 
41   /* verify the raw position, the pcm position and position decode */
42   if(val!=-1 && ov_raw_tell(ov)<val){
43     fprintf(stderr,"raw position out of tolerance: requested %ld, got %ld\n",
44            (long)val,(long)ov_raw_tell(ov));
45     exit(1);
46   }
47   if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){
48     fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n",
49            (long)pcmval,(long)ov_pcm_tell(ov));
50     exit(1);
51   }
52   if(timeval!=-1 && ov_time_tell(ov)>timeval){
53     fprintf(stderr,"time position out of tolerance: requested %ld, got %ld\n",
54             (long)timeval,(long)ov_time_tell(ov));
55     exit(1);
56   }
57   pos=ov_pcm_tell(ov);
58   if(pos<0 || pos>pcmlength){
59     fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos);
60     exit(1);
61   }
62   bread=ov_read(ov,buffer,4096,&dummy);
63   if(bigassbuffer){
64     for(j=0;j<bread;j++){
65       if(buffer[j]!=bigassbuffer[j+pos*4]){
66 	fprintf(stderr,"data position after seek doesn't match pcm position\n");
67 
68 	{
69 	  FILE *f=fopen("a.m","w");
70 	  for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)buffer[j]);
71 	  fclose(f);
72 	  f=fopen("b.m","w");
73 	  for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)bigassbuffer[j+pos*2]);
74 	  fclose(f);
75 	}
76 
77 	exit(1);
78       }
79     }
80   }
81 }
82 
main()83 int main(){
84   OggVorbis_File ov;
85   int i,ret;
86   ogg_int64_t pcmlength;
87   ogg_int64_t timelength;
88   char *bigassbuffer;
89   int dummy;
90 
91 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
92   _setmode( _fileno( stdin ), _O_BINARY );
93 #endif
94 
95 
96   /* open the file/pipe on stdin */
97   if(ov_open(stdin, &ov, NULL, 0) < 0) {
98     fprintf(stderr,"Could not open input as an OggVorbis file.\n\n");
99     exit(1);
100   }
101 
102   if(ov_seekable(&ov)){
103 
104     /* to simplify our own lives, we want to assume the whole file is
105        stereo.  Verify this to avoid potentially mystifying users
106        (pissing them off is OK, just don't confuse them) */
107     for(i=0;i<ov.links;i++){
108       vorbis_info *vi=ov_info(&ov,i);
109       if(vi->channels!=2){
110         fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n"
111                "that are entirely stereo.\n\n");
112         exit(1);
113       }
114     }
115 
116     /* because we want to do sample-level verification that the seek
117        does what it claimed, decode the entire file into memory */
118     pcmlength=ov_pcm_total(&ov,-1);
119     timelength=ov_time_total(&ov,-1);
120     bigassbuffer=malloc(pcmlength*4); /* w00t */
121     if(bigassbuffer){
122       i=0;
123       while(i<pcmlength*4){
124 	int ret=ov_read(&ov,bigassbuffer+i,pcmlength*4-i,&dummy);
125 	if(ret<0)continue;
126 	if(ret){
127 	  i+=ret;
128 	}else{
129 	  pcmlength=i/4;
130 	}
131 	fprintf(stderr,"\rloading.... [%ld left]              ",
132 		(long)(pcmlength*4-i));
133       }
134     }else{
135       fprintf(stderr,"\rfile too large to load into memory for read tests;\n\tonly verifying seek positioning...\n");
136     }
137 
138     {
139       ogg_int64_t length=ov.end;
140       fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n",
141              (long)length);
142 
143       for(i=0;i<1000;i++){
144         ogg_int64_t val=rand()*length/RAND_MAX;
145         fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
146         ret=ov_raw_seek(&ov,val);
147         if(ret<0){
148           fprintf(stderr,"seek failed: %d\n",ret);
149           exit(1);
150         }
151 
152         _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);
153 
154       }
155     }
156 
157     fprintf(stderr,"\r");
158     {
159       fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n",
160              (long)pcmlength);
161 
162       for(i=0;i<1000;i++){
163         ogg_int64_t val=i==0?0:(double)rand()*pcmlength/RAND_MAX;
164         fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
165         ret=ov_pcm_seek_page(&ov,val);
166         if(ret<0){
167           fprintf(stderr,"seek failed: %d\n",ret);
168           exit(1);
169         }
170 
171         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
172 
173       }
174     }
175 
176     fprintf(stderr,"\r");
177     {
178       fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n",
179              (long)pcmlength);
180 
181       for(i=0;i<1000;i++){
182         ogg_int64_t val=i==0?0:(double)rand()*pcmlength/RAND_MAX;
183         fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
184         ret=ov_pcm_seek(&ov,val);
185         if(ret<0){
186           fprintf(stderr,"seek failed: %d\n",ret);
187           exit(1);
188         }
189         if(ov_pcm_tell(&ov)!=val){
190           fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
191                  (long)val,(long)ov_pcm_tell(&ov));
192           exit(1);
193         }
194 
195         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
196 
197       }
198     }
199 
200     fprintf(stderr,"\r");
201     {
202       fprintf(stderr,"testing time page seeking to random places in %ld milliseconds....\n",
203               (long)timelength);
204 
205       for(i=0;i<1000;i++){
206         ogg_int64_t val=(double)rand()*timelength/RAND_MAX;
207         fprintf(stderr,"\r\t%d [time position %ld]...     ",i,(long)val);
208         ret=ov_time_seek_page(&ov,val);
209         if(ret<0){
210           fprintf(stderr,"seek failed: %d\n",ret);
211           exit(1);
212         }
213 
214         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
215 
216       }
217     }
218 
219     fprintf(stderr,"\r");
220     {
221       fprintf(stderr,"testing time exact seeking to random places in %ld milliseconds....\n",
222               (long)timelength);
223 
224       for(i=0;i<1000;i++){
225         ogg_int64_t val=(double)rand()*timelength/RAND_MAX;
226         fprintf(stderr,"\r\t%d [time position %ld]...     ",i,(long)val);
227         ret=ov_time_seek(&ov,val);
228         if(ret<0){
229           fprintf(stderr,"seek failed: %d\n",ret);
230           exit(1);
231         }
232         if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
233           fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
234                   (long)val,(long)ov_time_tell(&ov));
235           exit(1);
236         }
237 
238         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
239 
240       }
241     }
242 
243     fprintf(stderr,"\r                                           \nOK.\n\n");
244 
245 
246   }else{
247     fprintf(stderr,"Standard input was not seekable.\n");
248   }
249 
250   ov_clear(&ov);
251   return 0;
252 }
253 
254 
255 
256 
257 
258 
259 
260 
261 
262 
263 
264 
265 
266