2010-05-18 17:58:33 +02:00
|
|
|
/*
|
2010-09-09 14:16:39 +02:00
|
|
|
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
|
2010-05-18 17:58:33 +02:00
|
|
|
*
|
2010-06-18 18:39:21 +02:00
|
|
|
* Use of this source code is governed by a BSD-style license
|
2010-06-04 22:19:40 +02:00
|
|
|
* that can be found in the LICENSE file in the root of the source
|
|
|
|
* tree. An additional intellectual property rights grant can be found
|
2010-06-18 18:39:21 +02:00
|
|
|
* in the file PATENTS. All contributing project authors may
|
2010-06-04 22:19:40 +02:00
|
|
|
* be found in the AUTHORS file in the root of the source tree.
|
2010-05-18 17:58:33 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2010-05-20 20:44:18 +02:00
|
|
|
#include "vpx_ports/config.h"
|
2010-05-18 17:58:33 +02:00
|
|
|
#include "blockd.h"
|
|
|
|
#include "vpx_mem/vpx_mem.h"
|
|
|
|
#include "onyxc_int.h"
|
|
|
|
#include "findnearmv.h"
|
|
|
|
#include "entropymode.h"
|
|
|
|
#include "systemdependent.h"
|
|
|
|
|
|
|
|
|
|
|
|
extern void vp8_init_scan_order_mask();
|
|
|
|
|
2012-01-28 11:07:08 +01:00
|
|
|
static void update_mode_info_border( VP8_COMMON *cpi, MODE_INFO *mi_base )
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
2012-01-28 11:07:08 +01:00
|
|
|
int stride = cpi->mode_info_stride;
|
2010-05-18 17:58:33 +02:00
|
|
|
int i;
|
|
|
|
|
2012-01-28 11:07:08 +01:00
|
|
|
// Clear down top border row
|
|
|
|
vpx_memset(mi_base, 0, sizeof(MODE_INFO) * cpi->mode_info_stride);
|
|
|
|
|
|
|
|
// Clear left border column
|
|
|
|
for (i = 1; i < cpi->mb_rows+1; i++)
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
2012-01-28 11:07:08 +01:00
|
|
|
vpx_memset(&mi_base[i*stride], 0, sizeof(MODE_INFO));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void update_mode_info_in_image( VP8_COMMON *cpi, MODE_INFO *mi )
|
|
|
|
{
|
|
|
|
int stride = cpi->mode_info_stride;
|
|
|
|
int rows = cpi->mb_rows;
|
|
|
|
int cols = cpi->mb_cols;
|
|
|
|
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
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
}
|
2010-07-22 14:07:32 +02:00
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
void vp8_de_alloc_frame_buffers(VP8_COMMON *oci)
|
|
|
|
{
|
2010-07-22 14:07:32 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < NUM_YV12_BUFFERS; i++)
|
|
|
|
vp8_yv12_de_alloc_frame_buffer(&oci->yv12_fb[i]);
|
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
vp8_yv12_de_alloc_frame_buffer(&oci->temp_scale_frame);
|
|
|
|
vp8_yv12_de_alloc_frame_buffer(&oci->post_proc_buffer);
|
|
|
|
|
2010-08-31 16:49:57 +02:00
|
|
|
vpx_free(oci->above_context);
|
2010-05-18 17:58:33 +02:00
|
|
|
vpx_free(oci->mip);
|
2011-05-02 15:30:51 +02:00
|
|
|
vpx_free(oci->prev_mip);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-08-31 16:49:57 +02:00
|
|
|
oci->above_context = 0;
|
2010-05-18 17:58:33 +02:00
|
|
|
oci->mip = 0;
|
2011-05-02 15:30:51 +02:00
|
|
|
oci->prev_mip = 0;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
int vp8_alloc_frame_buffers(VP8_COMMON *oci, int width, int height)
|
|
|
|
{
|
2010-07-22 14:07:32 +02:00
|
|
|
int i;
|
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
|
|
|
|
2010-10-28 01:04:02 +02:00
|
|
|
/* our internal buffers are always multiples of 16 */
|
2010-05-18 17:58:33 +02:00
|
|
|
if ((width & 0xf) != 0)
|
|
|
|
width += 16 - (width & 0xf);
|
|
|
|
|
|
|
|
if ((height & 0xf) != 0)
|
|
|
|
height += 16 - (height & 0xf);
|
|
|
|
|
|
|
|
|
2010-07-22 14:07:32 +02:00
|
|
|
for (i = 0; i < NUM_YV12_BUFFERS; i++)
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
2011-06-24 17:43:40 +02:00
|
|
|
oci->fb_idx_ref_cnt[i] = 0;
|
2011-04-20 14:12:23 +02:00
|
|
|
oci->yv12_fb[i].flags = 0;
|
|
|
|
if (vp8_yv12_alloc_frame_buffer(&oci->yv12_fb[i], width, height, VP8BORDERINPIXELS) < 0)
|
2010-07-22 14:07:32 +02:00
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
2011-02-17 12:59:48 +01:00
|
|
|
return 1;
|
2010-07-22 14:07:32 +02:00
|
|
|
}
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2010-07-22 14:07:32 +02:00
|
|
|
oci->new_fb_idx = 0;
|
|
|
|
oci->lst_fb_idx = 1;
|
|
|
|
oci->gld_fb_idx = 2;
|
|
|
|
oci->alt_fb_idx = 3;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-07-22 14:07:32 +02:00
|
|
|
oci->fb_idx_ref_cnt[0] = 1;
|
|
|
|
oci->fb_idx_ref_cnt[1] = 1;
|
|
|
|
oci->fb_idx_ref_cnt[2] = 1;
|
|
|
|
oci->fb_idx_ref_cnt[3] = 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-07-22 14:07:32 +02:00
|
|
|
if (vp8_yv12_alloc_frame_buffer(&oci->temp_scale_frame, width, 16, VP8BORDERINPIXELS) < 0)
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
2011-02-17 12:59:48 +01:00
|
|
|
return 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer, width, height, VP8BORDERINPIXELS) < 0)
|
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
2011-02-17 12:59:48 +01:00
|
|
|
return 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
oci->mb_rows = height >> 4;
|
|
|
|
oci->mb_cols = 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)
|
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
2011-02-17 12:59:48 +01:00
|
|
|
return 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
oci->mi = oci->mip + oci->mode_info_stride + 1;
|
|
|
|
|
2011-05-02 15:30:51 +02:00
|
|
|
/* allocate memory for last frame MODE_INFO array */
|
2012-02-03 16:10:44 +01:00
|
|
|
|
2011-05-02 15:30:51 +02:00
|
|
|
oci->prev_mip = vpx_calloc((oci->mb_cols + 1) * (oci->mb_rows + 1), sizeof(MODE_INFO));
|
|
|
|
|
|
|
|
if (!oci->prev_mip)
|
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
oci->prev_mi = oci->prev_mip + oci->mode_info_stride + 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-08-31 16:49:57 +02:00
|
|
|
oci->above_context = vpx_calloc(sizeof(ENTROPY_CONTEXT_PLANES) * oci->mb_cols, 1);
|
2010-05-18 17:58:33 +02:00
|
|
|
|
2010-08-31 16:49:57 +02:00
|
|
|
if (!oci->above_context)
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
2011-02-17 12:59:48 +01:00
|
|
|
return 1;
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
2012-01-28 11:07:08 +01:00
|
|
|
update_mode_info_border(oci, oci->mip);
|
|
|
|
update_mode_info_in_image(oci, oci->mi);
|
2011-05-19 19:57:45 +02:00
|
|
|
#if CONFIG_ERROR_CONCEALMENT
|
2012-01-28 11:07:08 +01:00
|
|
|
update_mode_info_border(oci, oci->prev_mip);
|
|
|
|
update_mode_info_in_image(oci, oci->prev_mi);
|
2011-05-19 19:57:45 +02:00
|
|
|
#endif
|
2010-05-18 17:58:33 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void vp8_setup_version(VP8_COMMON *cm)
|
|
|
|
{
|
2010-06-01 17:14:25 +02:00
|
|
|
if (cm->version & 0x4)
|
|
|
|
{
|
|
|
|
if (!CONFIG_EXPERIMENTAL)
|
|
|
|
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
|
|
|
|
"Bitstream was created by an experimental "
|
2011-11-30 17:05:45 +01:00
|
|
|
"encoder");
|
2010-06-01 17:14:25 +02:00
|
|
|
cm->experimental = 1;
|
|
|
|
}
|
2011-11-30 17:05:45 +01:00
|
|
|
|
2010-06-01 17:14:25 +02:00
|
|
|
switch (cm->version & 0x3)
|
2010-05-18 17:58:33 +02:00
|
|
|
{
|
|
|
|
case 0:
|
|
|
|
cm->no_lpf = 0;
|
2011-04-25 23:37:41 +02:00
|
|
|
cm->filter_type = NORMAL_LOOPFILTER;
|
2010-05-18 17:58:33 +02:00
|
|
|
cm->use_bilinear_mc_filter = 0;
|
|
|
|
cm->full_pixel = 0;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
cm->no_lpf = 0;
|
2011-04-25 23:37:41 +02:00
|
|
|
cm->filter_type = SIMPLE_LOOPFILTER;
|
2010-05-18 17:58:33 +02:00
|
|
|
cm->use_bilinear_mc_filter = 1;
|
|
|
|
cm->full_pixel = 0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
cm->no_lpf = 1;
|
2011-04-25 23:37:41 +02:00
|
|
|
cm->filter_type = NORMAL_LOOPFILTER;
|
2010-05-18 17:58:33 +02:00
|
|
|
cm->use_bilinear_mc_filter = 1;
|
|
|
|
cm->full_pixel = 0;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
cm->no_lpf = 1;
|
2011-04-25 23:37:41 +02:00
|
|
|
cm->filter_type = SIMPLE_LOOPFILTER;
|
2010-05-18 17:58:33 +02:00
|
|
|
cm->use_bilinear_mc_filter = 1;
|
|
|
|
cm->full_pixel = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void vp8_create_common(VP8_COMMON *oci)
|
|
|
|
{
|
|
|
|
vp8_machine_specific_config(oci);
|
2011-08-16 22:21:21 +02:00
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
vp8_init_mbmode_probs(oci);
|
2011-12-06 21:03:42 +01:00
|
|
|
|
2010-05-18 17:58:33 +02:00
|
|
|
vp8_default_bmode_probs(oci->fc.bmode_prob);
|
|
|
|
|
|
|
|
oci->mb_no_coeff_skip = 1;
|
Dual 16x16 inter prediction.
This patch introduces the concept of dual inter16x16 prediction. A
16x16 inter-predicted macroblock can use 2 references instead of 1,
where both references use the same mvmode (new, near/est, zero). In the
case of newmv, this means that two MVs are coded instead of one. The
frame can be encoded in 3 ways: all MBs single-prediction, all MBs dual
prediction, or per-MB single/dual prediction selection ("hybrid"), in
which case a single bit is coded per-MB to indicate whether the MB uses
single or dual inter prediction.
In the future, we can (maybe?) get further gains by mixing this with
Adrian's 32x32 work, per-segment dual prediction settings, or adding
support for dual splitmv/8x8mv inter prediction.
Gain (on derf-set, CQ mode) is ~2.8% (SSIM) or ~3.6% (glb PSNR). Most
gain is at medium/high bitrates, but there's minor gains at low bitrates
also. Output was confirmed to match between encoder and decoder.
Note for optimization people: this patch introduces a 2nd version of
16x16/8x8 sixtap/bilin functions, which does an avg instead of a
store. They may want to look and make sure this is implemented to
their satisfaction so we can optimize it best in the future.
Change-ID: I59dc84b07cbb3ccf073ac0f756d03d294cb19281
2011-12-06 20:53:02 +01:00
|
|
|
oci->dual_pred_mode = HYBRID_PREDICTION;
|
2010-05-18 17:58:33 +02:00
|
|
|
oci->no_lpf = 0;
|
2011-04-25 23:37:41 +02:00
|
|
|
oci->filter_type = NORMAL_LOOPFILTER;
|
2010-05-18 17:58:33 +02:00
|
|
|
oci->use_bilinear_mc_filter = 0;
|
|
|
|
oci->full_pixel = 0;
|
|
|
|
oci->multi_token_partition = ONE_PARTITION;
|
|
|
|
oci->clr_type = REG_YUV;
|
|
|
|
oci->clamp_type = RECON_CLAMP_REQUIRED;
|
|
|
|
|
2010-10-28 01:04:02 +02:00
|
|
|
/* Initialise reference frame sign bias structure to defaults */
|
2010-05-18 17:58:33 +02:00
|
|
|
vpx_memset(oci->ref_frame_sign_bias, 0, sizeof(oci->ref_frame_sign_bias));
|
|
|
|
|
2010-10-28 01:04:02 +02:00
|
|
|
/* Default disable buffer to buffer copying */
|
2010-05-18 17:58:33 +02:00
|
|
|
oci->copy_buffer_to_gf = 0;
|
|
|
|
oci->copy_buffer_to_arf = 0;
|
2011-08-31 21:01:58 +02:00
|
|
|
#if CONFIG_QIMODE
|
|
|
|
oci->kf_ymode_probs_update = 0;
|
|
|
|
#endif
|
2010-05-18 17:58:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void vp8_remove_common(VP8_COMMON *oci)
|
|
|
|
{
|
|
|
|
vp8_de_alloc_frame_buffers(oci);
|
|
|
|
}
|
|
|
|
|
|
|
|
void vp8_initialize_common()
|
|
|
|
{
|
|
|
|
vp8_coef_tree_initialize();
|
|
|
|
|
|
|
|
vp8_entropy_mode_init();
|
|
|
|
|
|
|
|
vp8_init_scan_order_mask();
|
|
|
|
|
|
|
|
}
|