From 1ab01bbc01bc482e9891fe843e1ddd14b7625540 Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Mon, 20 Jun 2005 00:08:28 +0000 Subject: [PATCH] custom quant matrices git-svn-id: svn://svn.videolan.org/x264/trunk@266 df754926-b1dd-0310-bc7b-ec298dee348c --- Makefile | 2 +- common/common.c | 8 +++ common/common.h | 5 ++ common/macroblock.c | 114 ++++++++++++++++++++++++------------------- common/macroblock.h | 21 ++++++-- common/set.c | 107 ++++++++++++++++++++++++++++++++++++++++ common/set.h | 67 +++++++++++++++++++++++++ encoder/encoder.c | 6 +++ encoder/macroblock.c | 114 +++++++++++-------------------------------- encoder/set.c | 78 ++++++++++++++++++++++++++--- x264.c | 109 +++++++++++++++++++++++++++++++++++++++++ x264.h | 10 ++++ 12 files changed, 495 insertions(+), 146 deletions(-) create mode 100644 common/set.c diff --git a/Makefile b/Makefile index c030cbdc..687146d8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ include config.mak SRCS = common/mc.c common/predict.c common/pixel.c common/macroblock.c \ common/frame.c common/dct.c common/cpu.c common/cabac.c \ - common/common.c common/mdate.c common/csp.c \ + common/common.c common/mdate.c common/csp.c common/set.c\ encoder/analyse.c encoder/me.c encoder/ratecontrol.c \ encoder/set.c encoder/macroblock.c encoder/cabac.c \ encoder/cavlc.c encoder/encoder.c encoder/eval.c diff --git a/common/common.c b/common/common.c index 3554d193..c6286f92 100644 --- a/common/common.c +++ b/common/common.c @@ -116,6 +116,14 @@ void x264_param_default( x264_param_t *param ) param->analyse.i_chroma_qp_offset = 0; param->analyse.b_psnr = 1; + param->i_cqm_preset = X264_CQM_FLAT; + memset( param->cqm_4iy, 16, 16 ); + memset( param->cqm_4ic, 16, 16 ); + memset( param->cqm_4py, 16, 16 ); + memset( param->cqm_4pc, 16, 16 ); + memset( param->cqm_8iy, 16, 64 ); + memset( param->cqm_8py, 16, 64 ); + param->b_aud = 0; } diff --git a/common/common.h b/common/common.h index 162c632d..e561ccca 100644 --- a/common/common.h +++ b/common/common.h @@ -239,6 +239,11 @@ struct x264_t x264_pps_t *pps; int i_idr_pic_id; + int dequant4_mf[4][6][4][4]; + int dequant8_mf[2][6][8][8]; + int quant4_mf[4][6][4][4]; + int quant8_mf[2][6][8][8]; + /* Slice header */ x264_slice_header_t sh; diff --git a/common/macroblock.c b/common/macroblock.c index 85a73c7d..f9fb030c 100644 --- a/common/macroblock.c +++ b/common/macroblock.c @@ -163,34 +163,35 @@ int x264_mb_transform_8x8_allowed( x264_t *h ) /**************************************************************************** * Scan and Quant functions ****************************************************************************/ -void x264_mb_dequant_2x2_dc( int16_t dct[2][2], int i_qscale ) +void x264_mb_dequant_2x2_dc( int16_t dct[2][2], int dequant_mf[6][4][4], int i_qscale ) { - const int i_qbits = i_qscale/6 - 1; + const int i_qbits = i_qscale/6 - 5; if( i_qbits >= 0 ) { const int i_dmf = dequant_mf[i_qscale%6][0][0] << i_qbits; - dct[0][0] = dct[0][0] * i_dmf; - dct[0][1] = dct[0][1] * i_dmf; - dct[1][0] = dct[1][0] * i_dmf; - dct[1][1] = dct[1][1] * i_dmf; + dct[0][0] *= i_dmf; + dct[0][1] *= i_dmf; + dct[1][0] *= i_dmf; + dct[1][1] *= i_dmf; } else { const int i_dmf = dequant_mf[i_qscale%6][0][0]; + // chroma DC is truncated, not rounded - dct[0][0] = ( dct[0][0] * i_dmf ) >> 1; - dct[0][1] = ( dct[0][1] * i_dmf ) >> 1; - dct[1][0] = ( dct[1][0] * i_dmf ) >> 1; - dct[1][1] = ( dct[1][1] * i_dmf ) >> 1; + dct[0][0] = ( dct[0][0] * i_dmf ) >> (-i_qbits); + dct[0][1] = ( dct[0][1] * i_dmf ) >> (-i_qbits); + dct[1][0] = ( dct[1][0] * i_dmf ) >> (-i_qbits); + dct[1][1] = ( dct[1][1] * i_dmf ) >> (-i_qbits); } } -void x264_mb_dequant_4x4_dc( int16_t dct[4][4], int i_qscale ) +void x264_mb_dequant_4x4_dc( int16_t dct[4][4], int dequant_mf[6][4][4], int i_qscale ) { - const int i_qbits = i_qscale/6 - 2; - int x,y; + const int i_qbits = i_qscale/6 - 6; + int y; if( i_qbits >= 0 ) { @@ -198,76 +199,89 @@ void x264_mb_dequant_4x4_dc( int16_t dct[4][4], int i_qscale ) for( y = 0; y < 4; y++ ) { - for( x = 0; x < 4; x++ ) - { - dct[y][x] = dct[y][x] * i_dmf; - } + dct[y][0] *= i_dmf; + dct[y][1] *= i_dmf; + dct[y][2] *= i_dmf; + dct[y][3] *= i_dmf; } } else { const int i_dmf = dequant_mf[i_qscale%6][0][0]; - const int f = -i_qbits; // 1 << (-1-i_qbits) + const int f = 1 << (-i_qbits-1); for( y = 0; y < 4; y++ ) { - for( x = 0; x < 4; x++ ) - { - dct[y][x] = ( dct[y][x] * i_dmf + f ) >> (-i_qbits); - } + dct[y][0] = ( dct[y][0] * i_dmf + f ) >> (-i_qbits); + dct[y][1] = ( dct[y][1] * i_dmf + f ) >> (-i_qbits); + dct[y][2] = ( dct[y][2] * i_dmf + f ) >> (-i_qbits); + dct[y][3] = ( dct[y][3] * i_dmf + f ) >> (-i_qbits); } } } -void x264_mb_dequant_4x4( int16_t dct[4][4], int i_qscale ) +void x264_mb_dequant_4x4( int16_t dct[4][4], int dequant_mf[6][4][4], int i_qscale ) { const int i_mf = i_qscale%6; - const int i_qbits = i_qscale/6; + const int i_qbits = i_qscale/6 - 4; int y; - for( y = 0; y < 4; y++ ) + if( i_qbits >= 0 ) + { + for( y = 0; y < 4; y++ ) + { + dct[y][0] = ( dct[y][0] * dequant_mf[i_mf][y][0] ) << i_qbits; + dct[y][1] = ( dct[y][1] * dequant_mf[i_mf][y][1] ) << i_qbits; + dct[y][2] = ( dct[y][2] * dequant_mf[i_mf][y][2] ) << i_qbits; + dct[y][3] = ( dct[y][3] * dequant_mf[i_mf][y][3] ) << i_qbits; + } + } + else { - dct[y][0] = ( dct[y][0] * dequant_mf[i_mf][y][0] ) << i_qbits; - dct[y][1] = ( dct[y][1] * dequant_mf[i_mf][y][1] ) << i_qbits; - dct[y][2] = ( dct[y][2] * dequant_mf[i_mf][y][2] ) << i_qbits; - dct[y][3] = ( dct[y][3] * dequant_mf[i_mf][y][3] ) << i_qbits; + const int f = 1 << (-i_qbits-1); + for( y = 0; y < 4; y++ ) + { + dct[y][0] = ( dct[y][0] * dequant_mf[i_mf][y][0] + f ) >> (-i_qbits); + dct[y][1] = ( dct[y][1] * dequant_mf[i_mf][y][1] + f ) >> (-i_qbits); + dct[y][2] = ( dct[y][2] * dequant_mf[i_mf][y][2] + f ) >> (-i_qbits); + dct[y][3] = ( dct[y][3] * dequant_mf[i_mf][y][3] + f ) >> (-i_qbits); + } } } -void x264_mb_dequant_8x8( int16_t dct[8][8], int i_qscale ) +void x264_mb_dequant_8x8( int16_t dct[8][8], int dequant_mf[6][8][8], int i_qscale ) { const int i_mf = i_qscale%6; + const int i_qbits = i_qscale/6 - 6; int y; - if( i_qscale >= 12 ) + if( i_qbits >= 0 ) { - const int i_qbits = (i_qscale/6) - 2; for( y = 0; y < 8; y++ ) { - dct[y][0] = ( dct[y][0] * dequant8_mf[i_mf][y][0] ) << i_qbits; - dct[y][1] = ( dct[y][1] * dequant8_mf[i_mf][y][1] ) << i_qbits; - dct[y][2] = ( dct[y][2] * dequant8_mf[i_mf][y][2] ) << i_qbits; - dct[y][3] = ( dct[y][3] * dequant8_mf[i_mf][y][3] ) << i_qbits; - dct[y][4] = ( dct[y][4] * dequant8_mf[i_mf][y][4] ) << i_qbits; - dct[y][5] = ( dct[y][5] * dequant8_mf[i_mf][y][5] ) << i_qbits; - dct[y][6] = ( dct[y][6] * dequant8_mf[i_mf][y][6] ) << i_qbits; - dct[y][7] = ( dct[y][7] * dequant8_mf[i_mf][y][7] ) << i_qbits; + dct[y][0] = ( dct[y][0] * dequant_mf[i_mf][y][0] ) << i_qbits; + dct[y][1] = ( dct[y][1] * dequant_mf[i_mf][y][1] ) << i_qbits; + dct[y][2] = ( dct[y][2] * dequant_mf[i_mf][y][2] ) << i_qbits; + dct[y][3] = ( dct[y][3] * dequant_mf[i_mf][y][3] ) << i_qbits; + dct[y][4] = ( dct[y][4] * dequant_mf[i_mf][y][4] ) << i_qbits; + dct[y][5] = ( dct[y][5] * dequant_mf[i_mf][y][5] ) << i_qbits; + dct[y][6] = ( dct[y][6] * dequant_mf[i_mf][y][6] ) << i_qbits; + dct[y][7] = ( dct[y][7] * dequant_mf[i_mf][y][7] ) << i_qbits; } } else { - const int i_qbits = 2 - (i_qscale/6); - const int i_round = i_qbits; // 1<<(i_qbits-1) + const int f = 1 << (-i_qbits-1); for( y = 0; y < 8; y++ ) { - dct[y][0] = ( dct[y][0] * dequant8_mf[i_mf][y][0] + i_round ) >> i_qbits; - dct[y][1] = ( dct[y][1] * dequant8_mf[i_mf][y][1] + i_round ) >> i_qbits; - dct[y][2] = ( dct[y][2] * dequant8_mf[i_mf][y][2] + i_round ) >> i_qbits; - dct[y][3] = ( dct[y][3] * dequant8_mf[i_mf][y][3] + i_round ) >> i_qbits; - dct[y][4] = ( dct[y][4] * dequant8_mf[i_mf][y][4] + i_round ) >> i_qbits; - dct[y][5] = ( dct[y][5] * dequant8_mf[i_mf][y][5] + i_round ) >> i_qbits; - dct[y][6] = ( dct[y][6] * dequant8_mf[i_mf][y][6] + i_round ) >> i_qbits; - dct[y][7] = ( dct[y][7] * dequant8_mf[i_mf][y][7] + i_round ) >> i_qbits; + dct[y][0] = ( dct[y][0] * dequant_mf[i_mf][y][0] + f ) >> (-i_qbits); + dct[y][1] = ( dct[y][1] * dequant_mf[i_mf][y][1] + f ) >> (-i_qbits); + dct[y][2] = ( dct[y][2] * dequant_mf[i_mf][y][2] + f ) >> (-i_qbits); + dct[y][3] = ( dct[y][3] * dequant_mf[i_mf][y][3] + f ) >> (-i_qbits); + dct[y][4] = ( dct[y][4] * dequant_mf[i_mf][y][4] + f ) >> (-i_qbits); + dct[y][5] = ( dct[y][5] * dequant_mf[i_mf][y][5] + f ) >> (-i_qbits); + dct[y][6] = ( dct[y][6] * dequant_mf[i_mf][y][6] + f ) >> (-i_qbits); + dct[y][7] = ( dct[y][7] * dequant_mf[i_mf][y][7] + f ) >> (-i_qbits); } } } diff --git a/common/macroblock.h b/common/macroblock.h index bbbed8f3..c545d5cf 100644 --- a/common/macroblock.h +++ b/common/macroblock.h @@ -157,6 +157,19 @@ static const int x264_mb_partition_count_table[17] = 4, 2, 2, 1 }; +static const int x264_zigzag_scan4[16] = +{ + 0, 1, 4, 8, 5, 2, 3, 6, 9, 12, 13, 10, 7, 11, 14, 15 +}; +static const int x264_zigzag_scan8[64] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63 +}; + + void x264_macroblock_cache_init( x264_t *h ); void x264_macroblock_slice_init( x264_t *h ); void x264_macroblock_cache_load( x264_t *h, int i_mb_x, int i_mb_y ); @@ -165,10 +178,10 @@ void x264_macroblock_cache_end( x264_t *h ); void x264_macroblock_bipred_init( x264_t *h ); -void x264_mb_dequant_4x4_dc( int16_t dct[4][4], int i_qscale ); -void x264_mb_dequant_2x2_dc( int16_t dct[2][2], int i_qscale ); -void x264_mb_dequant_4x4( int16_t dct[4][4], int i_qscale ); -void x264_mb_dequant_8x8( int16_t dct[8][8], int i_qscale ); +void x264_mb_dequant_4x4_dc( int16_t dct[4][4], int dequant_mf[6][4][4], int i_qscale ); +void x264_mb_dequant_2x2_dc( int16_t dct[2][2], int dequant_mf[6][4][4], int i_qscale ); +void x264_mb_dequant_4x4( int16_t dct[4][4], int dequant_mf[6][4][4], int i_qscale ); +void x264_mb_dequant_8x8( int16_t dct[8][8], int dequant_mf[6][8][8], int i_qscale ); /* x264_mb_predict_mv_16x16: * set mvp with predicted mv for D_16x16 block diff --git a/common/set.c b/common/set.c new file mode 100644 index 00000000..60bad3ad --- /dev/null +++ b/common/set.c @@ -0,0 +1,107 @@ +/***************************************************************************** + * set.c: h264 encoder library + ***************************************************************************** + * Copyright (C) 2005 x264 project + * + * Authors: Loren Merritt + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. + *****************************************************************************/ + +#include "common.h" + +static const int dequant4_scale[6][3] = +{ + { 10, 13, 16 }, + { 11, 14, 18 }, + { 13, 16, 20 }, + { 14, 18, 23 }, + { 16, 20, 25 }, + { 18, 23, 29 } +}; +static const int quant4_scale[6][3] = +{ + { 13107, 8066, 5243 }, + { 11916, 7490, 4660 }, + { 10082, 6554, 4194 }, + { 9362, 5825, 3647 }, + { 8192, 5243, 3355 }, + { 7282, 4559, 2893 }, +}; + +static const int quant8_scan[16] = +{ + 0,3,4,3, 3,1,5,1, 4,5,2,5, 3,1,5,1 +}; +static const int dequant8_scale[6][6] = +{ + { 20, 18, 32, 19, 25, 24 }, + { 22, 19, 35, 21, 28, 26 }, + { 26, 23, 42, 24, 33, 31 }, + { 28, 25, 45, 26, 35, 33 }, + { 32, 28, 51, 30, 40, 38 }, + { 36, 32, 58, 34, 46, 43 }, +}; +static const int quant8_scale[6][6] = +{ + { 13107, 11428, 20972, 12222, 16777, 15481 }, + { 11916, 10826, 19174, 11058, 14980, 14290 }, + { 10082, 8943, 15978, 9675, 12710, 11985 }, + { 9362, 8228, 14913, 8931, 11984, 11259 }, + { 8192, 7346, 13159, 7740, 10486, 9777 }, + { 7282, 6428, 11570, 6830, 9118, 8640 } +}; + +void x264_cqm_init( x264_t *h ) +{ + int def_quant4[6][16]; + int def_quant8[6][64]; + int def_dequant4[6][16]; + int def_dequant8[6][64]; + int q, i, i_list; + + for( q = 0; q < 6; q++ ) + { + for( i = 0; i < 16; i++ ) + { + int j = (i&1) + ((i>>2)&1); + def_dequant4[q][i] = dequant4_scale[q][j]; + def_quant4[q][i] = quant4_scale[q][j]; + } + for( i = 0; i < 64; i++ ) + { + int j = quant8_scan[((i>>1)&12) | (i&3)]; + def_dequant8[q][i] = dequant8_scale[q][j]; + def_quant8[q][i] = quant8_scale[q][j]; + } + } + + for( q = 0; q < 6; q++ ) + { + for( i_list = 0; i_list < 4; i_list++ ) + for( i = 0; i < 16; i++ ) + { + h->dequant4_mf[i_list][q][0][i] = def_dequant4[q][i] * h->pps->scaling_list[i_list][i]; + h-> quant4_mf[i_list][q][0][i] = def_quant4[q][i] * 16 / h->pps->scaling_list[i_list][i]; + } + for( i_list = 0; i_list < 2; i_list++ ) + for( i = 0; i < 64; i++ ) + { + h->dequant8_mf[i_list][q][0][i] = def_dequant8[q][i] * h->pps->scaling_list[4+i_list][i]; + h-> quant8_mf[i_list][q][0][i] = def_quant8[q][i] * 16 / h->pps->scaling_list[4+i_list][i]; + } + } +} + diff --git a/common/set.h b/common/set.h index b29a00dd..3f588fcc 100644 --- a/common/set.h +++ b/common/set.h @@ -35,6 +35,19 @@ enum profile_e PROFILE_HIGH444 = 144 }; +enum cqm4_e +{ + CQM_4IY = 0, + CQM_4PY = 1, + CQM_4IC = 2, + CQM_4PC = 3 +}; +enum cqm8_e +{ + CQM_8IY = 0, + CQM_8PY = 1 +}; + typedef struct { int i_id; @@ -147,6 +160,60 @@ typedef struct int b_transform_8x8_mode; + int i_cqm_preset; + const uint8_t *scaling_list[6]; /* could be 8, but we don't allow separate Cb/Cr lists */ + } x264_pps_t; +/* default quant matrices */ +static const uint8_t x264_cqm_jvt4i[16] = +{ + 6,13,20,28, + 13,20,28,32, + 20,28,32,37, + 28,32,37,42 +}; +static const uint8_t x264_cqm_jvt4p[16] = +{ + 10,14,20,24, + 14,20,24,27, + 20,24,27,30, + 24,27,30,34 +}; +static const uint8_t x264_cqm_jvt8i[64] = +{ + 6,10,13,16,18,23,25,27, + 10,11,16,18,23,25,27,29, + 13,16,18,23,25,27,29,31, + 16,18,23,25,27,29,31,33, + 18,23,25,27,29,31,33,36, + 23,25,27,29,31,33,36,38, + 25,27,29,31,33,36,38,40, + 27,29,31,33,36,38,40,42 +}; +static const uint8_t x264_cqm_jvt8p[64] = +{ + 9,13,15,17,19,21,22,24, + 13,13,17,19,21,22,24,25, + 15,17,19,21,22,24,25,27, + 17,19,21,22,24,25,27,28, + 19,21,22,24,25,27,28,30, + 21,22,24,25,27,28,30,32, + 22,24,25,27,28,30,32,33, + 24,25,27,28,30,32,33,35 +}; +static const uint8_t x264_cqm_flat16[64] = +{ + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16, + 16,16,16,16,16,16,16,16 +}; + +void x264_cqm_init( x264_t *h ); + #endif diff --git a/encoder/encoder.c b/encoder/encoder.c index 79857cc7..32c5072c 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -387,6 +387,7 @@ static int x264_validate_parameters( x264_t *h ) { h->mb.b_lossless = 1; h->param.analyse.b_transform_8x8 = 0; + h->param.i_cqm_preset = X264_CQM_FLAT; h->param.rc.f_ip_factor = 1; h->param.rc.f_pb_factor = 1; h->param.analyse.b_psnr = 0; @@ -414,6 +415,9 @@ static int x264_validate_parameters( x264_t *h ) if( h->param.i_threads > 1 && h->param.i_cabac_init_idc == -1 ) h->param.i_cabac_init_idc = 0; + if( h->param.i_cqm_preset < X264_CQM_FLAT || h->param.i_cqm_preset > X264_CQM_CUSTOM ) + h->param.i_cqm_preset = X264_CQM_FLAT; + if( h->param.analyse.i_me_method < X264_ME_DIA || h->param.analyse.i_me_method > X264_ME_ESA ) h->param.analyse.i_me_method = X264_ME_HEX; @@ -523,6 +527,8 @@ x264_t *x264_encoder_open ( x264_param_t *param ) h->pps = &h->pps_array[0]; x264_pps_init( h->pps, 0, &h->param, h->sps); + + x264_cqm_init( h ); h->mb.i_mb_count = h->sps->i_mb_width * h->sps->i_mb_height; diff --git a/encoder/macroblock.c b/encoder/macroblock.c index 40f53974..650c414d 100644 --- a/encoder/macroblock.c +++ b/encoder/macroblock.c @@ -45,7 +45,10 @@ static const uint8_t block_idx_xy[4][4] = { 5, 7, 13, 15 } }; -static const int quant_mf[6][4][4] = +/* def_quant4_mf only for probe_skip; actual encoding uses matrices from set.c */ +/* FIXME this seems to make better decisions with cqm=jvt, but could screw up + * with general custom matrices. */ +static const int def_quant4_mf[6][4][4] = { { { 13107, 8066, 13107, 8066 }, { 8066, 5243, 8066, 5243 }, { 13107, 8066, 13107, 8066 }, { 8066, 5243, 8066, 5243 } }, @@ -61,65 +64,6 @@ static const int quant_mf[6][4][4] = { 7282, 4559, 7282, 4559 }, { 4559, 2893, 4559, 2893 } } }; -const int quant8_mf[6][8][8] = -{ - { - { 13107, 12222, 16777, 12222, 13107, 12222, 16777, 12222 }, - { 12222, 11428, 15481, 11428, 12222, 11428, 15481, 11428 }, - { 16777, 15481, 20972, 15481, 16777, 15481, 20972, 15481 }, - { 12222, 11428, 15481, 11428, 12222, 11428, 15481, 11428 }, - { 13107, 12222, 16777, 12222, 13107, 12222, 16777, 12222 }, - { 12222, 11428, 15481, 11428, 12222, 11428, 15481, 11428 }, - { 16777, 15481, 20972, 15481, 16777, 15481, 20972, 15481 }, - { 12222, 11428, 15481, 11428, 12222, 11428, 15481, 11428 } - }, { - { 11916, 11058, 14980, 11058, 11916, 11058, 14980, 11058 }, - { 11058, 10826, 14290, 10826, 11058, 10826, 14290, 10826 }, - { 14980, 14290, 19174, 14290, 14980, 14290, 19174, 14290 }, - { 11058, 10826, 14290, 10826, 11058, 10826, 14290, 10826 }, - { 11916, 11058, 14980, 11058, 11916, 11058, 14980, 11058 }, - { 11058, 10826, 14290, 10826, 11058, 10826, 14290, 10826 }, - { 14980, 14290, 19174, 14290, 14980, 14290, 19174, 14290 }, - { 11058, 10826, 14290, 10826, 11058, 10826, 14290, 10826 } - }, { - { 10082, 9675, 12710, 9675, 10082, 9675, 12710, 9675 }, - { 9675, 8943, 11985, 8943, 9675, 8943, 11985, 8943 }, - { 12710, 11985, 15978, 11985, 12710, 11985, 15978, 11985 }, - { 9675, 8943, 11985, 8943, 9675, 8943, 11985, 8943 }, - { 10082, 9675, 12710, 9675, 10082, 9675, 12710, 9675 }, - { 9675, 8943, 11985, 8943, 9675, 8943, 11985, 8943 }, - { 12710, 11985, 15978, 11985, 12710, 11985, 15978, 11985 }, - { 9675, 8943, 11985, 8943, 9675, 8943, 11985, 8943 } - }, { - { 9362, 8931, 11984, 8931, 9362, 8931, 11984, 8931 }, - { 8931, 8228, 11259, 8228, 8931, 8228, 11259, 8228 }, - { 11984, 11259, 14913, 11259, 11984, 11259, 14913, 11259 }, - { 8931, 8228, 11259, 8228, 8931, 8228, 11259, 8228 }, - { 9362, 8931, 11984, 8931, 9362, 8931, 11984, 8931 }, - { 8931, 8228, 11259, 8228, 8931, 8228, 11259, 8228 }, - { 11984, 11259, 14913, 11259, 11984, 11259, 14913, 11259 }, - { 8931, 8228, 11259, 8228, 8931, 8228, 11259, 8228 } - }, { - { 8192, 7740, 10486, 7740, 8192, 7740, 10486, 7740 }, - { 7740, 7346, 9777, 7346, 7740, 7346, 9777, 7346 }, - { 10486, 9777, 13159, 9777, 10486, 9777, 13159, 9777 }, - { 7740, 7346, 9777, 7346, 7740, 7346, 9777, 7346 }, - { 8192, 7740, 10486, 7740, 8192, 7740, 10486, 7740 }, - { 7740, 7346, 9777, 7346, 7740, 7346, 9777, 7346 }, - { 10486, 9777, 13159, 9777, 10486, 9777, 13159, 9777 }, - { 7740, 7346, 9777, 7346, 7740, 7346, 9777, 7346 } - }, { - { 7282, 6830, 9118, 6830, 7282, 6830, 9118, 6830 }, - { 6830, 6428, 8640, 6428, 6830, 6428, 8640, 6428 }, - { 9118, 8640, 11570, 8640, 9118, 8640, 11570, 8640 }, - { 6830, 6428, 8640, 6428, 6830, 6428, 8640, 6428 }, - { 7282, 6830, 9118, 6830, 7282, 6830, 9118, 6830 }, - { 6830, 6428, 8640, 6428, 6830, 6428, 8640, 6428 }, - { 9118, 8640, 11570, 8640, 9118, 8640, 11570, 8640 }, - { 6830, 6428, 8640, 6428, 6830, 6428, 8640, 6428 } - } -}; - static const int i_chroma_qp_table[52] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, @@ -200,7 +144,7 @@ static inline void sub_zigzag_4x4( int level[15], const uint8_t *p_src, uint8_t } #undef ZIG -static void quant_8x8( int16_t dct[8][8], int i_qscale, int b_intra ) +static void quant_8x8( int16_t dct[8][8], int quant_mf[6][8][8], int i_qscale, int b_intra ) { const int i_qbits = 16 + i_qscale / 6; const int i_mf = i_qscale % 6; @@ -212,13 +156,13 @@ static void quant_8x8( int16_t dct[8][8], int i_qscale, int b_intra ) for( x = 0; x < 8; x++ ) { if( dct[y][x] > 0 ) - dct[y][x] = ( f + dct[y][x] * quant8_mf[i_mf][y][x] ) >> i_qbits; + dct[y][x] = ( f + dct[y][x] * quant_mf[i_mf][y][x] ) >> i_qbits; else - dct[y][x] = - ( ( f - dct[y][x] * quant8_mf[i_mf][y][x] ) >> i_qbits ); + dct[y][x] = - ( ( f - dct[y][x] * quant_mf[i_mf][y][x] ) >> i_qbits ); } } } -static void quant_4x4( int16_t dct[4][4], int i_qscale, int b_intra ) +static void quant_4x4( int16_t dct[4][4], int quant_mf[6][4][4], int i_qscale, int b_intra ) { const int i_qbits = 15 + i_qscale / 6; const int i_mf = i_qscale % 6; @@ -236,7 +180,7 @@ static void quant_4x4( int16_t dct[4][4], int i_qscale, int b_intra ) } } } -static void quant_4x4_dc( int16_t dct[4][4], int i_qscale ) +static void quant_4x4_dc( int16_t dct[4][4], int quant_mf[6][4][4], int i_qscale ) { const int i_qbits = 15 + i_qscale / 6; const int f2 = ( 2 << i_qbits ) / 3; @@ -254,7 +198,7 @@ static void quant_4x4_dc( int16_t dct[4][4], int i_qscale ) } } } -static void quant_2x2_dc( int16_t dct[2][2], int i_qscale, int b_intra ) +static void quant_2x2_dc( int16_t dct[2][2], int quant_mf[6][4][4], int i_qscale, int b_intra ) { int const i_qbits = 15 + i_qscale / 6; const int f2 = ( 2 << i_qbits ) / ( b_intra ? 3 : 6 ); @@ -433,9 +377,9 @@ void x264_mb_encode_i4x4( x264_t *h, int idx, int i_qscale ) } h->dctf.sub4x4_dct( dct4x4, p_src, i_stride, p_dst, i_stride ); - quant_4x4( dct4x4, i_qscale, 1 ); + quant_4x4( dct4x4, h->quant4_mf[CQM_4IY], i_qscale, 1 ); scan_zigzag_4x4full( h->dct.block[idx].luma4x4, dct4x4 ); - x264_mb_dequant_4x4( dct4x4, i_qscale ); + x264_mb_dequant_4x4( dct4x4, h->dequant4_mf[CQM_4IY], i_qscale ); /* output samples to fdec */ h->dctf.add4x4_idct( p_dst, i_stride, dct4x4 ); @@ -450,9 +394,9 @@ void x264_mb_encode_i8x8( x264_t *h, int idx, int i_qscale ) int16_t dct8x8[8][8]; h->dctf.sub8x8_dct8( dct8x8, p_src, i_stride, p_dst, i_stride ); - quant_8x8( dct8x8, i_qscale, 1 ); + quant_8x8( dct8x8, h->quant8_mf[CQM_8IY], i_qscale, 1 ); scan_zigzag_8x8full( h->dct.luma8x8[idx], dct8x8 ); - x264_mb_dequant_8x8( dct8x8, i_qscale ); + x264_mb_dequant_8x8( dct8x8, h->dequant8_mf[CQM_8IY], i_qscale ); h->dctf.add8x8_idct8( p_dst, i_stride, dct8x8 ); } @@ -486,18 +430,18 @@ static void x264_mb_encode_i16x16( x264_t *h, int i_qscale ) dct4x4[0][block_idx_y[i]][block_idx_x[i]] = dct4x4[1+i][0][0]; /* quant/scan/dequant */ - quant_4x4( dct4x4[1+i], i_qscale, 1 ); + quant_4x4( dct4x4[1+i], h->quant4_mf[CQM_4IY], i_qscale, 1 ); scan_zigzag_4x4( h->dct.block[i].residual_ac, dct4x4[1+i] ); - x264_mb_dequant_4x4( dct4x4[1+i], i_qscale ); + x264_mb_dequant_4x4( dct4x4[1+i], h->dequant4_mf[CQM_4IY], i_qscale ); } h->dctf.dct4x4dc( dct4x4[0] ); - quant_4x4_dc( dct4x4[0], i_qscale ); + quant_4x4_dc( dct4x4[0], h->quant4_mf[CQM_4IY], i_qscale ); scan_zigzag_4x4full( h->dct.luma16x16_dc, dct4x4[0] ); /* output samples to fdec */ h->dctf.idct4x4dc( dct4x4[0] ); - x264_mb_dequant_4x4_dc( dct4x4[0], i_qscale ); /* XXX not inversed */ + x264_mb_dequant_4x4_dc( dct4x4[0], h->dequant4_mf[CQM_4IY], i_qscale ); /* XXX not inversed */ /* calculate dct coeffs */ for( i = 0; i < 16; i++ ) @@ -542,9 +486,9 @@ static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale ) /* copy dc coeff */ dct2x2[block_idx_y[i]][block_idx_x[i]] = dct4x4[i][0][0]; - quant_4x4( dct4x4[i], i_qscale, b_inter ? 0 : 1 ); + quant_4x4( dct4x4[i], h->quant4_mf[CQM_4IC + b_inter], i_qscale, b_inter ? 0 : 1 ); scan_zigzag_4x4( h->dct.block[16+i+ch*4].residual_ac, dct4x4[i] ); - x264_mb_dequant_4x4( dct4x4[i], i_qscale ); + x264_mb_dequant_4x4( dct4x4[i], h->dequant4_mf[CQM_4IC + b_inter], i_qscale ); if( b_inter ) { @@ -553,12 +497,12 @@ static void x264_mb_encode_8x8_chroma( x264_t *h, int b_inter, int i_qscale ) } h->dctf.dct2x2dc( dct2x2 ); - quant_2x2_dc( dct2x2, i_qscale, b_inter ? 0 : 1 ); + quant_2x2_dc( dct2x2, h->quant4_mf[CQM_4IC + b_inter], i_qscale, b_inter ? 0 : 1 ); scan_zigzag_2x2_dc( h->dct.chroma_dc[ch], dct2x2 ); /* output samples to fdec */ h->dctf.idct2x2dc( dct2x2 ); - x264_mb_dequant_2x2_dc( dct2x2, i_qscale ); /* XXX not inversed */ + x264_mb_dequant_2x2_dc( dct2x2, h->dequant4_mf[CQM_4IC + b_inter], i_qscale ); /* XXX not inversed */ if( b_inter && i_decimate_score < 7 ) { @@ -724,9 +668,9 @@ void x264_macroblock_encode( x264_t *h ) { int i_decimate_8x8; - quant_8x8( dct8x8[idx], i_qp, 0 ); + quant_8x8( dct8x8[idx], h->quant8_mf[CQM_8PY], i_qp, 0 ); scan_zigzag_8x8full( h->dct.luma8x8[idx], dct8x8[idx] ); - x264_mb_dequant_8x8( dct8x8[idx], i_qp ); + x264_mb_dequant_8x8( dct8x8[idx], h->dequant8_mf[CQM_8PY], i_qp ); i_decimate_8x8 = x264_mb_decimate_score( h->dct.luma8x8[idx], 64 ); i_decimate_mb += i_decimate_8x8; @@ -759,9 +703,9 @@ void x264_macroblock_encode( x264_t *h ) { idx = i8x8 * 4 + i4x4; - quant_4x4( dct4x4[idx], i_qp, 0 ); + quant_4x4( dct4x4[idx], h->quant4_mf[CQM_4PY], i_qp, 0 ); scan_zigzag_4x4full( h->dct.block[idx].luma4x4, dct4x4[idx] ); - x264_mb_dequant_4x4( dct4x4[idx], i_qp ); + x264_mb_dequant_4x4( dct4x4[idx], h->dequant4_mf[CQM_4PY], i_qp ); i_decimate_8x8 += x264_mb_decimate_score( h->dct.block[idx].luma4x4, 16 ); } @@ -955,7 +899,7 @@ int x264_macroblock_probe_skip( x264_t *h, int b_bidir ) { const int idx = i8x8 * 4 + i4x4; - quant_4x4( dct4x4[idx], i_qp, 0 ); + quant_4x4( dct4x4[idx], (int(*)[4][4])def_quant4_mf, i_qp, 0 ); scan_zigzag_4x4full( dctscan, dct4x4[idx] ); i_decimate_mb += x264_mb_decimate_score( dctscan, 16 ); @@ -992,7 +936,7 @@ int x264_macroblock_probe_skip( x264_t *h, int b_bidir ) dct2x2[1][0] = dct4x4[2][0][0]; dct2x2[1][1] = dct4x4[3][0][0]; h->dctf.dct2x2dc( dct2x2 ); - quant_2x2_dc( dct2x2, i_qp, 0 ); + quant_2x2_dc( dct2x2, (int(*)[4][4])def_quant4_mf, i_qp, 0 ); if( dct2x2[0][0] || dct2x2[0][1] || dct2x2[1][0] || dct2x2[1][1] ) { /* can't be */ @@ -1002,7 +946,7 @@ int x264_macroblock_probe_skip( x264_t *h, int b_bidir ) /* calculate dct coeffs */ for( i4x4 = 0, i_decimate_mb = 0; i4x4 < 4; i4x4++ ) { - quant_4x4( dct4x4[i4x4], i_qp, 0 ); + quant_4x4( dct4x4[i4x4], (int(*)[4][4])def_quant4_mf, i_qp, 0 ); scan_zigzag_4x4( dctscan, dct4x4[i4x4] ); i_decimate_mb += x264_mb_decimate_score( dctscan, 15 ); diff --git a/encoder/set.c b/encoder/set.c index 0471edb7..212bdb01 100644 --- a/encoder/set.c +++ b/encoder/set.c @@ -34,10 +34,37 @@ #include "x264.h" #include "common/common.h" +#include "common/macroblock.h" #ifndef _MSC_VER #include "config.h" #endif +static const uint8_t *const x264_cqm_jvt[6] = +{ + x264_cqm_jvt4i, x264_cqm_jvt4p, + x264_cqm_jvt4i, x264_cqm_jvt4p, + x264_cqm_jvt8i, x264_cqm_jvt8p +}; + +static void scaling_list_write( bs_t *s, x264_pps_t *pps, int idx ) +{ + const int len = idx<4 ? 16 : 64; + const int *zigzag = idx<4 ? x264_zigzag_scan4 : x264_zigzag_scan8; + const uint8_t *list = pps->scaling_list[idx]; + const uint8_t *def_list = (idx==CQM_4IC) ? pps->scaling_list[CQM_4IY] + : (idx==CQM_4PC) ? pps->scaling_list[CQM_4PY] + : x264_cqm_jvt[idx]; + int j; + if( memcmp( list, def_list, len ) ) + { + bs_write( s, 1, 1 ); // scaling_list_present_flag + for( j = 0; j < len; j++ ) + bs_write_se( s, list[zigzag[j]] - (j>0 ? list[zigzag[j-1]] : 8) ); // delta + } + else + bs_write( s, 1, 0 ); // scaling_list_present_flag +} + void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) { sps->i_id = i_id; @@ -45,7 +72,7 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param ) sps->b_qpprime_y_zero_transform_bypass = !param->rc.b_cbr && param->rc.i_qp_constant == 0; if( sps->b_qpprime_y_zero_transform_bypass ) sps->i_profile_idc = PROFILE_HIGH444; - else if( param->analyse.b_transform_8x8 ) + else if( param->analyse.b_transform_8x8 || param->i_cqm_preset != X264_CQM_FLAT ) sps->i_profile_idc = PROFILE_HIGH; else if( param->b_cabac || param->i_bframe > 0 ) sps->i_profile_idc = PROFILE_MAIN; @@ -286,6 +313,8 @@ void x264_sps_write( bs_t *s, x264_sps_t *sps ) void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *sps ) { + int i, j; + pps->i_id = i_id; pps->i_sps_id = sps->i_id; pps->b_cabac = param->b_cabac; @@ -296,8 +325,6 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t * #if 0 if( pps->i_num_slice_groups > 1 ) { - int i; - pps->i_slice_group_map_type = 0; if( pps->i_slice_group_map_type == 0 ) { @@ -345,6 +372,31 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t * pps->b_redundant_pic_cnt = 0; pps->b_transform_8x8_mode = param->analyse.b_transform_8x8 ? 1 : 0; + + pps->i_cqm_preset = param->i_cqm_preset; + switch( pps->i_cqm_preset ) + { + case X264_CQM_FLAT: + for( i = 0; i < 6; i++ ) + pps->scaling_list[i] = x264_cqm_flat16; + break; + case X264_CQM_JVT: + for( i = 0; i < 6; i++ ) + pps->scaling_list[i] = x264_cqm_jvt[i]; + break; + case X264_CQM_CUSTOM: + pps->scaling_list[CQM_4IY] = param->cqm_4iy; + pps->scaling_list[CQM_4IC] = param->cqm_4ic; + pps->scaling_list[CQM_4PY] = param->cqm_4py; + pps->scaling_list[CQM_4PC] = param->cqm_4pc; + pps->scaling_list[CQM_8IY+4] = param->cqm_8iy; + pps->scaling_list[CQM_8PY+4] = param->cqm_8py; + for( i = 0; i < 6; i++ ) + for( j = 0; j < (i<4?16:64); j++ ) + if( pps->scaling_list[i][j] == 0 ) + pps->scaling_list[i] = x264_cqm_jvt[i]; + break; + } } void x264_pps_write( bs_t *s, x264_pps_t *pps ) @@ -410,11 +462,25 @@ void x264_pps_write( bs_t *s, x264_pps_t *pps ) bs_write( s, 1, pps->b_constrained_intra_pred ); bs_write( s, 1, pps->b_redundant_pic_cnt ); - if( pps->b_transform_8x8_mode ) + if( pps->b_transform_8x8_mode || pps->i_cqm_preset != X264_CQM_FLAT ) { bs_write( s, 1, pps->b_transform_8x8_mode ); - bs_write( s, 1, 0 ); // pic_scaling_matrix_present_flag - bs_write_se( s, 0 ); // second_chroma_qp_index_offset + bs_write( s, 1, (pps->i_cqm_preset != X264_CQM_FLAT) ); + if( pps->i_cqm_preset != X264_CQM_FLAT ) + { + scaling_list_write( s, pps, CQM_4IY ); + scaling_list_write( s, pps, CQM_4IC ); + bs_write( s, 1, 0 ); // Cr = Cb + scaling_list_write( s, pps, CQM_4PY ); + scaling_list_write( s, pps, CQM_4PC ); + bs_write( s, 1, 0 ); // Cr = Cb + if( pps->b_transform_8x8_mode ) + { + scaling_list_write( s, pps, CQM_8IY+4 ); + scaling_list_write( s, pps, CQM_8PY+4 ); + } + } + bs_write_se( s, pps->i_chroma_qp_index_offset ); } bs_rbsp_trailing( s ); diff --git a/x264.c b/x264.c index 2d261868..f81eb188 100644 --- a/x264.c +++ b/x264.c @@ -232,6 +232,17 @@ static void Help( x264_param_t *defaults ) " --no-chroma-me Ignore chroma in motion estimation\n" " -8, --8x8dct Adaptive spatial transform size\n" "\n" + " --cqm Preset quant matrices [\"flat\"]\n" + " - jvt, flat\n" + " --cqm4 Set all 4x4 quant matrices\n" + " Takes a comma-separated list of 16 integers.\n" + " --cqm8 Set all 8x8 quant matrices\n" + " Takes a comma-separated list of 64 integers.\n" + " --cqm4i, --cqm4p, --cqm8i, --cqm8p\n" + " Set both luma and chroma quant matrices\n" + " --cqm4iy, --cqm4ic, --cqm4py, --cqm4pc\n" + " Set individual quant matrices\n" + "\n" "Input/Output:\n" "\n" " --level Specify level (as defined by Annex A)\n" @@ -294,6 +305,18 @@ static void Help( x264_param_t *defaults ) ); } +static int parse_cqm( const char *str, uint8_t *cqm, int length ) +{ + int i = 0; + do { + int coef; + if( !sscanf( str, "%d", &coef ) || coef < 1 || coef > 255 ) + return -1; + cqm[i++] = coef; + } while( i < length && (str = strchr( str, ',' )) && str++ ); + return (i == length) ? 0 : -1; +} + /***************************************************************************** * Parse: *****************************************************************************/ @@ -324,6 +347,7 @@ static int Parse( int argc, char **argv, opterr = 0; // no error message for( ;; ) { + int b_error = 0; int long_options_index; #define OPT_QPMIN 256 #define OPT_QPMAX 257 @@ -360,6 +384,17 @@ static int Parse( int argc, char **argv, #define OPT_SEEK 291 #define OPT_ZONES 292 #define OPT_THREADS 293 +#define OPT_CQM 294 +#define OPT_CQM4 295 +#define OPT_CQM4I 296 +#define OPT_CQM4IY 297 +#define OPT_CQM4IC 298 +#define OPT_CQM4P 299 +#define OPT_CQM4PY 300 +#define OPT_CQM4PC 301 +#define OPT_CQM8 302 +#define OPT_CQM8I 303 +#define OPT_CQM8P 304 static struct option long_options[] = { @@ -416,6 +451,17 @@ static int Parse( int argc, char **argv, { "progress",no_argument, NULL, OPT_PROGRESS }, { "visualize",no_argument, NULL, OPT_VISUALIZE }, { "aud", no_argument, NULL, OPT_AUD }, + { "cqm", required_argument, NULL, OPT_CQM }, + { "cqm4", required_argument, NULL, OPT_CQM4 }, + { "cqm4i", required_argument, NULL, OPT_CQM4I }, + { "cqm4iy", required_argument, NULL, OPT_CQM4IY }, + { "cqm4ic", required_argument, NULL, OPT_CQM4IC }, + { "cqm4p", required_argument, NULL, OPT_CQM4P }, + { "cqm4py", required_argument, NULL, OPT_CQM4PY }, + { "cqm4pc", required_argument, NULL, OPT_CQM4PC }, + { "cqm8", required_argument, NULL, OPT_CQM8 }, + { "cqm8i", required_argument, NULL, OPT_CQM8I }, + { "cqm8p", required_argument, NULL, OPT_CQM8P }, {0, 0, 0, 0} }; @@ -680,10 +726,73 @@ static int Parse( int argc, char **argv, fprintf( stderr, "not compiled with visualization support\n" ); #endif break; + case OPT_CQM: + if( strstr( optarg, "flat" ) ) + param->i_cqm_preset = X264_CQM_FLAT; + else if( strstr( optarg, "jvt" ) ) + param->i_cqm_preset = X264_CQM_JVT; + else + { + fprintf( stderr, "bad CQM preset `%s'\n", optarg ); + return -1; + } + break; + case OPT_CQM4: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4iy, 16 ); + b_error |= parse_cqm( optarg, param->cqm_4ic, 16 ); + b_error |= parse_cqm( optarg, param->cqm_4py, 16 ); + b_error |= parse_cqm( optarg, param->cqm_4pc, 16 ); + break; + case OPT_CQM8: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_8iy, 64 ); + b_error |= parse_cqm( optarg, param->cqm_8py, 64 ); + break; + case OPT_CQM4I: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4iy, 16 ); + b_error |= parse_cqm( optarg, param->cqm_4ic, 16 ); + break; + case OPT_CQM4P: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4py, 16 ); + b_error |= parse_cqm( optarg, param->cqm_4pc, 16 ); + break; + case OPT_CQM4IY: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4iy, 16 ); + break; + case OPT_CQM4IC: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4ic, 16 ); + break; + case OPT_CQM4PY: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4iy, 16 ); + break; + case OPT_CQM4PC: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_4ic, 16 ); + break; + case OPT_CQM8I: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_8iy, 64 ); + break; + case OPT_CQM8P: + param->i_cqm_preset = X264_CQM_CUSTOM; + b_error |= parse_cqm( optarg, param->cqm_8py, 64 ); + break; default: fprintf( stderr, "unknown option (%c)\n", optopt ); return -1; } + + if( b_error ) + { + fprintf( stderr, "bad argument (%s)\n", optarg ); + return -1; + } } /* Get the file name */ diff --git a/x264.h b/x264.h index bde985c5..e3eedf3b 100644 --- a/x264.h +++ b/x264.h @@ -59,6 +59,9 @@ typedef struct x264_t x264_t; #define X264_ME_HEX 1 #define X264_ME_UMH 2 #define X264_ME_ESA 3 +#define X264_CQM_FLAT 0 +#define X264_CQM_JVT 1 +#define X264_CQM_CUSTOM 2 /* Colorspace type */ @@ -140,6 +143,13 @@ typedef struct int b_cabac; int i_cabac_init_idc; + int i_cqm_preset; + int8_t cqm_4iy[16]; /* used only if i_cqm_preset == X264_CQM_CUSTOM */ + int8_t cqm_4ic[16]; + int8_t cqm_4py[16]; + int8_t cqm_4pc[16]; + int8_t cqm_8iy[64]; + int8_t cqm_8py[64]; /* Log */ void (*pf_log)( void *, int i_level, const char *psz, va_list ); -- 2.39.2