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