shithub: opus

Download patch

ref: 885d7038d6eb16a938a5f731d8c8397980c8611e
parent: d1b48b716a881970d3b17d6bb58a85cd3983b245
author: Jean-Marc Valin <jmvalin@amazon.com>
date: Thu Dec 8 10:15:11 EST 2022

Make FEC handling in opus_demo more general

Now only running the decoder on "received" packets

--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -216,10 +216,10 @@
     OpusEncoder *enc=NULL;
     OpusDecoder *dec=NULL;
     int args;
-    int len[2];
+    int len;
     int frame_size, channels;
     opus_int32 bitrate_bps=0;
-    unsigned char *data[2] = {NULL, NULL};
+    unsigned char *data = NULL;
     unsigned char *fbytes=NULL;
     opus_int32 sampling_rate;
     int use_vbr;
@@ -243,8 +243,7 @@
     int bandwidth=OPUS_AUTO;
     const char *bandwidth_string;
     int lost = 0, lost_prev = 1;
-    int toggle = 0;
-    opus_uint32 enc_final_range[2];
+    opus_uint32 enc_final_range;
     opus_uint32 dec_final_range;
     int encode_only=0, decode_only=0;
     int max_frame_size = 48000*2;
@@ -264,6 +263,7 @@
     int variable_duration=OPUS_FRAMESIZE_ARG;
     int delayed_decision=0;
     int ret = EXIT_FAILURE;
+    int lost_count=0;
 
     if (argc < 5 )
     {
@@ -587,10 +587,7 @@
     out = (short*)malloc(max_frame_size*channels*sizeof(short));
     /* We need to allocate for 16-bit PCM data, but we store it as unsigned char. */
     fbytes = (unsigned char*)malloc(max_frame_size*channels*sizeof(short));
-    data[0] = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
-    if ( use_inbandfec ) {
-        data[1] = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
-    }
+    data = (unsigned char*)calloc(max_payload_bytes,sizeof(unsigned char));
     if(delayed_decision)
     {
        if (frame_size==sampling_rate/400)
@@ -652,22 +649,22 @@
             num_read = fread(ch, 1, 4, fin);
             if (num_read!=4)
                 break;
-            len[toggle] = char_to_int(ch);
-            if (len[toggle]>max_payload_bytes || len[toggle]<0)
+            len = char_to_int(ch);
+            if (len>max_payload_bytes || len<0)
             {
-                fprintf(stderr, "Invalid payload length: %d\n",len[toggle]);
+                fprintf(stderr, "Invalid payload length: %d\n",len);
                 break;
             }
             num_read = fread(ch, 1, 4, fin);
             if (num_read!=4)
                 break;
-            enc_final_range[toggle] = char_to_int(ch);
-            num_read = fread(data[toggle], 1, len[toggle], fin);
-            if (num_read!=(size_t)len[toggle])
+            enc_final_range = char_to_int(ch);
+            num_read = fread(data, 1, len, fin);
+            if (num_read!=(size_t)len)
             {
                 fprintf(stderr, "Ran out of input, "
                                 "expecting %d bytes got %d\n",
-                                len[toggle],(int)num_read);
+                                len,(int)num_read);
                 break;
             }
         } else {
@@ -696,8 +693,8 @@
                 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]);
+            len = opus_encode(enc, in, frame_size, data, max_payload_bytes);
+            nb_encoded = opus_packet_get_samples_per_frame(data, sampling_rate)*opus_packet_get_nb_frames(data, len);
             remaining = frame_size-nb_encoded;
             for(i=0;i<remaining*channels;i++)
                in[i] = in[nb_encoded*channels+i];
@@ -716,10 +713,10 @@
                   bitrate_bps = 1000;
                opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate_bps));
             }
-            opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range[toggle]));
-            if (len[toggle] < 0)
+            opus_encoder_ctl(enc, OPUS_GET_FINAL_RANGE(&enc_final_range));
+            if (len < 0)
             {
-                fprintf (stderr, "opus_encode() returned %d\n", len[toggle]);
+                fprintf (stderr, "opus_encode() returned %d\n", len);
                 goto failure;
             }
             curr_mode_count += frame_size;
@@ -731,56 +728,60 @@
         }
 
 #if 0 /* This is for testing the padding code, do not enable by default */
