Home | History | Annotate | Download | only in examples
      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 
     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){
    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