diff --git a/src/Makefile b/src/Makefile index a7dd0d28..5a35c313 100644 --- a/src/Makefile +++ b/src/Makefile @@ -50,7 +50,7 @@ LDFLAGS += -lm LD = gcc YASM = yasm ASMOBJS = cpu.o -OBJS = interface_main.o encmain.o bitstream.o cabac.o config.o context.o encoder.o filter.o inter.o intra.o nal.o picture.o rdo.o sao.o search.o tables.o transform.o extras/getopt.o +OBJS = interface_main.o encmain.o bitstream.o cabac.o config.o context.o encoder.o filter.o inter.o intra.o nal.o picture.o rdo.o sao.o scalinglist.o search.o tables.o transform.o extras/getopt.o PROG = ./kvazaar PROGS = $(PROG) diff --git a/src/encmain.c b/src/encmain.c index 33f939fe..3d4dc404 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -41,6 +41,7 @@ #include "cabac.h" #include "picture.h" #include "transform.h" +#include "scalinglist.h" // Assembly optimization headers #include "x86/cpu.h" @@ -392,7 +393,7 @@ int main(int argc, char *argv[]) // Deallocating config_destroy(cfg); - scalinglist_destroy(encoder); + scalinglist_destroy(&encoder->scaling_list); picture_list_destroy(encoder->ref); picture_destroy(encoder->in.cur_pic); FREE_POINTER(encoder->in.cur_pic); diff --git a/src/encoder.c b/src/encoder.c index 1c237611..b9bc124a 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -139,7 +139,7 @@ encoder_control *init_encoder_control(config *cfg) } // Initialize the scaling list - scalinglist_init(enc_c); + scalinglist_init(&enc_c->scaling_list); pic_list = picture_list_init(MAX_REF_PIC_COUNT); if(!pic_list) { @@ -155,7 +155,7 @@ encoder_control *init_encoder_control(config *cfg) FILE* cqmfile; cqmfile = cfg->cqmfile ? fopen(cfg->cqmfile, "rb") : NULL; if (cqmfile) { - scalinglist_parse(enc_c, cqmfile); + scalinglist_parse(&enc_c->scaling_list, cqmfile); fclose(cqmfile); } } @@ -311,7 +311,7 @@ void encode_one_frame(encoder_control* encoder) cabac_start(&cabac); init_contexts(&cabac, encoder->QP, encoder->in.cur_pic->slicetype); - scalinglist_process(encoder); + scalinglist_process(&encoder->scaling_list); encode_slice_header(encoder); bitstream_align(encoder->stream); @@ -697,7 +697,7 @@ static void encode_scaling_list(const encoder_control * const encoder) uint32_t ref_matrix_id = UINT32_MAX; for (pred_list_idx = list_id; pred_list_idx >= 0; pred_list_idx--) { - int32_t * const pred_list = (list_id == pred_list_idx) ? + const int32_t * const pred_list = (list_id == pred_list_idx) ? scalinglist_get_default(size_id, pred_list_idx) : encoder->scaling_list.scaling_list_coeff[size_id][pred_list_idx]; diff --git a/src/encoder.h b/src/encoder.h index c219677d..e091210b 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -31,15 +31,7 @@ #include "cabac.h" #include "config.h" #include "tables.h" - -typedef struct { - int32_t scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; - int32_t* scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; - int32_t* quant_coeff[4][6][6]; - int32_t *de_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; - double* error_scale[4][6][6]; -} scaling_list; - +#include "scalinglist.h" /* TODO: add ME data */ @@ -56,8 +48,8 @@ enum { FORMAT_400 = 0, FORMAT_420, FORMAT_422, FORMAT_444 }; typedef struct { FILE *file; - int32_t width; /*!< \brief input picture width */ - int32_t height; /*!< \brief input picture height */ + int32_t width; /*!< \brief input picture width (divisible by the minimum block size)*/ + int32_t height; /*!< \brief input picture height (divisible by the minimum block size) */ int32_t real_width; /*!< \brief real input picture width */ int32_t real_height; /*!< \brief real input picture width */ int32_t height_in_lcu; /*!< \brief input picture width in LCU*/ @@ -143,7 +135,6 @@ void encode_block_residual(const encoder_control * const encoder, extern double g_lambda_cost[55]; extern double g_cur_lambda_cost; -extern int8_t g_bitdepth; static const uint8_t g_group_idx[32] = { 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, diff --git a/src/global.h b/src/global.h index 5e88e854..eec730ff 100644 --- a/src/global.h +++ b/src/global.h @@ -171,5 +171,9 @@ typedef int16_t coefficient; #define MAX_MATRIX_COEF_NUM 64 #define SCALING_LIST_REM_NUM 6 +#define MAX_TR_DYNAMIC_RANGE 15 + +//Defined in encoder.c. It's global for now since it affects a lot of functions. +extern int8_t g_bitdepth; #endif diff --git a/src/rdo.c b/src/rdo.c index 0dfe81fc..c3389dfa 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -33,7 +33,6 @@ #define QUANT_SHIFT 14 -#define MAX_TR_DYNAMIC_RANGE 15 #define SCAN_SET_SIZE 16 #define LOG2_SCAN_SET_SIZE 4 #define SBH_THRESHOLD 4 @@ -404,8 +403,8 @@ void rdoq(const encoder_control * const encoder, cabac_data *cabac, coefficient { int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift; - int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; - double *err_scale = encoder->scaling_list.error_scale[log2_tr_size-2][scalinglist_type][qp_scaled%6]; + const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; + const double *err_scale = encoder->scaling_list.error_scale[log2_tr_size-2][scalinglist_type][qp_scaled%6]; double block_uncoded_cost = 0; diff --git a/src/scalinglist.c b/src/scalinglist.c new file mode 100644 index 00000000..cfce269d --- /dev/null +++ b/src/scalinglist.c @@ -0,0 +1,407 @@ +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2014 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Kvazaar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kvazaar. If not, see . + ****************************************************************************/ + +#include +#include +#include + +#include "tables.h" +#include "scalinglist.h" + +const uint8_t g_scaling_list_num[4] = { 6, 6, 6, 2}; +const uint16_t g_scaling_list_size[4] = { 16, 64, 256,1024}; +static const uint8_t g_scaling_list_size_x[4] = { 4, 8,16,32}; + +static const int32_t g_quant_default_4x4[16] = +{ + 16,16,16,16, + 16,16,16,16, + 16,16,16,16, + 16,16,16,16 +}; + +static const int32_t g_quant_intra_default_8x8[64] = +{ + 16,16,16,16,17,18,21,24, + 16,16,16,16,17,19,22,25, + 16,16,17,18,20,22,25,29, + 16,16,18,21,24,27,31,36, + 17,17,20,24,30,35,41,47, + 18,19,22,27,35,44,54,65, + 21,22,25,31,41,54,70,88, + 24,25,29,36,47,65,88,115 +}; + +static const int32_t g_quant_inter_default_8x8[64] = +{ + 16,16,16,16,17,18,20,24, + 16,16,16,17,18,20,24,25, + 16,16,17,18,20,24,25,28, + 16,17,18,20,24,25,28,33, + 17,18,20,24,25,28,33,41, + 18,20,24,25,28,33,41,54, + 20,24,25,28,33,41,54,71, + 24,25,28,33,41,54,71,91 +}; + +const int16_t g_quant_scales[6] = { 26214,23302,20560,18396,16384,14564 }; +const int16_t g_inv_quant_scales[6] = { 40,45,51,57,64,72 }; + + +/** + * \brief Initialize scaling lists + * + */ +void scalinglist_init(scaling_list * const scaling_list) +{ + uint32_t sizeId,listId,qp; + + for (sizeId = 0; sizeId < 4; sizeId++) { + for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) { + for (qp = 0; qp < 6; qp++) { + if (!(sizeId == 3 && listId == 3)) { + scaling_list->quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t)); + scaling_list->de_quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t)); + scaling_list->error_scale[sizeId][listId][qp] = (double*)calloc(g_scaling_list_size[sizeId], sizeof(double)); + } + } + scaling_list->scaling_list_coeff[sizeId][listId] = (int32_t*)calloc(MIN(MAX_MATRIX_COEF_NUM, g_scaling_list_size[sizeId]), sizeof(int32_t)); + } + } + // alias, assign pointer to an existing array + for (qp = 0; qp < 6; qp++) { + scaling_list->quant_coeff[3][3][qp] = scaling_list->quant_coeff[3][1][qp]; + scaling_list->de_quant_coeff[3][3][qp] = scaling_list->de_quant_coeff[3][1][qp]; + scaling_list->error_scale[3][3][qp] = scaling_list->error_scale[3][1][qp]; + } + + //Initialize dc (otherwise we switch on undef in scalinglist_set) + for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; ++sizeId) { + for (listId = 0; listId < SCALING_LIST_NUM; ++listId) { + scaling_list->scaling_list_dc[sizeId][listId] = 0; + } + } + + scaling_list->enable = 0; +} + +/** + * \brief Destroy scaling list allocated memory + * + */ +void scalinglist_destroy(scaling_list * const scaling_list) +{ + uint32_t sizeId,listId,qp; + + for (sizeId = 0; sizeId < 4; sizeId++) { + for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) { + for (qp = 0; qp < 6; qp++) { + if (!(sizeId == 3 && listId == 3)) { + FREE_POINTER(scaling_list->quant_coeff[sizeId][listId][qp]); + FREE_POINTER(scaling_list->de_quant_coeff[sizeId][listId][qp]); + FREE_POINTER(scaling_list->error_scale[sizeId][listId][qp]); + } + } + FREE_POINTER(scaling_list->scaling_list_coeff[sizeId][listId]); + } + } +} + +int scalinglist_parse(scaling_list * const scaling_list, FILE *fp) +{ + #define LINE_BUFSIZE 1024 + static const char matrix_type[4][6][20] = + { + { + "INTRA4X4_LUMA", + "INTRA4X4_CHROMAU", + "INTRA4X4_CHROMAV", + "INTER4X4_LUMA", + "INTER4X4_CHROMAU", + "INTER4X4_CHROMAV" + }, + { + "INTRA8X8_LUMA", + "INTRA8X8_CHROMAU", + "INTRA8X8_CHROMAV", + "INTER8X8_LUMA", + "INTER8X8_CHROMAU", + "INTER8X8_CHROMAV" + }, + { + "INTRA16X16_LUMA", + "INTRA16X16_CHROMAU", + "INTRA16X16_CHROMAV", + "INTER16X16_LUMA", + "INTER16X16_CHROMAU", + "INTER16X16_CHROMAV" + }, + { + "INTRA32X32_LUMA", + "INTER32X32_LUMA", + }, + }; + static const char matrix_type_dc[2][6][22] = + { + { + "INTRA16X16_LUMA_DC", + "INTRA16X16_CHROMAU_DC", + "INTRA16X16_CHROMAV_DC", + "INTER16X16_LUMA_DC", + "INTER16X16_CHROMAU_DC", + "INTER16X16_CHROMAV_DC" + }, + { + "INTRA32X32_LUMA_DC", + "INTER32X32_LUMA_DC", + }, + }; + + uint32_t size_id; + for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) { + uint32_t list_id; + uint32_t size = MIN(MAX_MATRIX_COEF_NUM, (int32_t)g_scaling_list_size[size_id]); + //const uint32_t * const scan = (size_id == 0) ? g_sig_last_scan[SCAN_DIAG][1] : g_sig_last_scan_32x32; + + for (list_id = 0; list_id < g_scaling_list_num[size_id]; list_id++) { + int found; + uint32_t i; + int32_t data; + //This IS valid (our pointer is dynamically allocated in scalinglist_init) + int32_t *coeff = (int32_t*) scaling_list->scaling_list_coeff[size_id][list_id]; + char line[LINE_BUFSIZE + 1] = { 0 }; // +1 for null-terminator + + // Go back for each matrix. + fseek(fp, 0, SEEK_SET); + + do { + if (!fgets(line, LINE_BUFSIZE, fp) || + ((found = !!strstr(line, matrix_type[size_id][list_id])) == 0 && feof(fp))) + return 0; + } while (!found); + + for (i = 0; i < size;) { + char *p; + if (!fgets(line, LINE_BUFSIZE, fp)) + return 0; + p = line; + + // Read coefficients per line. + // The comma (,) character is used as a separator. + // The coefficients are stored in up-right diagonal order. + do { + int ret = sscanf(p, "%d", &data); + if (ret != 1) + break; + else if (data < 1 || data > 255) + return 0; + + coeff[i++] = data; + if (i == size) + break; + + // Seek to the next newline, null-terminator or comma. + while (*p != '\n' && *p != '\0' && *p != ',') + ++p; + if (*p == ',') + ++p; + } while (*p != '\n' && *p != '\0'); + } + + // Set DC value. + if (size_id >= SCALING_LIST_16x16) { + fseek(fp, 0, SEEK_SET); + + do { + if (!fgets(line, LINE_BUFSIZE, fp) || + ((found = !!strstr(line, matrix_type_dc[size_id - SCALING_LIST_16x16][list_id])) == 0 && feof(fp))) + return 0; + } while (!found); + if (1 != fscanf(fp, "%d", &data) || data < 1 || data > 255) + return 0; + + scaling_list->scaling_list_dc[size_id][list_id] = data; + } else + scaling_list->scaling_list_dc[size_id][list_id] = coeff[0]; + } + } + + scaling_list->enable = 1; + return 1; + #undef LINE_BUFSIZE +} + +const int32_t *scalinglist_get_default(const uint32_t size_id, const uint32_t list_id) +{ + const int32_t *list_ptr = g_quant_intra_default_8x8; // Default to "8x8" intra + switch(size_id) { + case SCALING_LIST_4x4: + list_ptr = g_quant_default_4x4; + break; + case SCALING_LIST_8x8: + case SCALING_LIST_16x16: + if (list_id > 2) list_ptr = g_quant_inter_default_8x8; + break; + case SCALING_LIST_32x32: + if (list_id > 0) list_ptr = g_quant_inter_default_8x8; + break; + } + return list_ptr; +} + + +/** + * \brief get scaling list for decoder + * + */ +static void scalinglist_process_dec(const int32_t * const coeff, int32_t *dequantcoeff, + int32_t inv_quant_scales, uint32_t height, + uint32_t width, uint32_t ratio, + int32_t size_num, uint32_t dc, + uint8_t flat) +{ + uint32_t j,i; + + // Flat scaling list + if (flat) { + for (j = 0; j < height * width; j++) { + *dequantcoeff++ = inv_quant_scales<<4; + } + } else { + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + dequantcoeff[j*width + i] = inv_quant_scales * coeff[size_num * (j / ratio) + i / ratio]; + } + } + if (ratio > 1) { + dequantcoeff[0] = inv_quant_scales * dc; + } + } +} + +/** + * \brief get scaling list for encoder + * + */ +void scalinglist_process_enc(const int32_t * const coeff, int32_t* quantcoeff, const int32_t quant_scales, + const uint32_t height, const uint32_t width, const uint32_t ratio, + const int32_t size_num, const uint32_t dc, const uint8_t flat) +{ + uint32_t j,i; + int32_t nsqth = (height < width) ? 4: 1; //!< height ratio for NSQT + int32_t nsqtw = (width < height) ? 4: 1; //!< width ratio for NSQT + + // Flat scaling list + if (flat) { + for (j = 0; j < height * width; j++) { + *quantcoeff++ = quant_scales>>4; + } + } else { + for (j = 0; j < height; j++) { + for (i = 0; i < width; i++) { + uint32_t coeffpos = size_num * (j * nsqth / ratio) + i * nsqtw / ratio; + quantcoeff[j*width + i] = quant_scales / ((coeffpos > 63) ? 1 : coeff[coeffpos]); + } + } + if (ratio > 1) { + quantcoeff[0] = quant_scales / dc; + } + } +} + + + +/** set error scale coefficients + * \param list List ID + * \param uiSize Size + * \param uiQP Quantization parameter + */ +void scalinglist_set_err_scale(scaling_list * const scaling_list, uint32_t list,uint32_t size, uint32_t qp) +{ + uint32_t log2_tr_size = g_convert_to_bit[ g_scaling_list_size_x[size] ] + 2; + int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; // Represents scaling through forward transform + + uint32_t i,max_num_coeff = g_scaling_list_size[size]; + const int32_t *quantcoeff = scaling_list->quant_coeff[size][list][qp]; + //This cast is allowed, since error_scale is a malloc'd pointer in scalinglist_init + double *err_scale = (double *) scaling_list->error_scale[size][list][qp]; + + // Compensate for scaling of bitcount in Lagrange cost function + double scale = (double)(1<<15); + // Compensate for scaling through forward transform + scale = scale*pow(2.0,-2.0*transform_shift); + for(i=0;iscaling_list_dc[sizeId][listId] != 0 ? scaling_list->scaling_list_dc[sizeId][listId] : 16; + //These cast are allowed, since these are pointer's to malloc'd area in scalinglist_init + int32_t *quantcoeff = (int32_t*) scaling_list->quant_coeff[sizeId][listId][qp]; + int32_t *dequantcoeff = (int32_t*) scaling_list->de_quant_coeff[sizeId][listId][qp]; + + // Encoder list + scalinglist_process_enc(coeff, quantcoeff, g_quant_scales[qp]<<4, height, width, ratio, + MIN(8, g_scaling_list_size_x[sizeId]), dc, !scaling_list->enable); + // Decoder list + scalinglist_process_dec(coeff, dequantcoeff, g_inv_quant_scales[qp], height, width, ratio, + MIN(8, g_scaling_list_size_x[sizeId]), dc, !scaling_list->enable); + + + // TODO: support NSQT + // if(sizeId == /*SCALING_LIST_32x32*/3 || sizeId == /*SCALING_LIST_16x16*/2) { //for NSQT + // quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_VER*/1]; + // scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height,width>>2,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0); + + // quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_HOR*/2]; + // scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height>>2,width,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0); + // } +} + +/** + * \brief + * + */ +void scalinglist_process(scaling_list * const scaling_list) +{ + uint32_t size,list,qp; + + for (size = 0; size < SCALING_LIST_SIZE_NUM; size++) { + for (list = 0; list < g_scaling_list_num[size]; list++) { + const int32_t * const list_ptr = scaling_list->enable ? + scaling_list->scaling_list_coeff[size][list] : + scalinglist_get_default(size, list); + + for (qp = 0; qp < SCALING_LIST_REM_NUM; qp++) { + scalinglist_set(scaling_list, list_ptr, list, size, qp); + scalinglist_set_err_scale(scaling_list, list, size, qp); + } + } + } +} \ No newline at end of file diff --git a/src/scalinglist.h b/src/scalinglist.h new file mode 100644 index 00000000..1e8a76c0 --- /dev/null +++ b/src/scalinglist.h @@ -0,0 +1,57 @@ +#ifndef SCALINGLIST_H_ +#define SCALINGLIST_H_ +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2014 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Kvazaar is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Kvazaar. If not, see . + ****************************************************************************/ + +/* + * \file + * \brief Coding Unit (CU) and picture data related functions. + */ + +#include "global.h" + +typedef struct { + int8_t enable; + int32_t scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; + const int32_t *scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; + const int32_t *quant_coeff[4][6][6]; + const int32_t *de_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; + const double *error_scale[4][6][6]; +} scaling_list; + +extern const uint8_t g_scaling_list_num[4]; +extern const uint16_t g_scaling_list_size[4]; + +const int32_t *scalinglist_get_default(const uint32_t size_id, const uint32_t list_id); + +void scalinglist_init(scaling_list * const scaling_list); +void scalinglist_destroy(scaling_list * const scaling_list); + +int scalinglist_parse(scaling_list * const scaling_list, FILE *fp); +void scalinglist_process(scaling_list * const scaling_list); + +//void scalinglist_set(scaling_list * const scaling_list, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp); +//void scalinglist_set_err_scale(scaling_list * const scaling_list, uint32_t list, uint32_t size, uint32_t qp); + + + + + + +#endif \ No newline at end of file diff --git a/src/transform.c b/src/transform.c index 983f8f60..65d37eb8 100644 --- a/src/transform.c +++ b/src/transform.c @@ -110,37 +110,6 @@ const int16_t g_t32[32][32] = { 4,-13, 22,-31, 38,-46, 54,-61, 67,-73, 78,-82, 85,-88, 90,-90, 90,-90, 88,-85, 82,-78, 73,-67, 61,-54, 46,-38, 31,-22, 13, -4} }; -const int32_t g_quant_default_4x4[16] = -{ - 16,16,16,16, - 16,16,16,16, - 16,16,16,16, - 16,16,16,16 -}; - -const int32_t g_quant_intra_default_8x8[64] = -{ - 16,16,16,16,17,18,21,24, - 16,16,16,16,17,19,22,25, - 16,16,17,18,20,22,25,29, - 16,16,18,21,24,27,31,36, - 17,17,20,24,30,35,41,47, - 18,19,22,27,35,44,54,65, - 21,22,25,31,41,54,70,88, - 24,25,29,36,47,65,88,115 -}; - -const int32_t g_quant_inter_default_8x8[64] = -{ - 16,16,16,16,17,18,20,24, - 16,16,16,17,18,20,24,25, - 16,16,17,18,20,24,25,28, - 16,17,18,20,24,25,28,33, - 17,18,20,24,25,28,33,41, - 18,20,24,25,28,33,41,54, - 20,24,25,28,33,41,54,71, - 24,25,28,33,41,54,71,91 -}; const uint8_t g_chroma_scale[58]= { @@ -150,12 +119,6 @@ const uint8_t g_chroma_scale[58]= 45,46,47,48,49,50,51 }; -const uint8_t g_scaling_list_num[4] = { 6, 6, 6, 2}; -const uint16_t g_scaling_list_size[4] = { 16, 64, 256,1024}; -const uint8_t g_scaling_list_size_x[4] = { 4, 8,16,32}; -const int16_t g_quant_scales[6] = { 26214,23302,20560,18396,16384,14564 }; -const int16_t g_inv_quant_scales[6] = { 40,45,51,57,64,72 }; - ////////////////////////////////////////////////////////////////////////// // FUNCTIONS // @@ -180,200 +143,7 @@ int32_t get_scaled_qp(int8_t type, int8_t qp, int8_t qp_offset) return qp_scaled; } -/** - * \brief Initialize scaling lists - * - */ -void scalinglist_init(encoder_control * const encoder) -{ - uint32_t sizeId,listId,qp; - for (sizeId = 0; sizeId < 4; sizeId++) { - for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) { - for (qp = 0; qp < 6; qp++) { - if (!(sizeId == 3 && listId == 3)) { - encoder->scaling_list.quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t)); - encoder->scaling_list.de_quant_coeff[sizeId][listId][qp] = (int32_t*)calloc(g_scaling_list_size[sizeId], sizeof(int32_t)); - encoder->scaling_list.error_scale[sizeId][listId][qp] = (double*)calloc(g_scaling_list_size[sizeId], sizeof(double)); - } - } - encoder->scaling_list.scaling_list_coeff[sizeId][listId] = (int32_t*)calloc(MIN(MAX_MATRIX_COEF_NUM, g_scaling_list_size[sizeId]), sizeof(int32_t)); - } - } - // alias, assign pointer to an existing array - for (qp = 0; qp < 6; qp++) { - encoder->scaling_list.quant_coeff[3][3][qp] = encoder->scaling_list.quant_coeff[3][1][qp]; - encoder->scaling_list.de_quant_coeff[3][3][qp] = encoder->scaling_list.de_quant_coeff[3][1][qp]; - encoder->scaling_list.error_scale[3][3][qp] = encoder->scaling_list.error_scale[3][1][qp]; - } - - //Initialize dc (otherwise we switch on undef in scalinglist_set) - for (sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; ++sizeId) { - for (listId = 0; listId < SCALING_LIST_NUM; ++listId) { - encoder->scaling_list.scaling_list_dc[sizeId][listId] = 0; - } - } - - encoder->scaling_list_enable = 0; -} - -/** - * \brief Destroy scaling list allocated memory - * - */ -void scalinglist_destroy(encoder_control * const encoder) -{ - uint32_t sizeId,listId,qp; - - for (sizeId = 0; sizeId < 4; sizeId++) { - for (listId = 0; listId < g_scaling_list_num[sizeId]; listId++) { - for (qp = 0; qp < 6; qp++) { - if (!(sizeId == 3 && listId == 3)) { - FREE_POINTER( encoder->scaling_list.quant_coeff[sizeId][listId][qp]); - FREE_POINTER(encoder->scaling_list.de_quant_coeff[sizeId][listId][qp]); - FREE_POINTER( encoder->scaling_list.error_scale[sizeId][listId][qp]); - } - } - FREE_POINTER(encoder->scaling_list.scaling_list_coeff[sizeId][listId]); - } - } -} - - -/** - * \brief - * - */ -void scalinglist_process(const encoder_control * const encoder) -{ - uint32_t size,list,qp; - - for (size = 0; size < SCALING_LIST_SIZE_NUM; size++) { - for (list = 0; list < g_scaling_list_num[size]; list++) { - const int32_t * const list_ptr = encoder->scaling_list_enable ? - encoder->scaling_list.scaling_list_coeff[size][list] : - scalinglist_get_default(size, list); - - for (qp = 0; qp < SCALING_LIST_REM_NUM; qp++) { - scalinglist_set(encoder, list_ptr, list, size, qp); - scalinglist_set_err_scale(encoder, list, size, qp); - } - } - } -} - - -/** set error scale coefficients - * \param list List ID - * \param uiSize Size - * \param uiQP Quantization parameter - */ -#define MAX_TR_DYNAMIC_RANGE 15 -void scalinglist_set_err_scale(const encoder_control * const encoder, uint32_t list,uint32_t size, uint32_t qp) -{ - uint32_t log2_tr_size = g_convert_to_bit[ g_scaling_list_size_x[size] ] + 2; - int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; // Represents scaling through forward transform - - uint32_t i,max_num_coeff = g_scaling_list_size[size]; - int32_t *quantcoeff = encoder->scaling_list.quant_coeff[size][list][qp]; - double *err_scale = encoder->scaling_list.error_scale[size][list][qp]; - - // Compensate for scaling of bitcount in Lagrange cost function - double scale = (double)(1<<15); - // Compensate for scaling through forward transform - scale = scale*pow(2.0,-2.0*transform_shift); - for(i=0;i>4; - } - } else { - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - uint32_t coeffpos = size_num * (j * nsqth / ratio) + i * nsqtw / ratio; - quantcoeff[j*width + i] = quant_scales / ((coeffpos > 63) ? 1 : coeff[coeffpos]); - } - } - if (ratio > 1) { - quantcoeff[0] = quant_scales / dc; - } - } -} - -/** - * \brief get scaling list for decoder - * - */ -static void scalinglist_process_dec(const int32_t * const coeff, int32_t *dequantcoeff, - int32_t inv_quant_scales, uint32_t height, - uint32_t width, uint32_t ratio, - int32_t size_num, uint32_t dc, - uint8_t flat) -{ - uint32_t j,i; - - // Flat scaling list - if (flat) { - for (j = 0; j < height * width; j++) { - *dequantcoeff++ = inv_quant_scales<<4; - } - } else { - for (j = 0; j < height; j++) { - for (i = 0; i < width; i++) { - dequantcoeff[j*width + i] = inv_quant_scales * coeff[size_num * (j / ratio) + i / ratio]; - } - } - if (ratio > 1) { - dequantcoeff[0] = inv_quant_scales * dc; - } - } -} - -/** - * \brief set scaling lists - * - */ -void scalinglist_set(const encoder_control * const encoder, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp) -{ - uint32_t width = g_scaling_list_size_x[sizeId]; - uint32_t height = g_scaling_list_size_x[sizeId]; - uint32_t ratio = g_scaling_list_size_x[sizeId] / MIN(8, g_scaling_list_size_x[sizeId]); - int32_t *quantcoeff = encoder->scaling_list.quant_coeff[sizeId][listId][qp]; - int32_t *dequantcoeff = encoder->scaling_list.de_quant_coeff[sizeId][listId][qp]; - uint32_t dc = encoder->scaling_list.scaling_list_dc[sizeId][listId] != 0 ? encoder->scaling_list.scaling_list_dc[sizeId][listId] : 16; - - // Encoder list - scalinglist_process_enc(coeff, quantcoeff, g_quant_scales[qp]<<4, height, width, ratio, - MIN(8, g_scaling_list_size_x[sizeId]), dc, !encoder->scaling_list_enable); - // Decoder list - scalinglist_process_dec(coeff, dequantcoeff, g_inv_quant_scales[qp], height, width, ratio, - MIN(8, g_scaling_list_size_x[sizeId]), dc, !encoder->scaling_list_enable); - - - // TODO: support NSQT - // if(sizeId == /*SCALING_LIST_32x32*/3 || sizeId == /*SCALING_LIST_16x16*/2) { //for NSQT - // quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_VER*/1]; - // scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height,width>>2,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0); - - // quantcoeff = g_quant_coeff[listId][qp][sizeId-1][/*SCALING_LIST_HOR*/2]; - // scalinglist_process_enc(coeff,quantcoeff,g_quantScales[qp]<<4,height>>2,width,ratio,MIN(8,g_scalingListSizeX[sizeId]),/*scalingList->getScalingListDC(sizeId,listId)*/0); - // } -} static void partial_butterfly_4(short *src, short *dst, @@ -849,7 +619,6 @@ void itransform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode #define QUANT_SHIFT 14 -#define MAX_TR_DYNAMIC_RANGE 15 /** * \brief quantize transformed coefficents * @@ -872,7 +641,7 @@ void quant(const encoder_control * const encoder, int16_t *coef, int16_t *q_coef uint32_t log2_tr_size = g_convert_to_bit[ width ] + 2; int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]); - int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; + const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - g_bitdepth - log2_tr_size; //!< Represents scaling through forward transform int32_t q_bits = QUANT_SHIFT + qp_scaled/6 + transform_shift; @@ -1000,7 +769,7 @@ void dequant(const encoder_control * const encoder, int16_t *q_coef, int16_t *co uint32_t log2_tr_size = g_convert_to_bit[ width ] + 2; int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]); - int32_t *dequant_coef = encoder->scaling_list.de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; + const int32_t *dequant_coef = encoder->scaling_list.de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; shift += 4; if (shift >qp_scaled / 6) { @@ -1031,143 +800,3 @@ void dequant(const encoder_control * const encoder, int16_t *q_coef, int16_t *co } } -int32_t *scalinglist_get_default(uint32_t size_id, uint32_t list_id) -{ - int32_t *list_ptr = (int32_t *)g_quant_intra_default_8x8; // Default to "8x8" intra - switch(size_id) { - case SCALING_LIST_4x4: - list_ptr = (int32_t *)g_quant_default_4x4; - break; - case SCALING_LIST_8x8: - case SCALING_LIST_16x16: - if (list_id > 2) list_ptr = (int32_t *)g_quant_inter_default_8x8; - break; - case SCALING_LIST_32x32: - if (list_id > 0) list_ptr = (int32_t *)g_quant_inter_default_8x8; - break; - } - return list_ptr; -} - -int scalinglist_parse(encoder_control * const encoder, FILE *fp) -{ - #define LINE_BUFSIZE 1024 - static const char matrix_type[4][6][20] = - { - { - "INTRA4X4_LUMA", - "INTRA4X4_CHROMAU", - "INTRA4X4_CHROMAV", - "INTER4X4_LUMA", - "INTER4X4_CHROMAU", - "INTER4X4_CHROMAV" - }, - { - "INTRA8X8_LUMA", - "INTRA8X8_CHROMAU", - "INTRA8X8_CHROMAV", - "INTER8X8_LUMA", - "INTER8X8_CHROMAU", - "INTER8X8_CHROMAV" - }, - { - "INTRA16X16_LUMA", - "INTRA16X16_CHROMAU", - "INTRA16X16_CHROMAV", - "INTER16X16_LUMA", - "INTER16X16_CHROMAU", - "INTER16X16_CHROMAV" - }, - { - "INTRA32X32_LUMA", - "INTER32X32_LUMA", - }, - }; - static const char matrix_type_dc[2][6][22] = - { - { - "INTRA16X16_LUMA_DC", - "INTRA16X16_CHROMAU_DC", - "INTRA16X16_CHROMAV_DC", - "INTER16X16_LUMA_DC", - "INTER16X16_CHROMAU_DC", - "INTER16X16_CHROMAV_DC" - }, - { - "INTRA32X32_LUMA_DC", - "INTER32X32_LUMA_DC", - }, - }; - - uint32_t size_id; - for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) { - uint32_t list_id; - uint32_t size = MIN(MAX_MATRIX_COEF_NUM, (int32_t)g_scaling_list_size[size_id]); - //const uint32_t * const scan = (size_id == 0) ? g_sig_last_scan[SCAN_DIAG][1] : g_sig_last_scan_32x32; - - for (list_id = 0; list_id < g_scaling_list_num[size_id]; list_id++) { - int found; - uint32_t i; - int32_t data; - int32_t *coeff = encoder->scaling_list.scaling_list_coeff[size_id][list_id]; - char line[LINE_BUFSIZE + 1] = { 0 }; // +1 for null-terminator - - // Go back for each matrix. - fseek(fp, 0, SEEK_SET); - - do { - if (!fgets(line, LINE_BUFSIZE, fp) || - ((found = !!strstr(line, matrix_type[size_id][list_id])) == 0 && feof(fp))) - return 0; - } while (!found); - - for (i = 0; i < size;) { - char *p; - if (!fgets(line, LINE_BUFSIZE, fp)) - return 0; - p = line; - - // Read coefficients per line. - // The comma (,) character is used as a separator. - // The coefficients are stored in up-right diagonal order. - do { - int ret = sscanf(p, "%d", &data); - if (ret != 1) - break; - else if (data < 1 || data > 255) - return 0; - - coeff[i++] = data; - if (i == size) - break; - - // Seek to the next newline, null-terminator or comma. - while (*p != '\n' && *p != '\0' && *p != ',') - ++p; - if (*p == ',') - ++p; - } while (*p != '\n' && *p != '\0'); - } - - // Set DC value. - if (size_id >= SCALING_LIST_16x16) { - fseek(fp, 0, SEEK_SET); - - do { - if (!fgets(line, LINE_BUFSIZE, fp) || - ((found = !!strstr(line, matrix_type_dc[size_id - SCALING_LIST_16x16][list_id])) == 0 && feof(fp))) - return 0; - } while (!found); - if (1 != fscanf(fp, "%d", &data) || data < 1 || data > 255) - return 0; - - encoder->scaling_list.scaling_list_dc[size_id][list_id] = data; - } else - encoder->scaling_list.scaling_list_dc[size_id][list_id] = coeff[0]; - } - } - - encoder->scaling_list_enable = 1; - return 1; - #undef LINE_BUFSIZE -} diff --git a/src/transform.h b/src/transform.h index d681c522..65a5fdc9 100644 --- a/src/transform.h +++ b/src/transform.h @@ -30,9 +30,6 @@ #include -extern const uint8_t g_scaling_list_num[4]; -extern const uint16_t g_scaling_list_size[4]; -extern const int32_t g_quant_intra_default_8x8[64]; extern const uint8_t g_chroma_scale[58]; extern const int16_t g_inv_quant_scales[6]; @@ -47,17 +44,6 @@ void itransformskip(int16_t *block,int16_t *coeff, int8_t block_size); void transform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode); void itransform2d(int16_t *block,int16_t *coeff, int8_t block_size, int32_t mode); -void scalinglist_init(encoder_control*const encoder); -void scalinglist_process_enc(const int32_t * const coeff, int32_t *quant_coeff, int32_t quant_scales, - uint32_t height,uint32_t width, uint32_t ratio, int32_t size_num, uint32_t dc, uint8_t flat); -void scalinglist_process(const encoder_control * const encoder); -void scalinglist_set(const encoder_control * const encoder, const int32_t * const coeff, uint32_t listId, uint32_t sizeId, uint32_t qp); -void scalinglist_set_err_scale(const encoder_control * const encoder, uint32_t list, uint32_t size, uint32_t qp); -void scalinglist_destroy(encoder_control * const encoder); - -int32_t *scalinglist_get_default(uint32_t size_id, uint32_t list_id); -int scalinglist_parse(encoder_control * const encoder, FILE *fp); - int32_t get_scaled_qp(int8_t type, int8_t qp, int8_t qp_offset); #endif