Add weighted motion compensation for RV40 B-frames

Signed-off-by: Ronald S. Bultje <rsbultje@gmail.com>
This commit is contained in:
Kostya Shishkov
2011-08-10 11:26:39 +02:00
committed by Ronald S. Bultje
parent e5ec68699e
commit b86ab38137
5 changed files with 189 additions and 104 deletions
+65 -11
View File
@@ -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);
+5
View File
@@ -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);
+6
View File
@@ -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);
+20
View File
@@ -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);
}