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