Commit 28d31aed authored by Dmitry Kovalev's avatar Dmitry Kovalev Committed by Gerrit Code Review
Browse files

Merge "Moving bits from compressed header to uncompressed one." into experimental

parents 9504f5fa 12345cb3
......@@ -10,41 +10,39 @@
#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_blockd.h"
#include "vp9/common/vp9_entropymode.h"
#include "vp9/common/vp9_entropymv.h"
#include "vp9/common/vp9_findnearmv.h"
#include "vp9/common/vp9_onyxc_int.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;
void vp9_update_mode_info_border(VP9_COMMON *cm, MODE_INFO *mi) {
const int stride = cm->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->mi_rows + 1; i++)
for (i = 1; i < cm->mi_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) {
void vp9_update_mode_info_in_image(VP9_COMMON *cm, MODE_INFO *mi) {
int i, j;
MODE_INFO *ptr;
// For each in image mode_info element set the in image flag to 1
for (i = 0; i < cpi->mi_rows; i++) {
ptr = mi;
for (j = 0; j < cpi->mi_cols; j++) {
for (i = 0; i < cm->mi_rows; i++) {
MODE_INFO *ptr = mi;
for (j = 0; j < cm->mi_cols; j++) {
ptr->mbmi.mb_in_image = 1;
ptr++; // Next element in the row
}
// Step over border element at start of next row
mi += cpi->mode_info_stride;
mi += cm->mode_info_stride;
}
}
......@@ -69,23 +67,46 @@ void vp9_free_frame_buffers(VP9_COMMON *oci) {
oci->above_seg_context = 0;
}
static void set_mb_mi(VP9_COMMON *cm, int aligned_width, int aligned_height) {
cm->mb_cols = aligned_width >> 4;
cm->mb_rows = aligned_height >> 4;
cm->MBs = cm->mb_rows * cm->mb_cols;
cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
cm->mode_info_stride = cm->mi_cols + 1;
}
static void setup_mi(VP9_COMMON *cm) {
cm->mi = cm->mip + cm->mode_info_stride + 1;
cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
vpx_memset(cm->mip, 0,
cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
vp9_update_mode_info_border(cm, cm->mip);
vp9_update_mode_info_in_image(cm, cm->mi);
vp9_update_mode_info_border(cm, cm->prev_mip);
vp9_update_mode_info_in_image(cm, cm->prev_mi);
}
int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
int i, mi_cols;
// Our internal buffers are always multiples of 16
const int aligned_width = multiple16(width);
const int aligned_height = multiple16(height);
const int ss_x = oci->subsampling_x;
const int ss_y = oci->subsampling_y;
vp9_free_frame_buffers(oci);
for (i = 0; i < NUM_YV12_BUFFERS; i++) {
oci->fb_idx_ref_cnt[i] = 0;
if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
if (vp9_alloc_frame_buffer(&oci->yv12_fb[i], width, height, ss_x, ss_y,
VP9BORDERINPIXELS) < 0)
goto fail;
}
oci->new_fb_idx = NUM_YV12_BUFFERS - 1;
......@@ -99,47 +120,28 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
oci->fb_idx_ref_cnt[i] = 1;
}
if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
if (vp9_alloc_frame_buffer(&oci->temp_scale_frame, width, 16, ss_x, ss_y,
VP9BORDERINPIXELS) < 0)
goto fail;
if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height,
oci->subsampling_x, oci->subsampling_y,
VP9BORDERINPIXELS) < 0) {
vp9_free_frame_buffers(oci);
return 1;
}
if (vp9_alloc_frame_buffer(&oci->post_proc_buffer, width, height, ss_x, ss_y,
VP9BORDERINPIXELS) < 0)
goto fail;
set_mb_mi(oci, aligned_width, aligned_height);
oci->mb_rows = aligned_height >> 4;
oci->mi_rows = aligned_height >> LOG2_MI_SIZE;
oci->mb_cols = aligned_width >> 4;
oci->mi_cols = aligned_width >> LOG2_MI_SIZE;
oci->MBs = oci->mb_rows * oci->mb_cols;
oci->mode_info_stride = oci->mi_cols + 1;
// Allocation
oci->mip = vpx_calloc(oci->mode_info_stride * (oci->mi_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 */
if (!oci->mip)
goto fail;
oci->prev_mip = vpx_calloc(oci->mode_info_stride * (oci->mi_rows + 1),
sizeof(MODE_INFO));
if (!oci->prev_mip)
goto fail;
if (!oci->prev_mip) {
vp9_free_frame_buffers(oci);
return 1;
}
oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
setup_mi(oci);
// FIXME(jkoleszar): allocate subsampled arrays for U/V once subsampling
// information is exposed at this level
......@@ -150,26 +152,22 @@ int vp9_alloc_frame_buffers(VP9_COMMON *oci, int width, int height) {
#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;
}
if (!oci->above_context[0])
goto fail;
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);
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);
oci->above_seg_context = vpx_calloc(sizeof(PARTITION_CONTEXT) * mi_cols, 1);
if (!oci->above_seg_context)
goto fail;
return 0;
fail:
vp9_free_frame_buffers(oci);
return 1;
}
void vp9_setup_version(VP9_COMMON *cm) {
......@@ -222,27 +220,10 @@ void vp9_initialize_common() {
vp9_entropy_mv_init();
}
void vp9_update_frame_size(VP9_COMMON *cm) {
const int aligned_width = multiple16(cm->width);
const int aligned_height = multiple16(cm->height);
cm->mb_rows = aligned_height >> 4;
cm->mb_cols = aligned_width >> 4;
cm->mi_rows = aligned_height >> LOG2_MI_SIZE;
cm->mi_cols = aligned_width >> LOG2_MI_SIZE;
cm->MBs = cm->mb_rows * cm->mb_cols;
cm->mode_info_stride = cm->mi_cols + 1;
cm->mi = cm->mip + cm->mode_info_stride + 1;
cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
memset(cm->mip, 0,
cm->mode_info_stride * (cm->mi_rows + 1) * sizeof(MODE_INFO));
vp9_update_mode_info_border(cm, cm->mip);
vp9_update_mode_info_in_image(cm, cm->mi);
vp9_update_mode_info_border(cm, cm->prev_mip);
vp9_update_mode_info_in_image(cm, cm->prev_mi);
set_mb_mi(cm, aligned_width, aligned_height);
setup_mi(cm);
}
......@@ -14,6 +14,8 @@
#include "vp9/common/vp9_onyxc_int.h"
void vp9_initialize_common();
void vp9_update_mode_info_border(VP9_COMMON *cpi, MODE_INFO *mi);
void vp9_update_mode_info_in_image(VP9_COMMON *cpi, MODE_INFO *mi);
......
......@@ -16,8 +16,6 @@
#define LOG2_MI_SIZE 3
#define MI_SIZE (1 << LOG2_MI_SIZE)
#define MI_UV_SIZE (1 << (LOG2_MI_SIZE - 1))
#define MI_MASK ((64 >> LOG2_MI_SIZE) - 1)
typedef enum BLOCK_SIZE_TYPE {
......
......@@ -26,8 +26,6 @@
/* Create/destroy static data structures. */
void vp9_initialize_common(void);
// Define the number of candidate reference buffers.
#define NUM_REF_FRAMES 8
#define NUM_REF_FRAMES_LG2 3
......@@ -248,9 +246,6 @@ typedef struct VP9Common {
int near_boffset[3];
int version;
#ifdef PACKET_TESTING
VP9_HEADER oh;
#endif
double bitrate;
double framerate;
......
......@@ -530,25 +530,6 @@ static void setup_token_decoder(VP9D_COMP *pbi,
"Failed to allocate bool decoder %d", 1);
}
static void init_frame(VP9D_COMP *pbi) {
VP9_COMMON *const pc = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
if (pc->frame_type == KEY_FRAME) {
vp9_setup_past_independence(pc, xd);
// All buffers are implicitly updated on key frames.
pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
} else if (pc->error_resilient_mode) {
vp9_setup_past_independence(pc, xd);
}
xd->mode_info_context = pc->mi;
xd->prev_mode_info_context = pc->prev_mi;
xd->frame_type = pc->frame_type;
xd->mode_info_context->mbmi.mode = DC_PRED;
xd->mode_info_stride = pc->mode_info_stride;
}
static void read_coef_probs_common(FRAME_CONTEXT *fc, TX_SIZE tx_size,
vp9_reader *r) {
const int entropy_nodes_update = UNCONSTRAINED_NODES;
......@@ -646,22 +627,6 @@ static void setup_segmentation(VP9_COMMON *pc, MACROBLOCKD *xd, vp9_reader *r) {
}
}
static void setup_pred_probs(VP9_COMMON *pc, vp9_reader *r) {
// Read common prediction model status flag probability updates for the
// reference frame
if (pc->frame_type == KEY_FRAME) {
// Set the prediction probabilities to defaults
pc->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
pc->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
pc->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
} else {
int i;
for (i = 0; i < PREDICTION_PROBS; ++i)
if (vp9_read_bit(r))
pc->ref_pred_probs[i] = vp9_read_prob(r);
}
}
static void setup_loopfilter(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
......@@ -716,9 +681,10 @@ static void setup_quantization(VP9D_COMP *pbi, struct vp9_read_bit_buffer *rb) {
vp9_init_dequantizer(cm);
}
static INTERPOLATIONFILTERTYPE read_mcomp_filter_type(vp9_reader *r) {
return vp9_read_bit(r) ? SWITCHABLE
: vp9_read_literal(r, 2);
static INTERPOLATIONFILTERTYPE read_interp_filter_type(
struct vp9_read_bit_buffer *rb) {
return vp9_rb_read_bit(rb) ? SWITCHABLE
: vp9_rb_read_literal(rb, 2);
}
static void read_frame_size(VP9_COMMON *cm,
......@@ -757,8 +723,8 @@ static void setup_frame_size(VP9D_COMP *pbi, int scaling_active,
if (vp9_alloc_frame_buffers(pc, width, height))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate frame buffers");
pbi->initial_width = width;
pbi->initial_height = height;
pbi->initial_width = width;
pbi->initial_height = height;
} else {
if (width > pbi->initial_width)
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
......@@ -776,6 +742,10 @@ static void setup_frame_size(VP9D_COMP *pbi, int scaling_active,
vp9_update_frame_size(pc);
}
vp9_realloc_frame_buffer(&pc->yv12_fb[pc->new_fb_idx], pc->width, pc->height,
pc->subsampling_x, pc->subsampling_y,
VP9BORDERINPIXELS);
}
static void update_frame_context(FRAME_CONTEXT *fc) {
......@@ -784,10 +754,8 @@ static void update_frame_context(FRAME_CONTEXT *fc) {
vp9_copy(fc->pre_uv_mode_prob, fc->uv_mode_prob);
vp9_copy(fc->pre_partition_prob, fc->partition_prob);
fc->pre_nmvc = fc->nmvc;
vp9_copy(fc->pre_switchable_interp_prob,
fc->switchable_interp_prob);
vp9_copy(fc->pre_inter_mode_probs,
fc->inter_mode_probs);
vp9_copy(fc->pre_switchable_interp_prob, fc->switchable_interp_prob);
vp9_copy(fc->pre_inter_mode_probs, fc->inter_mode_probs);
vp9_zero(fc->coef_counts);
vp9_zero(fc->eob_branch_counts);
......@@ -909,8 +877,9 @@ static void error_handler(void *data, int bit_offset) {
size_t read_uncompressed_header(VP9D_COMP *pbi,
struct vp9_read_bit_buffer *rb) {
VP9_COMMON *const cm = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
int scaling_active;
int scaling_active, i;
cm->last_frame_type = cm->frame_type;
cm->frame_type = (FRAME_TYPE) vp9_rb_read_bit(rb);
cm->version = vp9_rb_read_literal(rb, 3);
......@@ -923,22 +892,13 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
if (vp9_rb_read_literal(rb, 8) != SYNC_CODE_0 ||
vp9_rb_read_literal(rb, 8) != SYNC_CODE_1 ||
vp9_rb_read_literal(rb, 8) != SYNC_CODE_2) {
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code");
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid frame sync code");
}
}
setup_frame_size(pbi, scaling_active, rb);
if (!cm->show_frame) {
cm->intra_only = vp9_rb_read_bit(rb);
} else {
cm->intra_only = 0;
}
cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
cm->error_resilient_mode = vp9_rb_read_bit(rb);
if (!cm->error_resilient_mode) {
cm->reset_frame_context = vp9_rb_read_bit(rb);
......@@ -950,6 +910,44 @@ size_t read_uncompressed_header(VP9D_COMP *pbi,
cm->frame_parallel_decoding_mode = 1;
}
if (cm->frame_type == KEY_FRAME) {
vp9_setup_past_independence(cm, xd);
pbi->refresh_frame_flags = (1 << NUM_REF_FRAMES) - 1;
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
cm->active_ref_idx[i] = cm->new_fb_idx;
cm->ref_pred_probs[0] = DEFAULT_PRED_PROB_0;
cm->ref_pred_probs[1] = DEFAULT_PRED_PROB_1;
cm->ref_pred_probs[2] = DEFAULT_PRED_PROB_2;
} else {
if (cm->error_resilient_mode)
vp9_setup_past_independence(cm, xd);
pbi->refresh_frame_flags = vp9_rb_read_literal(rb, NUM_REF_FRAMES);
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
const int ref = vp9_rb_read_literal(rb, NUM_REF_FRAMES_LG2);
cm->active_ref_idx[i] = cm->ref_frame_map[ref];
vp9_setup_scale_factors(cm, i);
}
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
cm->ref_frame_sign_bias[i + 1] = vp9_rb_read_bit(rb);
for (i = 0; i < PREDICTION_PROBS; ++i)
if (vp9_rb_read_bit(rb))
cm->ref_pred_probs[i] = vp9_rb_read_literal(rb, 8);
xd->allow_high_precision_mv = vp9_rb_read_bit(rb);
cm->mcomp_filter_type = read_interp_filter_type(rb);
}
cm->intra_only = cm->show_frame ? 0 : vp9_rb_read_bit(rb);
cm->frame_context_idx = vp9_rb_read_literal(rb, NUM_FRAME_CONTEXTS_LG2);
cm->clr_type = (YUV_TYPE)vp9_rb_read_bit(rb);
setup_loopfilter(pbi, rb);
setup_quantization(pbi, rb);
......@@ -961,7 +959,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
vp9_reader header_bc, residual_bc;
VP9_COMMON *const pc = &pbi->common;
MACROBLOCKD *const xd = &pbi->mb;
YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
const uint8_t *data = pbi->source;
const uint8_t *data_end = pbi->source + pbi->source_sz;
......@@ -969,6 +967,7 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
pc, error_handler };
const size_t first_partition_size = read_uncompressed_header(pbi, &rb);
const int keyframe = pc->frame_type == KEY_FRAME;
YV12_BUFFER_CONFIG *new_fb = &pc->yv12_fb[pc->new_fb_idx];
data += vp9_rb_bytes_read(&rb);
xd->corrupted = 0;
......@@ -981,15 +980,13 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
vp9_setup_version(pc);
if (!read_is_valid(data, first_partition_size, data_end))
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length");
init_frame(pbi);
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet or corrupt partition 0 length");
// Reset the frame pointers to the current frame size
vp9_realloc_frame_buffer(new_fb, pc->width, pc->height,
pc->subsampling_x, pc->subsampling_y,
VP9BORDERINPIXELS);
xd->mode_info_context = pc->mi;
xd->prev_mode_info_context = pc->prev_mi;
xd->frame_type = pc->frame_type;
xd->mode_info_stride = pc->mode_info_stride;
if (vp9_reader_init(&header_bc, data, first_partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
......@@ -1011,44 +1008,15 @@ int vp9_decode_frame(VP9D_COMP *pbi, const uint8_t **p_data_end) {
xd->itxm_add_uv_block = vp9_idct_add_uv_block;
}
// Determine if the golden frame or ARF buffer should be updated and how.
// For all non key frames the GF and ARF refresh flags and sign bias
// flags must be set explicitly.
if (keyframe) {
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
pc->active_ref_idx[i] = pc->new_fb_idx;
} else {
// Should the GF or ARF be updated from the current frame
pbi->refresh_frame_flags = vp9_read_literal(&header_bc, NUM_REF_FRAMES);
// Select active reference frames and calculate scaling factors
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i) {
const int ref = vp9_read_literal(&header_bc, NUM_REF_FRAMES_LG2);
pc->active_ref_idx[i] = pc->ref_frame_map[ref];
vp9_setup_scale_factors(pc, i);
}
// Read the sign bias for each reference frame buffer.
for (i = 0; i < ALLOWED_REFS_PER_FRAME; ++i)
pc->ref_frame_sign_bias[i + 1] = vp9_read_bit(&header_bc);
xd->allow_high_precision_mv = vp9_read_bit(&header_bc);
pc->mcomp_filter_type = read_mcomp_filter_type(&header_bc);
// To enable choice of different interpolation filters
if (!keyframe)
vp9_setup_interp_filters(xd, pc->mcomp_filter_type, pc);
}
pc->fc = pc->frame_contexts[pc->frame_context_idx];
setup_segmentation(pc, xd, &header_bc);
setup_pred_probs(pc, &header_bc);
setup_txfm_mode(pc, xd->lossless, &header_bc);
// Read inter mode probability context updates
update_frame_context(&pc->fc);
read_coef_probs(pbi, &header_bc);
......
......@@ -53,11 +53,6 @@ extern unsigned int active_section;
static int update_bits[255];
static INLINE void write_le16(uint8_t *p, int value) {
p[0] = value;
p[1] = value >> 8;
}
static INLINE void write_le32(uint8_t *p, int value) {
p[0] = value;
p[1] = value >> 8;
......@@ -1155,6 +1150,8 @@ static void update_coef_probs_common(vp9_writer* const bc, VP9_COMP *cpi,
}
static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
const TXFM_MODE txfm_mode = cpi->common.txfm_mode;
vp9_clear_system_state();
// Build the cofficient contexts based on counts collected in encode loop
......@@ -1162,18 +1159,15 @@ static void update_coef_probs(VP9_COMP* const cpi, vp9_writer* const bc) {
update_coef_probs_common(bc, cpi, TX_4X4);
/* do not do this if not even allowed */
if (cpi->common.txfm_mode != ONLY_4X4) {
// do not do this if not even allowed
if (txfm_mode > ONLY_4X4)
update_coef_probs_common(bc, cpi, TX_8X8);
}
if (cpi->common.txfm_mode > ALLOW_8X8) {
if (txfm_mode > ALLOW_8X8)
update_coef_probs_common(bc, cpi, TX_16X16);
}
if (cpi->common.txfm_mode > ALLOW_16X16) {
if (txfm_mode > ALLOW_16X16)
update_coef_probs_common(bc, cpi, TX_32X32);
}
}
static void segment_reference_frames(VP9_COMP *cpi) {
......@@ -1381,6 +1375,38 @@ static void encode_txfm(VP9_COMP *cpi, vp9_writer *w) {
}
}
static void write_interp_filter_type(INTERPOLATIONFILTERTYPE type,
struct vp9_write_bit_buffer *wb) {
vp9_wb_write_bit(wb, type == SWITCHABLE);
if (type != SWITCHABLE)
vp9_wb_write_literal(wb, type, 2);
}
static void fix_mcomp_filter_type(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
if (cm->mcomp_filter_type == SWITCHABLE) {
// Check to see if only one of the filters is actually used
int count[VP9_SWITCHABLE_FILTERS];
int i, j, c = 0;
for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
count[i] = 0;
for (j = 0; j <= VP9_SWITCHABLE_FILTERS; ++j)
count[i] += cm->fc.switchable_interp_count[j][i];
c += (count[i] > 0);
}
if (c == 1) {
// Only one filter is used. So set the filter at frame level
for (i = 0; i < VP9_SWITCHABLE_FILTERS; ++i) {
if (count[i]) {
cm->mcomp_filter_type = vp9_switchable_interp[i];
break;
}
}
}