shithub: opus

Download patch

ref: c5117c5ccd5da2680b29dbdae5d648d750107003
parent: 1f53f1e0a9b1e055222b28a70b2e327787e50d09
author: Jean-Marc Valin <jmvalin@jmvalin.ca>
date: Mon Feb 5 12:39:38 EST 2024

Add dred_end return value to opus_dred_parse()

--- a/include/opus.h
+++ b/include/opus.h
@@ -581,10 +581,11 @@
   * @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
   * @param [in] max_dred_samples <tt>opus_int32</tt>: Maximum number of DRED samples that may be needed (if available in the packet).
   * @param [in] sampling_rate <tt>opus_int32</tt>: Sampling rate used for max_dred_samples argument. Needs not match the actual sampling rate of the decoder.
+  * @param [out] dred_end <tt>opus_int32*</tt>: Number of non-encoded (silence) samples between the DRED timestamp and the last DRED sample.
   * @param [in] defer_processing <tt>int</tt>: Flag (0 or 1). If set to one, the CPU-intensive part of the DRED decoding is deferred until opus_dred_process() is called.
-  * @returns Number of decoded DRED samples or @ref opus_errorcodes
+  * @returns Offset (positive) of the first decoded DRED samples or @ref opus_errorcodes
   */
-OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int defer_processing) OPUS_ARG_NONNULL(1);
+OPUS_EXPORT int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing) OPUS_ARG_NONNULL(1);
 
 /** Finish decoding an Opus DRED packet. The function only needs to be called if opus_dred_parse() was called with defer_processing=1.
   * The source and destination will often be the same DRED state.
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -1396,7 +1396,7 @@
 #endif
 }
 
-int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int defer_processing)
+int opus_dred_parse(OpusDREDDecoder *dred_dec, OpusDRED *dred, const unsigned char *data, opus_int32 len, opus_int32 max_dred_samples, opus_int32 sampling_rate, int *dred_end, int defer_processing)
 {
 #ifdef ENABLE_DRED
    const unsigned char *payload;
@@ -1417,6 +1417,7 @@
       dred_ec_decode(dred, payload, payload_len, min_feature_frames, dred_frame_offset);
       if (!defer_processing)
          opus_dred_process(dred_dec, dred, dred);
+      if (dred_end) *dred_end = IMAX(0, -dred->dred_offset*sampling_rate/400);
       return IMAX(0, dred->nb_latents*sampling_rate/25 - dred->dred_offset* sampling_rate/400);
    }
    return 0;
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -945,6 +945,7 @@
             int fr;
             int run_decoder;
             int dred_input=0;
+            int dred_end=0;
             if (packet_loss_file != NULL) {
                 if ( fscanf(packet_loss_file, "%d", &lost) != 1) {
                     lost = 0;
@@ -971,7 +972,7 @@
                 opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
                 dred_input = lost_count*output_samples;
                 /* Only decode the amount we need to fill in the gap. */
-                ret = opus_dred_parse(dred_dec, dred, data, len, IMIN(48000, IMAX(0, dred_input)), sampling_rate, 0);
+                ret = opus_dred_parse(dred_dec, dred, data, len, IMIN(48000, IMAX(0, dred_input)), sampling_rate, &dred_end, 0);
                 dred_input = ret > 0 ? ret : 0;
             }
             /* FIXME: Figure out how to trigger the decoder when the last packet of the file is lost. */
--- a/tests/test_opus_dred.c
+++ b/tests/test_opus_dred.c
@@ -67,14 +67,16 @@
       int len;
       int j;
       int res1, res2;
+      int dred_end;
       len = fast_rand()%(MAX_EXTENSION_SIZE+1);
       for (j=0;j<len;j++)
          payload[j] = fast_rand()&0xFF;
-      res1 = opus_dred_parse(dred_dec, dred, payload, len, 48000, 48000, fast_rand()&0x1);
+      res1 = opus_dred_parse(dred_dec, dred, payload, len, 48000, 48000, &dred_end, fast_rand()&0x1);
       if (res1 > 0)
       {
          res2 = opus_dred_process(dred_dec, dred, dred);
          expect_true(res2 == OPUS_OK, "process should succeed if parse succeeds");
+         expect_true(res1 >= dred_end, "end before beginning");
       }
    }
    opus_dred_free(dred);
--