Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.xiph.org/xiph/opus.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Marc Valin <jmvalin@amazon.com>2023-05-19 09:31:11 +0300
committerJean-Marc Valin <jmvalin@amazon.com>2023-06-16 20:01:39 +0300
commite0c6eae8cc789b1d80babe5219d505fbf9d91a88 (patch)
tree50cbfe185c0524dbbfb77b385b88928b266980c7
parenta561f120c97f47d12baa56c33d351cbe8b579ddc (diff)
Update the API to add an OpusDREDDecoder
-rw-r--r--include/opus.h34
-rw-r--r--src/opus_decoder.c81
-rw-r--r--src/opus_demo.c5
3 files changed, 111 insertions, 9 deletions
diff --git a/include/opus.h b/include/opus.h
index cde0f20c..01668a8b 100644
--- a/include/opus.h
+++ b/include/opus.h
@@ -398,6 +398,13 @@ OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NON
*/
typedef struct OpusDecoder OpusDecoder;
+/** Opus DRED decoder.
+ * This contains the complete state of an Opus DRED decoder.
+ * It is position independent and can be freely copied.
+ * @see opus_dred_decoder_create,opus_dred_decoder_init
+ */
+typedef struct OpusDREDDecoder OpusDREDDecoder;
+
/** Opus DRED state.
* This contains the complete state of an Opus DRED packet.
@@ -519,6 +526,28 @@ OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NON
*/
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
+/** Gets the size of an <code>OpusDREDDecoder</code> structure.
+ * @returns The size in bytes.
+ */
+OPUS_EXPORT int opus_dred_decoder_get_size(void);
+
+/** Allocates and initializes an OpusDREDDecoder state.
+ * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT OpusDREDDecoder *opus_dred_decoder_create(int *error);
+
+/** Initializes an <code>OpusDREDDecoder</code> state.
+ * @param[in] st <tt>OpusDREDDecoder*</tt>: State to be initialized.
+ * @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
+ */
+OPUS_EXPORT int opus_dred_decoder_init(OpusDREDDecoder *dec);
+
+/** Frees an <code>OpusDREDDecoder</code> allocated by opus_dred_decoder_create().
+ * @param[in] st <tt>OpusDREDDecoder*</tt>: State to be freed.
+ */
+OPUS_EXPORT void opus_dred_decoder_destroy(OpusDREDDecoder *dec);
+
+
/** Gets the size of an <code>OpusDRED</code> structure.
* @returns The size in bytes.
@@ -544,13 +573,14 @@ OPUS_EXPORT void opus_dred_destroy(OpusDRED *dec);
* @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
*/
-OPUS_EXPORT int opus_dred_parse(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 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.
* @param [in] dred <tt>OpusDRED*</tt>: DRED state
* @returns @ref opus_errorcodes
*/
-OPUS_EXPORT int opus_dred_process(OpusDRED *dred);
+OPUS_EXPORT int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst);
/** Decode audio from an Opus DRED packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
diff --git a/src/opus_decoder.c b/src/opus_decoder.c
index d0ef18f2..bf2f38ed 100644
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -1089,6 +1089,69 @@ int opus_decoder_get_nb_samples(const OpusDecoder *dec,
return opus_packet_get_nb_samples(packet, len, dec->Fs);
}
+struct OpusDREDDecoder {
+ int arch;
+ opus_uint32 magic;
+};
+
+#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
+static void validate_dred_decoder(OpusDREDDecoder *st)
+{
+ celt_assert(st->magic == 0xD8EDDEC0);
+#ifdef OPUS_ARCHMASK
+ celt_assert(st->arch >= 0);
+ celt_assert(st->arch <= OPUS_ARCHMASK);
+#endif
+}
+#define VALIDATE_DRED_DECODER(st) validate_dred_decoder(st)
+#else
+#define VALIDATE_DRED_DECODER(st)
+#endif
+
+
+int opus_dred_decoder_get_size(void)
+{
+ return sizeof(OpusDREDDecoder);
+}
+
+int opus_dred_decoder_init(OpusDREDDecoder *dec)
+{
+ dec->arch = opus_select_arch();
+ /* To make sure nobody forgets to init, use a magic number. */
+ dec->magic = 0xD8EDDEC0;
+ return OPUS_OK;
+}
+
+OpusDREDDecoder *opus_dred_decoder_create(int *error)
+{
+ int ret;
+ OpusDREDDecoder *dec;
+ dec = (OpusDREDDecoder *)opus_alloc(opus_dred_get_size());
+ if (dec == NULL)
+ {
+ if (error)
+ *error = OPUS_ALLOC_FAIL;
+ return NULL;
+ }
+ ret = opus_dred_decoder_init(dec);
+ if (error)
+ *error = ret;
+ if (ret != OPUS_OK)
+ {
+ opus_free(dec);
+ dec = NULL;
+ }
+ return dec;
+}
+
+void opus_dred_decoder_destroy(OpusDREDDecoder *dec)
+{
+ dec->magic = 0xDE57801D;
+ free(dec);
+}
+
+
+
#ifdef ENABLE_NEURAL_FEC
static int dred_find_payload(const unsigned char *data, opus_int32 len, const unsigned char **payload)
{
@@ -1144,11 +1207,12 @@ static int dred_find_payload(const unsigned char *data, opus_int32 len, const un
}
#endif
-int opus_dred_parse(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 defer_processing)
{
#ifdef ENABLE_NEURAL_FEC
const unsigned char *payload;
opus_int32 payload_len;
+ VALIDATE_DRED_DECODER(dred_dec);
payload_len = dred_find_payload(data, len, &payload);
if (payload_len < 0)
return payload_len;
@@ -1160,7 +1224,7 @@ int opus_dred_parse(OpusDRED *dred, const unsigned char *data, opus_int32 len, o
min_feature_frames = IMIN(2 + offset, 2*DRED_NUM_REDUNDANCY_FRAMES);
dred_ec_decode(dred, payload, payload_len, min_feature_frames);
if (!defer_processing)
- opus_dred_process(dred);
+ opus_dred_process(dred_dec, dred, dred);
return dred->nb_latents*sampling_rate/25 - sampling_rate/50;
}
return 0;
@@ -1175,13 +1239,18 @@ int opus_dred_parse(OpusDRED *dred, const unsigned char *data, opus_int32 len, o
#endif
}
-int opus_dred_process(OpusDRED *dred)
+int opus_dred_process(OpusDREDDecoder *dred_dec, const OpusDRED *src, OpusDRED *dst)
{
#ifdef ENABLE_NEURAL_FEC
- if (dred->process_stage == 2)
+ if (dred_dec == NULL)
+ return OPUS_BAD_ARG;
+ VALIDATE_DRED_DECODER(dred_dec);
+ if (src != dst)
+ OPUS_COPY(dst, src, 1);
+ if (dst->process_stage == 2)
return OPUS_OK;
- DRED_rdovae_decode_all(dred->fec_features, dred->state, dred->latents, dred->nb_latents);
- dred->process_stage = 2;
+ DRED_rdovae_decode_all(dst->fec_features, dst->state, dst->latents, dst->nb_latents);
+ dst->process_stage = 2;
return OPUS_OK;
#else
(void)dred;
diff --git a/src/opus_demo.c b/src/opus_demo.c
index 2cad2986..7992050e 100644
--- a/src/opus_demo.c
+++ b/src/opus_demo.c
@@ -218,6 +218,7 @@ int main(int argc, char *argv[])
OpusEncoder *enc=NULL;
OpusDecoder *dec=NULL;
OpusDRED *dred=NULL;
+ OpusDREDDecoder *dred_dec=NULL;
int args;
int len;
int frame_size, channels;
@@ -630,6 +631,7 @@ int main(int argc, char *argv[])
opus_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(variable_duration));
frame_size = 2*48000;
}
+ dred_dec = opus_dred_decoder_create(&err);
dred = opus_dred_create(&err);
while (!stop)
{
@@ -803,7 +805,7 @@ int main(int argc, char *argv[])
opus_decoder_ctl(dec, OPUS_GET_LAST_PACKET_DURATION(&output_samples));
dred_input = lost_count*output_samples*100/sampling_rate;
/* Only decode the amount we need to fill in the gap. */
- opus_dred_parse(dred, data, len, IMIN(100, IMAX(0, dred_input))*480, 48000, 0);
+ opus_dred_parse(dred_dec, dred, data, len, IMIN(100, IMAX(0, dred_input))*480, 48000, 0);
}
/* FIXME: Figure out how to trigger the decoder when the last packet of the file is lost. */
for (fr=0;fr<run_decoder;fr++) {
@@ -917,6 +919,7 @@ failure:
opus_encoder_destroy(enc);
opus_decoder_destroy(dec);
opus_dred_destroy(dred);
+ opus_dred_decoder_destroy(dred_dec);
free(data);
if (fin)
fclose(fin);