[FFmpeg-devel] [PATCH] Chinese AVS encoder

Vitor Sessak vitor1001
Sun Jan 23 16:24:06 CET 2011


On 07/25/2007 07:50 AM, Stefan Gehrer wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Hi,
>
> Michael Niedermayer wrote:
>>> Michael, regarding your question on cvslog (sorry for crossposting,
>>> I wasn't subscribed to cvslog at the time):
>>>
>>>>> Author: stefang
>>>>> Date: Sat Jul  7 09:14:58 2007
>>>>> New Revision: 9518
>>>>>
>>>>> Log:
>>>>> move dequantization into it's own inline function
>>>> why inline? same question for the other inline functions
>>>> is there some speed gain from duplicating them in the object files
>>>> between encoder and decoder?
>>> To be honest I did not think much about object size, it just seemed
>>> to be a convenient way to share functions this way instead of having
>>> to create ff_cavs_foobar names and without creating function call
>>> overhead that was not there before.  If you think object size would be a
>>> problem I can of course move some functions back from cavs.h to cavs.c.
>>
>> yes please do unless theres a real speed loss from doing so
>>
>
> done
>
>>
>> [...]
>>> +/**
>>> + * eliminate residual blocks that only have insignificant coefficients,
>>> + * inspired from x264 and JVT-B118
>>> + */
>>> +static inline int decimate_block(uint8_t *run, DCTELEM *level, int count) {
>>> +    static const uint8_t run_score[30] = {
>>> +        0,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 };
>>> +    int i;
>>> +    int score = 0;
>>> +
>>> +    if(count>4)
>>> +        return 9;
>>> +    for(i=0;i<count;i++) {
>>> +        int abslevel = FFABS(level[i]);
>>> +        if(abslevel>  1)
>>> +            return 9;
>>> +        score += run_score[FFMIN(run[i],29)];
>>> +    }
>>> +    return score;
>>> +}
>>
>> how much psnr/bitrate is gained by this? if none then please drop it
>
> I tested on the popular foreman (300 CIF frames). When encoding at
> around 800kbps, roughly 0.1dB are gained by this. When encoding at
> around 200kbps, this increases to a gain of around 0.15dB.
> So I would like to keep it.
>
>>
>> [...]
>>
>>> +    av_reduce(&frame_rate.den,&frame_rate.num,
>>> +              s->avctx->time_base.num, s->avctx->time_base.den, 60000);
>>
>> if the exact one isnt support then the code should failm its the user
>> apps job to choose a supported one
>>
>
> removed
>
>
>>
>>> +    for(i=0;i<15;i++)
>>> +        if((ff_frame_rate_tab[i].den == frame_rate.den)&&
>>> +           (ff_frame_rate_tab[i].num == frame_rate.num))
>>> +            frame_rate_code = i;
>>> +    if(frame_rate_code<  0) {
>>> +        av_log(h->s.avctx, AV_LOG_ERROR, "unsupported framerate %d/%d\n",
>>> +               frame_rate.num, frame_rate.den);
>>> +        return -1;
>>> +    }
>>
>>
>> [...]
>>> +        put_bits(&s->pb,16,0);
>>> +        put_bits(&s->pb,16,CAVS_START_CODE);
>>
>> add a put_bits_long() to bitstrea.c, document the issue with 32bits and
>> fix vorbis_enc.c :)
>
> I looked a bit into this and I think a better way would be to fix
> put_bits() to support up to 32 bits instead of up to 31 bits.
> I am not so sure, but after a bit of checking in vorbis_enc.c it
> seems there is never any writing with more than 32 bits even
> though the local put_bits() function takes a 64bit argument.
>
> Attached a new encoder patch and a proposed fix for put_bits().


Git-friendly patches attached so patchwork will catch it up.

-Vitor

>From stefan.gehreratgmx.de  Sun Jan 23 16:19:30 2011
From: stefan.gehreratgmx.de (Stefan Gehrer)
Date: Sun, 23 Jan 2011 16:19:30 +0100
Subject: [PATCH 1/2] Make put_bits() support 32 bits instead of 31
Message-ID: <mailman.461.1295796257.1307.ffmpeg-devel at mplayerhq.hu>

---
 libavcodec/bitstream.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/libavcodec/bitstream.h b/libavcodec/bitstream.h
index fd1b4a9..04942a0 100644
--- a/libavcodec/bitstream.h
+++ b/libavcodec/bitstream.h
@@ -226,7 +226,7 @@ static inline void put_bits(PutBitContext *s, int n, unsigned int value)
         bit_buf = (bit_buf<<n) | value;
         bit_left-=n;
     } else {
-        bit_buf<<=bit_left;
+        bit_buf = (uint64_t)bit_buf << bit_left;
         bit_buf |= value >> (n - bit_left);
 #ifdef UNALIGNED_STORES_ARE_BAD
         if (3 & (intptr_t) s->buf_ptr) {
-- 
1.7.1


--------------010605070306040906030502
Content-Type: text/x-patch;
 name="0002-Chinese-AVS-encoder.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
 filename="0002-Chinese-AVS-encoder.patch"


>From stefan.gehreratgmx.de  Sun Jan 23 16:21:20 2011
From: stefan.gehreratgmx.de (Stefan Gehrer)
Date: Sun, 23 Jan 2011 16:21:20 +0100
Subject: [PATCH 2/2] Chinese AVS encoder
Message-ID: <mailman.462.1295796257.1307.ffmpeg-devel at mplayerhq.hu>

---
 Changelog              |    1 +
 doc/ffmpeg-doc.texi    |    1 +
 libavcodec/Makefile    |    1 +
 libavcodec/allcodecs.c |    2 +-
 libavcodec/allcodecs.h |    1 +
 libavcodec/cavs.c      |    4 +-
 libavcodec/cavs.h      |   27 ++-
 libavcodec/cavsdsp.c   |   99 +++++++-
 libavcodec/cavsenc.c   |  687 ++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/dsputil.h   |    3 +
 10 files changed, 821 insertions(+), 5 deletions(-)
 create mode 100644 libavcodec/cavsenc.c

diff --git a/Changelog b/Changelog
index 6ecbdb7..d8d177b 100644
--- a/Changelog
+++ b/Changelog
@@ -90,6 +90,7 @@ version <next>
 - RoQ video encoder
 - QTRLE encoder
 - OS/2 support removed
+- Chinese AVS encoder
 
 version 0.4.9-pre1:
 
diff --git a/doc/ffmpeg-doc.texi b/doc/ffmpeg-doc.texi
index fca90cc..0e99c29 100644
--- a/doc/ffmpeg-doc.texi
+++ b/doc/ffmpeg-doc.texi
@@ -1072,6 +1072,7 @@ following image formats are supported:
 @item THP                    @tab     @tab  X @tab Used on the Nintendo GameCube.
 @item Bethsoft VID           @tab     @tab  X @tab Used in some games from Bethesda Softworks.
 @item Renderware TXD         @tab     @tab  X @tab Texture dictionaries used by the Renderware Engine.
+ at item Chinese AVS            @tab  X  @tab  X @tab JiZhun Profile
 @end multitable
 
 @code{X} means that encoding (resp. decoding) is supported.
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e1685fe..47ffdae 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -45,6 +45,7 @@ OBJS-$(CONFIG_BMP_DECODER)             += bmp.o
 OBJS-$(CONFIG_BMP_ENCODER)             += bmpenc.o
 OBJS-$(CONFIG_C93_DECODER)             += c93.o
 OBJS-$(CONFIG_CAVS_DECODER)            += cavs.o cavsdec.o cavsdsp.o golomb.o
+OBJS-$(CONFIG_CAVS_ENCODER)            += cavs.o cavsenc.o cavsdsp.o golomb.o
 OBJS-$(CONFIG_CINEPAK_DECODER)         += cinepak.o
 OBJS-$(CONFIG_CLJR_DECODER)            += cljr.o
 OBJS-$(CONFIG_CLJR_ENCODER)            += cljr.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 8153e41..5a8f69b 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -63,7 +63,7 @@ void avcodec_register_all(void)
     REGISTER_DECODER(BETHSOFTVID, bethsoftvid);
     REGISTER_ENCDEC (BMP, bmp);
     REGISTER_DECODER(C93, c93);
-    REGISTER_DECODER(CAVS, cavs);
+    REGISTER_ENCDEC (CAVS, cavs);
     REGISTER_DECODER(CINEPAK, cinepak);
     REGISTER_DECODER(CLJR, cljr);
     REGISTER_DECODER(CSCD, cscd);
diff --git a/libavcodec/allcodecs.h b/libavcodec/allcodecs.h
index 3e18ca0..3d32945 100644
--- a/libavcodec/allcodecs.h
+++ b/libavcodec/allcodecs.h
@@ -27,6 +27,7 @@ extern AVCodec ac3_encoder;
 extern AVCodec asv1_encoder;
 extern AVCodec asv2_encoder;
 extern AVCodec bmp_encoder;
+extern AVCodec cavs_encoder;
 extern AVCodec dvvideo_encoder;
 extern AVCodec ffv1_encoder;
 extern AVCodec ffvhuff_encoder;
diff --git a/libavcodec/cavs.c b/libavcodec/cavs.c
index 31b7e58..323989b 100644
--- a/libavcodec/cavs.c
+++ b/libavcodec/cavs.c
@@ -1,5 +1,5 @@
 /*
- * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ * Chinese AVS video (AVS1-P2, JiZhun profile) codec
  * Copyright (c) 2006  Stefan Gehrer <stefan.gehrer at gmx.de>
  *
  * This file is part of FFmpeg.
@@ -21,7 +21,7 @@
 
 /**
  * @file cavs.c
- * Chinese AVS video (AVS1-P2, JiZhun profile) decoder
+ * Chinese AVS video (AVS1-P2, JiZhun profile) codec
  * @author Stefan Gehrer <stefan.gehrer at gmx.de>
  */
 
diff --git a/libavcodec/cavs.h b/libavcodec/cavs.h
index adc9c24..fad084a 100644
--- a/libavcodec/cavs.h
+++ b/libavcodec/cavs.h
@@ -55,6 +55,13 @@
 #define MV_BWD_OFFS                     12
 #define MV_STRIDE                        4
 
+#define CAVS_MAX_RUN                    25
+#define CAVS_MAX_LEVEL                  26
+#define INTRA_BIAS                   38<<8
+#define INTER_BIAS                   28<<8
+#define ME_THRES                     77000
+#define ME_ITER                         20
+
 enum mb_t {
   I_8X8 = 0,
   P_SKIP,
@@ -104,7 +111,8 @@ enum mv_pred_t {
   MV_PRED_TOP,
   MV_PRED_TOPRIGHT,
   MV_PRED_PSKIP,
-  MV_PRED_BSKIP
+  MV_PRED_BSKIP,
+  MV_PRED_ENC
 };
 
 enum block_t {
@@ -153,9 +161,16 @@ typedef struct dec_2dvlc_t {
 } dec_2dvlc_t;
 
 typedef struct {
+    int8_t rlcode[CAVS_MAX_RUN+1][CAVS_MAX_LEVEL+1];
+    int end_code;
+    const dec_2dvlc_t *dec;
+} enc_2dvlc_t;
+
+typedef struct {
     MpegEncContext s;
     Picture picture; ///< currently decoded frame
     Picture DPB[2];  ///< reference frames
+    Picture input_picture; ///< encoder input
     int dist[2];     ///< temporal distances from current frame to ref frames
     int profile, level;
     int aspect_ratio;
@@ -171,6 +186,7 @@ typedef struct {
     int flags;         ///< availability flags of neighbouring macroblocks
     int stc;           ///< last start code
     uint8_t *cy, *cu, *cv; ///< current MB sample pointers
+    uint8_t *ey, *eu, *ev; ///< encoded MB sample pointers
     int left_qp;
     uint8_t *top_qp;
 
@@ -222,6 +238,15 @@ typedef struct {
 
     int got_keyframe;
     DCTELEM *block;
+
+    /* encoder only */
+    DCTELEM *levels[6];
+    uint8_t *runs[6];
+    int total_coeff[6];
+    int lambda;
+    int mrefs;         ///< flag: one reference frame (0) or two (1)
+    int skip_count;
+    int poc;           ///< picture order count
 } AVSContext;
 
 extern const uint8_t     ff_cavs_dequant_shift[64];
diff --git a/libavcodec/cavsdsp.c b/libavcodec/cavsdsp.c
index fd744cc..5db9abd 100644
--- a/libavcodec/cavsdsp.c
+++ b/libavcodec/cavsdsp.c
@@ -1,5 +1,5 @@
 /*
- * Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
+ * Chinese AVS video (AVS1-P2, JiZhun profile) codec
  *
  * DSP functions
  *
@@ -177,6 +177,101 @@ static void cavs_filter_ch_c(uint8_t *d, int stride, int alpha, int beta, int tc
 
 /*****************************************************************************
  *
+ * quantization
+ *
+ ****************************************************************************/
+
+static void cavs_quant_c(DCTELEM *block, const uint16_t *norm, int mul,
+                         int bias) {
+    int i;
+
+    for(i=0;i<64;i++) {
+        if(block[i] > 0)
+            block[i] =   ((((1<<18) + block[i]*norm[i])>>19)*mul+bias)>>15;
+        else
+            block[i] = -(((((1<<18) - block[i]*norm[i])>>19)*mul+bias)>>15);
+    }
+}
+
+/*****************************************************************************
+ *
+ * forward transform
+ *
+ ****************************************************************************/
+
+static void cavs_sub_dct8_c(uint8_t *src1, uint8_t *src2, DCTELEM *block, int stride1, int stride2) {
+    int i,j;
+    DCTELEM (*dst)[8] = (DCTELEM(*)[8])block;
+
+    for(j=0;j<8;j++) {
+        for(i=0;i<8;i++)
+            dst[j][i] = src1[i] - src2[i];
+        src1 += stride1;
+        src2 += stride2;
+    }
+
+    for(i = 0; i < 8; i++) {
+        const int a0 =  dst[i][0] + dst[i][7];
+        const int a1 =  dst[i][1] + dst[i][6];
+        const int a2 =  dst[i][2] + dst[i][5];
+        const int a3 =  dst[i][3] + dst[i][4];
+        const int a4 =  dst[i][0] - dst[i][7];
+        const int a5 =  dst[i][1] - dst[i][6];
+        const int a6 =  dst[i][2] - dst[i][5];
+        const int a7 =  dst[i][3] - dst[i][4];
+
+        const int b0 = a0 + a3;
+        const int b1 = a1 + a2;
+        const int b2 = a0 - a3;
+        const int b3 = a1 - a2;
+
+        const int b4 = ((a4 - a7)<<1) + a4;
+        const int b5 = ((a6 + a5)<<1) + a5;
+        const int b6 = ((a6 - a5)<<1) + a6;
+        const int b7 = ((a4 + a7)<<1) + a7;
+
+        dst[i][0] = (b0 + b1)<<3;
+        dst[i][1] = ((b4 + b5 + b7)<<1) + b5;
+        dst[i][2] = b2*10 + b3*4;
+        dst[i][3] = ((b4 - b5 - b6)<<1) + b4;
+        dst[i][4] = (b0 - b1)<<3;
+        dst[i][5] = ((b7 - b5 + b6)<<1) + b7;
+        dst[i][6] = b2*4 - b3*10;
+        dst[i][7] = ((b4 + b6 - b7)<<1) + b6;
+    }
+    for(i = 0; i < 8; i++) {
+        const int a0 =  dst[0][i] + dst[7][i];
+        const int a1 =  dst[1][i] + dst[6][i];
+        const int a2 =  dst[2][i] + dst[5][i];
+        const int a3 =  dst[3][i] + dst[4][i];
+        const int a4 =  dst[0][i] - dst[7][i];
+        const int a5 =  dst[1][i] - dst[6][i];
+        const int a6 =  dst[2][i] - dst[5][i];
+        const int a7 =  dst[3][i] - dst[4][i];
+
+        const int b0 = a0 + a3 + 2;
+        const int b1 = a1 + a2;
+        const int b2 = a0 - a3;
+        const int b3 = a1 - a2;
+
+        const int b4 = ((a4 - a7)<<1) + a4;
+        const int b5 = ((a6 + a5)<<1) + a5;
+        const int b6 = ((a6 - a5)<<1) + a6;
+        const int b7 = ((a4 + a7)<<1) + a7;
+
+        dst[0][i] = (((b0 + b1)<<3)            + 0)>>5;
+        dst[1][i] = ((((b4 + b5 + b7)<<1) + b5)+16)>>5;
+        dst[2][i] = ((b2*10 + b3*4)            +16)>>5;
+        dst[3][i] = ((((b4 - b5 - b6)<<1) + b4)+16)>>5;
+        dst[4][i] = (((b0 - b1)<<3)            + 0)>>5;
+        dst[5][i] = ((((b7 - b5 + b6)<<1) + b7)+16)>>5;
+        dst[6][i] = ((b2*4 - b3*10)            +16)>>5;
+        dst[7][i] = ((((b4 + b6 - b7)<<1) + b6)+16)>>5;
+    }
+}
+
+/*****************************************************************************
+ *
  * inverse transform
  *
  ****************************************************************************/
@@ -543,4 +638,6 @@ void ff_cavsdsp_init(DSPContext* c, AVCodecContext *avctx) {
     c->cavs_filter_cv = cavs_filter_cv_c;
     c->cavs_filter_ch = cavs_filter_ch_c;
     c->cavs_idct8_add = cavs_idct8_add_c;
+    c->cavs_sub_dct8  = cavs_sub_dct8_c;
+    c->cavs_quant = cavs_quant_c;
 }
diff --git a/libavcodec/cavsenc.c b/libavcodec/cavsenc.c
new file mode 100644
index 0000000..d2d2743
--- /dev/null
+++ b/libavcodec/cavsenc.c
@@ -0,0 +1,687 @@
+/*
+ * Chinese AVS video (AVS1-P2, JiZhun profile) encoder
+ * Copyright (c) 2006  Stefan Gehrer <stefan.gehrer at gmx.de>
+ *
+ * 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
+ */
+
+/**
+ * @file cavsenc.c
+ * Chinese AVS video (AVS1-P2, JiZhun profile) encoder
+ * @author Stefan Gehrer <stefan.gehrer at gmx.de>
+ */
+
+#include "avcodec.h"
+#include "golomb.h"
+#include "cavs.h"
+
+static const uint8_t cbp_enc_tab[64][2] = {
+    { 4, 0},{16,19},{17,16},{19,15},{14,18},{ 9,11},{22,31},{ 8,13},
+    {11,17},{21,30},{10,12},{ 7, 9},{12,10},{ 6, 7},{ 5, 8},{ 1, 1},
+    {35, 4},{47,42},{48,38},{38,27},{46,39},{36,33},{50,59},{26,26},
+    {45,40},{52,58},{41,35},{28,25},{37,29},{23,24},{31,28},{ 2, 3},
+    {43, 5},{51,51},{56,52},{39,37},{55,50},{33,43},{62,63},{27,44},
+    {54,53},{60,62},{40,48},{32,47},{42,34},{24,45},{29,49},{ 3, 6},
+    {49,14},{53,55},{57,56},{25,36},{58,54},{30,41},{59,60},{15,21},
+    {61,57},{63,61},{44,46},{18,22},{34,32},{13,20},{20,23},{ 0, 2}
+};
+
+/*
+ * taken from AVS paper by Lu Yu/Feng Yi/Jie Dong/Cixun Zhang
+ * this is used to post-normalise the rounding errors of the
+ * forward transform in the encoder as well as pre-normalise the
+ * rounding errors of the inverse transform in the decoder,
+ * both due to using non-orthogonal integer matrices
+ */
+static const uint16_t quant_norm[64] = {
+    32768, 37958, 36158, 37958, 32768, 37958, 36158, 37958,
+    37958, 43969, 41884, 43969, 37958, 43969, 41884, 43969,
+    36158, 41884, 39898, 41884, 36158, 41884, 39898, 41884,
+    37958, 43969, 41884, 43969, 37958, 43969, 41884, 43969,
+    32768, 37958, 36158, 37958, 32768, 37958, 36158, 37958,
+    37958, 43969, 41884, 43969, 37958, 43969, 41884, 43969,
+    36158, 41884, 39898, 41884, 36158, 41884, 39898, 41884,
+    37958, 43969, 41884, 43969, 37958, 43969, 41884, 43969,
+};
+
+static const uint16_t quant_mul[64] = {
+    32768,29775,27554,25268,23170,21247,19369,17770,
+    16302,15024,13777,12634,11626,10624, 9742, 8958,
+     8192, 7512, 6889, 6305, 5793, 5303, 4878, 4467,
+     4091, 3756, 3444, 3161, 2894, 2654, 2435, 2235,
+     2048, 1878, 1722, 1579, 1449, 1329, 1218, 1117,
+     1024,  939,  861,  790,  724,  664,  609,  558,
+      512,  470,  430,  395,  362,  332,  304,  279,
+      256,  235,  215,  197,  181,  166,  152,  140
+};
+
+static enc_2dvlc_t intra_enc[7];
+static enc_2dvlc_t inter_enc[7];
+static enc_2dvlc_t chroma_enc[5];
+
+/*****************************************************************************
+ *
+ * residual data encoding
+ *
+ ****************************************************************************/
+
+/** kth-order exponential golomb code */
+static inline void put_ue_code(PutBitContext *pb, int order, int value) {
+    set_ue_golomb(pb, value>>order);
+    put_bits(pb, order, value & ((1<<order)-1));
+}
+
+/**
+ * entropy coding of one residual 8x8 block
+ * @param enc pointer to 2D VLC encoding table
+ * @param esc_golomb_order escape codes are k-golomb with this order k
+ * @param qp quantizer
+ * @param block block number [0..5]
+ */
+static void encode_residual_block(AVSContext *h, PutBitContext *pb,
+                                  const enc_2dvlc_t *enc, int esc_golomb_order,
+                                  int qp, int block) {
+    int run = 0;
+    int coeff_num, level_code;
+    DCTELEM *level_buf = h->levels[block];
+    uint8_t *run_buf = h->runs[block];
+    const dec_2dvlc_t *dec = enc->dec;
+
+    for(coeff_num=0;coeff_num<h->total_coeff[block];coeff_num++) {
+        int level = abs(level_buf[coeff_num])-1;
+        int sign = (level_buf[coeff_num]>>31)&1;
+        run = run_buf[coeff_num] - 1;
+        if((level > CAVS_MAX_LEVEL)||(run > CAVS_MAX_RUN)
+           ||((level_code = enc->rlcode[run][level])<0)) {
+            put_ue_code(pb,dec->golomb_order,run*2+ESCAPE_CODE+1-sign);
+            if(run >= dec->max_run)
+                put_ue_code(pb,esc_golomb_order, level);
+            else
+                put_ue_code(pb,esc_golomb_order, level + 1 -
+                            dec->level_add[run+1]);
+            while(level >= dec->inc_limit) {
+                dec++;
+                enc++;
+            }
+        } else {
+            put_ue_code(pb,dec->golomb_order,level_code+sign);
+            enc += dec->rltab[level_code][2];
+            dec += dec->rltab[level_code][2];
+        }
+    }
+    put_ue_code(pb,dec->golomb_order,enc->end_code);
+}
+
+/**
+ * entropy coding of one macroblock
+ * @param intra flag inter=0 intra=1
+ */
+static void encode_residual(AVSContext *h, int intra) {
+    PutBitContext *pb = &h->s.pb;
+    int block;
+
+    for(block=0;block<4;block++)
+        if(h->cbp & (1<<block)) {
+            if(intra)
+                encode_residual_block(h,pb,intra_enc,1,h->qp,block);
+            else
+                encode_residual_block(h,pb,inter_enc,0,h->qp,block);
+        }
+    if(h->cbp & (1<<4))
+        encode_residual_block(h,pb,chroma_enc,0,ff_cavs_chroma_qp[h->qp], 4);
+    if(h->cbp & (1<<5))
+        encode_residual_block(h,pb,chroma_enc,0,ff_cavs_chroma_qp[h->qp], 5);
+}
+
+/**
+ * eliminate residual blocks that only have insignificant coefficients,
+ * inspired from x264 and JVT-B118
+ */
+static inline int decimate_block(uint8_t *run, DCTELEM *level, int count) {
+    static const uint8_t run_score[30] = {
+        0,3,3,3,3,2,2,2,2,2,2,2,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0 };
+    int i;
+    int score = 0;
+
+    if(count>4)
+        return 9;
+    for(i=0;i<count;i++) {
+        int abslevel = FFABS(level[i]);
+        if(abslevel > 1)
+            return 9;
+        score += run_score[FFMIN(run[i],29)];
+    }
+    return score;
+}
+
+/*****************************************************************************
+ *
+ * reconstruction as the decoder sees it
+ *
+ ****************************************************************************/
+
+static int recon_block(AVSContext *h, uint8_t *src1, uint8_t *src2, int stride,
+                       int block, int qp, int intra) {
+    int i,pos;
+    int score = 9;
+    int run = 0;
+    const uint8_t *scantab = ff_zigzag_direct;
+
+    h->s.dsp.cavs_sub_dct8(src1, src2, h->block, stride, stride);
+    h->s.dsp.cavs_quant(h->block, quant_norm, quant_mul[qp],
+                        intra ? INTRA_BIAS : INTER_BIAS);
+    /* forward scan */
+    for(pos=63,i=0;pos>=0;pos--) {
+        if(h->block[scantab[pos]]) {
+            if(i)
+                h->runs[block][i-1] = run+1;
+            h->levels[block][i++] = h->block[scantab[pos]];
+            run = 0;
+        } else
+            run++;
+    }
+    /* eliminate empty or insignificant blocks */
+    if(!i)
+        return 0;
+    h->runs[block][i-1] = run+1;
+    if(!intra) {
+        score = decimate_block(h->runs[block],h->levels[block],i);
+        h->total_coeff[block] = 0;
+        if(score < 4)
+            return score;
+    }
+    h->cbp |= (1 << block);
+    h->total_coeff[block] = i;
+    /* dequantise and restore blocks */
+    dequant(h , h->levels[block], h->runs[block], h->block,
+            ff_cavs_dequant_mul[qp], ff_cavs_dequant_shift[qp], i);
+    h->s.dsp.cavs_idct8_add(src2, h->block, stride);
+    return score;
+}
+
+static inline void recon_mb(AVSContext *h, int *lscore, int *cscore) {
+    int block;
+
+    for(block=0;block<4;block++)
+        *lscore += recon_block(h, h->ey + h->luma_scan[block],
+                               h->cy + h->luma_scan[block],
+                               h->l_stride, block, h->qp, 0);
+    *cscore += recon_block(h, h->eu, h->cu, h->c_stride, 4,
+                           ff_cavs_chroma_qp[h->qp], 0);
+    *cscore += recon_block(h, h->ev, h->cv, h->c_stride, 5,
+                           ff_cavs_chroma_qp[h->qp], 0);
+}
+
+/*****************************************************************************
+ *
+ * intra encoding
+ *
+ ****************************************************************************/
+
+static inline int modify(int flags, int block, int mode) {
+    if(!(flags & A_AVAIL) && !(block & 1))
+        mode = ff_left_modifier_l[mode];
+    if(!(flags & B_AVAIL) && !(block & 2) && (mode >= 0))
+        mode = ff_top_modifier_l[mode];
+    return mode;
+}
+
+static void encode_mb_i(AVSContext *h) {
+    PutBitContext *pb = &h->s.pb;
+    int block, i, pred_mode_uv, min_cost, mode, best_mode, diff;
+    int coded_mode[5];
+    uint8_t top[18];
+    uint8_t *left = NULL;
+    uint8_t *d;
+    uint8_t *s;
+
+    assert(h->mbx || (!(h->flags & A_AVAIL)));
+    h->lambda = h->qp/3;
+    h->cbp = pred_mode_uv = best_mode = 0;
+    for(block=0;block<4;block++) {
+        int pos = ff_cavs_scan3x3[block];
+        int predpred = FFMIN(h->pred_mode_Y[pos-1], h->pred_mode_Y[pos-3]);
+
+        min_cost = INT_MAX;
+        s = h->ey + h->luma_scan[block];
+        d = h->cy + h->luma_scan[block];
+        ff_cavs_load_intra_pred_luma(h, top, &left, block);
+        if(predpred == NOT_AVAIL) // if either is not available
+            predpred = INTRA_L_LP;
+
+        /* try all luma intra prediction modes */
+        for(i=0;i<5;i++) {
+            const int bitcost[5] = {3,3,3,3,1};
+
+            mode = (i == 4) ? predpred : i + (i >= predpred);
+            mode = modify(h->flags, block, mode);
+            if(mode >= 0) {
+                h->intra_pred_l[mode](d, top, left, h->l_stride);
+                diff = h->s.dsp.sse[1](NULL, s, d, h->l_stride, 8);
+                if((bitcost[i]*h->lambda + diff) < min_cost) {
+                    min_cost = bitcost[i]*h->lambda + diff;
+                    coded_mode[block] = i;
+                    best_mode = mode;
+                    h->pred_mode_Y[pos] = (i == 4) ? predpred : i + (i >= predpred);
+                }
+            }
+        }
+        /* reconstruct block for next one */
+        h->intra_pred_l[best_mode](d, top, left, h->l_stride);
+        recon_block(h, s, d, h->l_stride, block, h->qp, 1);
+    }
+
+    /* try all chroma intra prediction modes */
+    ff_cavs_load_intra_pred_chroma(h);
+    min_cost = INT_MAX;
+    for(i=0;i<4;i++) {
+        const int bitcost[4] = {1,3,3,5};
+
+        mode = i;
+        if(!(h->flags & A_AVAIL))
+            mode = ff_left_modifier_c[mode];
+        if(!(h->flags & B_AVAIL) && (mode >=0))
+            mode = ff_top_modifier_c[mode];
+        if(mode >= 0) {
+            h->intra_pred_c[mode](h->cu, &h->top_border_u[h->mbx*10],
+                                  h->left_border_u, h->c_stride);
+            diff = h->s.dsp.sse[1](NULL, h->eu, h->cu, h->c_stride, 8);
+            h->intra_pred_c[mode](h->cv, &h->top_border_v[h->mbx*10],
+                                  h->left_border_v, h->c_stride);
+            diff += h->s.dsp.sse[1](NULL, h->ev, h->cv, h->c_stride, 8);
+            if((bitcost[i]*h->lambda + diff) < min_cost) {
+                min_cost = bitcost[i]*h->lambda + diff;
+                pred_mode_uv = mode;
+                coded_mode[4] = i;
+            }
+        }
+    }
+
+    /* reconstruct blocks */
+    h->intra_pred_c[pred_mode_uv](h->cu, &h->top_border_u[h->mbx*10],
+                                  h->left_border_u, h->c_stride);
+    recon_block(h, h->eu, h->cu, h->c_stride, 4, ff_cavs_chroma_qp[h->qp], 1);
+    h->intra_pred_c[pred_mode_uv](h->cv, &h->top_border_v[h->mbx*10],
+                                  h->left_border_v, h->c_stride);
+    recon_block(h, h->ev, h->cv, h->c_stride, 5, ff_cavs_chroma_qp[h->qp], 1);
+
+    ff_cavs_modify_mb_i(h,&pred_mode_uv);
+
+    if(h->pic_type != FF_I_TYPE)
+        set_ue_golomb(pb, cbp_enc_tab[h->cbp][0] + 4);
+    for(block=0;block<4;block++)
+        if(coded_mode[block] == 4)
+            put_bits(pb,1,1);
+        else
+            put_bits(pb,3,coded_mode[block]);
+    set_ue_golomb(pb,coded_mode[4]);
+    if(h->pic_type == FF_I_TYPE)
+        set_ue_golomb(pb, cbp_enc_tab[h->cbp][0]);
+    encode_residual(h, 1);
+    ff_cavs_filter(h,I_8X8);
+    set_mv_intra(h);
+}
+
+/*****************************************************************************
+ *
+ * inter P encoding
+ *
+ ****************************************************************************/
+
+static inline int mv_cost(vector_t *mv, vector_t *pmv) {
+  int x = FFABS(mv->x - pmv->x);
+  int y = FFABS(mv->y - pmv->y);
+  return  2*(av_log2(x*2)+av_log2(y*2))+2;
+}
+
+static inline int check_mv(AVSContext *h, int x, int y, vector_t *pmv,
+                           vector_t *mvmin, int *min_cost) {
+  int diff;
+
+  h->mv[MV_FWD_X0].x = x;
+  h->mv[MV_FWD_X0].y = y;
+  ff_cavs_inter(h, P_16X16);
+  diff = h->s.dsp.sse[0](NULL, h->ey, h->cy, h->l_stride, 16);
+  if((mv_cost(&h->mv[MV_FWD_X0],pmv)*h->lambda + diff) < *min_cost) {
+      *mvmin = h->mv[MV_FWD_X0];
+      *min_cost = mv_cost(&h->mv[MV_FWD_X0],pmv)*h->lambda + diff;
+      return 1;
+  }
+  return 0;
+}
+
+static void encode_mb_p(AVSContext *h) {
+    PutBitContext *pb = &h->s.pb;
+    int lscore = 0;
+    int cscore = 0;
+
+    h->lambda = h->qp/8;
+
+    /* test if we can skip */
+    ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0);
+    ff_cavs_inter(h, P_SKIP);
+    recon_mb(h, &lscore, &cscore);
+    if(lscore < 6 && cscore < 7) {
+        h->skip_count++;
+        if(h->cbp) //there can be an undecimated block
+            ff_cavs_inter(h, P_SKIP);
+        set_intra_mode_default(h);
+        ff_cavs_filter(h,P_SKIP);
+    } else {
+        int hex[6][2] = {{-4,-8},{4,-8},{8,0},{4,8},{-4,8},{-8,0}};
+        vector_t pmv[2], mv[2], mvmin;
+        int i, sub, x, y, min_cost[2], ref, count;
+        int newmv = 1;
+
+        set_ue_golomb(pb,h->skip_count);
+        h->skip_count = h->cbp = 0;
+
+        for(ref=0;ref<=h->mrefs;ref++) {
+            /* get predicted mv */
+            h->mv[MV_FWD_X0].ref=mv[ref].ref=pmv[ref].ref=mvmin.ref = ref;
+            ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_ENC, BLK_16X16, ref);
+            pmv[ref] = h->mv[MV_FWD_X0];
+
+            /* predicted full-pel mv as reference */
+            h->mv[MV_FWD_X0].x = mv[ref].x = mvmin.x = (pmv[ref].x+2) & ~3;
+            h->mv[MV_FWD_X0].y = mv[ref].y = mvmin.y = (pmv[ref].y+2) & ~3;
+            ff_cavs_inter(h, P_16X16);
+            min_cost[ref] = h->s.dsp.sse[0](NULL,h->ey,h->cy,h->l_stride,16) +
+                mv_cost(&mv[ref],&pmv[ref])*h->lambda;
+
+            /* iterative hex search */
+            count = ME_ITER;
+            while(newmv && count--) {
+                newmv = 0;
+                for(i=0;i<6;i++)
+                    if(check_mv(h, mv[ref].x+hex[i][0], mv[ref].y+hex[i][1],
+                                &pmv[ref], &mvmin, &min_cost[ref]))
+                        newmv = 1;
+                mv[ref] = mvmin;
+            }
+
+            /* refinement (full,half,quarter) */
+            for(sub=4;sub>0;sub>>=1) {
+                for(x=-sub;x<=sub;x+=sub)
+                    for(y=-sub;y<=sub;y+=sub)
+                        if(x|y)
+                            check_mv(h, mv[ref].x+x, mv[ref].y+y,
+                                     &pmv[ref], &mvmin, &min_cost[ref]);
+                mv[ref] = mvmin;
+            }
+        }
+        ref = (h->mrefs && (min_cost[1] < min_cost[0]));
+        if(min_cost[ref] < ME_THRES) {
+            h->mv[MV_FWD_X0] = mv[ref];
+            set_mvs(&h->mv[MV_FWD_X0],BLK_16X16);
+            ff_cavs_inter(h, P_16X16);
+            recon_mb(h,&lscore,&cscore);
+            set_intra_mode_default(h);
+            set_ue_golomb(pb,0); //mb_type is P_16X16
+            if(h->mrefs)
+                put_bits(pb,1,ref);
+            set_se_golomb(pb,mv[ref].x - pmv[ref].x); //mvd
+            set_se_golomb(pb,mv[ref].y - pmv[ref].y);
+            set_ue_golomb(pb, cbp_enc_tab[h->cbp][1]);
+            encode_residual(h, 0);
+            ff_cavs_filter(h,P_16X16);
+        } else {
+            encode_mb_i(h);
+        }
+    }
+}
+
+/*****************************************************************************
+ *
+ * header encoding
+ *
+ ****************************************************************************/
+
+static int encode_pic(AVSContext *h, Picture *p) {
+    MpegEncContext *s = &h->s;
+    int deblock = 1;
+
+    if (!s->context_initialized) {
+        s->avctx->idct_algo = FF_IDCT_CAVS;
+        if (MPV_common_init(s) < 0)
+            return -1;
+        ff_init_scantable(s->dsp.idct_permutation,&h->scantable,ff_zigzag_direct);
+    }
+    put_bits(&s->pb,16,0xdeaf); //TODO correct bbv_dwlay
+    if(h->pic_type == FF_I_TYPE)
+        put_bits(&s->pb,1,0); //time_code not present
+    else
+        put_bits(&s->pb,2,1); //picture type P
+    s->avctx->get_buffer(s->avctx, (AVFrame *)&h->picture);
+    ff_cavs_init_pic(h);
+    put_bits(&s->pb,8,h->poc);
+    h->picture.poc = h->poc*2;
+    h->dist[0] = (h->picture.poc - h->DPB[0].poc  + 512) % 512;
+    h->dist[1] = (h->picture.poc - h->DPB[1].poc  + 512) % 512;
+    h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0;
+    h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0;
+    h->poc = (h->poc + 1) & 0x7F;
+
+    if(s->low_delay)
+        set_ue_golomb(&s->pb,0); //TODO correct bbv_check_times?
+    put_bits(&s->pb,1,1); //set progressive
+
+    put_bits(&s->pb,1,1); //top_field_first
+    put_bits(&s->pb,1,0); //repeat_first_field
+    put_bits(&s->pb,1,1); //set qp_fixed
+    put_bits(&s->pb,6,h->qp);
+    if(h->pic_type == FF_I_TYPE) {
+        put_bits(&s->pb,4,0); //reserved bits
+    } else {
+        h->mrefs = !!h->DPB[1].data[0] && (s->avctx->refs > 1);
+        if(!(h->pic_type == FF_B_TYPE))
+            put_bits(&s->pb,1,!h->mrefs); //multiple references
+        put_bits(&s->pb,4,0);  //reserved bits
+        put_bits(&s->pb,1,1); //skip_mode_flag
+    }
+    put_bits(&s->pb,1,!deblock);
+    if(deblock) {
+        if(h->s.avctx->deblockalpha || h->s.avctx->deblockbeta) {
+            put_bits(&s->pb,1,1); //deblocking params coded
+            set_se_golomb(&s->pb, h->s.avctx->deblockalpha);
+            set_se_golomb(&s->pb, h->s.avctx->deblockbeta);
+        } else {
+            put_bits(&s->pb,1,0); //deblocking params not coded
+        }
+    }
+    h->skip_count = 0;
+    do {
+        h->ey = p->data[0] + h->mby*16*h->l_stride + h->mbx*16;
+        h->eu = p->data[1] + h->mby*8*h->c_stride + h->mbx*8;
+        h->ev = p->data[2] + h->mby*8*h->c_stride + h->mbx*8;
+        ff_cavs_init_mb(h);
+        if(h->pic_type == FF_I_TYPE)
+            encode_mb_i(h);
+        else
+            encode_mb_p(h);
+    } while(ff_cavs_next_mb(h));
+    if(h->DPB[1].data[0])
+        s->avctx->release_buffer(s->avctx, (AVFrame *)&h->DPB[1]);
+    memcpy(&h->DPB[1], &h->DPB[0], sizeof(Picture));
+    memcpy(&h->DPB[0], &h->picture, sizeof(Picture));
+    return 0;
+}
+
+static int encode_seq_header(AVSContext *h) {
+    MpegEncContext *s = &h->s;
+    int frame_rate_code = -1;
+    int i;
+
+    s->width = h->s.avctx->width;
+    s->height = h->s.avctx->height;
+    put_bits(&s->pb,8,h->profile);
+    put_bits(&s->pb,8,h->level);
+    put_bits(&s->pb,1,1); //progressive sequence only
+    put_bits(&s->pb,14,s->width);
+    put_bits(&s->pb,14,s->height);
+    put_bits(&s->pb,2,1); // 1 = YUV 4:2:0, 2 = YUV 4:2:2
+    put_bits(&s->pb,3,1); //sample_precision 8bits
+    put_bits(&s->pb,4,h->aspect_ratio);
+    for(i=0;i<15;i++)
+        if((ff_frame_rate_tab[i].den == s->avctx->time_base.num) &&
+           (ff_frame_rate_tab[i].num == s->avctx->time_base.den))
+            frame_rate_code = i;
+    if(frame_rate_code < 0) {
+        av_log(h->s.avctx, AV_LOG_ERROR, "unsupported framerate %d/%d\n",
+               s->avctx->time_base.den, s->avctx->time_base.num);
+        return -1;
+    }
+    put_bits(&s->pb,4,frame_rate_code & 0xF);
+    put_bits(&s->pb,18,0); //bit_rate_lower
+    put_bits(&s->pb,1,1); //marker_bit
+    put_bits(&s->pb,12,1); //bit_rate_upper
+    put_bits(&s->pb,1,s->low_delay);
+    put_bits(&s->pb,1,1); //marker_bit
+    put_bits(&s->pb,18,225); //bbv_buffer_size, enough for level 6.2
+    put_bits(&s->pb,3,0); //reserved_bits
+
+    h->mb_width  = (s->width  + 15) >> 4;
+    h->mb_height = (s->height + 15) >> 4;
+    if(!h->top_qp) {
+        ff_cavs_init_top_lines(h);
+        h->levels[0] = av_mallocz(6*64*sizeof(DCTELEM));
+        h->runs[0]   = av_mallocz(6*64);
+        for(i=1;i<6;i++) {
+            h->levels[i] = h->levels[i-1] + 64;
+            h->runs[i]   = h->runs[i-1]   + 64;
+        }
+    }
+    return 0;
+}
+
+static int cavs_encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){
+    AVSContext *h = avctx->priv_data;
+    MpegEncContext * const s = &h->s;
+    AVFrame *pict = data;
+    const int width= s->avctx->width;
+    const int height= s->avctx->height;
+    int size, i, y;
+
+    for(i=0; i<3; i++){
+        int shift= !!i;
+        for(y=0; y<(height>>shift); y++)
+            memcpy(&h->input_picture.data[i][y * h->input_picture.linesize[i]],
+                   &pict->data[i][y * pict->linesize[i]],
+                   width>>shift);
+    }
+    if(avctx->gop_size == 0 || h->poc % avctx->gop_size == 0) {
+        h->input_picture.pict_type= I_TYPE;
+        h->pic_type= FF_I_TYPE;
+        h->input_picture.key_frame= 1;
+    } else {
+        h->input_picture.pict_type= P_TYPE;
+        h->pic_type= FF_P_TYPE;
+    }
+
+    init_put_bits(&s->pb, buf, buf_size);
+    if(h->pic_type == FF_I_TYPE) {
+        if(h->DPB[0].data[0])
+            avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]);
+        if(h->DPB[1].data[0])
+            avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]);
+        put_bits(&s->pb,16,0);
+        put_bits(&s->pb,16,CAVS_START_CODE);
+        if(encode_seq_header(h) < 0)
+            return -1;
+        align_put_bits(&s->pb);
+        put_bits(&s->pb,16,0);
+        put_bits(&s->pb,16,PIC_I_START_CODE);
+    } else {
+        put_bits(&s->pb,16,0);
+        put_bits(&s->pb,16,PIC_PB_START_CODE);
+    }
+    encode_pic(h, &h->input_picture);
+    align_put_bits(&s->pb);
+    flush_put_bits(&s->pb);
+    size = put_bits_count(&s->pb)/8;
+    if(avctx->flags&CODEC_FLAG_PSNR) {
+        int i,x,y;
+        for(i=0;i<3;i++) {
+            int wi = s->width >> (!!i);
+            int he = s->height >> (!!i);
+            int64_t error = 0;
+            for(y=0;y<he;y++)
+                for(x=0;x<wi;x++) {
+                    int d = h->picture.data[i][y*h->picture.linesize[i] + x]
+                               - pict->data[i][y*     pict->linesize[i] + x];
+                    error += d*d;
+                }
+            s->avctx->error[i] += error;
+            h->picture.error[i] = error;
+        }
+    }
+    memset(&h->picture,0,sizeof(Picture));
+    return size;
+}
+
+static void init_enc_vlc(enc_2dvlc_t *enc, const dec_2dvlc_t *dec, int count) {
+    int i,j;
+
+    for(j=0;j<count;j++) {
+        memset(enc, -1, sizeof(enc_2dvlc_t));
+        for(i=0;i<ESCAPE_CODE;i++) {
+            if(dec->rltab[i][0]) {
+                enc->rlcode[dec->rltab[i][1]-1][dec->rltab[i][0]-1] = i;
+                i++; //skip negative level
+            } else
+                enc->end_code = i;
+        }
+        enc->dec = dec;
+        enc++;
+        dec++;
+    }
+}
+
+static int cavs_encode_init(AVCodecContext * avctx) {
+    AVSContext *h = avctx->priv_data;
+    MpegEncContext * const s = &h->s;
+
+    if(avctx->strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL){
+        av_log(avctx, AV_LOG_ERROR, "Chinese AVS encoder has not been tested for standard compliance.\n"
+               "use vstrict=-2 / -strict -2 to use it anyway\n");
+        return -1;
+    }
+    if(avctx->cqp > -1)
+        h->qp = avctx->cqp;
+    else {
+        av_log(avctx, AV_LOG_ERROR, "fixed qp encoding only, use -cqp\n");
+        return -1;
+    }
+    ff_cavs_init(avctx);
+    init_enc_vlc(intra_enc,  ff_cavs_intra_dec,  7);
+    init_enc_vlc(inter_enc,  ff_cavs_inter_dec,  7);
+    init_enc_vlc(chroma_enc, ff_cavs_chroma_dec, 5);
+    s->avctx = avctx;
+    s->avctx->get_buffer(s->avctx, (AVFrame *)&h->input_picture);
+    h->poc = 0;
+    return 0;
+}
+
+AVCodec cavs_encoder = {
+    "cavs",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_CAVS,
+    sizeof(AVSContext),
+    cavs_encode_init,
+    cavs_encode_frame,
+    ff_cavs_end,
+};
diff --git a/libavcodec/dsputil.h b/libavcodec/dsputil.h
index 2d312e5..d5ede49 100644
--- a/libavcodec/dsputil.h
+++ b/libavcodec/dsputil.h
@@ -297,6 +297,9 @@ typedef struct DSPContext {
     void (*cavs_filter_cv)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2);
     void (*cavs_filter_ch)(uint8_t *pix, int stride, int alpha, int beta, int tc, int bs1, int bs2);
     void (*cavs_idct8_add)(uint8_t *dst, DCTELEM *block, int stride);
+    void (*cavs_sub_dct8)(uint8_t *src1, uint8_t *src2, DCTELEM *block,
+                          int stride1, int stride2);
+    void (*cavs_quant)(DCTELEM *block, const uint16_t *norm,int mul, int bias);
 
     me_cmp_func pix_abs[2][4];
 
-- 
1.7.1


--------------010605070306040906030502--



More information about the ffmpeg-devel mailing list