summaryrefslogtreecommitdiff
path: root/vp8
diff options
context:
space:
mode:
Diffstat (limited to 'vp8')
-rw-r--r--vp8/common/vp8_skin_detection.c58
-rw-r--r--vp8/common/vp8_skin_detection.h11
-rw-r--r--vp8/encoder/pickinter.c2
-rw-r--r--vp8/vp8_dx_iface.c5
4 files changed, 58 insertions, 18 deletions
diff --git a/vp8/common/vp8_skin_detection.c b/vp8/common/vp8_skin_detection.c
index 495366dc8..2c0237087 100644
--- a/vp8/common/vp8_skin_detection.c
+++ b/vp8/common/vp8_skin_detection.c
@@ -14,26 +14,55 @@
#include "vpx_mem/vpx_mem.h"
#include "vpx_util/vpx_write_yuv_frame.h"
+static int avg_2x2(const uint8_t *s, int p) {
+ int i, j;
+ int sum = 0;
+ for (i = 0; i < 2; ++i, s += p) {
+ for (j = 0; j < 2; ++j) {
+ sum += s[j];
+ }
+ }
+ return (sum + 2) >> 2;
+}
+
int vp8_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
- int stride, int strideuv, int consec_zeromv,
+ int stride, int strideuv,
+ SKIN_DETECTION_BLOCK_SIZE bsize, int consec_zeromv,
int curr_motion_magn) {
// No skin if block has been zero/small motion for long consecutive time.
if (consec_zeromv > 60 && curr_motion_magn == 0) {
return 0;
} else {
int motion = 1;
- // Take the average of center 2x2 pixels.
- const int ysource = (y[7 * stride + 7] + y[7 * stride + 8] +
- y[8 * stride + 7] + y[8 * stride + 8]) >>
- 2;
- const int usource = (u[3 * strideuv + 3] + u[3 * strideuv + 4] +
- u[4 * strideuv + 3] + u[4 * strideuv + 4]) >>
- 2;
- const int vsource = (v[3 * strideuv + 3] + v[3 * strideuv + 4] +
- v[4 * strideuv + 3] + v[4 * strideuv + 4]) >>
- 2;
if (consec_zeromv > 25 && curr_motion_magn == 0) motion = 0;
- return vpx_skin_pixel(ysource, usource, vsource, motion);
+ if (bsize == SKIN_16X16) {
+ // Take the average of center 2x2 pixels.
+ const int ysource = avg_2x2(y + 7 * stride + 7, stride);
+ const int usource = avg_2x2(u + 3 * strideuv + 3, strideuv);
+ const int vsource = avg_2x2(v + 3 * strideuv + 3, strideuv);
+ return vpx_skin_pixel(ysource, usource, vsource, motion);
+ } else {
+ int num_skin = 0;
+ int i, j;
+ for (i = 0; i < 2; i++) {
+ for (j = 0; j < 2; j++) {
+ // Take the average of center 2x2 pixels.
+ const int ysource = avg_2x2(y + 3 * stride + 3, stride);
+ const int usource = avg_2x2(u + strideuv + 1, strideuv);
+ const int vsource = avg_2x2(v + strideuv + 1, strideuv);
+ num_skin += vpx_skin_pixel(ysource, usource, vsource, motion);
+ if (num_skin >= 2) return 1;
+ y += 8;
+ u += 4;
+ v += 4;
+ }
+ y += (stride << 3) - 16;
+ u += (strideuv << 2) - 8;
+ v += (strideuv << 2) - 8;
+ }
+
+ return 0;
+ }
}
}
@@ -74,8 +103,9 @@ void vp8_compute_skin_map(VP8_COMP *const cpi, FILE *yuv_skinmap_file) {
VPXMIN(cpi->consec_zero_last[bl_index1],
VPXMIN(cpi->consec_zero_last[bl_index2],
cpi->consec_zero_last[bl_index3])));
- is_skin = vp8_compute_skin_block(src_y, src_u, src_v, src_ystride,
- src_uvstride, consec_zeromv, 0);
+ is_skin =
+ vp8_compute_skin_block(src_y, src_u, src_v, src_ystride, src_uvstride,
+ SKIN_8X8, consec_zeromv, 0);
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
if (is_skin)
diff --git a/vp8/common/vp8_skin_detection.h b/vp8/common/vp8_skin_detection.h
index 3d0a9f45f..4d27f5eb2 100644
--- a/vp8/common/vp8_skin_detection.h
+++ b/vp8/common/vp8_skin_detection.h
@@ -22,8 +22,17 @@ extern "C" {
struct VP8_COMP;
+typedef enum {
+ // Skin detection based on 8x8 block. If two of them are identified as skin,
+ // the macroblock is marked as skin.
+ SKIN_8X8,
+ // Skin detection based on 16x16 block.
+ SKIN_16X16
+} SKIN_DETECTION_BLOCK_SIZE;
+
int vp8_compute_skin_block(const uint8_t *y, const uint8_t *u, const uint8_t *v,
- int stride, int strideuv, int consec_zeromv,
+ int stride, int strideuv,
+ SKIN_DETECTION_BLOCK_SIZE bsize, int consec_zeromv,
int curr_motion_magn);
#ifdef OUTPUT_YUV_SKINMAP
diff --git a/vp8/encoder/pickinter.c b/vp8/encoder/pickinter.c
index 74f9def69..d399839dd 100644
--- a/vp8/encoder/pickinter.c
+++ b/vp8/encoder/pickinter.c
@@ -693,7 +693,7 @@ void vp8_pick_inter_mode(VP8_COMP *cpi, MACROBLOCK *x, int recon_yoffset,
int block_index = mb_row * cpi->common.mb_cols + mb_col;
x->is_skin = vp8_compute_skin_block(
x->src.y_buffer, x->src.u_buffer, x->src.v_buffer, x->src.y_stride,
- x->src.uv_stride, cpi->consec_zero_last[block_index], 0);
+ x->src.uv_stride, SKIN_16X16, cpi->consec_zero_last[block_index], 0);
}
#if CONFIG_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity) {
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index 4868f15a6..987a5b8a4 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -228,7 +228,8 @@ static void yuvconfig2image(vpx_image_t *img, const YV12_BUFFER_CONFIG *yv12,
}
static int update_fragments(vpx_codec_alg_priv_t *ctx, const uint8_t *data,
- unsigned int data_sz, vpx_codec_err_t *res) {
+ unsigned int data_sz,
+ volatile vpx_codec_err_t *res) {
*res = VPX_CODEC_OK;
if (ctx->fragments.count == 0) {
@@ -267,7 +268,7 @@ static int update_fragments(vpx_codec_alg_priv_t *ctx, const uint8_t *data,
static vpx_codec_err_t vp8_decode(vpx_codec_alg_priv_t *ctx,
const uint8_t *data, unsigned int data_sz,
void *user_priv, long deadline) {
- vpx_codec_err_t res = VPX_CODEC_OK;
+ volatile vpx_codec_err_t res;
unsigned int resolution_change = 0;
unsigned int w, h;