2448 |
|
|
2449 |
iMinSAD = |
iMinSAD = |
2450 |
sad16(cur, |
sad16(cur, |
2451 |
get_ref_mv(pRef, pRefH, pRefV, pRefHV, x, y, 16, currMV, |
get_iref_mv(pRef, x, y, 16, currMV, |
2452 |
iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); |
iEdgedWidth), iEdgedWidth, MV_MAX_ERROR); |
2453 |
iMinSAD += |
iMinSAD += |
2454 |
calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y, |
calc_delta_16(currMV->x - pmv[0].x, currMV->y - pmv[0].y, |
2643 |
void |
void |
2644 |
MotionEstimationBVOP(MBParam * const pParam, |
MotionEstimationBVOP(MBParam * const pParam, |
2645 |
FRAMEINFO * const frame, |
FRAMEINFO * const frame, |
2646 |
|
// const float scalefactor, |
2647 |
// forward (past) reference |
// forward (past) reference |
2648 |
const MACROBLOCK * const f_mbs, |
const MACROBLOCK * const f_mbs, |
2649 |
const IMAGE * const f_ref, |
const IMAGE * const f_ref, |
2657 |
const IMAGE * const b_refV, |
const IMAGE * const b_refV, |
2658 |
const IMAGE * const b_refHV) |
const IMAGE * const b_refHV) |
2659 |
{ |
{ |
2660 |
const uint32_t mb_width = pParam->mb_width; |
const int mb_width = pParam->mb_width; |
2661 |
const uint32_t mb_height = pParam->mb_height; |
const int mb_height = pParam->mb_height; |
2662 |
const int32_t edged_width = pParam->edged_width; |
const int edged_width = pParam->edged_width; |
2663 |
|
|
2664 |
uint32_t i, j; |
const float scalefactor=0.666; |
2665 |
|
int i, j; |
2666 |
int32_t f_sad16; |
|
2667 |
int32_t b_sad16; |
// static const VECTOR zeroMV={0,0}; |
2668 |
int32_t i_sad16; |
|
2669 |
int32_t d_sad16; |
int f_sad16; /* forward (as usual) search */ |
2670 |
int32_t best_sad; |
int b_sad16; /* backward (only in b-frames) search */ |
2671 |
|
int i_sad16; /* interpolated (both direction, b-frames only) */ |
2672 |
|
int d_sad16; /* direct mode (assume linear motion) */ |
2673 |
|
|
2674 |
|
int best_sad; |
2675 |
|
|
2676 |
VECTOR pmv_dontcare; |
VECTOR pmv_dontcare; |
2677 |
|
|
2678 |
|
int f_count=0; |
2679 |
|
int b_count=0; |
2680 |
|
int i_count=0; |
2681 |
|
int d_count=0; |
2682 |
|
int dnv_count=0; |
2683 |
|
int s_count=0; |
2684 |
|
|
2685 |
// note: i==horizontal, j==vertical |
// note: i==horizontal, j==vertical |
2686 |
for (j = 0; j < mb_height; j++) { |
for (j = 0; j < mb_height; j++) { |
2687 |
for (i = 0; i < mb_width; i++) { |
for (i = 0; i < mb_width; i++) { |
2689 |
const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width]; |
const MACROBLOCK *f_mb = &f_mbs[i + j * mb_width]; |
2690 |
const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width]; |
const MACROBLOCK *b_mb = &b_mbs[i + j * mb_width]; |
2691 |
|
|
2692 |
|
VECTOR directMV=b_mb->mvs[0]; /* direct mode: presume linear motion */ |
2693 |
|
|
2694 |
|
/* special case, if collocated block is SKIPed: encoding is forward(0,0) */ |
2695 |
|
|
2696 |
if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 && |
if (b_mb->mode == MODE_INTER && b_mb->cbp == 0 && |
2697 |
b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) { |
b_mb->mvs[0].x == 0 && b_mb->mvs[0].y == 0) { |
2698 |
mb->mode = MODE_NOT_CODED; |
mb->mode = MODE_NOT_CODED; |
2702 |
mb->b_mvs[0].y = 0; |
mb->b_mvs[0].y = 0; |
2703 |
continue; |
continue; |
2704 |
} |
} |
|
/* force F_SAD16 |
|
|
f_sad16 = 100; |
|
|
b_sad16 = 65535; |
|
2705 |
|
|
2706 |
mb->mode = MODE_FORWARD; |
/* candidates for best MV assumes linear motion */ |
2707 |
mb->mvs[0].x = 1; |
/* next vector is linearly scaled (factor depends on distance to that frame) */ |
|
mb->mvs[0].y = 1; |
|
|
mb->b_mvs[0].x = 1; |
|
|
mb->b_mvs[0].y = 1; |
|
|
continue; |
|
|
^^ force F_SAD16 */ |
|
2708 |
|
|
2709 |
|
mb->mvs[0].x = (int)(directMV.x * scalefactor + 0.75); |
2710 |
|
mb->mvs[0].y = (int)(directMV.y * scalefactor + 0.75); |
2711 |
|
|
2712 |
|
mb->b_mvs[0].x = (int)(directMV.x * (scalefactor-1.) + 0.75); /* opposite direction! */ |
2713 |
|
mb->b_mvs[0].y = (int)(directMV.y * (scalefactor-1.) + 0.75); |
2714 |
|
|
2715 |
|
DEBUG2("last: ",f_mb->mvs[0].x,f_mb->mvs[0].y); |
2716 |
|
DEBUG2("next: ",b_mb->mvs[0].x,b_mb->mvs[0].y); |
2717 |
|
DEBUG2("directF: ",mb->mvs[0].x,mb->mvs[0].y); |
2718 |
|
DEBUG2("directB: ",mb->b_mvs[0].x,mb->b_mvs[0].y); |
2719 |
|
|
2720 |
|
d_sad16 = |
2721 |
|
sad16bi(frame->image.y + i * 16 + j * 16 * edged_width, |
2722 |
|
get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
2723 |
|
i, j, 16, &mb->mvs[0], edged_width), |
2724 |
|
get_ref_mv(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
2725 |
|
i, j, 16, &mb->b_mvs[0], edged_width), |
2726 |
|
edged_width); |
2727 |
|
|
2728 |
// forward search |
// forward search |
2729 |
f_sad16 = |
f_sad16 = SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
|
SEARCH16(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
|
2730 |
&frame->image, i, j, frame->motion_flags, |
&frame->image, i, j, frame->motion_flags, |
2731 |
frame->quant, frame->fcode, pParam, |
frame->quant, frame->fcode, pParam, |
2732 |
f_mbs, f_mbs, /* todo */ |
f_mbs, f_mbs, /* todo */ |
2733 |
&mb->mvs[0], &pmv_dontcare); // ignore pmv |
&mb->mvs[0], &pmv_dontcare); // ignore pmv (why?) |
2734 |
|
|
2735 |
|
|
2736 |
// backward search |
// backward search |
2737 |
b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
b_sad16 = SEARCH16(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
2740 |
b_mbs, b_mbs, /* todo */ |
b_mbs, b_mbs, /* todo */ |
2741 |
&mb->b_mvs[0], &pmv_dontcare); // ignore pmv |
&mb->b_mvs[0], &pmv_dontcare); // ignore pmv |
2742 |
|
|
|
// interpolate search (simple, but effective) |
|
|
i_sad16 = 65535; |
|
|
|
|
|
/* |
|
|
x/y range somewhat buggy |
|
2743 |
i_sad16 = |
i_sad16 = |
2744 |
sad16bi_c(frame->image.y + i * 16 + j * 16 * edged_width, |
sad16bi(frame->image.y + i * 16 + j * 16 * edged_width, |
2745 |
get_ref(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
get_ref_mv(f_ref->y, f_refH->y, f_refV->y, f_refHV->y, |
2746 |
i, j, 16, mb->mvs[0].x, mb->mvs[0].y, |
i, j, 16, &mb->mvs[0], edged_width), |
2747 |
edged_width), get_ref(b_ref->y, b_refH->y, |
get_ref(b_ref->y, b_refH->y, b_refV->y, b_refHV->y, |
2748 |
b_refV->y, b_refHV->y, |
i, j, 16, -mb->b_mvs[0].x, -mb->b_mvs[0].y, edged_width), |
|
i, j, 16, |
|
|
mb->b_mvs[0].x, |
|
|
mb->b_mvs[0].x, |
|
|
edged_width), |
|
2749 |
edged_width); |
edged_width); |
|
*/ |
|
2750 |
|
|
2751 |
// TODO: direct search |
// TODO: direct search |
2752 |
// predictor + range of [-32,32] |
// predictor + range of [-32,32] |
|
d_sad16 = 65535; |
|
2753 |
|
|
2754 |
|
DEBUG2("f_MV: ",mb->mvs[0].x,mb->mvs[0].y); |
2755 |
|
DEBUG2("b_MV: ",mb->b_mvs[0].x,mb->b_mvs[0].y); |
2756 |
|
|
2757 |
|
/* fprintf(stderr,"f_sad16 = %d, b_sad16 = %d, i_sad16 = %d, d_sad16 = %d\n", |
2758 |
|
f_sad16,b_sad16,i_sad16,d_sad16); |
2759 |
|
*/ |
2760 |
|
|
2761 |
|
// d_sad16 -= 50; |
2762 |
|
// d_sad16 = 65535; |
2763 |
|
// i_sad16 = 65535; |
2764 |
|
// b_sad16 = 65535; |
2765 |
|
|
2766 |
if (f_sad16 < b_sad16) { |
if (f_sad16 < b_sad16) { |
2767 |
best_sad = f_sad16; |
best_sad = f_sad16; |
2778 |
|
|
2779 |
if (d_sad16 < best_sad) { |
if (d_sad16 < best_sad) { |
2780 |
best_sad = d_sad16; |
best_sad = d_sad16; |
2781 |
mb->mode = MODE_DIRECT; |
mb->mode = MODE_DIRECT_NONE_MV; |
2782 |
|
} |
2783 |
|
|
2784 |
|
switch (mb->mode) |
2785 |
|
{ |
2786 |
|
case MODE_FORWARD: |
2787 |
|
f_count++; break; |
2788 |
|
case MODE_BACKWARD: |
2789 |
|
b_count++; break; |
2790 |
|
case MODE_INTERPOLATE: |
2791 |
|
i_count++; break; |
2792 |
|
case MODE_DIRECT: |
2793 |
|
d_count++; break; |
2794 |
|
case MODE_DIRECT_NONE_MV: |
2795 |
|
dnv_count++; break; |
2796 |
|
default: |
2797 |
|
s_count++; break; |
2798 |
} |
} |
2799 |
|
|
2800 |
} |
} |
2801 |
} |
} |
2802 |
|
|
2803 |
|
#ifdef _DEBUG_BFRAME_STAT |
2804 |
|
fprintf(stderr,"B-Stat: F: %04d B: %04d I: %04d D0: %04d D: %04d S: %04d\n", |
2805 |
|
f_count,b_count,i_count,dnv_count,d_count,s_count); |
2806 |
|
#endif |
2807 |
|
|
2808 |
} |
} |