[cleanup] remove all crypto related stuff, fix warnings, move estimate.m to tools/

This commit is contained in:
Marko Viitanen 2021-07-27 09:23:29 +03:00
parent 99a2b0384d
commit 5604b6f946
21 changed files with 19 additions and 371 deletions

View file

@ -80,27 +80,6 @@ AC_SEARCH_LIBS([log], [m c], [], [exit 1])
AC_SEARCH_LIBS([pow], [m c], [], [exit 1])
AC_SEARCH_LIBS([sqrt], [m c], [], [exit 1])
AC_ARG_WITH([cryptopp],
AS_HELP_STRING([--with-cryptopp],
[Build with cryptopp Enables selective encryption.]))
AS_IF([test "x$with_cryptopp" = "xyes"],
[PKG_CHECK_MODULES([cryptopp], [cryptopp],
[AC_DEFINE([KVZ_SEL_ENCRYPTION], [1], [With cryptopp])],
[PKG_CHECK_MODULES([cryptopp], [libcrypto++],
[AC_DEFINE([KVZ_SEL_ENCRYPTION], [1], [With cryptopp])],
[PKG_CHECK_MODULES([cryptopp], [libcryptopp],
[AC_DEFINE([KVZ_SEL_ENCRYPTION], [1], [With cryptopp])],
[AC_MSG_ERROR([neither cryptopp, libcrypto++ nor libcryptopp found with pkg-config])]
)]
)]
)]
)
AM_CONDITIONAL([USE_CRYPTOPP], [test "x$with_cryptopp" = "xyes"])
CPPFLAGS="$CPPFLAGS $cryptopp_CFLAGS"
LIBS="$LIBS $cryptopp_LIBS"
CPPFLAGS="-DKVZ_DLL_EXPORTS $CPPFLAGS"

View file

@ -34,15 +34,11 @@ kvazaar_LDADD = libkvazaar.la $(LIBS)
kvazaar_CPPFLAGS = -DKVZ_VERSION="`$(srcdir)/../tools/version.sh`"
if USE_CRYPTOPP
kvazaar_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
else
kvazaar_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
endif
libkvazaar_la_SOURCES = \
alf.c \
@ -162,8 +158,7 @@ libkvazaar_la_SOURCES = \
strategyselector.c \
strategyselector.h \
extras/libmd5.c \
extras/libmd5.h \
extras/crypto.h
extras/libmd5.h
libkvazaar_la_CFLAGS =
@ -175,18 +170,9 @@ libkvazaar_la_LIBADD = \
libkvazaar_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-number $(KVZ_API_VERSION)
if USE_CRYPTOPP
libkvazaar_la_SOURCES += \
extras/crypto.h \
extras/crypto.cpp
libkvazaar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
$(libkvazaar_la_LDFLAGS) $(LDFLAGS) -o $@
else
libkvazaar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libkvazaar_la_LDFLAGS) $(LDFLAGS) -o $@
endif
libaltivec_la_SOURCES = \
strategies/altivec/picture-altivec.c \

View file

@ -22,7 +22,6 @@
#include "encoder.h"
#include "encoderstate.h"
#include "extras/crypto.h"
#include "kvazaar.h"
#ifdef KVZ_DEBUG_PRINT_CABAC

View file

