/* * Copyright (c) 2014 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// TODO(jackychen): Replace this function with SSE2 code. There is // one SSE2 implementation in vp8, so will consider how to share it // between vp8 and vp9. staticvoid filter_by_weight(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int block_size, int src_weight) { constint dst_weight = (1 << MFQE_PRECISION) - src_weight; constint rounding_bit = 1 << (MFQE_PRECISION - 1); int r, c;
for (r = 0; r < block_size; r++) { for (c = 0; c < block_size; c++) {
dst[c] = (src[c] * src_weight + dst[c] * dst_weight + rounding_bit) >>
MFQE_PRECISION;
}
src += src_stride;
dst += dst_stride;
}
}
void vp9_filter_by_weight8x8_c(const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride, int src_weight) {
filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
}
void vp9_filter_by_weight16x16_c(const uint8_t *src, int src_stride,
uint8_t *dst, int dst_stride, int src_weight) {
filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
}
// vdiff > sad * 3 means vdiff should not be too small, otherwise, // it might be a lighting change in smooth area. When there is a // lighting change in smooth area, it is dangerous to do MFQE. if (sad > 1 && vdiff > sad * 3) { constint weight = 1 << MFQE_PRECISION; int ifactor = weight * sad * vdiff / (sad_thr * vdiff_thr); // When ifactor equals weight, no MFQE is done. if (ifactor > weight) {
ifactor = weight;
}
apply_ifactor(y, y_stride, yd, yd_stride, u, v, uv_stride, ud, vd,
uvd_stride, bs, ifactor);
} else { // Copy the block from current frame (i.e., no mfqe is done).
copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride, uvd_stride,
bs);
}
}
staticint mfqe_decision(MODE_INFO *mi, BLOCK_SIZE cur_bs) { // Check the motion in current block(for inter frame), // or check the motion in the correlated block in last frame (for keyframe). constint mv_len_square = mi->mv[0].as_mv.row * mi->mv[0].as_mv.row +
mi->mv[0].as_mv.col * mi->mv[0].as_mv.col; constint mv_threshold = 100; return mi->mode >= NEARESTMV && // Not an intra block
cur_bs >= BLOCK_16X16 && mv_len_square <= mv_threshold;
}
// Process each partiton in a super block, recursively. staticvoid mfqe_partition(VP9_COMMON *cm, MODE_INFO *mi, BLOCK_SIZE bs, const uint8_t *y, const uint8_t *u, const uint8_t *v, int y_stride, int uv_stride, uint8_t *yd,
uint8_t *ud, uint8_t *vd, int yd_stride, int uvd_stride) { int mi_offset, y_offset, uv_offset; const BLOCK_SIZE cur_bs = mi->sb_type; constint qdiff = cm->base_qindex - cm->postproc_state.last_base_qindex; constint bsl = b_width_log2_lookup[bs];
PARTITION_TYPE partition = partition_lookup[bsl][cur_bs]; const BLOCK_SIZE subsize = get_subsize(bs, partition);
BLOCK_SIZE mfqe_bs, bs_tmp;
if (cur_bs < BLOCK_8X8) { // If there are blocks smaller than 8x8, it must be on the boundary. return;
} // No MFQE on blocks smaller than 16x16 if (bs == BLOCK_16X16) {
partition = PARTITION_NONE;
} if (bs == BLOCK_64X64) {
mi_offset = 4;
y_offset = 32;
uv_offset = 16;
} else {
mi_offset = 2;
y_offset = 16;
uv_offset = 8;
} switch (partition) { case PARTITION_HORZ: if (bs == BLOCK_64X64) {
mfqe_bs = BLOCK_64X32;
bs_tmp = BLOCK_32X32;
} else {
mfqe_bs = BLOCK_32X16;
bs_tmp = BLOCK_16X16;
} if (mfqe_decision(mi, mfqe_bs)) { // Do mfqe on the first square partition.
mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
uvd_stride, qdiff); // Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset, y_stride,
uv_stride, yd + y_offset, ud + uv_offset, vd + uv_offset,
yd_stride, uvd_stride, qdiff);
} if (mfqe_decision(mi + mi_offset * cm->mi_stride, mfqe_bs)) { // Do mfqe on the first square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff); // Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset, yd_stride,
uvd_stride, qdiff);
} break; case PARTITION_VERT: if (bs == BLOCK_64X64) {
mfqe_bs = BLOCK_32X64;
bs_tmp = BLOCK_32X32;
} else {
mfqe_bs = BLOCK_16X32;
bs_tmp = BLOCK_16X16;
} if (mfqe_decision(mi, mfqe_bs)) { // Do mfqe on the first square partition.
mfqe_block(bs_tmp, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
uvd_stride, qdiff); // Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride, qdiff);
} if (mfqe_decision(mi + mi_offset, mfqe_bs)) { // Do mfqe on the first square partition.
mfqe_block(bs_tmp, y + y_offset, u + uv_offset, v + uv_offset, y_stride,
uv_stride, yd + y_offset, ud + uv_offset, vd + uv_offset,
yd_stride, uvd_stride, qdiff); // Do mfqe on the second square partition.
mfqe_block(bs_tmp, y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset, yd_stride,
uvd_stride, qdiff);
} break; case PARTITION_NONE: if (mfqe_decision(mi, cur_bs)) { // Do mfqe on this partition.
mfqe_block(cur_bs, y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
uvd_stride, qdiff);
} else { // Copy the block from current frame(i.e., no mfqe is done).
copy_block(y, u, v, y_stride, uv_stride, yd, ud, vd, yd_stride,
uvd_stride, bs);
} break; case PARTITION_SPLIT: // Recursion on four square partitions, e.g. if bs is 64X64, // then look into four 32X32 blocks in it.
mfqe_partition(cm, mi, subsize, y, u, v, y_stride, uv_stride, yd, ud, vd,
yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset, subsize, y + y_offset, u + uv_offset,
v + uv_offset, y_stride, uv_stride, yd + y_offset,
ud + uv_offset, vd + uv_offset, yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset * cm->mi_stride, subsize,
y + y_offset * y_stride, u + uv_offset * uv_stride,
v + uv_offset * uv_stride, y_stride, uv_stride,
yd + y_offset * yd_stride, ud + uv_offset * uvd_stride,
vd + uv_offset * uvd_stride, yd_stride, uvd_stride);
mfqe_partition(cm, mi + mi_offset * cm->mi_stride + mi_offset, subsize,
y + y_offset * y_stride + y_offset,
u + uv_offset * uv_stride + uv_offset,
v + uv_offset * uv_stride + uv_offset, y_stride, uv_stride,
yd + y_offset * yd_stride + y_offset,
ud + uv_offset * uvd_stride + uv_offset,
vd + uv_offset * uvd_stride + uv_offset, yd_stride,
uvd_stride); break; default: assert(0);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.