Mercurial > libavcodec.hg
annotate motion_est_template.c @ 2497:69adfbbdcdeb libavcodec
- samples from mplayer ftp in the "adv" profile seem to have profile=2,
which isn't the advanced one; and indeed, using adv. profile parser fails.
Using normal parser works, and that's what is done
- attempt at taking care of stride for NORM2 bitplane decoding
- duplication of much code from msmpeg4.c; this code isn't yet used, but
goes down as far as the block layer (mainly Transform Type stuff, the
remains are wild editing without checking). Unusable yet, and lacks the AC
decoding (but a step further in bitstream parsing)
patch by anonymous
author | michael |
---|---|
date | Fri, 04 Feb 2005 02:20:38 +0000 |
parents | 5e5cf598a48b |
children | e25782262d7d |
rev | line source |
---|---|
936 | 1 /* |
2 * Motion estimation | |
1739
07a484280a82
copyright year update of the files i touched and remembered, things look annoyingly unmaintained otherwise
michael
parents:
1708
diff
changeset
|
3 * Copyright (c) 2002-2004 Michael Niedermayer |
936 | 4 * |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 * | |
19 */ | |
1106 | 20 |
21 /** | |
22 * @file motion_est_template.c | |
23 * Motion estimation template. | |
24 */ | |
1950 | 25 |
936 | 26 //lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...) |
1708 | 27 #define LOAD_COMMON\ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
28 uint32_t * const score_map= c->score_map;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
29 const int xmin= c->xmin;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
30 const int ymin= c->ymin;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
31 const int xmax= c->xmax;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
32 const int ymax= c->ymax;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
33 uint8_t *mv_penalty= c->current_mv_penalty;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
34 const int pred_x= c->pred_x;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
35 const int pred_y= c->pred_y;\ |
936 | 36 |
37 #define CHECK_HALF_MV(dx, dy, x, y)\ | |
38 {\ | |
39 const int hx= 2*(x)+(dx);\ | |
40 const int hy= 2*(y)+(dy);\ | |
1950 | 41 d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\ |
936 | 42 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ |
43 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ | |
44 } | |
45 | |
46 #if 0 | |
1950 | 47 static int hpel_motion_search)(MpegEncContext * s, |
936 | 48 int *mx_ptr, int *my_ptr, int dmin, |
1950 | 49 uint8_t *ref_data[3], |
50 int size) | |
936 | 51 { |
52 const int xx = 16 * s->mb_x + 8*(n&1); | |
53 const int yy = 16 * s->mb_y + 8*(n>>1); | |
54 const int mx = *mx_ptr; | |
55 const int my = *my_ptr; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
56 const int penalty_factor= c->sub_penalty_factor; |
936 | 57 |
1708 | 58 LOAD_COMMON |
936 | 59 |
60 // INIT; | |
61 //FIXME factorize | |
62 me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub; | |
63 | |
64 if(s->no_rounding /*FIXME b_type*/){ | |
65 hpel_put= &s->dsp.put_no_rnd_pixels_tab[size]; | |
66 chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1]; | |
67 }else{ | |
68 hpel_put=& s->dsp.put_pixels_tab[size]; | |
69 chroma_hpel_put= &s->dsp.put_pixels_tab[size+1]; | |
70 } | |
1950 | 71 cmpf= s->dsp.me_cmp[size]; |
72 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 73 cmp_sub= s->dsp.me_sub_cmp[size]; |
74 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
75 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
76 if(c->skip){ //FIXME somehow move up (benchmark) |
936 | 77 *mx_ptr = 0; |
78 *my_ptr = 0; | |
79 return dmin; | |
80 } | |
81 | |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
82 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
936 | 83 CMP_HPEL(dmin, 0, 0, mx, my, size); |
84 if(mx || my) | |
85 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; | |
86 } | |
87 | |
88 if (mx > xmin && mx < xmax && | |
89 my > ymin && my < ymax) { | |
90 int bx=2*mx, by=2*my; | |
91 int d= dmin; | |
92 | |
93 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
94 CHECK_HALF_MV(0, 1, mx , my-1) | |
95 CHECK_HALF_MV(1, 1, mx , my-1) | |
96 CHECK_HALF_MV(1, 0, mx-1, my ) | |
97 CHECK_HALF_MV(1, 0, mx , my ) | |
98 CHECK_HALF_MV(1, 1, mx-1, my ) | |
99 CHECK_HALF_MV(0, 1, mx , my ) | |
100 CHECK_HALF_MV(1, 1, mx , my ) | |
101 | |
948 | 102 assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2); |
936 | 103 |
104 *mx_ptr = bx; | |
105 *my_ptr = by; | |
106 }else{ | |
107 *mx_ptr =2*mx; | |
108 *my_ptr =2*my; | |
109 } | |
110 | |
111 return dmin; | |
112 } | |
113 | |
114 #else | |
1950 | 115 static int hpel_motion_search(MpegEncContext * s, |
936 | 116 int *mx_ptr, int *my_ptr, int dmin, |
1950 | 117 int src_index, int ref_index, |
118 int size, int h) | |
936 | 119 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
120 MotionEstContext * const c= &s->me; |
936 | 121 const int mx = *mx_ptr; |
122 const int my = *my_ptr; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
123 const int penalty_factor= c->sub_penalty_factor; |
936 | 124 me_cmp_func cmp_sub, chroma_cmp_sub; |
1013 | 125 int bx=2*mx, by=2*my; |
936 | 126 |
1708 | 127 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
128 int flags= c->sub_flags; |
936 | 129 |
130 //FIXME factorize | |
131 | |
132 cmp_sub= s->dsp.me_sub_cmp[size]; | |
133 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
134 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
135 if(c->skip){ //FIXME move out of hpel? |
936 | 136 *mx_ptr = 0; |
137 *my_ptr = 0; | |
138 return dmin; | |
139 } | |
140 | |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
141 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
1950 | 142 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); |
1011 | 143 if(mx || my || size>0) |
936 | 144 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; |
145 } | |
146 | |
147 if (mx > xmin && mx < xmax && | |
148 my > ymin && my < ymax) { | |
149 int d= dmin; | |
150 const int index= (my<<ME_MAP_SHIFT) + mx; | |
151 const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
152 + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor; |
936 | 153 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)] |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
154 + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; |
936 | 155 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)] |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
156 + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; |
936 | 157 const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
158 + (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor; |
948 | 159 |
1013 | 160 #if 1 |
948 | 161 int key; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
162 int map_generation= c->map_generation; |
1419 | 163 #ifndef NDEBUG |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
164 uint32_t *map= c->map; |
1419 | 165 #endif |
948 | 166 key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation; |
167 assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key); | |
168 key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation; | |
169 assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key); | |
170 key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation; | |
171 assert(map[(index+1)&(ME_MAP_SIZE-1)] == key); | |
172 key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation; | |
173 assert(map[(index-1)&(ME_MAP_SIZE-1)] == key); | |
174 #endif | |
936 | 175 if(t<=b){ |
176 CHECK_HALF_MV(0, 1, mx ,my-1) | |
177 if(l<=r){ | |
178 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
179 if(t+r<=b+l){ | |
180 CHECK_HALF_MV(1, 1, mx , my-1) | |
181 }else{ | |
182 CHECK_HALF_MV(1, 1, mx-1, my ) | |
183 } | |
184 CHECK_HALF_MV(1, 0, mx-1, my ) | |
185 }else{ | |
186 CHECK_HALF_MV(1, 1, mx , my-1) | |
187 if(t+l<=b+r){ | |
188 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
189 }else{ | |
190 CHECK_HALF_MV(1, 1, mx , my ) | |
191 } | |
192 CHECK_HALF_MV(1, 0, mx , my ) | |
193 } | |
194 }else{ | |
195 if(l<=r){ | |
196 if(t+l<=b+r){ | |
197 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
198 }else{ | |
199 CHECK_HALF_MV(1, 1, mx , my ) | |
200 } | |
201 CHECK_HALF_MV(1, 0, mx-1, my) | |
202 CHECK_HALF_MV(1, 1, mx-1, my) | |
203 }else{ | |
204 if(t+r<=b+l){ | |
205 CHECK_HALF_MV(1, 1, mx , my-1) | |
206 }else{ | |
207 CHECK_HALF_MV(1, 1, mx-1, my) | |
208 } | |
209 CHECK_HALF_MV(1, 0, mx , my) | |
210 CHECK_HALF_MV(1, 1, mx , my) | |
211 } | |
212 CHECK_HALF_MV(0, 1, mx , my) | |
213 } | |
214 assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2); | |
215 } | |
216 | |
1013 | 217 *mx_ptr = bx; |
218 *my_ptr = by; | |
219 | |
936 | 220 return dmin; |
221 } | |
222 #endif | |
223 | |
2327
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
224 static int no_sub_motion_search(MpegEncContext * s, |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
225 int *mx_ptr, int *my_ptr, int dmin, |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
226 int src_index, int ref_index, |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
227 int size, int h) |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
228 { |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
229 (*mx_ptr)<<=1; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
230 (*my_ptr)<<=1; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
231 return dmin; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
232 } |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
233 |
2189
70b27300a496
quad tree based motion compensation (currently only 16x16 & 8x8 OBMC blocks, but can be extended to other block sizes easily)
michael
parents:
2184
diff
changeset
|
234 int inline ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index, |
70b27300a496
quad tree based motion compensation (currently only 16x16 & 8x8 OBMC blocks, but can be extended to other block sizes easily)
michael
parents:
2184
diff
changeset
|
235 int ref_index, int size, int h, int add_rate) |
1013 | 236 { |
237 // const int check_luma= s->dsp.me_sub_cmp != s->dsp.mb_cmp; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
238 MotionEstContext * const c= &s->me; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
239 const int penalty_factor= c->mb_penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
240 const int flags= c->mb_flags; |
1950 | 241 const int qpel= flags & FLAG_QPEL; |
242 const int mask= 1+2*qpel; | |
1013 | 243 me_cmp_func cmp_sub, chroma_cmp_sub; |
244 int d; | |
245 | |
1708 | 246 LOAD_COMMON |
1013 | 247 |
248 //FIXME factorize | |
249 | |
250 cmp_sub= s->dsp.mb_cmp[size]; | |
251 chroma_cmp_sub= s->dsp.mb_cmp[size+1]; | |
252 | |
2189
70b27300a496
quad tree based motion compensation (currently only 16x16 & 8x8 OBMC blocks, but can be extended to other block sizes easily)
michael
parents:
2184
diff
changeset
|
253 // assert(!c->skip); |
70b27300a496
quad tree based motion compensation (currently only 16x16 & 8x8 OBMC blocks, but can be extended to other block sizes easily)
michael
parents:
2184
diff
changeset
|
254 // assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp); |
1013 | 255 |
1950 | 256 d= cmp(s, mx>>(qpel+1), my>>(qpel+1), mx&mask, my&mask, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); |
1013 | 257 //FIXME check cbp before adding penalty for (0,0) vector |
2189
70b27300a496
quad tree based motion compensation (currently only 16x16 & 8x8 OBMC blocks, but can be extended to other block sizes easily)
michael
parents:
2184
diff
changeset
|
258 if(add_rate && (mx || my || size>0)) |
1013 | 259 d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor; |
260 | |
261 return d; | |
262 } | |
263 | |
936 | 264 #define CHECK_QUARTER_MV(dx, dy, x, y)\ |
265 {\ | |
266 const int hx= 4*(x)+(dx);\ | |
267 const int hy= 4*(y)+(dy);\ | |
1950 | 268 d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 269 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ |
270 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ | |
271 } | |
272 | |
1950 | 273 static int qpel_motion_search(MpegEncContext * s, |
936 | 274 int *mx_ptr, int *my_ptr, int dmin, |
1950 | 275 int src_index, int ref_index, |
276 int size, int h) | |
936 | 277 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
278 MotionEstContext * const c= &s->me; |
936 | 279 const int mx = *mx_ptr; |
280 const int my = *my_ptr; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
281 const int penalty_factor= c->sub_penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
282 const int map_generation= c->map_generation; |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
283 const int subpel_quality= c->avctx->me_subpel_quality; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
284 uint32_t *map= c->map; |
1950 | 285 me_cmp_func cmpf, chroma_cmpf; |
936 | 286 me_cmp_func cmp_sub, chroma_cmp_sub; |
287 | |
1708 | 288 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
289 int flags= c->sub_flags; |
936 | 290 |
1950 | 291 cmpf= s->dsp.me_cmp[size]; |
292 chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME | |
936 | 293 //FIXME factorize |
294 | |
295 cmp_sub= s->dsp.me_sub_cmp[size]; | |
296 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
297 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
298 if(c->skip){ //FIXME somehow move up (benchmark) |
936 | 299 *mx_ptr = 0; |
300 *my_ptr = 0; | |
301 return dmin; | |
302 } | |
303 | |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
304 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
1950 | 305 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); |
1011 | 306 if(mx || my || size>0) |
936 | 307 dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor; |
308 } | |
309 | |
310 if (mx > xmin && mx < xmax && | |
311 my > ymin && my < ymax) { | |
312 int bx=4*mx, by=4*my; | |
313 int d= dmin; | |
314 int i, nx, ny; | |
315 const int index= (my<<ME_MAP_SHIFT) + mx; | |
316 const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; | |
317 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]; | |
318 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]; | |
319 const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; | |
320 const int c= score_map[(index )&(ME_MAP_SIZE-1)]; | |
321 int best[8]; | |
322 int best_pos[8][2]; | |
323 | |
324 memset(best, 64, sizeof(int)*8); | |
325 #if 1 | |
954 | 326 if(s->me.dia_size>=2){ |
936 | 327 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
328 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
329 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
330 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
331 | |
332 for(ny= -3; ny <= 3; ny++){ | |
333 for(nx= -3; nx <= 3; nx++){ | |
2079 | 334 //FIXME this could overflow (unlikely though) |
335 const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t; | |
336 const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c; | |
337 const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b; | |
338 int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10; | |
936 | 339 int i; |
340 | |
341 if((nx&3)==0 && (ny&3)==0) continue; | |
342 | |
2079 | 343 score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; |
936 | 344 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
345 // if(nx&1) score-=1024*c->penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
346 // if(ny&1) score-=1024*c->penalty_factor; |
936 | 347 |
348 for(i=0; i<8; i++){ | |
349 if(score < best[i]){ | |
350 memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); | |
351 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); | |
352 best[i]= score; | |
353 best_pos[i][0]= nx + 4*mx; | |
354 best_pos[i][1]= ny + 4*my; | |
355 break; | |
356 } | |
357 } | |
358 } | |
359 } | |
360 }else{ | |
361 int tl; | |
2079 | 362 //FIXME this could overflow (unlikely though) |
936 | 363 const int cx = 4*(r - l); |
364 const int cx2= r + l - 2*c; | |
365 const int cy = 4*(b - t); | |
366 const int cy2= b + t - 2*c; | |
367 int cxy; | |
368 | |
369 if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME | |
370 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
371 }else{ | |
1950 | 372 tl= cmp(s, mx-1, my-1, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);//FIXME wrong if chroma me is different |
936 | 373 } |
374 | |
375 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c; | |
376 | |
377 assert(16*cx2 + 4*cx + 32*c == 32*r); | |
378 assert(16*cx2 - 4*cx + 32*c == 32*l); | |
379 assert(16*cy2 + 4*cy + 32*c == 32*b); | |
380 assert(16*cy2 - 4*cy + 32*c == 32*t); | |
381 assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl); | |
382 | |
383 for(ny= -3; ny <= 3; ny++){ | |
384 for(nx= -3; nx <= 3; nx++){ | |
2079 | 385 //FIXME this could overflow (unlikely though) |
936 | 386 int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor |
387 int i; | |
388 | |
389 if((nx&3)==0 && (ny&3)==0) continue; | |
390 | |
391 score += 32*(mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
392 // if(nx&1) score-=32*c->penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
393 // if(ny&1) score-=32*c->penalty_factor; |
936 | 394 |
395 for(i=0; i<8; i++){ | |
396 if(score < best[i]){ | |
397 memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); | |
398 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); | |
399 best[i]= score; | |
400 best_pos[i][0]= nx + 4*mx; | |
401 best_pos[i][1]= ny + 4*my; | |
402 break; | |
403 } | |
404 } | |
405 } | |
406 } | |
407 } | |
954 | 408 for(i=0; i<subpel_quality; i++){ |
936 | 409 nx= best_pos[i][0]; |
410 ny= best_pos[i][1]; | |
411 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2) | |
412 } | |
954 | 413 |
936 | 414 #if 0 |
954 | 415 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
416 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
417 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
418 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
419 // if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){ | |
420 if(tl<br){ | |
421 | |
422 // nx= FFMAX(4*mx - bx, bx - 4*mx); | |
423 // ny= FFMAX(4*my - by, by - 4*my); | |
936 | 424 |
954 | 425 static int stats[7][7], count; |
426 count++; | |
427 stats[4*mx - bx + 3][4*my - by + 3]++; | |
428 if(256*256*256*64 % count ==0){ | |
429 for(i=0; i<49; i++){ | |
430 if((i%7)==0) printf("\n"); | |
936 | 431 printf("%6d ", stats[0][i]); |
432 } | |
433 printf("\n"); | |
434 } | |
954 | 435 } |
936 | 436 #endif |
437 #else | |
438 | |
439 CHECK_QUARTER_MV(2, 2, mx-1, my-1) | |
440 CHECK_QUARTER_MV(0, 2, mx , my-1) | |
441 CHECK_QUARTER_MV(2, 2, mx , my-1) | |
442 CHECK_QUARTER_MV(2, 0, mx , my ) | |
443 CHECK_QUARTER_MV(2, 2, mx , my ) | |
444 CHECK_QUARTER_MV(0, 2, mx , my ) | |
445 CHECK_QUARTER_MV(2, 2, mx-1, my ) | |
446 CHECK_QUARTER_MV(2, 0, mx-1, my ) | |
447 | |
448 nx= bx; | |
449 ny= by; | |
450 | |
451 for(i=0; i<8; i++){ | |
452 int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1}; | |
453 int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1}; | |
454 CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2) | |
455 } | |
456 #endif | |
457 #if 0 | |
458 //outer ring | |
459 CHECK_QUARTER_MV(1, 3, mx-1, my-1) | |
460 CHECK_QUARTER_MV(1, 2, mx-1, my-1) | |
461 CHECK_QUARTER_MV(1, 1, mx-1, my-1) | |
462 CHECK_QUARTER_MV(2, 1, mx-1, my-1) | |
463 CHECK_QUARTER_MV(3, 1, mx-1, my-1) | |
464 CHECK_QUARTER_MV(0, 1, mx , my-1) | |
465 CHECK_QUARTER_MV(1, 1, mx , my-1) | |
466 CHECK_QUARTER_MV(2, 1, mx , my-1) | |
467 CHECK_QUARTER_MV(3, 1, mx , my-1) | |
468 CHECK_QUARTER_MV(3, 2, mx , my-1) | |
469 CHECK_QUARTER_MV(3, 3, mx , my-1) | |
470 CHECK_QUARTER_MV(3, 0, mx , my ) | |
471 CHECK_QUARTER_MV(3, 1, mx , my ) | |
472 CHECK_QUARTER_MV(3, 2, mx , my ) | |
473 CHECK_QUARTER_MV(3, 3, mx , my ) | |
474 CHECK_QUARTER_MV(2, 3, mx , my ) | |
475 CHECK_QUARTER_MV(1, 3, mx , my ) | |
476 CHECK_QUARTER_MV(0, 3, mx , my ) | |
477 CHECK_QUARTER_MV(3, 3, mx-1, my ) | |
478 CHECK_QUARTER_MV(2, 3, mx-1, my ) | |
479 CHECK_QUARTER_MV(1, 3, mx-1, my ) | |
480 CHECK_QUARTER_MV(1, 2, mx-1, my ) | |
481 CHECK_QUARTER_MV(1, 1, mx-1, my ) | |
482 CHECK_QUARTER_MV(1, 0, mx-1, my ) | |
483 #endif | |
484 assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4); | |
485 | |
486 *mx_ptr = bx; | |
487 *my_ptr = by; | |
488 }else{ | |
489 *mx_ptr =4*mx; | |
490 *my_ptr =4*my; | |
491 } | |
492 | |
493 return dmin; | |
494 } | |
495 | |
496 | |
497 #define CHECK_MV(x,y)\ | |
498 {\ | |
499 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\ | |
500 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\ | |
2072 | 501 assert((x) >= xmin);\ |
502 assert((x) <= xmax);\ | |
503 assert((y) >= ymin);\ | |
504 assert((y) <= ymax);\ | |
948 | 505 /*printf("check_mv %d %d\n", x, y);*/\ |
936 | 506 if(map[index]!=key){\ |
1950 | 507 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 508 map[index]= key;\ |
509 score_map[index]= d;\ | |
510 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\ | |
948 | 511 /*printf("score:%d\n", d);*/\ |
936 | 512 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\ |
513 }\ | |
514 } | |
515 | |
948 | 516 #define CHECK_CLIPED_MV(ax,ay)\ |
517 {\ | |
1799 | 518 const int x= ax;\ |
519 const int y= ay;\ | |
520 const int x2= FFMAX(xmin, FFMIN(x, xmax));\ | |
521 const int y2= FFMAX(ymin, FFMIN(y, ymax));\ | |
522 CHECK_MV(x2, y2)\ | |
948 | 523 } |
524 | |
936 | 525 #define CHECK_MV_DIR(x,y,new_dir)\ |
526 {\ | |
527 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\ | |
528 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\ | |
948 | 529 /*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\ |
936 | 530 if(map[index]!=key){\ |
1950 | 531 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 532 map[index]= key;\ |
533 score_map[index]= d;\ | |
534 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\ | |
948 | 535 /*printf("score:%d\n", d);*/\ |
936 | 536 if(d<dmin){\ |
537 best[0]=x;\ | |
538 best[1]=y;\ | |
539 dmin=d;\ | |
540 next_dir= new_dir;\ | |
541 }\ | |
542 }\ | |
543 } | |
544 | |
545 #define check(x,y,S,v)\ | |
546 if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\ | |
547 if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\ | |
548 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\ | |
549 if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\ | |
550 | |
1950 | 551 #define LOAD_COMMON2\ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
552 uint32_t *map= c->map;\ |
1950 | 553 const int qpel= flags&FLAG_QPEL;\ |
554 const int shift= 1+qpel;\ | |
936 | 555 |
1950 | 556 static always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, |
557 int src_index, int ref_index, int const penalty_factor, | |
558 int size, int h, int flags) | |
936 | 559 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
560 MotionEstContext * const c= &s->me; |
1950 | 561 me_cmp_func cmpf, chroma_cmpf; |
936 | 562 int next_dir=-1; |
1708 | 563 LOAD_COMMON |
1950 | 564 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
565 int map_generation= c->map_generation; |
936 | 566 |
1950 | 567 cmpf= s->dsp.me_cmp[size]; |
568 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 569 |
948 | 570 { /* ensure that the best point is in the MAP as h/qpel refinement needs it */ |
571 const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation; | |
572 const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1); | |
573 if(map[index]!=key){ //this will be executed only very rarey | |
1950 | 574 score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags); |
948 | 575 map[index]= key; |
576 } | |
577 } | |
578 | |
936 | 579 for(;;){ |
580 int d; | |
581 const int dir= next_dir; | |
582 const int x= best[0]; | |
583 const int y= best[1]; | |
584 next_dir=-1; | |
585 | |
586 //printf("%d", dir); | |
587 if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0) | |
588 if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1) | |
589 if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2) | |
590 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) | |
591 | |
592 if(next_dir==-1){ | |
593 return dmin; | |
594 } | |
595 } | |
596 } | |
597 | |
1950 | 598 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin, |
599 int src_index, int ref_index, int const penalty_factor, | |
600 int size, int h, int flags) | |
948 | 601 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
602 MotionEstContext * const c= &s->me; |
1950 | 603 me_cmp_func cmpf, chroma_cmpf; |
948 | 604 int dia_size; |
1708 | 605 LOAD_COMMON |
1950 | 606 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
607 int map_generation= c->map_generation; |
948 | 608 |
1950 | 609 cmpf= s->dsp.me_cmp[size]; |
610 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
948 | 611 |
612 for(dia_size=1; dia_size<=4; dia_size++){ | |
613 int dir; | |
614 const int x= best[0]; | |
615 const int y= best[1]; | |
616 | |
617 if(dia_size&(dia_size-1)) continue; | |
618 | |
619 if( x + dia_size > xmax | |
620 || x - dia_size < xmin | |
621 || y + dia_size > ymax | |
622 || y - dia_size < ymin) | |
623 continue; | |
624 | |
625 for(dir= 0; dir<dia_size; dir+=2){ | |
626 int d; | |
627 | |
628 CHECK_MV(x + dir , y + dia_size - dir); | |
629 CHECK_MV(x + dia_size - dir, y - dir ); | |
630 CHECK_MV(x - dir , y - dia_size + dir); | |
631 CHECK_MV(x - dia_size + dir, y + dir ); | |
632 } | |
633 | |
634 if(x!=best[0] || y!=best[1]) | |
635 dia_size=0; | |
636 #if 0 | |
637 { | |
638 int dx, dy, i; | |
639 static int stats[8*8]; | |
640 dx= ABS(x-best[0]); | |
641 dy= ABS(y-best[1]); | |
642 if(dy>dx){ | |
643 dx^=dy; dy^=dx; dx^=dy; | |
644 } | |
645 stats[dy*8 + dx] ++; | |
646 if(256*256*256*64 % (stats[0]+1)==0){ | |
647 for(i=0; i<64; i++){ | |
648 if((i&7)==0) printf("\n"); | |
649 printf("%8d ", stats[i]); | |
650 } | |
651 printf("\n"); | |
652 } | |
653 } | |
654 #endif | |
655 } | |
656 return dmin; | |
657 } | |
658 | |
659 #define SAB_CHECK_MV(ax,ay)\ | |
660 {\ | |
661 const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\ | |
662 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\ | |
663 /*printf("sab check %d %d\n", ax, ay);*/\ | |
664 if(map[index]!=key){\ | |
1950 | 665 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
948 | 666 map[index]= key;\ |
667 score_map[index]= d;\ | |
668 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\ | |
669 /*printf("score: %d\n", d);*/\ | |
670 if(d < minima[minima_count-1].height){\ | |
671 int j=0;\ | |
672 \ | |
673 while(d >= minima[j].height) j++;\ | |
674 \ | |
675 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\ | |
676 \ | |
677 minima[j].checked= 0;\ | |
678 minima[j].height= d;\ | |
679 minima[j].x= ax;\ | |
680 minima[j].y= ay;\ | |
681 \ | |
682 i=-1;\ | |
683 continue;\ | |
684 }\ | |
685 }\ | |
686 } | |
687 | |
2113
07a663d46be2
shape-adaptive diamond + prediction crash patch by (Loren Merritt <lorenm at u dot washington dot edu>)
michael
parents:
2079
diff
changeset
|
688 #define MAX_SAB_SIZE ME_MAP_SIZE |
1950 | 689 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, |
690 int src_index, int ref_index, int const penalty_factor, | |
691 int size, int h, int flags) | |
948 | 692 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
693 MotionEstContext * const c= &s->me; |
1950 | 694 me_cmp_func cmpf, chroma_cmpf; |
948 | 695 Minima minima[MAX_SAB_SIZE]; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
696 const int minima_count= ABS(c->dia_size); |
948 | 697 int i, j; |
1708 | 698 LOAD_COMMON |
1950 | 699 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
700 int map_generation= c->map_generation; |
948 | 701 |
1950 | 702 cmpf= s->dsp.me_cmp[size]; |
703 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
948 | 704 |
705 for(j=i=0; i<ME_MAP_SIZE; i++){ | |
706 uint32_t key= map[i]; | |
707 | |
708 key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1)); | |
709 | |
710 if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue; | |
711 | |
712 assert(j<MAX_SAB_SIZE); //max j = number of predictors | |
713 | |
714 minima[j].height= score_map[i]; | |
715 minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS; | |
716 minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1); | |
717 minima[j].x-= (1<<(ME_MAP_MV_BITS-1)); | |
718 minima[j].y-= (1<<(ME_MAP_MV_BITS-1)); | |
719 minima[j].checked=0; | |
720 if(minima[j].x || minima[j].y) | |
721 minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor; | |
722 | |
723 j++; | |
724 } | |
725 | |
726 qsort(minima, j, sizeof(Minima), minima_cmp); | |
727 | |
728 for(; j<minima_count; j++){ | |
729 minima[j].height=256*256*256*64; | |
730 minima[j].checked=0; | |
731 minima[j].x= minima[j].y=0; | |
732 } | |
733 | |
734 for(i=0; i<minima_count; i++){ | |
735 const int x= minima[i].x; | |
736 const int y= minima[i].y; | |
737 int d; | |
738 | |
739 if(minima[i].checked) continue; | |
740 | |
741 if( x >= xmax || x <= xmin | |
742 || y >= ymax || y <= ymin) | |
743 continue; | |
744 | |
745 SAB_CHECK_MV(x-1, y) | |
746 SAB_CHECK_MV(x+1, y) | |
747 SAB_CHECK_MV(x , y-1) | |
748 SAB_CHECK_MV(x , y+1) | |
749 | |
750 minima[i].checked= 1; | |
751 } | |
752 | |
753 best[0]= minima[0].x; | |
754 best[1]= minima[0].y; | |
755 dmin= minima[0].height; | |
756 | |
757 if( best[0] < xmax && best[0] > xmin | |
758 && best[1] < ymax && best[1] > ymin){ | |
759 int d; | |
760 //ensure that the refernece samples for hpel refinement are in the map | |
761 CHECK_MV(best[0]-1, best[1]) | |
762 CHECK_MV(best[0]+1, best[1]) | |
763 CHECK_MV(best[0], best[1]-1) | |
764 CHECK_MV(best[0], best[1]+1) | |
765 } | |
766 return dmin; | |
767 } | |
768 | |
1950 | 769 static int var_diamond_search(MpegEncContext * s, int *best, int dmin, |
770 int src_index, int ref_index, int const penalty_factor, | |
771 int size, int h, int flags) | |
936 | 772 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
773 MotionEstContext * const c= &s->me; |
1950 | 774 me_cmp_func cmpf, chroma_cmpf; |
948 | 775 int dia_size; |
1708 | 776 LOAD_COMMON |
1950 | 777 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
778 int map_generation= c->map_generation; |
936 | 779 |
1950 | 780 cmpf= s->dsp.me_cmp[size]; |
781 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 782 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
783 for(dia_size=1; dia_size<=c->dia_size; dia_size++){ |
936 | 784 int dir, start, end; |
785 const int x= best[0]; | |
786 const int y= best[1]; | |
787 | |
788 start= FFMAX(0, y + dia_size - ymax); | |
948 | 789 end = FFMIN(dia_size, xmax - x + 1); |
936 | 790 for(dir= start; dir<end; dir++){ |
791 int d; | |
792 | |
793 //check(x + dir,y + dia_size - dir,0, a0) | |
794 CHECK_MV(x + dir , y + dia_size - dir); | |
795 } | |
796 | |
797 start= FFMAX(0, x + dia_size - xmax); | |
948 | 798 end = FFMIN(dia_size, y - ymin + 1); |
936 | 799 for(dir= start; dir<end; dir++){ |
800 int d; | |
801 | |
802 //check(x + dia_size - dir, y - dir,0, a1) | |
803 CHECK_MV(x + dia_size - dir, y - dir ); | |
804 } | |
805 | |
806 start= FFMAX(0, -y + dia_size + ymin ); | |
948 | 807 end = FFMIN(dia_size, x - xmin + 1); |
936 | 808 for(dir= start; dir<end; dir++){ |
809 int d; | |
810 | |
811 //check(x - dir,y - dia_size + dir,0, a2) | |
812 CHECK_MV(x - dir , y - dia_size + dir); | |
813 } | |
814 | |
815 start= FFMAX(0, -x + dia_size + xmin ); | |
948 | 816 end = FFMIN(dia_size, ymax - y + 1); |
936 | 817 for(dir= start; dir<end; dir++){ |
818 int d; | |
819 | |
820 //check(x - dia_size + dir, y + dir,0, a3) | |
821 CHECK_MV(x - dia_size + dir, y + dir ); | |
822 } | |
823 | |
824 if(x!=best[0] || y!=best[1]) | |
825 dia_size=0; | |
948 | 826 #if 0 |
827 { | |
828 int dx, dy, i; | |
829 static int stats[8*8]; | |
830 dx= ABS(x-best[0]); | |
831 dy= ABS(y-best[1]); | |
832 stats[dy*8 + dx] ++; | |
833 if(256*256*256*64 % (stats[0]+1)==0){ | |
834 for(i=0; i<64; i++){ | |
835 if((i&7)==0) printf("\n"); | |
836 printf("%6d ", stats[i]); | |
837 } | |
838 printf("\n"); | |
839 } | |
840 } | |
841 #endif | |
936 | 842 } |
843 return dmin; | |
844 } | |
845 | |
1950 | 846 static always_inline int diamond_search(MpegEncContext * s, int *best, int dmin, |
847 int src_index, int ref_index, int const penalty_factor, | |
848 int size, int h, int flags){ | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
849 MotionEstContext * const c= &s->me; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
850 if(c->dia_size==-1) |
1950 | 851 return funny_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
852 else if(c->dia_size<-1) |
1950 | 853 return sab_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
854 else if(c->dia_size<2) |
1950 | 855 return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
856 else | |
857 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); | |
858 } | |
859 | |
860 static always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr, | |
861 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], | |
2184 | 862 int ref_mv_scale, int flags, int size, int h) |
936 | 863 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
864 MotionEstContext * const c= &s->me; |
936 | 865 int best[2]={0, 0}; |
1950 | 866 int d, dmin; |
936 | 867 int map_generation; |
2226 | 868 int penalty_factor; |
1708 | 869 const int ref_mv_stride= s->mb_stride; //pass as arg FIXME |
870 const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME | |
1950 | 871 me_cmp_func cmpf, chroma_cmpf; |
936 | 872 |
1950 | 873 LOAD_COMMON |
874 LOAD_COMMON2 | |
875 | |
2226 | 876 if(c->pre_pass){ |
877 penalty_factor= c->pre_penalty_factor; | |
878 cmpf= s->dsp.me_pre_cmp[size]; | |
879 chroma_cmpf= s->dsp.me_pre_cmp[size+1]; | |
880 }else{ | |
881 penalty_factor= c->penalty_factor; | |
882 cmpf= s->dsp.me_cmp[size]; | |
883 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
884 } | |
936 | 885 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
886 map_generation= update_map_generation(c); |
936 | 887 |
2184 | 888 assert(cmpf); |
1950 | 889 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags); |
936 | 890 map[0]= map_generation; |
891 score_map[0]= dmin; | |
892 | |
893 /* first line */ | |
1799 | 894 if (s->first_slice_line) { |
936 | 895 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
948 | 896 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
897 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
936 | 898 }else{ |
2184 | 899 if(dmin<h*h && ( P_LEFT[0] |P_LEFT[1] |
936 | 900 |P_TOP[0] |P_TOP[1] |
948 | 901 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){ |
936 | 902 *mx_ptr= 0; |
903 *my_ptr= 0; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
904 c->skip=1; |
936 | 905 return dmin; |
906 } | |
907 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) | |
2184 | 908 if(dmin>h*h*2){ |
948 | 909 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
910 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
936 | 911 CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift) |
912 CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift) | |
913 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
914 } | |
915 } | |
2184 | 916 if(dmin>h*h*4){ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
917 if(c->pre_pass){ |
952 | 918 CHECK_CLIPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16, |
919 (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16) | |
1799 | 920 if(!s->first_slice_line) |
921 CHECK_CLIPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, | |
922 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) | |
952 | 923 }else{ |
924 CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, | |
925 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) | |
1800
e039d79185c2
simplify MV availability check / dont use below last row MV which is always zero
michael
parents:
1799
diff
changeset
|
926 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
1799 | 927 CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
928 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) | |
952 | 929 } |
936 | 930 } |
948 | 931 |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
932 if(c->avctx->last_predictor_count){ |
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
933 const int count= c->avctx->last_predictor_count; |
948 | 934 const int xstart= FFMAX(0, s->mb_x - count); |
935 const int ystart= FFMAX(0, s->mb_y - count); | |
936 const int xend= FFMIN(s->mb_width , s->mb_x + count + 1); | |
937 const int yend= FFMIN(s->mb_height, s->mb_y + count + 1); | |
938 int mb_y; | |
936 | 939 |
948 | 940 for(mb_y=ystart; mb_y<yend; mb_y++){ |
941 int mb_x; | |
942 for(mb_x=xstart; mb_x<xend; mb_x++){ | |
943 const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride; | |
944 int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16; | |
945 int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16; | |
946 | |
947 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue; | |
948 CHECK_MV(mx,my) | |
936 | 949 } |
950 } | |
951 } | |
948 | 952 |
936 | 953 //check(best[0],best[1],0, b0) |
1950 | 954 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
936 | 955 |
956 //check(best[0],best[1],0, b1) | |
957 *mx_ptr= best[0]; | |
958 *my_ptr= best[1]; | |
959 | |
960 // printf("%d %d %d \n", best[0], best[1], dmin); | |
961 return dmin; | |
962 } | |
963 | |
1950 | 964 //this function is dedicated to the braindamaged gcc |
2184 | 965 inline int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr, |
1950 | 966 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], |
2184 | 967 int ref_mv_scale, int size, int h) |
1950 | 968 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
969 MotionEstContext * const c= &s->me; |
1950 | 970 //FIXME convert other functions in the same way if faster |
2184 | 971 if(c->flags==0 && h==16 && size==0){ |
972 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16); | |
1950 | 973 // case FLAG_QPEL: |
974 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL); | |
2184 | 975 }else{ |
976 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, c->flags, size, h); | |
1950 | 977 } |
978 } | |
979 | |
980 static int epzs_motion_search4(MpegEncContext * s, | |
981 int *mx_ptr, int *my_ptr, int P[10][2], | |
982 int src_index, int ref_index, int16_t (*last_mv)[2], | |
983 int ref_mv_scale) | |
936 | 984 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
985 MotionEstContext * const c= &s->me; |
936 | 986 int best[2]={0, 0}; |
987 int d, dmin; | |
988 int map_generation; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
989 const int penalty_factor= c->penalty_factor; |
936 | 990 const int size=1; |
1708 | 991 const int h=8; |
1177
fea03d2c4946
simplified adressing of most mb based arrays (mb_x + mb_y*s->mb_stride) now instead of mb_x + mb_y*mb_width and 1+mb_x + (1+mb_y)*(mb_width+2) and ... mixture
michaelni
parents:
1162
diff
changeset
|
992 const int ref_mv_stride= s->mb_stride; |
fea03d2c4946
simplified adressing of most mb based arrays (mb_x + mb_y*s->mb_stride) now instead of mb_x + mb_y*mb_width and 1+mb_x + (1+mb_y)*(mb_width+2) and ... mixture
michaelni
parents:
1162
diff
changeset
|
993 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; |
1950 | 994 me_cmp_func cmpf, chroma_cmpf; |
1708 | 995 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
996 int flags= c->flags; |
1950 | 997 LOAD_COMMON2 |
936 | 998 |
1950 | 999 cmpf= s->dsp.me_cmp[size]; |
1000 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 1001 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1002 map_generation= update_map_generation(c); |
936 | 1003 |
1004 dmin = 1000000; | |
1005 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); | |
1006 /* first line */ | |
1799 | 1007 if (s->first_slice_line) { |
936 | 1008 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
948 | 1009 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
1010 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
936 | 1011 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) |
1012 }else{ | |
1013 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1014 //FIXME try some early stop | |
1015 if(dmin>64*2){ | |
1016 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) | |
1017 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) | |
1018 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) | |
1019 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
948 | 1020 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
1021 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
936 | 1022 } |
1023 } | |
1024 if(dmin>64*4){ | |
948 | 1025 CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, |
1026 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) | |
1800
e039d79185c2
simplify MV availability check / dont use below last row MV which is always zero
michael
parents:
1799
diff
changeset
|
1027 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
1799 | 1028 CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1029 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) | |
936 | 1030 } |
1031 | |
1950 | 1032 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
1708 | 1033 |
1034 *mx_ptr= best[0]; | |
1035 *my_ptr= best[1]; | |
1036 | |
1037 // printf("%d %d %d \n", best[0], best[1], dmin); | |
1038 return dmin; | |
1039 } | |
1040 | |
1041 //try to merge with above FIXME (needs PSNR test) | |
1950 | 1042 static int epzs_motion_search2(MpegEncContext * s, |
1043 int *mx_ptr, int *my_ptr, int P[10][2], | |
1044 int src_index, int ref_index, int16_t (*last_mv)[2], | |
1045 int ref_mv_scale) | |
1708 | 1046 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1047 MotionEstContext * const c= &s->me; |
1708 | 1048 int best[2]={0, 0}; |
1049 int d, dmin; | |
1050 int map_generation; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1051 const int penalty_factor= c->penalty_factor; |
1708 | 1052 const int size=0; //FIXME pass as arg |
1053 const int h=8; | |
1054 const int ref_mv_stride= s->mb_stride; | |
1055 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; | |
1950 | 1056 me_cmp_func cmpf, chroma_cmpf; |
1708 | 1057 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1058 int flags= c->flags; |
1950 | 1059 LOAD_COMMON2 |
1708 | 1060 |
1950 | 1061 cmpf= s->dsp.me_cmp[size]; |
1062 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
1708 | 1063 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1064 map_generation= update_map_generation(c); |
1708 | 1065 |
1066 dmin = 1000000; | |
1067 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); | |
1068 /* first line */ | |
1799 | 1069 if (s->first_slice_line) { |
1708 | 1070 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
1071 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, | |
1072 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
1073 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1074 }else{ | |
1075 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1076 //FIXME try some early stop | |
1077 if(dmin>64*2){ | |
1078 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) | |
1079 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) | |
1080 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) | |
1081 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
1082 CHECK_CLIPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, | |
1083 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) | |
1084 } | |
1085 } | |
1086 if(dmin>64*4){ | |
1087 CHECK_CLIPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, | |
1088 (last_mv[ref_mv_xy+1][1]*ref_mv_scale + (1<<15))>>16) | |
1800
e039d79185c2
simplify MV availability check / dont use below last row MV which is always zero
michael
parents:
1799
diff
changeset
|
1089 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
1799 | 1090 CHECK_CLIPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1091 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) | |
1708 | 1092 } |
1093 | |
1950 | 1094 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
948 | 1095 |
936 | 1096 *mx_ptr= best[0]; |
1097 *my_ptr= best[1]; | |
1098 | |
1099 // printf("%d %d %d \n", best[0], best[1], dmin); | |
1100 return dmin; | |
1101 } |