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
This commit is contained in:
Yusuke Nakamura 2014-02-11 19:55:21 +09:00
parent 96d62e1bec
commit a860bbc7f9
9 changed files with 254 additions and 37 deletions

View file

@ -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 <string> : Custom Quantization Matrices from a file
Video Usability Information:
--sar <width:height> : Specify Sample Aspect Ratio

View file

@ -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}
};

View file

@ -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 */

View file

@ -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 <string> : Custom Quantization Matrices from a file\n"
"\n"
" Video Usability Information:\n"
" --sar <width:height> : 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

View file

@ -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,

View file

@ -94,6 +94,7 @@ typedef struct
} vui;
int8_t aud_enable;
FILE *cqmfile; // \brief Costum Quantization Matrices
} encoder_control;
void init_tables(void);

View file

@ -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 */

View file

@ -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
}

View file

@ -30,9 +30,21 @@
#include <math.h>
#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