seeking_example.c revision 8e01cdce135d5d816f92d7bb83f9a930aa1b45ae
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: seeking_example.c 16329 2009-07-24 01:53:20Z xiphmont $
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
28void _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
78int 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){
120        fprintf(stderr,"Error reading file.\n");
121        exit(1);
122      }
123      if(ret){
124        i+=ret;
125      }else{
126        pcmlength=i/2;
127      }
128      fprintf(stderr,"\rloading.... [%ld left]              ",
129              (long)(pcmlength*2-i));
130    }
131
132    {
133      ogg_int64_t length=ov.end;
134      fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n",
135             (long)length);
136
137      for(i=0;i<1000;i++){
138        ogg_int64_t val=(double)rand()/RAND_MAX*length;
139        fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
140        ret=ov_raw_seek(&ov,val);
141        if(ret<0){
142          fprintf(stderr,"seek failed: %d\n",ret);
143          exit(1);
144        }
145
146        _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);
147
148      }
149    }
150
151    fprintf(stderr,"\r");
152    {
153      fprintf(stderr,"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        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
159        ret=ov_pcm_seek_page(&ov,val);
160        if(ret<0){
161          fprintf(stderr,"seek failed: %d\n",ret);
162          exit(1);
163        }
164
165        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
166
167      }
168    }
169
170    fprintf(stderr,"\r");
171    {
172      fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n",
173             (long)pcmlength);
174
175      for(i=0;i<1000;i++){
176        ogg_int64_t val=(double)rand()/RAND_MAX*pcmlength;
177        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
178        ret=ov_pcm_seek(&ov,val);
179        if(ret<0){
180          fprintf(stderr,"seek failed: %d\n",ret);
181          exit(1);
182        }
183        if(ov_pcm_tell(&ov)!=val){
184          fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
185                 (long)val,(long)ov_pcm_tell(&ov));
186          exit(1);
187        }
188
189        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);
190
191      }
192    }
193
194    fprintf(stderr,"\r");
195    {
196      fprintf(stderr,"testing time page seeking to random places in %f seconds....\n",
197             timelength);
198
199      for(i=0;i<1000;i++){
200        double val=(double)rand()/RAND_MAX*timelength;
201        fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
202        ret=ov_time_seek_page(&ov,val);
203        if(ret<0){
204          fprintf(stderr,"seek failed: %d\n",ret);
205          exit(1);
206        }
207
208        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
209
210      }
211    }
212
213    fprintf(stderr,"\r");
214    {
215      fprintf(stderr,"testing time exact 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(&ov,val);
222        if(ret<0){
223          fprintf(stderr,"seek failed: %d\n",ret);
224          exit(1);
225        }
226        if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
227          fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n",
228                 val,ov_time_tell(&ov));
229          exit(1);
230        }
231
232        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);
233
234      }
235    }
236
237    fprintf(stderr,"\r                                           \nOK.\n\n");
238
239
240  }else{
241    fprintf(stderr,"Standard input was not seekable.\n");
242  }
243
244  ov_clear(&ov);
245  return 0;
246}
247
248
249
250
251
252
253
254
255
256
257
258
259
260