@ -126,7 +126,6 @@ int kvz_config_init(kvz_config *cfg)
cfg->calc_psnr = true;
cfg->mv_constraint = KVZ_MV_CONSTRAIN_NONE;
cfg->crypto_features = KVZ_CRYPTO_OFF;
cfg->me_early_termination = 1;
cfg->intra_rdo_et = 0;
@ -147,8 +146,6 @@ int kvz_config_init(kvz_config *cfg)
cfg->slices = KVZ_SLICES_NONE;
cfg->optional_key = NULL;
cfg->level = 62; // default hevc level, 6.2 (the highest)
cfg->force_level = true; // don't care about level limits by-default
cfg->high_tier = false;
@ -210,7 +207,6 @@ int kvz_config_destroy(kvz_config *cfg)
FREE_POINTER(cfg->tiles_height_split);
FREE_POINTER(cfg->slice_addresses_in_ts);
FREE_POINTER(cfg->roi.dqps);
FREE_POINTER(cfg->optional_key);
FREE_POINTER(cfg->fastrd_learning_outdir_fn);
}
free(cfg);
@ -1230,63 +1226,6 @@ int kvz_config_parse(kvz_config *cfg, const char *name, const char *value)
cfg->cu_split_termination = mode;
return result;
}
else if OPT("crypto")
{
// on, off, feature1+feature2
const char *token_begin = value;
const char *cur = token_begin;
cfg->crypto_features = KVZ_CRYPTO_OFF;
// If value is on or off, set all features to on or off.
int8_t toggle = 0;
if (parse_enum(token_begin, crypto_toggle_names, &toggle)) {
if (toggle == 1) {
cfg->crypto_features = KVZ_CRYPTO_ON;
}
} else {
// Try and parse "feature1+feature2" type list.
for (;;) {
if (*cur == '+' || *cur == '\0') {
int8_t feature = 0;
int num_chars = cur - token_begin;
if (parse_enum_n(token_begin, num_chars, crypto_feature_names, &feature)) {
cfg->crypto_features |= (1 << feature);
} else {
cfg->crypto_features = KVZ_CRYPTO_OFF;
return 0;
}
token_begin = cur + 1;
}
if (*cur == '\0') {
break;
} else {
++cur;
}
}
}
// Disallow turning on the encryption when it's not compiled in.
bool encryption_compiled_in = false;
#ifdef KVZ_SEL_ENCRYPTION
encryption_compiled_in = true;
#endif
if (!encryption_compiled_in && cfg->crypto_features) {
fprintf(stderr, "--crypto cannot be enabled because it's not compiled in.\n");
cfg->crypto_features = KVZ_CRYPTO_OFF;
return 0;
}
return 1;
}
else if OPT("key"){
int size_key = 16;
FREE_POINTER(cfg->optional_key);
cfg->optional_key = (uint8_t *)malloc(sizeof(uint8_t)*size_key);
return parse_array(value, cfg->optional_key, size_key, 0, 255);
}
else if OPT("me-early-termination"){
int8_t mode = 0;
int result = parse_enum(value, me_early_termination_names, &mode);

View file

@ -24,7 +24,6 @@
#include "context.h"
#include "cu.h"
#include "encoder.h"
#include "extras/crypto.h"
#include "global.h"
#include "imagelist.h"
#include "inter.h"
@ -54,7 +53,7 @@ static bool is_mts_allowed(encoder_state_t * const state, cu_info_t *const pred_
static void encode_mts_idx(encoder_state_t * const state,
cabac_data_t * const cabac,
cu_info_t *const pred_cu)
const cu_info_t *const pred_cu)
{
//TransformUnit &tu = *cu.firstTU;
int mts_idx = pred_cu->tr_idx;
@ -118,8 +117,8 @@ void kvz_encode_ts_residual(encoder_state_t* const state,
cabac->cur_ctx = base_coeff_group_ctx;
int maxCtxBins = (width * width * 7) >> 2;
unsigned scan_cg_last = -1;
unsigned scan_pos_last = -1;
unsigned scan_cg_last = (unsigned )-1;
unsigned scan_pos_last = (unsigned )-1;
for (int i = 0; i < width * width; i++) {
if (coeff[scan[i]]) {
@ -406,7 +405,7 @@ static void encode_transform_unit(encoder_state_t * const state,
width,
0,
scan_idx,
cur_pu,
(cu_info_t * )cur_pu,
true);
}
}
@ -423,7 +422,7 @@ static void encode_transform_unit(encoder_state_t * const state,
// corner of the block.
x -= 4;
y -= 4;
cur_pu = kvz_cu_array_at_const(frame->cu_array, x, y);
cur_pu = kvz_cu_array_at_const((const cu_array_t *)frame->cu_array, x, y);
}
}
@ -1067,18 +1066,18 @@ void kvz_encode_coding_tree(encoder_state_t * const state,
cabac_data_t * const cabac = &state->cabac;
const encoder_control_t * const ctrl = state->encoder_control;
const videoframe_t * const frame = state->tile->frame;
cu_info_t *cur_cu = kvz_cu_array_at_const(frame->cu_array, x, y);
const cu_info_t *cur_cu = kvz_cu_array_at_const((const cu_array_t * )frame->cu_array, x, y);
const int cu_width = LCU_WIDTH >> depth;
const int half_cu = cu_width >> 1;
const cu_info_t *left_cu = NULL;
if (x > 0) {
left_cu = kvz_cu_array_at_const(frame->cu_array, x - 1, y);
left_cu = kvz_cu_array_at_const((const cu_array_t*)frame->cu_array, x - 1, y);
}
const cu_info_t *above_cu = NULL;
if (y > 0) {
above_cu = kvz_cu_array_at_const(frame->cu_array, x, y - 1);
above_cu = kvz_cu_array_at_const((const cu_array_t*)frame->cu_array, x, y - 1);
}
uint8_t split_flag = GET_SPLITDATA(cur_cu, depth);

View file

@ -718,12 +718,6 @@ encoder_control_t* kvz_encoder_control_init(const kvz_config *const cfg)
encoder->cfg.vps_period = -1;
}
if(encoder->cfg.optional_key){
encoder->cfg.optional_key = MALLOC(uint8_t,16);
if (!encoder->cfg.optional_key) goto init_failed;
memcpy(encoder->cfg.optional_key, cfg->optional_key, 16);
}
for (int i = 0; i < cfg->num_used_table; i++) {
encoder->qp_map[i] = derive_chroma_QP_mapping_table(cfg, i);
}
@ -758,7 +752,6 @@ void kvz_encoder_control_free(encoder_control_t *const encoder)
FREE_POINTER(encoder->tiles_tile_id);
FREE_POINTER(encoder->cfg.roi.dqps);
FREE_POINTER(encoder->cfg.optional_key);
kvz_scalinglist_destroy(&encoder->scaling_list);

View file

@ -416,7 +416,6 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t
child_state->parent = parent_state;
child_state->children = MALLOC(encoder_state_t, 1);
child_state->children[0].encoder_control = NULL;
child_state->crypto_hdl = NULL;
child_state->must_code_qp_delta = false;
child_state->tqj_bitstream_written = NULL;
child_state->tqj_recon_done = NULL;

View file

@ -734,8 +734,6 @@ static void encoder_state_worker_encode_lcu_bitstream(void * opaque)
kvz_bitstream_align_zero(state->cabac.stream);
kvz_cabac_start(&state->cabac);
kvz_crypto_delete(&state->crypto_hdl);
}
}
@ -772,8 +770,6 @@ static void encoder_state_worker_encode_lcu_bitstream(void * opaque)
}
}
}
//fprintf(stderr, "Bitstream written: %d\r\n", lcu->id);
}
@ -794,11 +790,6 @@ static void encoder_state_encode_leaf(encoder_state_t * const state)
// Signaled slice QP may be different to frame QP with set-qp-in-cu enabled.
state->last_qp = ctrl->cfg.set_qp_in_cu ? 26 : state->frame->QP;
if (cfg->crypto_features) {
state->crypto_hdl = kvz_crypto_create(cfg);
state->crypto_prev_pos = 0;
}
// Select whether to encode the frame/tile in current thread or to define
// wavefront jobs for other threads to handle.
bool wavefront = state->type == ENCODER_STATE_TYPE_WAVEFRONT_ROW;

