indeo4: B-frames decoding
authorDirk Ausserhaus <dausserhaus@gmail.com>
Sun, 8 Jun 2014 11:44:17 +0000 (13:44 +0200)
committerKostya Shishkov <kostya.shishkov@gmail.com>
Thu, 26 Jun 2014 17:17:33 +0000 (19:17 +0200)
Signed-off-by: Kostya Shishkov <kostya.shishkov@gmail.com>
libavcodec/indeo4.c
libavcodec/indeo5.c
libavcodec/ivi_common.c
libavcodec/ivi_common.h
libavcodec/ivi_dsp.c
libavcodec/ivi_dsp.h

index 6893077..35f266e 100644 (file)
@@ -194,7 +194,7 @@ static int decode_pic_hdr(IVI45DecContext *ctx, AVCodecContext *avctx)
 
     /* check if picture layout was changed and reallocate buffers */
     if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf)) {
-        if (ff_ivi_init_planes(ctx->planes, &pic_conf)) {
+        if (ff_ivi_init_planes(ctx->planes, &pic_conf, 1)) {
             av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n");
             ctx->pic_conf.luma_bands = 0;
             return AVERROR(ENOMEM);
@@ -462,6 +462,8 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
             mb->xpos     = x;
             mb->ypos     = y;
             mb->buf_offs = mb_offset;
+            mb->b_mv_x   =
+            mb->b_mv_y   = 0;
 
             if (get_bits1(&ctx->gb)) {
                 if (ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
@@ -537,6 +539,24 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
                         mv_x += IVI_TOSIGNED(mv_delta);
                         mb->mv_x = mv_x;
                         mb->mv_y = mv_y;
+                        if (mb->type == 3) {
+                            mv_delta = get_vlc2(&ctx->gb,
+                                                ctx->mb_vlc.tab->table,
+                                                IVI_VLC_BITS, 1);
+                            mv_y += IVI_TOSIGNED(mv_delta);
+                            mv_delta = get_vlc2(&ctx->gb,
+                                                ctx->mb_vlc.tab->table,
+                                                IVI_VLC_BITS, 1);
+                            mv_x += IVI_TOSIGNED(mv_delta);
+                            mb->b_mv_x = -mv_x;
+                            mb->b_mv_y = -mv_y;
+                        }
+                    }
+                    if (mb->type == 2) {
+                        mb->b_mv_x = -mb->mv_x;
+                        mb->b_mv_y = -mb->mv_y;
+                        mb->mv_x = 0;
+                        mb->mv_y = 0;
                     }
                 }
             }
@@ -563,32 +583,30 @@ static int decode_mb_info(IVI45DecContext *ctx, IVIBandDesc *band,
  */
 static void switch_buffers(IVI45DecContext *ctx)
 {
+    int is_prev_ref = 0, is_ref = 0;
+
     switch (ctx->prev_frame_type) {
     case IVI4_FRAMETYPE_INTRA:
     case IVI4_FRAMETYPE_INTRA1:
     case IVI4_FRAMETYPE_INTER:
-        ctx->buf_switch ^= 1;
-        ctx->dst_buf     = ctx->buf_switch;
-        ctx->ref_buf     = ctx->buf_switch ^ 1;
-        break;
-    case IVI4_FRAMETYPE_INTER_NOREF:
+        is_prev_ref = 1;
         break;
     }
 
     switch (ctx->frame_type) {
     case IVI4_FRAMETYPE_INTRA:
     case IVI4_FRAMETYPE_INTRA1:
-        ctx->buf_switch = 0;
-        /* FALLTHROUGH */
     case IVI4_FRAMETYPE_INTER:
-        ctx->dst_buf = ctx->buf_switch;
-        ctx->ref_buf = ctx->buf_switch ^ 1;
-        break;
-    case IVI4_FRAMETYPE_INTER_NOREF:
-    case IVI4_FRAMETYPE_NULL_FIRST:
-    case IVI4_FRAMETYPE_NULL_LAST:
+        is_ref = 1;
         break;
     }
+
+    if (is_prev_ref && is_ref) {
+        FFSWAP(int, ctx->dst_buf, ctx->ref_buf);
+    } else if (is_prev_ref) {
+        FFSWAP(int, ctx->ref_buf, ctx->b_ref_buf);
+        FFSWAP(int, ctx->dst_buf, ctx->ref_buf);
+    }
 }
 
 
@@ -622,6 +640,9 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     ctx->is_indeo4 = 1;
 
+    ctx->dst_buf   = 0;
+    ctx->ref_buf   = 1;
+    ctx->b_ref_buf = 3; /* buffer 2 is used for scalability mode */
     ctx->p_frame = av_frame_alloc();
     if (!ctx->p_frame)
         return AVERROR(ENOMEM);
index 2465ce6..5a112f9 100644 (file)
@@ -113,7 +113,7 @@ static int decode_gop_header(IVI45DecContext *ctx, AVCodecContext *avctx)
 
     /* check if picture layout was changed and reallocate buffers */
     if (ivi_pic_config_cmp(&pic_conf, &ctx->pic_conf) || ctx->gop_invalid) {
-        result = ff_ivi_init_planes(ctx->planes, &pic_conf);
+        result = ff_ivi_init_planes(ctx->planes, &pic_conf, 0);
         if (result < 0) {
             av_log(avctx, AV_LOG_ERROR, "Couldn't reallocate color planes!\n");
             return result;
@@ -625,7 +625,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
     ctx->pic_conf.tile_height   = avctx->height;
     ctx->pic_conf.luma_bands    = ctx->pic_conf.chroma_bands = 1;
 
-    result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf);
+    result = ff_ivi_init_planes(ctx->planes, &ctx->pic_conf, 0);
     if (result) {
         av_log(avctx, AV_LOG_ERROR, "Couldn't allocate color planes!\n");
         return AVERROR_INVALIDDATA;
index 93936c2..7c4d53e 100644 (file)
@@ -73,23 +73,46 @@ static VLC ivi_blk_vlc_tabs[8]; ///< static block Huffman tables
 
 typedef void (*ivi_mc_func) (int16_t *buf, const int16_t *ref_buf,
                              uint32_t pitch, int mc_type);
+typedef void (*ivi_mc_avg_func) (int16_t *buf, const int16_t *ref_buf1,
+                                 const int16_t *ref_buf2,
+                                 uint32_t pitch, int mc_type, int mc_type2);
 
-static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc,
-                  int offs, int mv_x, int mv_y, int mc_type)
+static int ivi_mc(IVIBandDesc *band, ivi_mc_func mc, ivi_mc_avg_func mc_avg,
+                  int offs, int mv_x, int mv_y, int mv_x2, int mv_y2,
+                  int mc_type, int mc_type2)
 {
     int ref_offs = offs + mv_y * band->pitch + mv_x;
     int buf_size = band->pitch * band->aheight;
     int min_size = band->pitch * (band->blk_size - 1) + band->blk_size;
     int ref_size = (mc_type > 1) * band->pitch + (mc_type & 1);
 
-    if (offs < 0 || ref_offs < 0 || !band->ref_buf)
-        return AVERROR_INVALIDDATA;
-    if (buf_size - min_size < offs)
-        return AVERROR_INVALIDDATA;
-    if (buf_size - min_size - ref_size < ref_offs)
-        return AVERROR_INVALIDDATA;
+    if (mc_type != -1) {
+        if (offs < 0 || ref_offs < 0 || !band->ref_buf)
+            return AVERROR_INVALIDDATA;
+        if (buf_size - min_size < offs)
+            return AVERROR_INVALIDDATA;
+        if (buf_size - min_size - ref_size < ref_offs)
+            return AVERROR_INVALIDDATA;
+    }
+
+    if (mc_type2 == -1) {
+        mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type);
+    } else {
+        int ref_offs2 = offs + mv_y2 * band->pitch + mv_x2;
+        int ref_size2 = (mc_type2 > 1) * band->pitch + (mc_type2 & 1);
+        if (offs < 0 || ref_offs2 < 0 || !band->b_ref_buf)
+            return AVERROR_INVALIDDATA;
+        if (buf_size - min_size - ref_size2 < ref_offs2)
+            return AVERROR_INVALIDDATA;
 
-    mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type);
+        if (mc_type == -1)
+            mc(band->buf + offs, band->b_ref_buf + ref_offs2,
+               band->pitch, mc_type2);
+        else
+            mc_avg(band->buf + offs, band->ref_buf + ref_offs,
+                   band->b_ref_buf + ref_offs2, band->pitch,
+                   mc_type, mc_type2);
+    }
 
     return 0;
 }
@@ -266,6 +289,7 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes)
             av_freep(&planes[p].bands[b].bufs[0]);
             av_freep(&planes[p].bands[b].bufs[1]);
             av_freep(&planes[p].bands[b].bufs[2]);
+            av_freep(&planes[p].bands[b].bufs[3]);
 
             if (planes[p].bands[b].blk_vlc.cust_tab.table)
                 ff_free_vlc(&planes[p].bands[b].blk_vlc.cust_tab);
@@ -278,7 +302,8 @@ static av_cold void ivi_free_buffers(IVIPlaneDesc *planes)
     }
 }
 
-av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg)
+av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg,
+                               int is_indeo4)
 {
     int p, b;
     uint32_t b_width, b_height, align_fac, width_aligned,
@@ -340,6 +365,11 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg)
                 if (!band->bufs[2])
                     return AVERROR(ENOMEM);
             }
+            if (is_indeo4) {
+                band->bufs[3]  = av_mallocz(buf_size);
+                if (!band->bufs[3])
+                    return AVERROR(ENOMEM);
+            }
             /* reset custom vlc */
             planes[p].bands[0].blk_vlc.cust_desc.num_rows = 0;
         }
@@ -470,8 +500,11 @@ static int ivi_dc_transform(IVIBandDesc *band, int *prev_dc, int buf_offs,
 }
 
 static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
-                                   ivi_mc_func mc, int mv_x, int mv_y,
-                                   int *prev_dc, int is_intra, int mc_type,
+                                   ivi_mc_func mc, ivi_mc_avg_func mc_avg,
+                                   int mv_x, int mv_y,
+                                   int mv_x2, int mv_y2,
+                                   int *prev_dc, int is_intra,
+                                   int mc_type, int mc_type2,
                                    uint32_t quant, int offs,
                                    AVCodecContext *avctx)
 {
@@ -556,7 +589,8 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
 
     /* apply motion compensation */
     if (!is_intra)
-        return ivi_mc(band, mc, offs, mv_x, mv_y, mc_type);
+        return ivi_mc(band, mc, mc_avg, offs, mv_x, mv_y, mv_x2, mv_y2,
+                      mc_type, mc_type2);
 
     return 0;
 }
