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
This commit is contained in:
John Koleszar 2013-05-15 17:55:08 -07:00
parent 16ac5a5cde
commit 679e4abdd5
19 changed files with 214 additions and 52 deletions

1
configure vendored
View File

@ -246,6 +246,7 @@ EXPERIMENT_LIST="
oneshotq
multiple_arf
non420
alpha
ab4x4
comp_inter_joint_search
"

View File

@ -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);

View File

@ -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;

View File

@ -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,

View File

@ -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
}

View File

@ -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;

View File

@ -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};
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[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
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};
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[3] = {dst->y_buffer, dst->u_buffer, dst->v_buffer};
const int dst_strides[3] = {dst->y_stride, dst->uv_stride, dst->uv_stride};
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];

View File

@ -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);
}

View File

@ -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];

View File

@ -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,

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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]);

View File

@ -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() */

View File

@ -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++) {

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}