24 |
#endif |
#endif |
25 |
|
|
26 |
/* assume b>0 */ |
/* assume b>0 */ |
27 |
#ifndef ROUNDED_DIV |
#ifndef RDIV |
28 |
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) |
#define RDIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b)) |
29 |
#endif |
#endif |
30 |
|
|
31 |
|
|
173 |
} |
} |
174 |
} |
} |
175 |
|
|
176 |
|
|
177 |
|
static __inline void |
178 |
|
compensate16x16_interpolate_ro(int16_t * const dct_codes, |
179 |
|
const uint8_t * const cur, |
180 |
|
const uint8_t * const ref, |
181 |
|
const uint8_t * const refh, |
182 |
|
const uint8_t * const refv, |
183 |
|
const uint8_t * const refhv, |
184 |
|
uint8_t * const tmp, |
185 |
|
const uint32_t x, const uint32_t y, |
186 |
|
const int32_t dx, const int32_t dy, |
187 |
|
const int32_t stride, |
188 |
|
const int quarterpel) |
189 |
|
{ |
190 |
|
const uint8_t * ptr; |
191 |
|
|
192 |
|
if(quarterpel) { |
193 |
|
if ((dx&3) | (dy&3)) { |
194 |
|
interpolate16x16_quarterpel(tmp - y * stride - x, |
195 |
|
(uint8_t *) ref, tmp + 32, |
196 |
|
tmp + 64, tmp + 96, x, y, dx, dy, stride, 0); |
197 |
|
ptr = tmp; |
198 |
|
} else ptr = ref + (y + dy/4)*stride + x + dx/4; // fullpixel position |
199 |
|
|
200 |
|
} else ptr = get_ref(ref, refh, refv, refhv, x, y, 1, dx, dy, stride); |
201 |
|
|
202 |
|
transfer_8to16subro(dct_codes, cur + y * stride + x, |
203 |
|
ptr, stride); |
204 |
|
transfer_8to16subro(dct_codes+64, cur + y * stride + x + 8, |
205 |
|
ptr + 8, stride); |
206 |
|
transfer_8to16subro(dct_codes+128, cur + y * stride + x + 8*stride, |
207 |
|
ptr + 8*stride, stride); |
208 |
|
transfer_8to16subro(dct_codes+192, cur + y * stride + x + 8*stride+8, |
209 |
|
ptr + 8*stride + 8, stride); |
210 |
|
|
211 |
|
} |
212 |
|
|
213 |
|
|
214 |
/* XXX: slow, inelegant... */ |
/* XXX: slow, inelegant... */ |
215 |
static void |
static void |
216 |
interpolate18x18_switch(uint8_t * const cur, |
interpolate18x18_switch(uint8_t * const cur, |
301 |
if ( (!reduced_resolution) && (mb->mode == MODE_NOT_CODED) ) { /* quick copy for early SKIP */ |
if ( (!reduced_resolution) && (mb->mode == MODE_NOT_CODED) ) { /* quick copy for early SKIP */ |
302 |
/* early SKIP is only activated in P-VOPs, not in S-VOPs, so mcsel can never be 1 */ |
/* early SKIP is only activated in P-VOPs, not in S-VOPs, so mcsel can never be 1 */ |
303 |
|
|
|
/* if (mb->mcsel) { |
|
|
transfer16x16_copy(cur->y + 16 * (i + j * edged_width), |
|
|
refGMC->y + 16 * (i + j * edged_width), |
|
|
edged_width); |
|
|
transfer8x8_copy(cur->u + 8 * (i + j * edged_width/2), |
|
|
refGMC->u + 8 * (i + j * edged_width/2), |
|
|
edged_width / 2); |
|
|
transfer8x8_copy(cur->v + 8 * (i + j * edged_width/2), |
|
|
refGMC->v + 8 * (i + j * edged_width/2), |
|
|
edged_width / 2); |
|
|
} else |
|
|
*/ |
|
|
{ |
|
304 |
transfer16x16_copy(cur->y + 16 * (i + j * edged_width), |
transfer16x16_copy(cur->y + 16 * (i + j * edged_width), |
305 |
ref->y + 16 * (i + j * edged_width), |
ref->y + 16 * (i + j * edged_width), |
306 |
edged_width); |
edged_width); |
311 |
transfer8x8_copy(cur->v + 8 * (i + j * edged_width/2), |
transfer8x8_copy(cur->v + 8 * (i + j * edged_width/2), |
312 |
ref->v + 8 * (i + j * edged_width/2), |
ref->v + 8 * (i + j * edged_width/2), |
313 |
edged_width / 2); |
edged_width / 2); |
|
} |
|
314 |
return; |
return; |
315 |
} |
} |
316 |
|
|
317 |
if ((mb->mode == MODE_NOT_CODED || mb->mode == MODE_INTER |
if ((mb->mode == MODE_NOT_CODED || mb->mode == MODE_INTER |
318 |
|| mb->mode == MODE_INTER_Q) /*&& !quarterpel*/) { |
|| mb->mode == MODE_INTER_Q)) { |
319 |
|
|
320 |
/* reduced resolution + GMC: not possible */ |
/* reduced resolution + GMC: not possible */ |
321 |
|
|
424 |
f_refv->y, f_refhv->y, tmp, 16 * i, 16 * j, dx, |
f_refv->y, f_refhv->y, tmp, 16 * i, 16 * j, dx, |
425 |
dy, edged_width, quarterpel, 0, 0); |
dy, edged_width, quarterpel, 0, 0); |
426 |
|
|
427 |
dx /= 1 + quarterpel; |
if (quarterpel) { dx /= 2; dy /= 2; } |
428 |
dy /= 1 + quarterpel; |
|
429 |
CompensateChroma( (dx >> 1) + roundtab_79[dx & 0x3], |
CompensateChroma( (dx >> 1) + roundtab_79[dx & 0x3], |
430 |
(dy >> 1) + roundtab_79[dy & 0x3], |
(dy >> 1) + roundtab_79[dy & 0x3], |
431 |
i, j, cur, f_ref, tmp, |
i, j, cur, f_ref, tmp, |
436 |
case MODE_BACKWARD: |
case MODE_BACKWARD: |
437 |
b_dx = bmvs->x; b_dy = bmvs->y; |
b_dx = bmvs->x; b_dy = bmvs->y; |
438 |
|
|
439 |
compensate16x16_interpolate(&dct_codes[0 * 64], cur->y, b_ref->y, b_refh->y, |
compensate16x16_interpolate_ro(&dct_codes[0 * 64], cur->y, b_ref->y, b_refh->y, |
440 |
b_refv->y, b_refhv->y, tmp, 16 * i, 16 * j, b_dx, |
b_refv->y, b_refhv->y, tmp, 16 * i, 16 * j, b_dx, |
441 |
b_dy, edged_width, quarterpel, 0, 0); |
b_dy, edged_width, quarterpel); |
442 |
|
|
443 |
|
if (quarterpel) { b_dx /= 2; b_dy /= 2; } |
444 |
|
|
|
b_dx /= 1 + quarterpel; |
|
|
b_dy /= 1 + quarterpel; |
|
445 |
CompensateChroma( (b_dx >> 1) + roundtab_79[b_dx & 0x3], |
CompensateChroma( (b_dx >> 1) + roundtab_79[b_dx & 0x3], |
446 |
(b_dy >> 1) + roundtab_79[b_dy & 0x3], |
(b_dy >> 1) + roundtab_79[b_dy & 0x3], |
447 |
i, j, cur, b_ref, tmp, |
i, j, cur, b_ref, tmp, |
567 |
|
|
568 |
|
|
569 |
|
|
570 |
|
void generate_GMCparameters( const int num_wp, const int res, |
571 |
|
const WARPPOINTS *const warp, |
572 |
|
const int width, const int height, |
573 |
|
GMC_DATA *const gmc) |
574 |
|
{ |
575 |
|
const int du0 = warp->duv[0].x; |
576 |
|
const int dv0 = warp->duv[0].y; |
577 |
|
const int du1 = warp->duv[1].x; |
578 |
|
const int dv1 = warp->duv[1].y; |
579 |
|
const int du2 = warp->duv[2].x; |
580 |
|
const int dv2 = warp->duv[2].y; |
581 |
|
|
582 |
|
gmc->W = width; |
583 |
|
gmc->H = height; |
584 |
|
|
585 |
|
gmc->rho = 4 - log2bin(res-1); // = {3,2,1,0} for res={2,4,8,16} |
586 |
|
|
587 |
|
gmc->alpha = log2bin(gmc->W-1); |
588 |
|
gmc->Ws = (1 << gmc->alpha); |
589 |
|
|
590 |
|
gmc->dxF = 16*gmc->Ws + RDIV( 8*gmc->Ws*du1, gmc->W ); |
591 |
|
gmc->dxG = RDIV( 8*gmc->Ws*dv1, gmc->W ); |
592 |
|
gmc->Fo = (res*du0 + 1) << (gmc->alpha+gmc->rho-1); |
593 |
|
gmc->Go = (res*dv0 + 1) << (gmc->alpha+gmc->rho-1); |
594 |
|
|
595 |
|
if (num_wp==2) { |
596 |
|
gmc->dyF = -gmc->dxG; |
597 |
|
gmc->dyG = gmc->dxF; |
598 |
|
} |
599 |
|
else if (num_wp==3) { |
600 |
|
gmc->beta = log2bin(gmc->H-1); |
601 |
|
gmc->Hs = (1 << gmc->beta); |
602 |
|
gmc->dyF = RDIV( 8*gmc->Hs*du2, gmc->H ); |
603 |
|
gmc->dyG = 16*gmc->Hs + RDIV( 8*gmc->Hs*dv2, gmc->H ); |
604 |
|
if (gmc->beta > gmc->alpha) { |
605 |
|
gmc->dxF <<= (gmc->beta - gmc->alpha); |
606 |
|
gmc->dxG <<= (gmc->beta - gmc->alpha); |
607 |
|
gmc->alpha = gmc->beta; |
608 |
|
gmc->Ws = 1<< gmc->beta; |
609 |
|
} |
610 |
|
else { |
611 |
|
gmc->dyF <<= gmc->alpha - gmc->beta; |
612 |
|
gmc->dyG <<= gmc->alpha - gmc->beta; |
613 |
|
} |
614 |
|
} |
615 |
|
|
616 |
|
gmc->cFo = gmc->dxF + gmc->dyF + (1 << (gmc->alpha+gmc->rho+1)); |
617 |
|
gmc->cFo += 16*gmc->Ws*(du0-1); |
618 |
|
|
619 |
|
gmc->cGo = gmc->dxG + gmc->dyG + (1 << (gmc->alpha+gmc->rho+1)); |
620 |
|
gmc->cGo += 16*gmc->Ws*(dv0-1); |
621 |
|
} |
622 |
|
|
623 |
|
void |
624 |
|
generate_GMCimage( const GMC_DATA *const gmc_data, // [input] precalculated data |
625 |
|
const IMAGE *const pRef, // [input] |
626 |
|
const int mb_width, |
627 |
|
const int mb_height, |
628 |
|
const int stride, |
629 |
|
const int stride2, |
630 |
|
const int fcode, // [input] some parameters... |
631 |
|
const int32_t quarterpel, // [input] for rounding avgMV |
632 |
|
const int reduced_resolution, // [input] ignored |
633 |
|
const int32_t rounding, // [input] for rounding image data |
634 |
|
MACROBLOCK *const pMBs, // [output] average motion vectors |
635 |
|
IMAGE *const pGMC) // [output] full warped image |
636 |
|
{ |
637 |
|
|
638 |
|
unsigned int mj,mi; |
639 |
|
VECTOR avgMV; |
640 |
|
|
641 |
|
for (mj=0;mj<mb_height;mj++) |
642 |
|
for (mi=0;mi<mb_width; mi++) |
643 |
|
{ |
644 |
|
avgMV = generate_GMCimageMB(gmc_data, pRef, mi, mj, |
645 |
|
stride, stride2, quarterpel, rounding, pGMC); |
646 |
|
|
647 |
|
pMBs[mj*mb_width+mi].amv.x = gmc_sanitize(avgMV.x, quarterpel, fcode); |
648 |
|
pMBs[mj*mb_width+mi].amv.y = gmc_sanitize(avgMV.y, quarterpel, fcode); |
649 |
|
pMBs[mj*mb_width+mi].mcsel = 0; /* until mode decision */ |
650 |
|
} |
651 |
|
} |
652 |
|
|
653 |
|
|
654 |
|
|
655 |
|
#define MLT(i) (((16-(i))<<16) + (i)) |
656 |
|
static const uint32_t MTab[16] = { |
657 |
|
MLT( 0), MLT( 1), MLT( 2), MLT( 3), MLT( 4), MLT( 5), MLT( 6), MLT(7), |
658 |
|
MLT( 8), MLT( 9), MLT(10), MLT(11), MLT(12), MLT(13), MLT(14), MLT(15) |
659 |
|
}; |
660 |
|
#undef MLT |
661 |
|
|
662 |
|
VECTOR generate_GMCimageMB( const GMC_DATA *const gmc_data, |
663 |
|
const IMAGE *const pRef, |
664 |
|
const int mi, const int mj, |
665 |
|
const int stride, |
666 |
|
const int stride2, |
667 |
|
const int quarterpel, |
668 |
|
const int rounding, |
669 |
|
IMAGE *const pGMC) |
670 |
|
{ |
671 |
|
const int W = gmc_data->W; |
672 |
|
const int H = gmc_data->H; |
673 |
|
|
674 |
|
const int rho = gmc_data->rho; |
675 |
|
const int alpha = gmc_data->alpha; |
676 |
|
|
677 |
|
const int rounder = ( 128 - (rounding<<(rho+rho)) ) << 16; |
678 |
|
|
679 |
|
const int dxF = gmc_data->dxF; |
680 |
|
const int dyF = gmc_data->dyF; |
681 |
|
const int dxG = gmc_data->dxG; |
682 |
|
const int dyG = gmc_data->dyG; |
683 |
|
|
684 |
|
uint8_t *dstY, *dstU, *dstV; |
685 |
|
|
686 |
|
int I,J; |
687 |
|
VECTOR avgMV = {0,0}; |
688 |
|
|
689 |
|
int32_t Fj, Gj; |
690 |
|
|
691 |
|
dstY = &pGMC->y[(mj*16)*stride+mi*16] + 16; |
692 |
|
|
693 |
|
Fj = gmc_data->Fo + dyF*mj*16 + dxF*mi*16; |
694 |
|
Gj = gmc_data->Go + dyG*mj*16 + dxG*mi*16; |
695 |
|
for (J=16; J>0; --J) |
696 |
|
{ |
697 |
|
int32_t Fi, Gi; |
698 |
|
|
699 |
|
Fi = Fj; Fj += dyF; |
700 |
|
Gi = Gj; Gj += dyG; |
701 |
|
for (I=-16; I<0; ++I) |
702 |
|
{ |
703 |
|
int32_t F, G; |
704 |
|
uint32_t ri, rj; |
705 |
|
|
706 |
|
F = ( Fi >> (alpha+rho) ) << rho; Fi += dxF; |
707 |
|
G = ( Gi >> (alpha+rho) ) << rho; Gi += dxG; |
708 |
|
|
709 |
|
avgMV.x += F; |
710 |
|
avgMV.y += G; |
711 |
|
|
712 |
|
ri = MTab[F&15]; |
713 |
|
rj = MTab[G&15]; |
714 |
|
|
715 |
|
F >>= 4; |
716 |
|
G >>= 4; |
717 |
|
|
718 |
|
if (F< -1) F=-1; |
719 |
|
else if (F>W) F=W; |
720 |
|
if (G< -1) G=-1; |
721 |
|
else if (G>H) G=H; |
722 |
|
|
723 |
|
{ // MMX-like bilinear... |
724 |
|
const int offset = G*stride + F; |
725 |
|
uint32_t f0, f1; |
726 |
|
f0 = pRef->y[ offset +0 ]; |
727 |
|
f0 |= pRef->y[ offset +1 ] << 16; |
728 |
|
f1 = pRef->y[ offset+stride +0 ]; |
729 |
|
f1 |= pRef->y[ offset+stride +1 ] << 16; |
730 |
|
f0 = (ri*f0)>>16; |
731 |
|
f1 = (ri*f1) & 0x0fff0000; |
732 |
|
f0 |= f1; |
733 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
734 |
|
|
735 |
|
dstY[I] = (uint8_t)f0; |
736 |
|
} |
737 |
|
} |
738 |
|
dstY += stride; |
739 |
|
} |
740 |
|
|
741 |
|
dstU = &pGMC->u[(mj*8)*stride2+mi*8] + 8; |
742 |
|
dstV = &pGMC->v[(mj*8)*stride2+mi*8] + 8; |
743 |
|
|
744 |
|
Fj = gmc_data->cFo + dyF*4 *mj*8 + dxF*4 *mi*8; |
745 |
|
Gj = gmc_data->cGo + dyG*4 *mj*8 + dxG*4 *mi*8; |
746 |
|
for (J=8; J>0; --J) |
747 |
|
{ |
748 |
|
int32_t Fi, Gi; |
749 |
|
Fi = Fj; Fj += 4*dyF; |
750 |
|
Gi = Gj; Gj += 4*dyG; |
751 |
|
|
752 |
|
for (I=-8; I<0; ++I) |
753 |
|
{ |
754 |
|
int32_t F, G; |
755 |
|
uint32_t ri, rj; |
756 |
|
|
757 |
|
F = ( Fi >> (alpha+rho+2) ) << rho; Fi += 4*dxF; |
758 |
|
G = ( Gi >> (alpha+rho+2) ) << rho; Gi += 4*dxG; |
759 |
|
|
760 |
|
ri = MTab[F&15]; |
761 |
|
rj = MTab[G&15]; |
762 |
|
|
763 |
|
F >>= 4; |
764 |
|
G >>= 4; |
765 |
|
|
766 |
|
if (F< -1) F=-1; |
767 |
|
else if (F>=W/2) F=W/2; |
768 |
|
if (G< -1) G=-1; |
769 |
|
else if (G>=H/2) G=H/2; |
770 |
|
|
771 |
|
{ |
772 |
|
const int offset = G*stride2 + F; |
773 |
|
uint32_t f0, f1; |
774 |
|
|
775 |
|
f0 = pRef->u[ offset +0 ]; |
776 |
|
f0 |= pRef->u[ offset +1 ] << 16; |
777 |
|
f1 = pRef->u[ offset+stride2 +0 ]; |
778 |
|
f1 |= pRef->u[ offset+stride2 +1 ] << 16; |
779 |
|
f0 = (ri*f0)>>16; |
780 |
|
f1 = (ri*f1) & 0x0fff0000; |
781 |
|
f0 |= f1; |
782 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
783 |
|
|
784 |
|
dstU[I] = (uint8_t)f0; |
785 |
|
|
786 |
|
|
787 |
|
f0 = pRef->v[ offset +0 ]; |
788 |
|
f0 |= pRef->v[ offset +1 ] << 16; |
789 |
|
f1 = pRef->v[ offset+stride2 +0 ]; |
790 |
|
f1 |= pRef->v[ offset+stride2 +1 ] << 16; |
791 |
|
f0 = (ri*f0)>>16; |
792 |
|
f1 = (ri*f1) & 0x0fff0000; |
793 |
|
f0 |= f1; |
794 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
795 |
|
|
796 |
|
dstV[I] = (uint8_t)f0; |
797 |
|
} |
798 |
|
} |
799 |
|
dstU += stride2; |
800 |
|
dstV += stride2; |
801 |
|
} |
802 |
|
|
803 |
|
|
804 |
|
avgMV.x -= 16*((256*mi+120)<<4); // 120 = 15*16/2 |
805 |
|
avgMV.y -= 16*((256*mj+120)<<4); |
806 |
|
|
807 |
|
avgMV.x = RSHIFT( avgMV.x, (4+7-quarterpel) ); |
808 |
|
avgMV.y = RSHIFT( avgMV.y, (4+7-quarterpel) ); |
809 |
|
|
810 |
|
return avgMV; |
811 |
|
} |
812 |
|
|
813 |
|
|
814 |
|
|
815 |
|
#ifdef OLD_GRUEL_GMC |
816 |
void |
void |
817 |
generate_GMCparameters( const int num_wp, // [input]: number of warppoints |
generate_GMCparameters( const int num_wp, // [input]: number of warppoints |
818 |
const int res, // [input]: resolution |
const int res, // [input]: resolution |
1122 |
return avgMV; /* clipping to fcode area is done outside! */ |
return avgMV; /* clipping to fcode area is done outside! */ |
1123 |
} |
} |
1124 |
|
|
1125 |
|
#endif |