[FFmpeg-devel] [RFC v4] libbavcodec: add a native decoder for the Daala video codec

Rostislav Pehlivanov atomnuker at gmail.com
Fri Jan 1 21:16:12 CET 2016


Thanks for the feedback.
Fixed all the issues you reported. The new revision is in this email.

I've replaced the daalaent_cphase with a macro instead. Saves a few lines.

I don't think it's a problem having large functions marked as inline.
Sure they won't be inlined (not with current GCC version anyway) but
I've always though it was best to leave it up for the compiler to know
how big is too big.
Although if you still think they should be just left as <static> or
moved to a C file then just say so. Chances are the vector laplace
functions from the entropy decoding file will be moved into daalapvq
(which is going to have to be templated to handle multiple bit depths)
as they're the ones actually reading the quantized coefficients from
the bitstream.

Signed-off-by: Rostislav Pehlivanov <atomnuker at gmail.com>
---
 configure                  |    1 +
 libavcodec/Makefile        |    2 +
 libavcodec/allcodecs.c     |    2 +
 libavcodec/daala.h         |   97 +++
 libavcodec/daala_entropy.h |  562 +++++++++++++
 libavcodec/daala_parser.c  |   72 ++
 libavcodec/daala_pvq.h     |  385 +++++++++
 libavcodec/daala_utils.h   |  234 ++++++
 libavcodec/daaladec.c      |  810 +++++++++++++++++++
 libavcodec/daaladsp.c      | 1884 ++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/daaladsp.h      |  100 +++
 libavcodec/daalatab.c      | 1564 ++++++++++++++++++++++++++++++++++++
 libavcodec/daalatab.h      |  102 +++
 13 files changed, 5815 insertions(+)
 create mode 100644 libavcodec/daala.h
 create mode 100644 libavcodec/daala_entropy.h
 create mode 100644 libavcodec/daala_parser.c
 create mode 100644 libavcodec/daala_pvq.h
 create mode 100644 libavcodec/daala_utils.h
 create mode 100644 libavcodec/daaladec.c
 create mode 100644 libavcodec/daaladsp.c
 create mode 100644 libavcodec/daaladsp.h
 create mode 100644 libavcodec/daalatab.c
 create mode 100644 libavcodec/daalatab.h

diff --git a/configure b/configure
index da74ccd..0fff96f 100755
--- a/configure
+++ b/configure
@@ -2277,6 +2277,7 @@ comfortnoise_encoder_select="lpc"
 cook_decoder_select="audiodsp mdct sinewin"
 cscd_decoder_select="lzo"
 cscd_decoder_suggest="zlib"
+daala_decoder_select="daala_parser"
 dca_decoder_select="fmtconvert mdct"
 dds_decoder_select="texturedsp"
 dirac_decoder_select="dirac_parse dwt golomb videodsp mpegvideoenc"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index a18ca5b..5e4ab1a 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -221,6 +221,7 @@ OBJS-$(CONFIG_COMFORTNOISE_ENCODER)    += cngenc.o
 OBJS-$(CONFIG_CPIA_DECODER)            += cpia.o
 OBJS-$(CONFIG_CSCD_DECODER)            += cscd.o
 OBJS-$(CONFIG_CYUV_DECODER)            += cyuv.o
+OBJS-$(CONFIG_DAALA_DECODER)           += daaladec.o daalatab.o daaladsp.o
 OBJS-$(CONFIG_DCA_DECODER)             += dcadec.o dca.o dcadsp.o      \
                                           dcadata.o dca_exss.o         \
                                           dca_xll.o synth_filter.o
@@ -864,6 +865,7 @@ OBJS-$(CONFIG_BMP_PARSER)              += bmp_parser.o
 OBJS-$(CONFIG_CAVSVIDEO_PARSER)        += cavs_parser.o
 OBJS-$(CONFIG_COOK_PARSER)             += cook_parser.o
 OBJS-$(CONFIG_DCA_PARSER)              += dca_parser.o dca.o
+OBJS-$(CONFIG_DAALA_PARSER)            += daala_parser.o
 OBJS-$(CONFIG_DIRAC_PARSER)            += dirac_parser.o
 OBJS-$(CONFIG_DNXHD_PARSER)            += dnxhd_parser.o
 OBJS-$(CONFIG_DPX_PARSER)              += dpx_parser.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 4eeb6f3..804c076 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -154,6 +154,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(CPIA,              cpia);
     REGISTER_DECODER(CSCD,              cscd);
     REGISTER_DECODER(CYUV,              cyuv);
+    REGISTER_DECODER(DAALA,             daala);
     REGISTER_DECODER(DDS,               dds);
     REGISTER_DECODER(DFA,               dfa);
     REGISTER_DECODER(DIRAC,             dirac);
@@ -618,6 +619,7 @@ void avcodec_register_all(void)
     REGISTER_PARSER(CAVSVIDEO,          cavsvideo);
     REGISTER_PARSER(COOK,               cook);
     REGISTER_PARSER(DCA,                dca);
+    REGISTER_PARSER(DAALA,              daala);
     REGISTER_PARSER(DIRAC,              dirac);
     REGISTER_PARSER(DNXHD,              dnxhd);
     REGISTER_PARSER(DPX,                dpx);
diff --git a/libavcodec/daala.h b/libavcodec/daala.h
new file mode 100644
index 0000000..eef3d32
--- /dev/null
+++ b/libavcodec/daala.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALA_H
+#define AVCODEC_DAALA_H
+
+#include "avcodec.h"
+
+/* Essential typedefs */
+typedef uint32_t ent_win; /* Has to be able to express 32bit uint nums */
+typedef uint16_t ent_rng;
+typedef  int32_t dctcoef;
+
+#define daalaent_log2(x) (int)(1 + ff_log2(x))
+
+/* Block sizes */
+enum DaalaBsize {
+    DAALA_BLOCKSIZE_4x4 = 0,
+    DAALA_BLOCKSIZE_8x8,
+    DAALA_BLOCKSIZE_16x16,
+    DAALA_BLOCKSIZE_32x32,
+    DAALA_BLOCKSIZE_64x64,
+
+    DAALA_NBSIZES
+};
+
+#define DAALA_MAX_REF_FRAMES 2  /* Maximum number of reference frames */
+#define DAALA_MAX_PLANES 4      /* Redundant but makes loops more descriptive */
+#define DAALA_LOG_BSIZE0 2
+#define DAALA_LOG_BSIZE_MAX (DAALA_LOG_BSIZE0 + DAALA_NBSIZES - 1)
+#define DAALA_BSIZE_MAX  (1 << DAALA_LOG_BSIZE_MAX)
+#define DAALA_BSIZE_GRID (1 << (DAALA_NBSIZES - 2))
+#define DAALA_QM_SIZE DAALA_NBSIZES*(DAALA_NBSIZES + 1)
+#define DAALA_CSHIFT     4
+#define DAALA_PCLIP_FPR ((1 << 8 + DAALA_CSHIFT) - 1)
+
+#define DAALA_QM_SCALE (1 << 15)
+#define DAALA_QM_SCALE_MAX (DAALA_QM_SCALE - 1)
+#define DAALA_QM_SCALE_UNIT (1.0f/DAALA_QM_SCALE_MAX)
+#define DAALA_QM_INV_SCALE (1 << 12)
+#define DAALA_QM_INV_SCALE_UNIT (1.0f/DAALA_QM_INV_SCALE)
+#define DAALA_QM_BSIZE (DAALA_BSIZE_MAX*DAALA_BSIZE_MAX)
+#define DAALA_QM_BUFFER_SIZE (DAALA_NBSIZES*2*DAALA_QM_BSIZE)
+
+typedef struct DaalaBitstreamHeader {
+    uint8_t key_frame;
+    uint8_t bipred;
+    uint8_t ref_num;
+    uint8_t act_mask;
+    uint8_t qm;
+    uint8_t haar;
+    uint8_t golden;
+    uint8_t pvq_qm[DAALA_MAX_PLANES][DAALA_QM_SIZE];
+} DaalaBitstreamHeader;
+
+#endif /* AVCODEC_DAALA_H */
diff --git a/libavcodec/daala_entropy.h b/libavcodec/daala_entropy.h
new file mode 100644
index 0000000..11912d8
--- /dev/null
+++ b/libavcodec/daala_entropy.h
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALAENTROPY_H
+#define AVCODEC_DAALAENTROPY_H
+
+#include "libavutil/avassert.h"
+
+#include "daala.h"
+#include "daalatab.h"
+
+#define DAALAENT_UINT_BITS      4
+#define DAALAENT_MODEL_TAB      12
+#define DAALAENT_BIT_ABUNDANCE  16384
+#define DAALAENT_UNARY_MAX      INT16_MAX
+#define DAALAENT_SAT(a,b)       ((a) - FFMIN(a,b))
+#define DAALAENT_WSIZE          (int)sizeof(ent_win)*CHAR_BIT
+#define DAALAENT_CDF_ACCESS(n)  (&ff_daalaent_cdf_tab[((n)*((n) - 1) >> 1) - 1])
+
+#define DAALAENT_PVQ_COUNT      2
+#define DAALAENT_PVQ_COUNT_EX   3
+#define DAALAENT_PVQ_K          0
+#define DAALAENT_PVQ_SUM_EX     1
+#define DAALAENT_PVQ_NOVAL      INT32_MIN
+
+enum DaalaCDFDecodeType {
+    CDF_NORM = 0,
+    CDF_Q15,
+    CDF_UNSCALED,
+    CDF_DYADIC,
+};
+
+typedef struct DaalaCDF {
+    ent_rng *cdf;
+    int x, y, inc, inc_g, fir;
+    uint8_t gen_mod;
+} DaalaCDF;
+
+typedef struct DaalaEntropy {
+    const uint8_t *buf, *ebuf;    /* Normal, ends before the raw bits start   */
+    const uint8_t *rbuf, *erbuf;  /* Raw, located at the end of the bitstream */
+    ent_rng range;
+    ent_win diff, end_window;
+    int16_t count;
+    int eos_offset, end_window_size;
+    uint8_t err;
+} DaalaEntropy;
+
+/* Expectation value log, outputs Q1 */
+static av_always_inline int daalaent_log_ex(int ex_q16)
+{
+    int o, log = daalaent_log2(ex_q16);
+    if (log < 15) {
+        o = ex_q16*ex_q16 > 2 << 2*log;
+    } else {
+        int tmp = ex_q16 >> (log - 8);
+        o = tmp*tmp > (1 << 15);
+    }
+    return FFMAX(0, 2*log - 33 + o);
+}
+
+/* Number of bits read */
+static av_always_inline int daalaent_bits_count(DaalaEntropy *e)
+{
+    return ((e->ebuf - e->erbuf) + (e->buf - e->rbuf))*8 - \
+             e->count - e->end_window_size + e->eos_offset;
+}
+
+/* Updates the context */
+static av_always_inline void daalaent_fillup(DaalaEntropy *e)
+{
+    int i = DAALAENT_WSIZE - 9 - (e->count + 15);
+    const uint8_t *ebuf = e->ebuf, *buf = e->buf;
+    for (; i >= 0 && buf < ebuf; i -= 8, buf++) {
+        av_assert0(i <= DAALAENT_WSIZE - 8);
+        e->diff |= (ent_win)buf[0] << i;
+        e->count += 8;
+    }
+    if (buf >= ebuf) {
+        e->eos_offset += DAALAENT_BIT_ABUNDANCE - e->count;
+        e->count = DAALAENT_BIT_ABUNDANCE;
+    }
+    e->ebuf = ebuf;
+    e->buf = buf;
+}
+
+/* Updates the generic exponential probability model */
+static av_always_inline void daalaent_exp_model_update(DaalaCDF *c, int *ex, int x,
+                                                       int xs, int id, int integrate)
+{
+    int i, xenc;
+    ent_rng *cdf = &c->cdf[id*c->y];
+    if (cdf[15] + c->inc > 32767) {
+        for (i = 0; i < 16; i++)
+            cdf[i] = (cdf[i] >> 1) + i + 1;
+    }
+    xenc = FFMIN(15, xs);
+    for (i = xenc; i < 16; i++)
+        cdf[i] += c->inc;
+    x = FFMIN(x, 32767);
+    *ex += ((x << 16) - *ex) >> integrate;
+}
+
+
+/* Renormalizes */
+static inline void daalaent_renormalize(DaalaEntropy *e, uint32_t diff,
+                                        ent_rng range)
+{
+    int i = 16 - daalaent_log2(range);
+    e->diff = diff << i;
+    e->range = range << i;
+    if ((e->count -= i) < 0)
+        daalaent_fillup(e);
+}
+
+/* Decodes a bool from the bitstream, p ∈ (0, p_tot), p_tot ∈ [16384, 32768] */
+static inline uint8_t daalaent_decode_bool(DaalaEntropy *e, uint32_t p,
+                                           uint32_t p_tot)
+{
+    uint8_t rval;
+    long int diff = e->range - p_tot, tmp = diff >= p_tot;
+    av_assert0(e->diff >> (DAALAENT_WSIZE - 16) < e->range);
+    p <<= tmp;
+    p_tot <<= tmp;
+    tmp  = DAALAENT_SAT(2*diff, p_tot);
+    tmp  = p + FFMIN(p, tmp) + FFMIN(DAALAENT_SAT(p, tmp) >> 1, diff);
+    diff = tmp << (DAALAENT_WSIZE - 16);
+    rval = e->diff >= diff;
+    diff = e->diff - (rval ? diff : 0);
+    tmp  = rval ? e->range - tmp : tmp;
+    daalaent_renormalize(e, diff, tmp);
+    return rval;
+}
+
+/* Decodes a symbol from a CDF table */
+static inline int daalaent_decode_cdf(DaalaEntropy *e, const ent_rng *cdf,
+                                      int cdf_size, uint32_t p_tot,
+                                      enum DaalaCDFDecodeType type)
+{
+    int d, lim, g, scale, ret = 0;
+    ent_rng range = e->range;
+    ent_win diff = e->diff, u = 0, v = 0;
+    const int cshift = DAALAENT_WSIZE - 16;
+    const int cval = diff >> cshift;
+    av_assert0(diff >> cshift < range); /* Probably the most important assert */
+    if (type == CDF_UNSCALED) {
+        p_tot = cdf[cdf_size - 1];
+        av_assert0(2 <= p_tot && p_tot <= 32768);
+        scale = 15 - daalaent_log2(p_tot - 1);
+        p_tot <<= scale;
+        av_assert0(p_tot <= range);
+        if (range - p_tot >= p_tot) {
+            p_tot <<= 1;
+            scale++;
+        }
+        d = range - p_tot;
+    } else if (type == CDF_Q15) {
+        av_assert0(cdf[cdf_size - 1] == 32768);
+        av_assert0(32768 <= range);
+        d = range - 32768;
+        p_tot = 32768;
+        scale = 0;
+    } else if (type == CDF_DYADIC) {
+        av_assert0(cdf[cdf_size - 1] == 1 << p_tot);
+        scale = 15 - p_tot;
+        av_assert0(32768 <= range);
+        d = range - 32768;
+        p_tot = 32768;
+    } else {
+        p_tot = cdf[cdf_size - 1];
+        av_assert0(16384 <= p_tot && p_tot <= 32768);
+        av_assert0(p_tot <= range);
+        scale = range - p_tot >= p_tot;
+        p_tot <<= scale;
+        d = range - p_tot;
+    }
+    g = DAALAENT_SAT(2*d, p_tot);
+    lim = FFMAX(FFMAX(cval >> 1, cval - d), (2*cval + 1 - g)/3) >> scale;
+    for (v = cdf[ret]; v <= lim; v = cdf[++ret])
+        u = v;
+    u <<= scale;
+    v <<= scale;
+    u = u + FFMIN(u, g) + FFMIN(DAALAENT_SAT(u, g) >> 1, d);
+    v = v + FFMIN(v, g) + FFMIN(DAALAENT_SAT(v, g) >> 1, d);
+    range = v - u;
+    diff -= u << cshift;
+    daalaent_renormalize(e, diff, range);
+    return ret;
+}
+
+/*  Decodes raw bits from the bitstream, num ∈ [0, 25] */
+static inline ent_win daalaent_decode_bits(DaalaEntropy *e, int num)
+{
+    int avail = e->end_window_size;
+    ent_win ret, win = e->end_window;
+    if (avail < num) {
+        const uint8_t *erbuf = e->erbuf;
+        av_assert0(avail <= DAALAENT_WSIZE - 8);
+        do {
+            if (erbuf <= e->rbuf) {
+                e->eos_offset += DAALAENT_BIT_ABUNDANCE - avail;
+                avail = DAALAENT_BIT_ABUNDANCE;
+                break;
+            }
+            win |= (ent_win)*--erbuf << avail;
+            avail += 8;
+        } while (avail <= DAALAENT_WSIZE - 8);
+        e->erbuf = erbuf;
+    }
+    ret = win & ((1 << num) - 1);
+    win >>= num;
+    avail -= num;
+    e->end_window = win;
+    e->end_window_size = avail;
+    return ret;
+}
+
+/* Gets a single bit if !!cond and returns ±1 */
+#define daalaent_cphase(e, c) (!!(c) ? (1 - 2*daalaent_decode_bits(e, 1)) : 1)
+
+/* "+derf    | It was a hack for the screen coding wavelet tools." */
+/* "+jmspeex | Then you don't understand it." */
+static av_always_inline int daalaent_decode_unary(DaalaEntropy *e)
+{
+    int rval = 0;
+    for (; rval < DAALAENT_UNARY_MAX && !daalaent_decode_bits(e, 1); rval++);
+    return rval;
+}
+
+/* Decodes a uint from the bitstream, num ∈ [2, 2^29] */
+static inline ent_win daalaent_decode_uint(DaalaEntropy *e, ent_win num)
+{
+    av_assert0(num <= 1 << (25 + DAALAENT_UINT_BITS));
+    if (num > 1 << DAALAENT_UINT_BITS) {
+        int bit = daalaent_log2(--num) - DAALAENT_UINT_BITS;
+        int adr = (num >> bit) + 1;
+        ent_win t = daalaent_decode_cdf(e, DAALAENT_CDF_ACCESS(adr), adr,
+                                        0, CDF_Q15);
+        t = t << bit | daalaent_decode_bits(e, bit);
+        if (t <= num)
+            return t;
+        e->err = 1;
+        return num;
+    }
+    return daalaent_decode_cdf(e, DAALAENT_CDF_ACCESS(num), num, 0, CDF_Q15);
+}
+
+static inline int daalaent_decode_cdf_adapt(DaalaEntropy *e, DaalaCDF *c,
+                                            int cdf_offset, int num)
+{
+    int i;
+    ent_rng *cdf = &c->cdf[cdf_offset*c->y];
+    const int rval = daalaent_decode_cdf(e, cdf, num, 0, CDF_UNSCALED);
+    if (cdf[num - 1] + c->inc > 32767) {
+        for (i = 0; i < num; i++)
+            cdf[i] = (cdf[i] >> 1) + i + 1;
+    }
+    for (i = rval; i < num; i++)
+        cdf[i] += c->inc;
+    return rval;
+}
+
+/* "Special laplace decoder" */
+static inline int daalaent_decode_laplace(DaalaEntropy *e, unsigned int decay,
+                                          int max)
+{
+    const ent_rng *cdf;
+    int pos, sym, max_shift, shift = 0, p_shift = 0;
+    if (!max)
+        return 0;
+    while (((max >> shift) >= 15 || max == -1) && decay > 235) {
+        decay = (decay*decay + 128) >> 8;
+        shift++;
+    }
+    max_shift = max >> shift;
+    decay = FFMAX(FFMIN(decay, 254), 2);
+    cdf = ff_daalaent_cdf_exp_tab[(decay + 1) >> 1];
+    do {
+        uint8_t shift_bound = max_shift > 0 && max_shift < 15;
+        int cdf_size = shift_bound ? max_shift + 1 : 16;
+        int cdf_type = shift_bound ? CDF_UNSCALED : CDF_Q15;
+        sym = daalaent_decode_cdf(e, cdf, cdf_size, 0, cdf_type);
+        p_shift += sym;
+        max_shift -= 15;
+    } while (sym >= 15 && max_shift);
+    pos = shift ? (p_shift << shift) + daalaent_decode_bits(e, shift) : p_shift;
+    av_assert0(pos >> shift <= max >> shift || max == -1);
+    if (max != -1 && pos > max) {
+        pos = max;
+        e->err = 1;
+    }
+    return pos;
+}
+
+/* Used by the vector and delta laplace decoding functions for PVQ */
+static inline int daalaent_decode_laplace_pvq(DaalaEntropy *e, unsigned int exp_v,
+                                              int max_mod_v)
+{
+    int sym = 0, lsb = 0;
+    const int shift = FFMAX(daalaent_log2(exp_v) - 11, 0);
+    const int ex = (exp_v + (1 << shift >> 1)) >> shift;
+    const int maxval = (max_mod_v + (1 << shift >> 1)) >> shift;
+    /* The reference decoder uses snake oil DIVU optimization here */
+    const int decay = FFMIN(254, 256*ex/(ex + 256));
+    const int offset = ff_daalaent_laplace_offset[(decay + 1) >> 1];
+    if (maxval) {
+        ent_rng i, cdf[16];
+        for (i = 0; i < 16; i++)
+            cdf[i] = ff_daalaent_cdf_exp_tab[(decay + 1) >> 1][i] - offset;
+        sym = daalaent_decode_cdf(e, cdf, FFMIN(maxval + 1, 16), 0, CDF_UNSCALED);
+    }
+    if (shift) {
+        if (shift - !sym > 0)
+            lsb = daalaent_decode_bits(e, shift - !sym);
+        lsb -= (!!sym << (shift - 1));
+    }
+    if (sym == 15) /* Tail */
+        sym += daalaent_decode_laplace(e, decay, maxval - 15);
+    return (sym << shift) + lsb;
+}
+
+static inline void daalaent_decode_laplace_delta(DaalaEntropy *e, dctcoef *y,
+                                                 int n, int k, dctcoef *curr,
+                                                 const dctcoef *means)
+{
+    int i, k0 = k, k_left = k;
+    int prev = 0, sum_ex = 0, sum_c = 0, pos = 0;
+    int coef = 256*means[DAALAENT_PVQ_COUNT]/(1 + means[DAALAENT_PVQ_COUNT_EX]);
+    memset(y, 0, n*sizeof(dctcoef));
+    coef = FFMAX(coef, 1);
+    for (i = 0; i < k0; i++) {
+        int count;
+        if (!i) {
+            int decay;
+            int ex = coef*(n - prev)/k_left;
+            if (ex > 65280)
+                decay = 255;
+            else
+                decay = FFMIN(255, (int)((256*ex/(ex + 256) + (ex>>5)*ex/((n + 1)*(n - 1)*(n - 1)))));
+            count = daalaent_decode_laplace(e, decay, n - 1);
+        }
+        else
+            count = daalaent_decode_laplace_pvq(e, coef*(n - prev)/k_left, n - prev - 1);
+        sum_ex += 256*(n - prev);
+        sum_c += count*k_left;
+        pos += count;
+        av_assert0(pos < n);
+        y[pos] += daalaent_cphase(e, !y[pos]);
+        prev = pos;
+        k_left--;
+        if (!k_left)
+            break;
+    }
+    if (k > 0) {
+        curr[DAALAENT_PVQ_COUNT] = 256*sum_c;
+        curr[DAALAENT_PVQ_COUNT_EX] = sum_ex;
+    }
+    else {
+        curr[DAALAENT_PVQ_COUNT] = -1;
+        curr[DAALAENT_PVQ_COUNT_EX] = 0;
+    }
+    curr[DAALAENT_PVQ_K] = 0;
+    curr[DAALAENT_PVQ_SUM_EX] = 0;
+}
+
+/* Decodes quantized coefficients from  the bitsteam */
+static inline void daalaent_decode_laplace_vector(DaalaEntropy *e, dctcoef *y,
+                                                  int n, int k, dctcoef *curr,
+                                                  const dctcoef *means)
+{
+    int i, exp_q8, mean_k_q8, mean_sum_ex_q8, sum_ex = 0, kn = k, ran_delta = 0;
+    if (k <= 1) {
+        daalaent_decode_laplace_delta(e, y, n, k, curr, means);
+        return;
+    }
+    if (!k) {
+        curr[DAALAENT_PVQ_COUNT] = DAALAENT_PVQ_NOVAL;
+        curr[DAALAENT_PVQ_COUNT_EX] = DAALAENT_PVQ_NOVAL;
+        curr[DAALAENT_PVQ_K] = 0;
+        curr[DAALAENT_PVQ_SUM_EX] = 0;
+        memset(y, 0, n*sizeof(dctcoef));
+        return;
+    }
+    mean_k_q8 = means[DAALAENT_PVQ_K];
+    mean_sum_ex_q8 = means[DAALAENT_PVQ_SUM_EX];
+    if (mean_k_q8 < 1 << 23)
+        exp_q8 = 256*mean_k_q8/(1 + mean_sum_ex_q8);
+    else
+        exp_q8 = mean_k_q8/(1 + (mean_sum_ex_q8 >> 8));
+    for (i = 0; i < n; i++) {
+        int x, ex;
+        if (!kn)
+            break;
+        if (kn <= 1 && i != n - 1) {
+            daalaent_decode_laplace_delta(e, y + i, n - i, kn, curr, means);
+            ran_delta = 1;
+            i = n;
+            break;
+        }
+        ex = (2*exp_q8*kn + (n - i))/(2*(n - i));
+        if (ex > kn*256)
+            ex = kn*256;
+        sum_ex += (2*256*kn + (n - i))/(2*(n - i));
+        if (i != n - 1)
+            x = daalaent_decode_laplace_pvq(e, ex, kn);
+        else
+            x = kn;
+        y[i] = x*daalaent_cphase(e, x);
+        kn -= abs(x);
+    }
+    memset(&y[i], 0, (n - i)*sizeof(dctcoef)); /* Zero the rest */
+    if (!ran_delta) {
+        curr[DAALAENT_PVQ_COUNT] = DAALAENT_PVQ_NOVAL;
+        curr[DAALAENT_PVQ_COUNT_EX] = DAALAENT_PVQ_NOVAL;
+    }
+    curr[DAALAENT_PVQ_K] = k - kn;
+    curr[DAALAENT_PVQ_SUM_EX] = sum_ex;
+}
+
+/* Expectation value is in Q16 */
+static inline int daalaent_decode_generic(DaalaEntropy *e, DaalaCDF *c, int *ex,
+                                          int max, int integrate)
+{
+    int rval, lsb = 0, log_ex = daalaent_log_ex(*ex);
+    const int shift = FFMAX(0, (log_ex - 5) >> 1);
+    const int id = FFMIN(DAALAENT_MODEL_TAB - 1, log_ex);
+    const int ms = (max + (1 << shift >> 1)) >> shift;
+    int xs = (max == -1) ? 16 : FFMIN(ms + 1, 16);
+    ent_rng *cdf = &c->cdf[id*c->y];
+    if (!max)
+        return 0;
+    if ((xs = daalaent_decode_cdf(e, cdf, xs, 0, CDF_UNSCALED)) == 15) {
+        int g = ((2*(*ex) >> 8) + (1 << shift >> 1)) >> shift;
+        ent_win decay = FFMAX(2, FFMIN(254, 256*g/(g + 256)));
+        xs += daalaent_decode_laplace(e, decay, (max == -1) ? -1 : ms - 15);
+    }
+    if (shift) {
+        if (shift > !xs)
+            lsb = daalaent_decode_bits(e, shift - !xs);
+        lsb -= !!xs << (shift - 1);
+    }
+    rval = (xs << shift) + lsb;
+    daalaent_exp_model_update(c, ex, rval, xs, id, integrate);
+    return rval;
+}
+
+static inline void daalaent_decode_init(DaalaEntropy *e, const uint8_t *buf,
+                                        int buf_size)
+{
+    e->rbuf = buf;
+    e->erbuf = buf + buf_size;
+    e->buf = buf;
+    e->ebuf = buf + buf_size;
+    e->err = 0;
+    e->diff  = 0;
+    e->range = 32768;
+    e->count = -15;
+    e->eos_offset = 18 - DAALAENT_WSIZE;
+    e->end_window = 0;
+    e->end_window_size = 0;
+    daalaent_fillup(e);
+}
+
+static av_always_inline void daalaent_cdf_reset(DaalaCDF *s)
+{
+    int i, j;
+    for (i = 0; i < s->x; i++)
+        for (j = 0; j < s->y; j++)
+            s->cdf[i*s->y + j] = s->inc_g*(j + s->gen_mod) + s->fir;
+}
+
+static inline int daalaent_cdf_alloc(DaalaCDF *s, int x, int y, int inc, int fir,
+                                     uint8_t inc_shift, uint8_t gen_mod)
+{
+    s->x = x;
+    s->y = y;
+    s->inc = inc;
+    s->gen_mod = gen_mod;
+    s->inc_g = s->inc >> inc_shift;
+    s->fir = !!fir || s->gen_mod ? fir : s->inc_g;
+    s->cdf = av_malloc(x*y*sizeof(ent_rng));
+    if (!s->cdf)
+        return 1;
+    return 0;
+}
+
+static av_always_inline void daalaent_cdf_free(DaalaCDF *s)
+{
+    if (!s)
+        return;
+    av_freep(&s->cdf);
+}
+
+/* Decodes the preamble at the start of every frame */
+static inline int daalaent_decode_frame_header(DaalaEntropy *e,
+                                               DaalaBitstreamHeader *h,
+                                               uint8_t planes)
+{
+    int i, j;
+    if (daalaent_decode_bool(e, 16384, 32768))
+        return 1;
+    h->key_frame = daalaent_decode_bool(e, 16384, 32768);
+    if (!h->key_frame) {
+        h->bipred = daalaent_decode_bool(e, 16384, 32768);
+        h->ref_num = 1 + daalaent_decode_uint(e, DAALA_MAX_REF_FRAMES);
+    } else {
+        h->ref_num = 0;
+    }
+    h->act_mask  = daalaent_decode_bool(e, 16384, 32768);
+    h->qm        = daalaent_decode_bool(e, 16384, 32768);
+    h->haar      = daalaent_decode_bool(e, 16384, 32768);
+    h->golden    = daalaent_decode_bool(e, 16384, 32768);
+    if (h->key_frame && planes) {
+        for (i = 0; i < planes; i++)
+            for (j = 0; j < DAALA_QM_SIZE; j++)
+                h->pvq_qm[i][j] = daalaent_decode_bits(e, 8);
+    }
+    return 0;
+}
+
+#endif /* AVCODEC_DAALAENTROPY_H */
diff --git a/libavcodec/daala_parser.c b/libavcodec/daala_parser.c
new file mode 100644
index 0000000..434e18f
--- /dev/null
+++ b/libavcodec/daala_parser.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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 "parser.h"
+#include "daala_entropy.h"
+
+static int parse(AVCodecParserContext *s,
+                 AVCodecContext *avctx,
+                 const uint8_t **poutbuf, int *poutbuf_size,
+                 const uint8_t *buf, int buf_size)
+{
+    DaalaEntropy e;
+    DaalaBitstreamHeader h;
+
+    daalaent_decode_init(&e, buf, buf_size);
+    daalaent_decode_frame_header(&e, &h, 0);
+
+    s->key_frame = h.key_frame;
+    s->pict_type = h.key_frame ? AV_PICTURE_TYPE_I : !h.bipred ?
+                                 AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B;
+
+    *poutbuf      = buf;
+    *poutbuf_size = buf_size;
+
+    return buf_size;
+}
+
+AVCodecParser ff_daala_parser = {
+    .codec_ids    = { AV_CODEC_ID_DAALA },
+    .parser_parse = parse,
+};
diff --git a/libavcodec/daala_pvq.h b/libavcodec/daala_pvq.h
new file mode 100644
index 0000000..d44e7e2
--- /dev/null
+++ b/libavcodec/daala_pvq.h
@@ -0,0 +1,385 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALAPVQ_H
+#define AVCODEC_DAALAPVQ_H
+
+#include "daala.h"
+#include "daala_entropy.h"
+
+#define DAALAPVQ_NUM_ADAPTS 4
+
+#define DAALAPVQ_SKIP_ZERO 1
+#define DAALAPVQ_SKIP_COPY 2
+#define DAALAPVQ_PARTITIONS_MAX 9
+
+#define DAALAPVQ_MAX_PART_SIZE   (DAALA_QM_BSIZE/2)
+#define DAALAPVQ_COMPAND_SCALE   (256 << DAALA_CSHIFT)
+#define DAALAPVQ_COMPAND_SCALE_1 (1.0f/DAALAPVQ_COMPAND_SCALE)
+
+/* PVQ Context struct */
+typedef struct DaalaPVQ {
+    uint8_t phase;
+    int nb_coeffs;
+    int size[DAALAPVQ_PARTITIONS_MAX];
+    int skip[DAALAPVQ_PARTITIONS_MAX];
+    int qmax[DAALAPVQ_PARTITIONS_MAX];
+    /* All of the above is set on every decode call to reduce total arguments */
+
+    /* Everything below is reset on every frame */
+    DaalaCDF pvqcodeword_cdf;
+    DaalaCDF pvqskip_cdf;
+    DaalaCDF pvqtheta_gain_cdf;
+    DaalaCDF pvqgain_ref_mcdf;
+    DaalaCDF pvqgain_noref_mcdf;
+    DaalaCDF pvqtheta_mcdf;
+    int pvqgain_ex[DAALA_MAX_PLANES][DAALA_NBSIZES][DAALAPVQ_PARTITIONS_MAX];
+    int pvqtheta_ex[DAALA_NBSIZES*DAALAPVQ_PARTITIONS_MAX];
+    int pvqadapt[2*DAALAPVQ_NUM_ADAPTS*DAALA_NBSIZES];
+
+    int16_t qmatrix[DAALA_QM_BUFFER_SIZE];
+    int16_t qmatrix_inv[DAALA_NBSIZES*2*DAALA_QM_BSIZE];
+} DaalaPVQ;
+
+/* Index for packed quantization matrices */
+static av_always_inline int daalapvq_get_qm_idx(enum DaalaBsize bsize, int band)
+{
+    return bsize*bsize + bsize + band - band/3;
+}
+
+/* Computes theta quantization range */
+static av_always_inline int daalapvq_calc_theta_quant(double gain, double beta)
+{
+    if (gain < 1.4f)
+        return 1;
+    return lrint((gain*M_PI)/(2.0f*beta));
+}
+
+/* Dequantizes the theta angle */
+static av_always_inline double daalapvq_dequant_theta(int t, int max)
+{
+    if (!max)
+        return 0;
+    return FFMIN(t, max - 1)*0.5f*M_PI/max;
+}
+
+static inline void daalapvq_householder_a(double *x, const double *r, int n)
+{
+    int i;
+    double projection = 0.0f, e = 0.0f;
+    for (i = 0; i < n; i++) {
+        e += r[i]*r[i];
+        projection += r[i]*x[i];
+    }
+    projection *= 2.0f/(1e-100 + e);
+    for (i = 0; i < n; i++)
+        x[i] -= r[i]*projection;
+}
+
+static inline int daalapvq_householder_c(double *r, int n, double gr, int *sign)
+{
+    int i, s, m = 0;
+    double maxr = 0.0f;
+    for (i = 0; i < n; i++) {
+        if (fabs(r[i]) > maxr) {
+            maxr = fabs(r[i]);
+            m = i;
+        }
+    }
+    s = r[m] > 0 ? 1 : -1;
+    r[m] += gr*s;
+    *sign = s;
+    return m;
+}
+
+static inline int daalapvq_decode_gain_interleaved(int x, int ref_gain)
+{
+    if (x < 2*ref_gain - 1) {
+        if (x & 1)
+            return ref_gain - 1 - (x >> 1);
+        else
+            return ref_gain + (x >> 1);
+    }
+    return x + 1;
+}
+
+static av_always_inline double daalapvq_gain_root(double g, int q0, double beta)
+{
+    if (beta == 1.0f)
+        return g/q0;
+    return DAALAPVQ_COMPAND_SCALE*pow(g*DAALAPVQ_COMPAND_SCALE_1, 1.0f/beta)/q0;
+}
+
+static inline double daalapvq_gain_raise(double cg, int q0, double beta)
+{
+    if (beta == 1.0f)
+        return cg*q0;
+    else if (beta == 1.5f) {
+        cg *= q0*DAALAPVQ_COMPAND_SCALE_1;
+        return DAALAPVQ_COMPAND_SCALE*cg*sqrt(cg);
+    }
+    return DAALAPVQ_COMPAND_SCALE*pow(cg*q0*DAALAPVQ_COMPAND_SCALE_1, beta);
+}
+
+static inline double daalapvq_compute_gain(dctcoef *x, int n, int q0, double *g,
+                                           double beta, const int16_t *qmatrix)
+{
+    int i;
+    double acc = 0.0f;
+    for (i = 0; i < n; i++) {
+        const double tmp = x[i]*(double)qmatrix[i]*DAALA_QM_SCALE_UNIT;
+        acc += tmp*tmp;
+    }
+    *g = sqrt(acc);
+    return daalapvq_gain_root(*g, q0, beta);
+}
+
+static inline int daalapvq_compute_k(double qcg, int itheta, double theta,
+                                     int has_ref, int n, double beta, int robust)
+{
+    if (!has_ref) {
+        if (!qcg)
+            return 0;
+        if (n == 15 && qcg == 1.0f && beta > 1.25f)
+            return 1;
+        else
+            return FFMAX(1, lrint((qcg - 0.2f)*sqrt((n+3)/2)/beta));
+    }
+    if (!itheta)
+        return 0;
+    if (robust)
+        return FFMAX(1, lrint((itheta - 0.2f)*sqrt((n + 2)/2)));
+    else
+        return FFMAX(1, lrint((qcg*sin(theta) - 0.2f)*sqrt((n + 2)/2)/beta));
+}
+
+
+static inline void daalapvq_synth(dctcoef *xcoeff, dctcoef *ypulse, dctcoef *ref,
+                                  int n, double gr, uint8_t ref_p, double gain,
+                                  double theta, const int16_t *qmatrix,
+                                  const int16_t *qmatrix_inv)
+{
+    int i, m, nn = n - ref_p, s = 0, yy = 0;
+    double scale, r[DAALAPVQ_MAX_PART_SIZE], x[DAALAPVQ_MAX_PART_SIZE];
+    if (ref_p) {
+        for (i = 0; i < n; i++)
+            r[i] = ref[i]*qmatrix[i]*DAALA_QM_SCALE_UNIT;
+    }
+    m = !ref_p ? 0 : daalapvq_householder_c(r, n, gr, &s);
+    for (i = 0; i < nn; i++)
+        yy += ypulse[i]*ypulse[i];
+    scale = !yy ? 0 : gain/sqrt(yy);
+    if (!ref_p) {
+        for (i = 0; i < n; i++)
+            xcoeff[i] = lrint((ypulse[i]*scale)*(qmatrix_inv[i]*DAALA_QM_INV_SCALE_UNIT));
+    } else {
+        scale *= sin(theta);
+        for (i = 0; i < m; i++)
+            x[i] = ypulse[i]*scale;
+        x[m] = -s*gain*cos(theta);
+        for (i = m; i < nn; i++)
+            x[i+1] = ypulse[i]*scale;
+        daalapvq_householder_a(x, r, n);
+        for (i = 0; i < n; i++)
+            xcoeff[i] = lrint(x[i]*qmatrix_inv[i]*DAALA_QM_INV_SCALE_UNIT);
+    }
+}
+
+static av_always_inline void daalapvq_adapt_shuffle(int *dst, int *src, int spd,
+                                                    int idx, int mul)
+{
+    if (src[idx] < 1)
+        return;
+    dst[idx+0] += (mul*src[idx+0] - dst[idx+0]) >> spd;
+    dst[idx+1] += (    src[idx+1] - dst[idx+1]) >> spd;
+}
+
+static inline void daalapvq_decode_codeword(DaalaEntropy *e, DaalaPVQ *pvq,
+                                            dctcoef *y, int n, int k, uint8_t has_ref,
+                                            enum DaalaBsize bsize)
+{
+    int pos, adapt_curr[DAALAPVQ_NUM_ADAPTS] = {0};
+    int *pvq_adapt = pvq->pvqadapt + 4*(2*bsize + !has_ref);
+    const int cdf_id = 2*(n == 15) + !!has_ref, spd = 5;
+    if (k == 1 && n < 16) {
+        pos = daalaent_decode_cdf_adapt(e, &pvq->pvqcodeword_cdf, cdf_id, n - !!has_ref);
+        memset(y, 0, n*sizeof(dctcoef));
+        y[pos] = daalaent_cphase(e, 1);
+    } else {
+        daalaent_decode_laplace_vector(e, y, n - !!has_ref, k, adapt_curr, pvq_adapt);
+        daalapvq_adapt_shuffle(pvq_adapt, adapt_curr, spd, DAALAENT_PVQ_K,   256);
+        daalapvq_adapt_shuffle(pvq_adapt, adapt_curr, spd, DAALAENT_PVQ_COUNT, 1);
+    }
+}
+
+static inline void daalapvq_decode_vector(DaalaEntropy *e, DaalaPVQ *pvq,
+                                          dctcoef *out, dctcoef *ref,
+                                          const double beta,
+                                          uint8_t key_frame, int p,
+                                          uint8_t *skip_rest,
+                                          uint8_t has_err, int band_idx,
+                                          int qm_off, enum DaalaBsize bsize)
+{
+    int i, k;
+    int qg = 0, skip = 0, itheta = (!!key_frame), has_ref = !key_frame;
+    double qcg, gain, theta = 0.0f, gr = 0.0f, gain_off = 0.0f;
+    dctcoef tmp[DAALAPVQ_MAX_PART_SIZE] = {0};
+
+    const int robust = has_err || key_frame;
+    const int band_len = pvq->size[band_idx];
+    const int16_t *qmatrix = &pvq->qmatrix[qm_off];
+    const int16_t *qmatrix_inv = &pvq->qmatrix_inv[qm_off];
+
+    if (!skip_rest[(band_idx + 2) % 3]) {
+        int iloc = (!!p)*DAALA_NBSIZES*DAALAPVQ_PARTITIONS_MAX + bsize*DAALAPVQ_PARTITIONS_MAX + band_idx;
+        i = daalaent_decode_cdf_adapt(e, &pvq->pvqtheta_gain_cdf, iloc, 8 + 7*pvq->skip[band_idx]);
+        if (!key_frame && i >= 10)
+            i++;
+        if (key_frame && i >= 8)
+            i++;
+        if (i >= 8) {
+            i -= 8;
+            skip_rest[0] = skip_rest[1] = skip_rest[2] = 1;
+        }
+        qg = i & 1;
+        itheta = (i >> 1) - 1;
+        has_ref = !(itheta == -1);
+    }
+    if (qg) {
+        int *ex = pvq->pvqgain_ex[p][bsize] + band_idx, ex_tmp = *ex;
+        DaalaCDF *mcdf = has_ref ? &pvq->pvqgain_ref_mcdf : &pvq->pvqgain_noref_mcdf;
+        qg = 1 + daalaent_decode_generic(e, mcdf, &ex_tmp, -1, 2);
+        *ex += ((qg << 16) - *ex) >> 2;
+    }
+    if (has_ref) {
+        int icgr, max_theta;
+        const int cfl_enabled = p && key_frame;
+        double cgr = daalapvq_compute_gain(ref, band_len, pvq->qmax[band_idx],
+                                           &gr, beta, qmatrix);
+        if (cfl_enabled)
+            cgr = 1.0f;
+        icgr = lrint(cgr);
+        qg = daalapvq_decode_gain_interleaved(qg, icgr + !key_frame) - !key_frame;
+        if (!qg && !key_frame)
+            skip = (icgr ? DAALAPVQ_SKIP_ZERO : DAALAPVQ_SKIP_COPY);
+        if (qg == icgr && !itheta && !cfl_enabled)
+            skip = DAALAPVQ_SKIP_COPY;
+        gain_off = cgr - icgr;
+        qcg = qg + gain_off;
+        max_theta = daalapvq_calc_theta_quant(qcg, beta);
+        if (itheta > 1 && (robust || max_theta > 3)) {
+            const int off = bsize*DAALAPVQ_PARTITIONS_MAX + band_idx;
+            int ex_tmp = pvq->pvqtheta_ex[off];
+            itheta = 2 + daalaent_decode_generic(e, &pvq->pvqtheta_mcdf, &ex_tmp,
+                                                 robust ? -1 : max_theta - 3, 2);
+            pvq->pvqtheta_ex[off] += ((itheta << 16) - pvq->pvqtheta_ex[off]) >> 2;
+        }
+        theta = daalapvq_dequant_theta(itheta, max_theta);
+    } else {
+        itheta = 0;
+        qg += !key_frame;
+        qcg = qg;
+        skip = !qg ? DAALAPVQ_SKIP_ZERO : skip;
+    }
+
+    k = daalapvq_compute_k(qcg, itheta, theta, has_ref, band_len, beta, robust);
+    if (k)
+        daalapvq_decode_codeword(e, pvq, tmp, band_len, k, has_ref, bsize);
+
+    if (pvq->phase && has_ref) {
+        const int8_t phase = daalaent_cphase(e, 1);
+        for (i = 0; i < pvq->nb_coeffs; i++)
+            ref[i] *= phase;
+        pvq->phase = 0;
+    }
+
+    if (skip) {
+        if (skip == DAALAPVQ_SKIP_COPY)
+            memcpy(out, ref, band_len*sizeof(dctcoef));
+        else
+            memset(out, 0, band_len*sizeof(dctcoef));
+        return;
+    }
+    gain = daalapvq_gain_raise(qg + gain_off, pvq->qmax[band_idx], beta);
+    daalapvq_synth(out, tmp, ref, band_len, gr, has_ref, gain, theta, qmatrix,
+                   qmatrix_inv);
+}
+
+/* q: quantizer, qm = bitstream_header->pvq_qm[p] */
+static inline void daalapvq_decode(DaalaEntropy *e, DaalaPVQ *pvq,
+                                   DaalaBitstreamHeader *b, dctcoef *ref,
+                                   dctcoef *out, int q, uint8_t *pvq_qm, uint8_t p,
+                                   enum DaalaBsize bsize, const double *beta,
+                                   int qm_off, int bskip)
+{
+    int i, j;
+    int bands = ff_daala_layouts[bsize].band_offset_size;
+    const int *off = ff_daala_layouts[bsize].band_offset;
+    uint8_t skip_rest[3] = {0};
+    out[0] = bskip & 1;
+    if (!(bskip >> 1)) {
+        for (i = 1; i < 1 << (2*bsize + 4); i++)
+            out[i] = b->key_frame ? 0 : ref[i];
+    } else {
+        pvq->nb_coeffs = off[bands];
+        pvq->phase = p && b->key_frame;
+        for (i = 0; i < bands; i++) {
+            pvq->size[i] = off[i+1] - off[i];
+            pvq->skip[i] = (!i && (i < bands - 1));
+            pvq->qmax[i] = FFMAX(1, q*pvq_qm[daalapvq_get_qm_idx(bsize, i + 1)] >> 4);
+        }
+        for (i = 0; i < bands; i++) {
+            daalapvq_decode_vector(e, pvq, out+off[i], ref+off[i], beta[i], b->key_frame,
+                                   p, skip_rest, 1, i, qm_off + off[i], bsize);
+            if (!i && !skip_rest[0] && bsize) {
+                int sdir = daalaent_decode_cdf_adapt(e, &pvq->pvqskip_cdf,
+                                                     !!p + 2*(bsize - 1), 7);
+                for (j = 0; j < 3; j++)
+                    skip_rest[j] = !!(sdir & (1 << j));
+            }
+        }
+    }
+}
+
+#endif /* AVCODEC_DAALAPVQ_H */
diff --git a/libavcodec/daala_utils.h b/libavcodec/daala_utils.h
new file mode 100644
index 0000000..4295457
--- /dev/null
+++ b/libavcodec/daala_utils.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALAUTIL_H
+#define AVCODEC_DAALAUTIL_H
+
+#include "daala.h"
+
+#define DAALA_BSIZE8x8(arr, bstride, bx, by) ((arr)[(by)*(bstride) + (bx)])
+#define DAALA_BSIZE4x4(arr, bstride, bx, by) DAALA_BSIZE8x8(arr, bstride, (bx) >> 1, (by) >> 1)
+
+static av_always_inline int daala_get_qm_idx(enum DaalaBsize bsize, int b)
+{
+    return bsize*(bsize + 1) + b - b/3;
+}
+
+static av_always_inline int daala_qm_get_offset(enum DaalaBsize bsize, int dec)
+{
+    return DAALA_QM_BSIZE*(bsize*2 + dec);
+}
+
+#define BAND_FROM_RASTER(type)                                                 \
+static inline void daala_band_from_raster_##type(const DaalaBandLayout *layout,\
+                                                 type *dst, int stride,        \
+                                                 const type *src)              \
+{                                                                              \
+    int i;                                                                     \
+    for (i = 0; i < layout->tab_size; i++) {                                   \
+        dst[i] = src[layout->tab[i][1]*stride + layout->tab[i][0]];            \
+    }                                                                          \
+}
+
+#define RASTER_FROM_BAND(type)                                                 \
+static inline void daala_raster_from_band_##type(const DaalaBandLayout *layout,\
+                                                 type *dst, int stride,        \
+                                                 const type *src)              \
+{                                                                              \
+    int i;                                                                     \
+    for (i = 0; i < layout->tab_size; i++) {                                   \
+        dst[layout->tab[i][1]*stride + layout->tab[i][0]] = src[i];            \
+    }                                                                          \
+}
+
+BAND_FROM_RASTER(int16_t)
+BAND_FROM_RASTER(int32_t)
+RASTER_FROM_BAND(int16_t)
+RASTER_FROM_BAND(int32_t)
+
+#define RASTER_TO_CODING(type)                                                 \
+    static inline void daala_raster_to_coding_##type(type *dst, int n,         \
+                                                     const type *src,          \
+                                                     int stride)               \
+{                                                                              \
+    enum DaalaBsize bs;                                                        \
+    daala_band_from_raster_##type(&ff_daala_layouts[0], dst + 1, stride, src); \
+    for (bs = 1; bs < DAALA_NBSIZES; bs++) {                                   \
+        const type size = 1 << (DAALA_LOG_BSIZE0 + bs);                        \
+        const type offset = 1 << 2*(DAALA_LOG_BSIZE0 - 1 + bs);                \
+        if (n >= size) {                                                       \
+            daala_band_from_raster_##type(&ff_daala_layouts[bs], dst + offset, \
+                                          stride, src);                        \
+        }                                                                      \
+    }                                                                          \
+    dst[0] = src[0];                                                           \
+}
+
+#define CODING_TO_RASTER(type)                                                 \
+    static inline void daala_coding_to_raster_##type(type *dst, int stride,    \
+                                                     const type *src,          \
+                                                     int n)                    \
+{                                                                              \
+    enum DaalaBsize bs;                                                        \
+    daala_raster_from_band_##type(&ff_daala_layouts[0], dst, stride, src + 1); \
+    for (bs = 1; bs < DAALA_NBSIZES; bs++) {                                   \
+        const int size = 1 << (DAALA_LOG_BSIZE0 + bs);                         \
+        const int offset = 1 << 2*(DAALA_LOG_BSIZE0 - 1 + bs);                 \
+        if (n >= size) {                                                       \
+            daala_raster_from_band_##type(&ff_daala_layouts[bs], dst, stride,  \
+                                           src + offset);                      \
+        }                                                                      \
+    }                                                                          \
+    dst[0] = src[0];                                                           \
+}
+
+RASTER_TO_CODING(int16_t)
+RASTER_TO_CODING(int32_t)
+CODING_TO_RASTER(int16_t)
+CODING_TO_RASTER(int32_t)
+
+static inline void daala_raster_to_coding(dctcoef *dst, int n,
+                                          const dctcoef *src, int stride)
+{
+    daala_raster_to_coding_int32_t(dst, n, src, stride);
+}
+
+static inline void daala_coding_to_raster(dctcoef *dst, int stride,
+                                          const dctcoef *src, int n)
+{
+    daala_coding_to_raster_int32_t(dst, stride, src, n);
+}
+
+static inline void daala_init_qmatrix(int16_t *qmatrix, int16_t *qmatrix_inv,
+                                      int qm_idx)
+{
+    int i, j ,dec;
+    int16_t tmp[DAALA_QM_BSIZE] = {0}, tmp_inv[DAALA_QM_BSIZE] = {0};
+    const uint8_t *qm_mode = ff_daala_qmatrices[av_clip(qm_idx, 0, ff_daala_qmatrices_num)];
+    enum DaalaBsize bsize;
+    for (bsize = 0; bsize < DAALA_NBSIZES; bsize++) {
+        for (dec = 0; dec < 2; dec++) {
+            const int off = daala_qm_get_offset(bsize, dec);
+            int16_t *qm = qmatrix + off;
+            int16_t *qm_inv = qmatrix_inv + off;
+            const double *qm_basis = ff_daala_basis_qm_mag[dec][bsize];
+            for (i = 0; i < 4 << bsize; i++) {
+                for (j = 0; j < 4 << bsize; j++) {
+                    double val;
+                    double mag = 1.0f;
+                    if (i || j) {
+                        mag = qm_basis[i]*qm_basis[j];
+                        mag /= 0.0625f*qm_mode[(i << 1 >> bsize)*8 + (j << 1 >> bsize)];
+                    }
+                    val = FFMIN((double)DAALA_QM_SCALE_MAX, round(mag*DAALA_QM_SCALE));
+                    tmp[i*(4 << bsize) + j] = (int16_t)val;
+                    val = round(DAALA_QM_SCALE*DAALA_QM_INV_SCALE/val);
+                    tmp_inv[i*(4 << bsize) + j] = (int16_t)val;
+                }
+            }
+            daala_raster_to_coding_int16_t(qm,     4 << bsize, tmp,     4 << bsize);
+            daala_raster_to_coding_int16_t(qm_inv, 4 << bsize, tmp_inv, 4 << bsize);
+        }
+    }
+}
+
+static inline void daala_safe_free_2d_array(void **arr, int x)
+{
+    int i;
+    if (!arr)
+        return;
+    for (i = 0; i < x; i++)
+        av_free(arr[i]);
+    av_freep(&arr);
+}
+#define DAALA_FREE_2D_ARRAY(arr, xlen)\
+    daala_safe_free_2d_array((void **)arr, xlen);
+
+/* Will free any successfull allocations before the failed one */
+static inline void **daala_safe_alloc_2d_array(int x, int y, unsigned int vsize)
+{
+    int i;
+    void **arr = av_calloc(x, sizeof(void *));
+    if (!arr)
+        return NULL;
+    for (i = 0; i < x; i++) {
+        arr[i] = av_calloc(y, vsize);
+        if (!arr[i]) {
+            if (i > 0)
+                DAALA_FREE_2D_ARRAY(arr, i);
+            return NULL;
+        }
+    }
+    return arr;
+}
+#define DAALA_ALLOC_2D_ARRAY_GOTO(arr, xlen, ylen, vtype, label)\
+    if (!(arr = (vtype **)daala_safe_alloc_2d_array(xlen, ylen, sizeof(vtype)))) goto label;
+
+static inline void daala_safe_free_static_2d_array(void **arr[], int elem, int x)
+{
+    int i;
+    for (i = 0; i < elem; i++)
+        DAALA_FREE_2D_ARRAY(arr[i], x);
+}
+#define DAALA_FREE_STATIC_2D_ARRAY(arr, elem, xlen)\
+    daala_safe_free_static_2d_array((void ***)arr, elem, xlen);
+
+static inline int daala_safe_alloc_static_2d_array(void **arr[], int elem, int x,
+                                              int y, unsigned int vsize)
+{
+    int i;
+    for (i = 0; i < elem; i++) {
+        arr[i] = daala_safe_alloc_2d_array(x, y, vsize);
+        if (!arr[i]) {
+            if (i > 0)
+                DAALA_FREE_STATIC_2D_ARRAY(&arr[i], i, x);
+            return 1;
+        }
+    }
+    return 0;
+}
+#define DAALA_ALLOC_STATIC_2D_ARRAY_GOTO(arr, elem, xlen, ylen, vtype, label)\
+    if (daala_safe_alloc_static_2d_array((void ***)arr, elem, xlen, ylen, sizeof(vtype))) goto label;
+
+#endif /* AVCODEC_DAALAUTIL_H */
diff --git a/libavcodec/daaladec.c b/libavcodec/daaladec.c
new file mode 100644
index 0000000..1beab11
--- /dev/null
+++ b/libavcodec/daaladec.c
@@ -0,0 +1,810 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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 "daala.h"
+#include "avcodec.h"
+#include "get_bits.h"
+#include "bytestream.h"
+#include "internal.h"
+#include "libavutil/pixdesc.h"
+
+#include "daalatab.h"
+#include "daala_entropy.h"
+#include "daala_utils.h"
+#include "daala_pvq.h"
+#include "daaladsp.h"
+
+#define DERING_SKIP 255
+
+typedef struct DaalaContext {
+    DaalaEntropy e;
+    DaalaPVQ pvq;
+    DaalaDSP dsp;
+    DaalaBitstreamHeader h;
+
+    /* Full precision references flag */
+    int fpr;
+
+    /* Quantization matrix cache */
+    int last_qm;
+    int quantizer[DAALA_MAX_PLANES];
+
+    /* Picture constants */
+    const struct DaalaPixFmts *fmt;
+    int width, height;                       /* Padded avctx->width/height    */
+    int sbn_x, sbn_y;                        /* Number of x and y superblocks */
+
+    /* Cumulative distribution functions */
+    DaalaCDF skip_cdf;
+    DaalaCDF dering_cdf;
+    DaalaCDF q_scale_cdf;
+    DaalaCDF haar_coef_cdf;                  /* Split coef Haar CDF           */
+    DaalaCDF haar_split_cdf;                 /* Tree Splitting Haar CDF       */
+    DaalaCDF haar_bit_cdf;                   /* Bitstream Haar CDF            */
+    DaalaCDF haar_dc_mcdf[DAALA_MAX_PLANES]; /* Haar DC lvl. CDF (gen. model) */
+
+    /* Expectation values for MCDFs */
+    int haar_sb_ex[DAALA_MAX_PLANES];
+    int haar_dc_ex[DAALA_MAX_PLANES][DAALA_NBSIZES][3];
+
+    /* Block sizes array */
+    enum DaalaBsize *bsizes;
+    int bsizes_stride;
+
+    /* Buffers */
+    dctcoef *lcoef; /* Temporary resampled CfL coefficients */
+    dctcoef *dcoef[DAALA_MAX_PLANES];
+    dctcoef *ccoef[DAALA_MAX_PLANES];
+    dctcoef **haar_dc_buf[DAALA_MAX_PLANES]; /* #planes by sbn_x by sbn_y big */
+
+    uint8_t **dering;                        /* 2D array, sbn_x by sbn_y big  */
+    uint8_t **q_scale;
+} DaalaContext;
+
+/* Sets the AVFrame type */
+static av_always_inline void set_frame_type(DaalaBitstreamHeader *b, AVFrame *frame)
+{
+    frame->key_frame = b->key_frame;
+    frame->pict_type = frame->key_frame ? AV_PICTURE_TYPE_I : !b->bipred ?
+                                          AV_PICTURE_TYPE_P : AV_PICTURE_TYPE_B;
+}
+
+static const struct DaalaPixFmts *find_pix_fmt(enum AVPixelFormat fmt)
+{
+    int i;
+    for (i = 0; i < ff_daala_valid_formats_num ; i++)
+        if (ff_daala_valid_formats[i].fmt == fmt)
+            return &ff_daala_valid_formats[i];
+    return NULL;
+}
+
+/* Fetch motion vectors */
+static void get_motion_vectors(DaalaContext *s)
+{
+    if (s->h.key_frame)
+        return;
+}
+
+/* Fetch and decode per plane quantizers */
+static void get_plane_quantizers(DaalaContext *s)
+{
+    int i;
+    for (i = 0; i < s->fmt->planes; i++) {
+        int qcode = daalaent_decode_uint(&s->e, ff_daala_quant_codemap_size);
+        if (!qcode) {
+            s->quantizer[i] = 0;
+            continue;
+        }
+        s->quantizer[i] = qcode < ff_daala_quant_codemap_size ?
+            (ff_daala_quant_codemap[qcode] << DAALA_CSHIFT >> 4) :
+            (ff_daala_quant_codemap[ff_daala_quant_codemap_size-1] << DAALA_CSHIFT >> 4);
+    }
+}
+
+typedef struct HaarGradient {
+    int x, y;
+} HaarGradient;
+
+#define CALC_Q_DC(p) \
+    (s->quantizer[p]*s->h.pvq_qm[p][daala_get_qm_idx(DAALA_NBSIZES-1, 0)] >> 4)
+
+/* Get DC level */
+static void get_haar_dc_sb(DaalaContext *s, HaarGradient *g, dctcoef *d,
+                           int x, int y, uint8_t p, uint8_t lim_pass)
+{
+    int q, q_dc;
+    int xdec = s->fmt->dec[p][0];
+    const int aw = s->width >> xdec;
+    const int ln = DAALA_LOG_BSIZE_MAX - xdec;
+    dctcoef dc_pred = 0, **dc_buf = s->haar_dc_buf[p];
+    if (!s->quantizer[p])
+        q_dc = 1;
+    else
+        q_dc = FFMAX(1, CALC_Q_DC(p));
+    if (x && y) {
+        if (lim_pass) {
+            dc_pred = 22*dc_buf[x-1][y-0] -  9*dc_buf[x-1][y-1] +
+                      15*dc_buf[x+0][y-1] +  4*dc_buf[x+1][y-1];
+        } else {
+            dc_pred = 23*dc_buf[x-1][y-0] - 10*dc_buf[x-1][y-1] +
+                      19*dc_buf[x-0][y-1];
+        }
+        dc_pred = (dc_pred + 16) >> 5;
+    } else {
+        dc_pred += x > 0 ? dc_buf[x-1][y-0] : 0;
+        dc_pred += y > 0 ? dc_buf[x-0][y-1] : 0;
+    }
+    q = daalaent_decode_generic(&s->e, &s->haar_dc_mcdf[p], &s->haar_sb_ex[p], -1, 2);
+    q *= daalaent_cphase(&s->e, q);
+    q = q*q_dc + dc_pred;
+    d[(y << ln)*aw + (x << ln)] = q;
+    dc_buf[x][y] = q;
+    g->x = x ? dc_buf[x-1][y-0] - q : g->x;
+    g->y = y ? dc_buf[x-0][y-1] - q : g->y;
+}
+
+/* Get DC level for sub-blocks */
+static void get_haar_dc_lvl(DaalaContext *s, HaarGradient *g, dctcoef *d,
+                            int x, int y, uint8_t p, enum DaalaBsize bsize)
+{
+    int i, q_dc, q_ac[2];
+    int xdec = s->fmt->dec[p][0];
+    const int aw = s->width >> xdec;
+    const int ln = bsize - xdec + 2;
+    dctcoef coef[4];
+    if (!s->quantizer[p]) {
+        q_dc = 1;
+        q_ac[0] = 1;
+        q_ac[1] = 1;
+    } else {
+        q_dc = FFMAX(1, CALC_Q_DC(p));
+        q_ac[0] = (q_dc*ff_daala_dc_comp[bsize - xdec][0] + 8) >> 4;
+        q_ac[1] = (q_dc*ff_daala_dc_comp[bsize - xdec][1] + 8) >> 4;
+    }
+    coef[0] = d[(y << ln)*aw + (x << ln)];
+    for (i = 1; i < 4; i++) {
+        int *ex = &s->haar_dc_ex[p][bsize][i-1];
+        int q = daalaent_decode_generic(&s->e, &s->haar_dc_mcdf[p], ex, -1, 2);
+        q *= daalaent_cphase(&s->e, q);
+        coef[i] = q*q_ac[i == 3];
+    }
+    g->x = coef[1] += g->x/5;
+    g->y = coef[2] += g->y/5;
+    daala_haar_kern(&coef[0], &coef[1], &coef[2], &coef[3]);
+    d[(y << ln)*aw + (x << ln)] = coef[0];
+    d[(y << ln)*aw + ((x + 1) << ln)] = coef[1];
+    d[((y + 1) << ln)*aw + (x << ln)] = coef[2];
+    d[((y + 1) << ln)*aw + ((x + 1) << ln)] = coef[3];
+}
+
+/* Quantizer scaling - decoded data not currently used */
+static av_unused inline void decode_quantizer_scaling(DaalaContext *s,
+                                                      int x, int y, uint8_t skip)
+{
+    int q_scale = 0;
+    if (!skip) {
+        int u = y > 0 ? s->q_scale[x][y-1] : 0;
+        int l = x > 0 ? s->q_scale[x-1][y] : 0;
+        q_scale = daalaent_decode_cdf_adapt(&s->e, &s->q_scale_cdf, u + l*4, 4);
+    }
+    s->q_scale[x][y] = q_scale;
+}
+
+static void daala_calc_prediction(DaalaContext *s, dctcoef *pred, const dctcoef *d,
+                                  int x, int y, uint8_t p, enum DaalaBsize bsize)
+{
+    int n = 1 << (bsize + DAALA_LOG_BSIZE0);
+    int aw = s->width >> s->fmt->dec[p][0];
+    int off = ((y << DAALA_LOG_BSIZE0))*aw + (x << DAALA_LOG_BSIZE0);
+    if (s->h.key_frame) {
+        if (!p || s->h.haar) {
+            memset(pred, 0, n*n*sizeof(dctcoef));
+            if (!p && !s->h.haar && s->dsp.intrapred) {
+                s->dsp.intrapred((uint8_t *)pred, (uint8_t *)&d[off], aw, x, y,
+                                 s->bsizes, s->bsizes_stride, bsize);
+            }
+        } else {
+            for (y = 0; y < n; y++) {
+                for (x = 0; x < n; x++) {
+                    pred[n*y + x] = s->lcoef[n*y + x];
+                }
+            }
+        }
+    } else {
+        /* Copy from mv coeffs */
+    }
+}
+
+static inline int decode_haar_coeff_tree_split(DaalaContext *s, int sum, int ctx,
+                                               uint8_t coef_split)
+{
+    int a = 0, shift, offset;
+    DaalaCDF *cdf = coef_split ? &s->haar_coef_cdf : &s->haar_split_cdf;
+    if (!sum)
+        return 0;
+    if ((shift = FFMAX(0, daalaent_log2(sum) - 4)))
+        a = daalaent_decode_bits(&s->e, shift);
+    if (coef_split)
+        offset = 15*ctx + (sum >> shift) - 1;
+    else
+        offset = 15*(2*ctx + FFMIN(shift, 1)) + (sum >> shift) - 1;
+    a += daalaent_decode_cdf_adapt(&s->e, cdf, offset,
+                                   (sum >> shift) + 1) << shift;
+    if (a > sum) {
+        a = sum;
+        s->e.err = 1;
+    }
+    return a;
+}
+
+static void decode_tree_sum(DaalaContext *s, dctcoef *pred, int x, int y,
+                            dctcoef sum_t, const int shift, const int dir)
+{
+    dctcoef c_sum, t_sum, sub[2][2], n = 1 << shift;
+    const int offset = dir + 3*(daalaent_log2(FFMAX(x,y)) - 1);
+    if (!sum_t)
+        return;
+    pred[y*n + x] = decode_haar_coeff_tree_split(s, sum_t, offset, 1);
+    if ((c_sum = sum_t - pred[y*n + x])) {
+        uint32_t *ele_1 = &sub[!!dir][!dir], *ele_2 = &sub[!dir][!!dir];
+        t_sum = decode_haar_coeff_tree_split(s, c_sum, !!dir, 0);
+        sub[0][0] = decode_haar_coeff_tree_split(s, t_sum, 2, 0);
+        *ele_1 = t_sum - sub[0][0];
+        *ele_2 = decode_haar_coeff_tree_split(s, c_sum - t_sum, 2, 0);
+        sub[1][1] = c_sum - t_sum - *ele_2;
+    } else {
+        memset(&sub[0][0], 0, 4*sizeof(dctcoef));
+    }
+    if (4*x < n && 4*y < n) {
+        decode_tree_sum(s, pred, 2*x,     2*y,     sub[0][0], shift, dir);
+        decode_tree_sum(s, pred, 2*x + 1, 2*y,     sub[0][1], shift, dir);
+        decode_tree_sum(s, pred, 2*x,     2*y + 1, sub[1][0], shift, dir);
+        decode_tree_sum(s, pred, 2*x + 1, 2*y + 1, sub[1][1], shift, dir);
+        return;
+    }
+    pred[2*y*n + 2*x] = sub[0][0];
+    pred[2*y*n + 2*x + 1] = sub[0][1];
+    pred[(2*y + 1)*n + 2*x] = sub[1][0];
+    pred[(2*y + 1)*n + 2*x + 1] = sub[1][1];
+}
+
+/* Haar block decoding and transform */
+static void decode_block_haar(DaalaContext *s, int x, int y, uint8_t p,
+                              enum DaalaBsize bsize)
+{
+    int i, j, k, l, n = 1 << (bsize + 2);
+    const int dx = x << bsize, dy = y << bsize;
+    const int aw = s->width >> s->fmt->dec[p][0];
+    const int boffset = (dy << 2)*aw + (dx << 2);
+
+    dctcoef tree[4][4];
+    dctcoef pred[DAALA_BSIZE_MAX*DAALA_BSIZE_MAX];
+    dctcoef tpred[DAALA_BSIZE_MAX*DAALA_BSIZE_MAX];
+
+    daala_calc_prediction(s, pred, s->dcoef[p], dx, dy, p, bsize);
+    memcpy(tpred, pred, n*n*sizeof(dctcoef));
+
+    bsize += 2;
+
+    tree[0][0] = daalaent_decode_cdf_adapt(&s->e, &s->haar_bit_cdf, p, 16);
+    if (tree[0][0] == 15)
+        tree[0][0] += daalaent_decode_unary(&s->e);
+
+    if (tree[0][0] > 24) {
+        s->e.err = 1;
+        return;
+    } else if (tree[0][0] > 1) {
+        int tmp = daalaent_decode_bits(&s->e, tree[0][0] - 1);
+        tree[0][0] = (1 << (tree[0][0] - 1)) | tmp;
+    }
+
+    tree[1][1] = decode_haar_coeff_tree_split(s, tree[0][0],              3, 0);
+    tree[0][1] = decode_haar_coeff_tree_split(s, tree[0][0] - tree[1][1], 4, 0);
+    tree[1][0] = tree[0][0] - tree[1][1] - tree[0][1];
+
+    decode_tree_sum(s, pred, 1, 0, tree[0][1], bsize, 0);
+    decode_tree_sum(s, pred, 0, 1, tree[1][0], bsize, 1);
+    decode_tree_sum(s, pred, 1, 1, tree[1][1], bsize, 2);
+
+    for (i = 0; i < n; i++) {
+        for (j = (i == 0); j < n; j++)
+            pred[i*n + j] *= daalaent_cphase(&s->e, pred[i*n + j]);
+    }
+    for (i = 0; i < 3; i++) {
+        for (j = 0; j < bsize; j++) {
+            int bo = (((i + 1) >> 1) << j)*n + (((i + 1) & 1) << j);
+            int q = !s->quantizer[p] ? 1 : s->quantizer[p]*ff_daala_haar_qm[i == 2][j] >> 4;
+            for (k = 0; k < 1 << j; k++)
+                for (l = 0; l < 1 << j; l++)
+                    pred[bo + k*n + l] = q*pred[bo + k*n + l] + tpred[bo + k*n + l];
+        }
+    }
+
+    /* DC level */
+    pred[0] = s->dcoef[p][boffset];
+
+    for (i = 0; i < n; i++) {
+        for (j = 0; j < n; j++)
+            s->dcoef[p][boffset + i*aw + j] = pred[i*n + j];
+    }
+
+    /* IDWT */
+    if (s->dsp.idwt)
+        s->dsp.idwt((uint8_t *)(s->ccoef[p] + boffset), aw,
+                    (uint8_t *)(s->dcoef[p] + boffset), aw, bsize);
+}
+
+static void init_skipped(dctcoef *d, int ostride, dctcoef *pred, int istride,
+                         int key_frame)
+{
+    int i, j;
+    for (i = 0; i < istride; i++) {
+        for (j = 0; j < istride; j++) {
+            if (i || j)
+                d[i*ostride + j] = key_frame ? 0 : pred[i*istride + j];
+        }
+    }
+}
+
+/* PVQ decoding and transform */
+static inline void decode_block_pvq(DaalaContext *s, int x, int y, uint8_t p,
+                                    enum DaalaBsize bsize, int skip)
+{
+    const int sx = x << bsize;
+    const int sy = y << bsize;
+    const int n = 1 << (bsize + 2);
+    const int aw = s->width >> s->fmt->dec[p][0];
+    const int boffset = (sy << 2)*aw + (sx << 2);
+    const int qm = FFMAX(1, s->quantizer[p]);
+    const int qm_off = daala_qm_get_offset(bsize, s->fmt->dec[p][0]);
+    const double *beta = ff_daalapvq_beta[s->h.act_mask][p][bsize];
+
+    dctcoef *d = s->dcoef[p];
+    dctcoef pred[DAALA_BSIZE_MAX*DAALA_BSIZE_MAX];
+    dctcoef tpred[DAALA_BSIZE_MAX*DAALA_BSIZE_MAX];
+
+    daala_calc_prediction(s, pred, d, sx, sy, p, bsize);
+
+    init_skipped(&d[boffset], aw, pred, n, s->h.key_frame);
+
+    daala_raster_to_coding(tpred, n, pred, n);
+
+    daalapvq_decode(&s->e, &s->pvq, &s->h, tpred, pred, qm, s->h.pvq_qm[p],
+                    p, bsize, beta, qm_off, skip);
+
+    pred[0] = d[boffset];
+
+    daala_coding_to_raster(&d[boffset], aw, pred, n);
+
+    /* IDCT */
+    if (s->dsp.idct[bsize])
+        s->dsp.idct[bsize]((uint8_t *)(s->ccoef[p] + boffset), aw,
+                           (uint8_t *)(s->dcoef[p] + boffset), aw);
+}
+
+/* Segments frame && decodes */
+static inline int decode_block_rec(DaalaContext *s, HaarGradient g,
+                                   int x, int y, uint8_t p, enum DaalaBsize bsize)
+{
+    int i, j, lc_skip, cbs;
+    const int sx = x << bsize;
+    const int sy = y << bsize;
+    const int llim = 1 << bsize;
+    const int off  = 2*bsize + !!p;
+    const int bst  = s->bsizes_stride;
+    const int xdec = s->fmt->dec[p][0];
+    const int aw   = s->width >> xdec;
+    enum DaalaBsize obsize = DAALA_BSIZE4x4(s->bsizes, bst, sx, sy);
+
+    if (s->h.haar) {
+        obsize = bsize;
+    } else if (!p) {
+        lc_skip = daalaent_decode_cdf_adapt(&s->e, &s->skip_cdf, off,
+                                            4 + (bsize > 0));
+        obsize = lc_skip < 4 ? bsize : -1;
+    }
+
+    if ((cbs = FFMAX(obsize, xdec)) == bsize) {
+        cbs -= xdec;
+        if (!p) {
+            for (i = 0; i < llim; i++)
+                for (j = 0; j < llim; j++)
+                    DAALA_BSIZE4x4(s->bsizes, bst, sx + i, sy + j) = bsize;
+        }
+        if (p && s->dsp.cfl) {
+            s->dsp.cfl((uint8_t *)s->lcoef, 1 << (cbs + DAALA_LOG_BSIZE0),
+                       (uint8_t *)(s->dcoef[0] + (y << (2 + bsize))*s->width + (x << (2 + bsize))),
+                       s->width, xdec, s->fmt->dec[p][1], cbs, obsize);
+        }
+        if (p && !s->h.haar) {
+            lc_skip = daalaent_decode_cdf_adapt(&s->e, &s->skip_cdf, off, 4);
+        }
+        if (s->h.haar)
+            decode_block_haar(s, x, y, p, cbs);
+        else
+            decode_block_pvq(s, x, y, p, cbs, lc_skip);
+    } else {
+        int bs = bsize - s->fmt->dec[p][0];
+        int bo = (y << (DAALA_LOG_BSIZE0 + bs))*aw + (x << (DAALA_LOG_BSIZE0 + bs));
+        int hfilter = (x + 1) << (DAALA_LOG_BSIZE0 + bs) <= s->width;
+        int vfilter = (y + 1) << (DAALA_LOG_BSIZE0 + bs) <= s->height;
+        if (!s->h.key_frame && s->dsp.pre_split_filter)
+            s->dsp.pre_split_filter((uint8_t *)(s->ccoef + bo), aw, bs,
+                                    hfilter, vfilter);
+        if (s->h.key_frame)
+            get_haar_dc_lvl(s, &g, s->dcoef[p], 2*x, 2*y, p, bsize - 1);
+        decode_block_rec(s, g, 2*x + 0, 2*y + 0, p, bsize - 1);
+        decode_block_rec(s, g, 2*x + 1, 2*y + 0, p, bsize - 1);
+        decode_block_rec(s, g, 2*x + 0, 2*y + 1, p, bsize - 1);
+        decode_block_rec(s, g, 2*x + 1, 2*y + 1, p, bsize - 1);
+        if (s->dsp.post_split_filter)
+            s->dsp.post_split_filter((uint8_t *)(s->ccoef[p] + bo), aw, bs,
+                                     hfilter, vfilter);
+    }
+
+    return 0;
+}
+
+static void decode_blocks(DaalaContext *s, AVFrame *frame)
+{
+    int x, y, p;
+    for (y = 0; y < s->sbn_y; y++) {
+        for (x = 0; x < s->sbn_x; x++) {
+            for (p = 0; p < s->fmt->planes; p++) {
+                struct HaarGradient g = {0};
+                if (s->h.key_frame)
+                    get_haar_dc_sb(s, &g, s->dcoef[p], x, y, p, y > 0 && x < s->sbn_x - 1);
+                decode_block_rec(s, g, x, y, p, DAALA_NBSIZES - 1);
+            }
+        }
+    }
+}
+
+/* Applies post-decode filtering */
+static void apply_filtering(DaalaContext *s, AVFrame *frame)
+{
+    int p, x, y;
+    for (p = 0; p < s->fmt->planes; p++) {
+        int xdec = s->fmt->dec[p][0];
+        int ydec = s->fmt->dec[p][1];
+        int aw = s->width >> xdec;
+        if (!s->h.haar && s->dsp.frame_postfilter) {
+            s->dsp.frame_postfilter((uint8_t *)s->ccoef[p], aw, s->sbn_x,
+                                    s->sbn_y, xdec, ydec);
+        }
+    }
+    for (x = 0; x < s->sbn_x; x++) {
+        for (y = 0; y < s->sbn_y; y++) {
+            int off;
+            uint8_t u, l, res;
+            if (s->dering[x][y] == DERING_SKIP) {
+                s->dering[x][y] = 0;
+                continue;
+            }
+            u = y ? s->dering[x][y-1] << 1 : 0;
+            l = x ? s->dering[x-1][y] << 0 : 0;
+            off = av_clip(u + l, 0, s->dering_cdf.x);
+            res = daalaent_decode_cdf_adapt(&s->e, &s->dering_cdf, off, 2);
+            s->dering[x][y] = res;
+        }
+    }
+}
+
+/* Reinits adaptive probability contexts */
+static void reset_cdfs(DaalaContext *s)
+{
+    int i, j, k;
+    const int pvq_ex_const = 2 << 16;
+
+    /* CDFs */
+    daalaent_cdf_reset(&s->dering_cdf);
+    daalaent_cdf_reset(&s->q_scale_cdf);
+    daalaent_cdf_reset(&s->haar_bit_cdf);
+    daalaent_cdf_reset(&s->haar_split_cdf);
+    daalaent_cdf_reset(&s->skip_cdf);
+    daalaent_cdf_reset(&s->haar_coef_cdf);
+
+    /* PVQ CDFs */
+    daalaent_cdf_reset(&s->pvq.pvqcodeword_cdf);
+    daalaent_cdf_reset(&s->pvq.pvqskip_cdf);
+    daalaent_cdf_reset(&s->pvq.pvqtheta_gain_cdf);
+    daalaent_cdf_reset(&s->pvq.pvqtheta_mcdf);
+    daalaent_cdf_reset(&s->pvq.pvqgain_ref_mcdf);
+    daalaent_cdf_reset(&s->pvq.pvqgain_noref_mcdf);
+
+    /* DC MCDFs + Expectation values */
+    for (i = 0; i < DAALA_NBSIZES*DAALAPVQ_PARTITIONS_MAX; i++)
+        s->pvq.pvqtheta_ex[i] = s->h.key_frame ? 24576 : pvq_ex_const;
+
+    for (i = 0; i < 2*DAALA_NBSIZES; i++) {
+        s->pvq.pvqadapt[4*i + DAALAENT_PVQ_K] = 384;
+        s->pvq.pvqadapt[4*i + DAALAENT_PVQ_SUM_EX] = 256;
+        s->pvq.pvqadapt[4*i + DAALAENT_PVQ_COUNT] = 104;
+        s->pvq.pvqadapt[4*i + DAALAENT_PVQ_COUNT_EX] = 128;
+    }
+
+    for (i = 0; i < s->fmt->planes; i++) {
+        daalaent_cdf_reset(&s->haar_dc_mcdf[i]);
+        s->haar_sb_ex[i] = i > 0 ? 8 : 32768;
+        for (j = 0; j < DAALA_NBSIZES; j++) {
+            for (k = 0; k < 3; k++)
+                s->haar_dc_ex[i][j][k] = i > 0 ? 8 : 32768;
+            for (k = 0; k < DAALAPVQ_PARTITIONS_MAX; k++)
+                s->pvq.pvqgain_ex[i][j][k] = pvq_ex_const;
+        }
+    }
+}
+
+static int daala_decode_frame(AVCodecContext *avctx, void *data,
+                              int *got_frame, AVPacket *avpkt)
+{
+    int i, j, p, ret;
+    AVFrame *frame  = data;
+    DaalaContext *s = avctx->priv_data;
+
+    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
+        return ret;
+
+    /* Init the entropy decoding context */
+    daalaent_decode_init(&s->e, avpkt->data, avpkt->size);
+
+    /* Read the frame miniheader */
+    if (daalaent_decode_frame_header(&s->e, &s->h, s->fmt->planes))
+        return AVERROR_INVALIDDATA;
+
+    /* Update AVFrame type */
+    set_frame_type(&s->h, frame);
+
+    /* (Re)init the PVQ quantization matrix */
+    if (s->last_qm != s->h.qm) {
+        daala_init_qmatrix(s->pvq.qmatrix, s->pvq.qmatrix_inv, s->h.qm);
+        s->last_qm = s->h.qm;
+    }
+
+    /* Prepare the CDFs and MCDFs for use */
+    reset_cdfs(s);
+
+    /* TODO: Actually read the MVs */
+    get_motion_vectors(s);
+
+    /* Get per-plane quantizers (all identical for now) */
+    get_plane_quantizers(s);
+
+    /* NOTE: Remove when !I-frame support is added */
+    if (s->h.key_frame) {
+        /* Recursively decode all blocks */
+        decode_blocks(s, frame);
+
+        /* Apply frame postfilter */
+        apply_filtering(s, frame);
+    }
+
+    /* Copy data to frame */
+    for (p = 0; p < s->fmt->planes; p++) {
+        dctcoef *src = s->ccoef[p];
+        uint8_t *dst = frame->data[p];
+        int stride = s->width >> s->fmt->dec[p][0];
+        int r_w = avctx->width  >> s->fmt->dec[p][0];
+        int r_h = avctx->height >> s->fmt->dec[p][1];
+        if (s->fpr) {
+            const int cs = !s->quantizer[p] ? DAALA_CSHIFT - (s->fmt->depth_mode - 1)*2 : 0;
+            for (i = 0; i < r_h; i++) {
+                for (j = 0; j < r_w; j++)
+                    dst[j] = av_clip(src[j]*(1 << cs) + (128 << DAALA_CSHIFT), 0, DAALA_PCLIP_FPR);
+                dst += frame->linesize[p];
+                src += stride;
+            }
+        } else {
+            const int cs = !s->quantizer[p] ? (s->fmt->depth_mode - 1)*2 : DAALA_CSHIFT;
+            for (i = 0; i < r_h; i++) {
+                for (j = 0; j < r_w; j++)
+                    dst[j] = av_clip_uint8(((src[j] + (1 << cs >> 1)) >> cs) + 128);
+                dst += frame->linesize[p];
+                src += stride;
+            }
+        }
+    }
+
+    if (s->e.err)
+        av_log(avctx, AV_LOG_WARNING, "Bitstream error!\n");
+
+    *got_frame = 1;
+
+    return daalaent_bits_count(&s->e) >> 3;
+}
+
+static av_cold int daala_decode_free(AVCodecContext *avctx)
+{
+    int i;
+    DaalaContext *s = avctx->priv_data;
+
+    /* Blocksizes array */
+    s->bsizes -= DAALA_BSIZE_GRID*s->bsizes_stride + DAALA_BSIZE_GRID;
+    av_freep(&s->bsizes);
+
+    /* CDF */
+    daalaent_cdf_free(&s->dering_cdf);
+    daalaent_cdf_free(&s->q_scale_cdf);
+    daalaent_cdf_free(&s->haar_bit_cdf);
+    daalaent_cdf_free(&s->haar_split_cdf);
+    daalaent_cdf_free(&s->skip_cdf);
+    daalaent_cdf_free(&s->haar_coef_cdf);
+    for (i = 0; i < s->fmt->planes; i++)
+        daalaent_cdf_free(&s->haar_dc_mcdf[i]);
+
+    /* PVQ CDFs */
+    daalaent_cdf_free(&s->pvq.pvqcodeword_cdf);
+    daalaent_cdf_free(&s->pvq.pvqskip_cdf);
+    daalaent_cdf_free(&s->pvq.pvqtheta_gain_cdf);
+    daalaent_cdf_free(&s->pvq.pvqtheta_mcdf);
+    daalaent_cdf_free(&s->pvq.pvqgain_ref_mcdf);
+    daalaent_cdf_free(&s->pvq.pvqgain_noref_mcdf);
+
+    /* Coefs */
+    for (i = 0; i < s->fmt->planes; i++)
+        av_freep(&s->ccoef[i]);
+
+    av_freep(&s->dcoef[0]);
+    av_freep(&s->dcoef[1]);
+
+    av_freep(&s->lcoef);
+
+    /* 2(.5)D tables */
+    DAALA_FREE_2D_ARRAY(s->dering, s->sbn_x);
+    DAALA_FREE_2D_ARRAY(s->q_scale, s->sbn_x);
+    DAALA_FREE_STATIC_2D_ARRAY(s->haar_dc_buf, s->fmt->planes, s->sbn_x);
+
+    return 0;
+}
+
+static av_cold int daala_decode_init(AVCodecContext *avctx)
+{
+    int i, r_w, r_h, err = 0;
+    DaalaContext *s = avctx->priv_data;
+
+    /* Inits a default QM, if the file isn't using the default it will be reinit */
+    s->last_qm = 1;
+    daala_init_qmatrix(s->pvq.qmatrix, s->pvq.qmatrix_inv, s->last_qm);
+
+    s->fmt = find_pix_fmt(avctx->pix_fmt);
+    if (!s->fmt) {
+        av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format - %s!\n",
+               av_get_pix_fmt_name(avctx->pix_fmt));
+        return AVERROR(ENOTSUP);
+    }
+
+    if (ff_daaladsp_init(&s->dsp, s->fmt->depth)) {
+        av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth - %i!\n",
+               s->fmt->depth);
+        return AVERROR(ENOTSUP);
+    }
+
+    /* Can be turned on for 8 bit files too and the demuxer gets it, but how
+     * the hell to actually get that flag from the demuxer to this decoder? */
+    s->fpr = s->fmt->depth > 8 ? 1 : 0;
+
+    s->width  = FFALIGN(avctx->width,  DAALA_BSIZE_MAX);
+    s->height = FFALIGN(avctx->height, DAALA_BSIZE_MAX);
+
+    r_w = s->width  >> s->fmt->dec[i][0];
+    r_h = s->height >> s->fmt->dec[i][1];
+
+    s->sbn_x = s->width  >> DAALA_LOG_BSIZE_MAX;
+    s->sbn_y = s->height >> DAALA_LOG_BSIZE_MAX;
+
+    /* Block sizes array */
+    s->bsizes_stride = (s->sbn_x + 2)*DAALA_BSIZE_GRID;
+    s->bsizes = av_malloc(sizeof(enum DaalaBsize)*s->bsizes_stride*(s->sbn_y + 2)*DAALA_BSIZE_GRID);
+    if (!s->bsizes)
+        return AVERROR(ENOMEM);
+
+    /* Like motion vectors, this could be outside the image, so shift it */
+    s->bsizes += DAALA_BSIZE_GRID*s->bsizes_stride + DAALA_BSIZE_GRID;
+
+    /*  CDF init */
+    err |= daalaent_cdf_alloc(&s->dering_cdf, 4, 2, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->q_scale_cdf, 8, 4, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->haar_bit_cdf, 3, 16, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->haar_split_cdf, 15*2*5, 16, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->skip_cdf, DAALA_NBSIZES*2, 5, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->haar_coef_cdf, 15*3*(DAALA_NBSIZES+1), 16, 128, 0, 2, 0);
+    for (i = 0; i < s->fmt->planes; i++)
+        err |= daalaent_cdf_alloc(&s->haar_dc_mcdf[i], DAALAENT_MODEL_TAB, 16, 64, 0, 0, 1);
+
+    /* PVQ CDFs */
+    err |= daalaent_cdf_alloc(&s->pvq.pvqcodeword_cdf, 4, 16, 128, 0, 0, 0);
+    err |= daalaent_cdf_alloc(&s->pvq.pvqskip_cdf, 2*(DAALA_NBSIZES-1), 7, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->pvq.pvqtheta_gain_cdf, 2*DAALA_NBSIZES*DAALAPVQ_PARTITIONS_MAX, 16, 128, 0, 2, 0);
+    err |= daalaent_cdf_alloc(&s->pvq.pvqtheta_mcdf, DAALAENT_MODEL_TAB, 16, 64, 0, 0, 1);
+    err |= daalaent_cdf_alloc(&s->pvq.pvqgain_ref_mcdf, DAALAENT_MODEL_TAB, 16, 64, 0, 0, 1);
+    err |= daalaent_cdf_alloc(&s->pvq.pvqgain_noref_mcdf, DAALAENT_MODEL_TAB, 16, 64, 0, 0, 1);
+
+    /* The allocations above are unlikely to fail so checking here is okay */
+    if (err)
+        goto alloc_fail;
+
+    /* Arrays */
+    DAALA_ALLOC_2D_ARRAY_GOTO(s->dering, s->sbn_x, s->sbn_y, uint8_t, alloc_fail);
+    DAALA_ALLOC_2D_ARRAY_GOTO(s->q_scale, s->sbn_x, s->sbn_y, uint8_t, alloc_fail);
+    DAALA_ALLOC_STATIC_2D_ARRAY_GOTO(s->haar_dc_buf, s->fmt->planes, s->sbn_x,
+                                     s->sbn_y, dctcoef, alloc_fail);
+
+    /* Coefficients, still too much */
+    s->lcoef    = av_malloc(r_w*r_h*sizeof(dctcoef));
+    if (!s->lcoef)
+        goto alloc_fail;
+
+    s->dcoef[0] = av_malloc(r_w*r_h*sizeof(dctcoef));
+    if (!s->dcoef[0])
+        goto alloc_fail;
+
+    s->dcoef[1] = av_malloc(r_w*r_h*sizeof(dctcoef));
+    s->dcoef[3] = s->dcoef[2] = s->dcoef[1];
+    if (!s->dcoef[1])
+        goto alloc_fail;
+
+    for (i = 0; i < s->fmt->planes; i++) {
+        s->ccoef[i] = av_malloc(r_w*r_h*sizeof(dctcoef));
+        if (!s->ccoef[i])
+            goto alloc_fail;
+    }
+
+    return 0;
+
+alloc_fail:
+    av_log(avctx, AV_LOG_ERROR, "Failed to allocate memory!\n");
+    daala_decode_free(avctx);
+    return AVERROR(ENOMEM);
+}
+
+AVCodec ff_daala_decoder = {
+    .name           = "daala",
+    .long_name      = NULL_IF_CONFIG_SMALL("Daala"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_DAALA,
+    .priv_data_size = sizeof(DaalaContext),
+    .init           = daala_decode_init,
+    .close          = daala_decode_free,
+    .decode         = daala_decode_frame,
+};
diff --git a/libavcodec/daaladsp.c b/libavcodec/daaladsp.c
new file mode 100644
index 0000000..5b0e58d
--- /dev/null
+++ b/libavcodec/daaladsp.c
@@ -0,0 +1,1884 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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 "libavutil/intreadwrite.h"
+#include "daaladsp.h"
+#include "daalatab.h"
+#include "daala_utils.h"
+
+#define TEMPLATE_8bit
+
+#if defined(TEMPLATE_8bit)
+
+#    define RENAME(N)   N ## _8bit
+#    define READ(P)     AV_RN32(P)
+#    define WRITE(P, V) AV_WN32(P, V)
+#    define pixel       int32_t
+#    undef  TEMPLATE_8bit
+
+#endif
+
+#define DAALA_DCT_RSHIFT(_a, _b) (((pixel)(((uint32_t)(_a) >> (32 - (_b))) + (_a))) >> (_b))
+
+static void RENAME(daala_haar_iwt)(uint8_t *_dst, const int dst_stride,
+                                   const uint8_t *_src, const int src_stride,
+                                   const int ln)
+{
+    int i, j, p, lvl;
+    pixel *dst = (pixel *)_dst;
+    pixel *src = (pixel *)_src;
+    dst[0] = src[0];
+    for (lvl = ln - 1; lvl > -1; lvl--) {
+        p = 1 << (ln - 1 - lvl);
+        for (i = p - 1; i > -1; i--) {
+            for (j = p - 1; j > -1; j--) {
+                const pixel a = src[(i + 0)*src_stride + j + p];
+                const pixel b = src[(i + p)*src_stride + j + 0];
+                const pixel c = src[(i + p)*src_stride + j + p] - a;
+                const pixel d = dst[(i + 0)*dst_stride + j + 0] + b;
+                const pixel e = (d - c) >> 1;
+                const pixel f = e - a;
+                const pixel g = e - b;
+                dst[(2*i + 1)*dst_stride + 2*j + 0] = f;
+                dst[(2*i + 0)*dst_stride + 2*j + 1] = g;
+                dst[(2*i + 0)*dst_stride + 2*j + 0] = d - f;
+                dst[(2*i + 1)*dst_stride + 2*j + 1] = c + g;
+            }
+        }
+    }
+}
+
+static av_always_inline void idct_1D_4(pixel *x, int xstride, pixel y[4])
+{
+    pixel tmp;
+    y[3] += (y[1]*18293 +  8192) >> 14;
+    y[1] -= (y[3]*21407 + 16384) >> 15;
+    y[3] += (y[1]*23013 + 16384) >> 15;
+    y[2] = y[0] - y[2];
+    tmp = DAALA_DCT_RSHIFT(y[2], 1);
+    y[0] -= tmp - DAALA_DCT_RSHIFT(y[3], 1);
+    y[1] = tmp - y[1];
+    WRITE(x + 0*xstride, y[0]       );
+    WRITE(x + 1*xstride, y[2] - y[1]);
+    WRITE(x + 2*xstride, y[1]       );
+    WRITE(x + 3*xstride, y[0] - y[3]);
+}
+
+static av_always_inline void idct_1D_8(pixel *x, int xstride, pixel y[8])
+{
+    pixel tmp[3];
+    y[5] -= (y[3]*2485  +  4096) >> 13;
+    y[3] += (y[5]*18205 + 16384) >> 15;
+    y[5] -= (y[3]*2485  +  4096) >> 13;
+    y[7] -= (y[1]*3227  + 16384) >> 15;
+    y[1] += (y[7]*6393  + 16384) >> 15;
+    y[7] -= (y[1]*3227  + 16384) >> 15;
+    y[1] += y[3];
+    tmp[0] = DAALA_DCT_RSHIFT(y[1], 1);
+    y[3] = tmp[0] - y[3];
+    y[5] += y[7];
+    y[7] = DAALA_DCT_RSHIFT(y[5], 1) - y[7];
+    y[3] += (y[5]*7489  +  4096) >> 13;
+    y[5] -= (y[3]*11585 +  8192) >> 14;
+    y[3] -= (y[5]*19195 + 16384) >> 15;
+    y[6] += (y[2]*21895 + 16384) >> 15;
+    y[2] -= (y[6]*15137 +  8192) >> 14;
+    y[6] += (y[2]*21895 + 16384) >> 15;
+    y[0] += (y[4]*13573 + 16384) >> 15;
+    y[4] -= (y[0]*11585 +  8192) >> 14;
+    y[0] += (y[4]*13573 + 16384) >> 15;
+    y[4] = y[2] - y[4];
+    tmp[1] = DAALA_DCT_RSHIFT(y[4], 1);
+    y[2] = tmp[1] - y[2];
+    y[6] = y[0] - y[6];
+    tmp[2] = DAALA_DCT_RSHIFT(y[6], 1);
+    y[0] -= tmp[2];
+    y[7] = tmp[2] - y[7];
+    y[6] -= y[7];
+    y[2] += DAALA_DCT_RSHIFT(y[3], 1);
+    y[3] = y[2] - y[3];
+    y[5] += tmp[1];
+    y[4] -= y[5];
+    y[0] += tmp[0];
+    y[1] = y[0] - y[1];
+    WRITE(x + 0*xstride, y[0]);
+    WRITE(x + 1*xstride, y[4]);
+    WRITE(x + 2*xstride, y[2]);
+    WRITE(x + 3*xstride, y[6]);
+    WRITE(x + 4*xstride, y[7]);
+    WRITE(x + 5*xstride, y[3]);
+    WRITE(x + 6*xstride, y[5]);
+    WRITE(x + 7*xstride, y[1]);
+}
+
+static av_always_inline void idct_1D_16(pixel *x, int xstride, pixel y[16])
+{
+    pixel tmp[8];
+    y[1] += (y[15]*13573  + 16384) >> 15;
+    y[15] -= (y[1]*11585  +  8192) >> 14;
+    y[1] += ((y[15]*13573 + 16384) >> 15)+y[7];
+    y[13] -= (y[3]*10947  +  8192) >> 14;
+    y[3] += (y[13]*15137  +  8192) >> 14;
+    y[5] += (y[11]*10947  +  8192) >> 14;
+    y[11] -= (y[5]*15137  +  8192) >> 14;
+    y[5] += (y[11]*10947  +  8192) >> 14;
+    y[13] += y[5] - ((y[3]*21895 + 16384) >> 15);
+    y[15] = y[9] - y[15];
+    y[11] += y[3];
+    tmp[0] = DAALA_DCT_RSHIFT(y[15], 1);
+    y[9] -= tmp[0];
+    tmp[1] = DAALA_DCT_RSHIFT(y[11], 1);
+    y[3] += tmp[0] - tmp[1];
+    tmp[2] = DAALA_DCT_RSHIFT(y[1], 1);
+    y[7] = tmp[2] - y[7] + tmp[1];
+    tmp[3] = DAALA_DCT_RSHIFT(y[13], 1);
+    y[5] += tmp[2] - tmp[3];
+    y[9] = tmp[3] - y[9];
+    y[13] -= y[9];
+    y[15] = y[3] - y[15];
+    y[1] -= y[5] + ((y[15]*20055 + 16384) >> 15);
+    y[15] += (y[1]*23059  +  8192) >> 14;
+    y[1] -= (y[15]*5417   +  4096) >> 13;
+    y[11] = y[7] - y[11];
+    y[9] += (y[7]*14101   +  8192) >> 14;
+    y[7] += (y[9]*3363    +  4096) >> 13;
+    y[9] -= (y[7]*12905   +  8192) >> 14;
+    y[11] -= (y[13]*4379  +  8192) >> 14;
+    y[13] += (y[11]*20435 +  8192) >> 14;
+    y[11] -= (y[13]*17515 + 16384) >> 15;
+    y[3] += (y[5]*851     +  4096) >> 13;
+    y[5] += (y[3]*14699   +  8192) >> 14;
+    y[3] -= (y[5]*1035    +  1024) >> 11;
+    y[6] -= (y[10]*7335   + 16384) >> 15;
+    y[10] -= (y[6]*12873  +  8192) >> 14;
+    y[14] += (y[2]*2873   +  1024) >> 11;
+    y[2] += (y[14]*9041   + 16384) >> 15;
+    y[6] = DAALA_DCT_RSHIFT(y[2], 1) - y[6] - ((y[10]*8593 + 8192) >> 14);
+    y[14] = DAALA_DCT_RSHIFT(y[10], 1) - y[14] + ((y[2]*2275 + 1024) >> 11);
+    y[2] -= y[6];
+    y[10] -= y[14];
+    y[6] -= (y[10]*13573 + 16384) >> 15;
+    y[10] += (y[6]*11585 +  8192) >> 14;
+    y[6] -= (y[10]*13573 + 16384) >> 15;
+    y[12] += (y[4]*9147  +  4096) >> 13;
+    y[4] -= (y[12]*10703 +  8192) >> 14;
+    y[12] += (y[4]*23013 + 16384) >> 15;
+    y[8] = y[0] - y[8];
+    tmp[4] = DAALA_DCT_RSHIFT(y[8], 1);
+    y[0] -= tmp[4] - DAALA_DCT_RSHIFT(y[12], 1);
+    y[4] = tmp[4] - y[4];
+    y[8] += y[6] - y[4];
+    y[12] = y[0] - y[12] + y[14];
+    y[10] = y[4] - y[10];
+    y[2] = y[0] - y[2];
+    tmp[5] = DAALA_DCT_RSHIFT(y[12], 1);
+    y[14] = tmp[5] - y[14];
+    tmp[6] = DAALA_DCT_RSHIFT(y[10], 1);
+    y[4] -= tmp[6];
+    tmp[4] = DAALA_DCT_RSHIFT(y[8], 1);
+    y[6] = tmp[4] - y[6];
+    tmp[7] = DAALA_DCT_RSHIFT(y[2], 1);
+    y[0] -= tmp[7];
+    y[3] = tmp[7] - y[3];
+    y[6] += DAALA_DCT_RSHIFT(y[13], 1);
+    y[9] = tmp[6] - y[9];
+    y[14] += DAALA_DCT_RSHIFT(y[15], 1);
+    y[1] = tmp[5] - y[1];
+    y[4] += DAALA_DCT_RSHIFT(y[7], 1);
+    y[11] = tmp[4] - y[11];
+    y[0] += DAALA_DCT_RSHIFT(y[5], 1);
+    WRITE(x +  0*xstride,  y[0]        );
+    WRITE(x +  1*xstride,  y[8] - y[11]);
+    WRITE(x +  2*xstride,  y[4]        );
+    WRITE(x +  3*xstride, y[12] -  y[1]);
+    WRITE(x +  4*xstride, y[14]        );
+    WRITE(x +  5*xstride, y[10] -  y[9]);
+    WRITE(x +  6*xstride,  y[6]        );
+    WRITE(x +  7*xstride,  y[2] -  y[3]);
+    WRITE(x +  8*xstride,  y[3]        );
+    WRITE(x +  9*xstride,  y[6] - y[13]);
+    WRITE(x + 10*xstride,  y[9]        );
+    WRITE(x + 11*xstride, y[14] - y[15]);
+    WRITE(x + 12*xstride,  y[1]        );
+    WRITE(x + 13*xstride,  y[4] -  y[7]);
+    WRITE(x + 14*xstride, y[11]        );
+    WRITE(x + 15*xstride,  y[0] -  y[5]);
+}
+
+static av_always_inline void idct_1D_32(pixel *x, int xstride, pixel y[32])
+{
+    pixel tmp[25];
+    /* 8247/16384 ~= Tan[19*Pi/128] ~= 0.503357699799294 */
+    y[19] += (y[13]*8247 + 8192) >> 14;
+    /* 1645/2048 ~= Sin[19*Pi/64] ~= 0.803207531480645 */
+    y[13] -= (y[19]*1645 + 1024) >> 11;
+    /* 8247/16384 ~= Tan[19*Pi/128] ~= 0.503357699799294 */
+    y[19] += (y[13]*8247 + 8192) >> 14;
+    /* 10375/16384 ~= Tan[23*Pi/128] ~= 0.633243016177569 */
+    y[23] += (y[9]*10375 + 8192) >> 14;
+    /* 7405/8192 ~= Sin[23*Pi/64] ~= 0.903989293123443 */
+    y[9] -= (y[23]*7405 + 4096) >> 13;
+    /* 10375/16384 ~= Tan[23*Pi/128] ~= 0.633243016177569 */
+    y[23] += (y[9]*10375 + 8192) >> 14;
+    /* 11539/16384 ~= Tan[25*Pi/128] ~= 0.704279460865044 */
+    y[25] += (y[7]*11539 + 8192) >> 14;
+    /* 7713/8192 ~= Sin[25*Pi/64] ~= 0.941544065183021 */
+    y[7] -= (y[25]*7713 + 4096) >> 13;
+    /* 11539/16384 ~= Tan[25*Pi/128] ~= 0.704279460865044 */
+    y[25] += (y[7]*11539 + 8192) >> 14;
+    /* 9281/16384 ~= Tan[21*Pi/128] ~= 0.566493002730344 */
+    y[21] += (y[11]*9281 + 8192) >> 14;
+    /* 7027/8192 ~= Sin[21*Pi/64] ~= 0.857728610000272 */
+    y[11] -= (y[21]*7027 + 4096) >> 13;
+    /* 9281/16384 ~= Tan[21*Pi/128] ~= 0.566493002730344 */
+    y[21] += (y[11]*9281 + 8192) >> 14;
+    /* 6393/8192 ~= Tan[27*Pi/128] ~= 0.780407659653944 */
+    y[27] += (y[5]*6393 + 4096) >> 13;
+    /* 3973/4096 ~= Sin[27*Pi/64] ~= 0.970031253194544 */
+    y[5] -= (y[27]*3973 + 2048) >> 12;
+    /* 6393/8192 ~= Tan[27*Pi/128] ~= 0.780407659653944 */
+    y[27] += (y[5]*6393 + 4096) >> 13;
+    /* 7263/16384 ~= Tan[17*Pi/128] ~= 0.443269513890864 */
+    y[17] += (y[15]*7263 + 8192) >> 14;
+    /* 3035/4096 ~= Sin[17*Pi/64] ~= 0.740951125354959 */
+    y[15] -= (y[17]*3035 + 2048) >> 12;
+    /* 14525/32768 ~= Tan[17*Pi/128] ~= 0.443269513890864 */
+    y[17] += (y[15]*14525 + 16384) >> 15;
+    /* 2417/32768 ~= Tan[3*Pi/128] ~= 0.0737644315224493 */
+    y[29] -= (y[3]*2417 + 16384) >> 15;
+    /* 601/4096 ~= Sin[3*Pi/64] ~= 0.146730474455362 */
+    y[3] += (y[29]*601 + 2048) >> 12;
+    /* 2417/32768 ~= Tan[3*Pi/128] ~= 0.0737644315224493 */
+    y[29] -= (y[3]*2417 + 16384) >> 15;
+    /* 7799/8192 ~= Tan[31*Pi/128] ~= 0.952079146700925 */
+    y[31] += (y[1]*7799 + 4096) >> 13;
+    /* 4091/4096 ~= Sin[31*Pi/64] ~= 0.998795456205172 */
+    y[1] -= (y[31]*4091 + 2048) >> 12;
+    /* 7799/8192 ~= Tan[31*Pi/128] ~= 0.952079146700925 */
+    y[31] += (y[1]*7799 + 4096) >> 13;
+    y[15] = -y[15];
+    y[7] = -y[7];
+    y[11] = -y[11];
+    y[13] = -y[13];
+    y[5] = -y[5];
+    y[9] = -y[9];
+    y[1] = -y[1];
+    y[27] += y[21];
+    tmp[11] = DAALA_DCT_RSHIFT(y[27], 1);
+    y[21] = tmp[11] - y[21];
+    y[5] -= y[11];
+    tmp[8] = DAALA_DCT_RSHIFT(y[5], 1);
+    y[11] += tmp[8];
+    y[25] += y[23];
+    tmp[7] = DAALA_DCT_RSHIFT(y[25], 1);
+    y[23] -= tmp[7];
+    y[7] -= y[9];
+    tmp[12] = DAALA_DCT_RSHIFT(y[7], 1);
+    y[9] += tmp[12];
+    y[13] += y[29];
+    tmp[9] = DAALA_DCT_RSHIFT(y[13], 1);
+    y[29] -= tmp[9];
+    y[19] -= y[3];
+    tmp[10] = DAALA_DCT_RSHIFT(y[19], 1);
+    y[3] += tmp[10];
+    y[15] += y[1];
+    tmp[13] = DAALA_DCT_RSHIFT(y[15], 1);
+    y[1] -= tmp[13];
+    y[17] -= y[31];
+    tmp[16] = DAALA_DCT_RSHIFT(y[17], 1);
+    y[31] += tmp[16];
+    y[21] += tmp[9];
+    y[13] = y[21] - y[13];
+    y[11] -= tmp[10];
+    y[19] += y[11];
+    y[9] = tmp[16] - y[9];
+    y[17] = y[9] - y[17];
+    y[23] = tmp[13] - y[23];
+    y[15] -= y[23];
+    y[3] += tmp[11];
+    y[27] -= y[3];
+    y[29] -= tmp[8];
+    y[5] += y[29];
+    y[31] += tmp[7];
+    y[25] -= y[31];
+    y[1] -= tmp[12];
+    y[7] += y[1];
+    y[21] = -y[21];
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.820678790828660 */
+    y[9] += (y[23]*6723 + 4096) >> 13;
+    /* 16069/16384 ~= Sin[7*Pi/16] ~= 0.980785280403230 */
+    y[23] -= (y[9]*16069 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.820678790828660 */
+    y[9] += (y[23]*6723 + 4096) >> 13;
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[11] -= (y[21]*2485 + 4096) >> 13;
+    /* 18205/32768 ~= Sin[3*Pi/16] ~= 0.555570233019602 */
+    y[21] += (y[11]*18205 + 16384) >> 15;
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[11] -= (y[21]*2485 + 4096) >> 13;
+    y[23] += y[11];
+    tmp[15] = DAALA_DCT_RSHIFT(y[23], 1);
+    y[11] -= tmp[15];
+    y[21] = y[9] - y[21];
+    y[9] -= DAALA_DCT_RSHIFT(y[21], 1);
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[21] -= (y[11]*13573 + 8192) >> 14;
+    /* 11585/32768 ~= Sin[Pi/4]/2 ~= 0.353553390593274 */
+    y[11] += (y[21]*11585 + 16384) >> 15;
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[21] -= (y[11]*13573 + 8192) >> 14;
+    /* 17515/32768 ~= Tan[5*Pi/32] ~= 0.534511135950792 */
+    y[13] -= (y[19]*17515 + 16384) >> 15;
+    /* 13623/16384 ~= Sin[5*Pi/16] ~= 0.831469612302545 */
+    y[19] += (y[13]*13623 + 8192) >> 14;
+    /* 17515/32768 ~= Tan[5*Pi/32]) ~= 0.534511135950792 */
+    y[13] -= (y[19]*17515 + 16384) >> 15;
+    /* 6723/8192 ~= Tan[7*Pi/32]) ~= 0.820678790828660 */
+    y[15] -= (y[17]*6723 + 4096) >> 13;
+    /* 16069/16384 ~= Sin[7*Pi/16] ~= 0.980785280403230 */
+    y[17] += (y[15]*16069 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32]) ~= 0.820678790828660 */
+    y[15] -= (y[17]*6723 + 4096) >> 13;
+    y[17] += y[19];
+    tmp[16] = DAALA_DCT_RSHIFT(y[17], 1);
+    y[19] = tmp[16] - y[19];
+    y[13] += y[15];
+    y[15] -= DAALA_DCT_RSHIFT(y[13], 1);
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[13] -= (y[19]*19195 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[19] -= (y[13]*11585 + 8192) >> 14;
+    /* 7489/8192 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[13] += (y[19]*7489 + 4096) >> 13;
+    y[5] = y[25] - y[5];
+    y[25] = DAALA_DCT_RSHIFT(y[5], 1) - y[25];
+    y[7] += y[27];
+    y[27] = DAALA_DCT_RSHIFT(y[7], 1) - y[27];
+    y[7] = -y[7];
+    y[29] += y[1];
+    y[1] = DAALA_DCT_RSHIFT(y[29], 1) - y[1];
+    y[31] += y[3];
+    tmp[14] = DAALA_DCT_RSHIFT(y[31], 1);
+    y[3] = tmp[14] - y[3];
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[7] += (y[25]*4161 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[25] -= (y[7]*15137 + 8192) >> 14;
+    /* 14341/16384 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[7] += (y[25]*14341 + 8192) >> 14;
+    /* 14341/16384 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[27] -= (y[5]*14341 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[5] += (y[27]*15137 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[27] -= (y[5]*4161 + 8192) >> 14;
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[29] += (y[3]*13573 + 8192) >> 14;
+    /* 11585/32768 ~= Sin[Pi/4]/2 ~= 0.353553390593274 */
+    y[3] -= (y[29]*11585 + 16384) >> 15;
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[29] += (y[3]*13573 + 8192) >> 14;
+    y[15] = -y[15];
+    y[11] = -y[11];
+    y[13] = -y[13];
+    y[5] = -y[5];
+    y[9] = -y[9];
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.357805721314524 */
+    y[14] += (y[18]*11725 + 16384) >> 15;
+    /* 5197/8192 ~= Sin[7*Pi/32] ~= 0.634393284163645 */
+    y[18] -= (y[14]*5197 + 4096) >> 13;
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.357805721314524 */
+    y[14] += (y[18]*11725 + 16384) >> 15;
+    /* 2455/4096 ~= Tan[11*Pi/64] ~= 0.599376933681924 */
+    y[22] += (y[10]*2455 + 2048) >> 12;
+    /* 7225/8192 ~= Sin[11*Pi/32] ~= 0.881921264348355 */
+    y[10] -= (y[22]*7225 + 4096) >> 13;
+    /* 2455/4096 ~= Tan[11*Pi/64] ~= 0.599376933681924 */
+    y[22] += (y[10]*2455 + 2048) >> 12;
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.148335987538347 */
+    y[6] += (y[26]*4861 + 16384) >> 15;
+    /* 1189/4096 ~= Sin[3*Pi/32] ~= 0.290284677254462 */
+    y[26] -= (y[6]*1189 + 2048) >> 12;
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.148335987538347 */
+    y[6] += (y[26]*4861 + 16384) >> 15;
+    /* 7425/8192 ~= Tan[15*Pi/64] ~= 0.906347169019147 */
+    y[30] += (y[2]*7425 + 4096) >> 13;
+    /* 8153/8192 ~= Sin[15*Pi/32] ~= 0.995184726672197 */
+    y[2] -= (y[30]*8153 + 4096) >> 13;
+    /* 7425/8192 ~= Tan[15*Pi/64] ~= 0.906347169019147 */
+    y[30] += (y[2]*7425 + 4096) >> 13;
+
+    y[2] = -y[2];
+    y[2] -= y[18];
+    tmp[0] = DAALA_DCT_RSHIFT(y[2], 1);
+    y[18] += tmp[0];
+    y[22] -= y[6];
+    tmp[2] = DAALA_DCT_RSHIFT(y[22], 1);
+    y[6] += tmp[2];
+    y[30] += y[14];
+    tmp[3] = DAALA_DCT_RSHIFT(y[30], 1);
+    y[14] -= tmp[3];
+    y[10] = y[26] - y[10];
+    tmp[1] = DAALA_DCT_RSHIFT(y[10], 1);
+    y[26] -= tmp[1];
+    y[14] += tmp[1];
+    y[10] = y[14] - y[10];
+    y[6] -= tmp[3];
+    y[30] += y[6];
+    y[18] += tmp[2];
+    y[22] = y[18] - y[22];
+    y[26] += tmp[0];
+    y[2] -= y[26];
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[14] += (y[18]*3259 + 8192) >> 14;
+    /* 3135/8192 ~= Sin[Pi/8] ~= 0.382683432365090 */
+    y[18] -= (y[14]*3135 + 4096) >> 13;
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[14] += (y[18]*3259 + 8192) >> 14;
+    /* 10947/16384 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[10] += (y[22]*10947 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[22] -= (y[10]*15137 + 8192) >> 14;
+    /* 21895/32768 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[10] += (y[22]*21895 + 16384) >> 15;
+    /* 13573/32768 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[6] += (y[26]*13573 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186547 */
+    y[26] -= (y[6]*11585 + 8192) >> 14;
+    /* 13573/32768 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[6] += (y[26]*13573 + 16384) >> 15;
+    /* 8757/16384 ~= Tan[5*Pi/32] ~= 0.534511135950792 */
+    y[12] -= (y[20]*8757 + 8192) >> 14;
+    /* 6811/8192 ~= Sin[5*Pi/16] ~= 0.831469612302545 */
+    y[20] += (y[12]*6811 + 4096) >> 13;
+    /* 8757/16384 ~= Tan[5*Pi/32] ~= 0.534511135950792 */
+    y[12] -= (y[20]*8757 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.820678790828660 */
+    y[4] -= (y[28]*6723 + 4096) >> 13;
+    /* 8035/8192 ~= Sin[7*Pi/16] ~= 0.980785280403230 */
+    y[28] += (y[4]*8035 + 4096) >> 13;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.820678790828660 */
+    y[4] -= (y[28]*6723 + 4096) >> 13;
+    y[28] += y[20];
+    tmp[4] = DAALA_DCT_RSHIFT(y[28], 1);
+    y[20] = tmp[4] - y[20];
+    y[12] += y[4];
+    y[4] -= DAALA_DCT_RSHIFT(y[12], 1);
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[12] -= (y[20]*19195 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[20] -= (y[12]*11585 + 8192) >> 14;
+    /* 7489/8192 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[12] += (y[20]*7489 + 4096) >> 13;
+    /* 10947/16384 ~= Tan[3*Pi/16]) ~= 0.668178637919299 */
+    y[24] += (y[8]*10947 + 8192) >> 14;
+    /* 473/512 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[8] -= (y[24]*473 + 256) >> 9;
+    /* 10947/16384 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[24] += (y[8]*10947 + 8192) >> 14;
+    /* 3393/8192 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[0] += (y[16]*3393 + 4096) >> 13;
+    /* 5793/8192 ~= Sin[pi/4] ~= 0.707106781186547 */
+    y[16] -= (y[0]*5793 + 4096) >> 13;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[0] += (y[16]*13573 + 16384) >> 15;
+    y[16] = y[8] - y[16];
+    tmp[6] = DAALA_DCT_RSHIFT(y[16], 1);
+    y[8] = tmp[6] - y[8];
+    y[24] = y[0] - y[24];
+    tmp[5] = DAALA_DCT_RSHIFT(y[24], 1);
+    y[0] -= tmp[5];
+    y[4] = tmp[5] - y[4];
+    y[24] -= y[4];
+    y[8] += DAALA_DCT_RSHIFT(y[20], 1);
+    y[20] = y[8] - y[20];
+    y[12] = tmp[6] - y[12];
+    y[16] -= y[12];
+    y[0] += tmp[4];
+    y[28] = y[0] - y[28];
+    y[16] -= y[14];
+    tmp[24] = DAALA_DCT_RSHIFT(y[16], 1);
+    y[14] += tmp[24];
+    y[18] = y[12] - y[18];
+    tmp[20] = DAALA_DCT_RSHIFT(y[18], 1);
+    y[12] -= tmp[20];
+    y[20] -= y[10];
+    tmp[22] = DAALA_DCT_RSHIFT(y[20], 1);
+    y[10] += tmp[22];
+    y[22] = y[8] - y[22];
+    tmp[18] = DAALA_DCT_RSHIFT(y[22], 1);
+    y[8] -= tmp[18];
+    y[24] -= y[6];
+    tmp[23] = DAALA_DCT_RSHIFT(y[24], 1);
+    y[6] += tmp[23];
+    y[26] = y[4] - y[26];
+    tmp[19] = DAALA_DCT_RSHIFT(y[26], 1);
+    y[4] -= tmp[19];
+    y[28] -= y[2];
+    tmp[21] = DAALA_DCT_RSHIFT(y[28], 1);
+    y[2] += tmp[21];
+    y[30] = y[0] - y[30];
+    tmp[17] = DAALA_DCT_RSHIFT(y[30], 1);
+    y[0] -= tmp[17];
+    y[15] = tmp[24] - y[15];
+    y[16] -= y[15];
+    y[14] += tmp[16];
+    y[17] = y[14] - y[17];
+    y[13] = tmp[20] - y[13];
+    y[18] -= y[13];
+    y[12] += DAALA_DCT_RSHIFT(y[19], 1);
+    y[19] = y[12] - y[19];
+    y[11] = tmp[22] - y[11];
+    y[20] -= y[11];
+    y[10] += DAALA_DCT_RSHIFT(y[21], 1);
+    y[21] = y[10] - y[21];
+    y[9] = tmp[18] - y[9];
+    y[22] -= y[9];
+    y[8] += tmp[15];
+    y[23] = y[8] - y[23];
+    y[7] = tmp[23] - y[7];
+    y[24] -= y[7];
+    y[6] += DAALA_DCT_RSHIFT(y[25], 1);
+    y[25] = y[6] - y[25];
+    y[5] = tmp[19] - y[5];
+    y[26] -= y[5];
+    y[4] += DAALA_DCT_RSHIFT(y[27], 1);
+    y[27] = y[4] - y[27];
+    y[3] = tmp[21] - y[3];
+    y[28] -= y[3];
+    y[2] += DAALA_DCT_RSHIFT(y[29], 1);
+    y[29] = y[2] - y[29];
+    y[1] = tmp[17] - y[1];
+    y[30] -= y[1];
+    y[0] += tmp[14];
+    y[31] = y[0] - y[31];
+    WRITE(x +  0*xstride,  y[0]);
+    WRITE(x +  1*xstride, y[16]);
+    WRITE(x +  2*xstride,  y[8]);
+    WRITE(x +  3*xstride, y[24]);
+    WRITE(x +  4*xstride,  y[4]);
+    WRITE(x +  5*xstride, y[20]);
+    WRITE(x +  6*xstride, y[12]);
+    WRITE(x +  7*xstride, y[28]);
+    WRITE(x +  8*xstride,  y[2]);
+    WRITE(x +  9*xstride, y[18]);
+    WRITE(x + 10*xstride, y[10]);
+    WRITE(x + 11*xstride, y[26]);
+    WRITE(x + 12*xstride,  y[6]);
+    WRITE(x + 13*xstride, y[22]);
+    WRITE(x + 14*xstride, y[14]);
+    WRITE(x + 15*xstride, y[30]);
+    WRITE(x + 16*xstride,  y[1]);
+    WRITE(x + 17*xstride, y[17]);
+    WRITE(x + 18*xstride,  y[9]);
+    WRITE(x + 19*xstride, y[25]);
+    WRITE(x + 20*xstride,  y[5]);
+    WRITE(x + 21*xstride, y[21]);
+    WRITE(x + 22*xstride, y[13]);
+    WRITE(x + 23*xstride, y[29]);
+    WRITE(x + 24*xstride,  y[3]);
+    WRITE(x + 25*xstride, y[19]);
+    WRITE(x + 26*xstride, y[11]);
+    WRITE(x + 27*xstride, y[27]);
+    WRITE(x + 28*xstride,  y[7]);
+    WRITE(x + 29*xstride, y[23]);
+    WRITE(x + 30*xstride, y[15]);
+    WRITE(x + 31*xstride, y[31]);
+}
+
+static av_always_inline void idct_1D_64(pixel *x, int xstride, pixel y[64])
+{
+    pixel tmp[57];
+    /* 1301/2048 ~= (1/Sqrt[2] - Cos[61*Pi/128])/Sin[61*Pi/128] ~=
+        0.6352634915376478 */
+    y[3] -= (y[61]*1301 + 1024) >> 11;
+    /* 5777/4096 ~= Sqrt[2]*Sin[61*Pi/128] ~= 1.4103816894602614 */
+    y[61] += (y[3]*5777 + 2048) >> 12;
+    /* 2753/4096 ~= (1/Sqrt[2] - Cos[61*Pi/128]/2)/Sin[61*Pi/128] ~=
+        0.6721457072988726 */
+    y[3] -= (y[61]*2753 + 2048) >> 12;
+    /* -2513/32768 ~= (1/Sqrt[2] - Cos[29*Pi/128])/Sin[29*Pi/128] ~=
+        -0.07670567731102484 */
+    y[29] -= (y[35]*2513 + 16384) >> 15;
+    /* 7567/8192 ~= Sqrt[2]*Sin[29*Pi/128] ~= 0.9237258930790229 */
+    y[35] -= (y[29]*7567 + 4096) >> 13;
+    /* 515/1024 ~= (1/Sqrt[2] - Cos[29*Pi/128]/2)/Sin[29*Pi/128] ~=
+        0.5029332763556925 */
+    y[29] += (y[35]*515 + 512) >> 10;
+    /* -6331/8192 ~= (1/Sqrt[2] - Cos[13*Pi/128])/Sin[13*Pi/128] ~=
+        -0.772825983107003 */
+    y[13] -= (y[51]*6331 + 4096) >> 13;
+    /* 1817/4096 ~= Sqrt[2]*Sin[13*Pi/128] ~= 0.4436129715409088 */
+    y[51] -= (y[13]*1817 + 2048) >> 12;
+    /* 1517/2048 ~= (1/Sqrt[2] - Cos[13*Pi/128]/2)/Sin[13*Pi/128] ~=
+        0.7406956190518837 */
+    y[13] += (y[51]*1517 + 1024) >> 11;
+    /* -3391/8192 ~= (1/Sqrt[2] - Cos[19*Pi/128])/Sin[19*Pi/128] ~=
+        -0.41395202418930155 */
+    y[45] += (y[19]*3391 + 4096) >> 13;
+    /* 5209/8192 ~= Sqrt[2]*Sin[19*Pi/128] ~= 0.6358464401941452 */
+    y[19] += (y[45]*5209 + 4096) >> 13;
+    /* 2373/4096 ~= (1/Sqrt[2] - Cos[19*Pi/128]/2)/Sin[19*Pi/128] ~=
+        0.5793773719823809 */
+    y[45] -= (y[19]*2373 + 2048) >> 12;
+    /* 8195/16384 ~= (1/Sqrt[2] - Cos[55*Pi/128])/Sin[55*Pi/128] ~=
+        0.5001583229201391 */
+    y[9] -= (y[55]*8195 + 8192) >> 14;
+    /* 1413/1024 ~= Sqrt[2]*Sin[55*Pi/128] ~= 1.3798511851368045 */
+    y[55] += (y[9]*1413 + 512) >> 10;
+    /* 5017/8192 ~= (1/Sqrt[2] - Cos[55*Pi/128]/2)/Sin[55*Pi/128] ~=
+        0.6124370775787037 */
+    y[9] -= (y[55]*5017 + 4096) >> 13;
+    /* -8437/32768 ~= (1/Sqrt[2] - Cos[23*Pi/128])/Sin[23*Pi/128] ~=
+        -0.2574717698598901 */
+    y[23] -= (y[41]*8437 + 16384) >> 15;
+    /* 3099/4096 ~= Sqrt[2]*Sin[23*Pi/128] ~= 0.7566008898816587 */
+    y[41] -= (y[23]*3099 + 2048) >> 12;
+    /* 4359/8192 ~= (1/Sqrt[2] - Cos[23*Pi/128]/2)/Sin[23*Pi/128] ~=
+        0.5321145141202145 */
+    y[23] += (y[41]*4359 + 4096) >> 13;
+    /* -6287/32768 ~= (1/Sqrt[2] - Cos[25*Pi/128])/Sin[25*Pi/128] ~=
+        -0.19186603041023065 */
+    y[25] -= (y[39]*6287 + 16384) >> 15;
+    /* 6671/8192 ~= Sqrt[2]*Sin[25*Pi/128] ~= 0.8143157536286402 */
+    y[39] -= (y[25]*6671 + 4096) >> 13;
+    /* 1061/2048 ~= (1/Sqrt[2] - Cos[25*Pi/128]/2)/Sin[25*Pi/128] ~=
+        0.5180794213368158 */
+    y[25] += (y[39]*1061 + 1024) >> 11;
+    /* 2229/4096 ~= (1/Sqrt[2] - Cos[57*Pi/128])/Sin[57*Pi/128] ~=
+        0.5441561539205226 */
+    y[7] -= (y[57]*2229 + 2048) >> 12;
+    /* 5707/4096 ~= Sqrt[2]*Sin[57*Pi/128] ~= 1.3933930045694292 */
+    y[57] += (y[7]*5707 + 2048) >> 12;
+    /* 323/512 ~= (1/Sqrt[2] - Cos[57*Pi/128]/2)/Sin[57*Pi/128] ~=
+        0.6309143839894504 */
+    y[7] -= (y[57]*323 + 256) >> 9;
+    /* -1971/2048 ~= (1/Sqrt[2] - Cos[11*Pi/128])/Sin[11*Pi/128] ~=
+        -0.9623434853244648 */
+    y[53] += (y[11]*1971 + 1024) >> 11;
+    /* 1545/4096 ~= Sqrt[2]*Sin[11*Pi/128] ~= 0.37718879887892737 */
+    y[11] += (y[53]*1545 + 2048) >> 12;
+    /* 3459/4096 ~= (1/Sqrt[2] - Cos[11*Pi/128]/2)/Sin[11*Pi/128] ~=
+        0.8444243553292501 */
+    y[53] -= (y[11]*3459 + 2048) >> 12;
+    /* -5417/16384 ~= (1/Sqrt[2] - Cos[21*Pi/128])/Sin[21*Pi/128] ~=
+        -0.3306569439519963 */
+    y[21] -= (y[43]*5417 + 8192) >> 14;
+    /* 2855/4096 ~= Sqrt[2]*Sin[21*Pi/128] ~= 0.6970633083205415 */
+    y[43] -= (y[21]*2855 + 2048) >> 12;
+    /* 2261/4096 ~= (1/Sqrt[2] - Cos[21*Pi/128]/2)/Sin[21*Pi/128] ~=
+        0.5519664910950994 */
+    y[21] += (y[43]*2261 + 2048) >> 12;
+    /* -4327/32768 ~= (1/Sqrt[2] - Cos[27*Pi/128])/Sin[27*Pi/128] ~=
+        -0.13204726103773165 */
+    y[27] -= (y[37]*4327 + 16384) >> 15;
+    /* 891/1024 ~= Sqrt[2]*Sin[27*Pi/128] ~= 0.8700688593994939 */
+    y[37] -= (y[27]*891 + 512) >> 10;
+    /* 4167/8192 ~= (1/Sqrt[2] - Cos[27*Pi/128]/2)/Sin[27*Pi/128] ~=
+        0.5086435289805458 */
+    y[27] += (y[37]*4167 + 4096) >> 13;
+    /* 2413/4096 ~= (1/Sqrt[2] - Cos[59*Pi/128])/Sin[59*Pi/128] ~=
+        0.5891266122920528 */
+    y[5] -= (y[59]*2413 + 2048) >> 12;
+    /* 5749/4096 ~= Sqrt[2]*Sin[59*Pi/128] ~= 1.4035780182072333 */
+    y[59] += (y[5]*5749 + 2048) >> 12;
+    /* 5331/8192 ~= (1/Sqrt[2] - Cos[59*Pi/128]/2)/Sin[59*Pi/128] ~=
+        0.6507957303604222 */
+    y[5] -= (y[59]*5331 + 4096) >> 13;
+    /* -2571/4096 ~= (1/Sqrt[2] - Cos[15*Pi/128])/Sin[15*Pi/128] ~=
+        -0.6276441593165217 */
+    y[49] += (y[15]*2571 + 2048) >> 12;
+    /* 8339/32768 ~= Sqrt[2]*Sin[15*Pi/128] ~= 0.5089684416985407 */
+    y[15] += (y[49]*8339 + 8192) >> 14;
+    /* 5477/8192 ~= (1/Sqrt[2] - Cos[15*Pi/128]/2)/Sin[15*Pi/128] ~=
+        0.6685570995525147 */
+    y[49] -= (y[15]*5477 + 4096) >> 13;
+    /* -8373/16384 ~= (1/Sqrt[2] - Cos[17*Pi/128])/Sin[17*Pi/128] ~=
+        -0.5110608601827629 */
+    y[17] -= (y[47]*8373 + 8192) >> 14;
+    /* 4695/8192 ~= Sqrt[2]*Sin[17*Pi/128] ~= 0.5730977622997507 */
+    y[47] -= (y[17]*4695 + 4096) >> 13;
+    /* 2527/4096 ~= (1/Sqrt[2] - Cos[17*Pi/128]/2)/Sin[17*Pi/128] ~=
+        0.6169210657818165 */
+    y[17] += (y[47]*2527 + 2048) >> 12;
+    /* -815/32768 ~= (1/Sqrt[2] - Cos[31*Pi/128])/Sin[31*Pi/128] ~=
+        -0.02485756913896231 */
+    y[31] -= (y[33]*815 + 16384) >> 15;
+    /* 1997/2048 ~= Sqrt[2]*Sin[31*Pi/128] ~= 0.9751575901732918 */
+    y[33] -= (y[31]*1997 + 1024) >> 11;
+    /* 8197/16384 ~= (1/Sqrt[2] - Cos[31*Pi/128]/2)/Sin[31*Pi/128] ~=
+        0.5003088539809675 */
+    y[31] += (y[33]*8197 + 8192) >> 14;
+    /* 5593/8192 ~= (1/Sqrt[2] - Cos[63*Pi/128])/Sin[63*Pi/128] ~=
+        0.6827711905810085 */
+    y[1] -= (y[63]*5593 + 4096) >> 13;
+    /* 5791/4096 ~= Sqrt[2]*Sin[63*Pi/128] ~= 1.413787627688534 */
+    y[63] += (y[1]*5791 + 2048) >> 12;
+    /* 2847/4096 ~= (1/Sqrt[2] - Cos[63*Pi/128]/2)/Sin[63*Pi/128] ~=
+        0.6950455016354713 */
+    y[1] -= (y[63]*2847 + 2048) >> 12;
+    y[7] = -y[7];
+    y[3] = -y[3];
+    y[5] = -y[5];
+    y[9] = -y[9];
+    y[7] -= DAALA_DCT_RSHIFT(y[39], 1);
+    y[39] += y[7];
+    y[25] -= DAALA_DCT_RSHIFT(y[57], 1);
+    y[57] += y[25];
+    y[9] -= DAALA_DCT_RSHIFT(y[41], 1);
+    y[41] += y[9];
+    y[23] -= DAALA_DCT_RSHIFT(y[55], 1);
+    y[55] += y[23];
+    y[17] -= DAALA_DCT_RSHIFT(y[15], 1);
+    y[15] += y[17];
+    y[49] -= DAALA_DCT_RSHIFT(y[47], 1);
+    y[47] += y[49];
+    y[1] += DAALA_DCT_RSHIFT(y[33], 1);
+    y[33] -= y[1];
+    y[31] -= DAALA_DCT_RSHIFT(y[63], 1);
+    y[63] += y[31];
+    y[29] -= DAALA_DCT_RSHIFT(y[61], 1);
+    y[61] += y[29];
+    y[3] -= DAALA_DCT_RSHIFT(y[35], 1);
+    y[35] += y[3];
+    y[45] += DAALA_DCT_RSHIFT(y[51], 1);
+    y[51] -= y[45];
+    y[13] += DAALA_DCT_RSHIFT(y[19], 1);
+    y[19] -= y[13];
+    y[5] -= DAALA_DCT_RSHIFT(y[37], 1);
+    y[37] += y[5];
+    y[27] -= DAALA_DCT_RSHIFT(y[59], 1);
+    y[59] += y[27];
+    y[21] -= DAALA_DCT_RSHIFT(y[11], 1);
+    y[11] += y[21];
+    y[53] -= DAALA_DCT_RSHIFT(y[43], 1);
+    y[43] += y[53];
+    y[45] -= y[29];
+    y[29] += DAALA_DCT_RSHIFT(y[45], 1);
+    y[19] -= y[35];
+    y[35] += DAALA_DCT_RSHIFT(y[19], 1);
+    y[37] += y[21];
+    y[21] -= DAALA_DCT_RSHIFT(y[37], 1);
+    y[27] += y[43];
+    y[43] -= DAALA_DCT_RSHIFT(y[27], 1);
+    y[25] += y[41];
+    y[41] -= DAALA_DCT_RSHIFT(y[25], 1);
+    y[39] += y[23];
+    y[23] -= DAALA_DCT_RSHIFT(y[39], 1);
+    y[47] -= y[31];
+    y[31] += DAALA_DCT_RSHIFT(y[47], 1);
+    y[17] -= y[33];
+    y[33] += DAALA_DCT_RSHIFT(y[17], 1);
+    y[9] += y[7];
+    tmp[18] = DAALA_DCT_RSHIFT(y[9], 1);
+    y[7] -= tmp[18];
+    y[55] -= y[57];
+    tmp[23] = DAALA_DCT_RSHIFT(y[55], 1);
+    y[57] += tmp[23];
+    y[63] += y[15];
+    tmp[24] = DAALA_DCT_RSHIFT(y[63], 1);
+    y[15] -= tmp[24];
+    y[1] += y[49];
+    tmp[17] = DAALA_DCT_RSHIFT(y[1], 1);
+    y[49] -= tmp[17];
+    y[3] -= y[51];
+    tmp[21] = DAALA_DCT_RSHIFT(y[3], 1);
+    y[51] += tmp[21];
+    y[61] += y[13];
+    tmp[20] = DAALA_DCT_RSHIFT(y[61], 1);
+    y[13] -= tmp[20];
+    y[11] -= y[59];
+    tmp[22] = DAALA_DCT_RSHIFT(y[11], 1);
+    y[59] += tmp[22];
+    y[53] += y[5];
+    tmp[19] = DAALA_DCT_RSHIFT(y[53], 1);
+    y[5] -= tmp[19];
+    y[43] = -y[43];
+    y[41] = -y[41];
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.14833598753834742 */
+    y[35] -= (y[29]*4861 + 16384) >> 15;
+    /* 1189/4096 ~= Sin[3*Pi/32] ~= 0.29028467725446233 */
+    y[29] += (y[35]*1189 + 2048) >> 12;
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.14833598753834742 */
+    y[35] -= (y[29]*4861 + 16384) >> 15;
+    /* 513/2048 ~= Tan[5*Pi/64] ~= 0.25048696019130545 */
+    y[37] -= (y[27]*513 + 1024) >> 11;
+    /* 7723/16384 ~= Sin[5*Pi/32] ~= 0.47139673682599764 */
+    y[27] += (y[37]*7723 + 8192) >> 14;
+    /* 513/2048 ~= Tan[5*Pi/64] ~= 0.25048696019130545 */
+    y[37] -= (y[27]*513 + 1024) >> 11;
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.3578057213145241 */
+    y[39] -= (y[25]*11725 + 16384) >> 15;
+    /* 5197/8192 ~= Sin[7*Pi/32] ~= 0.6343932841636455 */
+    y[25] += (y[39]*5197 + 4096) >> 13;
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.3578057213145241 */
+    y[39] -= (y[25]*11725 + 16384) >> 15;
+    /* 805/16384 ~= Tan[Pi/64] ~= 0.04912684976946793 */
+    y[33] -= (y[31]*805 + 8192) >> 14;
+    /* 803/8192 ~= Sin[Pi/32] ~= 0.0980171403295606 */
+    y[31] += (y[33]*803 + 4096) >> 13;
+    /* 805/16384 ~= Tan[Pi/64] ~= 0.04912684976946793 */
+    y[33] -= (y[31]*805 + 8192) >> 14;
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.14833598753834742 */
+    y[45] -= (y[19]*4861 + 16384) >> 15;
+    /* 1189/4096 ~= Sin[3*Pi/32] ~= 0.29028467725446233 */
+    y[19] += (y[45]*1189 + 2048) >> 12;
+    /* 4861/32768 ~= Tan[3*Pi/64] ~= 0.14833598753834742 */
+    y[45] -= (y[19]*4861 + 16384) >> 15;
+    /* 2455/4096 ~= Tan[11*Pi/64] ~= 0.5993769336819237 */
+    y[43] -= (y[21]*2455 + 2048) >> 12;
+    /* 14449/16384 ~= Sin[11*Pi/32] ~= 0.881921264348355 */
+    y[21] += (y[43]*14449 + 8192) >> 14;
+    /* 2455/4096 ~= Tan[11*Pi/64] ~= 0.5993769336819237 */
+    y[43] -= (y[21]*2455 + 2048) >> 12;
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.3578057213145241 */
+    y[23] -= (y[41]*11725 + 16384) >> 15;
+    /* 5197/8192 ~= Sin[7*Pi/32] ~= 0.6343932841636455 */
+    y[41] += (y[23]*5197 + 4096) >> 13;
+    /* 11725/32768 ~= Tan[7*Pi/64] ~= 0.3578057213145241 */
+    y[23] -= (y[41]*11725 + 16384) >> 15;
+    /* 805/16384 ~= Tan[Pi/64] ~= 0.04912684976946793 */
+    y[47] -= (y[17]*805 + 8192) >> 14;
+    /* 803/8192 ~= Sin[Pi/32] ~= 0.0980171403295606 */
+    y[17] += (y[47]*803 + 4096) >> 13;
+    /* 805/16384 ~= Tan[Pi/64] ~= 0.04912684976946793 */
+    y[47] -= (y[17]*805 + 8192) >> 14;
+    y[21] = -y[21];
+    y[45] = -y[45];
+    y[29] += DAALA_DCT_RSHIFT(y[27], 1);
+    y[27] -= y[29];
+    y[35] -= DAALA_DCT_RSHIFT(y[37], 1);
+    y[37] += y[35];
+    y[31] += DAALA_DCT_RSHIFT(y[25], 1);
+    y[25] -= y[31];
+    y[33] -= DAALA_DCT_RSHIFT(y[39], 1);
+    y[39] += y[33];
+    y[43] -= DAALA_DCT_RSHIFT(y[19], 1);
+    y[19] += y[43];
+    y[21] += DAALA_DCT_RSHIFT(y[45], 1);
+    y[45] -= y[21];
+    y[23] += DAALA_DCT_RSHIFT(y[17], 1);
+    y[17] -= y[23];
+    y[41] += DAALA_DCT_RSHIFT(y[47], 1);
+    y[47] -= y[41];
+    y[59] -= tmp[20];
+    y[61] += y[59];
+    y[5] += tmp[21];
+    y[3] -= y[5];
+    y[7] -= tmp[17];
+    y[1] += y[7];
+    y[57] -= tmp[24];
+    y[63] += y[57];
+    y[51] += tmp[22];
+    y[11] -= y[51];
+    y[13] += tmp[19];
+    y[53] -= y[13];
+    y[49] += tmp[23];
+    y[55] -= y[49];
+    y[15] += tmp[18];
+    y[9] -= y[15];
+    y[53] = -y[53];
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[51] -= (y[13]*2485 + 4096) >> 13;
+    /* 18205/32768 ~= Sin[3*Pi/16] ~= 0.555570233019602 */
+    y[13] += (y[51]*18205 + 16384) >> 15;
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[51] -= (y[13]*2485 + 4096) >> 13;
+    /* 3227/32768 ~= Tan[Pi/32] ~= 0.09849140335716425 */
+    y[49] -= (y[15]*3227 + 16384) >> 15;
+    /* 6393/32768 ~= Sin[Pi/16] ~= 0.19509032201612825 */
+    y[15] += (y[49]*6393 + 16384) >> 15;
+    /* 3227/32768 ~= Tan[Pi/32] ~= 0.09849140335716425 */
+    y[49] -= (y[15]*3227 + 16384) >> 15;
+    /* 17515/32768 ~= Tan[5*Pi/32] ~= 0.5345111359507916 */
+    y[53] -= (y[11]*17515 + 16384) >> 15;
+    /* 13623/16384 ~= Sin[5*Pi/16] ~= 0.8314696123025452 */
+    y[11] += (y[53]*13623 + 8192) >> 14;
+    /* 17515/32768 ~= Tan[5*Pi/32] ~= 0.5345111359507916 */
+    y[53] -= (y[11]*17515 + 16384) >> 15;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.8206787908286602 */
+    y[55] -= (y[9]*6723 + 4096) >> 13;
+    /* 16069/16384 ~= Sin[7*Pi/16] ~= 0.9807852804032304 */
+    y[9] += (y[55]*16069 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.8206787908286602 */
+    y[55] -= (y[9]*6723 + 4096) >> 13;
+    y[55] = -y[55];
+    y[25] += y[37];
+    y[37] -= DAALA_DCT_RSHIFT(y[25], 1);
+    y[27] -= y[39];
+    y[39] += DAALA_DCT_RSHIFT(y[27], 1);
+    y[29] -= y[31];
+    y[31] += DAALA_DCT_RSHIFT(y[29], 1);
+    y[33] -= y[35];
+    y[35] += DAALA_DCT_RSHIFT(y[33], 1); /* pass */
+    y[23] -= y[21];
+    y[21] += DAALA_DCT_RSHIFT(y[23], 1);
+    y[43] += y[41];
+    y[41] -= DAALA_DCT_RSHIFT(y[43], 1);
+    y[19] += y[17];
+    y[17] -= DAALA_DCT_RSHIFT(y[19], 1);
+    y[47] -= y[45];
+    y[45] += DAALA_DCT_RSHIFT(y[47], 1); /* pass */
+    y[7] += y[59];
+    y[59] -= DAALA_DCT_RSHIFT(y[7], 1);
+    y[5] -= y[57];
+    y[57] += DAALA_DCT_RSHIFT(y[5], 1);
+    y[3] -= y[1];
+    y[1] += DAALA_DCT_RSHIFT(y[3], 1);
+    y[63] += y[61];
+    y[61] -= DAALA_DCT_RSHIFT(y[63], 1); /* pass */
+    y[13] -= y[15];
+    y[15] += DAALA_DCT_RSHIFT(y[13], 1); /* pass */
+    y[49] -= y[51];
+    y[51] += DAALA_DCT_RSHIFT(y[49], 1);
+    y[55] -= y[11];
+    y[11] += DAALA_DCT_RSHIFT(y[55], 1); /* pass */
+    y[53] -= y[9];
+    y[9] += DAALA_DCT_RSHIFT(y[53], 1);
+    y[31] = -y[31];
+    y[15] = -y[15];
+    y[7] = -y[7];
+    y[59] = -y[59];
+    y[61] = -y[61];
+    y[37] = -y[37];
+    y[57] = -y[57];
+    /* 14341/16384 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[37] -= (y[27]*14341 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[27] += (y[37]*15137 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[37] -= (y[27]*4161 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[25] -= (y[39]*4161 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[39] += (y[25]*15137 + 8192) >> 14;
+    /* 28681/32768 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[25] -= (y[39]*28681 + 16384) >> 15;
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[29] += (y[35]*19195 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[35] += (y[29]*11585 + 8192) >> 14;
+    /* 29957/32768 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[29] -= (y[35]*29957 + 16384) >> 15;
+    /* 14341/16384 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[41] -= (y[23]*14341 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[23] += (y[41]*15137 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[41] -= (y[23]*4161 + 8192) >> 14;
+    /* 3259/8192 ~= 2*Tan[Pi/16] ~= 0.397824734759316 */
+    y[43] -= (y[21]*3259 + 4096) >> 13;
+    /* 3135/16384 ~= Sin[Pi/8]/2 ~= 0.1913417161825449 */
+    y[21] += (y[43]*3135 + 8192) >> 14;
+    /* 3259/8192 ~= 2*Tan[Pi/16] ~= 0.397824734759316 */
+    y[43] -= (y[21]*3259 + 4096) >> 13;
+    /* 7489/8192 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[45] -= (y[19]*7489 + 4096) >> 13;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[19] += (y[45]*11585 + 8192) >> 14;
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[45] += (y[19]*19195 + 16384) >> 15;
+    /* 14341/16384 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[57] -= (y[7]*14341 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[7] += (y[57]*15137 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[57] -= (y[7]*4161 + 8192) >> 14;
+    /* 4161/16384 ~= Tan[3*Pi/16] - Tan[Pi/8] ~= 0.253965075546204 */
+    y[5] -= (y[59]*4161 + 8192) >> 14;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[59] += (y[5]*15137 + 8192) >> 14;
+    /* 28681/32768 ~= Tan[3*Pi/16] + Tan[Pi/8]/2 ~= 0.875285419105846 */
+    y[5] -= (y[59]*28681 + 16384) >> 15;
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[3] += (y[61]*19195 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[61] += (y[3]*11585 + 8192) >> 14;
+    /* 29957/32768 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[3] -= (y[61]*29957 + 16384) >> 15;
+    /* -19195/32768 ~= Tan[Pi/8] - Tan[Pi/4] ~= -0.585786437626905 */
+    y[13] += (y[51]*19195 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[Pi/4] ~= 0.707106781186548 */
+    y[51] += (y[13]*11585 + 8192) >> 14;
+    /* 29957/32768 ~= Tan[Pi/8] + Tan[Pi/4]/2 ~= 0.914213562373095 */
+    y[13] -= (y[51]*29957 + 16384) >> 15;
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[53] += (y[11]*13573 + 8192) >> 14;
+    /* 11585/32768 ~= Sin[Pi/4]/2 ~= 0.353553390593274 */
+    y[11] -= (y[53]*11585 + 16384) >> 15;
+    /* 13573/16384 ~= 2*Tan[Pi/8] ~= 0.828427124746190 */
+    y[53] += (y[11]*13573 + 8192) >> 14;
+    y[3] = -y[3];
+    /* 1651/32768 ~= (1/Sqrt[2] - Cos[15*Pi/64])/Sin[15*Pi/64] ~=
+        0.05039668360333519 */
+    y[34] += (y[30]*1651 + 16384) >> 15;
+    /* 1945/2048 ~= Sqrt[2]*Sin[15*Pi/64] ~= 0.9497277818777543 */
+    y[30] += (y[34]*1945 + 1024) >> 11;
+    /* 2053/4096 ~= (1/Sqrt[2] - Cos[15*Pi/64]/2)/Sin[15*Pi/64] ~=
+        0.5012683042634027 */
+    y[34] -= (y[30]*2053 + 2048) >> 12;
+    /* 4545/32768 ~= (1/Sqrt[2] - Cos[19*Pi/64])/Sin[19*Pi/64] ~=
+        0.13870322715817154 */
+    y[38] += (y[26]*4545 + 16384) >> 15;
+    /* 4653/32768 ~= Sqrt[2]*Sin[19*Pi/64] ~= 1.1359069844201428 */
+    y[26] -= (y[38]*4653 + 2048) >> 12;
+    /* 2087/4096 ~= (1/Sqrt[2] - Cos[19*Pi/64]/2)/Sin[19*Pi/64] ~=
+        0.5095285002941893 */
+    y[38] += (y[26]*2087 + 2048) >> 12;
+    /* 75/256 ~= (1/Sqrt[2] - Cos[11*Pi/64])/Sin[11*Pi/64] ~=
+        0.2929800132658202 */
+    y[22] -= (y[42]*75 + 128) >> 8;
+    /* 1489/2048 ~= Sqrt[2]*Sin[11*Pi/64] ~= 0.72705107329128 */
+    y[42] -= (y[22]*1489 + 1024) >> 11;
+    /* 2217/4096 ~= (1/Sqrt[2] - Cos[11*Pi/64]/2)/Sin[11*Pi/64] ~=
+        0.5412195895259334 */
+    y[22] += (y[42]*2217 + 2048) >> 12;
+    /* 5067/16384 ~= (1/Sqrt[2] - Cos[23*Pi/64])/Sin[23*Pi/64] ~=
+        0.30924225528198984 */
+    y[18] -= (y[46]*5067 + 8192) >> 14;
+    /* 1309/1024 ~= Sqrt[2]*Sin[23*Pi/64] ~= 1.278433918575241 */
+    y[46] += (y[18]*1309 + 512) >> 10;
+    /* 4471/8192 ~= (1/Sqrt[2] - Cos[23*Pi/64]/2)/Sin[23*Pi/64] ~=
+        0.5457246432276498 */
+    y[18] -= (y[46]*4471 + 4096) >> 13;
+    /* 5701/8192 ~= (1/Sqrt[2] - Cos[7*Pi/64])/Sin[7*Pi/64] ~=
+        0.6958870433047222 */
+    y[14] -= (y[50]*5701 + 4096) >> 13;
+    /* 3903/8192 ~= Sqrt[2]*Sin[7*Pi/64] ~= 0.47643419969316125 */
+    y[50] -= (y[14]*3903 + 4096) >> 13;
+    /* 5747/8192 ~= (1/Sqrt[2] - Cos[7*Pi/64]/2)/Sin[7*Pi/64] ~=
+        0.7015193429405162 */
+    y[14] += (y[50]*5747 + 4096) >> 13;
+    /* 7839/16384 ~= (1/Sqrt[2] - Cos[27*Pi/64])/Sin[27*Pi/64] ~=
+        0.47846561618999817 */
+    y[10] -= (y[54]*7839 + 8192) >> 14;
+    /* 5619/4096 ~= Sqrt[2]*Sin[27*Pi/64] ~= 1.371831354193494 */
+    y[54] += (y[10]*5619 + 2048) >> 12;
+    /* 2473/4096 ~= (1/Sqrt[2] - Cos[27*Pi/64]/2)/Sin[27*Pi/64] ~=
+        0.603709096285651 */
+    y[10] -= (y[54]*2473 + 2048) >> 12;
+    /* 4641/8192 ~= (1/Sqrt[2] - Cos[29*Pi/64])/Sin[29*Pi/64] ~=
+        0.5665078993345056 */
+    y[6] -= (y[58]*4641 + 4096) >> 13;
+    /* 2865/2048 ~= Sqrt[2]*Sin[29*Pi/64] ~= 1.3989068359730783 */
+    y[58] += (y[6]*2865 + 1024) >> 11;
+    /* 41/64 ~= (1/Sqrt[2] - Cos[29*Pi/64]/2)/Sin[29*Pi/64] ~=
+        0.6406758931036793 */
+    y[6] -= (y[58]*41 + 32) >> 6;
+    /* 5397/8192 ~= (Cos[Pi/4] - Cos[31*Pi/64])/Sin[31*Pi/64] ~=
+        0.6588326996993819 */
+    y[62] += (y[2]*5397 + 4096) >> 13;
+    /* 2893/2048 ~= Sqrt[2]*Sin[31*Pi/64] ~= 1.4125100802019777 */
+    y[2] -= (y[62]*2893 + 1024) >> 11;
+    /* 2799/4096 ~= (1/Sqrt[2] - Cos[31*Pi/64]/2)/Sin[31*Pi/64] ~=
+        0.6833961245841154 */
+    y[62] += (y[2]*2799 + 2048) >> 12;
+    y[18] -= DAALA_DCT_RSHIFT(y[50], 1);
+    y[50] += y[18];
+    y[14] += DAALA_DCT_RSHIFT(y[46], 1);
+    y[46] = y[14] - y[46];
+    y[10] += DAALA_DCT_RSHIFT(y[42], 1);
+    y[42] -= y[10];
+    y[22] = DAALA_DCT_RSHIFT(y[54], 1) - y[22];
+    y[54] -= y[22];
+    y[6] = DAALA_DCT_RSHIFT(y[26], 1) - y[6];
+    y[26] -= y[6];
+    y[38] -= DAALA_DCT_RSHIFT(y[58], 1);
+    y[58] += y[38];
+    y[34] = DAALA_DCT_RSHIFT(y[2], 1) - y[34];
+    y[2] -= y[34];
+    y[62] += DAALA_DCT_RSHIFT(y[30], 1);
+    y[30] -= y[62];
+    y[22] -= y[26];
+    y[26] += DAALA_DCT_RSHIFT(y[22], 1);
+    y[42] = y[38] - y[42];
+    y[38] -= DAALA_DCT_RSHIFT(y[42], 1);
+    y[34] += y[46];
+    y[46] -= DAALA_DCT_RSHIFT(y[34], 1);
+    y[30] = y[18] - y[30];
+    y[18] -= DAALA_DCT_RSHIFT(y[30], 1);
+    y[62] += y[14];
+    tmp[16] = DAALA_DCT_RSHIFT(y[62], 1);
+    y[14] = tmp[16] - y[14];
+    y[2] += y[50];
+    tmp[13] = DAALA_DCT_RSHIFT(y[2], 1);
+    y[50] -= tmp[13];
+    y[10] = y[6] - y[10];
+    tmp[14] = DAALA_DCT_RSHIFT(y[10], 1);
+    y[6] -= tmp[14];
+    y[54] -= y[58];
+    tmp[15] = DAALA_DCT_RSHIFT(y[54], 1);
+    y[58] += tmp[15];
+    /* 3227/32768 ~= Tan[Pi/32] ~= 0.09849140335716425 */
+    y[34] -= (y[30]*3227 + 16384) >> 15;
+    /* 6393/32768 ~= Sin[Pi/16] ~= 0.19509032201612825 */
+    y[30] += (y[34]*6393 + 16384) >> 15;
+    /* 3227/32768 ~= Tan[Pi/32] ~= 0.09849140335716425 */
+    y[34] -= (y[30]*3227 + 16384) >> 15;
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[38] -= (y[26]*2485 + 4096) >> 13;
+    /* 18205/32768 ~= Sin[3*Pi/16] ~= 0.555570233019602 */
+    y[26] += (y[38]*18205 + 16384) >> 15;
+    /* 2485/8192 ~= Tan[3*Pi/32] ~= 0.303346683607342 */
+    y[38] -= (y[26]*2485 + 4096) >> 13;
+    /* 8757/16384 ~= Tan[5*Pi/32] ~= 0.534511135950792 */
+    y[22] -= (y[42]*8757 + 8192) >> 14;
+    /* 6811/8192 ~= Sin[5*Pi/16] ~= 0.831469612302545 */
+    y[42] += (y[22]*6811 + 4096) >> 13;
+    /* 8757/16384 ~= Tan[5*Pi/32]) ~= 0.534511135950792 */
+    y[22] -= (y[42]*8757 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32]) ~= 0.820678790828660 */
+    y[46] -= (y[18]*6723 + 4096) >> 13;
+    /* 16069/16384 ~= Sin[7*Pi/16] ~= 0.980785280403230 */
+    y[18] += (y[46]*16069 + 8192) >> 14;
+    /* 6723/8192 ~= Tan[7*Pi/32] ~= 0.820678790828660 */
+    y[46] -= (y[18]*6723 + 4096) >> 13;
+    y[26] += DAALA_DCT_RSHIFT(y[34], 1);
+    y[34] = y[26] - y[34];
+    y[38] += DAALA_DCT_RSHIFT(y[30], 1);
+    y[30] -= y[38];
+    y[18] = DAALA_DCT_RSHIFT(y[42], 1) - y[18];
+    y[42] -= y[18];
+    y[46] += DAALA_DCT_RSHIFT(y[22], 1);
+    y[22] = y[46] - y[22];
+    y[14] -= tmp[14];
+    y[10] += y[14];
+    y[50] += tmp[15];
+    y[54] = y[50] - y[54];
+    y[58] = tmp[16] - y[58];
+    y[62] -= y[58];
+    y[6] = tmp[13] - y[6];
+    y[2] -= y[6];
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[38] -= (y[26]*13573 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[pi/4] ~= 0.707106781186547 */
+    y[26] += (y[38]*11585 + 8192) >> 14;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[38] -= (y[26]*13573 + 16384) >> 15;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[22] -= (y[42]*13573 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[pi/4] ~= 0.707106781186547 */
+    y[42] += (y[22]*11585 + 8192) >> 14;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[22] -= (y[42]*13573 + 16384) >> 15;
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[14] -= (y[50]*3259 + 8192) >> 14;
+    /* 3135/8192 ~= Sin[Pi/8] ~= 0.382683432365090 */
+    y[50] += (y[14]*3135 + 4096) >> 13;
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[14] -= (y[50]*3259 + 8192) >> 14;
+    /* 21895/32768 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[10] -= (y[54]*21895 + 16384) >> 15;
+    /* 15137/16384 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[54] += (y[10]*15137 + 8192) >> 14;
+    /* 21895/32768 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[10] -= (y[54]*21895 + 16384) >> 15;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[58] -= (y[6]*13573 + 16384) >> 15;
+    /* 11585/16384 ~= Sin[pi/4] ~= 0.707106781186547 */
+    y[6] += (y[58]*11585 + 8192) >> 14;
+    /* 13573/32768 ~= Tan[pi/8] ~= 0.414213562373095 */
+    y[58] -= (y[6]*13573 + 16384) >> 15;
+    /* 3393/8192 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[36] -= (y[28]*3393 + 4096) >> 13;
+    /* 5793/8192 ~= Sin[Pi/4] ~= 0.707106781186547 */
+    y[28] += (y[36]*5793 + 4096) >> 13;
+    /* 3393/8192 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[36] -= (y[28]*3393 + 4096) >> 13;
+    /* 2737/4096 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[20] -= (y[44]*2737 + 2048) >> 12;
+    /* 473/512 ~= Sin[3*Pi/8] ~= 0.923879532511287 */
+    y[44] += (y[20]*473 + 256) >> 9;
+    /* 2737/4096 ~= Tan[3*Pi/16] ~= 0.668178637919299 */
+    y[20] -= (y[44]*2737 + 2048) >> 12;
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[52] -= (y[12]*3259 + 8192) >> 14;
+    /* 3135/8192 ~= Sin[Pi/8] ~= 0.382683432365090 */
+    y[12] += (y[52]*3135 + 4096) >> 13;
+    /* 3259/16384 ~= Tan[Pi/16] ~= 0.198912367379658 */
+    y[52] -= (y[12]*3259 + 8192) >> 14;
+    y[60] -= y[36];
+    tmp[7] = DAALA_DCT_RSHIFT(y[60], 1);
+    y[36] += tmp[7];
+    y[44] = y[12] - y[44];
+    tmp[6] = DAALA_DCT_RSHIFT(y[44], 1);
+    y[12] -= tmp[6];
+    y[20] = y[52] - y[20];
+    tmp[5] = DAALA_DCT_RSHIFT(y[20], 1);
+    y[52] -= tmp[5];
+    y[4] += y[28];
+    tmp[4] = DAALA_DCT_RSHIFT(y[4], 1);
+    y[28] = tmp[4] - y[28];
+    y[12] = tmp[4] - y[12];
+    y[4] -= y[12];
+    y[28] -= tmp[5];
+    y[20] += y[28];
+    y[36] -= tmp[6];
+    y[44] += y[36];
+    y[52] += tmp[7];
+    y[60] -= y[52];
+    /* 20055/32768 ~= (1/Sqrt[2] - Sin[Pi/32])/Cos[Pi/32] ~=
+        0.612036765167935 */
+    y[4] -= (y[60]*20055 + 16384) >> 15;
+    /* 11529/8192 ~= Sqrt[2]*Cos[Pi/32] ~= 1.40740373752638 */
+    y[60] += (y[4]*11529 + 4096) >> 13;
+    /* 5417/8192 ~= (Sqrt[2] - Sin[Pi/32])/(2*Cos[Pi/32]) ~=
+        0.661282466846517 */
+    y[4] -= (y[60]*5417 + 4096) >> 13;
+    /* 3525/4096 ~= (Cos[3*Pi/32] - 1/Sqrt[2])/Sin[3*Pi/32] ~=
+        0.860650162139486 */
+    y[28] += (y[36]*3525 + 2048) >> 12;
+    /* 3363/8192 ~= Sqrt[2]*Sin[3*Pi/32] ~= 0.410524527522357 */
+    y[36] += (y[28]*3363 + 4096) >> 13;
+    /* 12905/16384 ~= (1/Sqrt[2] - Cos[3*Pi/32]/1)/Sin[3*Pi/32] ~=
+        0.787628942329675 */
+    y[28] -= (y[36]*12905 + 8192) >> 14;
+    /* 4379/16384 ~= (1/Sqrt[2] - Sin[5*Pi/32])/Cos[5*Pi/32] ~=
+        0.267268807193026 */
+    y[20] -= (y[44]*4379 + 8192) >> 14;
+    /* 10217/8192 ~= Sqrt[2]*Cos[5*Pi/32] ~= 1.24722501298667 */
+    y[44] += (y[20]*10217 + 4096) >> 13;
+    /* 4379/8192 ~= (Sqrt[2] - Sin[5*Pi/32])/(2*Cos[5*Pi/32]) ~=
+        0.534524375168421 */
+    y[20] -= (y[44]*4379 + 4096) >> 13;
+    /* 851/8192 ~= (Cos[7*Pi/32] - 1/Sqrt[2])/Sin[7*Pi/32] ~=
+        0.103884567856159 */
+    y[12] += (y[52]*851 + 4096) >> 13;
+    /* 14699/16384 ~= Sqrt[2]*Sin[7*Pi/32] ~= 0.897167586342636 */
+    y[52] += (y[12]*14699 + 8192) >> 14;
+    /* 1035/2048 ~= (Sqrt[2] - Cos[7*Pi/32])/(2*Sin[7*Pi/32]) ~=
+        0.505367194937830 */
+    y[12] -= (y[52]*1035 + 1024) >> 11;
+    /* 8553/16384 ~= (1/Sqrt[2] - Cos[7*Pi/16])/Sin[7*Pi/16] ~=
+        0.52204745462729 */
+    y[8] -= (y[56]*8553 + 8192) >> 14;
+    /* 5681/4096 ~= Sqrt[2]*Sin[7*Pi/16] ~= 1.38703984532215 */
+    y[56] += (y[8]*5681 + 2048) >> 12;
+    /* 5091/8192 ~= (1/Sqrt[2] - Cos[7*Pi/16]/2)/Sin[7*Pi/16] ~=
+        0.6215036383171189 */
+    y[8] -= (y[56]*5091 + 4096) >> 13;
+    /* 7335/32768 ~= (1/Sqrt[2] - Cos[3*Pi/16])/Sin[3*Pi/16] ~=
+        0.223847182092655 */
+    y[24] -= (y[40]*7335 + 16384) >> 15;
+    /* 1609/2048 ~= Sqrt[2]*Sin[3*Pi/16] ~= 0.785694958387102 */
+    y[40] -= (y[24]*1609 + 1024) >> 11;
+    /* 537/1024 ~= (1/Sqrt[2] - Cos[3*Pi/16]/2)/Sin[3*Pi/16] ~=
+        0.524455699240090 */
+    y[24] += (y[40]*537 + 512) >> 10;
+    tmp[2] = DAALA_DCT_RSHIFT(y[40], 1);
+    y[8] += tmp[2];
+    y[40] -= y[8];
+    tmp[3] = DAALA_DCT_RSHIFT(y[56], 1);
+    y[24] = tmp[3] - y[24];
+    y[56] -= y[24];
+    /* 3393/8192 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[24] -= (y[40]*3393 + 4096) >> 13;
+    /* 5793/8192 ~= Sin[Pi/4] ~= 0.707106781186547 */
+    y[40] += (y[24]*5793 + 4096) >> 13;
+    /* 13573/32768 ~= Tan[Pi/8] ~= 0.414213562373095 */
+    y[24] -= (y[40]*13573 + 16384) >> 15;
+    /* 4573/4096 ~= 4*Sin[Pi/8] - Tan[Pi/8] ~= 1.11652016708726 */
+    y[48] += (y[16]*4573 + 2048) >> 12;
+    /* 669/1024 ~= Cos[Pi/8]/Sqrt[2] ~= 0.653281482438188 */
+    y[16] -= (y[48]*669 + 512) >> 10;
+    /* 11507/16384 ~= 4*Sin[Pi/8] - 2*Tan[Pi/8] ~= 0.702306604714169 */
+    y[48] += (y[16]*11507 + 8192) >> 14;
+    y[32] = y[0] - y[32];
+    tmp[1] = DAALA_DCT_RSHIFT(y[32], 1);
+    y[0] -= tmp[1];
+    tmp[0] = DAALA_DCT_RSHIFT(y[48], 1);
+    y[0] += tmp[0];
+    y[48] = y[0] - y[48];
+    y[16] = tmp[1] - y[16];
+    y[32] -= y[16];
+    y[56] = y[0] - y[56];
+    tmp[9] = DAALA_DCT_RSHIFT(y[56], 1);
+    y[0] -= tmp[9];
+    y[32] += y[24];
+    tmp[12] = DAALA_DCT_RSHIFT(y[32], 1);
+    y[24] = tmp[12] - y[24];
+    y[40] = y[16] - y[40];
+    tmp[10] = DAALA_DCT_RSHIFT(y[40], 1);
+    y[16] -= tmp[10];
+    y[48] += y[8];
+    tmp[11] = DAALA_DCT_RSHIFT(y[48], 1);
+    y[8] = tmp[11] - y[8];
+    tmp[8] = DAALA_DCT_RSHIFT(y[60], 1);
+    y[0] += tmp[8];
+    y[60] = y[0] - y[60];
+    y[28] = tmp[12] - y[28];
+    y[32] -= y[28];
+    y[16] += DAALA_DCT_RSHIFT(y[44], 1);
+    y[44] = y[16] - y[44];
+    y[12] = tmp[11] - y[12];
+    y[48] -= y[12];
+    y[8] += DAALA_DCT_RSHIFT(y[52], 1);
+    y[52] = y[8] - y[52];
+    y[20] = tmp[10] - y[20];
+    y[40] -= y[20];
+    y[24] += DAALA_DCT_RSHIFT(y[36], 1);
+    y[36] = y[24] - y[36];
+    y[4] = tmp[9] - y[4];
+    y[56] -= y[4];
+    y[62] = y[0] - y[62];
+    tmp[41] = DAALA_DCT_RSHIFT(y[62], 1);
+    y[0] -= tmp[41];
+    y[32] += y[30];
+    tmp[56] = DAALA_DCT_RSHIFT(y[32], 1);
+    y[30] = tmp[56] - y[30];
+    y[46] = y[16] - y[46];
+    tmp[42] = DAALA_DCT_RSHIFT(y[46], 1);
+    y[16] -= tmp[42];
+    y[48] += y[14];
+    tmp[55] = DAALA_DCT_RSHIFT(y[48], 1);
+    y[14] = tmp[55] - y[14];
+    y[54] = y[8] - y[54];
+    tmp[43] = DAALA_DCT_RSHIFT(y[54], 1);
+    y[8] -= tmp[43];
+    y[40] += y[22];
+    tmp[54] = DAALA_DCT_RSHIFT(y[40], 1);
+    y[22] = tmp[54] - y[22];
+    y[38] = y[24] - y[38];
+    tmp[44] = DAALA_DCT_RSHIFT(y[38], 1);
+    y[24] -= tmp[44];
+    y[56] += y[6];
+    tmp[53] = DAALA_DCT_RSHIFT(y[56], 1);
+    y[6] = tmp[53] - y[6];
+    y[58] = y[4] - y[58];
+    tmp[45] = DAALA_DCT_RSHIFT(y[58], 1);
+    y[4] -= tmp[45];
+    y[36] += y[26];
+    tmp[52] = DAALA_DCT_RSHIFT(y[36], 1);
+    y[26] = tmp[52] - y[26];
+    y[42] = y[20] - y[42];
+    tmp[46] = DAALA_DCT_RSHIFT(y[42], 1);
+    y[20] -= tmp[46];
+    y[52] += y[10];
+    tmp[51] = DAALA_DCT_RSHIFT(y[52], 1);
+    y[10] = tmp[51] - y[10];
+    y[50] = y[12] - y[50];
+    tmp[47] = DAALA_DCT_RSHIFT(y[50], 1);
+    y[12] -= tmp[47];
+    y[44] += y[18];
+    tmp[50] = DAALA_DCT_RSHIFT(y[44], 1);
+    y[18] = tmp[50] - y[18];
+    y[34] = y[28] - y[34];
+    tmp[48] = DAALA_DCT_RSHIFT(y[34], 1);
+    y[28] -= tmp[48];
+    y[60] += y[2];
+    tmp[49] = DAALA_DCT_RSHIFT(y[60], 1);
+    y[2] = tmp[49] - y[2];
+    tmp[25] = DAALA_DCT_RSHIFT(y[63], 1);
+    y[0] += tmp[25];
+    y[63] = y[0] - y[63];
+    y[31] = tmp[56] - y[31];
+    y[32] -= y[31];
+    tmp[26] = DAALA_DCT_RSHIFT(y[47], 1);
+    y[16] += tmp[26];
+    y[47] = y[16] - y[47];
+    y[15] = tmp[55] - y[15];
+    y[48] -= y[15];
+    tmp[27] = DAALA_DCT_RSHIFT(y[55], 1);
+    y[8] += tmp[27];
+    y[55] = y[8] - y[55];
+    y[23] = tmp[54] - y[23];
+    y[40] -= y[23];
+    tmp[28] = DAALA_DCT_RSHIFT(y[39], 1);
+    y[24] += tmp[28];
+    y[39] = y[24] - y[39];
+    y[7] = tmp[53] - y[7];
+    y[56] -= y[7];
+    tmp[29] = DAALA_DCT_RSHIFT(y[59], 1);
+    y[4] += tmp[29];
+    y[59] = y[4] - y[59];
+    y[27] = tmp[52] - y[27];
+    y[36] -= y[27];
+    tmp[30] = DAALA_DCT_RSHIFT(y[43], 1);
+    y[20] += tmp[30];
+    y[43] = y[20] - y[43];
+    y[11] = tmp[51] - y[11];
+    y[52] -= y[11];
+    tmp[31] = DAALA_DCT_RSHIFT(y[51], 1);
+    y[12] += tmp[31];
+    y[51] = y[12] - y[51];
+    y[19] = tmp[50] - y[19];
+    y[44] -= y[19];
+    tmp[32] = DAALA_DCT_RSHIFT(y[35], 1);
+    y[28] += tmp[32];
+    y[35] = y[28] - y[35];
+    y[3] = tmp[49] - y[3];
+    y[60] -= y[3];
+    tmp[33] = DAALA_DCT_RSHIFT(y[61], 1);
+    y[2] += tmp[33];
+    y[61] = y[2] - y[61];
+    y[29] = tmp[48] - y[29];
+    y[34] -= y[29];
+    tmp[34] = DAALA_DCT_RSHIFT(y[45], 1);
+    y[18] += tmp[34];
+    y[45] = y[18] - y[45];
+    y[13] = tmp[47] - y[13];
+    y[50] -= y[13];
+    tmp[35] = DAALA_DCT_RSHIFT(y[53], 1);
+    y[10] += tmp[35];
+    y[53] = y[10] - y[53];
+    y[21] = tmp[46] - y[21];
+    y[42] -= y[21];
+    tmp[36] = DAALA_DCT_RSHIFT(y[37], 1);
+    y[26] += tmp[36];
+    y[37] = y[26] - y[37];
+    y[5] = tmp[45] - y[5];
+    y[58] -= y[5];
+    tmp[37] = DAALA_DCT_RSHIFT(y[57], 1);
+    y[6] += tmp[37];
+    y[57] = y[6] - y[57];
+    y[25] = tmp[44] - y[25];
+    y[38] -= y[25];
+    tmp[38] = DAALA_DCT_RSHIFT(y[41], 1);
+    y[22] += tmp[38];
+    y[41] = y[22] - y[41];
+    y[9] = tmp[43] - y[9];
+    y[54] -= y[9];
+    tmp[39] = DAALA_DCT_RSHIFT(y[49], 1);
+    y[14] += tmp[39];
+    y[49] = y[14] - y[49];
+    y[17] = tmp[42] - y[17];
+    y[46] -= y[17];
+    tmp[40] = DAALA_DCT_RSHIFT(y[33], 1);
+    y[30] += tmp[40];
+    y[33] = y[30] - y[33];
+    y[1] = tmp[41] - y[1];
+    y[62] -= y[1];
+    WRITE(x +  0*xstride,  y[0]);
+    WRITE(x +  1*xstride, y[32]);
+    WRITE(x +  2*xstride, y[16]);
+    WRITE(x +  3*xstride, y[48]);
+    WRITE(x +  4*xstride,  y[8]);
+    WRITE(x +  5*xstride, y[40]);
+    WRITE(x +  6*xstride, y[24]);
+    WRITE(x +  7*xstride, y[56]);
+    WRITE(x +  8*xstride,  y[4]);
+    WRITE(x +  9*xstride, y[36]);
+    WRITE(x + 10*xstride, y[20]);
+    WRITE(x + 11*xstride, y[52]);
+    WRITE(x + 12*xstride, y[12]);
+    WRITE(x + 13*xstride, y[44]);
+    WRITE(x + 14*xstride, y[28]);
+    WRITE(x + 15*xstride, y[60]);
+    WRITE(x + 16*xstride,  y[2]);
+    WRITE(x + 17*xstride, y[34]);
+    WRITE(x + 18*xstride, y[18]);
+    WRITE(x + 19*xstride, y[50]);
+    WRITE(x + 20*xstride, y[10]);
+    WRITE(x + 21*xstride, y[42]);
+    WRITE(x + 22*xstride, y[26]);
+    WRITE(x + 23*xstride, y[58]);
+    WRITE(x + 24*xstride,  y[6]);
+    WRITE(x + 25*xstride, y[38]);
+    WRITE(x + 26*xstride, y[22]);
+    WRITE(x + 27*xstride, y[54]);
+    WRITE(x + 28*xstride, y[14]);
+    WRITE(x + 29*xstride, y[46]);
+    WRITE(x + 30*xstride, y[30]);
+    WRITE(x + 31*xstride, y[62]);
+    WRITE(x + 32*xstride,  y[1]);
+    WRITE(x + 33*xstride, y[33]);
+    WRITE(x + 34*xstride, y[17]);
+    WRITE(x + 35*xstride, y[49]);
+    WRITE(x + 36*xstride,  y[9]);
+    WRITE(x + 37*xstride, y[41]);
+    WRITE(x + 38*xstride, y[25]);
+    WRITE(x + 39*xstride, y[57]);
+    WRITE(x + 40*xstride,  y[5]);
+    WRITE(x + 41*xstride, y[37]);
+    WRITE(x + 42*xstride, y[21]);
+    WRITE(x + 43*xstride, y[53]);
+    WRITE(x + 44*xstride, y[13]);
+    WRITE(x + 45*xstride, y[45]);
+    WRITE(x + 46*xstride, y[29]);
+    WRITE(x + 47*xstride, y[61]);
+    WRITE(x + 48*xstride,  y[3]);
+    WRITE(x + 49*xstride, y[35]);
+    WRITE(x + 50*xstride, y[19]);
+    WRITE(x + 51*xstride, y[51]);
+    WRITE(x + 52*xstride, y[11]);
+    WRITE(x + 53*xstride, y[43]);
+    WRITE(x + 54*xstride, y[27]);
+    WRITE(x + 55*xstride, y[59]);
+    WRITE(x + 56*xstride,  y[7]);
+    WRITE(x + 57*xstride, y[39]);
+    WRITE(x + 58*xstride, y[23]);
+    WRITE(x + 59*xstride, y[55]);
+    WRITE(x + 60*xstride, y[15]);
+    WRITE(x + 61*xstride, y[47]);
+    WRITE(x + 62*xstride, y[31]);
+    WRITE(x + 63*xstride, y[63]);
+}
+
+#define IDCT_DECL(BSIZE)                                                       \
+static void RENAME(idct_2D_##BSIZE)(uint8_t *dst, int dstride,                 \
+                                    const uint8_t *_src, int istride)          \
+{                                                                              \
+    int i, j;                                                                  \
+    pixel coef[BSIZE], tmp[BSIZE*BSIZE];                                       \
+    pixel *dstr = (pixel *)dst;                                                \
+    const pixel *src = (pixel *)_src;                                          \
+    for (i = 0; i < BSIZE; i++) {                                              \
+        for (j = 0; j < BSIZE; j++)                                            \
+            coef[j] = READ(src + i*istride + j);                               \
+        idct_1D_##BSIZE(tmp + i, BSIZE, coef);                                 \
+    }                                                                          \
+    for (i = 0; i < BSIZE; i++)                                                \
+        idct_1D_##BSIZE(dstr + i, dstride, tmp + BSIZE*i);                     \
+}
+
+IDCT_DECL(4)
+IDCT_DECL(8)
+IDCT_DECL(16)
+IDCT_DECL(32)
+IDCT_DECL(64)
+
+#define FILTER_PARAM_4_3 (33)
+#define FILTER_PARAM_4_2 (-15)
+#define FILTER_PARAM_4_1 (75)
+#define FILTER_PARAM_4_0 (85)
+
+static av_always_inline void prefilter_4x4(pixel *dst, const pixel *src)
+{
+    pixel t[4];
+    t[3] = src[0]-src[3];
+    t[2] = src[1]-src[2];
+    t[1] = src[1]-(t[2]>>1);
+    t[0] = src[0]-(t[3]>>1);
+    # if FILTER_PARAM_4_0 != 64
+    t[2] = t[2]*FILTER_PARAM_4_0>>6;
+    t[2] += -t[2]>>(32-1)&1;
+    # endif
+    # if FILTER_PARAM_4_1 != 64
+    t[3] = t[3]*FILTER_PARAM_4_1>>6;
+    t[3] += -t[3]>>(32-1)&1;
+    # endif
+    t[3] += (t[2]*FILTER_PARAM_4_2+32)>>6;
+    t[2] += (t[3]*FILTER_PARAM_4_3+32)>>6;
+    t[0] += t[3]>>1;
+    dst[0] = (pixel)t[0];
+    t[1] += t[2]>>1;
+    dst[1] = t[1];
+    dst[2] = t[1] - t[2];
+    dst[3] = t[0] - t[3];
+}
+
+static av_always_inline void postfilter_4x4(pixel *dst, const pixel *src)
+{
+    pixel t[4];
+    t[3] = src[0]-src[3];
+    t[2] = src[1]-src[2];
+    t[1] = src[1]-(t[2]>>1);
+    t[0] = src[0]-(t[3]>>1);
+    t[2] -= (t[3]*FILTER_PARAM_4_3+32)>>6;
+    t[3] -= (t[2]*FILTER_PARAM_4_2+32)>>6;
+    #if FILTER_PARAM_4_1 != 64
+    t[3] = t[3]*(1 << 6)/FILTER_PARAM_4_1;
+    #endif
+    #if FILTER_PARAM_4_0 != 64
+    t[2] = t[2]*(1 << 6)/FILTER_PARAM_4_0;
+    #endif
+    t[0] += t[3]>>1;
+    dst[0] = t[0];
+    t[1] += t[2]>>1;
+    dst[1] = t[1];
+    dst[2] = t[1] - t[2];
+    dst[3] = t[0] - t[3];
+}
+
+static void RENAME(daala_split_prefilter)(uint8_t *_blk, int stride, int bs,
+                                          int hfilter, int vfilter)
+{
+    int i, j;
+    const int f = 0;
+    pixel *c;
+    pixel *blk = (pixel *)_blk;
+    if (hfilter) {
+        c = blk + ((2 << bs) - (2 << f))*stride;
+        for (j = 0; j < 4 << bs; j++) {
+            int k;
+            pixel t[4 << DAALA_NBSIZES];
+            for (k = 0; k < 4 << f; k++) t[k] = c[stride*k + j];
+            prefilter_4x4(t, t);
+            for (k = 0; k < 4 << f; k++) c[stride*k + j] = t[k];
+        }
+    }
+    if (vfilter) {
+        c = blk + (2 << bs) - (2 << f);
+        for (i = 0; i < 4 << bs; i++) {
+            prefilter_4x4(c + i*stride, c + i*stride);
+        }
+    }
+}
+
+
+static void RENAME(daala_split_postfilter)(uint8_t *_blk, int stride, int bs,
+                                           int hfilter, int vfilter)
+{
+    int i, j;
+    const int f = 0;
+    pixel *c;
+    pixel *blk = (pixel *)_blk;
+    if (vfilter) {
+        c = blk + (2 << bs) - (2 << f);
+        for (i = 0; i < 4 << bs; i++) {
+            postfilter_4x4(c + i*stride, c + i*stride);
+        }
+    }
+    if (hfilter) {
+        c = blk + ((2 << bs) - (2 << f))*stride;
+        for (j = 0; j < 4 << bs; j++) {
+            int k;
+            pixel t[4 << DAALA_NBSIZES];
+            for (k = 0; k < 4 << f; k++) t[k] = c[stride*k + j];
+            postfilter_4x4(t, t);
+            for (k = 0; k < 4 << f; k++) c[stride*k + j] = t[k];
+        }
+    }
+}
+
+static void RENAME(daala_frame_postfilter)(uint8_t *_blk, int stride,
+                                           int sbn_x, int sbn_y,
+                                           int xdec, int ydec)
+{
+    int i, j, f;
+    pixel *c;
+    pixel *blk = (pixel *)_blk;
+    f = 0;
+    c = blk + (DAALA_BSIZE_MAX >> ydec) - (2 << f);
+    for (i = 1; i < sbn_x; i++) {
+        for (j = 0; j < sbn_y << DAALA_LOG_BSIZE_MAX >> ydec; j++) {
+            postfilter_4x4(c + j*stride, c + j*stride);
+        }
+        c += DAALA_BSIZE_MAX >> xdec;
+    }
+    c = blk + ((DAALA_BSIZE_MAX >> ydec) - (2 << f))*stride;
+    for (i = 1; i < sbn_y; i++) {
+        for (j = 0; j < sbn_x << DAALA_LOG_BSIZE_MAX >> xdec; j++) {
+            int k;
+            pixel t[4 << DAALA_NBSIZES];
+            for (k = 0; k < 4 << f; k++) t[k] = c[stride*k + j];
+            postfilter_4x4(t, t);
+            for (k = 0; k < 4 << f; k++) c[stride*k + j] = t[k];
+        }
+        c += DAALA_BSIZE_MAX*stride >> ydec;
+    }
+}
+
+/* Increase horizontal frequency resolution of a block and return the LF */
+static av_always_inline void daala_sf_hor_up(pixel *dst, int dstride,
+                                             const pixel *src, int istride,
+                                             int dx, int n)
+{
+    int x, y;
+    for (y = 0; y < n; y++) {
+        for (x = 0; x < n >> 1; x++) {
+            const int hswap = x & 1;
+            pixel ll = src[y*istride + x];
+            pixel lh = src[y*istride + x + dx];
+            lh = ll - lh;
+            ll -= DAALA_DCT_RSHIFT(lh, 1);
+            dst[y*dstride + 2*x + hswap] = ll;
+            dst[y*dstride + 2*x + 1 - hswap] = lh;
+        }
+    }
+}
+
+/* Increase vertical frequency resolution of a block and return the LF */
+static av_always_inline void daala_sf_ver_up(pixel *dst, int dstride,
+                                             const pixel *src, int istride,
+                                             int dy, int n)
+{
+    int x, y;
+    for (y = 0; y < n >> 1; y++) {
+        const int vswap = y & 1;
+        for (x = 0; x < n; x++) {
+            pixel ll = src[y*istride + x];
+            pixel hl = src[(y + dy)*istride + x];
+            hl = ll - hl;
+            ll -= DAALA_DCT_RSHIFT(hl, 1);
+            dst[(2*y + vswap)*dstride + x] = ll;
+            dst[(2*y + 1 - vswap)*dstride + x] = hl;
+        }
+    }
+}
+
+/* Increase vertical and horizontal resolution of a block and return the LF */
+static av_always_inline void daala_sf_ful_up(pixel *dst, int dstride,
+                                             const pixel *src, int istride,
+                                             int dx, int dy, int n)
+{
+    int x, y;
+    for (y = 0; y < n >> 1; y++) {
+        const int vswap = y & 1;
+        for (x = 0; x < n >> 1; x++) {
+            const int hswap = x & 1;
+            pixel ll = src[y*istride + x];
+            pixel lh = src[y*istride + x + dx];
+            pixel hl = src[(y + dy)*istride + x];
+            pixel hh = src[(y + dy)*istride + x + dx];
+            daala_haar_kern(&ll, &hl, &lh, &hh);
+            dst[(2*y + vswap)*dstride + 2*x + hswap] = ll;
+            dst[(2*y + vswap)*dstride + 2*x + 1 - hswap] = lh;
+            dst[(2*y + 1 - vswap)*dstride + 2*x + hswap] = hl;
+            dst[(2*y + 1 - vswap)*dstride + 2*x + 1 - hswap] = hh;
+        }
+    }
+}
+
+/* Chroma from luma */
+static void RENAME(daala_cfl_resample)(uint8_t *_dst, int dstride,
+                                       const uint8_t *_src, int istride,
+                                       int xdec, int ydec, int bs, int chroma_bs)
+{
+    int i, j;
+    const int n = 4 << bs;
+    pixel *dst = (pixel *)_dst;
+    pixel *src = (pixel *)_src;
+    if (!chroma_bs && (xdec || ydec)) {
+        if (xdec) {
+            if (ydec) {
+                daala_sf_ful_up(dst, dstride, src, istride, n, n, n);
+                for (i = 0; i < 4; i++) {
+                    for (j = 0; j < 4; j++) {
+                        const uint8_t scale = ff_daaladsp_cfl_scale[j][i];
+                        dst[i*dstride + j] = (scale*dst[i*dstride + j] + 64) >> 7;
+                    }
+                }
+            } else {
+                daala_sf_hor_up(dst, dstride, src, istride, n, n);
+            }
+        } else {
+            daala_sf_ver_up(dst, dstride, src, istride, n, n);
+        }
+    } else {
+        for (i = 0; i < n; i++) {
+            for (j = 0; j < n; j++) {
+                dst[i*dstride + j] = src[i*istride + j];
+            }
+        }
+    }
+}
+
+static void RENAME(daala_intra_prediction)(uint8_t *_pred, const uint8_t *_ref,
+                                           int stride, int x, int y,
+                                           enum DaalaBsize *bsize, int bstride,
+                                           enum DaalaBsize bs)
+{
+    int i;
+    int64_t g1 = 0, g2 = 0;
+    const int n = 1 << (bs + DAALA_LOG_BSIZE0);
+    const int t = y && DAALA_BSIZE4x4(bsize, bstride, x, y - 1) == bs;
+    const int l = x && DAALA_BSIZE4x4(bsize, bstride, x - 1, y) == bs;
+    pixel *pred = (pixel *)_pred;
+    const pixel *ref = (const pixel *)_ref;
+    if (t) {
+        for (i = 1; i < 4; i++)
+            g1 += abs(ref[-n*stride + i]);
+    }
+    if (l) {
+        for (i = 1; i < 4; i++)
+            g2 += abs(ref[-n + i*stride]);
+    }
+    if (t) {
+        for (i = 4; i < n; i++)
+            pred[i] = ref[-n*stride + i];
+    }
+    if (l) {
+        for (i = 4; i < n; i++)
+            pred[i*n] = ref[-n + i*stride];
+    }
+    if (g1 > g2) {
+        if (t)
+            for (i = 1; i < 4; i++)
+                pred[i] = ref[-n*stride + i];
+    } else if (l) {
+        for (i = 1; i < 4; i++)
+            pred[i*n] = ref[-n + i*stride];
+    }
+}
+
+static void RENAME(daaladsp_init)(DaalaDSP *d)
+{
+    /* Prediction */
+    d->cfl                         = RENAME(daala_cfl_resample    );
+    d->intrapred                   = RENAME(daala_intra_prediction);
+
+    /* Filters */
+    d->pre_split_filter            = RENAME(daala_split_prefilter );
+    d->post_split_filter           = RENAME(daala_split_postfilter);
+    d->frame_postfilter            = RENAME(daala_frame_postfilter);
+
+    /* Transforms */
+    d->idwt                        = RENAME(daala_haar_iwt);
+    d->idct[DAALA_BLOCKSIZE_4x4]   = RENAME(idct_2D_4     );
+    d->idct[DAALA_BLOCKSIZE_8x8]   = RENAME(idct_2D_8     );
+    d->idct[DAALA_BLOCKSIZE_16x16] = RENAME(idct_2D_16    );
+    d->idct[DAALA_BLOCKSIZE_32x32] = RENAME(idct_2D_32    );
+    d->idct[DAALA_BLOCKSIZE_64x64] = RENAME(idct_2D_64    );
+}
+
+#undef RENAME
+#undef WRITE
+#undef READ
+#undef pixel
+
+av_cold int ff_daaladsp_init(DaalaDSP *d, int bit_depth)
+{
+    switch(bit_depth) {
+    case 8:
+        daaladsp_init_8bit(d);
+        break;
+    case 10:
+    case 12:
+    default:
+        return 1;
+        break;
+    }
+    return 0;
+}
diff --git a/libavcodec/daaladsp.h b/libavcodec/daaladsp.h
new file mode 100644
index 0000000..67bcc1d
--- /dev/null
+++ b/libavcodec/daaladsp.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALADSP_H
+#define AVCODEC_DAALADSP_H
+
+#include "daala.h"
+
+/* Haar transform (external), internally in daaladct.c it's manually inlined */
+static av_always_inline void daala_haar_kern(dctcoef *a, dctcoef *b,
+                                             dctcoef *c, dctcoef *d)
+{
+    dctcoef tmp;
+    *a += *c;
+    *d -= *b;
+    tmp = (*a - *d) >> 1;
+    *b = tmp - *b;
+    *c = tmp - *c;
+    *a -= *b;
+    *d += *c;
+}
+
+typedef struct DaalaDSP {
+
+    /* Intra-block prediction */
+    void (*intrapred)(uint8_t *pred, const uint8_t *ref,
+                      int stride, int x, int y,
+                      enum DaalaBsize *bsize, int bstride,
+                      enum DaalaBsize bs);
+
+    /* Chroma from luma */
+    void (*cfl)(uint8_t *dst, int dstride, const uint8_t *src,
+                int istride, int xdec, int ydec, int bs, int chroma_bs);
+
+    /* Pre-split filter */
+    void (*pre_split_filter)(uint8_t *blk, int stride, int bs,
+                             int hfilter, int vfilter);
+
+    /* Post-split filter */
+    void (*post_split_filter)(uint8_t *blk, int stride, int bs,
+                              int hfilter, int vfilter);
+
+    /* Frame postfilter */
+    void (*frame_postfilter)(uint8_t *blk, int stride, int sbn_x, int sbn_y,
+                             int xdec, int ydec);
+
+    /* IDWT for the Haar wavelets */
+    void (*idwt)(uint8_t *dst, const int dst_stride, const uint8_t *src,
+                 const int src_stride, const int ln);
+
+    /* IDCT transforms */
+    void (*(idct)[DAALA_NBSIZES])(uint8_t *dst, int istride, const uint8_t *src,
+                                  int ostride);
+
+} DaalaDSP;
+
+int ff_daaladsp_init(DaalaDSP *d, int bit_depth);
+
+#endif /* AVCODEC_DAALADSP_H */
diff --git a/libavcodec/daalatab.c b/libavcodec/daalatab.c
new file mode 100644
index 0000000..2b5e2aa
--- /dev/null
+++ b/libavcodec/daalatab.c
@@ -0,0 +1,1564 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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 "daalatab.h"
+
+const struct DaalaPixFmts ff_daala_valid_formats[] = {
+    {AV_PIX_FMT_YUV420P,      3,  8, 1, {{0,0}, {1,1}, {1,1}, {0,0}}},
+    {AV_PIX_FMT_YUV444P,      3,  8, 1, {{0,0}, {0,0}, {0,0}, {0,0}}}
+};
+const int ff_daala_valid_formats_num = FF_ARRAY_ELEMS(ff_daala_valid_formats);
+
+/* Haar "quantization matrix" for each decomposition level */
+const uint8_t ff_daala_haar_qm[][DAALA_LOG_BSIZE_MAX] = {
+    {16, 16, 16, 16, 24, 32}, /* horizontal/vertical direction. */
+    {16, 16, 16, 24, 32, 48}, /* "diagonal" direction. */
+};
+
+/* Keyframe blur filter strength for every plane */
+const uint8_t ff_daala_bilinear_blur[] = {5, 20, 20, 5};
+
+/* Haar basis scaling compensation, [0] - x,y; [1] - diag */
+const uint8_t ff_daala_dc_comp[][2] = { {21, 25}, {18, 20}, {17, 18}, {17, 17} };
+
+/* Flat (e.g. PSNR) QM */
+const uint8_t daala_qm_flat[] = {
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16
+};
+
+/* HVS quantization matrix */
+static const uint8_t daala_qm_hvs[] = {
+    16, 16, 18, 21, 24, 28, 32, 36,
+    16, 17, 20, 21, 24, 27, 31, 35,
+    18, 20, 24, 25, 27, 31, 33, 38,
+    21, 21, 25, 28, 30, 34, 37, 42,
+    24, 24, 27, 30, 34, 38, 43, 49,
+    28, 27, 31, 34, 38, 44, 50, 58,
+    32, 31, 33, 37, 43, 50, 58, 68,
+    36, 35, 38, 42, 49, 58, 68, 78
+};
+
+const uint8_t *const ff_daala_qmatrices[] = {
+    daala_qm_flat,
+    daala_qm_hvs
+};
+const int ff_daala_qmatrices_num = FF_ARRAY_ELEMS(ff_daala_qmatrices);
+
+/* Chroma from luma scaling */
+const uint8_t ff_daaladsp_cfl_scale[4][4] = {
+    { 128, 128, 100,  36 },
+    { 128,  80,  71,  35 },
+    { 100,  71,  35,  31 },
+    {  36,  35,  31,  18 },
+};
+
+/* Generator: "trunc(e(((coded_quantizer)-6.235)*.10989525)*(1<<4))"
+ * Read the comment in quantizers.c, OD_CODED_QUANTIZER_MAP_Q4 of libdaala */
+const int ff_daala_quant_codemap[] = {
+    0x0000,                                          /*  0 (lossless) */
+    0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000F,  /*  1 */
+    0x0011, 0x0013, 0x0015, 0x0018, 0x001B, 0x001E,  /*  7 */
+    0x0021, 0x0024, 0x0029, 0x002E, 0x0034, 0x003A,  /* 13 */
+    0x0041, 0x0048, 0x0051, 0x005A, 0x0064, 0x0070,  /* 19 */
+    0x007D, 0x008C, 0x009C, 0x00AE, 0x00C3, 0x00D9,  /* 25 */
+    0x00F3, 0x010F, 0x012F, 0x0152, 0x0179, 0x01A5,  /* 31 */
+    0x01D6, 0x020D, 0x0249, 0x028E, 0x02DA, 0x032E,  /* 37 */
+    0x038D, 0x03F7, 0x046D, 0x04F0, 0x0583, 0x0627,  /* 43 */
+    0x06De, 0x07AA, 0x088E, 0x098D, 0x0AA9, 0x0BE6,  /* 49 */
+    0x0D48, 0x0ED3, 0x108C, 0x1278, 0x149D, 0x1702,  /* 55 */
+    0x19AE, 0x1CAA, 0x1FFF                           /* 61 */
+};
+const int ff_daala_quant_codemap_size = FF_ARRAY_ELEMS(ff_daala_quant_codemap);
+
+/* Probability distribution functions */
+const ent_rng ff_daalaent_cdf_tab[] = {
+    16384, 32768, 10923, 21845, 32768,  8192, 16384, 24576, 32768,  6554, 13107,
+    19661, 26214, 32768,  5461, 10923, 16384, 21845, 27307, 32768,  4681,  9362,
+    14043, 18725, 23406, 28087, 32768,  4096,  8192, 12288, 16384, 20480, 24576,
+    28672, 32768,  3641,  7282, 10923, 14564, 18204, 21845, 25486, 29127, 32768,
+    3277,   6554,  9830, 13107, 16384, 19661, 22938, 26214, 29491, 32768,  2979,
+    5958,   8937, 11916, 14895, 17873, 20852, 23831, 26810, 29789, 32768,  2731,
+    5461,   8192, 10923, 13653, 16384, 19115, 21845, 24576, 27307, 30037, 32768,
+    2521,   5041,  7562, 10082, 12603, 15124, 17644, 20165, 22686, 25206, 27727,
+    30247, 32768,  341,   4681,  7022,  9362, 11703, 14043, 16384, 18725, 21065,
+    23406, 25746, 28087, 30427, 32768,  2185,  4369,  6554,  8738, 10923, 13107,
+    15292, 17476, 19661, 21845, 24030, 26214, 28399, 30583, 32768,  2048,  4096,
+    6144,   8192, 10240, 12288, 14336, 16384, 18432, 20480, 22528, 24576, 26624,
+    28672, 30720, 32768
+};
+
+/* TODO: maybe generate on runtime if cheap enough? */
+const ent_rng ff_daalaent_cdf_exp_tab[][16] = {
+    {32753,32754,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {32499,32753,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {32243,32747,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {31987,32737,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {31732,32724,32755,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {31476,32706,32754,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {31220,32684,32753,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {30964,32658,32751,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {30708,32628,32748,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {30452,32594,32745,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {30198,32558,32742,32756,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {29941,32515,32736,32755,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {29686,32470,32731,32755,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {29429,32419,32723,32754,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {29174,32366,32715,32753,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {28918,32308,32705,32752,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {28662,32246,32694,32750,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {28406,32180,32681,32748,32757,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {28150,32110,32667,32745,32756,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {27894,32036,32651,32742,32756,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {27639,31959,32634,32739,32755,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {27383,31877,32614,32735,32755,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {27126,31790,32592,32730,32754,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {26871,31701,32569,32725,32753,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {26615,31607,32543,32719,32752,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {26361,31511,32517,32713,32751,32758,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {26104,31408,32485,32704,32748,32757,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {25848,31302,32452,32695,32746,32757,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {25591,31191,32416,32684,32743,32756,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {25336,31078,32379,32674,32741,32756,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {25080,30960,32338,32661,32737,32755,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {24824,30838,32295,32648,32733,32754,32759,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {24568,30712,32248,32632,32728,32752,32758,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {24313,30583,32199,32616,32723,32751,32758,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {24057,30449,32147,32598,32718,32750,32758,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {23801,30311,32091,32578,32711,32747,32757,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {23546,30170,32033,32557,32704,32745,32757,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {23288,30022,31969,32532,32695,32742,32756,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {23033,29873,31904,32507,32686,32739,32755,32760,32761,32762,32763,32764,32765,32766,32767,32768},
+    {22778,29720,31835,32479,32675,32735,32753,32759,32761,32762,32763,32764,32765,32766,32767,32768},
+    {22521,29561,31761,32449,32664,32731,32752,32759,32761,32762,32763,32764,32765,32766,32767,32768},
+    {22267,29401,31686,32418,32652,32727,32751,32759,32761,32762,32763,32764,32765,32766,32767,32768},
+    {22011,29235,31605,32383,32638,32722,32749,32758,32761,32762,32763,32764,32765,32766,32767,32768},
+    {21754,29064,31520,32345,32622,32715,32746,32757,32761,32762,32763,32764,32765,32766,32767,32768},
+    {21501,28893,31434,32307,32607,32710,32745,32757,32761,32762,32763,32764,32765,32766,32767,32768},
+    {21243,28713,31339,32262,32587,32701,32741,32755,32760,32762,32763,32764,32765,32766,32767,32768},
+    {20988,28532,31243,32217,32567,32693,32738,32754,32760,32762,32763,32764,32765,32766,32767,32768},
+    {20730,28344,31140,32167,32544,32682,32733,32752,32759,32762,32763,32764,32765,32766,32767,32768},
+    {20476,28156,31036,32116,32521,32673,32730,32751,32759,32762,32763,32764,32765,32766,32767,32768},
+    {20220,27962,30926,32061,32495,32661,32725,32749,32758,32762,32763,32764,32765,32766,32767,32768},
+    {19963,27763,30810,32000,32465,32647,32718,32746,32757,32761,32763,32764,32765,32766,32767,32768},
+    {19708,27562,30691,31938,32435,32633,32712,32743,32756,32761,32763,32764,32765,32766,32767,32768},
+    {19454,27358,30569,31873,32403,32618,32705,32741,32755,32761,32763,32764,32765,32766,32767,32768},
+    {19196,27146,30438,31801,32365,32599,32696,32736,32753,32760,32763,32764,32765,32766,32767,32768},
+    {18942,26934,30306,31728,32328,32581,32688,32733,32752,32760,32763,32764,32765,32766,32767,32768},
+    {18684,26714,30164,31647,32284,32558,32676,32727,32749,32758,32762,32764,32765,32766,32767,32768},
+    {18429,26493,30021,31565,32240,32535,32664,32721,32746,32757,32762,32764,32765,32766,32767,32768},
+    {18174,26268,29872,31477,32192,32510,32652,32715,32743,32756,32762,32764,32765,32766,32767,32768},
+    {17920,26040,29719,31386,32141,32483,32638,32708,32740,32754,32761,32764,32765,32766,32767,32768},
+    {17661,25803,29556,31286,32083,32451,32620,32698,32734,32751,32759,32763,32765,32766,32767,32768},
+    {17406,25566,29391,31184,32024,32418,32603,32690,32731,32750,32759,32763,32765,32766,32767,32768},
+    {17151,25325,29220,31076,31961,32383,32584,32680,32726,32748,32758,32763,32765,32766,32767,32768},
+    {16896,25080,29044,30964,31894,32344,32562,32668,32719,32744,32756,32762,32765,32766,32767,32768},
+    {16639,24829,28860,30844,31821,32302,32539,32655,32712,32740,32754,32761,32764,32766,32767,32768},
+    {16384,24576,28672,30720,31744,32256,32512,32640,32704,32736,32752,32760,32764,32766,32767,32768},
+    {16130,24320,28479,30591,31663,32208,32485,32625,32696,32732,32750,32759,32764,32766,32767,32768},
+    {15872,24056,28276,30452,31574,32152,32450,32604,32683,32724,32745,32756,32762,32765,32766,32768},
+    {15615,23789,28068,30308,31480,32094,32415,32583,32671,32717,32741,32754,32761,32764,32766,32768},
+    {15361,23521,27856,30159,31382,32032,32377,32560,32657,32709,32737,32752,32760,32764,32766,32768},
+    {15103,23245,27634,30000,31275,31963,32334,32534,32642,32700,32731,32748,32757,32762,32765,32768},
+    {14848,22968,27409,29837,31165,31891,32288,32505,32624,32689,32725,32744,32755,32761,32764,32768},
+    {14592,22686,27176,29666,31047,31813,32238,32474,32605,32678,32718,32740,32752,32759,32763,32768},
+    {14336,22400,26936,29488,30923,31730,32184,32439,32583,32664,32709,32735,32749,32757,32762,32768},
+    {14079,22109,26689,29301,30791,31641,32125,32401,32559,32649,32700,32729,32746,32756,32761,32768},
+    {13825,21817,26437,29108,30652,31545,32061,32359,32532,32632,32690,32723,32742,32753,32759,32768},
+    {13568,21518,26176,28905,30504,31441,31990,32312,32501,32611,32676,32714,32736,32749,32757,32768},
+    {13314,21218,25911,28697,30351,31333,31916,32262,32468,32590,32662,32705,32731,32746,32755,32768},
+    {13054,20908,25633,28475,30185,31214,31833,32205,32429,32564,32645,32694,32723,32741,32752,32768},
+    {12803,20603,25356,28252,30017,31093,31748,32147,32390,32538,32628,32683,32717,32737,32749,32768},
+    {12544,20286,25064,28013,29833,30956,31649,32077,32341,32504,32605,32667,32705,32729,32744,32768},
+    {12288,19968,24768,27768,29643,30815,31547,32005,32291,32470,32582,32652,32696,32723,32740,32768},
+    {12033,19647,24465,27514,29443,30664,31437,31926,32235,32431,32555,32633,32683,32714,32734,32768},
+    {11777,19321,24154,27250,29233,30504,31318,31839,32173,32387,32524,32612,32668,32704,32727,32768},
+    {11521,18991,23835,26976,29013,30334,31190,31745,32105,32338,32489,32587,32651,32692,32719,32768},
+    {11265,18657,23508,26691,28780,30151,31051,31641,32028,32282,32449,32559,32631,32678,32709,32768},
+    {11006,18316,23170,26394,28535,29957,30901,31528,31944,32220,32404,32526,32607,32661,32697,32768},
+    {10752,17976,22830,26091,28282,29754,30743,31408,31854,32154,32356,32491,32582,32643,32684,32768},
+    {10496,17630,22479,25775,28015,29538,30573,31276,31754,32079,32300,32450,32552,32621,32668,32768},
+    {10240,17280,22120,25448,27736,29309,30390,31133,31644,31995,32237,32403,32517,32595,32649,32768},
+    { 9984,16926,21753,25109,27443,29066,30194,30978,31523,31902,32166,32349,32476,32565,32627,32768},
+    { 9728,16568,21377,24759,27137,28809,29984,30811,31392,31801,32088,32290,32432,32532,32602,32768},
+    { 9474,16208,20995,24399,26819,28539,29762,30631,31249,31688,32000,32222,32380,32492,32572,32768},
+    { 9216,15840,20601,24023,26483,28251,29522,30435,31091,31563,31902,32146,32321,32447,32537,32768},
+    { 8959,15469,20199,23636,26133,27947,29265,30223,30919,31425,31792,32059,32253,32394,32496,32768},
+    { 8705,15097,19791,23238,25770,27629,28994,29997,30733,31274,31671,31963,32177,32334,32449,32768},
+    { 8449,14719,19373,22827,25390,27292,28704,29752,30530,31107,31535,31853,32089,32264,32394,32768},
+    { 8192,14336,18944,22400,24992,26936,28394,29488,30308,30923,31384,31730,31989,32184,32330,32768},
+    { 7936,13950,18507,21961,24578,26561,28064,29203,30066,30720,31216,31592,31877,32093,32256,32768},
+    { 7678,13558,18060,21507,24146,26166,27713,28897,29804,30498,31030,31437,31749,31988,32171,32768},
+    { 7423,13165,17606,21041,23698,25753,27342,28571,29522,30257,30826,31266,31606,31869,32073,32768},
+    { 7168,12768,17143,20561,23231,25317,26947,28220,29215,29992,30599,31073,31444,31734,31960,32768},
+    { 6911,12365,16669,20065,22744,24858,26526,27842,28881,29701,30348,30858,31261,31579,31830,32768},
+    { 6657,11961,16188,19556,22240,24379,26083,27441,28523,29385,30072,30620,31056,31404,31681,32768},
+    { 6400,11550,15694,19029,21712,23871,25609,27007,28132,29037,29766,30352,30824,31204,31509,32768},
+    { 6142,11134,15190,18486,21164,23340,25108,26544,27711,28659,29429,30055,30564,30977,31313,32768},
+    { 5890,10720,14682,17932,20598,22785,24579,26051,27258,28248,29060,29726,30273,30721,31089,32768},
+    { 5631,10295,14157,17356,20005,22199,24016,25520,26766,27798,28652,29359,29945,30430,30832,32768},
+    { 5377, 9871,13628,16768,19393,21587,23421,24954,26236,27308,28204,28953,29579,30102,30539,32768},
+    { 5121, 9441,13086,16161,18756,20945,22792,24351,25666,26776,27712,28502,29169,29731,30206,32768},
+    { 4865, 9007,12534,15538,18096,20274,22129,23708,25053,26198,27173,28004,28711,29313,29826,32768},
+    { 4608, 8568,11971,14896,17409,19569,21425,23020,24391,25569,26581,27451,28199,28842,29394,32768},
+    { 4351, 8125,11398,14236,16697,18831,20682,22287,23679,24886,25933,26841,27628,28311,28903,32768},
+    { 4096, 7680,10816,13560,15961,18062,19900,21508,22915,24146,25224,26167,26992,27714,28346,32768},
+    { 3840, 7230,10223,12865,15197,17256,19074,20679,22096,23347,24451,25426,26287,27047,27718,32768},
+    { 3584, 6776, 9619,12151,14406,16414,18203,19796,21215,22479,23604,24606,25499,26294,27002,32768},
+    { 3328, 6318, 9004,11417,13585,15533,17283,18856,20269,21538,22678,23703,24624,25451,26194,32768},
+    { 3072, 5856, 8379,10665,12737,14615,16317,17859,19257,20524,21672,22712,23655,24509,25283,32768},
+    { 2816, 5390, 7743, 9894,11860,13657,15299,16800,18172,19426,20573,21621,22579,23455,24255,32768},
+    { 2560, 4920, 7096, 9102,10951,12656,14227,15676,17011,18242,19377,20423,21388,22277,23097,32768},
+    { 2304, 4446, 6437, 8288,10009,11609,13097,14480,15766,16961,18072,19105,20066,20959,21789,32768},
+    { 2048, 3968, 5768, 7456, 9038,10521,11911,13215,14437,15583,16657,17664,18608,19493,20323,32768},
+    { 1792, 3486, 5087, 6601, 8032, 9385,10664,11873,13016,14096,15117,16082,16995,17858,18673,32768},
+    { 1536, 3000, 4395, 5725, 6993, 8201, 9353,10451,11497,12494,13444,14350,15213,16036,16820,32768},
+    { 1280, 2510, 3692, 4828, 5919, 6968, 7976, 8944, 9875,10769,11628,12454,13248,14011,14744,32768},
+    { 1024, 2016, 2977, 3908, 4810, 5684, 6530, 7350, 8144, 8913, 9658,10380,11080,11758,12415,32768},
+    {  768, 1518, 2250, 2965, 3663, 4345, 5011, 5662, 6297, 6917, 7523, 8115, 8693, 9257, 9808,32768},
+    {  512, 1016, 1512, 2000, 2481, 2954, 3420, 3879, 4330, 4774, 5211, 5642, 6066, 6483, 6894,32768},
+    {  256,  510,  762, 1012, 1260, 1506, 1750, 1992, 2232, 2471, 2708, 2943, 3176, 3407, 3636,32768},
+};
+
+const ent_rng ff_daalaent_laplace_offset[] = {
+        0,    29871,    28672,    27751,    26975,    26291,    25673,    25105,
+    24576,    24079,    23609,    23162,    22734,    22325,    21931,    21550,
+    21182,    20826,    20480,    20143,    19815,    19495,    19183,    18877,
+    18579,    18286,    17999,    17718,    17442,    17170,    16904,    16642,
+    16384,    16129,    15879,    15633,    15390,    15150,    14913,    14680,
+    14450,    14222,    13997,    13775,    13556,    13338,    13124,    12911,
+    12701,    12493,    12288,    12084,    11882,    11682,    11484,    11288,
+    11094,    10901,    10710,    10521,    10333,    10147,     9962,     9779,
+     9597,     9417,     9238,     9060,     8884,     8709,     8535,     8363,
+     8192,     8021,     7853,     7685,     7518,     7352,     7188,     7025,
+     6862,     6701,     6540,     6381,     6222,     6065,     5908,     5753,
+     5598,     5444,     5291,     5138,     4987,     4837,     4687,     4538,
+     4390,     4242,     4096,     3950,     3804,     3660,     3516,     3373,
+     3231,     3089,     2948,     2808,     2668,     2529,     2391,     2253,
+     2116,     1979,     1843,     1708,     1573,     1439,     1306,     1172,
+     1040,      908,      777,      646,      516,      386,      257,      128,
+};
+
+static const uint8_t daala_zigzag4x4[][2] = {
+    {  0,  1 }, {  1,  0 }, {  1,  1 }, {  0,  2 },
+    {  2,  0 }, {  1,  2 }, {  0,  3 }, {  2,  1 },
+    {  3,  0 }, {  1,  3 }, {  3,  1 }, {  2,  2 },
+    {  2,  3 }, {  3,  2 }, {  3,  3 }
+};
+
+static const uint8_t daala_zigzag8x8[][2] = {
+    {  4,  0 }, {  5,  0 }, {  4,  1 }, {  6,  0 },
+    {  5,  1 }, {  7,  0 }, {  6,  1 }, {  7,  1 },
+    {  0,  4 }, {  0,  5 }, {  1,  4 }, {  0,  6 },
+    {  1,  5 }, {  0,  7 }, {  1,  6 }, {  1,  7 },
+    {  2,  4 }, {  4,  2 }, {  2,  5 }, {  3,  4 },
+    {  4,  3 }, {  5,  2 }, {  3,  5 }, {  2,  6 },
+    {  4,  4 }, {  5,  3 }, {  2,  7 }, {  6,  2 },
+    {  3,  6 }, {  4,  5 }, {  7,  2 }, {  5,  4 },
+    {  6,  3 }, {  3,  7 }, {  5,  5 }, {  7,  3 },
+    {  4,  6 }, {  6,  4 }, {  4,  7 }, {  5,  6 },
+    {  7,  4 }, {  6,  5 }, {  5,  7 }, {  7,  5 },
+    {  6,  6 }, {  6,  7 }, {  7,  6 }, {  7,  7 }
+};
+
+static const uint8_t daala_zigzag16x16[][2] = {
+    {  8,  0 }, {  9,  0 }, {  8,  1 }, { 10,  0 },
+    {  9,  1 }, { 11,  0 }, {  8,  2 }, { 10,  1 },
+    { 12,  0 }, {  8,  3 }, {  9,  2 }, { 13,  0 },
+    { 11,  1 }, {  9,  3 }, { 10,  2 }, { 14,  0 },
+    { 15,  0 }, { 12,  1 }, { 10,  3 }, { 11,  2 },
+    { 13,  1 }, { 11,  3 }, { 12,  2 }, { 14,  1 },
+    { 15,  1 }, { 13,  2 }, { 12,  3 }, { 14,  2 },
+    { 13,  3 }, { 15,  2 }, { 14,  3 }, { 15,  3 },
+    {  0,  8 }, {  0,  9 }, {  1,  8 }, {  0, 10 },
+    {  1,  9 }, {  2,  8 }, {  0, 11 }, {  1, 10 },
+    {  0, 12 }, {  3,  8 }, {  2,  9 }, {  0, 13 },
+    {  1, 11 }, {  2, 10 }, {  3,  9 }, {  0, 14 },
+    {  1, 12 }, {  0, 15 }, {  2, 11 }, {  3, 10 },
+    {  1, 13 }, {  2, 12 }, {  1, 14 }, {  3, 11 },
+    {  1, 15 }, {  2, 13 }, {  3, 12 }, {  2, 14 },
+    {  2, 15 }, {  3, 13 }, {  3, 14 }, {  3, 15 },
+    {  4,  8 }, {  8,  4 }, {  5,  8 }, {  4,  9 },
+    {  8,  5 }, {  9,  4 }, {  5,  9 }, {  6,  8 },
+    {  4, 10 }, {  8,  6 }, {  9,  5 }, {  5, 10 },
+    {  6,  9 }, { 10,  4 }, {  7,  8 }, {  4, 11 },
+    {  8,  7 }, {  9,  6 }, { 10,  5 }, {  5, 11 },
+    {  7,  9 }, {  6, 10 }, {  4, 12 }, {  8,  8 },
+    { 11,  4 }, {  9,  7 }, { 10,  6 }, {  4, 13 },
+    {  6, 11 }, {  7, 10 }, { 11,  5 }, {  5, 12 },
+    {  8,  9 }, {  9,  8 }, { 12,  4 }, { 10,  7 },
+    {  4, 14 }, {  5, 13 }, { 11,  6 }, {  4, 15 },
+    {  6, 12 }, {  7, 11 }, {  8, 10 }, { 12,  5 },
+    {  9,  9 }, { 13,  4 }, { 10,  8 }, {  5, 14 },
+    { 11,  7 }, {  6, 13 }, {  5, 15 }, {  7, 12 },
+    { 14,  4 }, { 13,  5 }, { 12,  6 }, {  8, 11 },
+    {  9, 10 }, { 15,  4 }, { 10,  9 }, {  6, 14 },
+    { 11,  8 }, {  7, 13 }, { 14,  5 }, {  6, 15 },
+    { 12,  7 }, { 13,  6 }, {  8, 12 }, {  9, 11 },
+    { 15,  5 }, { 10, 10 }, {  7, 14 }, { 11,  9 },
+    { 13,  7 }, { 14,  6 }, {  7, 15 }, { 12,  8 },
+    {  8, 13 }, {  9, 12 }, { 15,  6 }, { 10, 11 },
+    {  8, 14 }, { 11, 10 }, { 14,  7 }, { 13,  8 },
+    { 12,  9 }, {  8, 15 }, {  9, 13 }, { 15,  7 },
+    { 10, 12 }, { 11, 11 }, { 14,  8 }, { 13,  9 },
+    {  9, 14 }, { 12, 10 }, { 15,  8 }, {  9, 15 },
+    { 10, 13 }, { 11, 12 }, { 12, 11 }, { 14,  9 },
+    { 13, 10 }, { 10, 14 }, { 15,  9 }, { 10, 15 },
+    { 11, 13 }, { 14, 10 }, { 12, 12 }, { 13, 11 },
+    { 15, 10 }, { 11, 14 }, { 11, 15 }, { 12, 13 },
+    { 14, 11 }, { 13, 12 }, { 15, 11 }, { 12, 14 },
+    { 13, 13 }, { 14, 12 }, { 12, 15 }, { 15, 12 },
+    { 13, 14 }, { 14, 13 }, { 13, 15 }, { 15, 13 },
+    { 14, 14 }, { 14, 15 }, { 15, 14 }, { 15, 15 }
+};
+
+static const uint8_t daala_zigzag32x32[][2] = {
+    { 16,  0 }, { 17,  0 }, { 18,  0 }, { 19,  0 },
+    { 16,  1 }, { 17,  1 }, { 20,  0 }, { 16,  2 },
+    { 18,  1 }, { 21,  0 }, { 17,  2 }, { 16,  3 },
+    { 19,  1 }, { 22,  0 }, { 18,  2 }, { 17,  3 },
+    { 20,  1 }, { 16,  4 }, { 23,  0 }, { 19,  2 },
+    { 24,  0 }, { 16,  5 }, { 21,  1 }, { 17,  4 },
+    { 18,  3 }, { 20,  2 }, { 17,  5 }, { 16,  6 },
+    { 19,  3 }, { 18,  4 }, { 25,  0 }, { 22,  1 },
+    { 16,  7 }, { 21,  2 }, { 17,  6 }, { 20,  3 },
+    { 26,  0 }, { 18,  5 }, { 19,  4 }, { 17,  7 },
+    { 23,  1 }, { 22,  2 }, { 18,  6 }, { 27,  0 },
+    { 19,  5 }, { 24,  1 }, { 21,  3 }, { 28,  0 },
+    { 20,  4 }, { 18,  7 }, { 19,  6 }, { 23,  2 },
+    { 29,  0 }, { 25,  1 }, { 21,  4 }, { 30,  0 },
+    { 20,  5 }, { 22,  3 }, { 31,  0 }, { 19,  7 },
+    { 24,  2 }, { 26,  1 }, { 20,  6 }, { 21,  5 },
+    { 22,  4 }, { 23,  3 }, { 27,  1 }, { 25,  2 },
+    { 20,  7 }, { 28,  1 }, { 24,  3 }, { 21,  6 },
+    { 22,  5 }, { 23,  4 }, { 26,  2 }, { 21,  7 },
+    { 29,  1 }, { 25,  3 }, { 30,  1 }, { 27,  2 },
+    { 22,  6 }, { 23,  5 }, { 31,  1 }, { 24,  4 },
+    { 26,  3 }, { 28,  2 }, { 22,  7 }, { 23,  6 },
+    { 25,  4 }, { 24,  5 }, { 29,  2 }, { 30,  2 },
+    { 27,  3 }, { 23,  7 }, { 31,  2 }, { 24,  6 },
+    { 26,  4 }, { 25,  5 }, { 28,  3 }, { 24,  7 },
+    { 27,  4 }, { 29,  3 }, { 25,  6 }, { 26,  5 },
+    { 30,  3 }, { 31,  3 }, { 28,  4 }, { 27,  5 },
+    { 25,  7 }, { 29,  4 }, { 26,  6 }, { 28,  5 },
+    { 30,  4 }, { 26,  7 }, { 27,  6 }, { 31,  4 },
+    { 29,  5 }, { 27,  7 }, { 30,  5 }, { 28,  6 },
+    { 31,  5 }, { 29,  6 }, { 28,  7 }, { 30,  6 },
+    { 31,  6 }, { 29,  7 }, { 30,  7 }, { 31,  7 },
+    {  0, 16 }, {  0, 17 }, {  1, 16 }, {  0, 18 },
+    {  1, 17 }, {  0, 19 }, {  2, 16 }, {  1, 18 },
+    {  0, 20 }, {  2, 17 }, {  3, 16 }, {  1, 19 },
+    {  2, 18 }, {  0, 21 }, {  3, 17 }, {  4, 16 },
+    {  1, 20 }, {  2, 19 }, {  0, 22 }, {  3, 18 },
+    {  4, 17 }, {  5, 16 }, {  0, 23 }, {  3, 19 },
+    {  2, 20 }, {  1, 21 }, {  4, 18 }, {  6, 16 },
+    {  5, 17 }, {  3, 20 }, {  2, 21 }, {  1, 22 },
+    {  0, 24 }, {  0, 25 }, {  4, 19 }, {  7, 16 },
+    {  6, 17 }, {  5, 18 }, {  0, 26 }, {  3, 21 },
+    {  2, 22 }, {  1, 23 }, {  4, 20 }, {  5, 19 },
+    {  6, 18 }, {  1, 24 }, {  7, 17 }, {  0, 27 },
+    {  2, 23 }, {  3, 22 }, {  4, 21 }, {  1, 25 },
+    {  5, 20 }, {  7, 18 }, {  0, 28 }, {  6, 19 },
+    {  2, 24 }, {  1, 26 }, {  0, 29 }, {  4, 22 },
+    {  3, 23 }, {  2, 25 }, {  5, 21 }, {  0, 31 },
+    {  7, 19 }, {  6, 20 }, {  0, 30 }, {  1, 27 },
+    {  3, 24 }, {  2, 26 }, {  4, 23 }, {  5, 22 },
+    {  7, 20 }, {  1, 28 }, {  6, 21 }, {  3, 25 },
+    {  2, 27 }, {  1, 29 }, {  4, 24 }, {  2, 28 },
+    {  1, 30 }, {  7, 21 }, {  5, 23 }, {  3, 26 },
+    {  6, 22 }, {  1, 31 }, {  4, 25 }, {  7, 22 },
+    {  3, 27 }, {  2, 29 }, {  2, 30 }, {  5, 24 },
+    {  2, 31 }, {  6, 23 }, {  4, 26 }, {  3, 28 },
+    {  5, 25 }, {  3, 29 }, {  6, 24 }, {  7, 23 },
+    {  3, 30 }, {  4, 27 }, {  3, 31 }, {  5, 26 },
+    {  6, 25 }, {  4, 28 }, {  7, 24 }, {  4, 29 },
+    {  5, 27 }, {  4, 30 }, {  4, 31 }, {  6, 26 },
+    {  5, 28 }, {  7, 25 }, {  6, 27 }, {  5, 29 },
+    {  7, 26 }, {  5, 30 }, {  5, 31 }, {  6, 28 },
+    {  7, 27 }, {  6, 29 }, {  6, 30 }, {  7, 28 },
+    {  6, 31 }, {  7, 29 }, {  7, 30 }, {  7, 31 },
+    {  8, 16 }, {  9, 16 }, {  8, 17 }, { 10, 16 },
+    {  9, 17 }, { 16,  8 }, {  8, 18 }, { 16,  9 },
+    { 10, 17 }, { 11, 16 }, { 17,  8 }, {  9, 18 },
+    {  8, 19 }, { 16, 10 }, { 11, 17 }, { 12, 16 },
+    { 10, 18 }, { 17,  9 }, {  9, 19 }, { 16, 11 },
+    {  8, 20 }, { 18,  8 }, { 17, 10 }, { 10, 19 },
+    { 12, 17 }, { 11, 18 }, {  9, 20 }, { 16, 12 },
+    { 18,  9 }, {  8, 21 }, { 13, 16 }, { 17, 11 },
+    { 19,  8 }, { 18, 10 }, { 13, 17 }, { 16, 13 },
+    { 11, 19 }, { 12, 18 }, { 10, 20 }, { 17, 12 },
+    {  9, 21 }, { 19,  9 }, {  8, 22 }, { 14, 16 },
+    { 18, 11 }, { 11, 20 }, { 10, 21 }, { 20,  8 },
+    { 13, 18 }, { 16, 14 }, { 12, 19 }, { 17, 13 },
+    { 19, 10 }, { 14, 17 }, {  9, 22 }, { 18, 12 },
+    {  8, 23 }, { 17, 14 }, { 20,  9 }, { 15, 16 },
+    { 16, 15 }, { 13, 19 }, { 10, 22 }, { 19, 11 },
+    { 11, 21 }, { 14, 18 }, { 12, 20 }, { 18, 13 },
+    { 20, 10 }, { 21,  8 }, { 15, 17 }, {  9, 23 },
+    { 19, 12 }, { 11, 22 }, {  8, 24 }, { 21,  9 },
+    { 17, 15 }, { 16, 16 }, { 14, 19 }, { 18, 14 },
+    { 12, 21 }, { 13, 20 }, { 20, 11 }, { 10, 23 },
+    { 19, 13 }, { 15, 18 }, { 16, 17 }, { 21, 10 },
+    { 22,  8 }, {  9, 24 }, {  8, 25 }, { 20, 12 },
+    { 15, 19 }, { 11, 23 }, { 17, 16 }, { 18, 15 },
+    { 14, 20 }, { 12, 22 }, { 10, 24 }, { 22,  9 },
+    { 21, 11 }, { 19, 14 }, { 13, 21 }, { 16, 18 },
+    {  9, 25 }, { 17, 17 }, {  8, 26 }, { 20, 13 },
+    { 23,  8 }, { 12, 23 }, { 13, 22 }, { 22, 10 },
+    { 19, 15 }, { 15, 20 }, { 16, 19 }, { 21, 12 },
+    { 11, 24 }, { 14, 21 }, {  8, 27 }, { 18, 16 },
+    { 10, 25 }, {  9, 26 }, { 22, 11 }, { 20, 14 },
+    { 23,  9 }, { 18, 17 }, { 17, 18 }, { 17, 19 },
+    { 19, 16 }, { 21, 13 }, { 10, 26 }, { 12, 24 },
+    { 23, 10 }, { 24,  8 }, {  8, 28 }, { 16, 20 },
+    {  9, 27 }, { 15, 21 }, { 22, 12 }, { 14, 22 },
+    { 13, 23 }, { 20, 15 }, { 11, 25 }, { 24,  9 },
+    { 18, 18 }, { 19, 17 }, { 23, 11 }, { 10, 27 },
+    {  8, 29 }, { 12, 25 }, {  9, 28 }, {  8, 30 },
+    { 21, 14 }, { 13, 24 }, { 11, 26 }, { 25,  8 },
+    { 24, 10 }, { 20, 16 }, { 19, 18 }, { 14, 23 },
+    { 22, 13 }, {  8, 31 }, { 17, 20 }, {  9, 29 },
+    { 23, 12 }, { 15, 22 }, { 25,  9 }, { 11, 27 },
+    { 10, 28 }, { 20, 17 }, { 21, 15 }, { 18, 19 },
+    { 16, 21 }, { 24, 11 }, {  9, 30 }, { 12, 26 },
+    { 10, 29 }, { 22, 14 }, { 14, 24 }, {  9, 31 },
+    { 26,  8 }, { 13, 25 }, { 25, 10 }, { 18, 20 },
+    { 19, 19 }, { 11, 28 }, { 15, 23 }, { 20, 18 },
+    { 10, 30 }, { 12, 27 }, { 17, 21 }, { 23, 13 },
+    { 24, 12 }, { 21, 16 }, { 16, 22 }, { 26,  9 },
+    { 27,  8 }, { 13, 26 }, { 22, 15 }, { 10, 31 },
+    { 14, 25 }, { 12, 28 }, { 25, 11 }, { 21, 17 },
+    { 26, 10 }, { 20, 19 }, { 11, 29 }, { 15, 24 },
+    { 23, 14 }, { 27,  9 }, { 11, 30 }, { 13, 27 },
+    { 19, 20 }, { 24, 13 }, { 28,  8 }, { 11, 31 },
+    { 22, 16 }, { 17, 22 }, { 16, 23 }, { 25, 12 },
+    { 18, 21 }, { 12, 29 }, { 21, 18 }, { 28,  9 },
+    { 27, 10 }, { 26, 11 }, { 29,  8 }, { 14, 26 },
+    { 15, 25 }, { 13, 28 }, { 12, 30 }, { 23, 15 },
+    { 30,  8 }, { 16, 24 }, { 13, 29 }, { 25, 13 },
+    { 24, 14 }, { 20, 20 }, { 31,  8 }, { 12, 31 },
+    { 14, 27 }, { 28, 10 }, { 26, 12 }, { 22, 17 },
+    { 21, 19 }, { 17, 23 }, { 18, 22 }, { 29,  9 },
+    { 27, 11 }, { 19, 21 }, { 27, 12 }, { 30,  9 },
+    { 31,  9 }, { 13, 30 }, { 24, 15 }, { 23, 16 },
+    { 15, 26 }, { 14, 28 }, { 29, 10 }, { 28, 11 },
+    { 26, 13 }, { 17, 24 }, { 13, 31 }, { 25, 14 },
+    { 22, 18 }, { 16, 25 }, { 30, 10 }, { 14, 29 },
+    { 15, 27 }, { 19, 22 }, { 21, 20 }, { 20, 21 },
+    { 27, 13 }, { 29, 11 }, { 18, 23 }, { 23, 17 },
+    { 16, 26 }, { 31, 10 }, { 24, 16 }, { 14, 30 },
+    { 22, 19 }, { 14, 31 }, { 28, 12 }, { 26, 14 },
+    { 30, 11 }, { 15, 28 }, { 25, 15 }, { 17, 25 },
+    { 23, 18 }, { 18, 24 }, { 15, 30 }, { 29, 12 },
+    { 31, 11 }, { 16, 27 }, { 24, 17 }, { 28, 13 },
+    { 19, 23 }, { 15, 29 }, { 25, 16 }, { 17, 26 },
+    { 27, 14 }, { 22, 20 }, { 15, 31 }, { 20, 22 },
+    { 21, 21 }, { 16, 28 }, { 17, 27 }, { 30, 12 },
+    { 26, 15 }, { 19, 24 }, { 18, 25 }, { 23, 19 },
+    { 29, 13 }, { 31, 12 }, { 24, 18 }, { 26, 16 },
+    { 25, 17 }, { 16, 29 }, { 28, 14 }, { 20, 23 },
+    { 18, 26 }, { 21, 22 }, { 19, 25 }, { 22, 21 },
+    { 27, 15 }, { 17, 28 }, { 16, 30 }, { 26, 17 },
+    { 23, 20 }, { 16, 31 }, { 25, 18 }, { 27, 16 },
+    { 20, 24 }, { 24, 19 }, { 31, 13 }, { 30, 13 },
+    { 29, 14 }, { 18, 27 }, { 28, 15 }, { 17, 29 },
+    { 19, 26 }, { 17, 30 }, { 21, 23 }, { 22, 22 },
+    { 30, 14 }, { 20, 25 }, { 23, 21 }, { 17, 31 },
+    { 18, 28 }, { 25, 19 }, { 24, 20 }, { 28, 16 },
+    { 31, 14 }, { 26, 18 }, { 19, 27 }, { 29, 15 },
+    { 27, 17 }, { 30, 15 }, { 21, 24 }, { 22, 23 },
+    { 26, 19 }, { 23, 22 }, { 28, 17 }, { 29, 16 },
+    { 18, 30 }, { 24, 21 }, { 25, 20 }, { 18, 31 },
+    { 18, 29 }, { 20, 26 }, { 19, 28 }, { 27, 18 },
+    { 31, 15 }, { 20, 27 }, { 30, 16 }, { 19, 29 },
+    { 29, 17 }, { 31, 16 }, { 27, 19 }, { 21, 25 },
+    { 28, 18 }, { 26, 20 }, { 22, 24 }, { 25, 21 },
+    { 19, 30 }, { 24, 22 }, { 30, 17 }, { 21, 26 },
+    { 23, 23 }, { 19, 31 }, { 20, 28 }, { 31, 17 },
+    { 28, 19 }, { 27, 20 }, { 21, 27 }, { 29, 18 },
+    { 30, 18 }, { 25, 22 }, { 26, 21 }, { 20, 29 },
+    { 22, 25 }, { 24, 23 }, { 29, 19 }, { 23, 24 },
+    { 20, 31 }, { 20, 30 }, { 28, 20 }, { 21, 28 },
+    { 22, 26 }, { 31, 18 }, { 27, 21 }, { 30, 19 },
+    { 22, 27 }, { 29, 20 }, { 23, 25 }, { 24, 24 },
+    { 26, 22 }, { 21, 29 }, { 25, 23 }, { 31, 19 },
+    { 21, 30 }, { 23, 26 }, { 28, 21 }, { 21, 31 },
+    { 22, 28 }, { 30, 20 }, { 25, 24 }, { 27, 22 },
+    { 29, 21 }, { 26, 23 }, { 24, 25 }, { 31, 20 },
+    { 23, 27 }, { 22, 29 }, { 30, 21 }, { 28, 22 },
+    { 24, 26 }, { 25, 25 }, { 27, 23 }, { 22, 30 },
+    { 23, 28 }, { 22, 31 }, { 26, 24 }, { 31, 21 },
+    { 24, 27 }, { 29, 22 }, { 27, 24 }, { 30, 22 },
+    { 25, 26 }, { 28, 23 }, { 23, 30 }, { 23, 29 },
+    { 24, 28 }, { 25, 27 }, { 31, 22 }, { 23, 31 },
+    { 26, 25 }, { 28, 24 }, { 29, 23 }, { 24, 29 },
+    { 24, 30 }, { 27, 25 }, { 25, 28 }, { 26, 26 },
+    { 30, 23 }, { 26, 27 }, { 31, 23 }, { 28, 25 },
+    { 27, 26 }, { 25, 29 }, { 24, 31 }, { 29, 24 },
+    { 30, 24 }, { 27, 27 }, { 29, 25 }, { 26, 28 },
+    { 31, 24 }, { 25, 30 }, { 25, 31 }, { 28, 26 },
+    { 27, 28 }, { 26, 29 }, { 30, 25 }, { 29, 26 },
+    { 28, 27 }, { 26, 30 }, { 31, 25 }, { 27, 29 },
+    { 26, 31 }, { 30, 26 }, { 28, 28 }, { 31, 26 },
+    { 29, 27 }, { 27, 30 }, { 28, 29 }, { 27, 31 },
+    { 30, 27 }, { 31, 27 }, { 28, 30 }, { 29, 28 },
+    { 30, 28 }, { 29, 29 }, { 30, 29 }, { 31, 28 },
+    { 28, 31 }, { 29, 30 }, { 29, 31 }, { 31, 29 },
+    { 30, 30 }, { 30, 31 }, { 31, 30 }, { 31, 31 }
+};
+
+static const uint8_t daala_zigzag64x64[][2] = {
+    { 32,  0 }, { 33,  0 }, { 34,  0 }, { 35,  0 },
+    { 32,  1 }, { 36,  0 }, { 33,  1 }, { 37,  0 },
+    { 34,  1 }, { 32,  2 }, { 38,  0 }, { 35,  1 },
+    { 33,  2 }, { 39,  0 }, { 36,  1 }, { 34,  2 },
+    { 40,  0 }, { 32,  3 }, { 37,  1 }, { 35,  2 },
+    { 41,  0 }, { 33,  3 }, { 38,  1 }, { 36,  2 },
+    { 42,  0 }, { 32,  4 }, { 34,  3 }, { 39,  1 },
+    { 37,  2 }, { 43,  0 }, { 35,  3 }, { 33,  4 },
+    { 40,  1 }, { 44,  0 }, { 38,  2 }, { 32,  5 },
+    { 36,  3 }, { 41,  1 }, { 34,  4 }, { 45,  0 },
+    { 39,  2 }, { 33,  5 }, { 42,  1 }, { 37,  3 },
+    { 35,  4 }, { 46,  0 }, { 40,  2 }, { 32,  6 },
+    { 43,  1 }, { 34,  5 }, { 38,  3 }, { 36,  4 },
+    { 47,  0 }, { 41,  2 }, { 33,  6 }, { 44,  1 },
+    { 39,  3 }, { 35,  5 }, { 37,  4 }, { 48,  0 },
+    { 32,  7 }, { 42,  2 }, { 34,  6 }, { 45,  1 },
+    { 40,  3 }, { 36,  5 }, { 38,  4 }, { 49,  0 },
+    { 33,  7 }, { 43,  2 }, { 46,  1 }, { 35,  6 },
+    { 41,  3 }, { 37,  5 }, { 39,  4 }, { 32,  8 },
+    { 50,  0 }, { 44,  2 }, { 34,  7 }, { 47,  1 },
+    { 36,  6 }, { 42,  3 }, { 38,  5 }, { 51,  0 },
+    { 40,  4 }, { 33,  8 }, { 45,  2 }, { 35,  7 },
+    { 48,  1 }, { 32,  9 }, { 37,  6 }, { 43,  3 },
+    { 52,  0 }, { 39,  5 }, { 41,  4 }, { 34,  8 },
+    { 46,  2 }, { 49,  1 }, { 36,  7 }, { 33,  9 },
+    { 44,  3 }, { 53,  0 }, { 38,  6 }, { 42,  4 },
+    { 40,  5 }, { 35,  8 }, { 32, 10 }, { 47,  2 },
+    { 50,  1 }, { 37,  7 }, { 54,  0 }, { 45,  3 },
+    { 34,  9 }, { 39,  6 }, { 43,  4 }, { 41,  5 },
+    { 48,  2 }, { 36,  8 }, { 51,  1 }, { 33, 10 },
+    { 55,  0 }, { 38,  7 }, { 46,  3 }, { 32, 11 },
+    { 40,  6 }, { 35,  9 }, { 44,  4 }, { 42,  5 },
+    { 49,  2 }, { 52,  1 }, { 37,  8 }, { 34, 10 },
+    { 56,  0 }, { 39,  7 }, { 47,  3 }, { 41,  6 },
+    { 33, 11 }, { 45,  4 }, { 36,  9 }, { 43,  5 },
+    { 50,  2 }, { 53,  1 }, { 32, 12 }, { 38,  8 },
+    { 57,  0 }, { 35, 10 }, { 48,  3 }, { 40,  7 },
+    { 42,  6 }, { 46,  4 }, { 44,  5 }, { 34, 11 },
+    { 37,  9 }, { 51,  2 }, { 54,  1 }, { 58,  0 },
+    { 39,  8 }, { 33, 12 }, { 36, 10 }, { 49,  3 },
+    { 41,  7 }, { 32, 13 }, { 47,  4 }, { 43,  6 },
+    { 45,  5 }, { 52,  2 }, { 55,  1 }, { 38,  9 },
+    { 35, 11 }, { 59,  0 }, { 40,  8 }, { 34, 12 },
+    { 50,  3 }, { 37, 10 }, { 42,  7 }, { 48,  4 },
+    { 44,  6 }, { 33, 13 }, { 56,  1 }, { 53,  2 },
+    { 46,  5 }, { 60,  0 }, { 39,  9 }, { 36, 11 },
+    { 32, 14 }, { 41,  8 }, { 51,  3 }, { 35, 12 },
+    { 38, 10 }, { 43,  7 }, { 49,  4 }, { 57,  1 },
+    { 54,  2 }, { 45,  6 }, { 47,  5 }, { 61,  0 },
+    { 34, 13 }, { 40,  9 }, { 37, 11 }, { 33, 14 },
+    { 52,  3 }, { 42,  8 }, { 36, 12 }, { 32, 15 },
+    { 39, 10 }, { 44,  7 }, { 58,  1 }, { 50,  4 },
+    { 55,  2 }, { 62,  0 }, { 46,  6 }, { 48,  5 },
+    { 35, 13 }, { 41,  9 }, { 38, 11 }, { 53,  3 },
+    { 34, 14 }, { 43,  8 }, { 59,  1 }, { 63,  0 },
+    { 56,  2 }, { 51,  4 }, { 37, 12 }, { 45,  7 },
+    { 40, 10 }, { 33, 15 }, { 47,  6 }, { 49,  5 },
+    { 36, 13 }, { 42,  9 }, { 39, 11 }, { 54,  3 },
+    { 44,  8 }, { 60,  1 }, { 35, 14 }, { 57,  2 },
+    { 52,  4 }, { 46,  7 }, { 41, 10 }, { 38, 12 },
+    { 50,  5 }, { 48,  6 }, { 34, 15 }, { 43,  9 },
+    { 37, 13 }, { 55,  3 }, { 40, 11 }, { 61,  1 },
+    { 45,  8 }, { 58,  2 }, { 53,  4 }, { 36, 14 },
+    { 47,  7 }, { 51,  5 }, { 42, 10 }, { 49,  6 },
+    { 39, 12 }, { 35, 15 }, { 56,  3 }, { 44,  9 },
+    { 38, 13 }, { 62,  1 }, { 41, 11 }, { 59,  2 },
+    { 46,  8 }, { 54,  4 }, { 48,  7 }, { 37, 14 },
+    { 52,  5 }, { 50,  6 }, { 43, 10 }, { 40, 12 },
+    { 36, 15 }, { 57,  3 }, { 45,  9 }, { 63,  1 },
+    { 39, 13 }, { 60,  2 }, { 42, 11 }, { 47,  8 },
+    { 55,  4 }, { 49,  7 }, { 53,  5 }, { 51,  6 },
+    { 38, 14 }, { 44, 10 }, { 41, 12 }, { 58,  3 },
+    { 37, 15 }, { 46,  9 }, { 61,  2 }, { 40, 13 },
+    { 56,  4 }, { 43, 11 }, { 48,  8 }, { 54,  5 },
+    { 50,  7 }, { 52,  6 }, { 39, 14 }, { 45, 10 },
+    { 59,  3 }, { 42, 12 }, { 62,  2 }, { 47,  9 },
+    { 38, 15 }, { 57,  4 }, { 41, 13 }, { 44, 11 },
+    { 49,  8 }, { 55,  5 }, { 51,  7 }, { 53,  6 },
+    { 60,  3 }, { 46, 10 }, { 40, 14 }, { 43, 12 },
+    { 63,  2 }, { 48,  9 }, { 58,  4 }, { 39, 15 },
+    { 50,  8 }, { 45, 11 }, { 42, 13 }, { 56,  5 },
+    { 52,  7 }, { 54,  6 }, { 61,  3 }, { 47, 10 },
+    { 41, 14 }, { 44, 12 }, { 49,  9 }, { 59,  4 },
+    { 40, 15 }, { 51,  8 }, { 57,  5 }, { 46, 11 },
+    { 43, 13 }, { 53,  7 }, { 55,  6 }, { 62,  3 },
+    { 48, 10 }, { 42, 14 }, { 45, 12 }, { 60,  4 },
+    { 50,  9 }, { 52,  8 }, { 58,  5 }, { 41, 15 },
+    { 47, 11 }, { 54,  7 }, { 56,  6 }, { 44, 13 },
+    { 63,  3 }, { 49, 10 }, { 43, 14 }, { 61,  4 },
+    { 46, 12 }, { 51,  9 }, { 59,  5 }, { 53,  8 },
+    { 42, 15 }, { 57,  6 }, { 55,  7 }, { 48, 11 },
+    { 45, 13 }, { 50, 10 }, { 62,  4 }, { 44, 14 },
+    { 47, 12 }, { 52,  9 }, { 60,  5 }, { 54,  8 },
+    { 58,  6 }, { 56,  7 }, { 49, 11 }, { 43, 15 },
+    { 46, 13 }, { 51, 10 }, { 63,  4 }, { 48, 12 },
+    { 45, 14 }, { 53,  9 }, { 61,  5 }, { 55,  8 },
+    { 59,  6 }, { 57,  7 }, { 50, 11 }, { 44, 15 },
+    { 47, 13 }, { 52, 10 }, { 54,  9 }, { 49, 12 },
+    { 62,  5 }, { 46, 14 }, { 56,  8 }, { 60,  6 },
+    { 58,  7 }, { 51, 11 }, { 45, 15 }, { 48, 13 },
+    { 53, 10 }, { 63,  5 }, { 55,  9 }, { 50, 12 },
+    { 47, 14 }, { 57,  8 }, { 61,  6 }, { 59,  7 },
+    { 52, 11 }, { 46, 15 }, { 49, 13 }, { 54, 10 },
+    { 56,  9 }, { 51, 12 }, { 62,  6 }, { 58,  8 },
+    { 48, 14 }, { 60,  7 }, { 53, 11 }, { 47, 15 },
+    { 50, 13 }, { 55, 10 }, { 57,  9 }, { 63,  6 },
+    { 52, 12 }, { 59,  8 }, { 61,  7 }, { 49, 14 },
+    { 54, 11 }, { 51, 13 }, { 48, 15 }, { 56, 10 },
+    { 58,  9 }, { 60,  8 }, { 53, 12 }, { 62,  7 },
+    { 50, 14 }, { 55, 11 }, { 52, 13 }, { 49, 15 },
+    { 57, 10 }, { 59,  9 }, { 61,  8 }, { 63,  7 },
+    { 54, 12 }, { 51, 14 }, { 56, 11 }, { 53, 13 },
+    { 58, 10 }, { 50, 15 }, { 60,  9 }, { 62,  8 },
+    { 55, 12 }, { 52, 14 }, { 57, 11 }, { 59, 10 },
+    { 54, 13 }, { 51, 15 }, { 61,  9 }, { 63,  8 },
+    { 56, 12 }, { 53, 14 }, { 58, 11 }, { 60, 10 },
+    { 55, 13 }, { 52, 15 }, { 62,  9 }, { 57, 12 },
+    { 54, 14 }, { 59, 11 }, { 61, 10 }, { 56, 13 },
+    { 63,  9 }, { 53, 15 }, { 58, 12 }, { 55, 14 },
+    { 60, 11 }, { 62, 10 }, { 57, 13 }, { 54, 15 },
+    { 59, 12 }, { 56, 14 }, { 61, 11 }, { 63, 10 },
+    { 58, 13 }, { 55, 15 }, { 60, 12 }, { 57, 14 },
+    { 62, 11 }, { 59, 13 }, { 56, 15 }, { 61, 12 },
+    { 63, 11 }, { 58, 14 }, { 60, 13 }, { 57, 15 },
+    { 62, 12 }, { 59, 14 }, { 61, 13 }, { 58, 15 },
+    { 63, 12 }, { 60, 14 }, { 62, 13 }, { 59, 15 },
+    { 61, 14 }, { 63, 13 }, { 60, 15 }, { 62, 14 },
+    { 61, 15 }, { 63, 14 }, { 62, 15 }, { 63, 15 },
+    {  0, 32 }, {  0, 33 }, {  0, 34 }, {  0, 35 },
+    {  1, 32 }, {  0, 36 }, {  1, 33 }, {  0, 37 },
+    {  1, 34 }, {  2, 32 }, {  0, 38 }, {  1, 35 },
+    {  2, 33 }, {  0, 39 }, {  1, 36 }, {  2, 34 },
+    {  0, 40 }, {  3, 32 }, {  1, 37 }, {  2, 35 },
+    {  0, 41 }, {  3, 33 }, {  1, 38 }, {  2, 36 },
+    {  0, 42 }, {  4, 32 }, {  3, 34 }, {  1, 39 },
+    {  2, 37 }, {  0, 43 }, {  3, 35 }, {  4, 33 },
+    {  1, 40 }, {  0, 44 }, {  2, 38 }, {  5, 32 },
+    {  3, 36 }, {  1, 41 }, {  4, 34 }, {  0, 45 },
+    {  2, 39 }, {  5, 33 }, {  1, 42 }, {  3, 37 },
+    {  4, 35 }, {  0, 46 }, {  2, 40 }, {  6, 32 },
+    {  1, 43 }, {  5, 34 }, {  3, 38 }, {  4, 36 },
+    {  0, 47 }, {  2, 41 }, {  6, 33 }, {  1, 44 },
+    {  3, 39 }, {  5, 35 }, {  4, 37 }, {  0, 48 },
+    {  7, 32 }, {  2, 42 }, {  6, 34 }, {  1, 45 },
+    {  3, 40 }, {  5, 36 }, {  4, 38 }, {  0, 49 },
+    {  7, 33 }, {  2, 43 }, {  1, 46 }, {  6, 35 },
+    {  3, 41 }, {  5, 37 }, {  4, 39 }, {  8, 32 },
+    {  0, 50 }, {  2, 44 }, {  7, 34 }, {  1, 47 },
+    {  6, 36 }, {  3, 42 }, {  5, 38 }, {  0, 51 },
+    {  4, 40 }, {  8, 33 }, {  2, 45 }, {  7, 35 },
+    {  1, 48 }, {  9, 32 }, {  6, 37 }, {  3, 43 },
+    {  0, 52 }, {  5, 39 }, {  4, 41 }, {  8, 34 },
+    {  2, 46 }, {  1, 49 }, {  7, 36 }, {  9, 33 },
+    {  3, 44 }, {  0, 53 }, {  6, 38 }, {  4, 42 },
+    {  5, 40 }, {  8, 35 }, { 10, 32 }, {  2, 47 },
+    {  1, 50 }, {  7, 37 }, {  0, 54 }, {  3, 45 },
+    {  9, 34 }, {  6, 39 }, {  4, 43 }, {  5, 41 },
+    {  2, 48 }, {  8, 36 }, {  1, 51 }, { 10, 33 },
+    {  0, 55 }, {  7, 38 }, {  3, 46 }, { 11, 32 },
+    {  6, 40 }, {  9, 35 }, {  4, 44 }, {  5, 42 },
+    {  2, 49 }, {  1, 52 }, {  8, 37 }, { 10, 34 },
+    {  0, 56 }, {  7, 39 }, {  3, 47 }, {  6, 41 },
+    { 11, 33 }, {  4, 45 }, {  9, 36 }, {  5, 43 },
+    {  2, 50 }, {  1, 53 }, { 12, 32 }, {  8, 38 },
+    {  0, 57 }, { 10, 35 }, {  3, 48 }, {  7, 40 },
+    {  6, 42 }, {  4, 46 }, {  5, 44 }, { 11, 34 },
+    {  9, 37 }, {  2, 51 }, {  1, 54 }, {  0, 58 },
+    {  8, 39 }, { 12, 33 }, { 10, 36 }, {  3, 49 },
+    {  7, 41 }, { 13, 32 }, {  4, 47 }, {  6, 43 },
+    {  5, 45 }, {  2, 52 }, {  1, 55 }, {  9, 38 },
+    { 11, 35 }, {  0, 59 }, {  8, 40 }, { 12, 34 },
+    {  3, 50 }, { 10, 37 }, {  7, 42 }, {  4, 48 },
+    {  6, 44 }, { 13, 33 }, {  1, 56 }, {  2, 53 },
+    {  5, 46 }, {  0, 60 }, {  9, 39 }, { 11, 36 },
+    { 14, 32 }, {  8, 41 }, {  3, 51 }, { 12, 35 },
+    { 10, 38 }, {  7, 43 }, {  4, 49 }, {  1, 57 },
+    {  2, 54 }, {  6, 45 }, {  5, 47 }, {  0, 61 },
+    { 13, 34 }, {  9, 40 }, { 11, 37 }, { 14, 33 },
+    {  3, 52 }, {  8, 42 }, { 12, 36 }, { 15, 32 },
+    { 10, 39 }, {  7, 44 }, {  1, 58 }, {  4, 50 },
+    {  2, 55 }, {  0, 62 }, {  6, 46 }, {  5, 48 },
+    { 13, 35 }, {  9, 41 }, { 11, 38 }, {  3, 53 },
+    { 14, 34 }, {  8, 43 }, {  1, 59 }, {  0, 63 },
+    {  2, 56 }, {  4, 51 }, { 12, 37 }, {  7, 45 },
+    { 10, 40 }, { 15, 33 }, {  6, 47 }, {  5, 49 },
+    { 13, 36 }, {  9, 42 }, { 11, 39 }, {  3, 54 },
+    {  8, 44 }, {  1, 60 }, { 14, 35 }, {  2, 57 },
+    {  4, 52 }, {  7, 46 }, { 10, 41 }, { 12, 38 },
+    {  5, 50 }, {  6, 48 }, { 15, 34 }, {  9, 43 },
+    { 13, 37 }, {  3, 55 }, { 11, 40 }, {  1, 61 },
+    {  8, 45 }, {  2, 58 }, {  4, 53 }, { 14, 36 },
+    {  7, 47 }, {  5, 51 }, { 10, 42 }, {  6, 49 },
+    { 12, 39 }, { 15, 35 }, {  3, 56 }, {  9, 44 },
+    { 13, 38 }, {  1, 62 }, { 11, 41 }, {  2, 59 },
+    {  8, 46 }, {  4, 54 }, {  7, 48 }, { 14, 37 },
+    {  5, 52 }, {  6, 50 }, { 10, 43 }, { 12, 40 },
+    { 15, 36 }, {  3, 57 }, {  9, 45 }, {  1, 63 },
+    { 13, 39 }, {  2, 60 }, { 11, 42 }, {  8, 47 },
+    {  4, 55 }, {  7, 49 }, {  5, 53 }, {  6, 51 },
+    { 14, 38 }, { 10, 44 }, { 12, 41 }, {  3, 58 },
+    { 15, 37 }, {  9, 46 }, {  2, 61 }, { 13, 40 },
+    {  4, 56 }, { 11, 43 }, {  8, 48 }, {  5, 54 },
+    {  7, 50 }, {  6, 52 }, { 14, 39 }, { 10, 45 },
+    {  3, 59 }, { 12, 42 }, {  2, 62 }, {  9, 47 },
+    { 15, 38 }, {  4, 57 }, { 13, 41 }, { 11, 44 },
+    {  8, 49 }, {  5, 55 }, {  7, 51 }, {  6, 53 },
+    {  3, 60 }, { 10, 46 }, { 14, 40 }, { 12, 43 },
+    {  2, 63 }, {  9, 48 }, {  4, 58 }, { 15, 39 },
+    {  8, 50 }, { 11, 45 }, { 13, 42 }, {  5, 56 },
+    {  7, 52 }, {  6, 54 }, {  3, 61 }, { 10, 47 },
+    { 14, 41 }, { 12, 44 }, {  9, 49 }, {  4, 59 },
+    { 15, 40 }, {  8, 51 }, {  5, 57 }, { 11, 46 },
+    { 13, 43 }, {  7, 53 }, {  6, 55 }, {  3, 62 },
+    { 10, 48 }, { 14, 42 }, { 12, 45 }, {  4, 60 },
+    {  9, 50 }, {  8, 52 }, {  5, 58 }, { 15, 41 },
+    { 11, 47 }, {  7, 54 }, {  6, 56 }, { 13, 44 },
+    {  3, 63 }, { 10, 49 }, { 14, 43 }, {  4, 61 },
+    { 12, 46 }, {  9, 51 }, {  5, 59 }, {  8, 53 },
+    { 15, 42 }, {  6, 57 }, {  7, 55 }, { 11, 48 },
+    { 13, 45 }, { 10, 50 }, {  4, 62 }, { 14, 44 },
+    { 12, 47 }, {  9, 52 }, {  5, 60 }, {  8, 54 },
+    {  6, 58 }, {  7, 56 }, { 11, 49 }, { 15, 43 },
+    { 13, 46 }, { 10, 51 }, {  4, 63 }, { 12, 48 },
+    { 14, 45 }, {  9, 53 }, {  5, 61 }, {  8, 55 },
+    {  6, 59 }, {  7, 57 }, { 11, 50 }, { 15, 44 },
+    { 13, 47 }, { 10, 52 }, {  9, 54 }, { 12, 49 },
+    {  5, 62 }, { 14, 46 }, {  8, 56 }, {  6, 60 },
+    {  7, 58 }, { 11, 51 }, { 15, 45 }, { 13, 48 },
+    { 10, 53 }, {  5, 63 }, {  9, 55 }, { 12, 50 },
+    { 14, 47 }, {  8, 57 }, {  6, 61 }, {  7, 59 },
+    { 11, 52 }, { 15, 46 }, { 13, 49 }, { 10, 54 },
+    {  9, 56 }, { 12, 51 }, {  6, 62 }, {  8, 58 },
+    { 14, 48 }, {  7, 60 }, { 11, 53 }, { 15, 47 },
+    { 12, 52 }, {  8, 59 }, {  7, 61 }, { 14, 49 },
+    { 13, 50 }, { 10, 55 }, {  9, 57 }, {  6, 63 },
+    { 11, 54 }, { 13, 51 }, { 15, 48 }, { 10, 56 },
+    {  9, 58 }, {  8, 60 }, { 12, 53 }, {  7, 62 },
+    { 14, 50 }, { 11, 55 }, { 13, 52 }, { 15, 49 },
+    { 10, 57 }, {  9, 59 }, {  8, 61 }, {  7, 63 },
+    { 12, 54 }, { 14, 51 }, { 11, 56 }, { 13, 53 },
+    { 10, 58 }, { 15, 50 }, {  9, 60 }, {  8, 62 },
+    { 12, 55 }, { 14, 52 }, { 11, 57 }, { 10, 59 },
+    { 13, 54 }, { 15, 51 }, {  9, 61 }, { 8 , 63 },
+    { 12, 56 }, { 14, 53 }, { 11, 58 }, { 10, 60 },
+    { 13, 55 }, { 15, 52 }, {  9, 62 }, { 12, 57 },
+    { 14, 54 }, { 11, 59 }, { 10, 61 }, { 13, 56 },
+    {  9, 63 }, { 15, 53 }, { 12, 58 }, { 14, 55 },
+    { 11, 60 }, { 10, 62 }, { 13, 57 }, { 15, 54 },
+    { 12, 59 }, { 14, 56 }, { 11, 61 }, { 10, 63 },
+    { 13, 58 }, { 15, 55 }, { 12, 60 }, { 14, 57 },
+    { 11, 62 }, { 13, 59 }, { 15, 56 }, { 12, 61 },
+    { 11, 63 }, { 14, 58 }, { 13, 60 }, { 15, 57 },
+    { 12, 62 }, { 14, 59 }, { 13, 61 }, { 15, 58 },
+    { 12, 63 }, { 14, 60 }, { 13, 62 }, { 15, 59 },
+    { 14, 61 }, { 13, 63 }, { 15, 60 }, { 14, 62 },
+    { 15, 61 }, { 14, 63 }, { 15, 62 }, { 15, 63 },
+    { 32, 16 }, { 16, 32 }, { 33, 16 }, { 16, 33 },
+    { 32, 17 }, { 17, 32 }, { 34, 16 }, { 16, 34 },
+    { 33, 17 }, { 17, 33 }, { 32, 18 }, { 18, 32 },
+    { 35, 16 }, { 16, 35 }, { 34, 17 }, { 17, 34 },
+    { 33, 18 }, { 18, 33 }, { 32, 19 }, { 19, 32 },
+    { 36, 16 }, { 16, 36 }, { 35, 17 }, { 17, 35 },
+    { 34, 18 }, { 18, 34 }, { 33, 19 }, { 19, 33 },
+    { 32, 20 }, { 20, 32 }, { 37, 16 }, { 16, 37 },
+    { 36, 17 }, { 17, 36 }, { 35, 18 }, { 18, 35 },
+    { 34, 19 }, { 19, 34 }, { 33, 20 }, { 20, 33 },
+    { 38, 16 }, { 16, 38 }, { 32, 21 }, { 21, 32 },
+    { 37, 17 }, { 17, 37 }, { 36, 18 }, { 18, 36 },
+    { 35, 19 }, { 19, 35 }, { 39, 16 }, { 16, 39 },
+    { 34, 20 }, { 20, 34 }, { 33, 21 }, { 21, 33 },
+    { 38, 17 }, { 17, 38 }, { 32, 22 }, { 22, 32 },
+    { 37, 18 }, { 18, 37 }, { 36, 19 }, { 19, 36 },
+    { 40, 16 }, { 16, 40 }, { 35, 20 }, { 20, 35 },
+    { 34, 21 }, { 21, 34 }, { 39, 17 }, { 17, 39 },
+    { 33, 22 }, { 22, 33 }, { 32, 23 }, { 23, 32 },
+    { 38, 18 }, { 18, 38 }, { 37, 19 }, { 19, 37 },
+    { 41, 16 }, { 16, 41 }, { 36, 20 }, { 20, 36 },
+    { 35, 21 }, { 21, 35 }, { 40, 17 }, { 17, 40 },
+    { 34, 22 }, { 22, 34 }, { 33, 23 }, { 23, 33 },
+    { 39, 18 }, { 18, 39 }, { 32, 24 }, { 24, 32 },
+    { 38, 19 }, { 19, 38 }, { 42, 16 }, { 16, 42 },
+    { 37, 20 }, { 20, 37 }, { 41, 17 }, { 17, 41 },
+    { 36, 21 }, { 21, 36 }, { 35, 22 }, { 22, 35 },
+    { 40, 18 }, { 18, 40 }, { 34, 23 }, { 23, 34 },
+    { 33, 24 }, { 24, 33 }, { 32, 25 }, { 25, 32 },
+    { 39, 19 }, { 19, 39 }, { 43, 16 }, { 16, 43 },
+    { 38, 20 }, { 20, 38 }, { 42, 17 }, { 17, 42 },
+    { 37, 21 }, { 21, 37 }, { 36, 22 }, { 22, 36 },
+    { 41, 18 }, { 18, 41 }, { 35, 23 }, { 23, 35 },
+    { 34, 24 }, { 24, 34 }, { 40, 19 }, { 19, 40 },
+    { 44, 16 }, { 16, 44 }, { 33, 25 }, { 25, 33 },
+    { 32, 26 }, { 26, 32 }, { 39, 20 }, { 20, 39 },
+    { 43, 17 }, { 17, 43 }, { 38, 21 }, { 21, 38 },
+    { 37, 22 }, { 22, 37 }, { 42, 18 }, { 18, 42 },
+    { 36, 23 }, { 23, 36 }, { 45, 16 }, { 16, 45 },
+    { 41, 19 }, { 19, 41 }, { 35, 24 }, { 24, 35 },
+    { 34, 25 }, { 25, 34 }, { 33, 26 }, { 26, 33 },
+    { 40, 20 }, { 20, 40 }, { 32, 27 }, { 27, 32 },
+    { 44, 17 }, { 17, 44 }, { 39, 21 }, { 21, 39 },
+    { 43, 18 }, { 18, 43 }, { 38, 22 }, { 22, 38 },
+    { 37, 23 }, { 23, 37 }, { 46, 16 }, { 16, 46 },
+    { 42, 19 }, { 19, 42 }, { 36, 24 }, { 24, 36 },
+    { 35, 25 }, { 25, 35 }, { 41, 20 }, { 20, 41 },
+    { 34, 26 }, { 26, 34 }, { 45, 17 }, { 17, 45 },
+    { 33, 27 }, { 27, 33 }, { 32, 28 }, { 28, 32 },
+    { 40, 21 }, { 21, 40 }, { 44, 18 }, { 18, 44 },
+    { 39, 22 }, { 22, 39 }, { 38, 23 }, { 23, 38 },
+    { 47, 16 }, { 16, 47 }, { 43, 19 }, { 19, 43 },
+    { 37, 24 }, { 24, 37 }, { 36, 25 }, { 25, 36 },
+    { 42, 20 }, { 20, 42 }, { 46, 17 }, { 17, 46 },
+    { 35, 26 }, { 26, 35 }, { 34, 27 }, { 27, 34 },
+    { 33, 28 }, { 28, 33 }, { 41, 21 }, { 21, 41 },
+    { 32, 29 }, { 29, 32 }, { 45, 18 }, { 18, 45 },
+    { 40, 22 }, { 22, 40 }, { 48, 16 }, { 16, 48 },
+    { 39, 23 }, { 23, 39 }, { 44, 19 }, { 19, 44 },
+    { 38, 24 }, { 24, 38 }, { 43, 20 }, { 20, 43 },
+    { 47, 17 }, { 17, 47 }, { 37, 25 }, { 25, 37 },
+    { 36, 26 }, { 26, 36 }, { 35, 27 }, { 27, 35 },
+    { 42, 21 }, { 21, 42 }, { 34, 28 }, { 28, 34 },
+    { 46, 18 }, { 18, 46 }, { 33, 29 }, { 29, 33 },
+    { 32, 30 }, { 30, 32 }, { 41, 22 }, { 22, 41 },
+    { 49, 16 }, { 16, 49 }, { 45, 19 }, { 19, 45 },
+    { 40, 23 }, { 23, 40 }, { 39, 24 }, { 24, 39 },
+    { 48, 17 }, { 17, 48 }, { 44, 20 }, { 20, 44 },
+    { 38, 25 }, { 25, 38 }, { 37, 26 }, { 26, 37 },
+    { 43, 21 }, { 21, 43 }, { 36, 27 }, { 27, 36 },
+    { 47, 18 }, { 18, 47 }, { 35, 28 }, { 28, 35 },
+    { 34, 29 }, { 29, 34 }, { 42, 22 }, { 22, 42 },
+    { 33, 30 }, { 30, 33 }, { 50, 16 }, { 16, 50 },
+    { 32, 31 }, { 31, 32 }, { 46, 19 }, { 19, 46 },
+    { 41, 23 }, { 23, 41 }, { 40, 24 }, { 24, 40 },
+    { 49, 17 }, { 17, 49 }, { 45, 20 }, { 20, 45 },
+    { 39, 25 }, { 25, 39 }, { 38, 26 }, { 26, 38 },
+    { 44, 21 }, { 21, 44 }, { 48, 18 }, { 18, 48 },
+    { 37, 27 }, { 27, 37 }, { 36, 28 }, { 28, 36 },
+    { 51, 16 }, { 16, 51 }, { 43, 22 }, { 22, 43 },
+    { 35, 29 }, { 29, 35 }, { 34, 30 }, { 30, 34 },
+    { 33, 31 }, { 31, 33 }, { 32, 32 }, { 47, 19 },
+    { 19, 47 }, { 42, 23 }, { 23, 42 }, { 50, 17 },
+    { 17, 50 }, { 41, 24 }, { 24, 41 }, { 46, 20 },
+    { 20, 46 }, { 40, 25 }, { 25, 40 }, { 45, 21 },
+    { 21, 45 }, { 49, 18 }, { 18, 49 }, { 39, 26 },
+    { 26, 39 }, { 38, 27 }, { 27, 38 }, { 52, 16 },
+    { 16, 52 }, { 44, 22 }, { 22, 44 }, { 37, 28 },
+    { 28, 37 }, { 36, 29 }, { 29, 36 }, { 48, 19 },
+    { 19, 48 }, { 35, 30 }, { 30, 35 }, { 34, 31 },
+    { 31, 34 }, { 33, 32 }, { 32, 33 }, { 43, 23 },
+    { 23, 43 }, { 51, 17 }, { 17, 51 }, { 47, 20 },
+    { 20, 47 }, { 42, 24 }, { 24, 42 }, { 41, 25 },
+    { 25, 41 }, { 50, 18 }, { 18, 50 }, { 46, 21 },
+    { 21, 46 }, { 40, 26 }, { 26, 40 }, { 53, 16 },
+    { 16, 53 }, { 39, 27 }, { 27, 39 }, { 45, 22 },
+    { 22, 45 }, { 38, 28 }, { 28, 38 }, { 49, 19 },
+    { 19, 49 }, { 37, 29 }, { 29, 37 }, { 36, 30 },
+    { 30, 36 }, { 44, 23 }, { 23, 44 }, { 52, 17 },
+    { 17, 52 }, { 35, 31 }, { 31, 35 }, { 34, 32 },
+    { 32, 34 }, { 33, 33 }, { 48, 20 }, { 20, 48 },
+    { 43, 24 }, { 24, 43 }, { 42, 25 }, { 25, 42 },
+    { 51, 18 }, { 18, 51 }, { 47, 21 }, { 21, 47 },
+    { 54, 16 }, { 16, 54 }, { 41, 26 }, { 26, 41 },
+    { 40, 27 }, { 27, 40 }, { 46, 22 }, { 22, 46 },
+    { 50, 19 }, { 19, 50 }, { 39, 28 }, { 28, 39 },
+    { 38, 29 }, { 29, 38 }, { 53, 17 }, { 17, 53 },
+    { 45, 23 }, { 23, 45 }, { 37, 30 }, { 30, 37 },
+    { 36, 31 }, { 31, 36 }, { 49, 20 }, { 20, 49 },
+    { 35, 32 }, { 32, 35 }, { 34, 33 }, { 33, 34 },
+    { 44, 24 }, { 24, 44 }, { 52, 18 }, { 18, 52 },
+    { 43, 25 }, { 25, 43 }, { 48, 21 }, { 21, 48 },
+    { 55, 16 }, { 16, 55 }, { 42, 26 }, { 26, 42 },
+    { 47, 22 }, { 22, 47 }, { 51, 19 }, { 19, 51 },
+    { 41, 27 }, { 27, 41 }, { 40, 28 }, { 28, 40 },
+    { 54, 17 }, { 17, 54 }, { 46, 23 }, { 23, 46 },
+    { 39, 29 }, { 29, 39 }, { 50, 20 }, { 20, 50 },
+    { 38, 30 }, { 30, 38 }, { 37, 31 }, { 31, 37 },
+    { 45, 24 }, { 24, 45 }, { 36, 32 }, { 32, 36 },
+    { 35, 33 }, { 33, 35 }, { 34, 34 }, { 53, 18 },
+    { 18, 53 }, { 56, 16 }, { 16, 56 }, { 49, 21 },
+    { 21, 49 }, { 44, 25 }, { 25, 44 }, { 43, 26 },
+    { 26, 43 }, { 48, 22 }, { 22, 48 }, { 52, 19 },
+    { 19, 52 }, { 42, 27 }, { 27, 42 }, { 55, 17 },
+    { 17, 55 }, { 41, 28 }, { 28, 41 }, { 47, 23 },
+    { 23, 47 }, { 40, 29 }, { 29, 40 }, { 51, 20 },
+    { 20, 51 }, { 39, 30 }, { 30, 39 }, { 46, 24 },
+    { 24, 46 }, { 38, 31 }, { 31, 38 }, { 54, 18 },
+    { 18, 54 }, { 37, 32 }, { 32, 37 }, { 57, 16 },
+    { 16, 57 }, { 36, 33 }, { 33, 36 }, { 35, 34 },
+    { 34, 35 }, { 50, 21 }, { 21, 50 }, { 45, 25 },
+    { 25, 45 }, { 44, 26 }, { 26, 44 }, { 53, 19 },
+    { 19, 53 }, { 49, 22 }, { 22, 49 }, { 56, 17 },
+    { 17, 56 }, { 43, 27 }, { 27, 43 }, { 48, 23 },
+    { 23, 48 }, { 42, 28 }, { 28, 42 }, { 52, 20 },
+    { 20, 52 }, { 41, 29 }, { 29, 41 }, { 40, 30 },
+    { 30, 40 }, { 47, 24 }, { 24, 47 }, { 55, 18 },
+    { 18, 55 }, { 58, 16 }, { 16, 58 }, { 39, 31 },
+    { 31, 39 }, { 51, 21 }, { 21, 51 }, { 38, 32 },
+    { 32, 38 }, { 37, 33 }, { 33, 37 }, { 46, 25 },
+    { 25, 46 }, { 36, 34 }, { 34, 36 }, { 35, 35 },
+    { 54, 19 }, { 19, 54 }, { 45, 26 }, { 26, 45 },
+    { 50, 22 }, { 22, 50 }, { 57, 17 }, { 17, 57 },
+    { 44, 27 }, { 27, 44 }, { 49, 23 }, { 23, 49 },
+    { 53, 20 }, { 20, 53 }, { 43, 28 }, { 28, 43 },
+    { 42, 29 }, { 29, 42 }, { 56, 18 }, { 18, 56 },
+    { 59, 16 }, { 16, 59 }, { 48, 24 }, { 24, 48 },
+    { 41, 30 }, { 30, 41 }, { 52, 21 }, { 21, 52 },
+    { 40, 31 }, { 31, 40 }, { 39, 32 }, { 32, 39 },
+    { 47, 25 }, { 25, 47 }, { 38, 33 }, { 33, 38 },
+    { 37, 34 }, { 34, 37 }, { 36, 35 }, { 35, 36 },
+    { 55, 19 }, { 19, 55 }, { 51, 22 }, { 22, 51 },
+    { 46, 26 }, { 26, 46 }, { 58, 17 }, { 17, 58 },
+    { 45, 27 }, { 27, 45 }, { 50, 23 }, { 23, 50 },
+    { 54, 20 }, { 20, 54 }, { 44, 28 }, { 28, 44 },
+    { 57, 18 }, { 18, 57 }, { 60, 16 }, { 16, 60 },
+    { 43, 29 }, { 29, 43 }, { 49, 24 }, { 24, 49 },
+    { 53, 21 }, { 21, 53 }, { 42, 30 }, { 30, 42 },
+    { 41, 31 }, { 31, 41 }, { 48, 25 }, { 25, 48 },
+    { 40, 32 }, { 32, 40 }, { 56, 19 }, { 19, 56 },
+    { 39, 33 }, { 33, 39 }, { 59, 17 }, { 17, 59 },
+    { 52, 22 }, { 22, 52 }, { 38, 34 }, { 34, 38 },
+    { 37, 35 }, { 35, 37 }, { 36, 36 }, { 47, 26 },
+    { 26, 47 }, { 46, 27 }, { 27, 46 }, { 55, 20 },
+    { 20, 55 }, { 51, 23 }, { 23, 51 }, { 45, 28 },
+    { 28, 45 }, { 61, 16 }, { 16, 61 }, { 58, 18 },
+    { 18, 58 }, { 50, 24 }, { 24, 50 }, { 44, 29 },
+    { 29, 44 }, { 54, 21 }, { 21, 54 }, { 43, 30 },
+    { 30, 43 }, { 49, 25 }, { 25, 49 }, { 42, 31 },
+    { 31, 42 }, { 57, 19 }, { 19, 57 }, { 60, 17 },
+    { 17, 60 }, { 41, 32 }, { 32, 41 }, { 53, 22 },
+    { 22, 53 }, { 40, 33 }, { 33, 40 }, { 48, 26 },
+    { 26, 48 }, { 39, 34 }, { 34, 39 }, { 38, 35 },
+    { 35, 38 }, { 37, 36 }, { 36, 37 }, { 56, 20 },
+    { 20, 56 }, { 47, 27 }, { 27, 47 }, { 52, 23 },
+    { 23, 52 }, { 62, 16 }, { 16, 62 }, { 59, 18 },
+    { 18, 59 }, { 46, 28 }, { 28, 46 }, { 51, 24 },
+    { 24, 51 }, { 55, 21 }, { 21, 55 }, { 45, 29 },
+    { 29, 45 }, { 44, 30 }, { 30, 44 }, { 58, 19 },
+    { 19, 58 }, { 50, 25 }, { 25, 50 }, { 61, 17 },
+    { 17, 61 }, { 43, 31 }, { 31, 43 }, { 54, 22 },
+    { 22, 54 }, { 42, 32 }, { 32, 42 }, { 49, 26 },
+    { 26, 49 }, { 41, 33 }, { 33, 41 }, { 40, 34 },
+    { 34, 40 }, { 57, 20 }, { 20, 57 }, { 39, 35 },
+    { 35, 39 }, { 38, 36 }, { 36, 38 }, { 37, 37 },
+    { 53, 23 }, { 23, 53 }, { 48, 27 }, { 27, 48 },
+    { 63, 16 }, { 16, 63 }, { 60, 18 }, { 18, 60 },
+    { 47, 28 }, { 28, 47 }, { 52, 24 }, { 24, 52 },
+    { 56, 21 }, { 21, 56 }, { 46, 29 }, { 29, 46 },
+    { 59, 19 }, { 19, 59 }, { 62, 17 }, { 17, 62 },
+    { 45, 30 }, { 30, 45 }, { 51, 25 }, { 25, 51 },
+    { 55, 22 }, { 22, 55 }, { 44, 31 }, { 31, 44 },
+    { 43, 32 }, { 32, 43 }, { 50, 26 }, { 26, 50 },
+    { 42, 33 }, { 33, 42 }, { 58, 20 }, { 20, 58 },
+    { 41, 34 }, { 34, 41 }, { 54, 23 }, { 23, 54 },
+    { 61, 18 }, { 18, 61 }, { 40, 35 }, { 35, 40 },
+    { 49, 27 }, { 27, 49 }, { 39, 36 }, { 36, 39 },
+    { 38, 37 }, { 37, 38 }, { 48, 28 }, { 28, 48 },
+    { 57, 21 }, { 21, 57 }, { 53, 24 }, { 24, 53 },
+    { 47, 29 }, { 29, 47 }, { 60, 19 }, { 19, 60 },
+    { 63, 17 }, { 17, 63 }, { 52, 25 }, { 25, 52 },
+    { 46, 30 }, { 30, 46 }, { 56, 22 }, { 22, 56 },
+    { 45, 31 }, { 31, 45 }, { 51, 26 }, { 26, 51 },
+    { 44, 32 }, { 32, 44 }, { 59, 20 }, { 20, 59 },
+    { 62, 18 }, { 18, 62 }, { 43, 33 }, { 33, 43 },
+    { 55, 23 }, { 23, 55 }, { 42, 34 }, { 34, 42 },
+    { 50, 27 }, { 27, 50 }, { 41, 35 }, { 35, 41 },
+    { 40, 36 }, { 36, 40 }, { 39, 37 }, { 37, 39 },
+    { 38, 38 }, { 58, 21 }, { 21, 58 }, { 49, 28 },
+    { 28, 49 }, { 54, 24 }, { 24, 54 }, { 61, 19 },
+    { 19, 61 }, { 48, 29 }, { 29, 48 }, { 53, 25 },
+    { 25, 53 }, { 57, 22 }, { 22, 57 }, { 47, 30 },
+    { 30, 47 }, { 46, 31 }, { 31, 46 }, { 60, 20 },
+    { 20, 60 }, { 52, 26 }, { 26, 52 }, { 63, 18 },
+    { 18, 63 }, { 45, 32 }, { 32, 45 }, { 56, 23 },
+    { 23, 56 }, { 44, 33 }, { 33, 44 }, { 51, 27 },
+    { 27, 51 }, { 43, 34 }, { 34, 43 }, { 42, 35 },
+    { 35, 42 }, { 59, 21 }, { 21, 59 }, { 41, 36 },
+    { 36, 41 }, { 55, 24 }, { 24, 55 }, { 40, 37 },
+    { 37, 40 }, { 50, 28 }, { 28, 50 }, { 39, 38 },
+    { 38, 39 }, { 62, 19 }, { 19, 62 }, { 49, 29 },
+    { 29, 49 }, { 54, 25 }, { 25, 54 }, { 58, 22 },
+    { 22, 58 }, { 48, 30 }, { 30, 48 }, { 61, 20 },
+    { 20, 61 }, { 47, 31 }, { 31, 47 }, { 53, 26 },
+    { 26, 53 }, { 57, 23 }, { 23, 57 }, { 46, 32 },
+    { 32, 46 }, { 52, 27 }, { 27, 52 }, { 45, 33 },
+    { 33, 45 }, { 60, 21 }, { 21, 60 }, { 44, 34 },
+    { 34, 44 }, { 56, 24 }, { 24, 56 }, { 43, 35 },
+    { 35, 43 }, { 63, 19 }, { 19, 63 }, { 51, 28 },
+    { 28, 51 }, { 42, 36 }, { 36, 42 }, { 41, 37 },
+    { 37, 41 }, { 40, 38 }, { 38, 40 }, { 39, 39 },
+    { 50, 29 }, { 29, 50 }, { 55, 25 }, { 25, 55 },
+    { 59, 22 }, { 22, 59 }, { 49, 30 }, { 30, 49 },
+    { 62, 20 }, { 20, 62 }, { 54, 26 }, { 26, 54 },
+    { 48, 31 }, { 31, 48 }, { 58, 23 }, { 23, 58 },
+    { 47, 32 }, { 32, 47 }, { 53, 27 }, { 27, 53 },
+    { 46, 33 }, { 33, 46 }, { 61, 21 }, { 21, 61 },
+    { 57, 24 }, { 24, 57 }, { 45, 34 }, { 34, 45 },
+    { 52, 28 }, { 28, 52 }, { 44, 35 }, { 35, 44 },
+    { 43, 36 }, { 36, 43 }, { 42, 37 }, { 37, 42 },
+    { 41, 38 }, { 38, 41 }, { 40, 39 }, { 39, 40 },
+    { 60, 22 }, { 22, 60 }, { 51, 29 }, { 29, 51 },
+    { 56, 25 }, { 25, 56 }, { 63, 20 }, { 20, 63 },
+    { 50, 30 }, { 30, 50 }, { 55, 26 }, { 26, 55 },
+    { 59, 23 }, { 23, 59 }, { 49, 31 }, { 31, 49 },
+    { 48, 32 }, { 32, 48 }, { 54, 27 }, { 27, 54 },
+    { 62, 21 }, { 21, 62 }, { 47, 33 }, { 33, 47 },
+    { 58, 24 }, { 24, 58 }, { 46, 34 }, { 34, 46 },
+    { 53, 28 }, { 28, 53 }, { 45, 35 }, { 35, 45 },
+    { 44, 36 }, { 36, 44 }, { 61, 22 }, { 22, 61 },
+    { 57, 25 }, { 25, 57 }, { 52, 29 }, { 29, 52 },
+    { 43, 37 }, { 37, 43 }, { 42, 38 }, { 38, 42 },
+    { 41, 39 }, { 39, 41 }, { 40, 40 }, { 51, 30 },
+    { 30, 51 }, { 56, 26 }, { 26, 56 }, { 60, 23 },
+    { 23, 60 }, { 50, 31 }, { 31, 50 }, { 63, 21 },
+    { 21, 63 }, { 55, 27 }, { 27, 55 }, { 49, 32 },
+    { 32, 49 }, { 59, 24 }, { 24, 59 }, { 48, 33 },
+    { 33, 48 }, { 54, 28 }, { 28, 54 }, { 47, 34 },
+    { 34, 47 }, { 62, 22 }, { 22, 62 }, { 46, 35 },
+    { 35, 46 }, { 58, 25 }, { 25, 58 }, { 45, 36 },
+    { 36, 45 }, { 53, 29 }, { 29, 53 }, { 44, 37 },
+    { 37, 44 }, { 43, 38 }, { 38, 43 }, { 42, 39 },
+    { 39, 42 }, { 41, 40 }, { 40, 41 }, { 52, 30 },
+    { 30, 52 }, { 57, 26 }, { 26, 57 }, { 61, 23 },
+    { 23, 61 }, { 51, 31 }, { 31, 51 }, { 56, 27 },
+    { 27, 56 }, { 50, 32 }, { 32, 50 }, { 60, 24 },
+    { 24, 60 }, { 49, 33 }, { 33, 49 }, { 55, 28 },
+    { 28, 55 }, { 63, 22 }, { 22, 63 }, { 48, 34 },
+    { 34, 48 }, { 59, 25 }, { 25, 59 }, { 47, 35 },
+    { 35, 47 }, { 54, 29 }, { 29, 54 }, { 46, 36 },
+    { 36, 46 }, { 45, 37 }, { 37, 45 }, { 44, 38 },
+    { 38, 44 }, { 53, 30 }, { 30, 53 }, { 62, 23 },
+    { 23, 62 }, { 58, 26 }, { 26, 58 }, { 43, 39 },
+    { 39, 43 }, { 42, 40 }, { 40, 42 }, { 41, 41 },
+    { 52, 31 }, { 31, 52 }, { 57, 27 }, { 27, 57 },
+    { 61, 24 }, { 24, 61 }, { 51, 32 }, { 32, 51 },
+    { 50, 33 }, { 33, 50 }, { 56, 28 }, { 28, 56 },
+    { 49, 34 }, { 34, 49 }, { 60, 25 }, { 25, 60 },
+    { 48, 35 }, { 35, 48 }, { 55, 29 }, { 29, 55 },
+    { 47, 36 }, { 36, 47 }, { 63, 23 }, { 23, 63 },
+    { 46, 37 }, { 37, 46 }, { 59, 26 }, { 26, 59 },
+    { 54, 30 }, { 30, 54 }, { 45, 38 }, { 38, 45 },
+    { 44, 39 }, { 39, 44 }, { 43, 40 }, { 40, 43 },
+    { 42, 41 }, { 41, 42 }, { 53, 31 }, { 31, 53 },
+    { 58, 27 }, { 27, 58 }, { 62, 24 }, { 24, 62 },
+    { 52, 32 }, { 32, 52 }, { 57, 28 }, { 28, 57 },
+    { 51, 33 }, { 33, 51 }, { 61, 25 }, { 25, 61 },
+    { 50, 34 }, { 34, 50 }, { 56, 29 }, { 29, 56 },
+    { 49, 35 }, { 35, 49 }, { 48, 36 }, { 36, 48 },
+    { 60, 26 }, { 26, 60 }, { 55, 30 }, { 30, 55 },
+    { 47, 37 }, { 37, 47 }, { 46, 38 }, { 38, 46 },
+    { 45, 39 }, { 39, 45 }, { 44, 40 }, { 40, 44 },
+    { 54, 31 }, { 31, 54 }, { 43, 41 }, { 41, 43 },
+    { 42, 42 }, { 59, 27 }, { 27, 59 }, { 63, 24 },
+    { 24, 63 }, { 53, 32 }, { 32, 53 }, { 58, 28 },
+    { 28, 58 }, { 52, 33 }, { 33, 52 }, { 62, 25 },
+    { 25, 62 }, { 51, 34 }, { 34, 51 }, { 57, 29 },
+    { 29, 57 }, { 50, 35 }, { 35, 50 }, { 61, 26 },
+    { 26, 61 }, { 49, 36 }, { 36, 49 }, { 56, 30 },
+    { 30, 56 }, { 48, 37 }, { 37, 48 }, { 47, 38 },
+    { 38, 47 }, { 55, 31 }, { 31, 55 }, { 60, 27 },
+    { 27, 60 }, { 46, 39 }, { 39, 46 }, { 45, 40 },
+    { 40, 45 }, { 44, 41 }, { 41, 44 }, { 43, 42 },
+    { 42, 43 }, { 54, 32 }, { 32, 54 }, { 59, 28 },
+    { 28, 59 }, { 63, 25 }, { 25, 63 }, { 53, 33 },
+    { 33, 53 }, { 52, 34 }, { 34, 52 }, { 58, 29 },
+    { 29, 58 }, { 51, 35 }, { 35, 51 }, { 62, 26 },
+    { 26, 62 }, { 57, 30 }, { 30, 57 }, { 50, 36 },
+    { 36, 50 }, { 49, 37 }, { 37, 49 }, { 61, 27 },
+    { 27, 61 }, { 48, 38 }, { 38, 48 }, { 56, 31 },
+    { 31, 56 }, { 47, 39 }, { 39, 47 }, { 46, 40 },
+    { 40, 46 }, { 45, 41 }, { 41, 45 }, { 44, 42 },
+    { 42, 44 }, { 43, 43 }, { 55, 32 }, { 32, 55 },
+    { 60, 28 }, { 28, 60 }, { 54, 33 }, { 33, 54 },
+    { 59, 29 }, { 29, 59 }, { 53, 34 }, { 34, 53 },
+    { 63, 26 }, { 26, 63 }, { 52, 35 }, { 35, 52 },
+    { 58, 30 }, { 30, 58 }, { 51, 36 }, { 36, 51 },
+    { 50, 37 }, { 37, 50 }, { 62, 27 }, { 27, 62 },
+    { 57, 31 }, { 31, 57 }, { 49, 38 }, { 38, 49 },
+    { 48, 39 }, { 39, 48 }, { 47, 40 }, { 40, 47 },
+    { 56, 32 }, { 32, 56 }, { 46, 41 }, { 41, 46 },
+    { 61, 28 }, { 28, 61 }, { 45, 42 }, { 42, 45 },
+    { 44, 43 }, { 43, 44 }, { 55, 33 }, { 33, 55 },
+    { 60, 29 }, { 29, 60 }, { 54, 34 }, { 34, 54 },
+    { 53, 35 }, { 35, 53 }, { 59, 30 }, { 30, 59 },
+    { 52, 36 }, { 36, 52 }, { 63, 27 }, { 27, 63 },
+    { 51, 37 }, { 37, 51 }, { 58, 31 }, { 31, 58 },
+    { 50, 38 }, { 38, 50 }, { 49, 39 }, { 39, 49 },
+    { 57, 32 }, { 32, 57 }, { 62, 28 }, { 28, 62 },
+    { 48, 40 }, { 40, 48 }, { 47, 41 }, { 41, 47 },
+    { 46, 42 }, { 42, 46 }, { 45, 43 }, { 43, 45 },
+    { 44, 44 }, { 56, 33 }, { 33, 56 }, { 61, 29 },
+    { 29, 61 }, { 55, 34 }, { 34, 55 }, { 54, 35 },
+    { 35, 54 }, { 60, 30 }, { 30, 60 }, { 53, 36 },
+    { 36, 53 }, { 59, 31 }, { 31, 59 }, { 52, 37 },
+    { 37, 52 }, { 51, 38 }, { 38, 51 }, { 63, 28 },
+    { 28, 63 }, { 58, 32 }, { 32, 58 }, { 50, 39 },
+    { 39, 50 }, { 49, 40 }, { 40, 49 }, { 48, 41 },
+    { 41, 48 }, { 57, 33 }, { 33, 57 }, { 47, 42 },
+    { 42, 47 }, { 46, 43 }, { 43, 46 }, { 45, 44 },
+    { 44, 45 }, { 62, 29 }, { 29, 62 }, { 56, 34 },
+    { 34, 56 }, { 61, 30 }, { 30, 61 }, { 55, 35 },
+    { 35, 55 }, { 54, 36 }, { 36, 54 }, { 60, 31 },
+    { 31, 60 }, { 53, 37 }, { 37, 53 }, { 52, 38 },
+    { 38, 52 }, { 59, 32 }, { 32, 59 }, { 51, 39 },
+    { 39, 51 }, { 50, 40 }, { 40, 50 }, { 58, 33 },
+    { 33, 58 }, { 49, 41 }, { 41, 49 }, { 63, 29 },
+    { 29, 63 }, { 48, 42 }, { 42, 48 }, { 47, 43 },
+    { 43, 47 }, { 46, 44 }, { 44, 46 }, { 45, 45 },
+    { 57, 34 }, { 34, 57 }, { 62, 30 }, { 30, 62 },
+    { 56, 35 }, { 35, 56 }, { 55, 36 }, { 36, 55 },
+    { 61, 31 }, { 31, 61 }, { 54, 37 }, { 37, 54 },
+    { 60, 32 }, { 32, 60 }, { 53, 38 }, { 38, 53 },
+    { 52, 39 }, { 39, 52 }, { 51, 40 }, { 40, 51 },
+    { 59, 33 }, { 33, 59 }, { 50, 41 }, { 41, 50 },
+    { 49, 42 }, { 42, 49 }, { 48, 43 }, { 43, 48 },
+    { 58, 34 }, { 34, 58 }, { 47, 44 }, { 44, 47 },
+    { 46, 45 }, { 45, 46 }, { 63, 30 }, { 30, 63 },
+    { 57, 35 }, { 35, 57 }, { 62, 31 }, { 31, 62 },
+    { 56, 36 }, { 36, 56 }, { 55, 37 }, { 37, 55 },
+    { 61, 32 }, { 32, 61 }, { 54, 38 }, { 38, 54 },
+    { 53, 39 }, { 39, 53 }, { 60, 33 }, { 33, 60 },
+    { 52, 40 }, { 40, 52 }, { 51, 41 }, { 41, 51 },
+    { 50, 42 }, { 42, 50 }, { 59, 34 }, { 34, 59 },
+    { 49, 43 }, { 43, 49 }, { 48, 44 }, { 44, 48 },
+    { 47, 45 }, { 45, 47 }, { 46, 46 }, { 58, 35 },
+    { 35, 58 }, { 63, 31 }, { 31, 63 }, { 57, 36 },
+    { 36, 57 }, { 56, 37 }, { 37, 56 }, { 62, 32 },
+    { 32, 62 }, { 55, 38 }, { 38, 55 }, { 54, 39 },
+    { 39, 54 }, { 61, 33 }, { 33, 61 }, { 53, 40 },
+    { 40, 53 }, { 52, 41 }, { 41, 52 }, { 60, 34 },
+    { 34, 60 }, { 51, 42 }, { 42, 51 }, { 50, 43 },
+    { 43, 50 }, { 49, 44 }, { 44, 49 }, { 48, 45 },
+    { 45, 48 }, { 59, 35 }, { 35, 59 }, { 47, 46 },
+    { 46, 47 }, { 58, 36 }, { 36, 58 }, { 57, 37 },
+    { 37, 57 }, { 63, 32 }, { 32, 63 }, { 56, 38 },
+    { 38, 56 }, { 62, 33 }, { 33, 62 }, { 55, 39 },
+    { 39, 55 }, { 54, 40 }, { 40, 54 }, { 61, 34 },
+    { 34, 61 }, { 53, 41 }, { 41, 53 }, { 52, 42 },
+    { 42, 52 }, { 51, 43 }, { 43, 51 }, { 60, 35 },
+    { 35, 60 }, { 50, 44 }, { 44, 50 }, { 49, 45 },
+    { 45, 49 }, { 48, 46 }, { 46, 48 }, { 47, 47 },
+    { 59, 36 }, { 36, 59 }, { 58, 37 }, { 37, 58 },
+    { 57, 38 }, { 38, 57 }, { 63, 33 }, { 33, 63 },
+    { 56, 39 }, { 39, 56 }, { 55, 40 }, { 40, 55 },
+    { 62, 34 }, { 34, 62 }, { 54, 41 }, { 41, 54 },
+    { 53, 42 }, { 42, 53 }, { 61, 35 }, { 35, 61 },
+    { 52, 43 }, { 43, 52 }, { 51, 44 }, { 44, 51 },
+    { 50, 45 }, { 45, 50 }, { 49, 46 }, { 46, 49 },
+    { 48, 47 }, { 47, 48 }, { 60, 36 }, { 36, 60 },
+    { 59, 37 }, { 37, 59 }, { 58, 38 }, { 38, 58 },
+    { 57, 39 }, { 39, 57 }, { 56, 40 }, { 40, 56 },
+    { 63, 34 }, { 34, 63 }, { 55, 41 }, { 41, 55 },
+    { 54, 42 }, { 42, 54 }, { 62, 35 }, { 35, 62 },
+    { 53, 43 }, { 43, 53 }, { 52, 44 }, { 44, 52 },
+    { 51, 45 }, { 45, 51 }, { 61, 36 }, { 36, 61 },
+    { 50, 46 }, { 46, 50 }, { 49, 47 }, { 47, 49 },
+    { 48, 48 }, { 60, 37 }, { 37, 60 }, { 59, 38 },
+    { 38, 59 }, { 58, 39 }, { 39, 58 }, { 57, 40 },
+    { 40, 57 }, { 56, 41 }, { 41, 56 }, { 63, 35 },
+    { 35, 63 }, { 55, 42 }, { 42, 55 }, { 54, 43 },
+    { 43, 54 }, { 53, 44 }, { 44, 53 }, { 62, 36 },
+    { 36, 62 }, { 52, 45 }, { 45, 52 }, { 51, 46 },
+    { 46, 51 }, { 50, 47 }, { 47, 50 }, { 49, 48 },
+    { 48, 49 }, { 61, 37 }, { 37, 61 }, { 60, 38 },
+    { 38, 60 }, { 59, 39 }, { 39, 59 }, { 58, 40 },
+    { 40, 58 }, { 57, 41 }, { 41, 57 }, { 56, 42 },
+    { 42, 56 }, { 55, 43 }, { 43, 55 }, { 63, 36 },
+    { 36, 63 }, { 54, 44 }, { 44, 54 }, { 53, 45 },
+    { 45, 53 }, { 52, 46 }, { 46, 52 }, { 62, 37 },
+    { 37, 62 }, { 51, 47 }, { 47, 51 }, { 50, 48 },
+    { 48, 50 }, { 49, 49 }, { 61, 38 }, { 38, 61 },
+    { 60, 39 }, { 39, 60 }, { 59, 40 }, { 40, 59 },
+    { 58, 41 }, { 41, 58 }, { 57, 42 }, { 42, 57 },
+    { 56, 43 }, { 43, 56 }, { 55, 44 }, { 44, 55 },
+    { 54, 45 }, { 45, 54 }, { 63, 37 }, { 37, 63 },
+    { 53, 46 }, { 46, 53 }, { 52, 47 }, { 47, 52 },
+    { 51, 48 }, { 48, 51 }, { 50, 49 }, { 49, 50 },
+    { 62, 38 }, { 38, 62 }, { 61, 39 }, { 39, 61 },
+    { 60, 40 }, { 40, 60 }, { 59, 41 }, { 41, 59 },
+    { 58, 42 }, { 42, 58 }, { 57, 43 }, { 43, 57 },
+    { 56, 44 }, { 44, 56 }, { 55, 45 }, { 45, 55 },
+    { 54, 46 }, { 46, 54 }, { 53, 47 }, { 47, 53 },
+    { 52, 48 }, { 48, 52 }, { 63, 38 }, { 38, 63 },
+    { 51, 49 }, { 49, 51 }, { 50, 50 }, { 62, 39 },
+    { 39, 62 }, { 61, 40 }, { 40, 61 }, { 60, 41 },
+    { 41, 60 }, { 59, 42 }, { 42, 59 }, { 58, 43 },
+    { 43, 58 }, { 57, 44 }, { 44, 57 }, { 56, 45 },
+    { 45, 56 }, { 55, 46 }, { 46, 55 }, { 54, 47 },
+    { 47, 54 }, { 53, 48 }, { 48, 53 }, { 52, 49 },
+    { 49, 52 }, { 51, 50 }, { 50, 51 }, { 63, 39 },
+    { 39, 63 }, { 62, 40 }, { 40, 62 }, { 61, 41 },
+    { 41, 61 }, { 60, 42 }, { 42, 60 }, { 59, 43 },
+    { 43, 59 }, { 58, 44 }, { 44, 58 }, { 57, 45 },
+    { 45, 57 }, { 56, 46 }, { 46, 56 }, { 55, 47 },
+    { 47, 55 }, { 54, 48 }, { 48, 54 }, { 53, 49 },
+    { 49, 53 }, { 52, 50 }, { 50, 52 }, { 51, 51 },
+    { 63, 40 }, { 40, 63 }, { 62, 41 }, { 41, 62 },
+    { 61, 42 }, { 42, 61 }, { 60, 43 }, { 43, 60 },
+    { 59, 44 }, { 44, 59 }, { 58, 45 }, { 45, 58 },
+    { 57, 46 }, { 46, 57 }, { 56, 47 }, { 47, 56 },
+    { 55, 48 }, { 48, 55 }, { 54, 49 }, { 49, 54 },
+    { 53, 50 }, { 50, 53 }, { 52, 51 }, { 51, 52 },
+    { 63, 41 }, { 41, 63 }, { 62, 42 }, { 42, 62 },
+    { 61, 43 }, { 43, 61 }, { 60, 44 }, { 44, 60 },
+    { 59, 45 }, { 45, 59 }, { 58, 46 }, { 46, 58 },
+    { 57, 47 }, { 47, 57 }, { 56, 48 }, { 48, 56 },
+    { 55, 49 }, { 49, 55 }, { 54, 50 }, { 50, 54 },
+    { 53, 51 }, { 51, 53 }, { 52, 52 }, { 63, 42 },
+    { 42, 63 }, { 62, 43 }, { 43, 62 }, { 61, 44 },
+    { 44, 61 }, { 60, 45 }, { 45, 60 }, { 59, 46 },
+    { 46, 59 }, { 58, 47 }, { 47, 58 }, { 57, 48 },
+    { 48, 57 }, { 56, 49 }, { 49, 56 }, { 55, 50 },
+    { 50, 55 }, { 54, 51 }, { 51, 54 }, { 53, 52 },
+    { 52, 53 }, { 63, 43 }, { 43, 63 }, { 62, 44 },
+    { 44, 62 }, { 61, 45 }, { 45, 61 }, { 60, 46 },
+    { 46, 60 }, { 59, 47 }, { 47, 59 }, { 58, 48 },
+    { 48, 58 }, { 57, 49 }, { 49, 57 }, { 56, 50 },
+    { 50, 56 }, { 55, 51 }, { 51, 55 }, { 54, 52 },
+    { 52, 54 }, { 53, 53 }, { 63, 44 }, { 44, 63 },
+    { 62, 45 }, { 45, 62 }, { 61, 46 }, { 46, 61 },
+    { 60, 47 }, { 47, 60 }, { 59, 48 }, { 48, 59 },
+    { 58, 49 }, { 49, 58 }, { 57, 50 }, { 50, 57 },
+    { 56, 51 }, { 51, 56 }, { 55, 52 }, { 52, 55 },
+    { 54, 53 }, { 53, 54 }, { 63, 45 }, { 45, 63 },
+    { 62, 46 }, { 46, 62 }, { 61, 47 }, { 47, 61 },
+    { 60, 48 }, { 48, 60 }, { 59, 49 }, { 49, 59 },
+    { 58, 50 }, { 50, 58 }, { 57, 51 }, { 51, 57 },
+    { 56, 52 }, { 52, 56 }, { 55, 53 }, { 53, 55 },
+    { 54, 54 }, { 63, 46 }, { 46, 63 }, { 62, 47 },
+    { 47, 62 }, { 61, 48 }, { 48, 61 }, { 60, 49 },
+    { 49, 60 }, { 59, 50 }, { 50, 59 }, { 58, 51 },
+    { 51, 58 }, { 57, 52 }, { 52, 57 }, { 56, 53 },
+    { 53, 56 }, { 55, 54 }, { 54, 55 }, { 63, 47 },
+    { 47, 63 }, { 62, 48 }, { 48, 62 }, { 61, 49 },
+    { 49, 61 }, { 60, 50 }, { 50, 60 }, { 59, 51 },
+    { 51, 59 }, { 58, 52 }, { 52, 58 }, { 57, 53 },
+    { 53, 57 }, { 56, 54 }, { 54, 56 }, { 55, 55 },
+    { 63, 48 }, { 48, 63 }, { 62, 49 }, { 49, 62 },
+    { 61, 50 }, { 50, 61 }, { 60, 51 }, { 51, 60 },
+    { 59, 52 }, { 52, 59 }, { 58, 53 }, { 53, 58 },
+    { 57, 54 }, { 54, 57 }, { 56, 55 }, { 55, 56 },
+    { 63, 49 }, { 49, 63 }, { 62, 50 }, { 50, 62 },
+    { 61, 51 }, { 51, 61 }, { 60, 52 }, { 52, 60 },
+    { 59, 53 }, { 53, 59 }, { 58, 54 }, { 54, 58 },
+    { 57, 55 }, { 55, 57 }, { 56, 56 }, { 63, 50 },
+    { 50, 63 }, { 62, 51 }, { 51, 62 }, { 61, 52 },
+    { 52, 61 }, { 60, 53 }, { 53, 60 }, { 59, 54 },
+    { 54, 59 }, { 58, 55 }, { 55, 58 }, { 57, 56 },
+    { 56, 57 }, { 63, 51 }, { 51, 63 }, { 62, 52 },
+    { 52, 62 }, { 61, 53 }, { 53, 61 }, { 60, 54 },
+    { 54, 60 }, { 59, 55 }, { 55, 59 }, { 58, 56 },
+    { 56, 58 }, { 57, 57 }, { 63, 52 }, { 52, 63 },
+    { 62, 53 }, { 53, 62 }, { 61, 54 }, { 54, 61 },
+    { 60, 55 }, { 55, 60 }, { 59, 56 }, { 56, 59 },
+    { 58, 57 }, { 57, 58 }, { 63, 53 }, { 53, 63 },
+    { 62, 54 }, { 54, 62 }, { 61, 55 }, { 55, 61 },
+    { 60, 56 }, { 56, 60 }, { 59, 57 }, { 57, 59 },
+    { 58, 58 }, { 63, 54 }, { 54, 63 }, { 62, 55 },
+    { 55, 62 }, { 61, 56 }, { 56, 61 }, { 60, 57 },
+    { 57, 60 }, { 59, 58 }, { 58, 59 }, { 63, 55 },
+    { 55, 63 }, { 62, 56 }, { 56, 62 }, { 61, 57 },
+    { 57, 61 }, { 60, 58 }, { 58, 60 }, { 59, 59 },
+    { 63, 56 }, { 56, 63 }, { 62, 57 }, { 57, 62 },
+    { 61, 58 }, { 58, 61 }, { 60, 59 }, { 59, 60 },
+    { 63, 57 }, { 57, 63 }, { 62, 58 }, { 58, 62 },
+    { 61, 59 }, { 59, 61 }, { 60, 60 }, { 63, 58 },
+    { 58, 63 }, { 62, 59 }, { 59, 62 }, { 61, 60 },
+    { 60, 61 }, { 63, 59 }, { 59, 63 }, { 62, 60 },
+    { 60, 62 }, { 61, 61 }, { 63, 60 }, { 60, 63 },
+    { 62, 61 }, { 61, 62 }, { 63, 61 }, { 61, 63 },
+    { 62, 62 }, { 63, 62 }, { 62, 63 }, { 63, 63 }
+};
+
+static const int   daala_layout_offset4x4[] = { 0 };
+static const int   daala_layout_offset8x8[] = { 0, 8, 16 };
+static const int daala_layout_offset16x16[] = { 0, 32, 64 };
+static const int daala_layout_offset32x32[] = { 0, 128 };
+static const int daala_layout_offset64x64[] = { 0 };
+
+static const int   daala_band_offset4x4[] = { 1, 16 };
+static const int   daala_band_offset8x8[] = { 1, 16, 24, 32, 64 };
+static const int daala_band_offset16x16[] = { 1, 16, 24, 32, 64, 96, 128, 256 };
+static const int daala_band_offset32x32[] = { 1, 16, 24, 32, 64, 96, 128, 256, 384, 512 };
+static const int daala_band_offset64x64[] = { 1, 16, 24, 32, 64, 96, 128, 256, 384, 512 };
+
+const DaalaBandLayout ff_daala_layouts[] = {
+    {
+        daala_zigzag4x4,
+        FF_ARRAY_ELEMS(daala_zigzag4x4),
+        daala_layout_offset4x4,
+        FF_ARRAY_ELEMS(daala_layout_offset4x4),
+        daala_band_offset4x4,
+        FF_ARRAY_ELEMS(daala_band_offset4x4) - 1
+    },
+    {
+        daala_zigzag8x8,
+        FF_ARRAY_ELEMS(daala_zigzag8x8),
+        daala_layout_offset8x8,
+        FF_ARRAY_ELEMS(daala_layout_offset8x8),
+        daala_band_offset8x8,
+        FF_ARRAY_ELEMS(daala_band_offset8x8) - 1
+    },
+    {
+        daala_zigzag16x16,
+        FF_ARRAY_ELEMS(daala_zigzag16x16),
+        daala_layout_offset16x16,
+        FF_ARRAY_ELEMS(daala_layout_offset16x16),
+        daala_band_offset16x16,
+        FF_ARRAY_ELEMS(daala_band_offset16x16) - 1
+    },
+    {
+        daala_zigzag32x32,
+        FF_ARRAY_ELEMS(daala_zigzag32x32),
+        daala_layout_offset32x32,
+        FF_ARRAY_ELEMS(daala_layout_offset32x32),
+        daala_band_offset32x32,
+        FF_ARRAY_ELEMS(daala_band_offset32x32) - 1
+    },
+    {
+        daala_zigzag64x64,
+        FF_ARRAY_ELEMS(daala_zigzag64x64),
+        daala_layout_offset64x64,
+        FF_ARRAY_ELEMS(daala_layout_offset64x64),
+        daala_band_offset64x64,
+        FF_ARRAY_ELEMS(daala_band_offset64x64) - 1
+    }
+};
+
+static const double daala_basis_qm_mag_4x4_l[] = {
+    0.870774f, 0.872037f, 0.949493f, 0.947936f
+};
+
+static const double daala_basis_qm_mag_8x8_l[] = {
+    0.936496f, 0.892830f, 0.938452f, 0.970087f,
+    0.974272f, 0.967954f, 0.974035f, 0.990480f
+};
+static const double daala_basis_qm_mag_16x16_l[] = {
+    0.968807f, 0.940969f, 0.947977f, 0.957741f,
+    0.969762f, 0.978644f, 0.984885f, 0.988009f,
+    0.987424f, 0.985569f, 0.984215f, 0.984462f,
+    0.987205f, 0.991415f, 0.994985f, 0.998237f
+};
+static const double daala_basis_qm_mag_32x32_l[] = {
+    0.985068f, 0.970006f, 0.969893f, 0.973192f,
+    0.973444f, 0.975881f, 0.979601f, 0.981070f,
+    0.984989f, 0.987520f, 0.988830f, 0.990983f,
+    0.992376f, 0.992884f, 0.993447f, 0.993381f,
+    0.993712f, 0.994060f, 0.993294f, 0.992392f,
+    0.991338f, 0.992410f, 0.992051f, 0.993874f,
+    0.993488f, 0.994162f, 0.995318f, 0.995925f,
+    0.997475f, 0.999027f, 0.998303f, 1.001413f,
+};
+static const double daala_basis_qm_mag_64x64_l[] = {
+    0.992453f, 0.984930f, 0.985137f, 0.985029f,
+    0.985514f, 0.985784f, 0.986269f, 0.986854f,
+    0.989932f, 0.987780f, 0.988269f, 0.989175f,
+    0.989951f, 0.990466f, 0.991145f, 0.991839f,
+    0.990773f, 0.993191f, 0.993618f, 0.994221f,
+    0.994662f, 0.995259f, 0.995826f, 0.995996f,
+    0.999070f, 0.996624f, 0.996835f, 0.996948f,
+    0.997022f, 0.996973f, 0.996993f, 0.996996f,
+    0.996871f, 0.996828f, 0.996598f, 0.996688f,
+    0.996845f, 0.996407f, 0.996327f, 0.996435f,
+    0.999173f, 0.996216f, 0.995981f, 0.996173f,
+    0.996595f, 0.996334f, 0.996512f, 0.996627f,
+    0.994976f, 0.997113f, 0.997248f, 0.997548f,
+    0.997943f, 0.998121f, 0.998291f, 0.998687f,
+    1.001696f, 0.999133f, 0.999315f, 0.999621f,
+    0.999745f, 0.999905f, 0.999936f, 1.000075f
+};
+
+static const double daala_basis_qm_mag_4x4_c420[] = {
+    0.870774f, 0.872037f, 0.949493f, 0.947936f
+};
+static const double daala_basis_qm_mag_8x8_c420[] = {
+    0.936496f, 0.892830f, 0.938452f, 0.970087f,
+    0.974272f, 0.967954f, 0.974035f, 0.990480f
+};
+static const double daala_basis_qm_mag_16x16_c420[] = {
+    0.968807f, 0.940969f, 0.947977f, 0.957741f,
+    0.969762f, 0.978644f, 0.984885f, 0.988009f,
+    0.987424f, 0.985569f, 0.984215f, 0.984462f,
+    0.987205f, 0.991415f, 0.994985f, 0.998237f
+};
+static const double daala_basis_qm_mag_32x32_c420[] = {
+    0.985068f, 0.970006f, 0.969893f, 0.973192f,
+    0.973444f, 0.975881f, 0.979601f, 0.981070f,
+    0.984989f, 0.987520f, 0.988830f, 0.990983f,
+    0.992376f, 0.992884f, 0.993447f, 0.993381f,
+    0.993712f, 0.994060f, 0.993294f, 0.992392f,
+    0.991338f, 0.992410f, 0.992051f, 0.993874f,
+    0.993488f, 0.994162f, 0.995318f, 0.995925f,
+    0.997475f, 0.999027f, 0.998303f, 1.001413f
+};
+static const double daala_basis_qm_mag_64x64_c420[] = {
+    0.992453f, 0.984930f, 0.985137f, 0.985029f,
+    0.985514f, 0.985784f, 0.986269f, 0.986854f,
+    0.989932f, 0.987780f, 0.988269f, 0.989175f,
+    0.989951f, 0.990466f, 0.991145f, 0.991839f,
+    0.990773f, 0.993191f, 0.993618f, 0.994221f,
+    0.994662f, 0.995259f, 0.995826f, 0.995996f,
+    0.999070f, 0.996624f, 0.996835f, 0.996948f,
+    0.997022f, 0.996973f, 0.996993f, 0.996996f,
+    0.996871f, 0.996828f, 0.996598f, 0.996688f,
+    0.996845f, 0.996407f, 0.996327f, 0.996435f,
+    0.999173f, 0.996216f, 0.995981f, 0.996173f,
+    0.996595f, 0.996334f, 0.996512f, 0.996627f,
+    0.994976f, 0.997113f, 0.997248f, 0.997548f,
+    0.997943f, 0.998121f, 0.998291f, 0.998687f,
+    1.001696f, 0.999133f, 0.999315f, 0.999621f,
+    0.999745f, 0.999905f, 0.999936f, 1.000075f
+};
+
+const double *ff_daala_basis_qm_mag[2][DAALA_NBSIZES+1] = {
+    {
+        daala_basis_qm_mag_4x4_l,
+        daala_basis_qm_mag_8x8_l,
+        daala_basis_qm_mag_16x16_l,
+        daala_basis_qm_mag_32x32_l,
+        daala_basis_qm_mag_64x64_l
+    },
+    {
+        daala_basis_qm_mag_4x4_c420,
+        daala_basis_qm_mag_8x8_c420,
+        daala_basis_qm_mag_16x16_c420,
+        daala_basis_qm_mag_32x32_c420,
+        daala_basis_qm_mag_64x64_c420
+    }
+};
+
+static const double daala_pvq_beta_4x4_l[]   = {1.0f};
+static const double daala_pvq_beta_8x8_l[]   = {1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_16x16_l[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_32x32_l[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_64x64_l[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+
+static const double daala_pvq_beta_4x4_am_l[]   = {1.0f};
+static const double daala_pvq_beta_8x8_am_l[]   = {1.5f, 1.5f, 1.5f, 1.5f};
+static const double daala_pvq_beta_16x16_am_l[] = {1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f};
+static const double daala_pvq_beta_32x32_am_l[] = {1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f};
+static const double daala_pvq_beta_64x64_am_l[] = {1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f, 1.5f};
+
+static const double daala_pvq_beta_4x4_c[]   = {1.0f};
+static const double daala_pvq_beta_8x8_c[]   = {1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_16x16_c[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_32x32_c[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+static const double daala_pvq_beta_64x64_c[] = {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};
+
+const double *const ff_daalapvq_beta[2][DAALA_MAX_PLANES][DAALA_NBSIZES + 1] = {
+    {
+        {
+            daala_pvq_beta_4x4_l,
+            daala_pvq_beta_8x8_l,
+            daala_pvq_beta_16x16_l,
+            daala_pvq_beta_32x32_l,
+            daala_pvq_beta_64x64_l
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        }
+    },
+    {
+        {
+            daala_pvq_beta_4x4_am_l,
+            daala_pvq_beta_8x8_am_l,
+            daala_pvq_beta_16x16_am_l,
+            daala_pvq_beta_32x32_am_l,
+            daala_pvq_beta_64x64_am_l
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        },
+        {
+            daala_pvq_beta_4x4_c,
+            daala_pvq_beta_8x8_c,
+            daala_pvq_beta_16x16_c,
+            daala_pvq_beta_32x32_c,
+            daala_pvq_beta_64x64_c
+        }
+    }
+};
diff --git a/libavcodec/daalatab.h b/libavcodec/daalatab.h
new file mode 100644
index 0000000..eb9ab7f
--- /dev/null
+++ b/libavcodec/daalatab.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2001-2015 Xiph.Org and contributors.
+ * Copyright 2015 Rostislav Pehlivanov <atomnuker at gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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_DAALATAB_H
+#define AVCODEC_DAALATAB_H
+
+#include "daala.h"
+
+typedef uint8_t daala_u8_doublet[2];
+
+typedef struct DaalaBandLayout {
+    const daala_u8_doublet *const tab;
+    const int tab_size;
+    const int *layout_offset;
+    const int layout_offset_size;
+    const int *band_offset;
+    const int band_offset_size;
+} DaalaBandLayout;
+
+struct DaalaPixFmts {
+    enum AVPixelFormat fmt;
+    int planes, depth, depth_mode;
+    int dec[DAALA_MAX_PLANES][2];
+};
+
+extern const struct DaalaPixFmts ff_daala_valid_formats[];
+extern const int ff_daala_valid_formats_num;
+
+/* Haar "quantization matrix" for each decomposition level */
+extern const uint8_t ff_daala_haar_qm[][DAALA_LOG_BSIZE_MAX];
+
+/* Per-plane keyframe bilinear blur filter strength */
+extern const uint8_t ff_daala_bilinear_blur[];
+
+/* Haar basis scaling compensation, [0] - x,y; [1] - diag */
+extern const uint8_t ff_daala_dc_comp[][2];
+
+/* Quantization matrices, currently only flat (0) and HVS(1) */
+extern const uint8_t *const ff_daala_qmatrices[];
+extern const int ff_daala_qmatrices_num;
+
+/* Chroma from luma scaling */
+extern const uint8_t ff_daaladsp_cfl_scale[4][4];
+
+/* Maps quantizers */
+extern const int ff_daala_quant_codemap[];
+extern const int ff_daala_quant_codemap_size;
+
+extern const ent_rng ff_daalaent_cdf_tab[];
+
+extern const ent_rng ff_daalaent_cdf_exp_tab[][16];
+extern const ent_rng ff_daalaent_laplace_offset[];
+
+extern const DaalaBandLayout ff_daala_layouts[];
+
+extern const double *ff_daala_basis_qm_mag[2][DAALA_NBSIZES+1];
+
+/* PVQ beta angles for enabling activity masking */
+extern const double *const ff_daalapvq_beta[2][DAALA_MAX_PLANES][DAALA_NBSIZES + 1];
+
+#endif /* AVCODEC_DAALATAB_H */
-- 
2.6.4



More information about the ffmpeg-devel mailing list