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
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;
}
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;
/****************************************************************************
* 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 )
{
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);
}
}
}
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 );
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
--- /dev/null
+/*****************************************************************************
+ * set.c: h264 encoder library
+ *****************************************************************************
+ * Copyright (C) 2005 x264 project
+ *
+ * Authors: Loren Merritt <lorenm@u.washington.edu>
+ *
+ * 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];
+ }
+ }
+}
+
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;
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
{
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;
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;
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;
{ 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 } },
{ 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,
}
#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;
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;
}
}
}
-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;
}
}
}
-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 );
}
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 );
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 );
}
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++ )
/* 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 )
{
}
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 )
{
{
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;
{
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 );
}
{
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 );
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 */
/* 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 );
#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;
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;
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;
#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 )
{
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 )
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 );
" --no-chroma-me Ignore chroma in motion estimation\n"
" -8, --8x8dct Adaptive spatial transform size\n"
"\n"
+ " --cqm <string> Preset quant matrices [\"flat\"]\n"
+ " - jvt, flat\n"
+ " --cqm4 <list> Set all 4x4 quant matrices\n"
+ " Takes a comma-separated list of 16 integers.\n"
+ " --cqm8 <list> 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 <integer> Specify level (as defined by Annex A)\n"
);
}
+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:
*****************************************************************************/
opterr = 0; // no error message
for( ;; )
{
+ int b_error = 0;
int long_options_index;
#define OPT_QPMIN 256
#define OPT_QPMAX 257
#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[] =
{
{ "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}
};
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 */
#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
*/
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 );