From a860bbc7f99dbaed577a465bd0e899c1138f272e Mon Sep 17 00:00:00 2001 From: Yusuke Nakamura Date: Tue, 11 Feb 2014 19:55:21 +0900 Subject: [PATCH] config: Add --cqmfile to use custom quantization matrices from a file. The coefficients in a matrix are stored in up-right diagonal order. The following indicates the default matrices specified in the spec. INTRA4X4_LUMA 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTRA4X4_CHROMAU 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTRA4X4_CHROMAV 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTER4X4_LUMA 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTER4X4_CHROMAU 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTER4X4_CHROMAV 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 INTRA8X8_LUMA 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 INTRA8X8_CHROMAU 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 INTRA8X8_CHROMAV 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 INTER8X8_LUMA 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 INTER8X8_CHROMAU 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 INTER8X8_CHROMAV 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 INTRA16X16_LUMA 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 INTRA16X16_CHROMAU 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 INTRA16X16_CHROMAV 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 INTER16X16_LUMA 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 INTER16X16_CHROMAU 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 INTER16X16_CHROMAV 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 INTRA32X32_LUMA 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 INTER32X32_LUMA 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 INTRA16X16_LUMA_DC 16 INTRA16X16_CHROMAU_DC 16 INTRA16X16_CHROMAV_DC 16 INTER16X16_LUMA_DC 16 INTER16X16_CHROMAU_DC 16 INTER16X16_CHROMAV_DC 16 INTRA32X32_LUMA_DC 16 INTER32X32_LUMA_DC 16 --- README.md | 1 + src/config.c | 5 ++ src/config.h | 1 + src/encmain.c | 6 ++ src/encoder.c | 69 +++++++++++++++-- src/encoder.h | 1 + src/global.h | 1 - src/transform.c | 192 ++++++++++++++++++++++++++++++++++++++++-------- src/transform.h | 15 ++++ 9 files changed, 254 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 6e8085a5..82fe4e86 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ meant to be user configurable later. beta and tc range is -6..6 [0:0] --no-sao : Disable sample adaptive offset --aud : Use access unit delimiters + --cqmfile : Custom Quantization Matrices from a file Video Usability Information: --sar : Specify Sample Aspect Ratio diff --git a/src/config.c b/src/config.c index 3f7897ac..841e0e2a 100644 --- a/src/config.c +++ b/src/config.c @@ -74,6 +74,7 @@ int config_init(config *cfg) cfg->vui.colormatrix = 2; /* undef */ cfg->vui.chroma_loc = 0; /* left center */ cfg->aud_enable = 0; + cfg->cqmfile = NULL; return 1; } @@ -87,6 +88,7 @@ int config_destroy(config *cfg) { FREE_POINTER(cfg->input); FREE_POINTER(cfg->output); + FREE_POINTER(cfg->cqmfile); free(cfg); return 1; @@ -234,6 +236,8 @@ static int config_parse(config *cfg, const char *name, const char *value) } OPT("aud") cfg->aud_enable = atobool(value); + OPT("cqmfile") + cfg->cqmfile = copy_string(value); else return 0; #undef OPT @@ -277,6 +281,7 @@ int config_read(config *cfg,int argc, char *argv[]) { "colormatrix", required_argument, NULL, 0 }, { "chromaloc", required_argument, NULL, 0 }, { "aud", no_argument, NULL, 0 }, + { "cqmfile", required_argument, NULL, 0 }, {0, 0, 0, 0} }; diff --git a/src/config.h b/src/config.h index 1175fd90..8159297c 100644 --- a/src/config.h +++ b/src/config.h @@ -58,6 +58,7 @@ typedef struct int8_t chroma_loc; /*!< \brief Chroma sample location */ } vui; int8_t aud_enable; /*!< \brief Flag to use access unit delimiters */ + char * cqmfile; /*!< \brief Pointer to custom quantization matrices filename */ } config; /* Function definitions */ diff --git a/src/encmain.c b/src/encmain.c index 260a74dd..cd3e730a 100644 --- a/src/encmain.c +++ b/src/encmain.c @@ -59,6 +59,7 @@ int main(int argc, char *argv[]) config *cfg = NULL; //!< Global configuration FILE *input = NULL; //!< input file (YUV) FILE *output = NULL; //!< output file (HEVC NAL stream) + FILE *cqmfile = NULL; //!< HM-compatible CQM file encoder_control *encoder = NULL; //!< Encoder control struct double psnr[3] = { 0.0, 0.0, 0.0 }; uint64_t curpos = 0; @@ -102,6 +103,7 @@ int main(int argc, char *argv[]) " beta and tc range is -6..6 [0:0]\n" " --no-sao : Disable sample adaptive offset\n" " --aud : Use access unit delimiters\n" + " --cqmfile : Custom Quantization Matrices from a file\n" "\n" " Video Usability Information:\n" " --sar : Specify Sample Aspect Ratio\n" @@ -202,6 +204,9 @@ int main(int argc, char *argv[]) encoder->vui.chroma_loc = encoder->cfg->vui.chroma_loc; // AUD encoder->aud_enable = encoder->cfg->aud_enable; + // CQM + cqmfile = cfg->cqmfile ? fopen(cfg->cqmfile, "rb") : NULL; + encoder->cqmfile = cqmfile; init_encoder_input(&encoder->in, input, cfg->width, cfg->height); @@ -290,6 +295,7 @@ int main(int argc, char *argv[]) fclose(input); fclose(output); + fclose(cqmfile); #ifdef _DEBUG fclose(recout); #endif diff --git a/src/encoder.c b/src/encoder.c index b6f90cfd..ca9b7fe8 100644 --- a/src/encoder.c +++ b/src/encoder.c @@ -398,6 +398,8 @@ void encode_one_frame(encoder_control* encoder) picture_list_rem(encoder->ref, encoder->ref->used_size - 1, 1); } + if (encoder->frame == 0 && encoder->cqmfile) + scalinglist_parse(encoder->cqmfile); encoder->poc = 0; @@ -433,6 +435,7 @@ void encode_one_frame(encoder_control* encoder) bitstream_clear_buffer(encoder->stream); if (encoder->frame == 0) { + // Prefix SEI encode_prefix_sei_version(encoder); bitstream_align(encoder->stream); bitstream_flush(encoder->stream); @@ -749,6 +752,61 @@ void encode_PTL(encoder_control *encoder) // end PTL } +static void encode_scaling_list(encoder_control* encoder) +{ + uint32_t size_id; + for (size_id = 0; size_id < SCALING_LIST_SIZE_NUM; size_id++) { + uint32_t list_id; + for (list_id = 0; list_id < g_scaling_list_num[size_id]; list_id++) { + uint8_t scaling_list_pred_mode_flag = 1; + int32_t pred_list_idx; + int32_t i; + uint32_t ref_matrix_id; + + for (pred_list_idx = list_id; pred_list_idx >= 0; pred_list_idx--) { + int32_t *pred_list = (list_id == pred_list_idx) ? + scalinglist_get_default(size_id, pred_list_idx) : + g_scaling_list_coeff[size_id][pred_list_idx]; + + if (!memcmp(g_scaling_list_coeff[size_id][list_id], pred_list, sizeof(int32_t) * MIN(8, g_scaling_list_size[size_id])) && + ((size_id < SCALING_LIST_16x16) || + (g_scaling_list_dc[size_id][list_id] == g_scaling_list_dc[size_id][pred_list_idx]))) { + ref_matrix_id = pred_list_idx; + scaling_list_pred_mode_flag = 0; + break; + } + } + WRITE_U(encoder->stream, scaling_list_pred_mode_flag, 1, "scaling_list_pred_mode_flag" ); + + if (!scaling_list_pred_mode_flag) { + WRITE_UE(encoder->stream, list_id - ref_matrix_id, "scaling_list_pred_matrix_id_delta"); + } else { + int32_t delta; + int32_t coef_num = MIN(MAX_MATRIX_COEF_NUM, g_scaling_list_size[size_id]); + uint32_t *scan = (size_id == 0) ? g_sig_last_scan[SCAN_DIAG][1] : g_sig_last_scan_32x32; + int32_t next_coef = 8; + int32_t *coef_list = g_scaling_list_coeff[size_id][list_id]; + + if (size_id >= SCALING_LIST_16x16) { + WRITE_SE(encoder->stream, g_scaling_list_dc[size_id][list_id] - 8, "scaling_list_dc_coef_minus8"); + next_coef = g_scaling_list_dc[size_id][list_id]; + } + + for (i = 0; i < coef_num; i++) { + delta = coef_list[scan[i]] - next_coef; + next_coef = coef_list[scan[i]]; + if (delta > 127) + delta -= 256; + if (delta < -128) + delta += 256; + + WRITE_SE(encoder->stream, delta, "scaling_list_delta_coef"); + } + } + } + } +} + void encode_seq_parameter_set(encoder_control* encoder) { encoder_input* const in = &encoder->in; @@ -813,11 +871,12 @@ void encode_seq_parameter_set(encoder_control* encoder) WRITE_UE(encoder->stream, TR_DEPTH_INTER, "max_transform_hierarchy_depth_inter"); WRITE_UE(encoder->stream, TR_DEPTH_INTRA, "max_transform_hierarchy_depth_intra"); - // Use default scaling list - WRITE_U(encoder->stream, ENABLE_SCALING_LIST, 1, "scaling_list_enable_flag"); - #if ENABLE_SCALING_LIST == 1 - WRITE_U(encoder->stream, 0, 1, "sps_scaling_list_data_present_flag"); - #endif + // scaling list + WRITE_U(encoder->stream, g_scaling_list_enable, 1, "scaling_list_enable_flag"); + if (g_scaling_list_enable) { + WRITE_U(encoder->stream, 1, 1, "sps_scaling_list_data_present_flag"); + encode_scaling_list(encoder); + } WRITE_U(encoder->stream, 0, 1, "amp_enabled_flag"); WRITE_U(encoder->stream, encoder->sao_enable ? 1 : 0, 1, diff --git a/src/encoder.h b/src/encoder.h index 403d7e2f..429b05d0 100644 --- a/src/encoder.h +++ b/src/encoder.h @@ -94,6 +94,7 @@ typedef struct } vui; int8_t aud_enable; + FILE *cqmfile; // \brief Costum Quantization Matrices } encoder_control; void init_tables(void); diff --git a/src/global.h b/src/global.h index 0caf7b56..526e19cd 100644 --- a/src/global.h +++ b/src/global.h @@ -73,7 +73,6 @@ typedef int16_t coefficient; #define ENABLE_PCM 0 /*!< Setting to 1 will enable using PCM blocks (current intra-search does not consider PCM) */ #define ENABLE_SIGN_HIDING 1 -#define ENABLE_SCALING_LIST 0 /*!< Enable usage of (default) scaling list */ #define ENABLE_TEMPORAL_MVP 0 /*!< Enable usage of temporal Motion Vector Prediction */ diff --git a/src/transform.c b/src/transform.c index ff5bd000..ea0d2ec7 100644 --- a/src/transform.c +++ b/src/transform.c @@ -33,6 +33,9 @@ ////////////////////////////////////////////////////////////////////////// // INITIALIZATIONS // + +#define SCALING_LIST_REM_NUM 6 + const int16_t g_t4[4][4] = { { 64, 64, 64, 64}, @@ -149,9 +152,12 @@ const uint8_t g_chroma_scale[58]= 45,46,47,48,49,50,51 }; -int32_t *g_quant_coeff[4][6][6]; -int32_t *g_de_quant_coeff[4][6][6]; -double *g_error_scale[4][6][6]; +uint8_t g_scaling_list_enable = 0; +int32_t g_scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM] = { { 0 } }; +int32_t *g_scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM] = { { NULL } }; +int32_t *g_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; +int32_t *g_de_quant_coeff [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; +double *g_error_scale [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM][SCALING_LIST_REM_NUM]; const uint8_t g_scaling_list_num[4] = { 6, 6, 6, 2}; const uint16_t g_scaling_list_size[4] = { 16, 64, 256,1024}; @@ -181,6 +187,7 @@ void scalinglist_init() g_error_scale[sizeId][listId][qp] = (double*)calloc(g_scaling_list_size[sizeId], sizeof(double)); } } + g_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 @@ -208,6 +215,7 @@ void scalinglist_destroy() free( g_error_scale[sizeId][listId][qp]); } } + free(g_scaling_list_coeff[sizeId][listId]); } } } @@ -219,26 +227,13 @@ void scalinglist_destroy() */ void scalinglist_process() { - #define SCALING_LIST_SIZE_NUM 4 - #define SCALING_LIST_REM_NUM 6 uint32_t size,list,qp; for (size = 0; size < SCALING_LIST_SIZE_NUM; size++) { - int32_t* list_ptr = (int32_t *)g_quant_intra_default_8x8; // Default to "8x8" intra - for (list = 0; list < g_scaling_list_num[size]; list++) { - switch(size) { - case 0: // 4x4 - list_ptr = (int32_t *)g_quant_default_4x4; - break; - case 1: // 8x8 - case 2: // 16x16 - if (list > 2) list_ptr = (int32_t*)g_quant_inter_default_8x8; - break; - case 3: // 32x32 - if (list > 0) list_ptr = (int32_t*)g_quant_inter_default_8x8; - break; - } + int32_t *list_ptr = g_scaling_list_enable ? + g_scaling_list_coeff[size][list] : + scalinglist_get_default(size, list); for (qp = 0; qp < SCALING_LIST_REM_NUM; qp++) { scalinglist_set(list_ptr, list, size, qp); @@ -246,8 +241,6 @@ void scalinglist_process() } } } - #undef SCALING_LIST_SIZE_NUM - #undef SCALING_LIST_REM_NUM } @@ -334,19 +327,19 @@ void scalinglist_process_dec( int32_t *coeff, int32_t *dequantcoeff, int32_t inv */ void scalinglist_set(int32_t *coeff, uint32_t listId, uint32_t sizeId, uint32_t qp) { - #define SCALING_LIST_DC 16 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 = g_quant_coeff[sizeId][listId][qp]; int32_t *dequantcoeff = g_de_quant_coeff[sizeId][listId][qp]; + uint32_t dc = g_scaling_list_dc[sizeId][listId] != 0 ? g_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]), SCALING_LIST_DC, ENABLE_SCALING_LIST ? 0 : 1); + MIN(8, g_scaling_list_size_x[sizeId]), dc, !g_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]), SCALING_LIST_DC, ENABLE_SCALING_LIST ? 0 : 1); + MIN(8, g_scaling_list_size_x[sizeId]), dc, !g_scaling_list_enable); // TODO: support NSQT @@ -357,7 +350,6 @@ void scalinglist_set(int32_t *coeff, uint32_t listId, uint32_t sizeId, uint32_t // 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); // } - #undef SCALING_LIST_DC } @@ -962,12 +954,12 @@ void dequant(encoder_control *encoder, int16_t *q_coef, int16_t *coef, int32_t w shift = 20 - QUANT_SHIFT - transform_shift; UNREFERENCED_PARAMETER(block_type); - #if ENABLE_SCALING_LIST == 1 + if (g_scaling_list_enable) { 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]); - dequant_coef = g_de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; + int32_t *dequant_coef = g_de_quant_coeff[log2_tr_size-2][scalinglist_type][qp_scaled%6]; shift += 4; if (shift >qp_scaled / 6) { @@ -986,9 +978,7 @@ void dequant(encoder_control *encoder, int16_t *q_coef, int16_t *coef, int32_t w coef[n] = (int16_t)CLIP(-32768, 32767, coeff_q << (qp_scaled/6 - shift)); } } - } - #else - { + } else { int32_t scale = g_inv_quant_scales[qp_scaled%6] << (qp_scaled/6); add = 1 << (shift-1); @@ -998,5 +988,145 @@ void dequant(encoder_control *encoder, int16_t *q_coef, int16_t *coef, int32_t w coef[n] = (int16_t)CLIP(-32768, 32767, coeff_q); } } - #endif +} + +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(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]); + uint32_t *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 = g_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; + + g_scaling_list_dc[size_id][list_id] = data; + } else + g_scaling_list_dc[size_id][list_id] = coeff[0]; + } + } + + g_scaling_list_enable = 1; + return 1; + #undef LINE_BUFSIZE } diff --git a/src/transform.h b/src/transform.h index 6bbf00a3..c4035e2e 100644 --- a/src/transform.h +++ b/src/transform.h @@ -30,9 +30,21 @@ #include +#define SCALING_LIST_4x4 0 +#define SCALING_LIST_8x8 1 +#define SCALING_LIST_16x16 2 +#define SCALING_LIST_32x32 3 +#define SCALING_LIST_SIZE_NUM 4 +#define SCALING_LIST_NUM 6 +#define MAX_MATRIX_COEF_NUM 64 +extern uint8_t g_scaling_list_enable; +extern int32_t g_scaling_list_dc [SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; +extern int32_t* g_scaling_list_coeff[SCALING_LIST_SIZE_NUM][SCALING_LIST_NUM]; extern int32_t* g_quant_coeff[4][6][6]; extern double* g_error_scale[4][6][6]; +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]; @@ -53,4 +65,7 @@ void scalinglist_set(int32_t *coeff, uint32_t list_id, uint32_t size_id, uint32_ void scalinglist_set_err_scale(uint32_t list,uint32_t size, uint32_t qp); void scalinglist_destroy(); +int32_t *scalinglist_get_default(uint32_t size_id, uint32_t list_id); +int scalinglist_parse(FILE *fp); + #endif