83fb7f4880d0601bccb876127bfcb95c37dff6c7
[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       fprintf(stderr,"testing pcm exact seeking to random places in %f seconds....\n",
193              timelength);
194       for(i=0;i<1000;i++){
195         ogg_int64_t val= i==0?(ogg_int64_t)0:(double)rand()/RAND_MAX*pcmlength;
196         fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
197         ret=ov_pcm_seek(&ov,val);
198         if(ret<0){
199           fprintf(stderr,"seek failed: %d\n",ret);
200           exit(1);
201         }
202         if(ov_pcm_tell(&ov)!=((val>>hs)<<hs)){
203           fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
204                  (long)val,(long)ov_pcm_tell(&ov));
205           exit(1);
206         }
207
208         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
209
210       }
211     }
212
213     fprintf(stderr,"\r");
214     {
215       fprintf(stderr,"testing time page seeking to random places in %f seconds....\n",
216              timelength);
217     
218       for(i=0;i<1000;i++){
219         double val=(double)rand()/RAND_MAX*timelength;
220         fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
221         ret=ov_time_seek_page(&ov,val);
222         if(ret<0){
223           fprintf(stderr,"seek failed: %d\n",ret);
224           exit(1);
225         }
226
227         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
228
229       }
230     }
231
232     fprintf(stderr,"\r");
233     {
234       fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n",
235              timelength);
236     
237       for(i=0;i<1000;i++){
238         double val=(double)rand()/RAND_MAX*timelength;
239         fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
240         ret=ov_time_seek(&ov,val);
241         if(ret<0){
242           fprintf(stderr,"seek failed: %d\n",ret);
243           exit(1);
244         }
245         if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
246           fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n",
247                  val,ov_time_tell(&ov));
248           exit(1);
249         }
250
251         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
252
253       }
254     }
255     
256     fprintf(stderr,"\r                                           \nOK.\n\n");
257
258
259   }else{
260     fprintf(stderr,"Standard input was not seekable.\n");
261   }
262
263   ov_clear(&ov);
264   return 0;
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278