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