summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Koleszar <jkoleszar@google.com>2013-05-15 17:55:08 -0700
committerJohn Koleszar <jkoleszar@google.com>2013-05-16 22:21:09 -0700
commit679e4abdd5f733ab544689ce210b42d37e7ce164 (patch)
treeb2afbb63f8dc55e5f3ba974617bdce10b5ab34e1
parent16ac5a5cde0472fc29719aab7ad0958d1492df43 (diff)
downloadlibvpx-679e4abdd5f733ab544689ce210b42d37e7ce164.tar
libvpx-679e4abdd5f733ab544689ce210b42d37e7ce164.tar.gz
libvpx-679e4abdd5f733ab544689ce210b42d37e7ce164.tar.bz2
libvpx-679e4abdd5f733ab544689ce210b42d37e7ce164.zip
Initial version of alpha channel support
This is a mostly-working implementation of an extra channel in the bitstream. Configure with --enable-alpha to test. Notable TODOs: - Add extra channel to all mismatch tests, PSNR, SSIM, etc - Configurable subsampling - Variable number of planes (currently always uses all 4) - Loop filtering - Per-plane lossless quantizer - ARNR support This implementation just uses the same contents as the Y channel for the A channel, due to lack of content and general pain in playing back 4 channel content. A later patch will use the actual alpha channel passed in from outside the codec. Change-Id: Ibf81f023b1c570bd84b3064e9b4b8ae52e087592
-rwxr-xr-xconfigure1
-rw-r--r--vp9/common/vp9_alloccommon.c12
-rw-r--r--vp9/common/vp9_blockd.h4
-rw-r--r--vp9/common/vp9_extend.c20
-rw-r--r--vp9/common/vp9_mbpitch.c5
-rw-r--r--vp9/common/vp9_onyxc_int.h7
-rw-r--r--vp9/common/vp9_postproc.c40
-rw-r--r--vp9/common/vp9_reconinter.c15
-rw-r--r--vp9/common/vp9_reconinter.h12
-rw-r--r--vp9/encoder/vp9_encodeframe.c28
-rw-r--r--vp9/encoder/vp9_encodemb.c1
-rw-r--r--vp9/encoder/vp9_lookahead.c12
-rw-r--r--vp9/encoder/vp9_onyx_if.c24
-rw-r--r--vp9/encoder/vp9_onyx_int.h8
-rw-r--r--vp9/encoder/vp9_quantize.c37
-rw-r--r--vp9/encoder/vp9_rdopt.c4
-rw-r--r--vp9/encoder/vp9_temporal_filter.c13
-rw-r--r--vp9/vp9_iface_common.h7
-rw-r--r--vpx_scale/generic/yv12config.c20
19 files changed, 216 insertions, 54 deletions
diff --git a/configure b/configure
index cc8c58141..f4fea8d46 100755
--- a/configure
+++ b/configure
@@ -246,6 +246,7 @@ EXPERIMENT_LIST="
oneshotq
multiple_arf
non420
+ alpha
ab4x4
comp_inter_joint_search
"
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index ec81fbd7a..a272846d9 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -144,15 +144,19 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
// FIXME(jkoleszar): allocate subsampled arrays for U/V once subsampling
// information is exposed at this level
mi_cols = mi_cols_aligned_to_sb(oci);
+# if CONFIG_ALPHA
+ // TODO(jkoleszar): Why is this * 2?
+ oci->above_context[0] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * 8 * mi_cols, 1);
+#else
oci->above_context[0] = vpx_calloc(sizeof(ENTROPY_CONTEXT) * 6 * mi_cols, 1);
+#endif
if (!oci->above_context[0]) {
vp9_free_frame_buffers(oci);
return 1;
}
- oci->above_context[1] =
- oci->above_context[0] + sizeof(ENTROPY_CONTEXT) * 2 * mi_cols;
- oci->above_context[2] =
- oci->above_context[1] + sizeof(ENTROPY_CONTEXT) * 2 * mi_cols;
+ for (i = 1; i < MAX_MB_PLANE; i++)
+ oci->above_context[i] =
+ oci->above_context[0] + i * sizeof(ENTROPY_CONTEXT) * 2 * mi_cols;
oci->above_seg_context =
vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 07607d895..c1e9800ec 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -298,7 +298,11 @@ struct scale_factors {
convolve_fn_t predict[2][2][2]; // horiz, vert, avg
};
+#if CONFIG_ALPHA
+enum { MAX_MB_PLANE = 4 };
+#else
enum { MAX_MB_PLANE = 3 };
+#endif
struct buf_2d {
uint8_t *buf;
diff --git a/vp9/common/vp9_extend.c b/vp9/common/vp9_extend.c
index 6aeadf6aa..95ec59061 100644
--- a/vp9/common/vp9_extend.c
+++ b/vp9/common/vp9_extend.c
@@ -60,10 +60,22 @@ void vp9_copy_and_extend_frame(const YV12_BUFFER_CONFIG *src,
const int eb_y = dst->border + dst->y_height - src->y_height;
const int er_y = dst->border + dst->y_width - src->y_width;
- const int et_uv = dst->border >> 1;
- const int el_uv = dst->border >> 1;
- const int eb_uv = (dst->border >> 1) + dst->uv_height - src->uv_height;
- const int er_uv = (dst->border >> 1) + dst->uv_width - src->uv_width;
+ const int et_uv = dst->border >> (dst->uv_height != dst->y_height);
+ const int el_uv = dst->border >> (dst->uv_width != dst->y_width);
+ const int eb_uv = et_uv + dst->uv_height - src->uv_height;
+ const int er_uv = el_uv + dst->uv_width - src->uv_width;
+
+#if CONFIG_ALPHA
+ const int et_a = dst->border >> (dst->alpha_height != dst->y_height);
+ const int el_a = dst->border >> (dst->alpha_width != dst->y_width);
+ const int eb_a = et_a + dst->alpha_height - src->alpha_height;
+ const int er_a = el_a + dst->alpha_width - src->alpha_width;
+
+ copy_and_extend_plane(src->alpha_buffer, src->alpha_stride,
+ dst->alpha_buffer, dst->alpha_stride,
+ src->alpha_width, src->alpha_height,
+ et_a, el_a, eb_a, er_a);
+#endif
copy_and_extend_plane(src->y_buffer, src->y_stride,
dst->y_buffer, dst->y_stride,
diff --git a/vp9/common/vp9_mbpitch.c b/vp9/common/vp9_mbpitch.c
index d9f892b76..3cf37ffab 100644
--- a/vp9/common/vp9_mbpitch.c
+++ b/vp9/common/vp9_mbpitch.c
@@ -20,4 +20,9 @@ void vp9_setup_block_dptrs(MACROBLOCKD *mb,
mb->plane[i].subsampling_x = i ? subsampling_x : 0;
mb->plane[i].subsampling_y = i ? subsampling_y : 0;
}
+#if CONFIG_ALPHA
+ // TODO(jkoleszar): Using the Y w/h for now
+ mb->plane[3].subsampling_x = 0;
+ mb->plane[3].subsampling_y = 0;
+#endif
}
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 2d4cd30cc..51bdb196b 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -124,6 +124,9 @@ typedef struct VP9Common {
DECLARE_ALIGNED(16, int16_t, y_dequant[QINDEX_RANGE][2]);
DECLARE_ALIGNED(16, int16_t, uv_dequant[QINDEX_RANGE][2]);
+#if CONFIG_ALPHA
+ DECLARE_ALIGNED(16, int16_t, a_dequant[QINDEX_RANGE][2]);
+#endif
int width;
int height;
@@ -187,6 +190,10 @@ typedef struct VP9Common {
int y_dc_delta_q;
int uv_dc_delta_q;
int uv_ac_delta_q;
+#if CONFIG_ALPHA
+ int a_dc_delta_q;
+ int a_ac_delta_q;
+#endif
unsigned int frames_since_golden;
unsigned int frames_till_alt_ref_frame;
diff --git a/vp9/common/vp9_postproc.c b/vp9/common/vp9_postproc.c
index 8001adb29..d2c52edfd 100644
--- a/vp9/common/vp9_postproc.c
+++ b/vp9/common/vp9_postproc.c
@@ -320,13 +320,19 @@ void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
+ 0.0065 + 0.5);
int i;
- const uint8_t *const srcs[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
- const int src_strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
- const int src_widths[3] = {src->y_width, src->uv_width, src->uv_width};
- const int src_heights[3] = {src->y_height, src->uv_height, src->uv_height};
-
- uint8_t *const dsts[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
- const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
+ const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
+ src->alpha_buffer};
+ const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
+ src->alpha_stride};
+ const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
+ src->alpha_width};
+ const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
+ src->alpha_height};
+
+ uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
+ dst->alpha_buffer};
+ const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
+ dst->alpha_stride};
for (i = 0; i < MAX_MB_PLANE; ++i)
vp9_post_proc_down_and_across(srcs[i], dsts[i],
@@ -340,13 +346,19 @@ void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst,
+ 0.0065 + 0.5);
int i;
- const uint8_t *const srcs[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
- const int src_strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
- const int src_widths[3] = {src->y_width, src->uv_width, src->uv_width};
- const int src_heights[3] = {src->y_height, src->uv_height, src->uv_height};
-
- uint8_t *const dsts[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
- const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
+ const uint8_t *const srcs[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
+ src->alpha_buffer};
+ const int src_strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
+ src->alpha_stride};
+ const int src_widths[4] = {src->y_width, src->uv_width, src->uv_width,
+ src->alpha_width};
+ const int src_heights[4] = {src->y_height, src->uv_height, src->uv_height,
+ src->alpha_height};
+
+ uint8_t *const dsts[4] = {dst->y_buffer, dst->u_buffer, dst->v_buffer,
+ dst->alpha_buffer};
+ const int dst_strides[4] = {dst->y_stride, dst->uv_stride, dst->uv_stride,
+ dst->alpha_stride};
for (i = 0; i < MAX_MB_PLANE; ++i) {
const int src_stride = src_strides[i];
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index e7303f15f..cd0ba8445 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -469,12 +469,27 @@ void vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd,
BLOCK_SIZE_TYPE bsize) {
struct build_inter_predictors_args args = {
xd, mi_col * MI_SIZE, mi_row * MI_SIZE,
+#if CONFIG_ALPHA
+ {NULL, xd->plane[1].dst.buf, xd->plane[2].dst.buf,
+ xd->plane[3].dst.buf},
+ {0, xd->plane[1].dst.stride, xd->plane[1].dst.stride,
+ xd->plane[3].dst.stride},
+ {{NULL, xd->plane[1].pre[0].buf, xd->plane[2].pre[0].buf,
+ xd->plane[3].pre[0].buf},
+ {NULL, xd->plane[1].pre[1].buf, xd->plane[2].pre[1].buf,
+ xd->plane[3].pre[1].buf}},
+ {{0, xd->plane[1].pre[0].stride, xd->plane[1].pre[0].stride,
+ xd->plane[3].pre[0].stride},
+ {0, xd->plane[1].pre[1].stride, xd->plane[1].pre[1].stride,
+ xd->plane[3].pre[1].stride}},
+#else
{NULL, xd->plane[1].dst.buf, xd->plane[2].dst.buf},
{0, xd->plane[1].dst.stride, xd->plane[1].dst.stride},
{{NULL, xd->plane[1].pre[0].buf, xd->plane[2].pre[0].buf},
{NULL, xd->plane[1].pre[1].buf, xd->plane[2].pre[1].buf}},
{{0, xd->plane[1].pre[0].stride, xd->plane[1].pre[0].stride},
{0, xd->plane[1].pre[1].stride, xd->plane[1].pre[1].stride}},
+#endif
};
foreach_predicted_block_uv(xd, bsize, build_inter_predictors, &args);
}
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index 8f7619520..af289d27e 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -74,8 +74,10 @@ static void setup_pred_plane(struct buf_2d *dst,
static void setup_dst_planes(MACROBLOCKD *xd,
const YV12_BUFFER_CONFIG *src,
int mi_row, int mi_col) {
- uint8_t *buffers[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
- int strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
+ uint8_t *buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
+ src->alpha_buffer};
+ int strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
+ src->alpha_stride};
int i;
for (i = 0; i < MAX_MB_PLANE; ++i) {
@@ -97,8 +99,10 @@ static void setup_pre_planes(MACROBLOCKD *xd,
for (i = 0; i < 2; ++i) {
const YV12_BUFFER_CONFIG *src = srcs[i];
if (src) {
- uint8_t* buffers[3] = {src->y_buffer, src->u_buffer, src->v_buffer};
- int strides[3] = {src->y_stride, src->uv_stride, src->uv_stride};
+ uint8_t* buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
+ src->alpha_buffer};
+ int strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
+ src->alpha_stride};
for (j = 0; j < MAX_MB_PLANE; ++j) {
struct macroblockd_plane *pd = &xd->plane[j];
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index ae1e3f5d3..cdc49e96e 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -515,21 +515,19 @@ static unsigned find_seg_id(uint8_t *buf, BLOCK_SIZE_TYPE bsize,
void vp9_setup_src_planes(MACROBLOCK *x,
const YV12_BUFFER_CONFIG *src,
int mb_row, int mb_col) {
- setup_pred_plane(&x->plane[0].src,
- src->y_buffer, src->y_stride,
- mb_row, mb_col, NULL,
- x->e_mbd.plane[0].subsampling_x,
- x->e_mbd.plane[0].subsampling_y);
- setup_pred_plane(&x->plane[1].src,
- src->u_buffer, src->uv_stride,
- mb_row, mb_col, NULL,
- x->e_mbd.plane[1].subsampling_x,
- x->e_mbd.plane[1].subsampling_y);
- setup_pred_plane(&x->plane[2].src,
- src->v_buffer, src->uv_stride,
- mb_row, mb_col, NULL,
- x->e_mbd.plane[2].subsampling_x,
- x->e_mbd.plane[2].subsampling_y);
+ uint8_t *buffers[4] = {src->y_buffer, src->u_buffer, src->v_buffer,
+ src->alpha_buffer};
+ int strides[4] = {src->y_stride, src->uv_stride, src->uv_stride,
+ src->alpha_stride};
+ int i;
+
+ for (i = 0; i < MAX_MB_PLANE; i++) {
+ setup_pred_plane(&x->plane[i].src,
+ buffers[i], strides[i],
+ mb_row, mb_col, NULL,
+ x->e_mbd.plane[i].subsampling_x,
+ x->e_mbd.plane[i].subsampling_y);
+ }
}
static void set_offsets(VP9_COMP *cpi,
diff --git a/vp9/encoder/vp9_encodemb.c b/vp9/encoder/vp9_encodemb.c
index 221de7426..976d04ec0 100644
--- a/vp9/encoder/vp9_encodemb.c
+++ b/vp9/encoder/vp9_encodemb.c
@@ -44,7 +44,6 @@ static void subtract_plane(MACROBLOCK *x, BLOCK_SIZE_TYPE bsize, int plane) {
const uint8_t *src = x->plane[plane].src.buf;
const int src_stride = x->plane[plane].src.stride;
- assert(plane < 3);
vp9_subtract_block(bh, bw,
x->plane[plane].src_diff, bw, src, src_stride,
xd->plane[plane].dst.buf, xd->plane[plane].dst.stride);
diff --git a/vp9/encoder/vp9_lookahead.c b/vp9/encoder/vp9_lookahead.c
index 708fe4549..b07d92a44 100644
--- a/vp9/encoder/vp9_lookahead.c
+++ b/vp9/encoder/vp9_lookahead.c
@@ -84,20 +84,27 @@ bail:
return NULL;
}
+#define USE_PARTIAL_COPY 0
int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int64_t ts_start, int64_t ts_end, unsigned int flags,
unsigned char *active_map) {
struct lookahead_entry *buf;
+#if USE_PARTIAL_COPY
int row, col, active_end;
int mb_rows = (src->y_height + 15) >> 4;
int mb_cols = (src->y_width + 15) >> 4;
+#endif
if (ctx->sz + 1 > ctx->max_sz)
return 1;
ctx->sz++;
buf = pop(ctx, &ctx->write_idx);
+#if USE_PARTIAL_COPY
+ // TODO(jkoleszar): This is disabled for now, as
+ // vp9_copy_and_extend_frame_with_rect is not subsampling/alpha aware.
+
// Only do this partial copy if the following conditions are all met:
// 1. Lookahead queue has has size of 1.
// 2. Active map is provided.
@@ -140,6 +147,11 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
} else {
vp9_copy_and_extend_frame(src, &buf->img);
}
+#else
+ // Partial copy not implemented yet
+ vp9_copy_and_extend_frame(src, &buf->img);
+#endif
+
buf->ts_start = ts_start;
buf->ts_end = ts_end;
buf->flags = flags;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index b6f9eb7f8..24649c193 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -2118,6 +2118,18 @@ void vp9_write_yuv_rec_frame(VP9_COMMON *cm) {
fwrite(src, s->uv_width, 1, yuv_rec_file);
src += s->uv_stride;
} while (--h);
+
+#if CONFIG_ALPHA
+ if (s->alpha_buffer) {
+ src = s->alpha_buffer;
+ h = s->alpha_height;
+ do {
+ fwrite(src, s->alpha_width, 1, yuv_rec_file);
+ src += s->alpha_stride;
+ } while (--h);
+ }
+#endif
+
fflush(yuv_rec_file);
}
#endif
@@ -2130,11 +2142,15 @@ static void scale_and_extend_frame(YV12_BUFFER_CONFIG *src_fb,
const int out_h = dst_fb->y_crop_height;
int x, y, i;
- uint8_t *srcs[3] = {src_fb->y_buffer, src_fb->u_buffer, src_fb->v_buffer};
- int src_strides[3] = {src_fb->y_stride, src_fb->uv_stride, src_fb->uv_stride};
+ uint8_t *srcs[4] = {src_fb->y_buffer, src_fb->u_buffer, src_fb->v_buffer,
+ src_fb->alpha_buffer};
+ int src_strides[4] = {src_fb->y_stride, src_fb->uv_stride, src_fb->uv_stride,
+ src_fb->alpha_stride};
- uint8_t *dsts[3] = {dst_fb->y_buffer, dst_fb->u_buffer, dst_fb->v_buffer};
- int dst_strides[3] = {dst_fb->y_stride, dst_fb->uv_stride, dst_fb->uv_stride};
+ uint8_t *dsts[4] = {dst_fb->y_buffer, dst_fb->u_buffer, dst_fb->v_buffer,
+ dst_fb->alpha_buffer};
+ int dst_strides[4] = {dst_fb->y_stride, dst_fb->uv_stride, dst_fb->uv_stride,
+ dst_fb->alpha_stride};
for (y = 0; y < out_h; y += 16) {
for (x = 0; x < out_w; x += 16) {
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index aba4c0e64..1d0bc46f1 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -268,6 +268,14 @@ typedef struct VP9_COMP {
DECLARE_ALIGNED(16, short, uv_zbin[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, uv_round[QINDEX_RANGE][16]);
+#if CONFIG_ALPHA
+ DECLARE_ALIGNED(16, short, a_quant[QINDEX_RANGE][16]);
+ DECLARE_ALIGNED(16, unsigned char, a_quant_shift[QINDEX_RANGE][16]);
+ DECLARE_ALIGNED(16, short, a_zbin[QINDEX_RANGE][16]);
+ DECLARE_ALIGNED(16, short, a_round[QINDEX_RANGE][16]);
+
+ DECLARE_ALIGNED(16, short, zrun_zbin_boost_a[QINDEX_RANGE][16]);
+#endif
DECLARE_ALIGNED(16, short, zrun_zbin_boost_y[QINDEX_RANGE][16]);
DECLARE_ALIGNED(16, short, zrun_zbin_boost_uv[QINDEX_RANGE][16]);
diff --git a/vp9/encoder/vp9_quantize.c b/vp9/encoder/vp9_quantize.c
index aea350bc4..9beda3466 100644
--- a/vp9/encoder/vp9_quantize.c
+++ b/vp9/encoder/vp9_quantize.c
@@ -148,6 +148,9 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
int i;
int quant_val;
int quant_uv_val;
+#if CONFIG_ALPHA
+ int quant_alpha_val;
+#endif
int q;
static const int zbin_boost[16] = { 0, 0, 0, 8, 8, 8, 10, 12,
@@ -168,7 +171,6 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
cpi->common.y_dequant[q][0] = quant_val;
cpi->zrun_zbin_boost_y[q][0] = (quant_val * zbin_boost[0]) >> 7;
-
quant_val = vp9_dc_quant(q, cpi->common.uv_dc_delta_q);
invert_quant(cpi->uv_quant[q] + 0, cpi->uv_quant_shift[q] + 0, quant_val);
cpi->uv_zbin[q][0] = ROUND_POWER_OF_TWO(qzbin_factor * quant_val, 7);
@@ -176,10 +178,23 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
cpi->common.uv_dequant[q][0] = quant_val;
cpi->zrun_zbin_boost_uv[q][0] = (quant_val * zbin_boost[0]) >> 7;
+#if CONFIG_ALPHA
+ quant_val = vp9_dc_quant(q, cpi->common.a_dc_delta_q);
+ invert_quant(cpi->a_quant[q] + 0, cpi->a_quant_shift[q] + 0, quant_val);
+ cpi->a_zbin[q][0] = ROUND_POWER_OF_TWO(qzbin_factor * quant_val, 7);
+ cpi->a_round[q][0] = (qrounding_factor * quant_val) >> 7;
+ cpi->common.a_dequant[q][0] = quant_val;
+ cpi->zrun_zbin_boost_a[q][0] = (quant_val * zbin_boost[0]) >> 7;
+#endif
+
quant_val = vp9_ac_quant(q, 0);
cpi->common.y_dequant[q][1] = quant_val;
quant_uv_val = vp9_ac_quant(q, cpi->common.uv_ac_delta_q);
cpi->common.uv_dequant[q][1] = quant_uv_val;
+#if CONFIG_ALPHA
+ quant_alpha_val = vp9_ac_quant(q, cpi->common.a_ac_delta_q);
+ cpi->common.a_dequant[q][1] = quant_alpha_val;
+#endif
// all the 4x4 ac values =;
for (i = 1; i < 16; i++) {
int rc = vp9_default_zig_zag1d_4x4[i];
@@ -196,6 +211,16 @@ void vp9_init_quantizer(VP9_COMP *cpi) {
cpi->uv_round[q][rc] = (qrounding_factor * quant_uv_val) >> 7;
cpi->zrun_zbin_boost_uv[q][i] =
ROUND_POWER_OF_TWO(quant_uv_val * zbin_boost[i], 7);
+
+#if CONFIG_ALPHA
+ invert_quant(cpi->a_quant[q] + rc, cpi->a_quant_shift[q] + rc,
+ quant_alpha_val);
+ cpi->a_zbin[q][rc] =
+ ROUND_POWER_OF_TWO(qzbin_factor * quant_alpha_val, 7);
+ cpi->a_round[q][rc] = (qrounding_factor * quant_alpha_val) >> 7;
+ cpi->zrun_zbin_boost_a[q][i] =
+ ROUND_POWER_OF_TWO(quant_alpha_val * zbin_boost[i], 7);
+#endif
}
}
}
@@ -233,6 +258,16 @@ void vp9_mb_init_quantizer(VP9_COMP *cpi, MACROBLOCK *x) {
x->e_mbd.plane[i].dequant = cpi->common.uv_dequant[qindex];
}
+#if CONFIG_ALPHA
+ x->plane[3].quant = cpi->a_quant[qindex];
+ x->plane[3].quant_shift = cpi->a_quant_shift[qindex];
+ x->plane[3].zbin = cpi->a_zbin[qindex];
+ x->plane[3].round = cpi->a_round[qindex];
+ x->plane[3].zrun_zbin_boost = cpi->zrun_zbin_boost_a[qindex];
+ x->plane[3].zbin_extra = (int16_t)zbin_extra;
+ x->e_mbd.plane[3].dequant = cpi->common.a_dequant[qindex];
+#endif
+
x->skip_block = vp9_segfeature_active(xd, segment_id, SEG_LVL_SKIP);
/* save this macroblock QIndex for vp9_update_zbin_extra() */
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 271a63f99..deab6a67c 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -1608,6 +1608,10 @@ static void setup_pred_block(const MACROBLOCKD *xd,
dst[1].buf = src->u_buffer;
dst[2].buf = src->v_buffer;
dst[1].stride = dst[2].stride = src->uv_stride;
+#if CONFIG_ALPHA
+ dst[3].buf = src->alpha_buffer;
+ dst[3].stride = src->alpha_stride;
+#endif
// TODO(jkoleszar): Make scale factors per-plane data
for (i = 0; i < MAX_MB_PLANE; i++) {
diff --git a/vp9/encoder/vp9_temporal_filter.c b/vp9/encoder/vp9_temporal_filter.c
index 30143d77d..47792fcc2 100644
--- a/vp9/encoder/vp9_temporal_filter.c
+++ b/vp9/encoder/vp9_temporal_filter.c
@@ -205,9 +205,11 @@ static void temporal_filter_iterate_c(VP9_COMP *cpi,
DECLARE_ALIGNED_ARRAY(16, uint8_t, predictor, 16 * 16 + 8 * 8 + 8 * 8);
// Save input state
- uint8_t *y_buffer = mbd->plane[0].pre[0].buf;
- uint8_t *u_buffer = mbd->plane[1].pre[0].buf;
- uint8_t *v_buffer = mbd->plane[2].pre[0].buf;
+ uint8_t* input_buffer[MAX_MB_PLANE];
+ int i;
+
+ for (i = 0; i < MAX_MB_PLANE; i++)
+ input_buffer[i] = mbd->plane[i].pre[0].buf;
for (mb_row = 0; mb_row < mb_rows; mb_row++) {
#if ALT_REF_MC_ENABLED
@@ -352,9 +354,8 @@ static void temporal_filter_iterate_c(VP9_COMP *cpi,
}
// Restore input state
- mbd->plane[0].pre[0].buf = y_buffer;
- mbd->plane[1].pre[0].buf = u_buffer;
- mbd->plane[2].pre[0].buf = v_buffer;
+ for (i = 0; i < MAX_MB_PLANE; i++)
+ mbd->plane[i].pre[0].buf = input_buffer[i];
}
void vp9_temporal_filter_prepare(VP9_COMP *cpi, int distance) {
diff --git a/vp9/vp9_iface_common.h b/vp9/vp9_iface_common.h
index 84b4d398b..1c3cc62d2 100644
--- a/vp9/vp9_iface_common.h
+++ b/vp9/vp9_iface_common.h
@@ -76,6 +76,13 @@ static vpx_codec_err_t image2yuvconfig(const vpx_image_t *img,
yv12->border = (img->stride[VPX_PLANE_Y] - img->w) / 2;
yv12->clrtype = REG_YUV;
+#if CONFIG_ALPHA
+ // For development purposes, force alpha to hold the same data a Y for now.
+ yv12->alpha_buffer = yv12->y_buffer;
+ yv12->alpha_width = yv12->y_width;
+ yv12->alpha_height = yv12->y_height;
+ yv12->alpha_stride = yv12->y_stride;
+#endif
return VPX_CODEC_OK;
}
diff --git a/vpx_scale/generic/yv12config.c b/vpx_scale/generic/yv12config.c
index 99e3543ac..632ff71f4 100644
--- a/vpx_scale/generic/yv12config.c
+++ b/vpx_scale/generic/yv12config.c
@@ -135,8 +135,19 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
const int uv_border_w = border >> ss_x;
const int uv_border_h = border >> ss_y;
const int uvplane_size = (uv_height + 2 * uv_border_h) * uv_stride;
+#if CONFIG_ALPHA
+ const int alpha_width = aligned_width;
+ const int alpha_height = aligned_height;
+ const int alpha_stride = y_stride;
+ const int alpha_border_w = border;
+ const int alpha_border_h = border;
+ const int alpha_plane_size = (alpha_height + 2 * alpha_border_h) *
+ alpha_stride;
+ const int frame_size = yplane_size + 2 * uvplane_size +
+ alpha_plane_size;
+#else
const int frame_size = yplane_size + 2 * uvplane_size;
-
+#endif
if (!ybf->buffer_alloc) {
ybf->buffer_alloc = vpx_memalign(32, frame_size);
ybf->buffer_alloc_sz = frame_size;
@@ -172,6 +183,13 @@ int vp9_realloc_frame_buffer(YV12_BUFFER_CONFIG *ybf,
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size +
(uv_border_h * uv_stride) + uv_border_w;
+#if CONFIG_ALPHA
+ ybf->alpha_width = alpha_width;
+ ybf->alpha_height = alpha_height;
+ ybf->alpha_stride = alpha_stride;
+ ybf->alpha_buffer = ybf->buffer_alloc + yplane_size + 2 * uvplane_size +
+ (alpha_border_h * alpha_stride) + alpha_border_w;
+#endif
ybf->corrupted = 0; /* assume not currupted by errors */
return 0;
}