📄 mwfa.c
字号:
/* * mwfa.c: Initialization of MWFA coder * * Written by: Michael Unger * Ullrich Hafner * * This file is part of FIASCO (獸籸actal 獻籱age 獳籲d 玈籩quence 獵O籨ec) * Copyright (C) 1994-2000 Ullrich Hafner <hafner@bigfoot.de> *//* * $Date: 2000/06/14 20:50:51 $ * $Author: hafner $ * $Revision: 5.1 $ * $State: Exp $ */#include "config.h"#include <ctype.h>#if HAVE_STRING_H# include <string.h>#else /* not HAVE_STRING_H */# include <strings.h>#endif /* not HAVE_STRING_H */#include "types.h"#include "macros.h"#include "error.h"#include "misc.h"#include "cwfa.h"#include "image.h"#include "mwfa.h"#include "motion.h"/***************************************************************************** local variables *****************************************************************************/unsigned mv_code_table [33][2] =/* * MPEG's huffman code for vector components. Format: code_value, length */{ {0x19, 11}, {0x1b, 11}, {0x1d, 11}, {0x1f, 11}, {0x21, 11}, {0x23, 11}, {0x13, 10}, {0x15, 10}, {0x17, 10}, {0x7, 8}, {0x9, 8}, {0xb, 8}, {0x7, 7}, {0x3, 5}, {0x3, 4}, {0x3, 3}, {0x1, 1}, {0x2, 3}, {0x2, 4}, {0x2, 5}, {0x6, 7}, {0xa, 8}, {0x8, 8}, {0x6, 8}, {0x16, 10}, {0x14, 10}, {0x12, 10}, {0x22, 11}, {0x20, 11}, {0x1e, 11}, {0x1c, 11}, {0x1a, 11}, {0x18, 11}};static const unsigned local_range = 6;/***************************************************************************** prototypes *****************************************************************************/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);static real_tmcpe_norm (const image_t *original, unsigned x0, unsigned y0, unsigned width, unsigned height, const word_t *mcblock1, const word_t *mcblock2);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);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);/***************************************************************************** public code *****************************************************************************/motion_t *alloc_motion (const wfa_info_t *wi)/* * Motion structure constructor. * Allocate memory for the motion structure and * fill in default values specified by 'wi'. * * Return value: * pointer to the new option structure or NULL on error */{ int dx; /* motion vector coordinate */ unsigned level; unsigned range_size = wi->half_pixel ? square (wi->search_range) : square (2 * wi->search_range); motion_t *mt = Calloc (1, sizeof (motion_t)); mt->original = NULL; mt->past = NULL; mt->future = NULL; mt->xbits = Calloc (2 * wi->search_range, sizeof (real_t)); mt->ybits = Calloc (2 * wi->search_range, sizeof (real_t)); for (dx = -wi->search_range; dx < (int) wi->search_range; dx++) { mt->xbits [dx + wi->search_range] = mt->ybits [dx + wi->search_range] = mv_code_table [dx + wi->search_range][1]; } mt->mc_forward_norms = Calloc (MAXLEVEL, sizeof (real_t *)); mt->mc_backward_norms = Calloc (MAXLEVEL, sizeof (real_t *)); for (level = wi->p_min_level; level <= wi->p_max_level; level++) { mt->mc_forward_norms [level] = Calloc (range_size, sizeof (real_t)); mt->mc_backward_norms [level] = Calloc (range_size, sizeof (real_t)); } return mt;}voidfree_motion (motion_t *mt)/* * Motion struct destructor: * Free memory of 'motion' struct. * * No return value. * * Side effects: * structure 'motion' is discarded. */{ unsigned level; Free (mt->xbits); Free (mt->ybits); for (level = 0; level < MAXLEVEL; level++) { if (mt->mc_forward_norms [level]) Free (mt->mc_forward_norms [level]); if (mt->mc_backward_norms [level]) Free (mt->mc_backward_norms [level]); } Free (mt->mc_forward_norms); Free (mt->mc_backward_norms); Free (mt);}voidsubtract_mc (image_t *image, const image_t *past, const image_t *future, const wfa_t *wfa)/* * Subtract motion compensation from chrom channels of 'image'. * Reference frames are given by 'past' and 'future'. * * No return values. */{ unsigned state, label; word_t *mcblock1 = Calloc (size_of_level (wfa->wfainfo->p_max_level), sizeof (word_t)); word_t *mcblock2 = Calloc (size_of_level (wfa->wfainfo->p_max_level), sizeof (word_t)); for (state = wfa->basis_states; state < wfa->states; state++) for (label = 0; label < MAXLABELS; label++) if (wfa->mv_tree [state][label].type != NONE) { color_e band; /* current color band */ unsigned width, height; /* size of mcblock */ unsigned offset; /* remaining pixels in original */ width = width_of_level (wfa->level_of_state [state] - 1); height = height_of_level (wfa->level_of_state [state] - 1); offset = image->width - width; switch (wfa->mv_tree [state][label].type) { case FORWARD: for (band = first_band (image->color) + 1; band <= last_band (image->color); band++) { unsigned y; /* row of block */ word_t *mc1; /* pixel in MC block 1 */ word_t *orig; /* pixel in original image */ extract_mc_block (mcblock1, width, height, past->pixels [band], past->width, wfa->wfainfo->half_pixel, wfa->x [state][label], wfa->y [state][label], (wfa->mv_tree [state][label].fx / 2) * 2, (wfa->mv_tree [state][label].fy / 2) * 2); mc1 = mcblock1; orig = image->pixels [band] + wfa->x [state][label] + wfa->y [state][label] * image->width; for (y = height; y; y--) { unsigned x; /* column of block */ for (x = width; x; x--) *orig++ -= *mc1++; orig += offset; } } break; case BACKWARD: for (band = first_band (image->color) + 1; band <= last_band (image->color); band++) { unsigned y; /* row of block */ word_t *mc1; /* pixel in MC block 1 */ word_t *orig; /* pixel in original image */ extract_mc_block (mcblock1, width, height, future->pixels [band], future->width, wfa->wfainfo->half_pixel, wfa->x [state][label], wfa->y [state][label], (wfa->mv_tree [state][label].bx / 2) * 2, (wfa->mv_tree [state][label].by / 2) * 2); mc1 = mcblock1; orig = image->pixels [band] + wfa->x [state][label] + wfa->y [state][label] * image->width; for (y = height; y; y--) { unsigned x; /* column of block */ for (x = width; x; x--) *orig++ -= *mc1++; orig += offset; } } break; case INTERPOLATED: for (band = first_band (image->color) + 1; band <= last_band (image->color); band++) { unsigned y; /* row of block */ word_t *mc1; /* pixel in MC block 1 */ word_t *mc2; /* pixel in MC block 2 */ word_t *orig; /* pixel in original image */ extract_mc_block (mcblock1, width, height, past->pixels [band], past->width, wfa->wfainfo->half_pixel, wfa->x [state][label], wfa->y [state][label], (wfa->mv_tree[state][label].fx / 2) * 2, (wfa->mv_tree[state][label].fy / 2) * 2); extract_mc_block (mcblock2, width, height, future->pixels [band], future->width, wfa->wfainfo->half_pixel, wfa->x [state][label], wfa->y [state][label], (wfa->mv_tree[state][label].bx / 2) * 2, (wfa->mv_tree[state][label].by / 2) * 2); mc1 = mcblock1; mc2 = mcblock2; orig = image->pixels [band] + wfa->x [state][label] + wfa->y [state][label] * image->width; for (y = height; y; y--) { unsigned x; /* column of block */ for (x = width; x; x--) *orig++ -= (*mc1++ + *mc2++) / 2; orig += offset; } } break; default: break; } } Free (mcblock1); Free (mcblock2);}voidfind_P_frame_mc (word_t *mcpe, real_t price, range_t *range, const wfa_info_t *wi, const motion_t *mt)/* * Determine best motion vector for P-frame. * * No return value. * * Side effects: * range->mvt_bits (# of mv-tree bits) * range->mvxybits (# of bits for vector components) * mt->mcpe (MCPE in scan-order) */{ unsigned width = width_of_level (range->level); unsigned height = height_of_level (range->level); word_t *mcblock = Calloc (width * height, sizeof (word_t)); range->mv_tree_bits = 1; range->mv.type = FORWARD; /* * Find best matching forward prediction */ find_best_mv (price, mt->original, mt->past, range->x, range->y, width, height, &range->mv_coord_bits, &range->mv.fx, &range->mv.fy, mt->mc_forward_norms [range->level], wi, mt); /* * Compute MCPE */ extract_mc_block (mcblock, 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, mcblock, NULL); Free (mcblock);}voidfind_B_frame_mc (word_t *mcpe, real_t price, range_t *range, const wfa_info_t *wi, const motion_t *mt)/* * Determines best motion compensation for B-frame. * Steps: * 1) find best forward motion vector * 2) find best backward motion vector * 3) try both motion vectors together (interpolation) * 4) choose best mode (FORWARD, BACKWARD or INTERPOLATED) * Bitcodes: * FORWARD 000 * BACKWARD 001 * INTERPOLATED 01 * * Return values: * range->mvt_bits (# of mv-tree bits) * range->mvxybits (# of bits for vector components) * mt->mcpe (MCPE in scan-order) */{ mc_type_e mctype; /* type of motion compensation */ real_t forward_costs; /* costs of FORWARD mc */ real_t backward_costs; /* costs of BACKWARD mc */ real_t interp_costs; /* costs of INTERPOLATED mc */ real_t forward_bits; /* bits for FORWARD mc */ real_t backward_bits; /* bits for BACKWARD mc */ real_t interp_bits; /* bits for INTERPOLATED mc */ int fx, fy; /* coordinates FORWARD mc */ int bx, by; /* coordinates BACKWARD mc */ int ifx, ify; /* coordinates forw. INTERPOLATED mc */ int ibx, iby; /* coordinates back. INTERPOLATED mc */ unsigned width = width_of_level (range->level); unsigned height = height_of_level (range->level); word_t *mcblock1 = Calloc (width * height, sizeof (word_t)); word_t *mcblock2 = Calloc (width * height, sizeof (word_t)); /* * Forward interpolation: use past frame as reference */ forward_costs = find_best_mv (price, mt->original, mt->past, range->x, range->y, width, height, &forward_bits, &fx, &fy, mt->mc_forward_norms [range->level], wi, mt) + 3 * price; /* code 000 */ /* * Backward interpolation: use future frame as reference */ backward_costs = find_best_mv (price, mt->original, mt->future, range->x, range->y, width, height, &backward_bits, &bx, &by, mt->mc_backward_norms [range->level], wi, mt) + 3 * price; /* code 001 */ /* * Bidirectional interpolation: use both past and future frame as reference */ if (wi->cross_B_search) { real_t icosts1; /* costs interpolation alternative 1 */ real_t icosts2; /* costs interpolation alternative 2 */ real_t ibackward_bits; /* additional bits alternative 1 */ real_t iforward_bits; /* additional bits alternative 1 */ /* * Alternative 1: keep forward mv and vary backward mv locally */ extract_mc_block (mcblock1, width, height, mt->past->pixels [GRAY], mt->past->width, wi->half_pixel, range->x, range->y, fx, fy); ibx = bx; /* start with backward coordinates */ iby = by; icosts1 = find_second_mv (price, mt->original, mt->future, mcblock1, range->x, range->y, width, height, &ibackward_bits, &ibx, &iby, wi, mt) + (forward_bits + 2) * price; /* code 01 */ /* * Alternative 2: Keep backward mv and vary forward mv locally */ extract_mc_block (mcblock1, width, height, mt->future->pixels [GRAY], mt->future->width, wi->half_pixel, range->x, range->y, bx, by); ifx = fx; ify = fy; icosts2 = find_second_mv (price, mt->original, mt->past, mcblock1, range->x, range->y, width, height, &iforward_bits, &ifx, &ify, wi, mt) + (backward_bits + 2) * price; /* code 01 */ /* * Choose best alternative
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -