shithub: opus

Download patch

ref: 360fd07115618a0104e314f4f93575c1b1f46717
parent: 6f9cb7aac39a2d1b363355cdc58445bdad2618c7
author: Jean-Marc Valin <jeanmarcv@google.com>
date: Wed Jan 22 10:29:04 EST 2025

Test corrupted bitstreams in test_opus_custom

--- a/tests/test_opus_custom.c
+++ b/tests/test_opus_custom.c
@@ -2,6 +2,11 @@
 #include "config.h"
 #endif
 
+/* FIXME: Is there a better way to get access to opus_custom_decoder_get_size()? */
+#ifdef OPUS_BUILD
+#undef OPUS_BUILD
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <limits.h>
@@ -30,6 +35,7 @@
 typedef struct {
    void* encoder;
    void* decoder;
+   OpusCustomMode *mode;
    int sample_rate;
    int num_channels;
    int frame_size;
@@ -109,9 +115,12 @@
    void *outbuf;
    OpusEncoder* enc = NULL;
    OpusDecoder* dec = NULL;
+   OpusDecoder* dec_copy = NULL;
    OpusCustomEncoder* encC = NULL;
    OpusCustomDecoder* decC = NULL;
+   OpusCustomDecoder* decC_copy = NULL;
    unsigned char packet[MAX_PACKET+257];
+   unsigned char packet_corrupt[MAX_PACKET+257];
    int len;
    int input_samples;
    int samples_decoded;
@@ -149,10 +158,16 @@
    }
 
    if (params.custom_decode) {
+      int size = opus_custom_decoder_get_size(params.mode, params.num_channels);
       decC = (OpusCustomDecoder*)params.decoder;
+      decC_copy = malloc(size);
+      memcpy(decC_copy, decC, size);
    }
    else {
+      int size = opus_decoder_get_size(params.num_channels);
       dec = (OpusDecoder*)params.decoder;
+      dec_copy = malloc(size);
+      memcpy(dec_copy, dec, size);
    }
 
    /* Encode data, then decode for sanity check */
@@ -214,6 +229,52 @@
          }
       }
 
+      /* Generate bit/byte errors and check that nothing bad happens. */
+      {
+         int error_pos;
+         int len2;
+         /* Draw the inverse bit error rate from an exponential distribution. */
+         int ber_1 = 1 - 100*log(1e-10 + fast_rand()/4294967296.);
+         opus_int16 scratch[1920*6];
+         memcpy(packet_corrupt, packet, sizeof(packet));
+         /* Randomly flip the 5 first bytes. */
+         for (error_pos=0;error_pos<5;error_pos++) {
+            /* 25% chance of flipping each byte. */
+            if (error_pos<len && fast_rand()%5 == 0) packet_corrupt[error_pos] = fast_rand()&0xFF;
+         }
+         /* Arbitrarily truncate the packet. */
+         len2 = (int)(1-len*log(1e-10 + fast_rand()/4294967296.));
+         len2 = IMIN(len, len2);
+         error_pos=0;
+         /* Generate bit errors using "run-length" flipping. */
+         while (1) {
+            error_pos += (int)-ber_1*log(1e-10 + fast_rand()/4294967296.);
+            if (error_pos >= len2*8) break;
+            packet_corrupt[error_pos/8] ^= (1<<(error_pos&7));
+         }
+         if (params.custom_decode) {
+            int error = opus_custom_decode(decC_copy,
+                  packet_corrupt,
+                  len2,
+                  scratch,
+                  frame_size);
+            if (!(error > 0 || error == OPUS_BAD_ARG || error == OPUS_INVALID_PACKET || error == OPUS_BUFFER_TOO_SMALL)) {
+               fprintf(stderr, "opus_custom_decode() with corrupt stream failed with: %s\n", opus_strerror(error));
+               test_failed();
+            }
+         } else {
+            int error = opus_decode(dec_copy,
+                  packet_corrupt,
+                  len2,
+                  scratch,
+                  frame_size,
+                  0);
+            if (!(error > 0 || error == OPUS_BAD_ARG || error == OPUS_INVALID_PACKET || error == OPUS_BUFFER_TOO_SMALL)) {
+               fprintf(stderr, "opus_custom_decode() with corrupt stream failed with: %s\n", opus_strerror(error));
+               test_failed();
+            }
+         }
+      }
 #ifndef DISABLE_FLOAT_API
       if (params.float_decode) {
          float* output = (float*)outbuf;
@@ -310,6 +371,8 @@
    }
 #endif
 
+   if (dec_copy) free(dec_copy);
+   if (decC_copy) free(decC_copy);
    /* Clean up */
    free(inbuf);
    free(outbuf);
@@ -374,6 +437,9 @@
                     params.custom_encode, params.custom_decode, frame_size_ms_x2);
             test_failed();
          }
+         params.mode = mode;
+      } else {
+         params.mode = NULL;
       }
 
       if (params.custom_decode) {
--