vpx/vp9/common/vp9_alloccommon.c
Jingning Han ff2b8aa2c9 Contextual entropy coding of partition syntax
This commit enables selecting probability models for recursive block
partition information syntax, depending on its above/left partition
information, as well as the current block size. These conditional
probability models are reasonably stationary and consistent across
frames, hence the backward adaptive approach is used to maintain and
update the contextual models.

It achieves coding performance gains (on top of enabling rectangular
block sizes):
derf:   0.242%
yt:     0.391%
hd:     0.376%
stdhd:  0.645%

Change-Id: Ie513d9673337f0d27abd65fb566b711d0844ec2e
2013-04-24 14:23:14 -07:00

213 lines
5.6 KiB
C

/*
* Copyright (c) 2010 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.
*/
#include "./vpx_config.h"
#include "vp9/common/vp9_blockd.h"
#include "vpx_mem/vpx_mem.h"
#include "vp9/common/vp9_onyxc_int.h"
#include "vp9/common/vp9_findnearmv.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_entropymv.h"
#include "vp9/common/vp9_systemdependent.h"
void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi) {
const int stride = cpi->mode_info_stride;
int i;
// Clear down top border row
vpx_memset(mi, 0, sizeof(MODE_INFO) * stride);
// Clear left border column
for (i = 1; i < cpi->mb_rows + 1; i++)
vpx_memset(&mi[i * stride], 0, sizeof(MODE_INFO));
}
void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi) {
int i, j;
// For each in image mode_info element set the in image flag to 1
for (i = 0; i < cpi->mb_rows; i++) {
for (j = 0; j < cpi->mb_cols; j++) {
mi->mbmi.mb_in_image = 1;
mi++; // Next element in the row
}
mi++; // Step over border element at start of next row
}
}
void vp9_free_frame_buffers(VP9_COMMON *oci) {
int i;
for (i = 0; i < NUM_YV12_BUFFERS; i++)
vp8_yv12_de_alloc_frame_buffer(&oci->yv12_fb[i]);
vp8_yv12_de_alloc_frame_buffer(&oci->temp_scale_frame);
vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer);
vpx_free(oci->above_context);
vpx_free(oci->mip);
vpx_free(oci->prev_mip);
vpx_free(oci->above_seg_context);
oci->above_context = 0;
oci->mip = 0;
oci->prev_mip = 0;
oci->above_seg_context = 0;
}
int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
int i;
// Our internal buffers are always multiples of 16
const int aligned_width = multiple16(width);
const int aligned_height = multiple16(height);
vp9_free_frame_buffers(oci);
for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0;
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
}
oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
oci->fb_idx_ref_cnt[oci->new_fb_idx] = 1;
for (i = 0; i < ALLOWED_REFS_PER_FRAME; i++)
oci->active_ref_idx[i] = i;
for (i = 0; i < NUM_REF_FRAMES; i++) {
oci->ref_frame_map[i] = i;
oci->fb_idx_ref_cnt[i] = 1;
}
if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
oci->mb_rows = aligned_height >> 4;
oci->mb_cols = aligned_width >> 4;
oci->MBs = oci->mb_rows * oci->mb_cols;
oci->mode_info_stride = oci->mb_cols + 1;
oci->mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
if (!oci->mip) {
vp9_free_frame_buffers(oci);
return 1;
}
oci->mi = oci->mip + oci->mode_info_stride + 1;
/* allocate memory for last frame MODE_INFO array */
oci->prev_mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
if (!oci->prev_mip) {
vp9_free_frame_buffers(oci);
return 1;
}
oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
oci->above_context =
vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * mb_cols_aligned_to_sb(oci), 1);
if (!oci->above_context) {
vp9_free_frame_buffers(oci);
return 1;
}
oci->above_seg_context =
vpx_calloc(sizeof(PARTITION_CONTEXT) * mb_cols_aligned_to_sb(oci), 1);
if (!oci->above_seg_context) {
vp9_free_frame_buffers(oci);
return 1;
}
vp9_update_mode_info_border(oci, oci->mip);
vp9_update_mode_info_in_image(oci, oci->mi);
return 0;
}
void vp9_setup_version(VP9_COMMON *cm) {
if (cm->version & 0x4) {
if (!CONFIG_EXPERIMENTAL)
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Bitstream was created by an experimental "
"encoder");
cm->experimental = 1;
}
switch (cm->version & 0x3) {
case 0:
cm->no_lpf = 0;
cm->filter_type = NORMAL_LOOPFILTER;
cm->use_bilinear_mc_filter = 0;
break;
case 1:
cm->no_lpf = 0;
cm->filter_type = SIMPLE_LOOPFILTER;
cm->use_bilinear_mc_filter = 1;
break;
case 2:
case 3:
cm->no_lpf = 1;
cm->filter_type = NORMAL_LOOPFILTER;
cm->use_bilinear_mc_filter = 1;
break;
}
}
void vp9_create_common(VP9_COMMON *oci) {
vp9_machine_specific_config(oci);
vp9_init_mbmode_probs(oci);
vp9_default_bmode_probs(oci->fc.bmode_prob);
oci->txfm_mode = ONLY_4X4;
oci->comp_pred_mode = HYBRID_PREDICTION;
oci->no_lpf = 0;
oci->filter_type = NORMAL_LOOPFILTER;
oci->use_bilinear_mc_filter = 0;
oci->clr_type = REG_YUV;
oci->clamp_type = RECON_CLAMP_REQUIRED;
// Initialize reference frame sign bias structure to defaults
vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias));
oci->kf_ymode_probs_update = 0;
}
void vp9_remove_common(VP9_COMMON *oci) {
vp9_free_frame_buffers(oci);
}
void vp9_initialize_common() {
vp9_coef_tree_initialize();
vp9_entropy_mode_init();
vp9_entropy_mv_init();
}