[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