📄 decoder.c
字号:
color_e band; /* current color band */ word_t *src, *dst; /* source and destination pointers */ unsigned y; /* current row */ for (band = first_band (frame->color); band <= last_band (frame->color); band++) { src = dst = frame->pixels [band]; for (y = orig_height; y; y--) { memmove (dst, src, orig_width * sizeof (word_t)); dst += orig_width; src += width; } if (format == FORMAT_4_2_0 && band == Y) { orig_width >>= 1; orig_height >>= 1; width >>= 1; } } } } if (dec_timer) dec_timer [2] += prg_timer (&ptimer, STOP); return frame;}image_t *decode_state (unsigned state, unsigned level, wfa_t *wfa)/* * Decode 'state' image of 'wfa' at given 'level'. * * Return value. * pointer to decoded state image * * Side effects: * 'wfa' states > 'state' are removed. */{ word_t *domains [2]; image_t *img = Calloc (1, sizeof (image_t)); /* * Generate a new state with a 1.0 transition to 'state' */ remove_states (state + 1, wfa); append_edge (state + 1, state, 1.0, 0, wfa); wfa->states = state + 2; img->color = NO; img->width = width_of_level (level); img->height = height_of_level (level); img->format = FORMAT_4_4_4; img->pixels [GRAY] = decode_range (state + 1, 0, level, domains, wfa); /* * Copy decoded range to the frame buffer */ { word_t *src, *dst; unsigned y; src = domains [0]; dst = img->pixels [GRAY]; for (y = img->height; y; y--) { memcpy (dst, src, width_of_level (level) * sizeof (word_t)); src += width_of_level (level); dst += img->width; } Free (domains [0]); } return img;}word_t *decode_range (unsigned range_state, unsigned range_label, unsigned range_level, word_t **domain, wfa_t *wfa)/* * Compute 'wfa' image of range (identified by 'state' and 'label') * at 'range_level (works as function decode_image()). * * Return value: * pointer to the pixels in SHORT format * * Side effects: * if 'domain' != NULL then also the domain blocks * of the corresponding range blocks are generated * and returned in domain[] * 'wfa->level_of_state []' is changed */{ unsigned root_state [3]; /* dummy (for alloc_state_images) */ image_t *state_image; /* regenerated state image */ word_t **images; /* pointer to array of pointers to state images */ u_word_t *offsets; /* pointer to array of state image offsets */ word_t *range; enlarge_image (range_level - (wfa->level_of_state [range_state] - 1), FORMAT_4_4_4, -1, wfa); root_state [0] = range_state; state_image = alloc_image (width_of_level (range_level + 1), height_of_level (range_level + 1), NO, FORMAT_4_4_4); alloc_state_images (&images, &offsets, state_image, NULL, range_state, range_level + 1, NO, wfa); compute_state_images (range_level + 1, images, offsets, wfa); range = Calloc (size_of_level (range_level), sizeof (word_t)); if ((range_level & 1) == 0) /* square image */ { memcpy (range, images [range_state + (range_level + 1) * wfa->states] + range_label * size_of_level (range_level), size_of_level (range_level) * sizeof (word_t)); } else /* rectangle */ { word_t *src, *dst; unsigned y; src = images [range_state + (range_level + 1) * wfa->states] + range_label * width_of_level (range_level); dst = range; for (y = height_of_level (range_level); y; y--) { memcpy (dst, src, width_of_level (range_level) * sizeof (word_t)); dst += width_of_level (range_level); src += width_of_level (range_level + 1); } } if (domain != NULL) /* copy domain images */ { int s; /* domain state */ unsigned edge; /* counter */ if (ischild (s = wfa->tree [range_state][range_label])) *domain++ = duplicate_state_image (images [s + (range_level) * wfa->states], offsets [s + (range_level) * wfa->states], range_level); for (edge = 0; isedge (s = wfa->into[range_state][range_label][edge]); edge++) *domain++ = duplicate_state_image (images [s + (range_level) * wfa->states], offsets [s + (range_level) * wfa->states], range_level); *domain = NULL; } free_state_images (range_level + 1, NO, images, offsets, NULL, range_state, NO, wfa); free_image (state_image); return range;}voidsmooth_image (unsigned sf, const wfa_t *wfa, image_t *image)/* * Smooth 'image' along the partitioning boundaries of the 'wfa' * with factor 's'. * * No return value. * * Side effects: * pixel values of the 'image' are modified with respect to 's' */{ int is, inegs; /* integer factors of s and 1 - s*/ unsigned state; unsigned img_width = image->width; unsigned img_height = image->height; real_t s = 1.0 - sf / 200.0; if (s < 0.5 || s >= 1) /* value out of range */ return; is = s * 512 + .5; /* integer representation of s */ inegs = (1 - s) * 512 + .5; /* integer representation of 1 - s */ for (state = wfa->basis_states; state < (wfa->wfainfo->color ? wfa->tree [wfa->root_state][0] : wfa->states); state++) { word_t *bptr = image->pixels [Y]; /* pointer to right or lower line */ unsigned level = wfa->level_of_state[state]; /* level of state image */ unsigned width = width_of_level (level); /* size of state image */ unsigned height = height_of_level (level); /* size of state image */ if (wfa->y [state][1] >= img_height || wfa->x [state][1] >= img_width) continue; /* outside visible area */ if (level % 2) /* horizontal smoothing */ { unsigned i; /* line counter */ word_t *img1; /* pointer to left or upper line */ word_t *img2; /* pointer to right or lower line */ img1 = bptr + (wfa->y [state][1] - 1) * img_width + wfa->x [state][1]; img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; for (i = min (width, img_width - wfa->x [state][1]); i; i--, img1++, img2++) { int tmp = *img1; #ifdef HAVE_SIGNED_SHIFT *img1 = (((is * tmp) >> 10) << 1) + (((inegs * (int) *img2) >> 10) << 1); *img2 = (((is * (int) *img2) >> 10) << 1) + (((inegs * tmp) >> 10) << 1);#else /* not HAVE_SIGNED_SHIFT */ *img1 = (((is * tmp) / 1024) * 2) + (((inegs * (int) *img2) / 1024) * 2); *img2 = (((is * (int) *img2) / 1024) * 2) + (((inegs * tmp) / 1024) *2);#endif /* not HAVE_SIGNED_SHIFT */ } } else /* vertical smoothing */ { unsigned i; /* line counter */ word_t *img1; /* pointer to left or upper line */ word_t *img2; /* pointer to right or lower line */ img1 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1] - 1; img2 = bptr + wfa->y [state][1] * img_width + wfa->x [state][1]; for (i = min (height, img_height - wfa->y [state][1]); i; i--, img1 += img_width, img2 += img_width) { int tmp = *img1; #ifdef HAVE_SIGNED_SHIFT *img1 = (((is * tmp) >> 10) << 1) + (((inegs * (int) *img2) >> 10) << 1); *img2 = (((is * (int) *img2) >> 10) << 1) + (((inegs * tmp) >> 10) << 1);#else /* not HAVE_SIGNED_SHIFT */ *img1 = (((is * tmp) / 1024) * 2) + (((inegs * (int) *img2) / 1024) * 2); *img2 = (((is * (int) *img2) / 1024) * 2) + (((inegs * tmp) / 1024) *2);#endif /* not HAVE_SIGNED_SHIFT */ } } }}/***************************************************************************** private code *****************************************************************************/static voidenlarge_image (int enlarge_factor, format_e format, unsigned y_root, wfa_t *wfa)/* * Enlarge or reduce size of state images by factor 2^'enlarge_factor'. * Use 4:2:0 subsampling if specified by 'format', else use 4:4:4 format. * 'wfa' root state of the first chroma band is given by 'y_root' + 1. * * No return value. * * Side effects: * coordinates of ranges and motion blocks in the WFA structure 'wfa' * are modified. */{ if (enlarge_factor != 0 || format == FORMAT_4_2_0) { unsigned state; if (enlarge_factor == 0) { state = y_root + 1; enlarge_factor = -1; } else state = wfa->basis_states; for (; state < wfa->states; state++) { unsigned label, n; wfa->level_of_state [state] = max (wfa->level_of_state [state] + enlarge_factor * 2, 0); for (label = 0; label < MAXLABELS; label++) if (enlarge_factor > 0) { wfa->x [state][label] <<= enlarge_factor; wfa->y [state][label] <<= enlarge_factor; for (n = enlarge_factor; n; n--) { wfa->mv_tree [state][label].fx *= 2; wfa->mv_tree [state][label].fy *= 2; wfa->mv_tree [state][label].bx *= 2; wfa->mv_tree [state][label].by *= 2; } } else /* enlarge_factor < 0 */ { wfa->x [state][label] >>= - enlarge_factor; wfa->y [state][label] >>= - enlarge_factor; for (n = - enlarge_factor; n; n--) { wfa->mv_tree [state][label].fx /= 2; wfa->mv_tree [state][label].fy /= 2; wfa->mv_tree [state][label].bx /= 2; wfa->mv_tree [state][label].by /= 2; } } if (format == FORMAT_4_2_0 && state == y_root) enlarge_factor--; } }}static voidcompute_actual_size (unsigned luminance_root, unsigned *width, unsigned *height, const wfa_t *wfa)/* * Compute actual size of the frame represented by the given 'wfa'. * (The reconstructed frame may get larger than the original due * to the bintree partitioning.) * If 'luminance_root' < MAXSTATES then the size of chroma ranges (4:2:0). * * Return values: * actual 'width' and 'height' of the decoded frame. */{ unsigned x = 0, y = 0; /* maximum coordinates */ unsigned state; /* counter */ for (state = wfa->basis_states; state < wfa->states; state++) if (isedge (wfa->into [state][0][0]) || isedge (wfa->into [state][1][0])) { unsigned mult = state > luminance_root ? 2 : 1; x = max ((wfa->x [state][0] + width_of_level (wfa->level_of_state [state])) * mult, x); y = max ((wfa->y [state][0] + height_of_level (wfa->level_of_state [state])) * mult, y); } if (x & 1) /* ensure that image size is even */ x++; if (y & 1) y++; *width = x; *height = y;}static voidalloc_state_images (word_t ***images, u_word_t **offsets, const image_t *frame, const unsigned *root_state, unsigned range_state, unsigned max_level, format_e format, const wfa_t *wfa)/* * Generate list of 'wfa' state images which have to be computed for * each level to obtain the decoded 'frame'. 'root_state[]' denotes the * state images of the three color bands. * 'max_level' fives the max. level of a linear combination. * Memory is allocated for every required state image. * Use 4:2:0 subsampling or 4:4:4 'format' for color images. * If 'range_state' > 0 then rather compute image of 'range_state' than * image of 'wfa->root_state'. * * Return values: * '*images' Pointer to array of state image pointers * '*offsets' Pointer to array of state image offsets. * * Side effects: * The arrays given above are filled with useful values. */{ word_t **simg; /* ptr to list of state image ptr's */ u_word_t *offs; /* ptr to list of offsets */ unsigned level; /* counter */ simg = Calloc (wfa->states * (max_level + 1), sizeof (word_t *)); offs = Calloc (wfa->states * (max_level + 1), sizeof (u_word_t)); /* * Initialize buffers for those state images which are at 'max_level'. */ if (range_state > 0) /* a range is given */ { simg [range_state + max_level * wfa->states] = frame->pixels [GRAY]; offs [range_state + max_level * wfa->states] = frame->width; } else { unsigned state; for (state = wfa->basis_states; state <= root_state [Y]; state++) if (wfa->level_of_state [state] == max_level) { simg [state + max_level * wfa->states] = (frame->pixels [Y] + wfa->y [state][0] * frame->width + wfa->x [state][0]); offs [state + max_level * wfa->states] = frame->width; } if (frame->color) { unsigned width = format == FORMAT_4_2_0 ? (frame->width >> 1) : frame->width; for (; state < wfa->states; state++) if (wfa->level_of_state [state] == max_level) { simg [state + max_level * wfa->states] = (frame->pixels [state > root_state [Cb] ? Cr : Cb] + wfa->y [state][0] * width + wfa->x [state][0]); offs [state + max_level * wfa->states] = width; } } } /* * Generate list of state images which must be computed at each level */ for (level = max_level; level > 0; level--) { int child, domain; unsigned state, label, edge; /* * Range approximation with child. */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) if (simg [state + level * wfa->states]) for (label = 0; label < MAXLABELS; label++) if (ischild (child = wfa->tree[state][label])) { if (isedge (wfa->into[state][label][0])) { /* * Allocate new image block. */ simg [child + (level - 1) * wfa->states] = Calloc (size_of_level (level - 1), sizeof (word_t)); offs [child + (level - 1) * wfa->states] = width_of_level (level - 1); } else { /* * Use image block and offset of parent. */ if (level & 1) /* split vertically */ { simg [child + (level - 1) * wfa->states] = (simg [state + level * wfa->states] + label * (height_of_level (level - 1) * offs [state + level * wfa->states])); } else /* split horizontally */ { simg [child + (level - 1) * wfa->states] = (simg [state + level * wfa->states] + label * width_of_level (level - 1)); } offs [child + (level - 1) * wfa->states] = offs [state + level * wfa->states]; } } /* * Range approximation with linear combination */ for (state = 1; state < (range_state > 0 ? range_state + 1 : wfa->states); state++) if (simg [state + level * wfa->states]) for (label = 0; label < MAXLABELS; label++) for (edge = 0; isedge (domain = wfa->into[state][label][edge]); edge++) { if (domain > 0 /* don't allocate memory for state 0 */ && !simg [domain + (level - 1) * wfa->states]) { simg [domain + (level - 1) * wfa->states] = Calloc (size_of_level (level - 1), sizeof (word_t)); offs [domain + (level - 1) * wfa->states] = width_of_level (level - 1); } } } *images = simg; *offsets = offs;}static voidfree_state_images (unsigned max_level, bool_t color, word_t **state_image,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -