[CELT-dev] Add callback for twiddling DCT data
Thorvald Natvig
thorvald at natvig.com
Wed Jun 3 08:31:25 PDT 2009
Hi,
Attached is the first version of the DCT callback. It's still a bit WIP,
but now you have something to refer to when I'm rambling :)
Best Regards,
Thorvald
-------------- next part --------------
From 829e9912762d3a7a513d10a8eb8a7a3fe17b2c52 Mon Sep 17 00:00:00 2001
From: Thorvald Natvig <slicer at users.sourceforge.net>
Date: Wed, 3 Jun 2009 16:48:30 +0200
Subject: [PATCH] Add callback for twiddling DCT data
---
libcelt/celt.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
libcelt/celt.h | 28 ++++++++++++++++++++++++++++
2 files changed, 75 insertions(+), 0 deletions(-)
diff --git a/libcelt/celt.c b/libcelt/celt.c
index 26ec8e1..e49d0aa 100644
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -93,6 +93,12 @@ struct CELTEncoder {
celt_word16_t *psy_mem;
struct PsyDecay psy;
#endif
+#ifdef FIXED_POINT
+ _celt_callback_dct callback_dct;
+#else
+ _celt_callback_dct_float callback_dct;
+#endif
+ void *callback_dct_userdata;
};
CELTEncoder *celt_encoder_create(const CELTMode *mode)
@@ -132,6 +138,9 @@ CELTEncoder *celt_encoder_create(const CELTMode *mode)
psydecay_init(&st->psy, MAX_PERIOD/2, st->mode->Fs);
#endif
+ st->callback_dct = NULL;
+ st->callback_dct_userdata = NULL;
+
return st;
}
@@ -549,6 +558,21 @@ int celt_encode_float(CELTEncoder * restrict st, const celt_sig_t * pcm, celt_si
ALLOC(bandE,st->mode->nbEBands*C, celt_ener_t);
/* Compute MDCTs */
compute_mdcts(st->mode, shortBlocks, in, freq);
+
+ if (st->callback_dct) {
+#ifdef FIXED_POINT
+ if(st->callback_dct(st, freq, shortBlocks ? st->mode->nbShortMdcts : 1, SIG_SHIFT, st->callback_dct_userdata) == 0) {
+#else
+ if(st->callback_dct(st, freq, shortBlocks ? st->mode->nbShortMdcts : 1, st->callback_dct_userdata) == 0) {
+#endif
+ if (st->pitch_available > 0) st->pitch_available = 1;
+ st->delayedIntra = 1;
+
+ RESTORE_STACK;
+ return CELT_CALLBACK_DCT_ABORT;
+ }
+ }
+
if (shortBlocks && !transient_shift)
{
celt_word32_t sum[4]={1,1,1,1};
@@ -972,6 +996,29 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
st->delayedIntra = 1;
}
break;
+#ifdef FIXED_POINT
+ case CELT_SET_CALLBACK_DCT_REQUEST:
+ {
+ _celt_callback_dct cb = va_arg(ap, _celt_callback_dct);
+ void *data = va_arg(ap, void *);
+ if (cb == NULL)
+ data = NULL;
+ st->callback_dct = cb;
+ st->callback_dct_userdata = data;
+ }
+ break;
+#else
+ case CELT_SET_CALLBACK_DCT_FLOAT_REQUEST:
+ {
+ _celt_callback_dct_float cb = va_arg(ap, _celt_callback_dct_float);
+ void *data = va_arg(ap, void *);
+ if (cb == NULL)
+ data = NULL;
+ st->callback_dct = cb;
+ st->callback_dct_userdata = data;
+ }
+ break;
+#endif
default:
goto bad_request;
}
diff --git a/libcelt/celt.h b/libcelt/celt.h
index aa40364..9c2c6c0 100644
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -51,7 +51,11 @@ extern "C" {
#define EXPORT
#endif
+
#define _celt_check_int(x) (((void)((x) == (celt_int32_t)0)), (celt_int32_t)(x))
+#define _celt_check_dct_callback_float(x) (((void)((_celt_callback_dct_float)NULL == (x))), (_celt_callback_dct_float)(x))
+#define _celt_check_dct_callback(x) (((void)((_celt_callback_dct)NULL == (x))), (_celt_callback_dct)(x))
+#define _celt_check_voidptr(x) (((void)((void *)NULL == (x))), (void *)(x))
/* Error codes */
/** No error */
@@ -66,6 +70,8 @@ extern "C" {
#define CELT_CORRUPTED_DATA -4
/** Invalid/unsupported request number */
#define CELT_UNIMPLEMENTED -5
+/** Encoding aborted by DCT callback */
+#define CELT_CALLBACK_DCT_ABORT -6
/* Requests */
#define CELT_SET_COMPLEXITY_REQUEST 2
@@ -93,6 +99,13 @@ extern "C" {
/** GET the bit-stream version for compatibility check */
#define CELT_GET_BITSTREAM_VERSION 2000
+#define CELT_SET_CALLBACK_DCT_FLOAT_REQUEST 3000
+#define CELT_SET_CALLBACK_DCT_REQUEST 3001
+
+/** Set the DCT callback for floating point mode */
+#define CELT_SET_CALLBACK_DCT_FLOAT(x,y) CELT_SET_CALLBACK_DCT_FLOAT_REQUEST, _celt_check_dct_callback_float(x), _celt_check_voidptr(y)
+/** Set the DCT callback for fixed point mode */
+#define CELT_SET_CALLBACK_DCT(x,y) CELT_SET_CALLBACK_DCT_REQUEST, _celt_check_dct_callback(x), _celt_check_voidptr(y)
/** Contains the state of an encoder. One encoder state is needed for each
stream. It is initialised once at the beginning of the stream. Do *not*
@@ -111,6 +124,21 @@ typedef struct CELTDecoder CELTDecoder;
otherwise the quality will be very bad */
typedef struct CELTMode CELTMode;
+/** Callback function for twiddling DCT data in floating point mode.
+ * You need to fetch the block length, channels and sample rate either from the encoder state or
+ * have in the user_data.
+ * @param st Encoder state called back from
+ * @param freq Block to be encoded, frequency domain
+ * @param Number of interleaved DCTs in freq.
+ * @param user_data User data pointer.
+ * @return Abort state. If the callback returns 0, encoding will be aborted, and the encoder call will
+ * return CELT_CALLBACK_DCT_ABORT. You can therefore do encoding decisions in this callback.
+ */
+typedef celt_int32_t (* _celt_callback_dct_float)(CELTEncoder *st, float *freq, celt_int32_t numMdcts, void *user_data);
+
+/** Callback function for twiddling DCT data in fixed point mode.
+ */
+typedef celt_int32_t (* _celt_callback_dct)(CELTEncoder *st, celt_int32_t *freq, celt_int32_t numMdcts, celt_int32_t scale, void *user_data);
/** \defgroup codec Encoding and decoding */
/* @{ */
--
1.6.1.3
More information about the celt-dev
mailing list