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 |
|
|
543 |
|
|
544 |
|
|
545 |
|
|
546 |
|
void generate_GMCparameters( const int num_wp, const int res, |
547 |
|
const WARPPOINTS *const warp, |
548 |
|
const int width, const int height, |
549 |
|
GMC_DATA *const gmc) |
550 |
|
{ |
551 |
|
const int du0 = warp->duv[0].x; |
552 |
|
const int dv0 = warp->duv[0].y; |
553 |
|
const int du1 = warp->duv[1].x; |
554 |
|
const int dv1 = warp->duv[1].y; |
555 |
|
const int du2 = warp->duv[2].x; |
556 |
|
const int dv2 = warp->duv[2].y; |
557 |
|
|
558 |
|
gmc->W = width; |
559 |
|
gmc->H = height; |
560 |
|
|
561 |
|
gmc->rho = 4 - log2bin(res-1); // = {3,2,1,0} for res={2,4,8,16} |
562 |
|
|
563 |
|
gmc->alpha = log2bin(gmc->W-1); |
564 |
|
gmc->Ws = (1 << gmc->alpha); |
565 |
|
|
566 |
|
gmc->dxF = 16*gmc->Ws + RDIV( 8*gmc->Ws*du1, gmc->W ); |
567 |
|
gmc->dxG = RDIV( 8*gmc->Ws*dv1, gmc->W ); |
568 |
|
gmc->Fo = (res*du0 + 1) << (gmc->alpha+gmc->rho-1); |
569 |
|
gmc->Go = (res*dv0 + 1) << (gmc->alpha+gmc->rho-1); |
570 |
|
|
571 |
|
if (num_wp==2) { |
572 |
|
gmc->dyF = -gmc->dxG; |
573 |
|
gmc->dyG = gmc->dxF; |
574 |
|
} |
575 |
|
else if (num_wp==3) { |
576 |
|
gmc->beta = log2bin(gmc->H-1); |
577 |
|
gmc->Hs = (1 << gmc->beta); |
578 |
|
gmc->dyF = RDIV( 8*gmc->Hs*du2, gmc->H ); |
579 |
|
gmc->dyG = 16*gmc->Hs + RDIV( 8*gmc->Hs*dv2, gmc->H ); |
580 |
|
if (gmc->beta > gmc->alpha) { |
581 |
|
gmc->dxF <<= (gmc->beta - gmc->alpha); |
582 |
|
gmc->dxG <<= (gmc->beta - gmc->alpha); |
583 |
|
gmc->alpha = gmc->beta; |
584 |
|
gmc->Ws = 1<< gmc->beta; |
585 |
|
} |
586 |
|
else { |
587 |
|
gmc->dyF <<= gmc->alpha - gmc->beta; |
588 |
|
gmc->dyG <<= gmc->alpha - gmc->beta; |
589 |
|
} |
590 |
|
} |
591 |
|
|
592 |
|
gmc->cFo = gmc->dxF + gmc->dyF + (1 << (gmc->alpha+gmc->rho+1)); |
593 |
|
gmc->cFo += 16*gmc->Ws*(du0-1); |
594 |
|
|
595 |
|
gmc->cGo = gmc->dxG + gmc->dyG + (1 << (gmc->alpha+gmc->rho+1)); |
596 |
|
gmc->cGo += 16*gmc->Ws*(dv0-1); |
597 |
|
} |
598 |
|
|
599 |
|
void |
600 |
|
generate_GMCimage( const GMC_DATA *const gmc_data, // [input] precalculated data |
601 |
|
const IMAGE *const pRef, // [input] |
602 |
|
const int mb_width, |
603 |
|
const int mb_height, |
604 |
|
const int stride, |
605 |
|
const int stride2, |
606 |
|
const int fcode, // [input] some parameters... |
607 |
|
const int32_t quarterpel, // [input] for rounding avgMV |
608 |
|
const int reduced_resolution, // [input] ignored |
609 |
|
const int32_t rounding, // [input] for rounding image data |
610 |
|
MACROBLOCK *const pMBs, // [output] average motion vectors |
611 |
|
IMAGE *const pGMC) // [output] full warped image |
612 |
|
{ |
613 |
|
|
614 |
|
unsigned int mj,mi; |
615 |
|
VECTOR avgMV; |
616 |
|
|
617 |
|
for (mj=0;mj<mb_height;mj++) |
618 |
|
for (mi=0;mi<mb_width; mi++) |
619 |
|
{ |
620 |
|
avgMV = generate_GMCimageMB(gmc_data, pRef, mi, mj, |
621 |
|
stride, stride2, quarterpel, rounding, pGMC); |
622 |
|
|
623 |
|
pMBs[mj*mb_width+mi].amv.x = gmc_sanitize(avgMV.x, quarterpel, fcode); |
624 |
|
pMBs[mj*mb_width+mi].amv.y = gmc_sanitize(avgMV.y, quarterpel, fcode); |
625 |
|
pMBs[mj*mb_width+mi].mcsel = 0; /* until mode decision */ |
626 |
|
} |
627 |
|
} |
628 |
|
|
629 |
|
|
630 |
|
|
631 |
|
#define MLT(i) (((16-(i))<<16) + (i)) |
632 |
|
static const uint32_t MTab[16] = { |
633 |
|
MLT( 0), MLT( 1), MLT( 2), MLT( 3), MLT( 4), MLT( 5), MLT( 6), MLT(7), |
634 |
|
MLT( 8), MLT( 9), MLT(10), MLT(11), MLT(12), MLT(13), MLT(14), MLT(15) |
635 |
|
}; |
636 |
|
#undef MLT |
637 |
|
|
638 |
|
VECTOR generate_GMCimageMB( const GMC_DATA *const gmc_data, |
639 |
|
const IMAGE *const pRef, |
640 |
|
const int mi, const int mj, |
641 |
|
const int stride, |
642 |
|
const int stride2, |
643 |
|
const int quarterpel, |
644 |
|
const int rounding, |
645 |
|
IMAGE *const pGMC) |
646 |
|
{ |
647 |
|
const int W = gmc_data->W; |
648 |
|
const int H = gmc_data->H; |
649 |
|
|
650 |
|
const int rho = gmc_data->rho; |
651 |
|
const int alpha = gmc_data->alpha; |
652 |
|
|
653 |
|
const int rounder = ( 128 - (rounding<<(rho+rho)) ) << 16; |
654 |
|
|
655 |
|
const int dxF = gmc_data->dxF; |
656 |
|
const int dyF = gmc_data->dyF; |
657 |
|
const int dxG = gmc_data->dxG; |
658 |
|
const int dyG = gmc_data->dyG; |
659 |
|
|
660 |
|
uint8_t *dstY, *dstU, *dstV; |
661 |
|
|
662 |
|
int I,J; |
663 |
|
VECTOR avgMV = {0,0}; |
664 |
|
|
665 |
|
int32_t Fj, Gj; |
666 |
|
|
667 |
|
dstY = &pGMC->y[(mj*16)*stride+mi*16] + 16; |
668 |
|
|
669 |
|
Fj = gmc_data->Fo + dyF*mj*16 + dxF*mi*16; |
670 |
|
Gj = gmc_data->Go + dyG*mj*16 + dxG*mi*16; |
671 |
|
for (J=16; J>0; --J) |
672 |
|
{ |
673 |
|
int32_t Fi, Gi; |
674 |
|
|
675 |
|
Fi = Fj; Fj += dyF; |
676 |
|
Gi = Gj; Gj += dyG; |
677 |
|
for (I=-16; I<0; ++I) |
678 |
|
{ |
679 |
|
int32_t F, G; |
680 |
|
uint32_t ri, rj; |
681 |
|
|
682 |
|
F = ( Fi >> (alpha+rho) ) << rho; Fi += dxF; |
683 |
|
G = ( Gi >> (alpha+rho) ) << rho; Gi += dxG; |
684 |
|
|
685 |
|
avgMV.x += F; |
686 |
|
avgMV.y += G; |
687 |
|
|
688 |
|
ri = MTab[F&15]; |
689 |
|
rj = MTab[G&15]; |
690 |
|
|
691 |
|
F >>= 4; |
692 |
|
G >>= 4; |
693 |
|
|
694 |
|
if (F< -1) F=-1; |
695 |
|
else if (F>W) F=W; |
696 |
|
if (G< -1) G=-1; |
697 |
|
else if (G>H) G=H; |
698 |
|
|
699 |
|
{ // MMX-like bilinear... |
700 |
|
const int offset = G*stride + F; |
701 |
|
uint32_t f0, f1; |
702 |
|
f0 = pRef->y[ offset +0 ]; |
703 |
|
f0 |= pRef->y[ offset +1 ] << 16; |
704 |
|
f1 = pRef->y[ offset+stride +0 ]; |
705 |
|
f1 |= pRef->y[ offset+stride +1 ] << 16; |
706 |
|
f0 = (ri*f0)>>16; |
707 |
|
f1 = (ri*f1) & 0x0fff0000; |
708 |
|
f0 |= f1; |
709 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
710 |
|
|
711 |
|
dstY[I] = (uint8_t)f0; |
712 |
|
} |
713 |
|
} |
714 |
|
dstY += stride; |
715 |
|
} |
716 |
|
|
717 |
|
dstU = &pGMC->u[(mj*8)*stride2+mi*8] + 8; |
718 |
|
dstV = &pGMC->v[(mj*8)*stride2+mi*8] + 8; |
719 |
|
|
720 |
|
Fj = gmc_data->cFo + dyF*4 *mj*8 + dxF*4 *mi*8; |
721 |
|
Gj = gmc_data->cGo + dyG*4 *mj*8 + dxG*4 *mi*8; |
722 |
|
for (J=8; J>0; --J) |
723 |
|
{ |
724 |
|
int32_t Fi, Gi; |
725 |
|
Fi = Fj; Fj += 4*dyF; |
726 |
|
Gi = Gj; Gj += 4*dyG; |
727 |
|
|
728 |
|
for (I=-8; I<0; ++I) |
729 |
|
{ |
730 |
|
int32_t F, G; |
731 |
|
uint32_t ri, rj; |
732 |
|
|
733 |
|
F = ( Fi >> (alpha+rho+2) ) << rho; Fi += 4*dxF; |
734 |
|
G = ( Gi >> (alpha+rho+2) ) << rho; Gi += 4*dxG; |
735 |
|
|
736 |
|
ri = MTab[F&15]; |
737 |
|
rj = MTab[G&15]; |
738 |
|
|
739 |
|
F >>= 4; |
740 |
|
G >>= 4; |
741 |
|
|
742 |
|
if (F< -1) F=-1; |
743 |
|
else if (F>=W/2) F=W/2; |
744 |
|
if (G< -1) G=-1; |
745 |
|
else if (G>=H/2) G=H/2; |
746 |
|
|
747 |
|
{ |
748 |
|
const int offset = G*stride2 + F; |
749 |
|
uint32_t f0, f1; |
750 |
|
|
751 |
|
f0 = pRef->u[ offset +0 ]; |
752 |
|
f0 |= pRef->u[ offset +1 ] << 16; |
753 |
|
f1 = pRef->u[ offset+stride2 +0 ]; |
754 |
|
f1 |= pRef->u[ offset+stride2 +1 ] << 16; |
755 |
|
f0 = (ri*f0)>>16; |
756 |
|
f1 = (ri*f1) & 0x0fff0000; |
757 |
|
f0 |= f1; |
758 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
759 |
|
|
760 |
|
dstU[I] = (uint8_t)f0; |
761 |
|
|
762 |
|
|
763 |
|
f0 = pRef->v[ offset +0 ]; |
764 |
|
f0 |= pRef->v[ offset +1 ] << 16; |
765 |
|
f1 = pRef->v[ offset+stride2 +0 ]; |
766 |
|
f1 |= pRef->v[ offset+stride2 +1 ] << 16; |
767 |
|
f0 = (ri*f0)>>16; |
768 |
|
f1 = (ri*f1) & 0x0fff0000; |
769 |
|
f0 |= f1; |
770 |
|
f0 = ( rj*f0 + rounder ) >> 24; |
771 |
|
|
772 |
|
dstV[I] = (uint8_t)f0; |
773 |
|
} |
774 |
|
} |
775 |
|
dstU += stride2; |
776 |
|
dstV += stride2; |
777 |
|
} |
778 |
|
|
779 |
|
|
780 |
|
avgMV.x -= 16*((256*mi+120)<<4); // 120 = 15*16/2 |
781 |
|
avgMV.y -= 16*((256*mj+120)<<4); |
782 |
|
|
783 |
|
avgMV.x = RSHIFT( avgMV.x, (4+7-quarterpel) ); |
784 |
|
avgMV.y = RSHIFT( avgMV.y, (4+7-quarterpel) ); |
785 |
|
|
786 |
|
return avgMV; |
787 |
|
} |
788 |
|
|
789 |
|
|
790 |
|
|
791 |
|
#ifdef OLD_GRUEL_GMC |
792 |
void |
void |
793 |
generate_GMCparameters( const int num_wp, // [input]: number of warppoints |
generate_GMCparameters( const int num_wp, // [input]: number of warppoints |
794 |
const int res, // [input]: resolution |
const int res, // [input]: resolution |
1098 |
return avgMV; /* clipping to fcode area is done outside! */ |
return avgMV; /* clipping to fcode area is done outside! */ |
1099 |
} |
} |
1100 |
|
|
1101 |
|
#endif |