[FFmpeg-cvslog] opus: move the entropy decoding functions to opus_rc.c

Rostislav Pehlivanov git at videolan.org
Tue Nov 8 16:19:16 EET 2016


ffmpeg | branch: master | Rostislav Pehlivanov <atomnuker at gmail.com> | Mon Nov  7 22:33:11 2016 +0000| [317be31eaf4f07b3bbeb703e8ee73d04b08a587c] | committer: Rostislav Pehlivanov

opus: move the entropy decoding functions to opus_rc.c

The intention is to have both encoding and decoding functions
in opus_rc.c.

Signed-off-by: Rostislav Pehlivanov <atomnuker at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=317be31eaf4f07b3bbeb703e8ee73d04b08a587c
---

 libavcodec/Makefile    |   2 +-
 libavcodec/opus.h      | 222 +------------------------------------------------
 libavcodec/opus_celt.c |  58 ++++++-------
 libavcodec/opus_rc.c   | 221 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/opus_rc.h   |  85 +++++++++++++++++++
 libavcodec/opus_silk.c |  72 ++++++++--------
 libavcodec/opusdec.c   |  40 ++-------
 7 files changed, 380 insertions(+), 320 deletions(-)

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 8e4087e..5fdc97f 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -436,7 +436,7 @@ OBJS-$(CONFIG_NELLYMOSER_DECODER)      += nellymoserdec.o nellymoser.o
 OBJS-$(CONFIG_NELLYMOSER_ENCODER)      += nellymoserenc.o nellymoser.o
 OBJS-$(CONFIG_NUV_DECODER)             += nuv.o rtjpeg.o
 OBJS-$(CONFIG_ON2AVC_DECODER)          += on2avc.o on2avcdata.o
-OBJS-$(CONFIG_OPUS_DECODER)            += opusdec.o opus.o opus_celt.o \
+OBJS-$(CONFIG_OPUS_DECODER)            += opusdec.o opus.o opus_celt.o opus_rc.o \
                                           opus_silk.o opustab.o vorbis_data.o
 OBJS-$(CONFIG_PAF_AUDIO_DECODER)       += pafaudio.o
 OBJS-$(CONFIG_PAF_VIDEO_DECODER)       += pafvideo.o
diff --git a/libavcodec/opus.h b/libavcodec/opus.h
index 3a7ea9f..2079f42 100644
--- a/libavcodec/opus.h
+++ b/libavcodec/opus.h
@@ -32,7 +32,7 @@
 #include "libswresample/swresample.h"
 
 #include "avcodec.h"
-#include "get_bits.h"
+#include "opus_rc.h"
 
 #define MAX_FRAME_SIZE               1275
 #define MAX_FRAMES                   48
@@ -59,7 +59,6 @@
 
 #define ROUND_MULL(a,b,s) (((MUL64(a, b) >> ((s) - 1)) + 1) >> 1)
 #define ROUND_MUL16(a,b)  ((MUL16(a, b) + 16384) >> 15)
-#define opus_ilog(i) (av_log2(i) + !!(i))
 
 #define OPUS_TS_HEADER     0x7FE0        // 0x3ff (11 bits)
 #define OPUS_TS_MASK       0xFFE0        // top 11 bits
@@ -84,21 +83,6 @@ enum OpusBandwidth {
     OPUS_BANDWIDTH_FULLBAND
 };
 
-typedef struct RawBitsContext {
-    const uint8_t *position;
-    unsigned int bytes;
-    unsigned int cachelen;
-    unsigned int cacheval;
-} RawBitsContext;
-
-typedef struct OpusRangeCoder {
-    GetBitContext gb;
-    RawBitsContext rb;
-    unsigned int range;
-    unsigned int value;
-    unsigned int total_read_bits;
-} OpusRangeCoder;
-
 typedef struct SilkContext SilkContext;
 
 typedef struct CeltContext CeltContext;
@@ -193,210 +177,6 @@ typedef struct OpusContext {
     ChannelMap *channel_maps;
 } OpusContext;
 
-static av_always_inline void opus_rc_normalize(OpusRangeCoder *rc)
-{
-    while (rc->range <= 1<<23) {
-        rc->value = ((rc->value << 8) | (get_bits(&rc->gb, 8) ^ 0xFF)) & ((1u << 31) - 1);
-        rc->range          <<= 8;
-        rc->total_read_bits += 8;
-    }
-}
-
-static av_always_inline void opus_rc_update(OpusRangeCoder *rc, unsigned int scale,
-                                          unsigned int low, unsigned int high,
-                                          unsigned int total)
-{
-    rc->value -= scale * (total - high);
-    rc->range  = low ? scale * (high - low)
-                      : rc->range - scale * (total - high);
-    opus_rc_normalize(rc);
-}
-
-static av_always_inline unsigned int opus_rc_getsymbol(OpusRangeCoder *rc, const uint16_t *cdf)
-{
-    unsigned int k, scale, total, symbol, low, high;
-
-    total = *cdf++;
-
-    scale   = rc->range / total;
-    symbol = rc->value / scale + 1;
-    symbol = total - FFMIN(symbol, total);
-
-    for (k = 0; cdf[k] <= symbol; k++);
-    high = cdf[k];
-    low  = k ? cdf[k-1] : 0;
-
-    opus_rc_update(rc, scale, low, high, total);
-
-    return k;
-}
-
-static av_always_inline unsigned int opus_rc_p2model(OpusRangeCoder *rc, unsigned int bits)
-{
-    unsigned int k, scale;
-    scale = rc->range >> bits; // in this case, scale = symbol
-
-    if (rc->value >= scale) {
-        rc->value -= scale;
-        rc->range -= scale;
-        k = 0;
-    } else {
-        rc->range = scale;
-        k = 1;
-    }
-    opus_rc_normalize(rc);
-    return k;
-}
-
-/**
- * CELT: estimate bits of entropy that have thus far been consumed for the
- *       current CELT frame, to integer and fractional (1/8th bit) precision
- */
-static av_always_inline unsigned int opus_rc_tell(const OpusRangeCoder *rc)
-{
-    return rc->total_read_bits - av_log2(rc->range) - 1;
-}
-
-static av_always_inline unsigned int opus_rc_tell_frac(const OpusRangeCoder *rc)
-{
-    unsigned int i, total_bits, rcbuffer, range;
-
-    total_bits = rc->total_read_bits << 3;
-    rcbuffer   = av_log2(rc->range) + 1;
-    range      = rc->range >> (rcbuffer-16);
-
-    for (i = 0; i < 3; i++) {
-        int bit;
-        range = range * range >> 15;
-        bit = range >> 16;
-        rcbuffer = rcbuffer << 1 | bit;
-        range >>= bit;
-    }
-
-    return total_bits - rcbuffer;
-}
-
-/**
- * CELT: read 1-25 raw bits at the end of the frame, backwards byte-wise
- */
-static av_always_inline unsigned int opus_getrawbits(OpusRangeCoder *rc, unsigned int count)
-{
-    unsigned int value = 0;
-
-    while (rc->rb.bytes && rc->rb.cachelen < count) {
-        rc->rb.cacheval |= *--rc->rb.position << rc->rb.cachelen;
-        rc->rb.cachelen += 8;
-        rc->rb.bytes--;
-    }
-
-    value = av_mod_uintp2(rc->rb.cacheval, count);
-    rc->rb.cacheval    >>= count;
-    rc->rb.cachelen     -= count;
-    rc->total_read_bits += count;
-
-    return value;
-}
-
-/**
- * CELT: read a uniform distribution
- */
-static av_always_inline unsigned int opus_rc_unimodel(OpusRangeCoder *rc, unsigned int size)
-{
-    unsigned int bits, k, scale, total;
-
-    bits  = opus_ilog(size - 1);
-    total = (bits > 8) ? ((size - 1) >> (bits - 8)) + 1 : size;
-
-    scale  = rc->range / total;
-    k      = rc->value / scale + 1;
-    k      = total - FFMIN(k, total);
-    opus_rc_update(rc, scale, k, k + 1, total);
-
-    if (bits > 8) {
-        k = k << (bits - 8) | opus_getrawbits(rc, bits - 8);
-        return FFMIN(k, size - 1);
-    } else
-        return k;
-}
-
-static av_always_inline int opus_rc_laplace(OpusRangeCoder *rc, unsigned int symbol, int decay)
-{
-    /* extends the range coder to model a Laplace distribution */
-    int value = 0;
-    unsigned int scale, low = 0, center;
-
-    scale  = rc->range >> 15;
-    center = rc->value / scale + 1;
-    center = (1 << 15) - FFMIN(center, 1 << 15);
-
-    if (center >= symbol) {
-        value++;
-        low = symbol;
-        symbol = 1 + ((32768 - 32 - symbol) * (16384-decay) >> 15);
-
-        while (symbol > 1 && center >= low + 2 * symbol) {
-            value++;
-            symbol *= 2;
-            low    += symbol;
-            symbol  = (((symbol - 2) * decay) >> 15) + 1;
-        }
-
-        if (symbol <= 1) {
-            int distance = (center - low) >> 1;
-            value += distance;
-            low   += 2 * distance;
-        }
-
-        if (center < low + symbol)
-            value *= -1;
-        else
-            low += symbol;
-    }
-
-    opus_rc_update(rc, scale, low, FFMIN(low + symbol, 32768), 32768);
-
-    return value;
-}
-
-static av_always_inline unsigned int opus_rc_stepmodel(OpusRangeCoder *rc, int k0)
-{
-    /* Use a probability of 3 up to itheta=8192 and then use 1 after */
-    unsigned int k, scale, symbol, total = (k0+1)*3 + k0;
-    scale  = rc->range / total;
-    symbol = rc->value / scale + 1;
-    symbol = total - FFMIN(symbol, total);
-
-    k = (symbol < (k0+1)*3) ? symbol/3 : symbol - (k0+1)*2;
-
-    opus_rc_update(rc, scale, (k <= k0) ? 3*(k+0) : (k-1-k0) + 3*(k0+1),
-                   (k <= k0) ? 3*(k+1) : (k-0-k0) + 3*(k0+1), total);
-    return k;
-}
-
-static av_always_inline unsigned int opus_rc_trimodel(OpusRangeCoder *rc, int qn)
-{
-    unsigned int k, scale, symbol, total, low, center;
-
-    total = ((qn>>1) + 1) * ((qn>>1) + 1);
-    scale   = rc->range / total;
-    center = rc->value / scale + 1;
-    center = total - FFMIN(center, total);
-
-    if (center < total >> 1) {
-        k      = (ff_sqrt(8 * center + 1) - 1) >> 1;
-        low    = k * (k + 1) >> 1;
-        symbol = k + 1;
-    } else {
-        k      = (2*(qn + 1) - ff_sqrt(8*(total - center - 1) + 1)) >> 1;
-        low    = total - ((qn + 1 - k) * (qn + 2 - k) >> 1);
-        symbol = qn + 1 - k;
-    }
-
-    opus_rc_update(rc, scale, low, low + symbol, total);
-
-    return k;
-}
-
 int ff_opus_parse_packet(OpusPacket *pkt, const uint8_t *buf, int buf_size,
                          int self_delimited);
 
diff --git a/libavcodec/opus_celt.c b/libavcodec/opus_celt.c
index ea097bd..c115ee7 100644
--- a/libavcodec/opus_celt.c
+++ b/libavcodec/opus_celt.c
@@ -138,7 +138,7 @@ static void celt_decode_coarse_energy(CeltContext *s, OpusRangeCoder *rc)
     /* use the 2D z-transform to apply prediction in both */
     /* the time domain (alpha) and the frequency domain (beta) */
 
