Fix for bug 577; used a different approach than the submitted patch
[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-2002             *
9  * by the XIPHOPHORUS Company 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     printf("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     printf("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     printf("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     printf("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       printf("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   _setmode( _fileno( stdout ), _O_BINARY );
89 #endif
90
91
92   /* open the file/pipe on stdin */
93   if(ov_open(stdin,&ov,NULL,-1)<0){
94     printf("Could not open input as an OggVorbis file.\n\n");
95     exit(1);
96   }
97
98   if(ov_seekable(&ov)){
99
100     /* to simplify our own lives, we want to assume the whole file is
101        stereo.  Verify this to avoid potentially mystifying users
102        (pissing them off is OK, just don't confuse them) */
103     for(i=0;i<ov.links;i++){
104       vorbis_info *vi=ov_info(&ov,i);
105       if(vi->channels!=2){
106         printf("Sorry; right now seeking_test can only use Vorbis files\n"
107                "that are entirely stereo.\n\n");
108         exit(1);
109       }
110     }
111     
112     /* because we want to do sample-level verification that the seek
113        does what it claimed, decode the entire file into memory */
114     fflush(stdout);
115     pcmlength=ov_pcm_total(&ov,-1);
116     timelength=ov_time_total(&ov,-1);
117     bigassbuffer=malloc(pcmlength*2); /* w00t */
118     i=0;
119     while(i<pcmlength*2){
120       int ret=ov_read(&ov,bigassbuffer+i,pcmlength*2-i,1,1,1,&dummy);
121       if(ret<0)continue;
122       if(ret){
123         i+=ret;
124       }else{
125         pcmlength=i/2;
126       }
127       fprintf(stderr,"\rloading.... [%ld left]              ",
128               (long)(pcmlength*2-i));
129     }
130     
131     {
132       ogg_int64_t length=ov.end;
133       printf("\rtesting raw seeking to random places in %ld bytes....\n",
134              (long)length);
135     
136       for(i=0;i<1000;i++){
137         ogg_int64_t val=(double)rand()/RAND_MAX*length;
138         printf("\r\t%d [raw position %ld]...     ",i,(long)val);
139         fflush(stdout);
140         ret=ov_raw_seek(&ov,val);
141         if(ret<0){
142           printf("seek failed: %d\n",ret);
143           exit(1);
144         }
145
146         _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);
147
148       }
149     }
150
151     printf("\r");
152     {
153       printf("testing pcm page seeking to random places in %ld samples....\n",
154              (long)pcmlength);
155     
156       for(i=0;i<1000;i++){
157         ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
158         printf("\r\t%d [pcm position %ld]...     ",i,(long)val);
159         fflush(stdout);
160         ret=ov_pcm_seek_page(&ov,val);
161         if(ret<0){
162           printf("seek failed: %d\n",ret);
163           exit(1);
164         }
165
166         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
167
168       }
169     }
170     
171     printf("\r");
172     {
173       printf("testing pcm exact seeking to random places in %ld samples....\n",
174              (long)pcmlength);
175     
176       for(i=0;i<1000;i++){
177         ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
178         printf("\r\t%d [pcm position %ld]...     ",i,(long)val);
179         fflush(stdout);
180         ret=ov_pcm_seek(&ov,val);
181         if(ret<0){
182           printf("seek failed: %d\n",ret);
183           exit(1);
184         }
185         if(ov_pcm_tell(&ov)!=val){
186           printf("Declared position didn't perfectly match request: %ld != %ld\n",
187                  (long)val,(long)ov_pcm_tell(&ov));
188           exit(1);
189         }
190
191         _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
192
193       }
194     }
195
196     printf("\r");
197     {
198       printf("testing time page seeking to random places in %f seconds....\n",
199              timelength);
200     
201       for(i=0;i<1000;i++){
202         double val=(double)rand()/RAND_MAX*timelength;
203         printf("\r\t%d [time position %f]...     ",i,val);
204         fflush(stdout);
205         ret=ov_time_seek_page(&ov,val);
206         if(ret<0){
207           printf("seek failed: %d\n",ret);
208           exit(1);
209         }
210
211         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
212
213       }
214     }
215
216     printf("\r");
217     {
218       printf("testing time exact seeking to random places in %f seconds....\n",
219              timelength);
220     
221       for(i=0;i<1000;i++){
222         double val=(double)rand()/RAND_MAX*timelength;
223         printf("\r\t%d [time position %f]...     ",i,val);
224         fflush(stdout);
225         ret=ov_time_seek(&ov,val);
226         if(ret<0){
227           printf("seek failed: %d\n",ret);
228           exit(1);
229         }
230         if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
231           printf("Declared position didn't perfectly match request: %f != %f\n",
232                  val,ov_time_tell(&ov));
233           exit(1);
234         }
235
236         _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
237
238       }
239     }
240     
241     printf("\r                                           \nOK.\n\n");
242
243
244   }else{
245     printf("Standard input was not seekable.\n");
246   }
247
248   ov_clear(&ov);
249   return 0;
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263