View file

@ -37,7 +37,6 @@
#include "tables.h"
#include "threadqueue.h"
#include "videoframe.h"
#include "extras/crypto.h"
struct kvz_rc_data;
@ -305,10 +304,6 @@ typedef struct encoder_state_t {
bitstream_t stream;
cabac_data_t cabac;
// Crypto stuff
crypto_handle_t *crypto_hdl;
uint32_t crypto_prev_pos;
uint32_t stats_bitstream_length; //Bitstream length written in bytes
//! \brief Lambda for SSE

View file

@ -1,140 +0,0 @@
#include <extras/crypto.h>
#ifndef KVZ_SEL_ENCRYPTION
int kvz_make_vs_ignore_crypto_not_having_symbols = 0;
#else
#include <cryptopp/aes.h>
#include <cryptopp/modes.h>
#include <cryptopp/osrng.h>
#if AESEncryptionStreamMode
typedef CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption cipher_t;
#else
typedef CryptoPP::CFB_Mode<CryptoPP::AES>::Decryption cipher_t;
#endif
struct crypto_handle_t {
cipher_t *cipher;
unsigned char key[CryptoPP::AES::DEFAULT_KEYLENGTH];
unsigned char iv[CryptoPP::AES::BLOCKSIZE];
unsigned char out_stream_counter[CryptoPP::AES::BLOCKSIZE];
unsigned char counter[CryptoPP::AES::BLOCKSIZE];
int couter_avail;
int counter_index;
int counter_index_pos;
};
static uint8_t default_IV[16] = {201, 75, 219, 152, 6, 245, 237, 107, 179, 194, 81, 29, 66, 98, 198, 0};
static uint8_t default_key[16] = {16, 213, 27, 56, 255, 127, 242, 112, 97, 126, 197, 204, 25, 59, 38, 30};
crypto_handle_t* kvz_crypto_create(const kvz_config *cfg)
{
crypto_handle_t* hdl = (crypto_handle_t*)calloc(1, sizeof(crypto_handle_t));
uint8_t *key;
if(cfg->optional_key!=NULL)
key = cfg->optional_key;
else
key = default_key;
for (int i = 0; i < 16; i++) {
hdl->iv [i] = default_IV[i];
hdl->counter[i] = (i<11)? default_IV[5+i] : key[i-11];
hdl->key[i] = key[i];
}
hdl->cipher = new cipher_t(hdl->key, CryptoPP::AES::DEFAULT_KEYLENGTH, hdl->iv);
hdl->couter_avail = 0;
hdl->counter_index = 0;
hdl->counter_index_pos = 0;
return hdl;
}
void kvz_crypto_delete(crypto_handle_t **hdl)
{
if (*hdl) {
delete (*hdl)->cipher;
(*hdl)->cipher = NULL;
}
FREE_POINTER(*hdl);
}
void kvz_crypto_decrypt(crypto_handle_t* hdl,
const uint8_t *in_stream,
int size_bits,
uint8_t *out_stream)
{
int num_bytes = ceil((double)size_bits/8);
hdl->cipher->ProcessData(out_stream, in_stream, num_bytes);
if (size_bits & 7) {
hdl->cipher->SetKeyWithIV(hdl->key, CryptoPP::AES::DEFAULT_KEYLENGTH, hdl->iv);
}
}
#if AESEncryptionStreamMode
static void increment_counter(unsigned char *counter)
{
counter[0]++;
}
static void decrypt_counter(crypto_handle_t *hdl)
{
hdl->cipher->ProcessData(hdl->out_stream_counter, hdl->counter, 16);
hdl->couter_avail = 128;
hdl->counter_index = 15;
hdl->counter_index_pos = 8;
increment_counter(hdl->counter);
}
unsigned kvz_crypto_get_key(crypto_handle_t *hdl, int nb_bits)
{
unsigned key = 0;
if (nb_bits > 32) {
fprintf(stderr, "The generator cannot generate %d bits (max 32 bits)\n", nb_bits);
return 0;
}
if (nb_bits == 0) return 0;
if (!hdl->couter_avail) {
decrypt_counter(hdl);
}
if(hdl->couter_avail >= nb_bits) {
hdl->couter_avail -= nb_bits;
} else {
hdl->couter_avail = 0;
}
int nb = 0;
while (nb_bits) {
if (nb_bits >= hdl->counter_index_pos) {
nb = hdl->counter_index_pos;
} else {
nb = nb_bits;
}
key <<= nb;
key += hdl->out_stream_counter[hdl->counter_index] & ((1 << nb) - 1);
hdl->out_stream_counter[hdl->counter_index] >>= nb;
nb_bits -= nb;
if (hdl->counter_index && nb == hdl->counter_index_pos) {
hdl->counter_index--;
hdl->counter_index_pos = 8;
} else {
hdl->counter_index_pos -= nb;
if (nb_bits) {
decrypt_counter(hdl);
hdl->couter_avail -= nb_bits;
}
}
}
return key;
}
#endif // AESEncryptionStreamMode
#endif // KVZ_SEL_ENCRYPTION

View file

@ -1,72 +0,0 @@
#ifndef CRYPTO_H_
#define CRYPTO_H_
#include "global.h"
#include "../cfg.h"
#include <stdio.h>
#include <math.h>
#ifdef KVZ_SEL_ENCRYPTION
#define STUBBED extern
#else
#define STUBBED static
#endif
#define AESEncryptionStreamMode 1
#ifdef __cplusplus
extern "C" {
#endif
typedef struct crypto_handle_t crypto_handle_t;
STUBBED crypto_handle_t* kvz_crypto_create(const kvz_config *cfg);
STUBBED void kvz_crypto_decrypt(crypto_handle_t* hdl,
const uint8_t *in_stream,
int size_bits,
uint8_t *out_stream);
STUBBED void kvz_crypto_delete(crypto_handle_t **hdl);
#if AESEncryptionStreamMode
STUBBED unsigned kvz_crypto_get_key(crypto_handle_t *hdl, int num_bits);
#endif
#ifdef __cplusplus
}
#endif
#undef STUBBED
#ifndef KVZ_SEL_ENCRYPTION
// Provide static stubs to allow linking without libcryptopp and allows us
// to avoid sprinkling ifdefs everywhere and having a bunch of code that's
// not compiled during normal development.
// Provide them in the header so we can avoid compiling the cpp file, which
// means we don't need a C++ compiler when crypto is not enabled.
static INLINE crypto_handle_t* kvz_crypto_create(const kvz_config *cfg)
{
return NULL;
}
static INLINE void kvz_crypto_decrypt(crypto_handle_t* hdl,
const uint8_t *in_stream,
int size_bits,
uint8_t *out_stream)
{}
static INLINE void kvz_crypto_delete(crypto_handle_t **hdl)
{}
#if AESEncryptionStreamMode
static INLINE unsigned kvz_crypto_get_key(crypto_handle_t *hdl, int num_bits)
{
return 0;
}
#endif
#endif // KVZ_SEL_ENCRYPTION
#endif // CRYPTO_H_

View file

@ -149,20 +149,6 @@ enum kvz_cu_split_termination
KVZ_CU_SPLIT_TERMINATION_OFF = 1
};
/**
* \brief Enable and disable crypto features.
* \since 3.7.0
*/
enum kvz_crypto_features {
KVZ_CRYPTO_OFF = 0,
KVZ_CRYPTO_MVs = (1 << 0),
KVZ_CRYPTO_MV_SIGNS = (1 << 1),
KVZ_CRYPTO_TRANSF_COEFFS = (1 << 2),
KVZ_CRYPTO_TRANSF_COEFF_SIGNS = (1 << 3),
KVZ_CRYPTO_INTRA_MODE = (1 << 4),
KVZ_CRYPTO_ON = (1 << 5) - 1,
};
/**
* \brief me early termination mode
* \since since 3.8.0
@ -384,9 +370,6 @@ typedef struct kvz_config
enum kvz_cu_split_termination cu_split_termination; /*!< \since 3.8.0 \brief Mode of cu split termination. */
enum kvz_crypto_features crypto_features; /*!< \since 3.7.0 */
uint8_t *optional_key;
enum kvz_me_early_termination me_early_termination; /*!< \since 3.8.0 \brief Mode of me early termination. */
int32_t intra_rdo_et; /*!< \since 4.1.0 \brief Use early termination in intra rdo. */