-    if (opus_rc_tell(rc)+3 <= s->framebits && opus_rc_p2model(rc, 3)) {
+    if (opus_rc_tell(rc)+3 <= s->framebits && ff_opus_rc_dec_log(rc, 3)) {
         /* intra frame */
         alpha = 0;
         beta  = 1.0f - 4915.0f/32768.0f;
@@ -164,12 +164,12 @@ static void celt_decode_coarse_energy(CeltContext *s, OpusRangeCoder *rc)
             if (available >= 15) {
                 /* decode using a Laplace distribution */
                 int k = FFMIN(i, 20) << 1;
-                value = opus_rc_laplace(rc, model[k] << 7, model[k+1] << 6);
+                value = ff_opus_rc_dec_laplace(rc, model[k] << 7, model[k+1] << 6);
             } else if (available >= 2) {
-                int x = opus_rc_getsymbol(rc, ff_celt_model_energy_small);
+                int x = ff_opus_rc_dec_cdf(rc, ff_celt_model_energy_small);
                 value = (x>>1) ^ -(x&1);
             } else if (available >= 1) {
-                value = -(float)opus_rc_p2model(rc, 1);
+                value = -(float)ff_opus_rc_dec_log(rc, 1);
             } else value = -1;
 
             frame->energy[i] = FFMAX(-9.0f, frame->energy[i]) * alpha + prev[j] + value;
@@ -190,7 +190,7 @@ static void celt_decode_fine_energy(CeltContext *s, OpusRangeCoder *rc)
             CeltFrame *frame = &s->frame[j];
             int q2;
             float offset;
-            q2 = opus_getrawbits(rc, s->fine_bits[i]);
+            q2 = ff_opus_rc_get_raw(rc, s->fine_bits[i]);
             offset = (q2 + 0.5f) * (1 << (14 - s->fine_bits[i])) / 16384.0f - 0.5f;
             frame->energy[i] += offset;
         }
@@ -210,7 +210,7 @@ static void celt_decode_final_energy(CeltContext *s, OpusRangeCoder *rc,
             for (j = 0; j < s->coded_channels; j++) {
                 int q2;
                 float offset;
-                q2 = opus_getrawbits(rc, 1);
+                q2 = ff_opus_rc_get_raw(rc, 1);
                 offset = (q2 - 0.5f) * (1 << (14 - s->fine_bits[i] - 1)) / 16384.0f;
                 s->frame[j].energy[i] += offset;
                 bits_left--;
@@ -230,7 +230,7 @@ static void celt_decode_tf_changes(CeltContext *s, OpusRangeCoder *rc,
 
     for (i = s->startband; i < s->endband; i++) {
         if (consumed+bits+tf_select_bit <= s->framebits) {
-            diff ^= opus_rc_p2model(rc, bits);
+            diff ^= ff_opus_rc_dec_log(rc, bits);
             consumed = opus_rc_tell(rc);
             tf_changed |= diff;
         }
@@ -240,7 +240,7 @@ static void celt_decode_tf_changes(CeltContext *s, OpusRangeCoder *rc,
 
     if (tf_select_bit && ff_celt_tf_select[s->duration][transient][0][tf_changed] !=
                          ff_celt_tf_select[s->duration][transient][1][tf_changed])
-        tf_select = opus_rc_p2model(rc, 1);
+        tf_select = ff_opus_rc_dec_log(rc, 1);
 
     for (i = s->startband; i < s->endband; i++) {
         s->tf_change[i] = ff_celt_tf_select[s->duration][transient][tf_select][s->tf_change[i]];
@@ -277,7 +277,7 @@ static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc)
     /* obtain spread flag */
     s->spread = CELT_SPREAD_NORMAL;
     if (consumed + 4 <= s->framebits)
-        s->spread = opus_rc_getsymbol(rc, ff_celt_model_spread);
+        s->spread = ff_opus_rc_dec_cdf(rc, ff_celt_model_spread);
 
     /* generate static allocation caps */
     for (i = 0; i < CELT_MAX_BANDS; i++) {
@@ -297,7 +297,7 @@ static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc)
         quanta = FFMIN(quanta << 3, FFMAX(6 << 3, quanta));
         band_dynalloc = dynalloc;
         while (consumed + (band_dynalloc<<3) < totalbits && boost[i] < cap[i]) {
-            int add = opus_rc_p2model(rc, band_dynalloc);
+            int add = ff_opus_rc_dec_log(rc, band_dynalloc);
             consumed = opus_rc_tell_frac(rc);
             if (!add)
                 break;
@@ -313,7 +313,7 @@ static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc)
 
     /* obtain allocation trim */
     if (consumed + (6 << 3) <= totalbits)
-        alloctrim = opus_rc_getsymbol(rc, ff_celt_model_alloc_trim);
+        alloctrim = ff_opus_rc_dec_cdf(rc, ff_celt_model_alloc_trim);
 
     /* anti-collapse bit reservation */
     totalbits = (s->framebits << 3) - opus_rc_tell_frac(rc) - 1;
@@ -465,7 +465,7 @@ static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc)
         /* a "do not skip" marker is only coded if the allocation is
            above the chosen threshold */
         if (allocation >= FFMAX(threshold[j], (s->coded_channels + 1) <<3 )) {
-            if (opus_rc_p2model(rc, 1))
+            if (ff_opus_rc_dec_log(rc, 1))
                 break;
 
             total      += 1 << 3;
@@ -489,11 +489,11 @@ static void celt_decode_allocation(CeltContext *s, OpusRangeCoder *rc)
     s->dualstereo      = 0;
     if (intensitystereo_bit)
         s->intensitystereo = s->startband +
-                          opus_rc_unimodel(rc, s->codedbands + 1 - s->startband);
+                          ff_opus_rc_dec_uint(rc, s->codedbands + 1 - s->startband);
     if (s->intensitystereo <= s->startband)
         totalbits += dualstereo_bit; /* no intensity stereo means no dual stereo */
     else if (dualstereo_bit)
-        s->dualstereo = opus_rc_p2model(rc, 1);
+        s->dualstereo = ff_opus_rc_dec_log(rc, 1);
 
     /* supply the remaining bits in this frame to lower bands */
     remaining = totalbits - total;
@@ -909,7 +909,7 @@ static inline float celt_decode_pulses(OpusRangeCoder *rc, int *y, unsigned int
     unsigned int idx;
 #define CELT_PVQ_U(n, k) (ff_celt_pvq_u_row[FFMIN(n, k)][FFMAX(n, k)])
 #define CELT_PVQ_V(n, k) (CELT_PVQ_U(n, k) + CELT_PVQ_U(n, (k) + 1))
-    idx = opus_rc_unimodel(rc, CELT_PVQ_V(N, K));
+    idx = ff_opus_rc_dec_uint(rc, CELT_PVQ_V(N, K));
     return celt_cwrsi(N, K, idx, y);
 }
 
@@ -960,7 +960,7 @@ static unsigned int celt_decode_band(CeltContext *s, OpusRangeCoder *rc,
         for (i = 0; i <= dualstereo; i++) {
             int sign = 0;
             if (s->remaining2 >= 1<<3) {
-                sign           = opus_getrawbits(rc, 1);
+                sign           = ff_opus_rc_get_raw(rc, 1);
                 s->remaining2 -= 1 << 3;
                 b             -= 1 << 3;
             }
@@ -1048,16 +1048,16 @@ static unsigned int celt_decode_band(CeltContext *s, OpusRangeCoder *rc,
             /* Entropy coding of the angle. We use a uniform pdf for the
             time split, a step for stereo, and a triangular one for the rest. */
             if (dualstereo && N > 2)
-                itheta = opus_rc_stepmodel(rc, qn/2);
+                itheta = ff_opus_rc_dec_uint_step(rc, qn/2);
             else if (dualstereo || B0 > 1)
-                itheta = opus_rc_unimodel(rc, qn+1);
+                itheta = ff_opus_rc_dec_uint(rc, qn+1);
             else
-                itheta = opus_rc_trimodel(rc, qn);
+                itheta = ff_opus_rc_dec_uint_tri(rc, qn);
             itheta = itheta * 16384 / qn;
             /* NOTE: Renormalising X and Y *may* help fixed-point a bit at very high rate.
             Let's do that at higher complexity */
         } else if (dualstereo) {
-            inv = (b > 2 << 3 && s->remaining2 > 2 << 3) ? opus_rc_p2model(rc, 2) : 0;
+            inv = (b > 2 << 3 && s->remaining2 > 2 << 3) ? ff_opus_rc_dec_log(rc, 2) : 0;
             itheta = 0;
         }
         qalloc = opus_rc_tell_frac(rc) - tell;
@@ -1103,7 +1103,7 @@ static unsigned int celt_decode_band(CeltContext *s, OpusRangeCoder *rc,
             x2 = c ? Y : X;
             y2 = c ? X : Y;
             if (sbits)
-                sign = opus_getrawbits(rc, 1);
+                sign = ff_opus_rc_get_raw(rc, 1);
             sign = 1 - 2 * sign;
             /* We use orig_fill here because we want to fold the side, but if
             itheta==16384, we'll have cleared the low bits of fill. */
@@ -1411,16 +1411,16 @@ static int parse_postfilter(CeltContext *s, OpusRangeCoder *rc, int consumed)
     memset(s->frame[1].pf_gains_new, 0, sizeof(s->frame[1].pf_gains_new));
 
     if (s->startband == 0 && consumed + 16 <= s->framebits) {
-        int has_postfilter = opus_rc_p2model(rc, 1);
+        int has_postfilter = ff_opus_rc_dec_log(rc, 1);
         if (has_postfilter) {
             float gain;
             int tapset, octave, period;
 
-            octave = opus_rc_unimodel(rc, 6);
-            period = (16 << octave) + opus_getrawbits(rc, 4 + octave) - 1;
-            gain   = 0.09375f * (opus_getrawbits(rc, 3) + 1);
+            octave = ff_opus_rc_dec_uint(rc, 6);
+            period = (16 << octave) + ff_opus_rc_get_raw(rc, 4 + octave) - 1;
+            gain   = 0.09375f * (ff_opus_rc_get_raw(rc, 3) + 1);
             tapset = (opus_rc_tell(rc) + 2 <= s->framebits) ?
-                     opus_rc_getsymbol(rc, ff_celt_model_tapset) : 0;
+                     ff_opus_rc_dec_cdf(rc, ff_celt_model_tapset) : 0;
 
             for (i = 0; i < 2; i++) {
                 CeltFrame *frame = &s->frame[i];
@@ -1636,7 +1636,7 @@ int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc,
     if (consumed >= s->framebits)
         silence = 1;
     else if (consumed == 1)
-        silence = opus_rc_p2model(rc, 15);
+        silence = ff_opus_rc_dec_log(rc, 15);
 
 
     if (silence) {
@@ -1649,7 +1649,7 @@ int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc,
 
     /* obtain transient flag */
     if (s->duration != 0 && consumed+3 <= s->framebits)
-        transient = opus_rc_p2model(rc, 3);
+        transient = ff_opus_rc_dec_log(rc, 3);
 
     s->blocks    = transient ? 1 << s->duration : 1;
     s->blocksize = frame_size / s->blocks;
@@ -1668,7 +1668,7 @@ int ff_celt_decode_frame(CeltContext *s, OpusRangeCoder *rc,
     celt_decode_bands        (s, rc);
 
     if (s->anticollapse_bit)
-        anticollapse = opus_getrawbits(rc, 1);
+        anticollapse = ff_opus_rc_get_raw(rc, 1);
 
     celt_decode_final_energy(s, rc, s->framebits - opus_rc_tell(rc));
 
diff --git a/libavcodec/opus_rc.c b/libavcodec/opus_rc.c
new file mode 100644
index 0000000..1f9af04
--- /dev/null
+++ b/libavcodec/opus_rc.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2012 Andrew D'Addesio
+ * Copyright (c) 2013-2014 Mozilla Corporation
+ * Copyright (c) 2016 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "opus_rc.h"
+
+static av_always_inline void opus_rc_dec_normalize(OpusRangeCoder *rc)
+{
+    while (rc->range <= 1<<23) {
+        rc->value = ((rc->value << 8) | (get_bits(&rc->gb, 8) ^ 0xFF)) & ((1u << 31) - 1);
+        rc->range          <<= 8;
+        rc->total_read_bits += 8;
+    }
+}
+
+static av_always_inline void opus_rc_dec_update(OpusRangeCoder *rc, uint32_t scale,
+                                                uint32_t low, uint32_t high,
+                                                uint32_t total)
+{
+    rc->value -= scale * (total - high);
+    rc->range  = low ? scale * (high - low)
+                      : rc->range - scale * (total - high);
+    opus_rc_dec_normalize(rc);
+}
+
+uint32_t ff_opus_rc_dec_cdf(OpusRangeCoder *rc, const uint16_t *cdf)
+{
+    unsigned int k, scale, total, symbol, low, high;
+
+    total = *cdf++;
+
+    scale   = rc->range / total;
+    symbol = rc->value / scale + 1;
+    symbol = total - FFMIN(symbol, total);
+
+    for (k = 0; cdf[k] <= symbol; k++);
+    high = cdf[k];
+    low  = k ? cdf[k-1] : 0;
+
+    opus_rc_dec_update(rc, scale, low, high, total);
+
+    return k;
+}
+
+uint32_t ff_opus_rc_dec_log(OpusRangeCoder *rc, uint32_t bits)
+{
+    uint32_t k, scale;
+    scale = rc->range >> bits; // in this case, scale = symbol
+
+    if (rc->value >= scale) {
+        rc->value -= scale;
+        rc->range -= scale;
+        k = 0;
+    } else {
+        rc->range = scale;
+        k = 1;
+    }
+    opus_rc_dec_normalize(rc);
+    return k;
+}
+
+/**
+ * CELT: read 1-25 raw bits at the end of the frame, backwards byte-wise
+ */
+uint32_t ff_opus_rc_get_raw(OpusRangeCoder *rc, uint32_t count)
+{
+    uint32_t value = 0;
+
+    while (rc->rb.bytes && rc->rb.cachelen < count) {
+        rc->rb.cacheval |= *--rc->rb.position << rc->rb.cachelen;
+        rc->rb.cachelen += 8;
+        rc->rb.bytes--;
+    }
+
+    value = av_mod_uintp2(rc->rb.cacheval, count);
+    rc->rb.cacheval    >>= count;
+    rc->rb.cachelen     -= count;
+    rc->total_read_bits += count;
+
+    return value;
+}
+
+/**
+ * CELT: read a uniform distribution
+ */
+uint32_t ff_opus_rc_dec_uint(OpusRangeCoder *rc, uint32_t size)
+{
+    uint32_t bits, k, scale, total;
+
+    bits  = opus_ilog(size - 1);
+    total = (bits > 8) ? ((size - 1) >> (bits - 8)) + 1 : size;
+
+    scale  = rc->range / total;
+    k      = rc->value / scale + 1;
+    k      = total - FFMIN(k, total);
+    opus_rc_dec_update(rc, scale, k, k + 1, total);
+
+    if (bits > 8) {
+        k = k << (bits - 8) | ff_opus_rc_get_raw(rc, bits - 8);
+        return FFMIN(k, size - 1);
+    } else
+        return k;
+}
+
+uint32_t ff_opus_rc_dec_uint_step(OpusRangeCoder *rc, int k0)
+{
+    /* Use a probability of 3 up to itheta=8192 and then use 1 after */
+    uint32_t k, scale, symbol, total = (k0+1)*3 + k0;
+    scale  = rc->range / total;
+    symbol = rc->value / scale + 1;
+    symbol = total - FFMIN(symbol, total);
+
+    k = (symbol < (k0+1)*3) ? symbol/3 : symbol - (k0+1)*2;
+
+    opus_rc_dec_update(rc, scale, (k <= k0) ? 3*(k+0) : (k-1-k0) + 3*(k0+1),
+                       (k <= k0) ? 3*(k+1) : (k-0-k0) + 3*(k0+1), total);
+    return k;
+}
+
+uint32_t ff_opus_rc_dec_uint_tri(OpusRangeCoder *rc, int qn)
+{
+    uint32_t k, scale, symbol, total, low, center;
+
+    total = ((qn>>1) + 1) * ((qn>>1) + 1);
+    scale   = rc->range / total;
+    center = rc->value / scale + 1;
+    center = total - FFMIN(center, total);
+
+    if (center < total >> 1) {
+        k      = (ff_sqrt(8 * center + 1) - 1) >> 1;
+        low    = k * (k + 1) >> 1;
+        symbol = k + 1;
+    } else {
+        k      = (2*(qn + 1) - ff_sqrt(8*(total - center - 1) + 1)) >> 1;
+        low    = total - ((qn + 1 - k) * (qn + 2 - k) >> 1);
+        symbol = qn + 1 - k;
+    }
+
+    opus_rc_dec_update(rc, scale, low, low + symbol, total);
+
+    return k;
+}
+
+int ff_opus_rc_dec_laplace(OpusRangeCoder *rc, uint32_t symbol, int decay)
+{
+    /* extends the range coder to model a Laplace distribution */
+    int value = 0;
+    uint32_t scale, low = 0, center;
+
+    scale  = rc->range >> 15;
+    center = rc->value / scale + 1;
+    center = (1 << 15) - FFMIN(center, 1 << 15);
+
+    if (center >= symbol) {
+        value++;
+        low = symbol;
+        symbol = 1 + ((32768 - 32 - symbol) * (16384-decay) >> 15);
+
+        while (symbol > 1 && center >= low + 2 * symbol) {
+            value++;
+            symbol *= 2;
+            low    += symbol;
+            symbol  = (((symbol - 2) * decay) >> 15) + 1;
+        }
+
+        if (symbol <= 1) {
+            int distance = (center - low) >> 1;
+            value += distance;
+            low   += 2 * distance;
+        }
+
+        if (center < low + symbol)
+            value *= -1;
+        else
+            low += symbol;
+    }
+
+    opus_rc_dec_update(rc, scale, low, FFMIN(low + symbol, 32768), 32768);
+
+    return value;
+}
+
+int ff_opus_rc_dec_init(OpusRangeCoder *rc, const uint8_t *data, int size)
+{
+    int ret = init_get_bits8(&rc->gb, data, size);
+    if (ret < 0)
+        return ret;
+
+    rc->range = 128;
+    rc->value = 127 - get_bits(&rc->gb, 7);
+    rc->total_read_bits = 9;
+    opus_rc_dec_normalize(rc);
+
+    return 0;
+}
+
+void ff_opus_rc_dec_raw_init(OpusRangeCoder *rc, const uint8_t *rightend, uint32_t bytes)
+{
+    rc->rb.position = rightend;
+    rc->rb.bytes    = bytes;
+    rc->rb.cachelen = 0;
+    rc->rb.cacheval = 0;
+}
diff --git a/libavcodec/opus_rc.h b/libavcodec/opus_rc.h
new file mode 100644
index 0000000..68ebc05
--- /dev/null
+++ b/libavcodec/opus_rc.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012 Andrew D'Addesio
+ * Copyright (c) 2013-2014 Mozilla Corporation
+ * Copyright (c) 2016 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_OPUS_RC_H
+#define AVCODEC_OPUS_RC_H
+
+#include <stdint.h>
+#include "get_bits.h"
+
+#define opus_ilog(i) (av_log2(i) + !!(i))
+
+typedef struct RawBitsContext {
+    const uint8_t *position;
+    uint32_t bytes;
+    uint32_t cachelen;
+    uint32_t cacheval;
+} RawBitsContext;
+
+typedef struct OpusRangeCoder {
+    GetBitContext gb;
+    RawBitsContext rb;
+    uint32_t range;
+    uint32_t value;
+    uint32_t total_read_bits;
+} OpusRangeCoder;
+
+/**
+ * CELT: estimate bits of entropy that have thus far been consumed for the
+ *       current CELT frame, to integer and fractional (1/8th bit) precision
+ */
+static av_always_inline uint32_t opus_rc_tell(const OpusRangeCoder *rc)
+{
+    return rc->total_read_bits - av_log2(rc->range) - 1;
+}
+
+static av_always_inline uint32_t opus_rc_tell_frac(const OpusRangeCoder *rc)
+{
+    uint32_t i, total_bits, rcbuffer, range;
+
+    total_bits = rc->total_read_bits << 3;
+    rcbuffer   = av_log2(rc->range) + 1;
+    range      = rc->range >> (rcbuffer-16);
+
+    for (i = 0; i < 3; i++) {
+        int bit;
+        range = range * range >> 15;
+        bit = range >> 16;
+        rcbuffer = rcbuffer << 1 | bit;
+        range >>= bit;
+    }
+
+    return total_bits - rcbuffer;
+}
+
+uint32_t ff_opus_rc_dec_cdf(OpusRangeCoder *rc, const uint16_t *cdf);
+uint32_t ff_opus_rc_dec_log(OpusRangeCoder *rc, uint32_t bits);
+uint32_t ff_opus_rc_dec_uint(OpusRangeCoder *rc, uint32_t size);
+uint32_t ff_opus_rc_dec_uint_step(OpusRangeCoder *rc, int k0);
+uint32_t ff_opus_rc_dec_uint_tri(OpusRangeCoder *rc, int qn);
+uint32_t ff_opus_rc_get_raw(OpusRangeCoder *rc, uint32_t count);
+int      ff_opus_rc_dec_laplace(OpusRangeCoder *rc, uint32_t symbol, int decay);
+
+int  ff_opus_rc_dec_init(OpusRangeCoder *rc, const uint8_t *data, int size);
+void ff_opus_rc_dec_raw_init(OpusRangeCoder *rc, const uint8_t *rightend, uint32_t bytes);
+
+#endif /* AVCODEC_OPUS_RC_H */
diff --git a/libavcodec/opus_silk.c b/libavcodec/opus_silk.c
index c64d24c..4561b5a 100644
--- a/libavcodec/opus_silk.c
+++ b/libavcodec/opus_silk.c
@@ -307,15 +307,15 @@ static inline void silk_decode_lpc(SilkContext *s, SilkFrame *frame,
     *lpc_order = order = s->wb ? 16 : 10;
 
     /* obtain LSF stage-1 and stage-2 indices */
-    lsf_i1 = opus_rc_getsymbol(rc, ff_silk_model_lsf_s1[s->wb][voiced]);
+    lsf_i1 = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s1[s->wb][voiced]);
     for (i = 0; i < order; i++) {
         int index = s->wb ? ff_silk_lsf_s2_model_sel_wb  [lsf_i1][i] :
                             ff_silk_lsf_s2_model_sel_nbmb[lsf_i1][i];
-        lsf_i2[i] = opus_rc_getsymbol(rc, ff_silk_model_lsf_s2[index]) - 4;
+        lsf_i2[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2[index]) - 4;
         if (lsf_i2[i] == -4)
-            lsf_i2[i] -= opus_rc_getsymbol(rc, ff_silk_model_lsf_s2_ext);
+            lsf_i2[i] -= ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2_ext);
         else if (lsf_i2[i] == 4)
-            lsf_i2[i] += opus_rc_getsymbol(rc, ff_silk_model_lsf_s2_ext);
+            lsf_i2[i] += ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_s2_ext);
     }
 
     /* reverse the backwards-prediction step */
@@ -365,7 +365,7 @@ static inline void silk_decode_lpc(SilkContext *s, SilkFrame *frame,
     /* and then convert both sets of NLSFs to LPC coefficients */
     *has_lpc_leadin = 0;
     if (s->subframes == 4) {
-        int offset = opus_rc_getsymbol(rc, ff_silk_model_lsf_interpolation_offset);
+        int offset = ff_opus_rc_dec_cdf(rc, ff_silk_model_lsf_interpolation_offset);
         if (offset != 4 && frame->coded) {
             *has_lpc_leadin = 1;
             if (offset != 0) {
@@ -394,7 +394,7 @@ static inline void silk_count_children(OpusRangeCoder *rc, int model, int32_t to
                                        int32_t child[2])
 {
     if (total != 0) {
-        child[0] = opus_rc_getsymbol(rc,
+        child[0] = ff_opus_rc_dec_cdf(rc,
                        ff_silk_model_pulse_location[model] + (((total - 1 + 5) * (total - 1)) >> 1));
         child[1] = total - child[0];
     } else {
@@ -416,17 +416,17 @@ static inline void silk_decode_excitation(SilkContext *s, OpusRangeCoder *rc,
     int32_t excitation[320];    // Q23
 
     /* excitation parameters */
-    seed = opus_rc_getsymbol(rc, ff_silk_model_lcg_seed);
+    seed = ff_opus_rc_dec_cdf(rc, ff_silk_model_lcg_seed);
     shellblocks = ff_silk_shell_blocks[s->bandwidth][s->subframes >> 2];
-    ratelevel = opus_rc_getsymbol(rc, ff_silk_model_exc_rate[voiced]);
+    ratelevel = ff_opus_rc_dec_cdf(rc, ff_silk_model_exc_rate[voiced]);
 
     for (i = 0; i < shellblocks; i++) {
-        pulsecount[i] = opus_rc_getsymbol(rc, ff_silk_model_pulse_count[ratelevel]);
+        pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[ratelevel]);
         if (pulsecount[i] == 17) {
             while (pulsecount[i] == 17 && ++lsbcount[i] != 10)
-                pulsecount[i] = opus_rc_getsymbol(rc, ff_silk_model_pulse_count[9]);
+                pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[9]);
             if (lsbcount[i] == 10)
-                pulsecount[i] = opus_rc_getsymbol(rc, ff_silk_model_pulse_count[10]);
+                pulsecount[i] = ff_opus_rc_dec_cdf(rc, ff_silk_model_pulse_count[10]);
         }
     }
 
@@ -461,13 +461,13 @@ static inline void silk_decode_excitation(SilkContext *s, OpusRangeCoder *rc,
         int bit;
         for (bit = 0; bit < lsbcount[i >> 4]; bit++)
             excitation[i] = (excitation[i] << 1) |
-                            opus_rc_getsymbol(rc, ff_silk_model_excitation_lsb);
+                            ff_opus_rc_dec_cdf(rc, ff_silk_model_excitation_lsb);
     }
 
     /* decode signs */
     for (i = 0; i < shellblocks << 4; i++) {
         if (excitation[i] != 0) {
-            int sign = opus_rc_getsymbol(rc, ff_silk_model_excitation_sign[active +
+            int sign = ff_opus_rc_dec_cdf(rc, ff_silk_model_excitation_sign[active +
                                          voiced][qoffset_high][FFMIN(pulsecount[i >> 4], 6)]);
             if (sign == 0)
                 excitation[i] *= -1;
@@ -522,11 +522,11 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
     /* obtain stereo weights */
     if (coded_channels == 2 && channel == 0) {
         int n, wi[2], ws[2], w[2];
-        n     = opus_rc_getsymbol(rc, ff_silk_model_stereo_s1);
-        wi[0] = opus_rc_getsymbol(rc, ff_silk_model_stereo_s2) + 3 * (n / 5);
-        ws[0] = opus_rc_getsymbol(rc, ff_silk_model_stereo_s3);
-        wi[1] = opus_rc_getsymbol(rc, ff_silk_model_stereo_s2) + 3 * (n % 5);
-        ws[1] = opus_rc_getsymbol(rc, ff_silk_model_stereo_s3);
+        n     = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s1);
+        wi[0] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s2) + 3 * (n / 5);
+        ws[0] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s3);
+        wi[1] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s2) + 3 * (n % 5);
+        ws[1] = ff_opus_rc_dec_cdf(rc, ff_silk_model_stereo_s3);
 
         for (i = 0; i < 2; i++)
             w[i] = ff_silk_stereo_weights[wi[i]] +
@@ -537,15 +537,15 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
         s->stereo_weights[1] = w[1]          / 8192.0;
 
         /* and read the mid-only flag */
-        s->midonly = active1 ? 0 : opus_rc_getsymbol(rc, ff_silk_model_mid_only);
+        s->midonly = active1 ? 0 : ff_opus_rc_dec_cdf(rc, ff_silk_model_mid_only);
     }
 
     /* obtain frame type */
     if (!active) {
-        qoffset_high = opus_rc_getsymbol(rc, ff_silk_model_frame_type_inactive);
+        qoffset_high = ff_opus_rc_dec_cdf(rc, ff_silk_model_frame_type_inactive);
         voiced = 0;
     } else {
-        int type = opus_rc_getsymbol(rc, ff_silk_model_frame_type_active);
+        int type = ff_opus_rc_dec_cdf(rc, ff_silk_model_frame_type_active);
         qoffset_high = type & 1;
         voiced = type >> 1;
     }
@@ -557,14 +557,14 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
 
         if (i == 0 && (frame_num == 0 || !frame->coded)) {
             /* gain is coded absolute */
-            int x = opus_rc_getsymbol(rc, ff_silk_model_gain_highbits[active + voiced]);
-            log_gain = (x<<3) | opus_rc_getsymbol(rc, ff_silk_model_gain_lowbits);
+            int x = ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_highbits[active + voiced]);
+            log_gain = (x<<3) | ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_lowbits);
 
             if (frame->coded)
                 log_gain = FFMAX(log_gain, frame->log_gain - 16);
         } else {
             /* gain is coded relative */
-            int delta_gain = opus_rc_getsymbol(rc, ff_silk_model_gain_delta);
+            int delta_gain = ff_opus_rc_dec_cdf(rc, ff_silk_model_gain_delta);
             log_gain = av_clip_uintp2(FFMAX((delta_gain<<1) - 16,
                                      frame->log_gain + delta_gain - 4), 6);
         }
@@ -590,7 +590,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
         const int8_t * offsets;
 
         if (!lag_absolute) {
-            int delta = opus_rc_getsymbol(rc, ff_silk_model_pitch_delta);
+            int delta = ff_opus_rc_dec_cdf(rc, ff_silk_model_pitch_delta);
             if (delta)
                 primarylag = frame->primarylag + delta - 9;
             else
@@ -604,8 +604,8 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
                 ff_silk_model_pitch_lowbits_nb, ff_silk_model_pitch_lowbits_mb,
                 ff_silk_model_pitch_lowbits_wb
             };
-            highbits = opus_rc_getsymbol(rc, ff_silk_model_pitch_highbits);
-            lowbits  = opus_rc_getsymbol(rc, model[s->bandwidth]);
+            highbits = ff_opus_rc_dec_cdf(rc, ff_silk_model_pitch_highbits);
+            lowbits  = ff_opus_rc_dec_cdf(rc, model[s->bandwidth]);
 
             primarylag = ff_silk_pitch_min_lag[s->bandwidth] +
                          highbits*ff_silk_pitch_scale[s->bandwidth] + lowbits;
@@ -614,15 +614,15 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
 
         if (s->subframes == 2)
             offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND)
-                     ? ff_silk_pitch_offset_nb10ms[opus_rc_getsymbol(rc,
+                     ? ff_silk_pitch_offset_nb10ms[ff_opus_rc_dec_cdf(rc,
                                                 ff_silk_model_pitch_contour_nb10ms)]
-                     : ff_silk_pitch_offset_mbwb10ms[opus_rc_getsymbol(rc,
+                     : ff_silk_pitch_offset_mbwb10ms[ff_opus_rc_dec_cdf(rc,
                                                 ff_silk_model_pitch_contour_mbwb10ms)];
         else
             offsets = (s->bandwidth == OPUS_BANDWIDTH_NARROWBAND)
-                     ? ff_silk_pitch_offset_nb20ms[opus_rc_getsymbol(rc,
+                     ? ff_silk_pitch_offset_nb20ms[ff_opus_rc_dec_cdf(rc,
                                                 ff_silk_model_pitch_contour_nb20ms)]
-                     : ff_silk_pitch_offset_mbwb20ms[opus_rc_getsymbol(rc,
+                     : ff_silk_pitch_offset_mbwb20ms[ff_opus_rc_dec_cdf(rc,
                                                 ff_silk_model_pitch_contour_mbwb20ms)];
 
         for (i = 0; i < s->subframes; i++)
@@ -631,7 +631,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
                                      ff_silk_pitch_max_lag[s->bandwidth]);
 
         /* obtain LTP filter coefficients */
-        ltpfilter = opus_rc_getsymbol(rc, ff_silk_model_ltp_filter);
+        ltpfilter = ff_opus_rc_dec_cdf(rc, ff_silk_model_ltp_filter);
         for (i = 0; i < s->subframes; i++) {
             int index, j;
             static const uint16_t *filter_sel[] = {
@@ -641,7 +641,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
             static const int8_t (*filter_taps[])[5] = {
                 ff_silk_ltp_filter0_taps, ff_silk_ltp_filter1_taps, ff_silk_ltp_filter2_taps
             };
-            index = opus_rc_getsymbol(rc, filter_sel[ltpfilter]);
+            index = ff_opus_rc_dec_cdf(rc, filter_sel[ltpfilter]);
             for (j = 0; j < 5; j++)
                 sf[i].ltptaps[j] = filter_taps[ltpfilter][index][j] / 128.0f;
         }
@@ -649,7 +649,7 @@ static void silk_decode_frame(SilkContext *s, OpusRangeCoder *rc,
 
     /* obtain LTP scale factor */
     if (voiced && frame_num == 0)
-        ltpscale = ff_silk_ltp_scale_factor[opus_rc_getsymbol(rc,
+        ltpscale = ff_silk_ltp_scale_factor[ff_opus_rc_dec_cdf(rc,
                                          ff_silk_model_ltp_scale_index)] / 16384.0f;
     else ltpscale = 15565.0f/16384.0f;
 
@@ -803,9 +803,9 @@ int ff_silk_decode_superframe(SilkContext *s, OpusRangeCoder *rc,
     /* read the LP-layer header bits */
     for (i = 0; i < coded_channels; i++) {
         for (j = 0; j < nb_frames; j++)
-            active[i][j] = opus_rc_p2model(rc, 1);
+            active[i][j] = ff_opus_rc_dec_log(rc, 1);
 
-        redundancy[i] = opus_rc_p2model(rc, 1);
+        redundancy[i] = ff_opus_rc_dec_log(rc, 1);
         if (redundancy[i]) {
             av_log(s->avctx, AV_LOG_ERROR, "LBRR frames present; this is unsupported\n");
             return AVERROR_PATCHWELCOME;
diff --git a/libavcodec/opusdec.c b/libavcodec/opusdec.c
index 95a2435..ec793c6 100644
--- a/libavcodec/opusdec.c
+++ b/libavcodec/opusdec.c
@@ -73,32 +73,6 @@ static int get_silk_samplerate(int config)
     return 16000;
 }
 
-/**
- * Range decoder
- */
-static int opus_rc_init(OpusRangeCoder *rc, const uint8_t *data, int size)
-{
-    int ret = init_get_bits8(&rc->gb, data, size);
-    if (ret < 0)
-        return ret;
-
-    rc->range = 128;
-    rc->value = 127 - get_bits(&rc->gb, 7);
-    rc->total_read_bits = 9;
-    opus_rc_normalize(rc);
-
-    return 0;
-}
-
-static void opus_raw_init(OpusRangeCoder *rc, const uint8_t *rightend,
-                          unsigned int bytes)
-{
-    rc->rb.position = rightend;
-    rc->rb.bytes    = bytes;
-    rc->rb.cachelen = 0;
-    rc->rb.cacheval = 0;
-}
-
 static void opus_fade(float *out,
                       const float *in1, const float *in2,
                       const float *window, int len)
@@ -185,10 +159,10 @@ static int opus_decode_redundancy(OpusStreamContext *s, const uint8_t *data, int
         bw == OPUS_BANDWIDTH_MEDIUMBAND)
         bw = OPUS_BANDWIDTH_WIDEBAND;
 
-    ret = opus_rc_init(&s->redundancy_rc, data, size);
+    ret = ff_opus_rc_dec_init(&s->redundancy_rc, data, size);
     if (ret < 0)
         goto fail;
-    opus_raw_init(&s->redundancy_rc, data + size, size);
+    ff_opus_rc_dec_raw_init(&s->redundancy_rc, data + size, size);
 
     ret = ff_celt_decode_frame(s->celt, &s->redundancy_rc,
                                s->redundancy_output,
@@ -211,7 +185,7 @@ static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size
     int ret, i, consumed;
     int delayed_samples = s->delayed_samples;
 
-    ret = opus_rc_init(&s->rc, data, size);
+    ret = ff_opus_rc_dec_init(&s->rc, data, size);
     if (ret < 0)
         return ret;
 
@@ -246,15 +220,15 @@ static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size
     // decode redundancy information
     consumed = opus_rc_tell(&s->rc);
     if (s->packet.mode == OPUS_MODE_HYBRID && consumed + 37 <= size * 8)
-        redundancy = opus_rc_p2model(&s->rc, 12);
+        redundancy = ff_opus_rc_dec_log(&s->rc, 12);
     else if (s->packet.mode == OPUS_MODE_SILK && consumed + 17 <= size * 8)
         redundancy = 1;
 
     if (redundancy) {
-        redundancy_pos = opus_rc_p2model(&s->rc, 1);
+        redundancy_pos = ff_opus_rc_dec_log(&s->rc, 1);
 
         if (s->packet.mode == OPUS_MODE_HYBRID)
-            redundancy_size = opus_rc_unimodel(&s->rc, 256) + 2;
+            redundancy_size = ff_opus_rc_dec_uint(&s->rc, 256) + 2;
         else
             redundancy_size = size - (consumed + 7) / 8;
         size -= redundancy_size;
@@ -298,7 +272,7 @@ static int opus_decode_frame(OpusStreamContext *s, const uint8_t *data, int size
             }
         }
 
-        opus_raw_init(&s->rc, data + size, size);
+        ff_opus_rc_dec_raw_init(&s->rc, data + size, size);
 
         ret = ff_celt_decode_frame(s->celt, &s->rc, dst,
                                    s->packet.stereo + 1,




More information about the ffmpeg-cvslog mailing list