diff options
author | Kostya Shishkov <kostya.shishkov@gmail.com> | 2011-08-10 13:26:39 +0400 |
---|---|---|
committer | Ronald S. Bultje <rsbultje@gmail.com> | 2011-08-12 03:07:58 +0400 |
commit | b86ab38137be34376c90d45d08d49dbd28f2a72f (patch) | |
tree | 81d8adb7d44ff7e650d72212f94dab9a18528877 /libavcodec | |
parent | e5ec68699e418b5c6044195fb998ee5287f2bb6f (diff) |
Add weighted motion compensation for RV40 B-frames
Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/rv34.c | 76 | ||||
-rw-r--r-- | libavcodec/rv34.h | 5 | ||||
-rw-r--r-- | libavcodec/rv34dsp.h | 6 | ||||
-rw-r--r-- | libavcodec/rv40dsp.c | 20 |
4 files changed, 96 insertions, 11 deletions
diff --git a/libavcodec/rv34.c b/libavcodec/rv34.c index 58e4552bd8..cdc559fa07 100644 --- a/libavcodec/rv34.c +++ b/libavcodec/rv34.c @@ -717,7 +717,7 @@ static const int chroma_coeffs[3] = { 0, 3, 5 }; static inline void rv34_mc(RV34DecContext *r, const int block_type, const int xoff, const int yoff, int mv_off, const int width, const int height, int dir, - const int thirdpel, + const int thirdpel, int weighted, qpel_mc_func (*qpel_mc)[16], h264_chroma_mc_func (*chroma_mc)) { @@ -781,9 +781,15 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, srcU = uvbuf; srcV = uvbuf + 16; } - Y = s->dest[0] + xoff + yoff *s->linesize; - U = s->dest[1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; - V = s->dest[2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + if(!weighted){ + Y = s->dest[0] + xoff + yoff *s->linesize; + U = s->dest[1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + V = s->dest[2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + }else{ + Y = r->tmp_b_block_y [dir] + xoff + yoff *s->linesize; + U = r->tmp_b_block_uv[dir*2] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + V = r->tmp_b_block_uv[dir*2+1] + (xoff>>1) + (yoff>>1)*s->uvlinesize; + } if(block_type == RV34_MB_P_16x8){ qpel_mc[1][dxy](Y, srcY, s->linesize); @@ -804,33 +810,70 @@ static void rv34_mc_1mv(RV34DecContext *r, const int block_type, const int xoff, const int yoff, int mv_off, const int width, const int height, int dir) { - rv34_mc(r, block_type, xoff, yoff, mv_off, width, height, dir, r->rv30, + rv34_mc(r, block_type, xoff, yoff, mv_off, width, height, dir, r->rv30, 0, r->rdsp.put_pixels_tab, r->rdsp.put_chroma_pixels_tab); } +static void rv4_weight(RV34DecContext *r) +{ + r->rdsp.rv40_weight_pixels_tab[0](r->s.dest[0], + r->tmp_b_block_y[0], + r->tmp_b_block_y[1], + r->weight1, + r->weight2, + r->s.linesize); + r->rdsp.rv40_weight_pixels_tab[1](r->s.dest[1], + r->tmp_b_block_uv[0], + r->tmp_b_block_uv[2], + r->weight1, + r->weight2, + r->s.uvlinesize); + r->rdsp.rv40_weight_pixels_tab[1](r->s.dest[2], + r->tmp_b_block_uv[1], + r->tmp_b_block_uv[3], + r->weight1, + r->weight2, + r->s.uvlinesize); +} + static void rv34_mc_2mv(RV34DecContext *r, const int block_type) { - rv34_mc(r, block_type, 0, 0, 0, 2, 2, 0, r->rv30, + int weighted = !r->rv30 && block_type != RV34_MB_B_BIDIR && r->weight1 != 8192; + + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 0, r->rv30, weighted, r->rdsp.put_pixels_tab, r->rdsp.put_chroma_pixels_tab); - rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, - r->rdsp.avg_pixels_tab, - r->rdsp.avg_chroma_pixels_tab); + if(!weighted){ + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 0, + r->rdsp.avg_pixels_tab, + r->rdsp.avg_chroma_pixels_tab); + }else{ + rv34_mc(r, block_type, 0, 0, 0, 2, 2, 1, r->rv30, 1, + r->rdsp.put_pixels_tab, + r->rdsp.put_chroma_pixels_tab); + rv4_weight(r); + } } static void rv34_mc_2mv_skip(RV34DecContext *r) { int i, j; + int weighted = !r->rv30 && r->weight1 != 8192; + for(j = 0; j < 2; j++) for(i = 0; i < 2; i++){ rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 0, r->rv30, + weighted, r->rdsp.put_pixels_tab, r->rdsp.put_chroma_pixels_tab); rv34_mc(r, RV34_MB_P_8x8, i*8, j*8, i+j*r->s.b8_stride, 1, 1, 1, r->rv30, - r->rdsp.avg_pixels_tab, - r->rdsp.avg_chroma_pixels_tab); + weighted, + weighted ? r->rdsp.put_pixels_tab : r->rdsp.avg_pixels_tab, + weighted ? r->rdsp.put_chroma_pixels_tab : r->rdsp.avg_chroma_pixels_tab); } + if(weighted) + rv4_weight(r); } /** number of motion vectors in each macroblock type */ @@ -1265,6 +1308,16 @@ static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int if(MPV_frame_start(s, s->avctx) < 0) return -1; ff_er_frame_start(s); + if (!r->tmp_b_block_base || s->width != r->si.width || s->height != r->si.height) { + int i; + + r->tmp_b_block_base = av_realloc(r->tmp_b_block_base, s->linesize * 48); + for (i = 0; i < 2; i++) + r->tmp_b_block_y[i] = r->tmp_b_block_base + i * 16 * s->linesize; + for (i = 0; i < 4; i++) + r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize + + (i >> 1) * 8 * s->uvlinesize + (i & 1) * 16; + } r->cur_pts = r->si.pts; if(s->pict_type != AV_PICTURE_TYPE_B){ r->last_pts = r->next_pts; @@ -1500,6 +1553,7 @@ av_cold int ff_rv34_decode_end(AVCodecContext *avctx) av_freep(&r->intra_types_hist); r->intra_types = NULL; + av_freep(&r->tmp_b_block_base); av_freep(&r->mb_type); av_freep(&r->cbp_luma); av_freep(&r->cbp_chroma); diff --git a/libavcodec/rv34.h b/libavcodec/rv34.h index ef19813cf8..12607fb806 100644 --- a/libavcodec/rv34.h +++ b/libavcodec/rv34.h @@ -116,6 +116,11 @@ typedef struct RV34DecContext{ /** 8x8 block available flags (for MV prediction) */ DECLARE_ALIGNED(8, uint32_t, avail_cache)[3*4]; + /** temporary blocks for RV4 weighted MC */ + uint8_t *tmp_b_block_y[2]; + uint8_t *tmp_b_block_uv[4]; + uint8_t *tmp_b_block_base; + int (*parse_slice_header)(struct RV34DecContext *r, GetBitContext *gb, SliceInfo *si); int (*decode_mb_info)(struct RV34DecContext *r); int (*decode_intra_types)(struct RV34DecContext *r, GetBitContext *gb, int8_t *dst); diff --git a/libavcodec/rv34dsp.h b/libavcodec/rv34dsp.h index 771a6c0f08..e1def7dc26 100644 --- a/libavcodec/rv34dsp.h +++ b/libavcodec/rv34dsp.h @@ -29,11 +29,17 @@ #include "dsputil.h" +typedef void (*rv40_weight_func)(uint8_t *dst/*align width (8 or 16)*/, + uint8_t *src1/*align width (8 or 16)*/, + uint8_t *src2/*align width (8 or 16)*/, + int w1, int w2, int stride); + typedef struct RV34DSPContext { qpel_mc_func put_pixels_tab[4][16]; qpel_mc_func avg_pixels_tab[4][16]; h264_chroma_mc_func put_chroma_pixels_tab[3]; h264_chroma_mc_func avg_chroma_pixels_tab[3]; + rv40_weight_func rv40_weight_pixels_tab[2]; } RV34DSPContext; void ff_rv30dsp_init(RV34DSPContext *c, DSPContext* dsp); diff --git a/libavcodec/rv40dsp.c b/libavcodec/rv40dsp.c index 132f063dfa..ca620ab7d7 100644 --- a/libavcodec/rv40dsp.c +++ b/libavcodec/rv40dsp.c @@ -285,6 +285,23 @@ static void OPNAME ## rv40_chroma_mc8_c(uint8_t *dst/*align 8*/, uint8_t *src/*a RV40_CHROMA_MC(put_, op_put) RV40_CHROMA_MC(avg_, op_avg) +#define RV40_WEIGHT_FUNC(size) \ +static void rv40_weight_func_ ## size (uint8_t *dst, uint8_t *src1, uint8_t *src2, int w1, int w2, int stride)\ +{\ + int i, j;\ +\ + for (j = 0; j < size; j++) {\ + for (i = 0; i < size; i++)\ + dst[i] = (((w2 * src1[i]) >> 9) + ((w1 * src2[i]) >> 9) + 0x10) >> 5;\ + src1 += stride;\ + src2 += stride;\ + dst += stride;\ + }\ +} + +RV40_WEIGHT_FUNC(16) +RV40_WEIGHT_FUNC(8) + av_cold void ff_rv40dsp_init(RV34DSPContext *c, DSPContext* dsp) { c->put_pixels_tab[0][ 0] = dsp->put_h264_qpel_pixels_tab[0][0]; c->put_pixels_tab[0][ 1] = put_rv40_qpel16_mc10_c; @@ -356,6 +373,9 @@ av_cold void ff_rv40dsp_init(RV34DSPContext *c, DSPContext* dsp) { c->avg_chroma_pixels_tab[0] = avg_rv40_chroma_mc8_c; c->avg_chroma_pixels_tab[1] = avg_rv40_chroma_mc4_c; + c->rv40_weight_pixels_tab[0] = rv40_weight_func_16; + c->rv40_weight_pixels_tab[1] = rv40_weight_func_8; + if (HAVE_MMX) ff_rv40dsp_init_x86(c, dsp); } |