Add status output to opusfile_example.
authorTimothy B. Terriberry <tterribe@xiph.org>
Mon, 1 Oct 2012 06:30:37 +0000 (23:30 -0700)
committerTimothy B. Terriberry <tterribe@xiph.org>
Mon, 1 Oct 2012 06:30:37 +0000 (23:30 -0700)
This displays the current raw position, PCM position, and
 instantaneous bitrate once per second of output.
This is useful when testing against long-running streams.

examples/opusfile_example.c
examples/seeking_example.c

index 5b3f864..baac5bc 100644 (file)
@@ -32,10 +32,77 @@ typedef float op_sample;
 # define op_read_native_stereo op_read_float_stereo
 #endif
 
+static void print_duration(FILE *_fp,ogg_int64_t _nsamples,int _frac){
+  ogg_int64_t seconds;
+  ogg_int64_t minutes;
+  ogg_int64_t hours;
+  ogg_int64_t days;
+  ogg_int64_t weeks;
+  _nsamples+=_frac?24:24000;
+  seconds=_nsamples/48000;
+  _nsamples-=seconds*48000;
+  minutes=seconds/60;
+  seconds-=minutes*60;
+  hours=minutes/60;
+  minutes-=hours*60;
+  days=hours/24;
+  hours-=days*24;
+  weeks=days/7;
+  days-=weeks*7;
+  if(weeks)fprintf(_fp,"%liw",(long)weeks);
+  if(weeks||days)fprintf(_fp,"%id",(int)days);
+  if(weeks||days||hours){
+    if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
+    else fprintf(_fp,"%ih",(int)hours);
+  }
+  if(weeks||days||hours||minutes){
+    if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
+    else fprintf(_fp,"%im",(int)minutes);
+    fprintf(_fp,"%02i",(int)seconds);
+  }
+  else fprintf(_fp,"%i",(int)seconds);
+  if(_frac)fprintf(_fp,".%03i",(int)(_nsamples/48));
+  fprintf(_fp,"s");
+}
+
+static void print_size(FILE *_fp,opus_int64 _nbytes,int _metric,
+ const char *_spacer){
+  static const char SUFFIXES[7]={' ','k','M','G','T','P','E'};
+  opus_int64 val;
+  opus_int64 den;
+  opus_int64 round;
+  int        base;
+  int        shift;
+  base=_metric?1000:1024;
+  round=0;
+  den=1;
+  for(shift=0;shift<6;shift++){
+    if(_nbytes<den*base-round)break;
+    den*=base;
+    round=den>>1;
+  }
+  val=(_nbytes+round)/den;
+  if(den>1&&val<10){
+    if(den>=1000000000)val=(_nbytes+(round/100))/(den/100);
+    else val=(_nbytes*100+round)/den;
+    fprintf(_fp,"%li.%02i%s%c",(long)(val/100),(int)(val%100),
+     _spacer,SUFFIXES[shift]);
+  }
+  else if(den>1&&val<100){
+    if(den>=1000000000)val=(_nbytes+(round/10))/(den/10);
+    else val=(_nbytes*10+round)/den;
+    fprintf(_fp,"%li.%i%s%c",(long)(val/10),(int)(val%10),
+     _spacer,SUFFIXES[shift]);
+  }
+  else fprintf(_fp,"%li%s%c",(long)val,_spacer,SUFFIXES[shift]);
+}
+
 int main(int _argc,const char **_argv){
   OggOpusFile *of;
   ogg_int64_t  pcm_offset;
+  ogg_int64_t  pcm_print_offset;
   ogg_int64_t  nsamples;
+  opus_int32   bitrate;
   int          ret;
   int          prev_li;
 #if defined(_WIN32)
@@ -80,10 +147,16 @@ int main(int _argc,const char **_argv){
   }
   if(op_seekable(of)){
     ogg_int64_t duration;
+    opus_int64  size;
     fprintf(stderr,"Total number of links: %i\n",op_link_count(of));
     duration=op_pcm_total(of,-1);
-    fprintf(stderr,"Total duration: %f seconds (%li samples @ 48 kHz).\n",
-     duration/48000.0,(long)duration);
+    fprintf(stderr,"Total duration: ");
+    print_duration(stderr,duration,3);
+    fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
+    size=op_raw_total(of,-1);
+    fprintf(stderr,"Total size: ");
+    print_size(stderr,size,0,"");
+    fprintf(stderr,"\n");
   }
   prev_li=-1;
   nsamples=0;
@@ -91,13 +164,15 @@ int main(int _argc,const char **_argv){
   if(pcm_offset!=0){
     fprintf(stderr,"Non-zero starting PCM offset: %li\n",(long)pcm_offset);
   }
+  pcm_print_offset=pcm_offset-48000;
+  bitrate=0;
   for(;;){
     ogg_int64_t next_pcm_offset;
     op_sample   pcm[120*48*2];
     int         li;
     ret=op_read_native_stereo(of,pcm,sizeof(pcm)/sizeof(*pcm));
     if(ret<0){
-      fprintf(stderr,"Error decoding '%s': %i\n",_argv[1],ret);
+      fprintf(stderr,"\nError decoding '%s': %i\n",_argv[1],ret);
       ret=EXIT_FAILURE;
       break;
     }
@@ -108,14 +183,20 @@ int main(int _argc,const char **_argv){
       int             ci;
       /*We found a new link.
         Print out some information.*/
-      fprintf(stderr,"Decoding link %i:\n",li);
+      fprintf(stderr,"Decoding link %i:                          \n",li);
       head=op_head(of,li);
       fprintf(stderr,"  Channels: %i\n",head->channel_count);
       if(op_seekable(of)){
         ogg_int64_t duration;
+        opus_int64  size;
         duration=op_pcm_total(of,li);
-        fprintf(stderr,"  Duration: %f seconds (%li samples @ 48 kHz).\n",
-         duration/48000.0,(long)duration);
+        fprintf(stderr,"  Duration: ");
+        print_duration(stderr,duration,3);
+        fprintf(stderr," (%li samples @ 48 kHz)\n",(long)duration);
+        size=op_raw_total(of,li);
+        fprintf(stderr,"  Size: ");
+        print_size(stderr,size,0,"");
+        fprintf(stderr,"\n");
       }
       if(head->input_sample_rate){
         fprintf(stderr,"  Original sampling rate: %lu Hz\n",
@@ -135,9 +216,24 @@ int main(int _argc,const char **_argv){
         }
       }
     }
+    if(li!=prev_li||pcm_offset>=pcm_print_offset+48000){
+      opus_int32 next_bitrate;
+      opus_int64 raw_offset;
+      next_bitrate=op_bitrate_instant(of);
+      if(next_bitrate>=0)bitrate=next_bitrate;
+      raw_offset=op_raw_tell(of);
+      fprintf(stderr,"\r ");
+      print_size(stderr,raw_offset,0,"");
+      fprintf(stderr,"  ");
+      print_duration(stderr,pcm_offset,0);
+      fprintf(stderr,"  (");
+      print_size(stderr,bitrate,1," ");
+      fprintf(stderr,"bps)                    \r");
+      pcm_print_offset=pcm_offset;
+    }
     next_pcm_offset=op_pcm_tell(of);
     if(pcm_offset+ret!=next_pcm_offset){
-      fprintf(stderr,"PCM offset gap! %li+%i!=%li\n",
+      fprintf(stderr,"\nPCM offset gap! %li+%i!=%li\n",
        (long)pcm_offset,ret,(long)next_pcm_offset);
     }
     pcm_offset=next_pcm_offset;
@@ -146,7 +242,8 @@ int main(int _argc,const char **_argv){
       break;
     }
     if(!fwrite(pcm,sizeof(*pcm)*2,ret,stdout)){
-      fprintf(stderr,"Error writing decoded audio data: %s\n",strerror(errno));
+      fprintf(stderr,"\nError writing decoded audio data: %s\n",
+       strerror(errno));
       ret=EXIT_FAILURE;
       break;
     }
@@ -155,7 +252,9 @@ int main(int _argc,const char **_argv){
   }
   op_free(of);
   if(ret==EXIT_SUCCESS){
-    fprintf(stderr,"Done (played %li samples).\n",(long)nsamples);
+    fprintf(stderr,"\nDone: played ");
+    print_duration(stderr,nsamples,3);
+    fprintf(stderr," (%li samples @ 48 kHz).\n",(long)nsamples);
   }
   return ret;
 }
index aeee06b..7b30d8e 100644 (file)
@@ -238,9 +238,17 @@ static void print_duration(FILE *_fp,ogg_int64_t _nsamples){
   days-=weeks*7;
   if(weeks)fprintf(_fp,"%liw",(long)weeks);
   if(weeks||days)fprintf(_fp,"%id",(int)days);
-  if(weeks||days||hours)fprintf(_fp,"%ih",(int)hours);
-  if(weeks||days||hours||minutes)fprintf(_fp,"%im",(int)minutes);
-  fprintf(_fp,"%i.%03is",(int)seconds,(int)(_nsamples+24)/48);
+  if(weeks||days||hours){
+    if(weeks||days)fprintf(_fp,"%02ih",(int)hours);
+    else fprintf(_fp,"%ih",(int)hours);
+  }
+  if(weeks||days||hours||minutes){
+    if(weeks||days||hours)fprintf(_fp,"%02im",(int)minutes);
+    else fprintf(_fp,"%im",(int)minutes);
+    fprintf(_fp,"%02i",(int)seconds);
+  }
+  else fprintf(_fp,"%i",(int)seconds);
+  fprintf(_fp,".%03is",(int)(_nsamples+24)/48);
 }
 
 int main(int _argc,const char **_argv){