1
2 #ifdef HAVE_CONFIG_H
3 #include "config.h"
4 #endif
5 #include <schroedinger/schro.h>
6 #include <string.h>
7 #include <math.h>
8
9
10 static void schro_motion_global_metric (SchroMotionField * field,
11 SchroFrame * frame, SchroFrame * ref_frame, int ref);
12 static void schro_motion_field_global_estimation (SchroMotionField * mf,
13 SchroGlobalMotion * gm, int mv_precision, int ref, SchroParams * params);
14
15 void
schro_encoder_global_estimation(SchroEncoderFrame * frame)16 schro_encoder_global_estimation (SchroEncoderFrame * frame)
17 {
18 SchroParams *params = &frame->params;
19 SchroMotionField *mf, *mf_orig;
20 int i;
21
22 SCHRO_ERROR ("global motion is broken");
23
24 for (i = 0; i < params->num_refs; i++) {
25 mf_orig = frame->rme[i]->motion_fields[1];
26 mf = schro_motion_field_new (mf_orig->x_num_blocks, mf_orig->y_num_blocks);
27
28 SCHRO_DEBUG ("ref %d", i);
29 memcpy (mf->motion_vectors, mf_orig->motion_vectors,
30 sizeof (SchroMotionVector) * mf->x_num_blocks * mf->y_num_blocks);
31 schro_motion_field_global_estimation (mf,
32 &frame->params.global_motion[i], params->mv_precision, i, params);
33 schro_motion_global_metric (mf, frame->filtered_frame,
34 frame->ref_frame[i]->filtered_frame, i);
35 }
36 }
37
38 static void
schro_motion_global_metric(SchroMotionField * field,SchroFrame * frame,SchroFrame * ref_frame,int ref)39 schro_motion_global_metric (SchroMotionField * field, SchroFrame * frame,
40 SchroFrame * ref_frame, int ref)
41 {
42 SchroMotionVector *mv;
43 int i;
44 int j;
45
46 for (j = 0; j < field->y_num_blocks; j++) {
47 for (i = 0; i < field->x_num_blocks; i++) {
48 mv = field->motion_vectors + j * field->x_num_blocks + i;
49
50 #if 0
51 x = i * 8 + mv->u.vec.dx[ref];
52 y = j * 8 + mv->u.vec.dy[ref];
53 mv->metric =
54 schro_metric_absdiff_u8 (frame->components[0].data + x +
55 y * frame->components[0].stride, frame->components[0].stride,
56 ref->components[0].data + i * 8 + j * 8 * ref->components[0].stride,
57 ref->components[0].stride, 8, 8);
58 #endif
59 mv->metric = 0;
60 }
61 }
62 }
63
64 void
schro_motion_field_global_estimation(SchroMotionField * mf,SchroGlobalMotion * gm,int mv_precision,int ref,SchroParams * params)65 schro_motion_field_global_estimation (SchroMotionField * mf,
66 SchroGlobalMotion * gm, int mv_precision, int ref, SchroParams * params)
67 {
68 int i;
69 int j;
70 int k;
71 SchroMotionVector *mv;
72 int xbsep = 2 * params->xbsep_luma;
73 int ybsep = 2 * params->ybsep_luma;
74 double a00, a01, a10, a11;
75 double pan_x, pan_y;
76
77 for (j = 0; j < mf->y_num_blocks; j++) {
78 for (i = 0; i < mf->x_num_blocks; i++) {
79 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
80
81 mv->using_global = 1;
82
83 /* HACK */
84 if (j >= mf->y_num_blocks - 4 || i >= mf->x_num_blocks - 4) {
85 mv->using_global = 0;
86 }
87 if (j < 4 || i < 4) {
88 mv->using_global = 0;
89 }
90 }
91 }
92
93 for (k = 0; k < 4; k++) {
94 double m_x, m_y;
95 double m_f, m_g;
96 double ave_x, ave_y;
97 double m_fx, m_fy, m_gx, m_gy;
98 double m_xx, m_yy;
99 double sum2;
100 double stddev2;
101 int n = 0;
102
103 SCHRO_DEBUG ("step %d", k);
104 m_x = 0;
105 m_y = 0;
106 m_f = 0;
107 m_g = 0;
108 for (j = 0; j < mf->y_num_blocks; j++) {
109 for (i = 0; i < mf->x_num_blocks; i++) {
110 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
111 if (mv->using_global) {
112 m_f += mv->u.vec.dx[ref];
113 m_g += mv->u.vec.dy[ref];
114 m_x += i * xbsep;
115 m_y += j * ybsep;
116 n++;
117 }
118 }
119 }
120 pan_x = m_f / n;
121 pan_y = m_g / n;
122 ave_x = m_x / n;
123 ave_y = m_y / n;
124
125 SCHRO_DEBUG ("pan %f %f ave %f %f n %d", pan_x, pan_y, ave_x, ave_y, n);
126
127 m_fx = 0;
128 m_fy = 0;
129 m_gx = 0;
130 m_gy = 0;
131 m_xx = 0;
132 m_yy = 0;
133 n = 0;
134 for (j = 0; j < mf->y_num_blocks; j++) {
135 for (i = 0; i < mf->x_num_blocks; i++) {
136 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
137 if (mv->using_global) {
138 m_fx += (mv->u.vec.dx[ref] - pan_x) * (i * xbsep - ave_x);
139 m_fy += (mv->u.vec.dx[ref] - pan_x) * (j * ybsep - ave_y);
140 m_gx += (mv->u.vec.dy[ref] - pan_y) * (i * xbsep - ave_x);
141 m_gy += (mv->u.vec.dy[ref] - pan_y) * (j * ybsep - ave_y);
142 m_xx += (i * xbsep - ave_x) * (i * xbsep - ave_x);
143 m_yy += (j * ybsep - ave_y) * (j * ybsep - ave_y);
144 n++;
145 }
146 }
147 }
148 SCHRO_DEBUG ("m_fx %f m_gx %f m_xx %f n %d", m_fx, m_gx, m_xx, n);
149 a00 = m_fx / m_xx;
150 a01 = m_fy / m_yy;
151 a10 = m_gx / m_xx;
152 a11 = m_gy / m_yy;
153
154 pan_x -= a00 * ave_x + a01 * ave_y;
155 pan_y -= a10 * ave_x + a11 * ave_y;
156
157 SCHRO_DEBUG ("pan %f %f a[] %f %f %f %f", pan_x, pan_y, a00, a01, a10, a11);
158
159 sum2 = 0;
160 for (j = 0; j < mf->y_num_blocks; j++) {
161 for (i = 0; i < mf->x_num_blocks; i++) {
162 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
163 if (mv->using_global) {
164 double dx, dy;
165 dx = mv->u.vec.dx[ref] - (pan_x + a00 * i + a01 * j);
166 dy = mv->u.vec.dy[ref] - (pan_y + a10 * i + a11 * j);
167 sum2 += dx * dx + dy * dy;
168 }
169 }
170 }
171
172 stddev2 = sum2 / n;
173 SCHRO_DEBUG ("stddev %f", sqrt (sum2 / n));
174
175 if (stddev2 < 1)
176 stddev2 = 1;
177
178 n = 0;
179 for (j = 0; j < mf->y_num_blocks; j++) {
180 for (i = 0; i < mf->x_num_blocks; i++) {
181 double dx, dy;
182 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
183 dx = mv->u.vec.dx[ref] - (pan_x + a00 * i + a01 * j);
184 dy = mv->u.vec.dy[ref] - (pan_y + a10 * i + a11 * j);
185 mv->using_global = (dx * dx + dy * dy < stddev2 * 16);
186 n += mv->using_global;
187 }
188 }
189 SCHRO_DEBUG ("using n = %d", n);
190 }
191
192 SCHRO_DEBUG ("pan %f %f a[] %f %f %f %f", pan_x, pan_y, a00, a01, a10, a11);
193
194 pan_x *= 4.0;
195 pan_y *= 4.0;
196 a00 *= 8;
197 a01 *= 8;
198 a10 *= 8;
199 a11 *= 8;
200
201 gm->b0 = rint (pan_x * (1 << mv_precision));
202 gm->b1 = rint (pan_y * (1 << mv_precision));
203 gm->a_exp = 16;
204 gm->a00 = rint (a00 * (1 << (gm->a_exp + mv_precision)));
205 gm->a01 = rint (a01 * (1 << (gm->a_exp + mv_precision)));
206 gm->a10 = rint (a10 * (1 << (gm->a_exp + mv_precision)));
207 gm->a11 = rint (a11 * (1 << (gm->a_exp + mv_precision)));
208
209 for (j = 0; j < mf->y_num_blocks; j++) {
210 for (i = 0; i < mf->x_num_blocks; i++) {
211 mv = mf->motion_vectors + j * mf->x_num_blocks + i;
212 mv->using_global = 1;
213 //mv->u.vec.dx[ref] = gm->b0 + ((gm->a00 * (i*8) + gm->a01 * (j*8))>>gm->a_exp) - i*8;
214 //mv->u.vec.dy[ref] = gm->b1 + ((gm->a10 * (i*8) + gm->a11 * (j*8))>>gm->a_exp) - j*8;
215 mv->u.vec.dx[ref] = 0;
216 mv->u.vec.dy[ref] = 0;
217 }
218 }
219 }
220
221 void
schro_motionest_superblock_global(SchroMotionEst * me,int ref,SchroBlock * block,int i,int j)222 schro_motionest_superblock_global (SchroMotionEst * me, int ref,
223 SchroBlock * block, int i, int j)
224 {
225 SchroMotionVector *mv;
226
227 mv = &block->mv[0][0];
228 mv->split = 0;
229 mv->pred_mode = 1 << ref;
230 mv->using_global = 1;
231 mv->u.vec.dx[ref] = 0;
232 mv->u.vec.dy[ref] = 0;
233 //block->error = schro_motionest_superblock_get_metric (me, block, i, j);
234 block->error = (ref == 1) ? -1000 : 1000;
235 block->entropy = 0;
236 schro_block_fixup (block);
237
238 //block->valid = (block->error != SCHRO_METRIC_INVALID_2);
239 block->valid = TRUE;
240 }
241