Update documentation, version numbers, copyright dates
[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   int j;
33   long bread;
34   char buffer[4096];
35   int dummy;
36   ogg_int64_t pos;
37
38   /* verify the raw position, the pcm position and position decode */
39   if(val!=-1 && ov_raw_tell(ov)<val){
40     fprintf(stderr,"raw position out of tolerance: requested %ld, got %ld\n",
41            (long)val,(long)ov_raw_tell(ov));
42     exit(1);
43   }
44   if(pcmval!=-1 && ov_pcm_tell(ov)>pcmval){
45     fprintf(stderr,"pcm position out of tolerance: requested %ld, got %ld\n",
46            (long)pcmval,(long)ov_pcm_tell(ov));
47     exit(1);
48   }
49   if(timeval!=-1 && ov_time_tell(ov)>timeval){
50     fprintf(stderr,"time position out of tolerance: requested %f, got %f\n",
51            timeval,ov_time_tell(ov));
52     exit(1);
53   }
54   pos=ov_pcm_tell(ov);
55   if(pos<0 || pos>pcmlength){
56     fprintf(stderr,"pcm position out of bounds: got %ld\n",(long)pos);
57     exit(1);
58   }
59   bread=ov_read(ov,buffer,4096,1,1,1,&dummy);
60   for(j=0;j<bread;j++){
61     if(buffer[j]!=bigassbuffer[j+pos*2]){
62       fprintf(stderr,"data position after seek doesn't match pcm position\n");
63
64       {
65         FILE *f=fopen("a.m","w");
66         for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)buffer[j]);
67         fclose(f);
68         f=fopen("b.m","w");
69         for(j=0;j<bread;j++)fprintf(f,"%d\n",(int)bigassbuffer[j+pos*2]);
70         fclose(f);
71       }
72
73       exit(1);
74     }
75   }
76 }
77
78 int main(){
79   OggVorbis_File ov;
80   int i,ret;
81   ogg_int64_t pcmlength;
82   double timelength;
83   char *bigassbuffer;
84   int dummy;
85
86 #ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
87   _setmode( _fileno( stdin ), _O_BINARY );
88 #endif
89
90
91   /* open the file/pipe on stdin */
92   if(ov_open_callbacks(stdin,&ov,NULL,-1,OV_CALLBACKS_NOCLOSE)<0){
93     fprintf(stderr,"Could not open input as an OggVorbis file.\n\n");
94     exit(1);
95   }
96
97   if(ov_seekable(&ov)){
98
99     /* to simplify our own lives, we want to assume the whole file is
100        stereo.  Verify this to avoid potentially mystifying users
101        (pissing them off is OK, just don't confuse them) */
102     for(i=0;i<ov.links;i++){
103       vorbis_info *vi=ov_info(&ov,i);
104       if(vi->channels!=2){
105         fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n"
106                "that are entirely stereo.\n\n");
107         exit(1);
108       }
109     }
110     
111     /* because we want to do sample-level verification that the seek
112        does what it claimed, decode the entire file into memory */
113     pcmlength=ov_pcm_total(&ov,-1);
114     timelength=ov_time_total(&ov,-1);
115     bigassbuffer=malloc(pcmlength*2); /* w00t */
116     i=0;
117     while(i<pcmlength*2){
118       int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy);
119       if(ret<0)continue;
120       if(ret){
121         i+=ret;
122       }else{
123         pcmlength=i/2;
124       }
125       fprintf(stderr,"\rloading.... [%ld left]              ",
126               (long)(pcmlength*2-i));
127     }
128     
129     {
130       ogg_int64_t length=ov.end;
131       fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n",
132              (long)length);
133     
134       for(i=0;i<1000;i++){
135         ogg_int64_t val=(double)rand()/RAND_MAX*length;
136         fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
137         ret=ov_raw_seek(&ov,val);
138         if(ret<0){
139           fprintf(stderr,"seek failed: %d\n",ret);
140           exit(1);
141         }
142
143         _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);
144
145       }
146     }
147
148     fprintf(stderr,"\r");
149     {
150       fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n",
151              (long)pcmlength);
152     
153       for(i=0;i<1000;i++){
154         ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
155         fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
156         ret=ov_pcm_seek_page(&ov,val);
157         if(ret<0){
158           fprintf(stderr,"seek failed: %d\n",ret);
159           exit(1);
160         }
161
162         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
163
164       }
165     }
166     
167     fprintf(stderr,"\r");
168     {
169       fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n",
170              (long)pcmlength);
171     
172       for(i=0;i<1000;i++){
173         ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
174         fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
175         ret=ov_pcm_seek(&ov,val);
176         if(ret<0){
177           fprintf(stderr,"seek failed: %d\n",ret);
178           exit(1);
179         }
180         if(ov_pcm_tell(&ov)!=val){
181           fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
182                  (long)val,(long)ov_pcm_tell(&ov));
183           exit(1);
184         }
185
186         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
187
188       }
189     }
190
191     fprintf(stderr,"\r");
192     {
193       fprintf(stderr,"testing time page seeking to random places in %f seconds....\n",
194              timelength);
195     
196       for(i=0;i<1000;i++){
197         double val=(double)rand()/RAND_MAX*timelength;
198         fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
199         ret=ov_time_seek_page(&ov,val);
200         if(ret<0){
201           fprintf(stderr,"seek failed: %d\n",ret);
202           exit(1);
203         }
204
205         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
206
207       }
208     }
209
210     fprintf(stderr,"\r");
211     {
212       fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n",
213              timelength);
214     
215       for(i=0;i<1000;i++){
216         double val=(double)rand()/RAND_MAX*timelength;
217         fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
218         ret=ov_time_seek(&ov,val);
219         if(ret<0){
220           fprintf(stderr,"seek failed: %d\n",ret);
221           exit(1);
222         }
223         if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
224           fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n",
225                  val,ov_time_tell(&ov));
226           exit(1);
227         }
228
229         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
230
231       }
232     }
233     
234     fprintf(stderr,"\r                                           \nOK.\n\n");
235
236
237   }else{
238     fprintf(stderr,"Standard input was not seekable.\n");
239   }
240
241   ov_clear(&ov);
242   return 0;
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256