View file

@ -58,7 +58,6 @@ void kvz_nal_write(bitstream_t * const bitstream, const uint8_t nal_type,
if ((nal_type >= 16) && (nal_type <= 31)) {
zero_tid_required_flag = 1;
}
uint8_t nal_type_lsb = nal_type - (zero_tid_required_flag << 4);
// forbidden zero (1bit) + reserver zero (1bit) layer_id (6 bits)
byte = 0;

View file

@ -273,7 +273,7 @@ static INLINE uint32_t get_coeff_cabac_cost(
false);
}
else {
kvz_encode_ts_residual(state,
kvz_encode_ts_residual((encoder_state_t* const)state,
&cabac_copy,
coeff,
width,

View file

@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include "cabac.h"
#include "rdo.h"

View file

@ -1201,7 +1201,7 @@ const int16_t* kvz_g_mts_input[2][3][5] = {
static void mts_dct_4x4_avx2(const int16_t* input, int16_t* output, tr_type_t type_hor, tr_type_t type_ver, uint8_t bitdepth)
{
const int height = 4;
//const int height = 4;
const int width = 4;
const int log2_width_minus2 = kvz_g_convert_to_bit[width];
@ -1528,7 +1528,7 @@ static void mts_idct_32x32_avx2(const int16_t* input, int16_t* output, tr_type_t
const int16_t* tdct = kvz_g_mts_input[1][type_ver][3];
const int16_t* dct = kvz_g_mts_input[0][type_hor][3];
const int skip_width = (type_hor != DCT2) ? 16 : 0;
//const int skip_width = (type_hor != DCT2) ? 16 : 0;
const int skip_height = (type_ver != DCT2) ? 16 : 0;
mul_clip_matrix_32x32_mts_avx2(tdct, input, tmp, shift_1st, skip_height,0);

View file

@ -73,8 +73,8 @@ void kvz_encode_coeff_nxn_generic(encoder_state_t * const state,
cabac_ctx_t *base_coeff_group_ctx = &(cabac->ctx.sig_coeff_group_model[(type == 0 ? 0 : 1) * 2]);
unsigned scan_cg_last = -1;
unsigned scan_pos_last = -1;
unsigned scan_cg_last = (unsigned)-1;
unsigned scan_pos_last = (unsigned)-1;
for (int i = 0; i < width * width; i++) {
if (coeff[scan[i]]) {

View file

@ -131,7 +131,7 @@ static void kvz_angular_pred_generic(
// Whether to swap references to always project on the left reference row.
const bool vertical_mode = intra_mode >= 34;
// Modes distance to horizontal or vertical mode.
const int_fast8_t mode_disp = vertical_mode ? pred_mode - 50 : -(pred_mode - 18);
const int_fast8_t mode_disp = vertical_mode ? pred_mode - 50 : -((int32_t)pred_mode - 18);
//const int_fast8_t mode_disp = vertical_mode ? intra_mode - 26 : 10 - intra_mode;
// Sample displacement per column in fractions of 32.

View file

@ -36,7 +36,6 @@ static void array_md5_generic(const kvz_pixel* data,
context_md5_t md5_ctx;
kvz_md5_init(&md5_ctx);
unsigned bytes = width * height * sizeof(kvz_pixel);
uint32_t N = 32;
uint32_t width_modN = width % N;
uint32_t width_less_modN = width - width_modN;

View file

@ -152,8 +152,6 @@ int32_t kvz_get_scaled_qp(int8_t type, int8_t qp, int8_t qp_offset, int8_t const
*/
void kvz_transformskip(const encoder_control_t * const encoder, int16_t *block,int16_t *coeff, int8_t block_size)
{
uint32_t log2_tr_size = kvz_g_convert_to_bit[block_size] + 2;
int32_t shift = MAX_TR_DYNAMIC_RANGE - encoder->bitdepth - log2_tr_size;
int32_t j,k;
for (j = 0; j < block_size; j++) {
for(k = 0; k < block_size; k ++) {
@ -256,7 +254,7 @@ int kvz_quantize_residual_trskip(
coeff_t coeff[4*4];
uint32_t cost;
int has_coeffs;
} skip, noskip, *best;
} skip, *best;
const int bit_cost = (int)(state->lambda + 0.5);