[libav-devel] Indeo4 B-frames decoding support

Kostya Shishkov kostya.shishkov at gmail.com
Sat Jun 21 08:41:14 CEST 2014


On Fri, Jun 20, 2014 at 08:46:11PM +0200, Dirk Ausserhaus wrote:
> Here is my patch for decoding B-frames in Indeo4 at last. And another
> patch to make things a bit simpler first.

At last!
 
> I suppose I have to give some explanation what I did here and why.
> 
> First of all, every band has three buffers—current, reference and one
> for scalability. I had to add the fourth buffer for the second
> reference and change Indeo4 switch_buffers function to handle the
> second reference frame.
> 
> Second, I had to add the second motion vector to the block
> information. I chose a new name for it in order to have less impact on
> existing code, since making mv_x and mv_y arrays would lead to more
> changes in all places and more possible errors.
> 
> Third, I had to extend ivi_mc function to handle B-frames and add some
> new functions for bidirectional motion compensation. Motion types are
> distinguished by mc_type and mc_type2 variables. Normally they should
> contain fractional offset for the motion compensation but I overloaded
> it so -1 means no motion vector at all.

That sounds reasonable to me.

> I've tested it on various Indeo4 and Indeo5 samples and it doesn't
> seem to break anything.

That's the best part ;)

