📄 mvmv.c
字号:
#include "stdlib.h"
#include "MVBitstream.h"
#include "MVMv.h"
extern VLC const TMNMVtab0[];
extern VLC const TMNMVtab1[];
extern VLC const TMNMVtab2[];
static const VECTOR zeroMV = { 0, 0 };
__inline int get_mv_data(Bitstream * bs)
{
uint32_t index;
if (BitstreamGetBit(bs))
return 0;
index = BitstreamShowBits(bs, 12);
if (index >= 512) {
index = (index >> 8) - 2;
BitstreamSkip(bs, TMNMVtab0[index].len);
return TMNMVtab0[index].code;
}
if (index >= 128) {
index = (index >> 2) - 32;
BitstreamSkip(bs, TMNMVtab1[index].len);
return TMNMVtab1[index].code;
}
index -= 4;
BitstreamSkip(bs, TMNMVtab2[index].len);
return TMNMVtab2[index].code;
}
int get_mv(Bitstream * bs, int fcode)
{
int data;
int res;
int mv;
int scale_fac = 1 << (fcode - 1);
data = get_mv_data(bs);
if (scale_fac == 1 || data == 0)
return data;
res = BitstreamGetBits(bs, fcode - 1);
mv = ((abs(data) - 1) * scale_fac) + res + 1;
return data < 0 ? -mv : mv;
}
VECTOR get_pmv2_interlaced(const MACROBLOCK * const mbs,
const int mb_width,
const int bound,
const int x,
const int y,
const int block)
{
int lx, ly, lz; /* left */
int tx, ty, tz; /* top */
int rx, ry, rz; /* top-right */
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
lx=x-1; ly=y; lz=1;
tx=x; ty=y-1; tz=2;
rx=x+1; ry=y-1; rz=2;
lpos=lx+ly*mb_width;
rpos=rx+ry*mb_width;
tpos=tx+ty*mb_width;
if(lx>=0 && lpos>=bound)
{
num_cand++;
if(mbs[lpos].field_pred)
pmv[1] = mbs[lpos].mvs_avg;
else
pmv[1] = mbs[lpos].mvs[lz];
}
else
{
pmv[1] = zeroMV;
}
if(tpos>=bound)
{
num_cand++;
last_cand=2;
if(mbs[tpos].field_pred)
pmv[2] = mbs[tpos].mvs_avg;
else
pmv[2] = mbs[tpos].mvs[tz];
}
else
{
pmv[2] = zeroMV;
}
if(rx<mb_width && rpos>=bound)
{
num_cand++;
last_cand = 3;
if(mbs[rpos].field_pred)
pmv[3] = mbs[rpos].mvs_avg;
else
pmv[3] = mbs[rpos].mvs[rz];
}
else
{
pmv[3] = zeroMV;
}
/* If there're more than one candidate, we return the median vector */
if(num_cand>1)
{
/* set median */
pmv[0].x = MIN(MAX(pmv[1].x, pmv[2].x),
MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
pmv[0].y = MIN(MAX(pmv[1].y, pmv[2].y),
MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
return pmv[0];
}
return pmv[last_cand]; /* no point calculating median mv */
}
VECTOR get_pmv2(const MACROBLOCK * const mbs,
const int mb_width,
const int bound,
const int x,
const int y,
const int block)
{
int lx, ly, lz; /* left */
int tx, ty, tz; /* top */
int rx, ry, rz; /* top-right */
int lpos, tpos, rpos;
int num_cand = 0, last_cand = 1;
VECTOR pmv[4]; /* left neighbour, top neighbour, top-right neighbour */
switch (block) {
case 0:
lx = x - 1; ly = y; lz = 1;
tx = x; ty = y - 1; tz = 2;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 1:
lx = x; ly = y; lz = 0;
tx = x; ty = y - 1; tz = 3;
rx = x + 1; ry = y - 1; rz = 2;
break;
case 2:
lx = x - 1; ly = y; lz = 3;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
break;
default:
lx = x; ly = y; lz = 2;
tx = x; ty = y; tz = 0;
rx = x; ry = y; rz = 1;
}
lpos = lx + ly * mb_width;
rpos = rx + ry * mb_width;
tpos = tx + ty * mb_width;
if (lpos >= bound && lx >= 0) {
num_cand++;
pmv[1] = mbs[lpos].mvs[lz];
} else pmv[1] = zeroMV;
if (tpos >= bound) {
num_cand++;
last_cand = 2;
pmv[2] = mbs[tpos].mvs[tz];
} else pmv[2] = zeroMV;
if (rpos >= bound && rx < mb_width) {
num_cand++;
last_cand = 3;
pmv[3] = mbs[rpos].mvs[rz];
} else pmv[3] = zeroMV;
/* If there're more than one candidate, we return the median vector */
if (num_cand > 1) {
/* set median */
pmv[0].x =
MIN(MAX(pmv[1].x, pmv[2].x),
MIN(MAX(pmv[2].x, pmv[3].x), MAX(pmv[1].x, pmv[3].x)));
pmv[0].y =
MIN(MAX(pmv[1].y, pmv[2].y),
MIN(MAX(pmv[2].y, pmv[3].y), MAX(pmv[1].y, pmv[3].y)));
return pmv[0];
}
return pmv[last_cand]; /* no point calculating median mv */
}
void get_motion_vector_interlaced(DECODER * dec,
Bitstream * bs,
int x,
int y,
int k,
MACROBLOCK *pMB,
int fcode,
const int bound)
{
const int scale_fac = 1 << (fcode - 1);
const int high = (32 * scale_fac) - 1;
const int low = ((-32) * scale_fac);
const int range = (64 * scale_fac);
/* Get interlaced prediction */
const VECTOR pmv=get_pmv2_interlaced(dec->mbs,dec->mb_width,bound,x,y,k);
VECTOR mv,mvf1,mvf2;
if(!pMB->field_pred)
{
mv.x = get_mv(bs,fcode);
mv.y = get_mv(bs,fcode);
mv.x += pmv.x;
mv.y += pmv.y;
if(mv.x<low)
{
mv.x += range;
}
else
if(mv.x>high)
{
mv.x-=range;
}
if(mv.y < low)
{
mv.y += range;
}
else
if (mv.y > high)
{
mv.y -= range;
}
pMB->mvs[0]=pMB->mvs[1]=pMB->mvs[2]=pMB->mvs[3]=mv;
}
else
{
mvf1.x = get_mv(bs, fcode);
mvf1.y = get_mv(bs, fcode);
mvf1.x += pmv.x;
mvf1.y = 2*(mvf1.y+pmv.y/2); /* It's multiple of 2 */
if (mvf1.x < low)
{
mvf1.x += range;
}
else
if (mvf1.x > high)
{
mvf1.x -= range;
}
if (mvf1.y < low)
{
mvf1.y += range;
}
else
if (mvf1.y > high)
{
mvf1.y -= range;
}
mvf2.x = get_mv(bs, fcode);
mvf2.y = get_mv(bs, fcode);
mvf2.x += pmv.x;
mvf2.y = 2*(mvf2.y+pmv.y/2); /* It's multiple of 2 */
if (mvf2.x < low)
{
mvf2.x += range;
}
else
if (mvf2.x > high)
{
mvf2.x -= range;
}
if (mvf2.y < low)
{
mvf2.y += range;
}
else
if (mvf2.y > high)
{
mvf2.y -= range;
}
pMB->mvs[0]=mvf1;
pMB->mvs[1]=mvf2;
pMB->mvs[2].x=pMB->mvs[3].x=0;
pMB->mvs[2].y=pMB->mvs[3].y=0;
/* Calculate average for as it is field predicted */
pMB->mvs_avg.x=DIV2ROUND(pMB->mvs[0].x+pMB->mvs[1].x);
pMB->mvs_avg.y=DIV2ROUND(pMB->mvs[0].y+pMB->mvs[1].y);
}
}
void get_b_motion_vector(Bitstream * bs,
VECTOR * mv,
int fcode,
const VECTOR pmv,
const DECODER * const dec,
const int x, const int y)
{
const int scale_fac = 1 << (fcode - 1);
const int high = (32 * scale_fac) - 1;
const int low = ((-32) * scale_fac);
const int range = (64 * scale_fac);
int mv_x = get_mv(bs, fcode);
int mv_y = get_mv(bs, fcode);
mv_x += pmv.x;
mv_y += pmv.y;
if (mv_x < low)
mv_x += range;
else if (mv_x > high)
mv_x -= range;
if (mv_y < low)
mv_y += range;
else if (mv_y > high)
mv_y -= range;
mv->x = mv_x;
mv->y = mv_y;
}
void get_motion_vector(DECODER * dec,
Bitstream * bs,
int x,
int y,
int k,
VECTOR * ret_mv,
int fcode,
const int bound)
{
const int scale_fac = 1 << (fcode - 1);
const int high = (32 * scale_fac) - 1;
const int low = ((-32) * scale_fac);
const int range = (64 * scale_fac);
const VECTOR pmv = get_pmv2(dec->mbs, dec->mb_width, bound, x, y, k);
VECTOR mv;
mv.x = get_mv(bs, fcode);
mv.y = get_mv(bs, fcode);
mv.x += pmv.x;
mv.y += pmv.y;
if (mv.x < low)
{
mv.x += range;
}
else
if (mv.x > high)
{
mv.x -= range;
}
if (mv.y < low)
{
mv.y += range;
}
else
if (mv.y > high)
{
mv.y -= range;
}
ret_mv->x = mv.x;
ret_mv->y = mv.y;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -