[opus] API for checking whether the encoder is in DTX (PR #107)

Gustaf Ullberg
2019-04-01T10:37:19Z

Hi everyone,

Some time ago, I sent a pull request
<https://github.com/xiph/opus/pull/107>
to the Opus github page. Jean-Marc asked me to post it to the mailing list
so everyone can have a look at it.

You can find the description and code changes below. Please let me know if
you have any questions or concerns.

Best regards
Gustaf Ullberg

In WebRTC, we would like to be able to differentiate between "normal"
frames and the comfort noise update frames that are encoded before and
in-between DTX frames. These CNG update frames could then be flagged for
routing or statistics reasons. Such flagging could also make it easier for
a jitterbuffer to differ DTX from packet loss.

This PR implements an encoder CTL named OPUS_GET_IN_DTX. OPUS_GET_IN_DTX
returns 1 if the last encoded frame was either a DTX frame, or a CNG update
frame that is sent every 420 ms between the DTX frames.

This is achieved by checking if the number of consecutive inactive frames
(nb_no_activity_frames) is greater or equal to NB_SPEECH_FRAMES_BEFORE_DTX.


diff --git a/include/opus_defines.h b/include/opus_defines.h
index fbf5d0eb..e35114e4 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -168,6 +168,7 @@ extern "C" {
 /* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
 #define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
 #define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
+#define OPUS_GET_IN_DTX_REQUEST              4049

 /** Defines for the presence of extended APIs. */
 #define OPUS_HAVE_OPUS_PROJECTION_H
@@ -715,6 +716,16 @@ extern "C" {
*
   * @hideinitializer */
 #define OPUS_GET_PHASE_INVERSION_DISABLED(x)
OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+/** Gets the DTX state of the encoder.
+  * Returns wheter the last encoded frame was either a comfort noise update
+  * during DTX or not encoded because of DTX.
+ * @param[out] x opus_int32 * : Returns one of the
following
values:
+ *
+ * 0 The encoder is not in DTX.
+ * 1 The encoder is in DTX.
+ *
+  * @hideinitializer */
+#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)

 /**@}*/

diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index cbeb40ae..0d84737a 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -2725,6 +2725,27 @@ int opus_encoder_ctl(OpusEncoder *st, int request,
...)
             ret = celt_encoder_ctl(celt_enc, OPUS_SET_ENERGY_MASK(value));
         }
         break;
+        case OPUS_GET_IN_DTX_REQUEST:
+        {
+            opus_int32 *value = va_arg(ap, opus_int32*);
+            if (!value)
+            {
+                goto bad_arg;
+            }
+            *value = 0;
+            if (st->silk_mode.useDTX) {
+                /* DTX determined by Silk. */
+                void *silk_enc = (char*)st+st->silk_enc_offset;
+                *value
((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.noSpeechCounter
>NB_SPEECH_FRAMES_BEFORE_DTX;
+            }
+#ifndef DISABLE_FLOAT_API
+            else if (st->use_dtx) {
+                /* DTX determined by Opus. */
+                *value = st->nb_no_activity_frames
>NB_SPEECH_FRAMES_BEFORE_DTX;
+            }
+#endif
+        }
+        break;

         case CELT_GET_MODE_REQUEST:
         {
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.xiph.org/pipermail/opus/attachments/20190401/13a3c223/attachment.html>