-        if (len[toggle]<1275)
+        if (len<1275)
         {
-           int new_len = len[toggle]+rand()%(max_payload_bytes-len[toggle]);
-           if ((err = opus_packet_pad(data[toggle], len[toggle], new_len)) != OPUS_OK)
+           int new_len = len+rand()%(max_payload_bytes-len);
+           if ((err = opus_packet_pad(data, len, new_len)) != OPUS_OK)
            {
               fprintf(stderr, "padding failed: %s\n", opus_strerror(err));
               goto failure;
            }
-           len[toggle] = new_len;
+           len = new_len;
         }
 #endif
         if (encode_only)
         {
             unsigned char int_field[4];
-            int_to_char(len[toggle], int_field);
+            int_to_char(len, int_field);
             if (fwrite(int_field, 1, 4, fout) != 4) {
                fprintf(stderr, "Error writing.\n");
                goto failure;
             }
-            int_to_char(enc_final_range[toggle], int_field);
+            int_to_char(enc_final_range, int_field);
             if (fwrite(int_field, 1, 4, fout) != 4) {
                fprintf(stderr, "Error writing.\n");
                goto failure;
             }
-            if (fwrite(data[toggle], 1, len[toggle], fout) != (unsigned)len[toggle]) {
+            if (fwrite(data, 1, len, fout) != (unsigned)len) {
                fprintf(stderr, "Error writing.\n");
                goto failure;
             }
             tot_samples += nb_encoded;
         } else {
-            opus_int32 output_samples;
-            lost = len[toggle]==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
+            int fr;
+            int run_decoder;
+            lost = len==0 || (packet_loss_perc>0 && rand()%100 < packet_loss_perc);
             if (lost)
-               opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
-            else
-               output_samples = max_frame_size;
-            if( count >= use_inbandfec ) {
-                /* delay by one packet when using in-band FEC */
-                if( use_inbandfec  ) {
-                    if( lost_prev ) {
-                        /* attempt to decode with in-band FEC from next packet */
-                        opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
-                        output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 1);
-                    } else {
-                        /* regular decode */
-                        output_samples = max_frame_size;
-                        output_samples = opus_decode(dec, data[1-toggle], len[1-toggle], out, output_samples, 0);
-                    }
+            {
+               lost_count++;
+               run_decoder = 0;
+            } else {
+               run_decoder= 1;
+            }
+            if (run_decoder)
+                run_decoder += lost_count;
+            /* FIXME: Figure out how to trigger the decoder when the last packet of the file is lost. */
+            for (fr=0;fr<run_decoder;fr++) {
+                opus_int32 output_samples=0;
+                if (fr < lost_count-1) {
+                   opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
+                   output_samples = opus_decode(dec, NULL, 0, out, output_samples, 1);
+                } else if (fr == lost_count-1) {
+                   opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
+                   output_samples = opus_decode(dec, data, len, out, output_samples, 1);
                 } else {
-                    output_samples = opus_decode(dec, lost ? NULL : data[toggle], len[toggle], out, output_samples, 0);
+                   output_samples = max_frame_size;
+                   output_samples = opus_decode(dec, data, len, out, output_samples, 0);
                 }
                 if (output_samples>0)
                 {
@@ -817,24 +818,26 @@
         if (!encode_only)
            opus_decoder_ctl(dec, OPUS_GET_FINAL_RANGE(&dec_final_range));
         /* compare final range encoder rng values of encoder and decoder */
-        if( enc_final_range[toggle^use_inbandfec]!=0  && !encode_only
+        if( enc_final_range!=0  && !encode_only
          && !lost && !lost_prev
-         && dec_final_range != enc_final_range[toggle^use_inbandfec] ) {
+         && dec_final_range != enc_final_range ) {
             fprintf (stderr, "Error: Range coder state mismatch "
                              "between encoder and decoder "
                              "in frame %ld: 0x%8lx vs 0x%8lx\n",
                          (long)count,
-                         (unsigned long)enc_final_range[toggle^use_inbandfec],
+                         (unsigned long)enc_final_range,
                          (unsigned long)dec_final_range);
             goto failure;
         }
 
         lost_prev = lost;
+        if (!lost)
+           lost_count = 0;
         if( count >= use_inbandfec ) {
             /* count bits */
-            bits += len[toggle]*8;
-            bits_max = ( len[toggle]*8 > bits_max ) ? len[toggle]*8 : bits_max;
-            bits2 += len[toggle]*len[toggle]*64;
+            bits += len*8;
+            bits_max = ( len*8 > bits_max ) ? len*8 : bits_max;
+            bits2 += len*len*64;
             if (!decode_only)
             {
                 nrg = 0.0;
@@ -843,13 +846,12 @@
                 }
                 nrg /= frame_size * channels;
                 if( nrg > 1e5 ) {
-                    bits_act += len[toggle]*8;
+                    bits_act += len*8;
                     count_act++;
                 }
             }
         }
         count++;
-        toggle = (toggle + use_inbandfec) & 1;
     }
 
     if(decode_only && count > 0)
@@ -879,8 +881,7 @@
 failure:
     opus_encoder_destroy(enc);
     opus_decoder_destroy(dec);
-    free(data[0]);
-    free(data[1]);
+    free(data);
     if (fin)
         fclose(fin);
     if (fout)
--