From e4336a5c2188564a82a111c89e5ad047a0de07e3 Mon Sep 17 00:00:00 2001
From: Jean-Marc Valin <jmvalin@jmvalin.ca>
Date: Thu, 8 Sep 2011 18:19:50 -0400
Subject: [PATCH] Encoder can now produce 40- and 60-ms frames even for
 CELT-only and hybrid

---
 src/opus_encoder.c | 39 ++++++++++++++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 5 deletions(-)

diff --git a/src/opus_encoder.c b/src/opus_encoder.c
index 7987e31da..5051f43e7 100644
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -348,9 +348,11 @@ OpusEncoder *opus_encoder_create(opus_int32 Fs, int channels, int mode, int *err
    return st;
 }
 #ifdef FIXED_POINT
+#define opus_encode_native opus_encode
 int opus_encode(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
                 unsigned char *data, int max_data_bytes)
 #else
+#define opus_encode_native opus_encode_float
 int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
                       unsigned char *data, int max_data_bytes)
 #endif
@@ -480,8 +482,6 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
 #endif
 
     /* Override the chosen mode to make sure we meet the requested frame size */
-    if (st->mode == MODE_CELT_ONLY && frame_size > st->Fs/50)
-       st->mode = MODE_SILK_ONLY;
     if (st->mode != MODE_CELT_ONLY && frame_size < st->Fs/100)
        st->mode = MODE_CELT_ONLY;
 
@@ -567,9 +567,38 @@ int opus_encode_float(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
         st->bandwidth = st->user_bandwidth;
 
     /* Can't support higher than wideband for >20 ms frames */
-    if (frame_size > st->Fs/50 && st->bandwidth > OPUS_BANDWIDTH_WIDEBAND)
-       st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
-
+    if (frame_size > st->Fs/50 && (st->mode == MODE_CELT_ONLY || st->bandwidth > OPUS_BANDWIDTH_WIDEBAND))
+    {
+       unsigned char tmp_data[3][1276];
+       int nb_frames;
+       int bak_mode, bak_bandwidth, bak_channels;
+       OpusRepacketizer *rp = opus_repacketizer_create();
+
+       bak_mode = st->user_forced_mode;
+       bak_bandwidth = st->user_bandwidth;
+       bak_channels = st->force_channels;
+
+       st->user_forced_mode = st->mode;
+       st->user_bandwidth = st->bandwidth;
+       st->force_channels = st->stream_channels;
+
+       nb_frames = frame_size > st->Fs/25 ? 3 : 2;
+       for (i=0;i<nb_frames;i++)
+       {
+          int tmp_len;
+          tmp_len = opus_encode_native(st, pcm+i*(st->channels*st->Fs/50), st->Fs/50, tmp_data[i], max_data_bytes/nb_frames-3);
+          ret = opus_repacketizer_cat(rp, tmp_data[i], tmp_len);
+       }
+       ret = opus_repacketizer_out(rp, data, max_data_bytes);
+
+       opus_repacketizer_destroy(rp);
+
+       st->user_forced_mode = bak_mode;
+       st->user_bandwidth = bak_bandwidth;
+       st->force_channels = bak_channels;
+       RESTORE_STACK;
+       return ret;
+    }
     /* CELT mode doesn't support mediumband, use wideband instead */
     if (st->mode == MODE_CELT_ONLY && st->bandwidth == OPUS_BANDWIDTH_MEDIUMBAND)
         st->bandwidth = OPUS_BANDWIDTH_WIDEBAND;
-- 
GitLab