// Identical to aom_clpf_detect_c() apart from "rec" and "org". void aom_clpf_detect_hbd_c(const uint16_t *rec, const uint16_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum0, int *sum1, unsigned int strength, int size, unsigned int bd) { const int shift = bd - 8; int x, y; for (y = y0; y < y0 + size; y++) { for (x = x0; x < x0 + size; x++) { const int O = org[y * ostride + x] >> shift; const int X = rec[y * rstride + x] >> shift; const int A = rec[AOMMAX(0, y - 2) * rstride + x] >> shift; const int B = rec[AOMMAX(0, y - 1) * rstride + x] >> shift; const int C = rec[y * rstride + AOMMAX(0, x - 2)] >> shift; const int D = rec[y * rstride + AOMMAX(0, x - 1)] >> shift; const int E = rec[y * rstride + AOMMIN(width - 1, x + 1)] >> shift; const int F = rec[y * rstride + AOMMIN(width - 1, x + 2)] >> shift; const int G = rec[AOMMIN(height - 1, y + 1) * rstride + x] >> shift; const int H = rec[AOMMIN(height - 1, y + 2) * rstride + x] >> shift; const int delta = av1_clpf_sample(X, A, B, C, D, E, F, G, H, strength >> shift, bd - shift); const int Y = X + delta; *sum0 += (O - X) * (O - X); *sum1 += (O - Y) * (O - Y); } } }
void aom_clpf_detect_multi_c(const uint8_t *rec, const uint8_t *org, int rstride, int ostride, int x0, int y0, int width, int height, int *sum, int size, unsigned int bd) { int x, y; for (y = y0; y < y0 + size; y++) { for (x = x0; x < x0 + size; x++) { const int O = org[y * ostride + x]; const int X = rec[y * rstride + x]; const int A = rec[AOMMAX(0, y - 2) * rstride + x]; const int B = rec[AOMMAX(0, y - 1) * rstride + x]; const int C = rec[y * rstride + AOMMAX(0, x - 2)]; const int D = rec[y * rstride + AOMMAX(0, x - 1)]; const int E = rec[y * rstride + AOMMIN(width - 1, x + 1)]; const int F = rec[y * rstride + AOMMIN(width - 1, x + 2)]; const int G = rec[AOMMIN(height - 1, y + 1) * rstride + x]; const int H = rec[AOMMIN(height - 1, y + 2) * rstride + x]; const int delta1 = av1_clpf_sample(X, A, B, C, D, E, F, G, H, 1, bd); const int delta2 = av1_clpf_sample(X, A, B, C, D, E, F, G, H, 2, bd); const int delta3 = av1_clpf_sample(X, A, B, C, D, E, F, G, H, 4, bd); const int F1 = X + delta1; const int F2 = X + delta2; const int F3 = X + delta3; sum[0] += (O - X) * (O - X); sum[1] += (O - F1) * (O - F1); sum[2] += (O - F2) * (O - F2); sum[3] += (O - F3) * (O - F3); } } }
void aom_noise_tx_filter(struct aom_noise_tx_t *noise_tx, const float *psd) { const int block_size = noise_tx->block_size; const float kBeta = 1.1f; const float kEps = 1e-6f; for (int y = 0; y < block_size; ++y) { for (int x = 0; x < block_size; ++x) { int i = y * block_size + x; float *c = noise_tx->tx_block + 2 * i; const float p = c[0] * c[0] + c[1] * c[1]; if (p > kBeta * psd[i] && p > 1e-6) { noise_tx->tx_block[2 * i + 0] *= (p - psd[i]) / AOMMAX(p, kEps); noise_tx->tx_block[2 * i + 1] *= (p - psd[i]) / AOMMAX(p, kEps); } else { noise_tx->tx_block[2 * i + 0] *= (kBeta - 1.0f) / kBeta; noise_tx->tx_block[2 * i + 1] *= (kBeta - 1.0f) / kBeta; } } } }
static int cost_and_tokenize_map(Av1ColorMapParam *param, TOKENEXTRA **t, int plane, int calc_rate, int allow_update_cdf, FRAME_COUNTS *counts, MapCdf map_pb_cdf) { const uint8_t *const color_map = param->color_map; MapCdf map_cdf = param->map_cdf; ColorCost color_cost = param->color_cost; const int plane_block_width = param->plane_width; const int rows = param->rows; const int cols = param->cols; const int n = param->n_colors; const int palette_size_idx = n - PALETTE_MIN_SIZE; int this_rate = 0; uint8_t color_order[PALETTE_MAX_SIZE]; (void)plane; (void)counts; for (int k = 1; k < rows + cols - 1; ++k) { for (int j = AOMMIN(k, cols - 1); j >= AOMMAX(0, k - rows + 1); --j) { int i = k - j; int color_new_idx; const int color_ctx = av1_get_palette_color_index_context( color_map, plane_block_width, i, j, n, color_order, &color_new_idx); assert(color_new_idx >= 0 && color_new_idx < n); if (calc_rate) { this_rate += (*color_cost)[palette_size_idx][color_ctx][color_new_idx]; } else { (*t)->token = color_new_idx; (*t)->color_map_cdf = map_pb_cdf[palette_size_idx][color_ctx]; ++(*t); if (allow_update_cdf) update_cdf(map_cdf[palette_size_idx][color_ctx], color_new_idx, n); #if CONFIG_ENTROPY_STATS if (plane) { ++counts->palette_uv_color_index[palette_size_idx][color_ctx] [color_new_idx]; } else { ++counts->palette_y_color_index[palette_size_idx][color_ctx] [color_new_idx]; } #endif } } } if (calc_rate) return this_rate; return 0; }
void av1_loop_filter_frame_mt(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm, struct macroblockd_plane *planes, int frame_filter_level, #if CONFIG_LOOPFILTER_LEVEL int frame_filter_level_r, #endif int y_only, int partial_frame, AVxWorker *workers, int num_workers, AV1LfSync *lf_sync) { int start_mi_row, end_mi_row, mi_rows_to_filter; if (!frame_filter_level) return; start_mi_row = 0; mi_rows_to_filter = cm->mi_rows; if (partial_frame && cm->mi_rows > 8) { start_mi_row = cm->mi_rows >> 1; start_mi_row &= 0xfffffff8; mi_rows_to_filter = AOMMAX(cm->mi_rows / 8, 8); }
void av1_set_contexts(const MACROBLOCKD *xd, struct macroblockd_plane *pd, int plane, TX_SIZE tx_size, int has_eob, int aoff, int loff) { ENTROPY_CONTEXT *const a = pd->above_context + aoff; ENTROPY_CONTEXT *const l = pd->left_context + loff; const int txs_wide = tx_size_wide_unit[tx_size]; const int txs_high = tx_size_high_unit[tx_size]; const BLOCK_SIZE bsize = AOMMAX(xd->mi[0]->mbmi.sb_type, BLOCK_8X8); const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize, pd); // above if (has_eob && xd->mb_to_right_edge < 0) { int i; const int blocks_wide = max_block_wide(xd, plane_bsize, plane); int above_contexts = txs_wide; if (above_contexts + aoff > blocks_wide) above_contexts = blocks_wide - aoff; for (i = 0; i < above_contexts; ++i) a[i] = has_eob; for (i = above_contexts; i < txs_wide; ++i) a[i] = 0; } else { memset(a, has_eob, sizeof(ENTROPY_CONTEXT) * txs_wide); } // left if (has_eob && xd->mb_to_bottom_edge < 0) { int i; const int blocks_high = max_block_high(xd, plane_bsize, plane); int left_contexts = txs_high; if (left_contexts + loff > blocks_high) left_contexts = blocks_high - loff; for (i = 0; i < left_contexts; ++i) l[i] = has_eob; for (i = left_contexts; i < txs_high; ++i) l[i] = 0; } else { memset(l, has_eob, sizeof(ENTROPY_CONTEXT) * txs_high); } }
static void setup_ref_mv_list(const AV1_COMMON *cm, const MACROBLOCKD *xd, MV_REFERENCE_FRAME ref_frame, uint8_t *refmv_count, CANDIDATE_MV *ref_mv_stack, int_mv *mv_ref_list, int block, int mi_row, int mi_col, int16_t *mode_context) { int idx, nearest_refmv_count = 0; uint8_t newmv_count = 0; CANDIDATE_MV tmp_mv; int len, nr_len; const MV_REF *const prev_frame_mvs_base = cm->use_prev_frame_mvs ? cm->prev_frame->mvs + mi_row * cm->mi_cols + mi_col : NULL; const int bs = AOMMAX(xd->n8_w, xd->n8_h); const int has_tr = has_top_right(xd, mi_row, mi_col, bs); MV_REFERENCE_FRAME rf[2]; av1_set_ref_frame(rf, ref_frame); mode_context[ref_frame] = 0; *refmv_count = 0; // Scan the first above row mode info. newmv_count += scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, ref_mv_stack, refmv_count); // Scan the first left column mode info. newmv_count += scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, ref_mv_stack, refmv_count); // Check top-right boundary if (has_tr) newmv_count += scan_blk_mbmi(cm, xd, mi_row, mi_col, block, rf, -1, 1, ref_mv_stack, refmv_count); nearest_refmv_count = *refmv_count; for (idx = 0; idx < nearest_refmv_count; ++idx) ref_mv_stack[idx].weight += REF_CAT_LEVEL; if (prev_frame_mvs_base && cm->show_frame && cm->last_show_frame && rf[1] == NONE) { int blk_row, blk_col; int coll_blk_count = 0; for (blk_row = 0; blk_row < xd->n8_h; ++blk_row) { for (blk_col = 0; blk_col < xd->n8_w; ++blk_col) { coll_blk_count += add_col_ref_mv(cm, prev_frame_mvs_base, xd, mi_row, mi_col, ref_frame, blk_row, blk_col, refmv_count, ref_mv_stack, mode_context); } } if (coll_blk_count == 0) mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); } else { mode_context[ref_frame] |= (1 << ZEROMV_OFFSET); } // Scan the second outer area. for (idx = 2; idx <= 4; ++idx) { scan_row_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack, refmv_count); scan_col_mbmi(cm, xd, mi_row, mi_col, block, rf, -idx, ref_mv_stack, refmv_count); } switch (nearest_refmv_count) { case 0: mode_context[ref_frame] |= 0; if (*refmv_count >= 1) mode_context[ref_frame] |= 1; if (*refmv_count == 1) mode_context[ref_frame] |= (1 << REFMV_OFFSET); else if (*refmv_count >= 2) mode_context[ref_frame] |= (2 << REFMV_OFFSET); break; case 1: mode_context[ref_frame] |= (newmv_count > 0) ? 2 : 3; if (*refmv_count == 1) mode_context[ref_frame] |= (3 << REFMV_OFFSET); else if (*refmv_count >= 2) mode_context[ref_frame] |= (4 << REFMV_OFFSET); break; case 2: default: if (newmv_count >= 2) mode_context[ref_frame] |= 4; else if (newmv_count == 1) mode_context[ref_frame] |= 5; else mode_context[ref_frame] |= 6; mode_context[ref_frame] |= (5 << REFMV_OFFSET); break; } // Rank the likelihood and assign nearest and near mvs. len = nearest_refmv_count; while (len > 0) { nr_len = 0; for (idx = 1; idx < len; ++idx) { if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) { tmp_mv = ref_mv_stack[idx - 1]; ref_mv_stack[idx - 1] = ref_mv_stack[idx]; ref_mv_stack[idx] = tmp_mv; nr_len = idx; } } len = nr_len; } len = *refmv_count; while (len > nearest_refmv_count) { nr_len = nearest_refmv_count; for (idx = nearest_refmv_count + 1; idx < len; ++idx) { if (ref_mv_stack[idx - 1].weight < ref_mv_stack[idx].weight) { tmp_mv = ref_mv_stack[idx - 1]; ref_mv_stack[idx - 1] = ref_mv_stack[idx]; ref_mv_stack[idx] = tmp_mv; nr_len = idx; } } len = nr_len; } if (xd->is_sec_rect) { if (xd->n8_w < xd->n8_h) { const MODE_INFO *const candidate_mi = xd->mi[-1]; const MB_MODE_INFO *const candidate_mbmi = &candidate_mi->mbmi; handle_sec_rect_block(candidate_mbmi, nearest_refmv_count, ref_mv_stack, ref_frame, mode_context); } if (xd->n8_w > xd->n8_h) { const MODE_INFO *const candidate_mi = xd->mi[-xd->mi_stride]; const MB_MODE_INFO *const candidate_mbmi = &candidate_mi->mbmi; handle_sec_rect_block(candidate_mbmi, nearest_refmv_count, ref_mv_stack, ref_frame, mode_context); } } if (rf[1] > NONE) { for (idx = 0; idx < *refmv_count; ++idx) { clamp_mv_ref(&ref_mv_stack[idx].this_mv.as_mv, xd->n8_w << 3 , xd->n8_h << 3, xd); clamp_mv_ref(&ref_mv_stack[idx].comp_mv.as_mv, xd->n8_w << 3 , xd->n8_h << 3, xd); } } else { for (idx = 0; idx < AOMMIN(MAX_MV_REF_CANDIDATES, *refmv_count); ++idx) { mv_ref_list[idx].as_int = ref_mv_stack[idx].this_mv.as_int; clamp_mv_ref(&mv_ref_list[idx].as_mv, xd->n8_w << 3, xd->n8_h << 3, xd); } } }
static int ransac(const int *matched_points, int npoints, int *num_inliers_by_motion, double *params_by_motion, int num_desired_motions, const int minpts, IsDegenerateFunc is_degenerate, FindTransformationFunc find_transformation, ProjectPointsDoubleFunc projectpoints) { static const double PROBABILITY_REQUIRED = 0.9; static const double EPS = 1e-12; int N = 10000, trial_count = 0; int i = 0; int ret_val = 0; unsigned int seed = (unsigned int)npoints; int indices[MAX_MINPTS] = { 0 }; double *points1, *points2; double *corners1, *corners2; double *image1_coord; // Store information for the num_desired_motions best transformations found // and the worst motion among them, as well as the motion currently under // consideration. RANSAC_MOTION *motions, *worst_kept_motion = NULL; RANSAC_MOTION current_motion; // Store the parameters and the indices of the inlier points for the motion // currently under consideration. double params_this_motion[MAX_PARAMDIM]; double *cnp1, *cnp2; for (i = 0; i < num_desired_motions; ++i) { num_inliers_by_motion[i] = 0; } if (npoints < minpts * MINPTS_MULTIPLIER || npoints == 0) { return 1; } points1 = (double *)aom_malloc(sizeof(*points1) * npoints * 2); points2 = (double *)aom_malloc(sizeof(*points2) * npoints * 2); corners1 = (double *)aom_malloc(sizeof(*corners1) * npoints * 2); corners2 = (double *)aom_malloc(sizeof(*corners2) * npoints * 2); image1_coord = (double *)aom_malloc(sizeof(*image1_coord) * npoints * 2); motions = (RANSAC_MOTION *)aom_malloc(sizeof(RANSAC_MOTION) * num_desired_motions); for (i = 0; i < num_desired_motions; ++i) { motions[i].inlier_indices = (int *)aom_malloc(sizeof(*motions->inlier_indices) * npoints); clear_motion(motions + i, npoints); } current_motion.inlier_indices = (int *)aom_malloc(sizeof(*current_motion.inlier_indices) * npoints); clear_motion(¤t_motion, npoints); worst_kept_motion = motions; if (!(points1 && points2 && corners1 && corners2 && image1_coord && motions && current_motion.inlier_indices)) { ret_val = 1; goto finish_ransac; } cnp1 = corners1; cnp2 = corners2; for (i = 0; i < npoints; ++i) { *(cnp1++) = *(matched_points++); *(cnp1++) = *(matched_points++); *(cnp2++) = *(matched_points++); *(cnp2++) = *(matched_points++); } while (N > trial_count) { double sum_distance = 0.0; double sum_distance_squared = 0.0; clear_motion(¤t_motion, npoints); int degenerate = 1; int num_degenerate_iter = 0; while (degenerate) { num_degenerate_iter++; if (!get_rand_indices(npoints, minpts, indices, &seed)) { ret_val = 1; goto finish_ransac; } copy_points_at_indices(points1, corners1, indices, minpts); copy_points_at_indices(points2, corners2, indices, minpts); degenerate = is_degenerate(points1); if (num_degenerate_iter > MAX_DEGENERATE_ITER) { ret_val = 1; goto finish_ransac; } } if (find_transformation(minpts, points1, points2, params_this_motion)) { trial_count++; continue; } projectpoints(params_this_motion, corners1, image1_coord, npoints, 2, 2); for (i = 0; i < npoints; ++i) { double dx = image1_coord[i * 2] - corners2[i * 2]; double dy = image1_coord[i * 2 + 1] - corners2[i * 2 + 1]; double distance = sqrt(dx * dx + dy * dy); if (distance < INLIER_THRESHOLD) { current_motion.inlier_indices[current_motion.num_inliers++] = i; sum_distance += distance; sum_distance_squared += distance * distance; } } if (current_motion.num_inliers >= worst_kept_motion->num_inliers && current_motion.num_inliers > 1) { int temp; double fracinliers, pNoOutliers, mean_distance, dtemp; mean_distance = sum_distance / ((double)current_motion.num_inliers); current_motion.variance = sum_distance_squared / ((double)current_motion.num_inliers - 1.0) - mean_distance * mean_distance * ((double)current_motion.num_inliers) / ((double)current_motion.num_inliers - 1.0); if (is_better_motion(¤t_motion, worst_kept_motion)) { // This motion is better than the worst currently kept motion. Remember // the inlier points and variance. The parameters for each kept motion // will be recomputed later using only the inliers. worst_kept_motion->num_inliers = current_motion.num_inliers; worst_kept_motion->variance = current_motion.variance; memcpy(worst_kept_motion->inlier_indices, current_motion.inlier_indices, sizeof(*current_motion.inlier_indices) * npoints); assert(npoints > 0); fracinliers = (double)current_motion.num_inliers / (double)npoints; pNoOutliers = 1 - pow(fracinliers, minpts); pNoOutliers = fmax(EPS, pNoOutliers); pNoOutliers = fmin(1 - EPS, pNoOutliers); dtemp = log(1.0 - PROBABILITY_REQUIRED) / log(pNoOutliers); temp = (dtemp > (double)INT32_MAX) ? INT32_MAX : dtemp < (double)INT32_MIN ? INT32_MIN : (int)dtemp; if (temp > 0 && temp < N) { N = AOMMAX(temp, MIN_TRIALS); } // Determine the new worst kept motion and its num_inliers and variance. for (i = 0; i < num_desired_motions; ++i) { if (is_better_motion(worst_kept_motion, &motions[i])) { worst_kept_motion = &motions[i]; } } } } trial_count++; } // Sort the motions, best first. qsort(motions, num_desired_motions, sizeof(RANSAC_MOTION), compare_motions); // Recompute the motions using only the inliers. for (i = 0; i < num_desired_motions; ++i) { if (motions[i].num_inliers >= minpts) { copy_points_at_indices(points1, corners1, motions[i].inlier_indices, motions[i].num_inliers); copy_points_at_indices(points2, corners2, motions[i].inlier_indices, motions[i].num_inliers); find_transformation(motions[i].num_inliers, points1, points2, params_by_motion + (MAX_PARAMDIM - 1) * i); } num_inliers_by_motion[i] = motions[i].num_inliers; } finish_ransac: aom_free(points1); aom_free(points2); aom_free(corners1); aom_free(corners2); aom_free(image1_coord); aom_free(current_motion.inlier_indices); for (i = 0; i < num_desired_motions; ++i) { aom_free(motions[i].inlier_indices); } aom_free(motions); return ret_val; }
void av1_dering_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm, MACROBLOCKD *xd, int global_level) { int r, c; int sbr, sbc; int nhsb, nvsb; int16_t src[OD_DERING_INBUF_SIZE]; int16_t *linebuf[3]; int16_t colbuf[3][OD_BSIZE_MAX + 2 * OD_FILT_VBORDER][OD_FILT_HBORDER]; dering_list dlist[MAX_MIB_SIZE * MAX_MIB_SIZE]; unsigned char *row_dering, *prev_row_dering, *curr_row_dering; int dering_count; int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } }; int stride; int bsize[3]; int dec[3]; int pli; int dering_left; int coeff_shift = AOMMAX(cm->bit_depth - 8, 0); int nplanes; if (xd->plane[1].subsampling_x == xd->plane[1].subsampling_y && xd->plane[2].subsampling_x == xd->plane[2].subsampling_y) nplanes = 3; else nplanes = 1; nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE; nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE; av1_setup_dst_planes(xd->plane, frame, 0, 0); row_dering = aom_malloc(sizeof(*row_dering) * nhsb * 2); memset(row_dering, 1, sizeof(*row_dering) * (nhsb + 2) * 2); prev_row_dering = row_dering + 1; curr_row_dering = prev_row_dering + nhsb + 2; for (pli = 0; pli < nplanes; pli++) { dec[pli] = xd->plane[pli].subsampling_x; bsize[pli] = OD_DERING_SIZE_LOG2 - dec[pli]; } stride = (cm->mi_cols << bsize[0]) + 2 * OD_FILT_HBORDER; for (pli = 0; pli < nplanes; pli++) { linebuf[pli] = aom_malloc(sizeof(*linebuf) * OD_FILT_VBORDER * stride); } for (sbr = 0; sbr < nvsb; sbr++) { for (pli = 0; pli < nplanes; pli++) { for (r = 0; r < (MAX_MIB_SIZE << bsize[pli]) + 2 * OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { colbuf[pli][r][c] = OD_DERING_VERY_LARGE; } } } dering_left = 1; for (sbc = 0; sbc < nhsb; sbc++) { int level; int nhb, nvb; int cstart = 0; if (!dering_left) cstart = -OD_FILT_HBORDER; nhb = AOMMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE * sbc); nvb = AOMMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE * sbr); level = compute_level_from_index( global_level, cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride + MAX_MIB_SIZE * sbc] ->mbmi.dering_gain); curr_row_dering[sbc] = 0; if (level == 0 || (dering_count = sb_compute_dering_list( cm, sbr * MAX_MIB_SIZE, sbc * MAX_MIB_SIZE, dlist)) == 0) { dering_left = 0; continue; } curr_row_dering[sbc] = 1; for (pli = 0; pli < nplanes; pli++) { int16_t dst[OD_BSIZE_MAX * OD_BSIZE_MAX]; int threshold; int coffset; int rend, cend; if (sbc == nhsb - 1) cend = (nhb << bsize[pli]); else cend = (nhb << bsize[pli]) + OD_FILT_HBORDER; if (sbr == nvsb - 1) rend = (nvb << bsize[pli]); else rend = (nvb << bsize[pli]) + OD_FILT_VBORDER; coffset = sbc * MAX_MIB_SIZE << bsize[pli]; if (sbc == nhsb - 1) { /* On the last superblock column, fill in the right border with OD_DERING_VERY_LARGE to avoid filtering with the outside. */ for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = cend; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; ++c) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (sbr == nvsb - 1) { /* On the last superblock row, fill in the bottom border with OD_DERING_VERY_LARGE to avoid filtering with the outside. */ for (r = rend; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < (nhb << bsize[pli]) + 2 * OD_FILT_HBORDER; c++) { src[(r + OD_FILT_VBORDER) * OD_FILT_BSTRIDE + c] = OD_DERING_VERY_LARGE; } } } /* Copy in the pixels we need from the current superblock for deringing.*/ copy_sb8_16( cm, &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER + cstart], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr, coffset + cstart, xd->plane[pli].dst.stride, rend, cend - cstart); if (!prev_row_dering[sbc]) { copy_sb8_16(cm, &src[OD_FILT_HBORDER], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER, nhb << bsize[pli]); } else if (sbr > 0) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = 0; c < nhb << bsize[pli]; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = 0; c < nhb << bsize[pli]; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (!prev_row_dering[sbc - 1]) { copy_sb8_16(cm, src, OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset - OD_FILT_HBORDER, xd->plane[pli].dst.stride, OD_FILT_VBORDER, OD_FILT_HBORDER); } else if (sbr > 0 && sbc > 0) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = -OD_FILT_HBORDER; c < 0; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = -OD_FILT_HBORDER; c < 0; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (!prev_row_dering[sbc + 1]) { copy_sb8_16(cm, &src[OD_FILT_HBORDER + (nhb << bsize[pli])], OD_FILT_BSTRIDE, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * sbr - OD_FILT_VBORDER, coffset + (nhb << bsize[pli]), xd->plane[pli].dst.stride, OD_FILT_VBORDER, OD_FILT_HBORDER); } else if (sbr > 0 && sbc < nhsb - 1) { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = nhb << bsize[pli]; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = linebuf[pli][r * stride + coffset + c]; } } } else { for (r = 0; r < OD_FILT_VBORDER; r++) { for (c = nhb << bsize[pli]; c < (nhb << bsize[pli]) + OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c + OD_FILT_HBORDER] = OD_DERING_VERY_LARGE; } } } if (dering_left) { /* If we deringed the superblock on the left then we need to copy in saved pixels. */ for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { src[r * OD_FILT_BSTRIDE + c] = colbuf[pli][r][c]; } } } for (r = 0; r < rend + OD_FILT_VBORDER; r++) { for (c = 0; c < OD_FILT_HBORDER; c++) { /* Saving pixels in case we need to dering the superblock on the right. */ colbuf[pli][r][c] = src[r * OD_FILT_BSTRIDE + c + (nhb << bsize[pli])]; } } copy_sb8_16(cm, &linebuf[pli][coffset], stride, xd->plane[pli].dst.buf, (MAX_MIB_SIZE << bsize[pli]) * (sbr + 1) - OD_FILT_VBORDER, coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER, (nhb << bsize[pli])); /* FIXME: This is a temporary hack that uses more conservative deringing for chroma. */ if (pli) threshold = (level * 5 + 4) >> 3 << coeff_shift; else threshold = level << coeff_shift; if (threshold == 0) continue; od_dering( dst, &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER], dec[pli], dir, pli, dlist, dering_count, threshold, coeff_shift); #if CONFIG_AOM_HIGHBITDEPTH if (cm->use_highbitdepth) { copy_dering_16bit_to_16bit( (int16_t *)&CONVERT_TO_SHORTPTR( xd->plane[pli] .dst.buf)[xd->plane[pli].dst.stride * (MAX_MIB_SIZE * sbr << bsize[pli]) + (sbc * MAX_MIB_SIZE << bsize[pli])], xd->plane[pli].dst.stride, dst, dlist, dering_count, 3 - dec[pli]); } else { #endif copy_dering_16bit_to_8bit( &xd->plane[pli].dst.buf[xd->plane[pli].dst.stride * (MAX_MIB_SIZE * sbr << bsize[pli]) + (sbc * MAX_MIB_SIZE << bsize[pli])], xd->plane[pli].dst.stride, dst, dlist, dering_count, bsize[pli]); #if CONFIG_AOM_HIGHBITDEPTH } #endif } dering_left = 1; } { unsigned char *tmp; tmp = prev_row_dering; prev_row_dering = curr_row_dering; curr_row_dering = tmp; } }