@@ -574,12 +608,14 @@ static int ivi_decode_coded_blocks(GetBitContext *gb, IVIBandDesc *band,
 static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
                              IVITile *tile, AVCodecContext *avctx)
 {
-    int mbn, blk, num_blocks, blk_size, ret, is_intra, mc_type = 0;
-    int mv_x = 0, mv_y = 0;
+    int mbn, blk, num_blocks, blk_size, ret, is_intra;
+    int mc_type = 0, mc_type2 = -1;
+    int mv_x = 0, mv_y = 0, mv_x2 = 0, mv_y2 = 0;
     int32_t prev_dc;
     uint32_t cbp, quant, buf_offs;
     IVIMbInfo *mb;
     ivi_mc_func mc_with_delta_func, mc_no_delta_func;
+    ivi_mc_avg_func mc_avg_with_delta_func, mc_avg_no_delta_func;
     const uint8_t *scale_tab;
 
     /* init intra prediction for the DC coefficient */
@@ -588,11 +624,15 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
     /* number of blocks per mb */
     num_blocks = (band->mb_size != blk_size) ? 4 : 1;
     if (blk_size == 8) {
-        mc_with_delta_func = ff_ivi_mc_8x8_delta;
-        mc_no_delta_func   = ff_ivi_mc_8x8_no_delta;
+        mc_with_delta_func     = ff_ivi_mc_8x8_delta;
+        mc_no_delta_func       = ff_ivi_mc_8x8_no_delta;
+        mc_avg_with_delta_func = ff_ivi_mc_avg_8x8_delta;
+        mc_avg_no_delta_func   = ff_ivi_mc_avg_8x8_no_delta;
     } else {
-        mc_with_delta_func = ff_ivi_mc_4x4_delta;
-        mc_no_delta_func   = ff_ivi_mc_4x4_no_delta;
+        mc_with_delta_func     = ff_ivi_mc_4x4_delta;
+        mc_no_delta_func       = ff_ivi_mc_4x4_no_delta;
+        mc_avg_with_delta_func = ff_ivi_mc_avg_4x4_delta;
+        mc_avg_no_delta_func   = ff_ivi_mc_avg_4x4_no_delta;
     }
 
     for (mbn = 0, mb = tile->mbs; mbn < tile->num_MBs; mb++, mbn++) {
@@ -611,13 +651,22 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
             quant = scale_tab[quant];
 
         if (!is_intra) {
-            mv_x = mb->mv_x;
-            mv_y = mb->mv_y;
+            mv_x  = mb->mv_x;
+            mv_y  = mb->mv_y;
+            mv_x2 = mb->b_mv_x;
+            mv_y2 = mb->b_mv_y;
             if (band->is_halfpel) {
-                mc_type = ((mv_y & 1) << 1) | (mv_x & 1);
-                mv_x >>= 1;
-                mv_y >>= 1; /* convert halfpel vectors into fullpel ones */
+                mc_type  = ((mv_y  & 1) << 1) | (mv_x  & 1);
+                mc_type2 = ((mv_y2 & 1) << 1) | (mv_x2 & 1);
+                mv_x  >>= 1;
+                mv_y  >>= 1;
+                mv_x2 >>= 1;
+                mv_y2 >>= 1; /* convert halfpel vectors into fullpel ones */
             }
+            if (mb->type == 2)
+                mc_type = -1;
+            if (mb->type != 2 && mb->type != 3)
+                mc_type2 = -1;
             if (mb->type) {
                 int dmv_x, dmv_y, cx, cy;
 
@@ -633,6 +682,21 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
                     return AVERROR_INVALIDDATA;
                 }
             }
+            if (mb->type == 2 || mb->type == 3) {
+                int dmv_x, dmv_y, cx, cy;
+
+                dmv_x = mb->b_mv_x >> band->is_halfpel;
+                dmv_y = mb->b_mv_y >> band->is_halfpel;
+                cx    = mb->b_mv_x &  band->is_halfpel;
+                cy    = mb->b_mv_y &  band->is_halfpel;
+
+                if (mb->xpos + dmv_x < 0 ||
+                    mb->xpos + dmv_x + band->mb_size + cx > band->pitch ||
+                    mb->ypos + dmv_y < 0 ||
+                    mb->ypos + dmv_y + band->mb_size + cy > band->aheight) {
+                    return AVERROR_INVALIDDATA;
+                }
+            }
         }
 
         for (blk = 0; blk < num_blocks; blk++) {
@@ -646,8 +710,11 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
 
             if (cbp & 1) { /* block coded ? */
                 ret = ivi_decode_coded_blocks(gb, band, mc_with_delta_func,
-                                              mv_x, mv_y, &prev_dc, is_intra,
-                                              mc_type, quant, buf_offs, avctx);
+                                              mc_avg_with_delta_func,
+                                              mv_x, mv_y, mv_x2, mv_y2,
+                                              &prev_dc, is_intra,
+                                              mc_type, mc_type2, quant,
+                                              buf_offs, avctx);
                 if (ret < 0)
                     return ret;
             } else {
@@ -659,8 +726,9 @@ static int ivi_decode_blocks(GetBitContext *gb, IVIBandDesc *band,
                     if (ret < 0)
                         return ret;
                 } else {
-                    ret = ivi_mc(band, mc_no_delta_func, buf_offs,
-                                 mv_x, mv_y, mc_type);
+                    ret = ivi_mc(band, mc_no_delta_func, mc_avg_no_delta_func,
+                                 buf_offs, mv_x, mv_y, mv_x2, mv_y2,
+                                 mc_type, mc_type2);
                     if (ret < 0)
                         return ret;
                 }
@@ -766,8 +834,8 @@ static int ivi_process_empty_tile(AVCodecContext *avctx, IVIBandDesc *band,
             for (blk = 0; blk < num_blocks; blk++) {
                 /* adjust block position in the buffer according with its number */
                 offs = mb->buf_offs + band->blk_size * ((blk & 1) + !!(blk & 2) * band->pitch);
-                ret = ivi_mc(band, mc_no_delta_func, offs,
-                             mv_x, mv_y, mc_type);
+                ret = ivi_mc(band, mc_no_delta_func, 0, offs,
+                             mv_x, mv_y, 0, 0, mc_type, -1);
                 if (ret < 0)
                     return ret;
             }
@@ -849,8 +917,14 @@ static int decode_band(IVI45DecContext *ctx,
         av_log(avctx, AV_LOG_ERROR, "Band buffer points to no data!\n");
         return AVERROR_INVALIDDATA;
     }
-    band->ref_buf = band->bufs[ctx->ref_buf];
-    band->data_ptr = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3);
+    if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_BIDIR) {
+        band->ref_buf   = band->bufs[ctx->b_ref_buf];
+        band->b_ref_buf = band->bufs[ctx->ref_buf];
+    } else {
+        band->ref_buf   = band->bufs[ctx->ref_buf];
+        band->b_ref_buf = 0;
+    }
+    band->data_ptr  = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3);
 
     result = ctx->decode_band_hdr(ctx, band, avctx);
     if (result) {
index 515b073..e2cc593 100644 (file)
@@ -117,6 +117,8 @@ typedef struct IVIMbInfo {
     int8_t      q_delta;  ///< quant delta
     int8_t      mv_x;     ///< motion vector (x component)
     int8_t      mv_y;     ///< motion vector (y component)
+    int8_t      b_mv_x;   ///< second motion vector (x component)
+    int8_t      b_mv_y;   ///< second motion vector (y component)
 } IVIMbInfo;
 
 
@@ -150,7 +152,8 @@ typedef struct IVIBandDesc {
     int             data_size;      ///< size of the band data
     int16_t         *buf;           ///< pointer to the output buffer for this band
     int16_t         *ref_buf;       ///< pointer to the reference frame buffer (for motion compensation)
-    int16_t         *bufs[3];       ///< array of pointers to the band buffers
+    int16_t         *b_ref_buf;     ///< pointer to the second reference frame buffer (for motion compensation)
+    int16_t         *bufs[4];       ///< array of pointers to the band buffers
     int             pitch;          ///< pitch associated with the buffers above
     int             is_empty;       ///< = 1 if this band doesn't contain any data
     int             mb_size;        ///< macroblock size
@@ -231,6 +234,7 @@ typedef struct IVI45DecContext {
     int             dst_buf;         ///< buffer index for the currently decoded frame
     int             ref_buf;         ///< inter frame reference buffer index
     int             ref2_buf;        ///< temporal storage for switching buffers
+    int             b_ref_buf;       ///< second reference frame buffer index
 
     IVIHuffTab      mb_vlc;          ///< current macroblock table descriptor
     IVIHuffTab      blk_vlc;         ///< current block table descriptor
@@ -314,11 +318,13 @@ int  ff_ivi_dec_huff_desc(GetBitContext *gb, int desc_coded, int which_tab,
 /**
  *  Initialize planes (prepares descriptors, allocates buffers etc).
  *
- *  @param[in,out]  planes  pointer to the array of the plane descriptors
- *  @param[in]      cfg     pointer to the ivi_pic_config structure describing picture layout
+ *  @param[in,out]  planes     pointer to the array of the plane descriptors
+ *  @param[in]      cfg        pointer to the ivi_pic_config structure describing picture layout
+ *  @param[in]      is_indeo4  flag signalling if it is Indeo 4 or not
  *  @return             result code: 0 - OK
  */
-int  ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg);
+int  ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg,
+                        int is_indeo4);
 
 /**
  *  Initialize tile and macroblock descriptors.
index bd1f523..ecc49b3 100644 (file)
@@ -762,39 +762,66 @@ void ff_ivi_put_dc_pixel_8x8(const int32_t *in, int16_t *out, uint32_t pitch,
 }
 
 #define IVI_MC_TEMPLATE(size, suffix, OP) \
-void ff_ivi_mc_ ## size ##x## size ## suffix (int16_t *buf, const int16_t *ref_buf, \
-                                              uint32_t pitch, int mc_type) \
+static void ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, \
+                                                 uint32_t dpitch, \
+                                                 const int16_t *ref_buf, \
+                                                 uint32_t pitch, int mc_type) \
 { \
     int     i, j; \
     const int16_t *wptr; \
 \
     switch (mc_type) { \
     case 0: /* fullpel (no interpolation) */ \
-        for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) { \
+        for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) { \
             for (j = 0; j < size; j++) {\
                 OP(buf[j], ref_buf[j]); \
             } \
         } \
         break; \
     case 1: /* horizontal halfpel interpolation */ \
-        for (i = 0; i < size; i++, buf += pitch, ref_buf += pitch) \
+        for (i = 0; i < size; i++, buf += dpitch, ref_buf += pitch) \
             for (j = 0; j < size; j++) \
                 OP(buf[j], (ref_buf[j] + ref_buf[j+1]) >> 1); \
         break; \
     case 2: /* vertical halfpel interpolation */ \
         wptr = ref_buf + pitch; \
-        for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \
+        for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \
             for (j = 0; j < size; j++) \
                 OP(buf[j], (ref_buf[j] + wptr[j]) >> 1); \
         break; \
     case 3: /* vertical and horizontal halfpel interpolation */ \
         wptr = ref_buf + pitch; \
-        for (i = 0; i < size; i++, buf += pitch, wptr += pitch, ref_buf += pitch) \
+        for (i = 0; i < size; i++, buf += dpitch, wptr += pitch, ref_buf += pitch) \
             for (j = 0; j < size; j++) \
                 OP(buf[j], (ref_buf[j] + ref_buf[j+1] + wptr[j] + wptr[j+1]) >> 2); \
         break; \
     } \
 } \