> From 49d6cf8a6415d2cc49576919aea38a869872fa6b Mon Sep 17 00:00:00 2001
> From: Dirk Ausserhaus <dausserhaus at gmail.com>
> Date: Fri, 20 Jun 2014 20:15:20 +0200
> Subject: [PATCH 1/2] indeo45: use is_indeo4 context flag instead of checking
>  codec ID
> 
> ---
>  libavcodec/indeo4.c     |    2 ++
>  libavcodec/indeo5.c     |    2 ++
>  libavcodec/ivi_common.c |   10 ++++------
>  libavcodec/ivi_common.h |    2 ++
>  4 files changed, 10 insertions(+), 6 deletions(-)
> 
> diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
> index 3e97221..6893077 100644
> --- a/libavcodec/indeo4.c
> +++ b/libavcodec/indeo4.c
> @@ -620,6 +620,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
>      ctx->switch_buffers   = switch_buffers;
>      ctx->is_nonnull_frame = is_nonnull_frame;
>  
> +    ctx->is_indeo4 = 1;
> +
>      ctx->p_frame = av_frame_alloc();
>      if (!ctx->p_frame)
>          return AVERROR(ENOMEM);
> diff --git a/libavcodec/indeo5.c b/libavcodec/indeo5.c
> index 476355b..2465ce6 100644
> --- a/libavcodec/indeo5.c
> +++ b/libavcodec/indeo5.c
> @@ -640,6 +640,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
>      ctx->switch_buffers   = switch_buffers;
>      ctx->is_nonnull_frame = is_nonnull_frame;
>  
> +    ctx->is_indeo4 = 0;
> +
>      avctx->pix_fmt = AV_PIX_FMT_YUV410P;
>  
>      return 0;
> diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c
> index 6eb5b6c..93936c2 100644
> --- a/libavcodec/ivi_common.c
> +++ b/libavcodec/ivi_common.c
> @@ -968,8 +968,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
>      if (ctx->gop_invalid)
>          return AVERROR_INVALIDDATA;
>  
> -    if (avctx->codec_id == AV_CODEC_ID_INDEO4 &&
> -        ctx->frame_type == IVI4_FRAMETYPE_NULL_LAST) {
> +    if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_NULL_LAST) {
>          if (ctx->got_p_frame) {
>              av_frame_move_ref(data, ctx->p_frame);
>              *got_frame = 1;
> @@ -1027,7 +1026,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
>      }
>  
>      if (ctx->is_scalable) {
> -        if (avctx->codec_id == AV_CODEC_ID_INDEO4)
> +        if (ctx->is_indeo4)
>              ff_ivi_recompose_haar(&ctx->planes[0], frame->data[0], frame->linesize[0]);
>          else
>              ff_ivi_recompose53   (&ctx->planes[0], frame->data[0], frame->linesize[0]);
> @@ -1045,8 +1044,7 @@ int ff_ivi_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
>       * to be the only way to handle the B-frames mode.
>       * That's exactly the same Intel decoders do.
>       */
> -    if (avctx->codec_id == AV_CODEC_ID_INDEO4 &&
> -        ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
> +    if (ctx->is_indeo4 && ctx->frame_type == IVI4_FRAMETYPE_INTRA) {
>          int left;
>  
>          while (get_bits(&ctx->gb, 8)); // skip version string
> @@ -1077,7 +1075,7 @@ av_cold int ff_ivi_decode_close(AVCodecContext *avctx)
>          ff_free_vlc(&ctx->mb_vlc.cust_tab);
>  
>  #if IVI4_STREAM_ANALYSER
> -    if (avctx->codec_id == AV_CODEC_ID_INDEO4) {
> +    if (ctx->is_indeo4) {
>      if (ctx->is_scalable)
>          av_log(avctx, AV_LOG_ERROR, "This video uses scalability mode!\n");
>      if (ctx->uses_tiling)
> diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi_common.h
> index 604b549..515b073 100644
> --- a/libavcodec/ivi_common.h
> +++ b/libavcodec/ivi_common.h
> @@ -261,6 +261,8 @@ typedef struct IVI45DecContext {
>  
>      int gop_invalid;
>  
> +    int is_indeo4;
> +
>      AVFrame         *p_frame;
>      int             got_p_frame;
>  } IVI45DecContext;
> -- 
> 1.7.9.5

There's one more place - where quantiser is clipped but context is not passed
there. So LGTM and I'll apply this soon if noone objects.


> From 1b42b3679db161b6e97b0d51c18ec8a3f69e3106 Mon Sep 17 00:00:00 2001
> From: Dirk Ausserhaus <dausserhaus at gmail.com>
> Date: Sun, 8 Jun 2014 13:44:17 +0200
> Subject: [PATCH 2/2] indeo4: B-frames decoding
> 
> ---
>  libavcodec/indeo4.c     |   47 ++++++++++++-----
>  libavcodec/ivi_common.c |  133 +++++++++++++++++++++++++++++++++++------------
>  libavcodec/ivi_common.h |    6 ++-
>  libavcodec/ivi_dsp.c    |   43 ++++++++++++---
>  libavcodec/ivi_dsp.h    |   48 +++++++++++++++++
>  5 files changed, 225 insertions(+), 52 deletions(-)
> 
> diff --git a/libavcodec/indeo4.c b/libavcodec/indeo4.c
> index 6893077..288fd28 100644
> --- a/libavcodec/indeo4.c
> +++ b/libavcodec/indeo4.c
> @@ -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);
> diff --git a/libavcodec/ivi_common.c b/libavcodec/ivi_common.c
> index 93936c2..b2d54e1 100644
> --- a/libavcodec/ivi_common.c
> +++ b/libavcodec/ivi_common.c
> @@ -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;
> +    }
>  
> -    mc(band->buf + offs, band->ref_buf + ref_offs, band->pitch, mc_type);
> +    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;
> +
> +        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);
> @@ -331,7 +355,8 @@ av_cold int ff_ivi_init_planes(IVIPlaneDesc *planes, const IVIPicConfig *cfg)
>              band->aheight  = height_aligned;
>              band->bufs[0]  = av_mallocz(buf_size);
>              band->bufs[1]  = av_mallocz(buf_size);
> -            if (!band->bufs[0] || !band->bufs[1])
> +            band->bufs[3]  = av_mallocz(buf_size);
> +            if (!band->bufs[0] || !band->bufs[1] || !band->bufs[3])
>                  return AVERROR(ENOMEM);
>  
>              /* allocate the 3rd band buffer for scalability mode */

Is it possible to allocate that buffer only for Indeo4?

> @@ -470,8 +495,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 +584,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 +603,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 +619,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 +646,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 +677,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 +705,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 +721,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 +829,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 +912,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 = band->bufs[ctx->b_ref_buf];

Why set second reference for the frames that are not bidirectional?
Maybe set it to NULL instead?

> +    }
> +    band->data_ptr  = ctx->frame_data + (get_bits_count(&ctx->gb) >> 3);
>  
>      result = ctx->decode_band_hdr(ctx, band, avctx);
>      if (result) {
> diff --git a/libavcodec/ivi_common.h b/libavcodec/ivi_common.h
> index 515b073..6f3d084 100644
> --- a/libavcodec/ivi_common.h
> +++ b/libavcodec/ivi_common.h
> @@ -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
> diff --git a/libavcodec/ivi_dsp.c b/libavcodec/ivi_dsp.c
> index bd1f523..5a6cba8 100644
> --- a/libavcodec/ivi_dsp.c
> +++ b/libavcodec/ivi_dsp.c
> @@ -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)
> diff --git a/libavcodec/ivi_dsp.h b/libavcodec/ivi_dsp.h
> index 31d37e3..11c2f5c 100644
> --- a/libavcodec/ivi_dsp.h
> +++ b/libavcodec/ivi_dsp.h
> @@ -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 */
> -- 

In general LGTM


More information about the libav-devel mailing list