summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@amazon.com>2022-12-21 03:30:31 -0500
committerJean-Marc Valin <jmvalin@amazon.com>2022-12-21 03:30:31 -0500
commit87f8270f7959535c4fb2a2d9c8c6842466e49785 (patch)
tree07c5332cc26a052a9889792fd47e00779ad1ea3a
parentdf7e01521363893fc3e83330c424c5d74443a563 (diff)
downloadopus-87f8270f7959535c4fb2a2d9c8c6842466e49785.tar.gz
Controlling DRED on the encode side
-rw-r--r--include/opus_defines.h10
-rw-r--r--silk/dred_encoder.c4
-rw-r--r--silk/dred_encoder.h2
-rw-r--r--src/opus_decoder.c2
-rw-r--r--src/opus_demo.c9
-rw-r--r--src/opus_encoder.c31
6 files changed, 53 insertions, 5 deletions
diff --git a/include/opus_defines.h b/include/opus_defines.h
index 94b9e0d9..3ca90188 100644
--- a/include/opus_defines.h
+++ b/include/opus_defines.h
@@ -169,6 +169,8 @@ extern "C" {
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
#define OPUS_GET_IN_DTX_REQUEST 4049
+#define OPUS_SET_DRED_DURATION_REQUEST 4050
+#define OPUS_GET_DRED_DURATION_REQUEST 4051
/** Defines for the presence of extended APIs. */
#define OPUS_HAVE_OPUS_PROJECTION_H
@@ -620,6 +622,14 @@ extern "C" {
* @hideinitializer */
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
+/** If non-zero, enables Deep Redundancy (DRED) and use the specified maximum number of 10-ms redundant frames
+ * @hideinitializer */
+#define OPUS_SET_DRED_DURATION(x) OPUS_SET_DRED_DURATION_REQUEST, __opus_check_int(x)
+/** Gets the encoder's configured Deep Redundancy (DRED) maximum number of frames.
+ * @hideinitializer */
+#define OPUS_GET_DRED_DURATION(x) OPUS_GET_DRED_DURATION_REQUEST, __opus_check_int_ptr(x)
+
+
/**@}*/
/** @defgroup opus_genericctls Generic CTLs
diff --git a/silk/dred_encoder.c b/silk/dred_encoder.c
index 9e9077f8..5ab56ed1 100644
--- a/silk/dred_encoder.c
+++ b/silk/dred_encoder.c
@@ -74,7 +74,7 @@ void dred_process_silk_frame(DREDEnc *enc, const opus_int16 *silk_frame)
enc->latents_buffer_fill = IMIN(enc->latents_buffer_fill+1, DRED_NUM_REDUNDANCY_FRAMES);
}
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_frames, int max_bytes) {
+int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes) {
const opus_uint16 *dead_zone = DRED_rdovae_get_dead_zone_pointer();
const opus_uint16 *p0 = DRED_rdovae_get_p0_pointer();
const opus_uint16 *quant_scales = DRED_rdovae_get_quant_scales_pointer();
@@ -90,7 +90,7 @@ int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_frames, int
ec_enc_init(&ec_encoder, buf, max_bytes);
dred_encode_state(&ec_encoder, enc->state_buffer);
- for (i = 0; i < enc->latents_buffer_fill-1; i += 2)
+ for (i = 0; i < IMIN(2*max_chunks, enc->latents_buffer_fill-1); i += 2)
{
q_level = (int) floor(0.5f + DRED_ENC_Q0 + 1.f * (DRED_ENC_Q1 - DRED_ENC_Q0) * i / (DRED_NUM_REDUNDANCY_FRAMES - 2));
offset = q_level * DRED_LATENT_DIM;
diff --git a/silk/dred_encoder.h b/silk/dred_encoder.h
index a32cfa97..662cedd6 100644
--- a/silk/dred_encoder.h
+++ b/silk/dred_encoder.h
@@ -51,6 +51,6 @@ void dred_deinit_encoder(DREDEnc *enc);
void dred_process_silk_frame(DREDEnc *enc, const opus_int16 *silk_frame);
-int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_frames, int max_bytes);
+int dred_encode_silk_frame(DREDEnc *enc, unsigned char *buf, int max_chunks, int max_bytes);
#endif
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index 4c238a8a..670a898d 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -658,6 +658,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
/* For FEC/PLC, frame_size has to be to have a multiple of 2.5 ms */
if ((decode_fec || len==0 || data==NULL) && frame_size%(st->Fs/400)!=0)
return OPUS_BAD_ARG;
+#ifdef ENABLE_NEURAL_FEC
if (decode_fec > 0 && st->nb_fec_frames > 0) {
int features_per_frame;
int needed_feature_frames;
@@ -674,6 +675,7 @@ int opus_decode_native(OpusDecoder *st, const unsigned char *data,
}
}
+#endif
if (len==0 || data==NULL)
{
int pcm_count=0;
diff --git a/src/opus_demo.c b/src/opus_demo.c
index 50a66db3..af5e30f3 100644
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -64,6 +64,7 @@ void print_usage( char* argv[] )
fprintf(stderr, "-dtx : enable SILK DTX\n" );
fprintf(stderr, "-loss <perc> : optimize for loss percentage and simulate packet loss, in percent (0-100); default: 0\n" );
fprintf(stderr, "-lossfile <file> : simulate packet loss, reading loss from file\n" );
+ fprintf(stderr, "-dred <frames> : add Deep REDundancy (in units of 10-ms frames)\n" );
}
static void int_to_char(opus_uint32 i, unsigned char ch[4])
@@ -266,6 +267,7 @@ int main(int argc, char *argv[])
int ret = EXIT_FAILURE;
int lost_count=0;
FILE *packet_loss_file=NULL;
+ int dred_duration=0;
if (argc < 5 )
{
@@ -431,6 +433,9 @@ int main(int argc, char *argv[])
exit(1);
}
args += 2;
+ } else if( strcmp( argv[ args ], "-dred" ) == 0 ) {
+ dred_duration = atoi( argv[ args + 1 ] );
+ args += 2;
} else if( strcmp( argv[ args ], "-sweep" ) == 0 ) {
check_encoder_option(decode_only, "-sweep");
sweep_bps = atoi( argv[ args + 1 ] );
@@ -546,6 +551,10 @@ int main(int argc, char *argv[])
opus_encoder_ctl(enc, OPUS_GET_LOOKAHEAD(&skip));
opus_encoder_ctl(enc, OPUS_SET_LSB_DEPTH(16));
opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));
+ if (dred_duration > 0)
+ {
+ opus_encoder_ctl(enc, OPUS_SET_DRED_DURATION(dred_duration));
+ }
}
if (!encode_only)
{
diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 47a4d6eb..4d571c28 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -116,6 +116,9 @@ struct OpusEncoder {
int nb_no_activity_ms_Q1;
opus_val32 peak_signal_energy;
#endif
+#ifdef ENABLE_NEURAL_FEC
+ int dred_duration;
+#endif
int nonfinal_frame; /* current frame is not the final in a packet */
opus_uint32 rangeFinal;
};
@@ -2180,13 +2183,15 @@ opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_
/* Count ToC and redundancy */
ret += 1+redundancy_bytes;
#ifdef ENABLE_NEURAL_FEC
- if (1) {
+ if (st->dred_duration > 0) {
opus_extension_data extension;
unsigned char buf[DRED_MAX_DATA_SIZE];
+ int dred_chunks;
int dred_bytes;
DREDEnc *dred = &((silk_encoder*)silk_enc)->state_Fxx[0].sCmn.dred_encoder;
+ dred_chunks = IMIN(st->dred_duration/4, DRED_NUM_REDUNDANCY_FRAMES/2);
dred_bytes = IMIN(DRED_MAX_DATA_SIZE, max_data_bytes-ret-2);
- dred_bytes = dred_encode_silk_frame(dred, buf, DRED_NUM_REDUNDANCY_FRAMES/2, dred_bytes);
+ dred_bytes = dred_encode_silk_frame(dred, buf, dred_chunks, dred_bytes);
extension.id = 127;
extension.frame = 0;
extension.data = buf;
@@ -2698,6 +2703,28 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
celt_encoder_ctl(celt_enc, OPUS_GET_PHASE_INVERSION_DISABLED(value));
}
break;
+#ifdef ENABLE_NEURAL_FEC
+ case OPUS_SET_DRED_DURATION_REQUEST:
+ {
+ opus_int32 value = va_arg(ap, opus_int32);
+ if(value<0 || value>DRED_MAX_FRAMES)
+ {
+ goto bad_arg;
+ }
+ st->dred_duration = value;
+ }
+ break;
+ case OPUS_GET_DRED_DURATION_REQUEST:
+ {
+ opus_int32 *value = va_arg(ap, opus_int32*);
+ if (!value)
+ {
+ goto bad_arg;
+ }
+ *value = st->dred_duration;
+ }
+ break;
+#endif
case OPUS_RESET_STATE:
{
void *silk_enc;