Makes opus_demo rubust to the encoder using variable frame duration
authorJean-Marc Valin <jmvalin@jmvalin.ca>
Tue, 20 Nov 2012 04:21:43 +0000 (23:21 -0500)
committerJean-Marc Valin <jmvalin@jmvalin.ca>
Sun, 10 Feb 2013 05:15:49 +0000 (00:15 -0500)
Also, the encode+decode mode now produces an output of the same size
as the original.

src/opus_demo.c

index 09b12a3..ae6ccf3 100644 (file)
@@ -221,6 +221,8 @@ int main(int argc, char *argv[])
     short *in, *out;
     int application=OPUS_APPLICATION_AUDIO;
     double bits=0.0, bits_max=0.0, bits_act=0.0, bits2=0.0, nrg;
+    double tot_samples=0;
+    opus_uint64 tot_in, tot_out;
     int bandwidth=-1;
     const char *bandwidth_string;
     int lost = 0, lost_prev = 1;
@@ -239,6 +241,8 @@ int main(int argc, char *argv[])
     int curr_mode=0;
     int curr_mode_count=0;
     int mode_switch_time = 48000;
+    int nb_encoded;
+    int remaining=0;
 
     if (argc < 5 )
     {
@@ -246,6 +250,7 @@ int main(int argc, char *argv[])
        return EXIT_FAILURE;
     }
 
+    tot_in=tot_out=0;
     fprintf(stderr, "%s\n", opus_get_version_string());
 
     args = 1;
@@ -617,22 +622,28 @@ int main(int argc, char *argv[])
                 opus_encoder_ctl(enc, OPUS_SET_FORCE_CHANNELS(mode_list[curr_mode][3]));
                 frame_size = mode_list[curr_mode][2];
             }
-            err = fread(fbytes, sizeof(short)*channels, frame_size, fin);
+            err = fread(fbytes, sizeof(short)*channels, frame_size-remaining, fin);
             curr_read = err;
+            tot_in += curr_read;
             for(i=0;i<curr_read*channels;i++)
             {
                 opus_int32 s;
                 s=fbytes[2*i+1]<<8|fbytes[2*i];
                 s=((s&0xFFFF)^0x8000)-0x8000;
-                in[i]=s;
+                in[i+remaining*channels]=s;
             }
-            if (curr_read < frame_size)
+            if (curr_read+remaining < frame_size)
             {
-                for (i=curr_read*channels;i<frame_size*channels;i++)
+                for (i=(curr_read+remaining)*channels;i<frame_size*channels;i++)
                    in[i] = 0;
-                stop = 1;
+                if (encode_only || decode_only)
+                   stop = 1;
             }
             len[toggle] = opus_encode(enc, in, frame_size, data[toggle], max_payload_bytes);
+            nb_encoded = opus_packet_get_samples_per_frame(data[toggle], sampling_rate)*opus_packet_get_nb_frames(data[toggle], len[toggle]);
+            remaining = frame_size-nb_encoded;
+            for(i=0;i<remaining*channels;i++)
+               in[i] = in[nb_encoded*channels+i];
             if (sweep_bps!=0)
             {
                bitrate_bps += sweep_bps;
@@ -681,6 +692,7 @@ int main(int argc, char *argv[])
                fprintf(stderr, "Error writing.\n");
                return EXIT_FAILURE;
             }
+            tot_samples += nb_encoded;
         } else {
             int output_samples;
             lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
@@ -703,6 +715,11 @@ int main(int argc, char *argv[])
                 }
                 if (output_samples>0)
                 {
+                    if (!decode_only && tot_out + output_samples > tot_in)
+                    {
+                       stop=1;
+                       output_samples  = tot_in-tot_out;
+                    }
                     if (output_samples>skip) {
                        int i;
                        for(i=0;i<(output_samples-skip)*channels;i++)
@@ -716,6 +733,7 @@ int main(int argc, char *argv[])
                           fprintf(stderr, "Error writing.\n");
                           return EXIT_FAILURE;
                        }
+                       tot_out += output_samples-skip;
                     }
                     if (output_samples<skip) skip -= output_samples;
                     else skip = 0;
@@ -723,6 +741,7 @@ int main(int argc, char *argv[])
                    fprintf(stderr, "error decoding frame: %s\n",
                                    opus_strerror(output_samples));
                 }
+                tot_samples += output_samples;
             }
         }
 
@@ -767,7 +786,7 @@ int main(int argc, char *argv[])
         toggle = (toggle + use_inbandfec) & 1;
     }
     fprintf (stderr, "average bitrate:             %7.3f kb/s\n",
-                     1e-3*bits*sampling_rate/(frame_size*(double)count));
+                     1e-3*bits*sampling_rate/tot_samples);
     fprintf (stderr, "maximum bitrate:             %7.3f kb/s\n",
                      1e-3*bits_max*sampling_rate/frame_size);
     if (!decode_only)