📄 mwfa.c
字号:
*/ if (icosts1 < icosts2) { ifx = fx; ify = fy; interp_bits = forward_bits + ibackward_bits; interp_costs = icosts1; } else { ibx = bx; iby = by; interp_bits = iforward_bits + backward_bits; interp_costs = icosts2; } } else /* local exhaustive search */ { /* * Keep forward and backward mv due to time constraints */ ifx = fx; ify = fy; ibx = bx; iby = by; interp_bits = forward_bits + backward_bits; extract_mc_block (mcblock1, width, height, mt->past->pixels [GRAY], mt->past->width, wi->half_pixel, range->x, range->y, fx, fy); extract_mc_block (mcblock2, width, height, mt->future->pixels [GRAY], mt->future->width, wi->half_pixel, range->x, range->y, bx, by); interp_costs = mcpe_norm (mt->original, range->x, range->y, width, height, mcblock1, mcblock2) + (interp_bits + 2) * price; /* code 01 */ } /* * Choose alternative with smallest costs */ if (forward_costs <= interp_costs) { if (forward_costs <= backward_costs) mctype = FORWARD; else mctype = BACKWARD; } else { if (backward_costs <= interp_costs) mctype = BACKWARD; else mctype = INTERPOLATED; } switch (mctype) { case FORWARD: range->mv_tree_bits = 3; range->mv_coord_bits = forward_bits; range->mv.type = FORWARD; range->mv.fx = fx; range->mv.fy = fy; extract_mc_block (mcblock1, width, height, mt->past->pixels [GRAY], mt->past->width, wi->half_pixel, range->x, range->y, range->mv.fx, range->mv.fy); get_mcpe (mcpe, mt->original, range->x, range->y, width, height, mcblock1, NULL); break; case BACKWARD: range->mv_tree_bits = 3; range->mv_coord_bits = backward_bits; range->mv.type = BACKWARD; range->mv.bx = bx; range->mv.by = by; extract_mc_block (mcblock1, width, height, mt->future->pixels [GRAY], mt->future->width, wi->half_pixel, range->x, range->y, range->mv.bx, range->mv.by); get_mcpe (mcpe, mt->original, range->x, range->y, width, height, mcblock1, NULL); break; case INTERPOLATED: range->mv_tree_bits = 2; range->mv_coord_bits = interp_bits; range->mv.type = INTERPOLATED; range->mv.fx = ifx; range->mv.fy = ify; range->mv.bx = ibx; range->mv.by = iby; extract_mc_block (mcblock1, width, height, mt->past->pixels [GRAY], mt->past->width, wi->half_pixel, range->x, range->y, range->mv.fx, range->mv.fy); extract_mc_block (mcblock2, width, height, mt->future->pixels [GRAY], mt->future->width, wi->half_pixel, range->x, range->y, range->mv.bx, range->mv.by); get_mcpe (mcpe, mt->original, range->x, range->y, width, height, mcblock1, mcblock2); break; default: break; } Free (mcblock1); Free (mcblock2);}voidfill_norms_table (unsigned x0, unsigned y0, unsigned level, const wfa_info_t *wi, motion_t *mt)/* * Compute norms of difference images for all possible displacements * in 'mc_forward_norm' and 'mc_backward_norm'. * * No return value. * * Side effects: * 'mt->mc_backward_norms' are computed * 'mt->mc_forward_norms' are computed */{ int mx, my; /* coordinates of motion vector */ unsigned sr; /* mv search range +-'sr' pixels */ unsigned index = 0; /* index of motion vector */ unsigned width = width_of_level (level); unsigned height = height_of_level (level); word_t *mcblock = Calloc (width * height, sizeof (word_t)); sr = wi->half_pixel ? wi->search_range / 2 : wi->search_range; for (my = -sr; my < (int) sr; my++) for (mx = -sr; mx < (int) sr; mx++, index++) { if ((int) x0 + mx < 0 || /* block outside visible area */ x0 + mx + width > mt->original->width || (int) y0 + my < 0 || y0 + my + height > mt->original->height) { mt->mc_forward_norms [level][index] = 0.0; mt->mc_backward_norms [level][index] = 0.0; } else { extract_mc_block (mcblock, width, height, mt->past->pixels [GRAY], mt->past->width, wi->half_pixel, x0, y0, mx, my); mt->mc_forward_norms [level][index] = mcpe_norm (mt->original, x0, y0, width, height, mcblock, NULL); if (mt->frame_type == B_FRAME) { extract_mc_block (mcblock, width, height, mt->future->pixels [GRAY], mt->future->width, wi->half_pixel, x0, y0, mx, my); mt->mc_backward_norms[level][index] = mcpe_norm (mt->original, x0, y0, width, height, mcblock, NULL); } } } Free (mcblock);}/***************************************************************************** private code *****************************************************************************/static voidget_mcpe (word_t *mcpe, const image_t *original, unsigned x0, unsigned y0, unsigned width, unsigned height, const word_t *mcblock1, const word_t *mcblock2)/* * Compute MCPE image 'original' - reference. The reference is either * composed of 'mcblock1' or of ('mcblock1' + 'mcblock2') / 2 (if * 'mcblock2' != NULL). Coordinates of original block are given by * 'x0', 'y0', 'width', and 'height'. * * No return value. * * Side effects: * 'mcpe []' is filled with the delta image */{ const word_t *oblock; /* pointer to original image */ assert (mcpe); oblock = original->pixels [GRAY] + y0 * original->width + x0; if (mcblock2 != NULL) /* interpolated prediction */ { unsigned x, y; /* current coordinates */ for (y = height; y; y--) { for (x = width; x; x--) *mcpe++ = *oblock++ - (*mcblock1++ + *mcblock2++) / 2; oblock += original->width - width; } } else /* forward or backward prediction */ { unsigned x, y; /* current coordinates */ for (y = height; y; y--) { for (x = width; x; x--) *mcpe++ = *oblock++ - *mcblock1++; oblock += original->width - width; } }}static real_tmcpe_norm (const image_t *original, unsigned x0, unsigned y0, unsigned width, unsigned height, const word_t *mcblock1, const word_t *mcblock2)/* * Compute norm of motion compensation prediction error. * Coordinates of 'original' block are given by ('x0', 'y0') * and 'width', 'height'. * Reference blocks are stored in 'mcimage1' and 'mcimage2'. * * Return value: * square of norm of difference image */{ unsigned n; real_t norm = 0; word_t *mcpe = Calloc (width * height, sizeof (word_t)); word_t *ptr = mcpe; get_mcpe (mcpe, original, x0, y0, width, height, mcblock1, mcblock2); for (n = height * width; n; n--, ptr++) norm += square (*ptr / 16); Free (mcpe); return norm;}static real_t find_best_mv (real_t price, const image_t *original, const image_t *reference, unsigned x0, unsigned y0, unsigned width, unsigned height, real_t *bits, int *mx, int *my, const real_t *mc_norms, const wfa_info_t *wi, const motion_t *mt)/* * Find best matching motion vector in image 'reference' to predict * the block ('x0', 'y0') of size 'width'x'height in image 'original'. * * Return values: * prediction costs * * Side effects: * 'mx', 'my' coordinates of motion vector * 'bits' number of bits to encode mv */{ unsigned sr; /* mv search range +/- 'sr' pixels */ unsigned index; /* index of motion vector */ int x, y; /* coordinates of motion vector */ real_t costs; /* costs arising if mv is chosen */ real_t mincosts = MAXCOSTS; /* best costs so far */ unsigned bitshift; /* half_pixel coordinates multiplier */ *mx = *my = 0; /* * Find best fitting motion vector: * Use exhaustive search in the interval x,y +- sr (no halfpixel accuracy) * or x,y +- sr/2 (halfpixel accuracy) */ sr = wi->half_pixel ? wi->search_range / 2 : wi->search_range; bitshift = (wi->half_pixel ? 2 : 1); /* bit0 reserved for halfpixel pred. */ for (index = 0, y = -sr; y < (int) sr; y++) for (x = -sr; x < (int) sr; x++, index++) if ((int) x0 + x >= 0 && (int) y0 + y >= 0 && x0 + x + width <= original->width && y0 + y + height <= original->height) { /* * Block is inside visible area. * Compare current costs with 'mincosts' */ costs = mc_norms [index] + (mt->xbits [(x + sr) * bitshift] + mt->ybits [(y + sr) * bitshift]) * price; if (costs < mincosts) { mincosts = costs; *mx = x * bitshift; *my = y * bitshift; } } /* * Halfpixel prediction: * Compare all nine combinations (-1, y), (0, y), (+1, y) for y = -1,0,+1 */ if (wi->half_pixel) { int rx, ry; /* halfpixel refinement */ unsigned bestrx, bestry; /* coordinates of best mv */ word_t *mcblock = Calloc (width * height, sizeof (word_t)); bestrx = bestry = 0; for (rx = -1; rx <= 1; rx++) for (ry = -1; ry <= 1; ry++) { /* * Check if the new motion vector is in allowed area */ if (rx == 0 && ry == 0) /* already tested */ continue; if ((int) x0 + (*mx / 2) + rx < 0 || /* outside visible area */ x0 + (*mx / 2) + rx + width > original->width || (int) y0 + (*my / 2) + ry < 0 || y0 + (*my / 2) + ry + height > original->height) continue; if (*mx + rx < (int) -sr || *mx + rx >= (int) sr || *my + ry < (int) -sr || *my + ry >= (int) sr) continue; /* out of bounds */ /* * Compute costs of new motion compensation */ extract_mc_block (mcblock, width, height, reference->pixels [GRAY], reference->width, wi->half_pixel, x0, y0, *mx + rx, *my + ry); costs = mcpe_norm (mt->original, x0, y0, width, height, mcblock, NULL) + (mt->xbits [*mx + rx + sr * bitshift] + mt->ybits [*my + ry + sr * bitshift]) * price; if (costs < mincosts) { bestrx = rx; bestry = ry; mincosts = costs; } } *mx += bestrx; *my += bestry; Free (mcblock); } /* halfpixel */ *bits = mt->xbits [*mx + sr * bitshift] + mt->ybits [*my + sr * bitshift]; return mincosts;}static real_tfind_second_mv (real_t price, const image_t *original, const image_t *reference, const word_t *mcblock1, unsigned xr, unsigned yr, unsigned width, unsigned height, real_t *bits, int *mx, int *my, const wfa_info_t *wi, const motion_t *mt)/* * Search local area (*mx,*my) for best additional mv. * Overwrite mt->tmpblock. * TODO check sr = search_range * * Return values: * prediction costs * * Side effects: * 'mx','my' coordinates of mv * 'bits' number of bits to encode mv */{ real_t mincosts = MAXCOSTS; /* best costs so far */ unsigned sr; /* MV search range +/- 'sr' pixels */ int x, y; /* coordinates of motion vector */ int y0, y1, x0, x1; /* start/end coord. of search range */ unsigned bitshift; /* half_pixel coordinates multiplier */ word_t *mcblock2 = Calloc (width * height, sizeof (word_t)); sr = wi->search_range; y0 = max ((int) -sr, *my - (int) local_range); y1 = min ((int) sr, *my + (int) local_range); x0 = max ((int) -sr, *mx - (int) local_range); x1 = min ((int) sr, *mx + (int) local_range); *mx = *my = 0; bitshift = (wi->half_pixel ? 2 : 1); /* bit0 reserved for halfpixel pred. */ for (y = y0; y < y1; y++) for (x = x0; x < x1; x++) { real_t costs; /* costs arising if mv is chosen */ /* * Test each mv ('x', 'y') in the given search range: * Get the new motion compensation image from 'reference' and compute * the norm of the motion compensation prediction error * 'original' - 0.5 * ('firstmc' + 'reference') */ if ((int) (xr * bitshift) + x < 0 || /* outside visible area */ xr * bitshift + x > (original->width - width) * bitshift || (int) (yr * bitshift) + y < 0 || yr * bitshift + y > (original->height - height) * bitshift) continue; extract_mc_block (mcblock2, width, height, reference->pixels [GRAY], reference->width, wi->half_pixel, x0, y0, x, y); costs = mcpe_norm (mt->original, x0, y0, width, height, mcblock1, mcblock2) + (mt->xbits [x + sr] + mt->ybits [y + sr]) * price; if (costs < mincosts) { mincosts = costs; *mx = x; *my = y; } } *bits = mt->xbits [*mx + sr] + mt->ybits [*my + sr]; Free (mcblock2); return mincosts;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -