Copy from Berkano Overlay
[otih-overlay.git] / media-libs / x264 / files / x264_psy_rdo.r889.diff
blob6f36ed562c26b14a7e535b799c1619c0780043ff
1 diff --git a/common/common.c b/common/common.c
2 index 8a8f660..7e091bc 100644
3 --- a/common/common.c
4 +++ b/common/common.c
5 @@ -117,6 +117,7 @@ void x264_param_default( x264_param_t *param )
6 | X264_ANALYSE_PSUB16x16 | X264_ANALYSE_BSUB16x16;
7 param->analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
8 param->analyse.i_me_method = X264_ME_HEX;
9 + param->analyse.i_rdcmp = X264_CMP_PSY;
10 param->analyse.i_me_range = 16;
11 param->analyse.i_subpel_refine = 5;
12 param->analyse.b_chroma_me = 1;
13 @@ -464,6 +465,8 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
14 p->analyse.i_mv_range_thread = atoi(value);
15 OPT2("subme", "subq")
16 p->analyse.i_subpel_refine = atoi(value);
17 + OPT("rdcmp")
18 + b_error |= parse_enum( value, x264_rdcmp_names, &p->analyse.i_rdcmp );
19 OPT("bime")
20 p->analyse.b_bidir_me = atobool(value);
21 OPT("chroma-me")
22 @@ -856,6 +859,7 @@ char *x264_param2string( x264_param_t *p, int b_res )
23 s += sprintf( s, " analyse=%#x:%#x", p->analyse.intra, p->analyse.inter );
24 s += sprintf( s, " me=%s", x264_motion_est_names[ p->analyse.i_me_method ] );
25 s += sprintf( s, " subme=%d", p->analyse.i_subpel_refine );
26 + s += sprintf( s, " rdcmp=%s", x264_rdcmp_names[ p->analyse.i_rdcmp ] );
27 s += sprintf( s, " brdo=%d", p->analyse.b_bframe_rdo );
28 s += sprintf( s, " mixed_ref=%d", p->analyse.b_mixed_references );
29 s += sprintf( s, " me_range=%d", p->analyse.i_me_range );
30 diff --git a/encoder/analyse.c b/encoder/analyse.c
31 index 9200ace..f0b5409 100644
32 --- a/encoder/analyse.c
33 +++ b/encoder/analyse.c
34 @@ -1911,7 +1911,7 @@ static void x264_mb_analyse_p_rd( x264_t *h, x264_mb_analysis_t *a, int i_satd )
36 static void x264_mb_analyse_b_rd( x264_t *h, x264_mb_analysis_t *a, int i_satd_inter )
38 - int thresh = i_satd_inter * 17/16;
39 + int thresh = i_satd_inter * (17 + (h->param.analyse.i_rdcmp == X264_CMP_PSY))/16;
41 if( a->b_direct_available && a->i_rd16x16direct == COST_MAX )
43 diff --git a/encoder/rdo.c b/encoder/rdo.c
44 index 8223efd..55629ff 100644
45 --- a/encoder/rdo.c
46 +++ b/encoder/rdo.c
47 @@ -52,21 +52,54 @@ static uint16_t cabac_prefix_size[15][128];
49 #define COPY_CABAC h->mc.memcpy_aligned( &cabac_tmp.f8_bits_encoded, &h->cabac.f8_bits_encoded, \
50 sizeof(x264_cabac_t) - offsetof(x264_cabac_t,f8_bits_encoded) )
52 -static int ssd_mb( x264_t *h )
54 +#define ADD_ABS_SATD(satdtype, pixel)\
55 + satd += abs((h->pixf.satdtype[pixel]( zero, 0, fdec, FDEC_STRIDE ) - dc_coefs[0]) - \
56 + (h->pixf.satdtype[pixel]( zero, 0, fenc, FENC_STRIDE ) - dc_coefs[1]));
58 +/* Psy RD distortion metric: SSD plus "Absolute Difference of Complexities" */
59 +/* SATD and SA8D are used to measure block complexity. */
60 +/* Blocks with a complexity most similar to that of the source are scored best. */
61 +/* The difference between SATD and SA8D scores are both used to avoid bias from the DCT size. Using SATD */
62 +/* only, for example, results in overusage of 8x8dct, while the opposite occurs when using SA8D. */
63 +/* This is because frequencies stored in an 8x8dct sum up to a larger value when viewed through a 4x4 */
64 +/* transform and vice versa with a 4x4dct and an 8x8 transform. */
65 +/* The weights chosen (5 for each) are arbitrary. They should probably be the same for SATD and SA8D but */
66 +/* the overall weight is chosen for no particularly good reason. */
67 +/* SSD is still used as the primary RD metric; this value is merely added to it for psy purposes. */
69 +/* FIXME: Is there a better metric than averaged SATD/SA8D difference for complexity difference? */
70 +/* Hadamard transform is recursive, so a SATD+SA8D can be done faster by taking advantage of this fact. */
71 +/* We can factor out the fenc SATD/SA8D so they're only done once. */
73 +static inline int ssd_plane( x264_t *h, int size, int p, int x, int y )
75 - return h->pixf.ssd[PIXEL_16x16]( h->mb.pic.p_fenc[0], FENC_STRIDE,
76 - h->mb.pic.p_fdec[0], FDEC_STRIDE )
77 - + h->pixf.ssd[PIXEL_8x8]( h->mb.pic.p_fenc[1], FENC_STRIDE,
78 - h->mb.pic.p_fdec[1], FDEC_STRIDE )
79 - + h->pixf.ssd[PIXEL_8x8]( h->mb.pic.p_fenc[2], FENC_STRIDE,
80 - h->mb.pic.p_fdec[2], FDEC_STRIDE );
81 + DECLARE_ALIGNED_16(uint8_t zero[16]) = {0};
82 + int satd = 0;
83 + uint8_t *fdec = h->mb.pic.p_fdec[p] + x + y*FDEC_STRIDE;
84 + uint8_t *fenc = h->mb.pic.p_fenc[p] + x + y*FENC_STRIDE;
85 + if(p == 0 && h->param.analyse.i_rdcmp == X264_CMP_PSY)
86 + {
87 + int dc_coefs[2];
88 + dc_coefs[0] = h->pixf.sad[size]( zero, 0, fdec, FDEC_STRIDE ) >> 1;
89 + dc_coefs[1] = h->pixf.sad[size]( zero, 0, fenc, FENC_STRIDE ) >> 1;
90 + ADD_ABS_SATD(satd, size);
91 + /* If the plane is smaller than 8x8, we can't do an SA8D; this probably isn't a big problem. */
92 + if(size <= PIXEL_8x8)
93 + {
94 + dc_coefs[0] >>= 1;
95 + dc_coefs[1] >>= 1;
96 + ADD_ABS_SATD(sa8d, size);
97 + }
98 + else
99 + satd *= 2;
101 + return h->pixf.ssd[size]( fenc, FENC_STRIDE, fdec, FDEC_STRIDE ) + satd * 5;
104 -static int ssd_plane( x264_t *h, int size, int p, int x, int y )
105 +static inline int ssd_mb( x264_t *h )
107 - return h->pixf.ssd[size]( h->mb.pic.p_fenc[p] + x+y*FENC_STRIDE, FENC_STRIDE,
108 - h->mb.pic.p_fdec[p] + x+y*FDEC_STRIDE, FDEC_STRIDE );
109 + return ssd_plane(h, PIXEL_16x16, 0, 0, 0) + ssd_plane(h, PIXEL_8x8, 1, 0, 0) + ssd_plane(h, PIXEL_8x8, 2, 0, 0);
112 static int x264_rd_cost_mb( x264_t *h, int i_lambda2 )
113 diff --git a/x264.c b/x264.c
114 index d78461f..46b74b9 100644
115 --- a/x264.c
116 +++ b/x264.c
117 @@ -243,6 +243,10 @@ static void Help( x264_param_t *defaults, int b_longhelp )
118 H0( " -m, --subme <integer> Subpixel motion estimation and partition\n"
119 " decision quality: 1=fast, 7=best. [%d]\n", defaults->analyse.i_subpel_refine );
120 H0( " --b-rdo RD based mode decision for B-frames. Requires subme 6.\n" );
121 + H0( " --rdcmp Metric used for RD mode decision [\"%s\"]\n",
122 + strtable_lookup( x264_rdcmp_names, defaults->analyse.i_rdcmp ) );
123 + H0( " - ssd: normal (maximum PSNR)\n"
124 + " - psy: psychovisual (sharper)\n" );
125 H0( " --mixed-refs Decide references on a per partition basis\n" );
126 H1( " --no-chroma-me Ignore chroma in motion estimation\n" );
127 H1( " --bime Jointly optimize both MVs in B-frames\n" );
128 @@ -411,6 +415,7 @@ static int Parse( int argc, char **argv,
129 { "mvrange", required_argument, NULL, 0 },
130 { "mvrange-thread", required_argument, NULL, 0 },
131 { "subme", required_argument, NULL, 'm' },
132 + { "rdcmp", required_argument, NULL, 0 },
133 { "b-rdo", no_argument, NULL, 0 },
134 { "mixed-refs", no_argument, NULL, 0 },
135 { "no-chroma-me", no_argument, NULL, 0 },
136 diff --git a/x264.h b/x264.h
137 index 0e257a1..432f364 100644
138 --- a/x264.h
139 +++ b/x264.h
140 @@ -86,9 +86,12 @@ typedef struct x264_t x264_t;
141 #define X264_AQ_NONE 0
142 #define X264_AQ_LOCAL 1
143 #define X264_AQ_GLOBAL 2
144 +#define X264_CMP_SSD 0
145 +#define X264_CMP_PSY 1
147 static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
148 static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
149 +static const char * const x264_rdcmp_names[] = { "ssd", "psy", 0 };
150 static const char * const x264_overscan_names[] = { "undef", "show", "crop", 0 };
151 static const char * const x264_vidformat_names[] = { "component", "pal", "ntsc", "secam", "mac", "undef", 0 };
152 static const char * const x264_fullrange_names[] = { "off", "on", 0 };
153 @@ -238,6 +241,7 @@ typedef struct x264_param_t
154 int b_fast_pskip; /* early SKIP detection on P-frames */
155 int b_dct_decimate; /* transform coefficient thresholding on P-frames */
156 int i_noise_reduction; /* adaptive pseudo-deadzone */
157 + int i_rdcmp; /* RD comparison metric */
159 /* the deadzone size that will be used in luma quantization */
160 int i_luma_deadzone[2]; /* {inter, intra} */