+\
+void ff_ivi_mc_ ## size ##x## size ## suffix(int16_t *buf, const int16_t *ref_buf, \
+                                             uint32_t pitch, int mc_type) \
+{ \
+    ivi_mc_ ## size ##x## size ## suffix(buf, pitch, ref_buf, pitch, mc_type); \
+} \
+
+#define IVI_MC_AVG_TEMPLATE(size, suffix, OP) \
+void ff_ivi_mc_avg_ ## size ##x## size ## suffix(int16_t *buf, \
+                                                 const int16_t *ref_buf, \
+                                                 const int16_t *ref_buf2, \
+                                                 uint32_t pitch, \
+                                                 int mc_type, int mc_type2) \
+{ \
+    int16_t tmp[size * size]; \
+    int i, j; \
+\
+    ivi_mc_ ## size ##x## size ## _no_delta(tmp, size, ref_buf, pitch, mc_type); \
+    ivi_mc_ ## size ##x## size ## _delta(tmp, size, ref_buf2, pitch, mc_type2); \
+    for (i = 0; i < size; i++, buf += pitch) { \
+        for (j = 0; j < size; j++) {\
+            OP(buf[j], tmp[i * size + j] >> 1); \
+        } \
+    } \
+} \
 
 #define OP_PUT(a, b)  (a) = (b)
 #define OP_ADD(a, b)  (a) += (b)
