Added cabac bit cost calculations to SAO search

This commit is contained in:
Marko Viitanen 2014-09-11 16:42:27 +03:00
parent 5f732126c3
commit b274e7adcd

View file

@ -22,6 +22,7 @@
*/ */
#include "sao.h" #include "sao.h"
#include "rdo.h"
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
@ -144,52 +145,61 @@ static int sao_check_merge(const sao_info *sao_candidate, int type,
} }
static int sao_mode_bits_none(sao_info *sao_top, sao_info *sao_left) static float sao_mode_bits_none(const encoder_state * const encoder_state, sao_info *sao_top, sao_info *sao_left)
{ {
int mode_bits = 0; float mode_bits = 0.0;
cabac_data * const cabac = &encoder_state->cabac;
const cabac_ctx *ctx = NULL;
// FL coded merges. // FL coded merges.
if (sao_left != NULL) { if (sao_left != NULL) {
mode_bits += 1; ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_left->type == SAO_TYPE_NONE ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_left, SAO_TYPE_NONE, 0, 0, 0)) { if (sao_check_merge(sao_left, SAO_TYPE_NONE, 0, 0, 0)) {
return mode_bits; return mode_bits;
} }
} }
if (sao_top != NULL) { if (sao_top != NULL) {
mode_bits += 1; ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_top->type == SAO_TYPE_NONE ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_top, SAO_TYPE_NONE, 0, 0, 0)) { if (sao_check_merge(sao_top, SAO_TYPE_NONE, 0, 0, 0)) {
return mode_bits; return mode_bits;
} }
} }
// TR coded type_idx_, none = 0 // TR coded type_idx_, none = 0
mode_bits += 1; ctx = &(cabac->ctx_sao_type_idx_model);
mode_bits += CTX_ENTROPY_FBITS(ctx, 0);
return mode_bits; return mode_bits;
} }
static int sao_mode_bits_edge(int edge_class, int offsets[NUM_SAO_EDGE_CATEGORIES], static float sao_mode_bits_edge(const encoder_state * const encoder_state,
int edge_class, int offsets[NUM_SAO_EDGE_CATEGORIES],
sao_info *sao_top, sao_info *sao_left) sao_info *sao_top, sao_info *sao_left)
{ {
int mode_bits = 0; float mode_bits = 0.0;
cabac_data * const cabac = &encoder_state->cabac;
const cabac_ctx *ctx = NULL;
// FL coded merges. // FL coded merges.
if (sao_left != NULL) { if (sao_left != NULL) {
mode_bits += 1; ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_check_merge(sao_left, SAO_TYPE_EDGE, offsets, 0, edge_class) ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_left, SAO_TYPE_EDGE, offsets, 0, edge_class)) { if (sao_check_merge(sao_left, SAO_TYPE_EDGE, offsets, 0, edge_class)) {
return mode_bits; return mode_bits;
} }
} }
if (sao_top != NULL) { if (sao_top != NULL) {
mode_bits += 1; ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_check_merge(sao_top, SAO_TYPE_EDGE, offsets, 0, edge_class) ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_top, SAO_TYPE_EDGE, offsets, 0, edge_class)) { if (sao_check_merge(sao_top, SAO_TYPE_EDGE, offsets, 0, edge_class)) {
return mode_bits; return mode_bits;
} }
} }
// TR coded type_idx_, edge = 2 = cMax // TR coded type_idx_, edge = 2 = cMax
mode_bits += 1; ctx = &(cabac->ctx_sao_type_idx_model);
mode_bits += CTX_ENTROPY_FBITS(ctx, 1) + 1.0;
// TR coded offsets. // TR coded offsets.
{ {
@ -204,38 +214,38 @@ static int sao_mode_bits_edge(int edge_class, int offsets[NUM_SAO_EDGE_CATEGORIE
} }
} }
// TR coded sao_eo_class_ mode_bits += 2.0;
if (edge_class == SAO_EO0 || edge_class == SAO_EO3) {
mode_bits += 1;
} else {
mode_bits += 2;
}
return mode_bits; return mode_bits;
} }
static int sao_mode_bits_band(int band_position, int offsets[5], static float sao_mode_bits_band(const encoder_state * const encoder_state,
int band_position, int offsets[5],
sao_info *sao_top, sao_info *sao_left) sao_info *sao_top, sao_info *sao_left)
{ {
int mode_bits = 0; float mode_bits = 0.0;
cabac_data * const cabac = &encoder_state->cabac;
const cabac_ctx *ctx = NULL;
// FL coded merges. // FL coded merges.
if (sao_left != NULL) { if (sao_left != NULL) {
mode_bits += 1; const cabac_ctx *ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_check_merge(sao_left, SAO_TYPE_EDGE, offsets, band_position, 0) ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_left, SAO_TYPE_BAND, offsets, band_position, 0)) { if (sao_check_merge(sao_left, SAO_TYPE_BAND, offsets, band_position, 0)) {
return mode_bits; return mode_bits;
} }
} }
if (sao_top != NULL) { if (sao_top != NULL) {
mode_bits += 1; const cabac_ctx *ctx = &(cabac->ctx_sao_merge_flag_model);
mode_bits += sao_check_merge(sao_top, SAO_TYPE_EDGE, offsets, band_position, 0) ? CTX_ENTROPY_FBITS(ctx, 1) : CTX_ENTROPY_FBITS(ctx, 0);
if (sao_check_merge(sao_top, SAO_TYPE_BAND, offsets, band_position, 0)) { if (sao_check_merge(sao_top, SAO_TYPE_BAND, offsets, band_position, 0)) {
return mode_bits; return mode_bits;
} }
} }
// TR coded sao_type_idx_, band = 1 // TR coded sao_type_idx_, band = 1
mode_bits += 2; ctx = &(cabac->ctx_sao_type_idx_model);
mode_bits += CTX_ENTROPY_FBITS(ctx, 1) + 1.0;
// TR coded offsets and possible FL coded offset signs. // TR coded offsets and possible FL coded offset signs.
{ {
@ -244,16 +254,16 @@ static int sao_mode_bits_band(int band_position, int offsets[5],
int abs_offset = abs(offsets[i+1]); int abs_offset = abs(offsets[i+1]);
if (abs_offset == 0) { if (abs_offset == 0) {
mode_bits += abs_offset + 1; mode_bits += abs_offset + 1;
} else if (abs_offset == SAO_ABS_OFFSET_MAX) { } else if(abs_offset == SAO_ABS_OFFSET_MAX) {
mode_bits += abs_offset + 1 + 1; mode_bits += abs_offset + 1 + 1;
} else { } else {
mode_bits += abs_offset + 2 + 1; mode_bits += abs_offset + 2 + 1;
} }
} }
} }
// FL coded band position. // FL coded band position.
mode_bits += 5; mode_bits += 5.0;
return mode_bits; return mode_bits;
} }
@ -669,8 +679,8 @@ static void sao_search_edge_sao(const encoder_state * const encoder_state,
} }
{ {
int mode_bits = sao_mode_bits_edge(edge_class, edge_offset, sao_top, sao_left); float mode_bits = sao_mode_bits_edge(encoder_state,edge_class, edge_offset, sao_top, sao_left);
sum_ddistortion += (int)((double)mode_bits*(encoder_state->global->cur_lambda_cost+0.5)); sum_ddistortion += (int)((double)mode_bits*encoder_state->global->cur_lambda_cost+0.5);
} }
// SAO is not applied for category 0. // SAO is not applied for category 0.
edge_offset[SAO_EO_CAT0] = 0; edge_offset[SAO_EO_CAT0] = 0;
@ -701,7 +711,7 @@ static void sao_search_band_sao(const encoder_state * const encoder_state, const
int sao_bands[2][32]; int sao_bands[2][32];
int temp_offsets[5]; int temp_offsets[5];
int ddistortion; int ddistortion;
int temp_rate = 0; float temp_rate = 0.0;
memset(sao_bands, 0, 2 * 32 * sizeof(int)); memset(sao_bands, 0, 2 * 32 * sizeof(int));
for (i = 0; i < buf_cnt; ++i) { for (i = 0; i < buf_cnt; ++i) {
@ -711,8 +721,8 @@ static void sao_search_band_sao(const encoder_state * const encoder_state, const
ddistortion = calc_sao_band_offsets(sao_bands, &temp_offsets[1], &sao_out->band_position); ddistortion = calc_sao_band_offsets(sao_bands, &temp_offsets[1], &sao_out->band_position);
temp_rate = sao_mode_bits_band(sao_out->band_position, temp_offsets, sao_top, sao_left); temp_rate = sao_mode_bits_band(encoder_state, sao_out->band_position, temp_offsets, sao_top, sao_left);
ddistortion += (int)((double)temp_rate*(encoder_state->global->cur_lambda_cost+0.5)); ddistortion += (int)((double)temp_rate*encoder_state->global->cur_lambda_cost+0.5);
// Select band sao over edge sao when distortion is lower // Select band sao over edge sao when distortion is lower
if (ddistortion < sao_out->ddistortion) { if (ddistortion < sao_out->ddistortion) {
@ -753,8 +763,8 @@ static void sao_search_best_mode(const encoder_state * const encoder_state, cons
sao_search_band_sao(encoder_state, data, recdata, block_width, block_height, buf_cnt, &band_sao, sao_top, sao_left); sao_search_band_sao(encoder_state, data, recdata, block_width, block_height, buf_cnt, &band_sao, sao_top, sao_left);
{ {
int mode_bits = sao_mode_bits_edge(edge_sao.eo_class, edge_sao.offsets, sao_top, sao_left); float mode_bits = sao_mode_bits_edge(encoder_state, edge_sao.eo_class, edge_sao.offsets, sao_top, sao_left);
int ddistortion = mode_bits * (int)(encoder_state->global->cur_lambda_cost + 0.5); int ddistortion = (int)(mode_bits * encoder_state->global->cur_lambda_cost + 0.5);
unsigned buf_i; unsigned buf_i;
for (buf_i = 0; buf_i < buf_cnt; ++buf_i) { for (buf_i = 0; buf_i < buf_cnt; ++buf_i) {
@ -767,8 +777,8 @@ static void sao_search_best_mode(const encoder_state * const encoder_state, cons
} }
{ {
int mode_bits = sao_mode_bits_band(band_sao.band_position, band_sao.offsets, sao_top, sao_left); float mode_bits = sao_mode_bits_band(encoder_state, band_sao.band_position, band_sao.offsets, sao_top, sao_left);
int ddistortion = mode_bits * (int)(encoder_state->global->cur_lambda_cost + 0.5); int ddistortion = (int)(mode_bits * encoder_state->global->cur_lambda_cost + 0.5);
unsigned buf_i; unsigned buf_i;
for (buf_i = 0; buf_i < buf_cnt; ++buf_i) { for (buf_i = 0; buf_i < buf_cnt; ++buf_i) {
@ -789,7 +799,7 @@ static void sao_search_best_mode(const encoder_state * const encoder_state, cons
// Choose between SAO and doing nothing, taking into account the // Choose between SAO and doing nothing, taking into account the
// rate-distortion cost of coding do nothing. // rate-distortion cost of coding do nothing.
{ {
int cost_of_nothing = sao_mode_bits_none(sao_top, sao_left) * (int)(encoder_state->global->cur_lambda_cost + 0.5); int cost_of_nothing = (int)(sao_mode_bits_none(encoder_state, sao_top, sao_left) * encoder_state->global->cur_lambda_cost + 0.5);
if (sao_out->ddistortion >= cost_of_nothing) { if (sao_out->ddistortion >= cost_of_nothing) {
sao_out->type = SAO_TYPE_NONE; sao_out->type = SAO_TYPE_NONE;
} }