@@ -803,3 +830,7 @@ IVI_MC_TEMPLATE(8, _no_delta, OP_PUT)
 IVI_MC_TEMPLATE(8, _delta,    OP_ADD)
 IVI_MC_TEMPLATE(4, _no_delta, OP_PUT)
 IVI_MC_TEMPLATE(4, _delta,    OP_ADD)
+IVI_MC_AVG_TEMPLATE(8, _no_delta, OP_PUT)
+IVI_MC_AVG_TEMPLATE(8, _delta,    OP_ADD)
+IVI_MC_AVG_TEMPLATE(4, _no_delta, OP_PUT)
+IVI_MC_AVG_TEMPLATE(4, _delta,    OP_ADD)
index 31d37e3..11c2f5c 100644 (file)
@@ -291,4 +291,52 @@ void ff_ivi_mc_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch
  */
 void ff_ivi_mc_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, uint32_t pitch, int mc_type);
 
+/**
+ *  8x8 block motion compensation with adding delta
+ *
+ *  @param[in,out]  buf      pointer to the block in the current frame buffer containing delta
+ *  @param[in]      ref_buf  pointer to the corresponding block in the backward reference frame
+ *  @param[in]      ref_buf2 pointer to the corresponding block in the forward reference frame
+ *  @param[in]      pitch    pitch for moving to the next y line
+ *  @param[in]      mc_type  interpolation type for backward reference
+ *  @param[in]      mc_type2 interpolation type for forward reference
+ */
+void ff_ivi_mc_avg_8x8_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
+
+/**
+ *  4x4 block motion compensation with adding delta
+ *
+ *  @param[in,out]  buf      pointer to the block in the current frame buffer containing delta
+ *  @param[in]      ref_buf  pointer to the corresponding block in the backward reference frame
+ *  @param[in]      ref_buf2 pointer to the corresponding block in the forward reference frame
+ *  @param[in]      pitch    pitch for moving to the next y line
+ *  @param[in]      mc_type  interpolation type for backward reference
+ *  @param[in]      mc_type2 interpolation type for forward reference
+ */
+void ff_ivi_mc_avg_4x4_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
+
+/**
+ *  motion compensation without adding delta for B-frames
+ *
+ *  @param[in,out]  buf      pointer to the block in the current frame receiving the result
+ *  @param[in]      ref_buf  pointer to the corresponding block in the backward reference frame
+ *  @param[in]      ref_buf2 pointer to the corresponding block in the forward reference frame
+ *  @param[in]      pitch    pitch for moving to the next y line
+ *  @param[in]      mc_type  interpolation type for backward reference
+ *  @param[in]      mc_type2 interpolation type for forward reference
+ */
+void ff_ivi_mc_avg_8x8_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
+
+/**
+ *  4x4 block motion compensation without adding delta for B-frames
+ *
+ *  @param[in,out]  buf      pointer to the block in the current frame receiving the result
+ *  @param[in]      ref_buf  pointer to the corresponding block in the backward reference frame
+ *  @param[in]      ref_buf2 pointer to the corresponding block in the forward reference frame
+ *  @param[in]      pitch    pitch for moving to the next y line
+ *  @param[in]      mc_type  interpolation type for backward reference
+ *  @param[in]      mc_type2 interpolation type for forward reference
+ */
+void ff_ivi_mc_avg_4x4_no_delta(int16_t *buf, const int16_t *ref_buf, const int16_t *ref_buf2, uint32_t pitch, int mc_type, int mc_type2);
+
 #endif /* AVCODEC_IVI_DSP_H */