Mercurial > libavcodec.hg
annotate motion_est_template.c @ 5876:731ee5ad6bde libavcodec
Correct assignment of interlaced_frame; was being set on output frames,
in display order, based on decoding information in decoding order. Now
set properly, immediately upon completion of decode.
Based on original patch from Reinhard Nissl, rnisssl % gmx , de
Original Thread: [FFmpeg-devel] H.264 + PAFF: BBC HD recording shows
extreme interlacing artefacts, Thu, 01 Nov 2007 22:43:09
author | heydowns |
---|---|
date | Mon, 05 Nov 2007 18:16:42 +0000 |
parents | 2b72f9bc4f06 |
children | 493dc59d469a |
rev | line source |
---|---|
936 | 1 /* |
2967 | 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 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
936 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
936 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
936 | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3293
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
936 | 20 */ |
2967 | 21 |
1106 | 22 /** |
23 * @file motion_est_template.c | |
24 * Motion estimation template. | |
25 */ | |
1950 | 26 |
936 | 27 //lets hope gcc will remove the unused vars ...(gcc 3.2.2 seems to do it ...) |
1708 | 28 #define LOAD_COMMON\ |
5083
ce36118abbbb
rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents:
4758
diff
changeset
|
29 uint32_t av_unused * const score_map= c->score_map;\ |
ce36118abbbb
rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents:
4758
diff
changeset
|
30 const int av_unused xmin= c->xmin;\ |
ce36118abbbb
rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents:
4758
diff
changeset
|
31 const int av_unused ymin= c->ymin;\ |
ce36118abbbb
rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents:
4758
diff
changeset
|
32 const int av_unused xmax= c->xmax;\ |
ce36118abbbb
rename attribute_unused to av_unused and moves its declaration to common.h
benoit
parents:
4758
diff
changeset
|
33 const int av_unused ymax= c->ymax;\ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
34 uint8_t *mv_penalty= c->current_mv_penalty;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
35 const int pred_x= c->pred_x;\ |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
36 const int pred_y= c->pred_y;\ |
936 | 37 |
38 #define CHECK_HALF_MV(dx, dy, x, y)\ | |
39 {\ | |
40 const int hx= 2*(x)+(dx);\ | |
41 const int hy= 2*(y)+(dy);\ | |
1950 | 42 d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags);\ |
936 | 43 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ |
44 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ | |
45 } | |
46 | |
47 #if 0 | |
1950 | 48 static int hpel_motion_search)(MpegEncContext * s, |
2979 | 49 int *mx_ptr, int *my_ptr, int dmin, |
2967 | 50 uint8_t *ref_data[3], |
1950 | 51 int size) |
936 | 52 { |
53 const int xx = 16 * s->mb_x + 8*(n&1); | |
54 const int yy = 16 * s->mb_y + 8*(n>>1); | |
55 const int mx = *mx_ptr; | |
56 const int my = *my_ptr; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
57 const int penalty_factor= c->sub_penalty_factor; |
2967 | 58 |
1708 | 59 LOAD_COMMON |
2967 | 60 |
936 | 61 // INIT; |
62 //FIXME factorize | |
63 me_cmp_func cmp, chroma_cmp, cmp_sub, chroma_cmp_sub; | |
64 | |
65 if(s->no_rounding /*FIXME b_type*/){ | |
66 hpel_put= &s->dsp.put_no_rnd_pixels_tab[size]; | |
67 chroma_hpel_put= &s->dsp.put_no_rnd_pixels_tab[size+1]; | |
68 }else{ | |
69 hpel_put=& s->dsp.put_pixels_tab[size]; | |
70 chroma_hpel_put= &s->dsp.put_pixels_tab[size+1]; | |
71 } | |
1950 | 72 cmpf= s->dsp.me_cmp[size]; |
73 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 74 cmp_sub= s->dsp.me_sub_cmp[size]; |
75 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
76 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
77 if(c->skip){ //FIXME somehow move up (benchmark) |
936 | 78 *mx_ptr = 0; |
79 *my_ptr = 0; | |
80 return dmin; | |
81 } | |
2967 | 82 |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
83 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
936 | 84 CMP_HPEL(dmin, 0, 0, mx, my, size); |
85 if(mx || my) | |
86 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; | |
87 } | |
2967 | 88 |
89 if (mx > xmin && mx < xmax && | |
936 | 90 my > ymin && my < ymax) { |
91 int bx=2*mx, by=2*my; | |
92 int d= dmin; | |
2967 | 93 |
936 | 94 CHECK_HALF_MV(1, 1, mx-1, my-1) |
2967 | 95 CHECK_HALF_MV(0, 1, mx , my-1) |
936 | 96 CHECK_HALF_MV(1, 1, mx , my-1) |
97 CHECK_HALF_MV(1, 0, mx-1, my ) | |
98 CHECK_HALF_MV(1, 0, mx , my ) | |
99 CHECK_HALF_MV(1, 1, mx-1, my ) | |
2967 | 100 CHECK_HALF_MV(0, 1, mx , my ) |
936 | 101 CHECK_HALF_MV(1, 1, mx , my ) |
102 | |
948 | 103 assert(bx >= xmin*2 || bx <= xmax*2 || by >= ymin*2 || by <= ymax*2); |
936 | 104 |
105 *mx_ptr = bx; | |
106 *my_ptr = by; | |
107 }else{ | |
108 *mx_ptr =2*mx; | |
109 *my_ptr =2*my; | |
110 } | |
111 | |
112 return dmin; | |
113 } | |
114 | |
115 #else | |
1950 | 116 static int hpel_motion_search(MpegEncContext * s, |
2979 | 117 int *mx_ptr, int *my_ptr, int dmin, |
1950 | 118 int src_index, int ref_index, |
119 int size, int h) | |
936 | 120 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
121 MotionEstContext * const c= &s->me; |
936 | 122 const int mx = *mx_ptr; |
2967 | 123 const int my = *my_ptr; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
124 const int penalty_factor= c->sub_penalty_factor; |
936 | 125 me_cmp_func cmp_sub, chroma_cmp_sub; |
1013 | 126 int bx=2*mx, by=2*my; |
936 | 127 |
1708 | 128 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
129 int flags= c->sub_flags; |
2967 | 130 |
936 | 131 //FIXME factorize |
132 | |
133 cmp_sub= s->dsp.me_sub_cmp[size]; | |
134 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
135 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
136 if(c->skip){ //FIXME move out of hpel? |
936 | 137 *mx_ptr = 0; |
138 *my_ptr = 0; | |
139 return dmin; | |
140 } | |
2967 | 141 |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
142 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
1950 | 143 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); |
1011 | 144 if(mx || my || size>0) |
936 | 145 dmin += (mv_penalty[2*mx - pred_x] + mv_penalty[2*my - pred_y])*penalty_factor; |
146 } | |
2967 | 147 |
148 if (mx > xmin && mx < xmax && | |
936 | 149 my > ymin && my < ymax) { |
150 int d= dmin; | |
151 const int index= (my<<ME_MAP_SHIFT) + mx; | |
2967 | 152 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
|
153 + (mv_penalty[bx - pred_x] + mv_penalty[by-2 - pred_y])*c->penalty_factor; |
936 | 154 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
|
155 + (mv_penalty[bx-2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; |
936 | 156 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
|
157 + (mv_penalty[bx+2 - pred_x] + mv_penalty[by - pred_y])*c->penalty_factor; |
936 | 158 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
|
159 + (mv_penalty[bx - pred_x] + mv_penalty[by+2 - pred_y])*c->penalty_factor; |
2967 | 160 |
1013 | 161 #if 1 |
948 | 162 int key; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
163 int map_generation= c->map_generation; |
1419 | 164 #ifndef NDEBUG |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
165 uint32_t *map= c->map; |
1419 | 166 #endif |
948 | 167 key= ((my-1)<<ME_MAP_MV_BITS) + (mx) + map_generation; |
168 assert(map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key); | |
169 key= ((my+1)<<ME_MAP_MV_BITS) + (mx) + map_generation; | |
170 assert(map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)] == key); | |
171 key= ((my)<<ME_MAP_MV_BITS) + (mx+1) + map_generation; | |
172 assert(map[(index+1)&(ME_MAP_SIZE-1)] == key); | |
173 key= ((my)<<ME_MAP_MV_BITS) + (mx-1) + map_generation; | |
174 assert(map[(index-1)&(ME_MAP_SIZE-1)] == key); | |
2967 | 175 #endif |
936 | 176 if(t<=b){ |
177 CHECK_HALF_MV(0, 1, mx ,my-1) | |
178 if(l<=r){ | |
179 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
180 if(t+r<=b+l){ | |
181 CHECK_HALF_MV(1, 1, mx , my-1) | |
182 }else{ | |
183 CHECK_HALF_MV(1, 1, mx-1, my ) | |
184 } | |
185 CHECK_HALF_MV(1, 0, mx-1, my ) | |
186 }else{ | |
187 CHECK_HALF_MV(1, 1, mx , my-1) | |
188 if(t+l<=b+r){ | |
189 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
190 }else{ | |
191 CHECK_HALF_MV(1, 1, mx , my ) | |
192 } | |
193 CHECK_HALF_MV(1, 0, mx , my ) | |
194 } | |
195 }else{ | |
196 if(l<=r){ | |
197 if(t+l<=b+r){ | |
198 CHECK_HALF_MV(1, 1, mx-1, my-1) | |
199 }else{ | |
200 CHECK_HALF_MV(1, 1, mx , my ) | |
201 } | |
202 CHECK_HALF_MV(1, 0, mx-1, my) | |
203 CHECK_HALF_MV(1, 1, mx-1, my) | |
204 }else{ | |
205 if(t+r<=b+l){ | |
206 CHECK_HALF_MV(1, 1, mx , my-1) | |
207 }else{ | |
208 CHECK_HALF_MV(1, 1, mx-1, my) | |
209 } | |
210 CHECK_HALF_MV(1, 0, mx , my) | |
211 CHECK_HALF_MV(1, 1, mx , my) | |
212 } | |
213 CHECK_HALF_MV(0, 1, mx , my) | |
214 } | |
215 assert(bx >= xmin*2 && bx <= xmax*2 && by >= ymin*2 && by <= ymax*2); | |
216 } | |
217 | |
1013 | 218 *mx_ptr = bx; |
219 *my_ptr = by; | |
2967 | 220 |
936 | 221 return dmin; |
222 } | |
223 #endif | |
224 | |
2327
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
225 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
|
226 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
|
227 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
|
228 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
|
229 { |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
230 (*mx_ptr)<<=1; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
231 (*my_ptr)<<=1; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
232 return dmin; |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
233 } |
5e5cf598a48b
H.261 encoder by (Maarten Daniels <maarten dot daniels at luc dot ac dot be>)
michael
parents:
2226
diff
changeset
|
234 |
3959 | 235 inline int ff_get_mb_score(MpegEncContext * s, int mx, int my, int src_index, |
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
|
236 int ref_index, int size, int h, int add_rate) |
1013 | 237 { |
238 // 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
|
239 MotionEstContext * const c= &s->me; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
240 const int penalty_factor= c->mb_penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
241 const int flags= c->mb_flags; |
1950 | 242 const int qpel= flags & FLAG_QPEL; |
243 const int mask= 1+2*qpel; | |
1013 | 244 me_cmp_func cmp_sub, chroma_cmp_sub; |
245 int d; | |
246 | |
1708 | 247 LOAD_COMMON |
2967 | 248 |
1013 | 249 //FIXME factorize |
250 | |
251 cmp_sub= s->dsp.mb_cmp[size]; | |
252 chroma_cmp_sub= s->dsp.mb_cmp[size+1]; | |
2967 | 253 |
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
|
254 // 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
|
255 // assert(c->avctx->me_sub_cmp != c->avctx->mb_cmp); |
1013 | 256 |
1950 | 257 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 | 258 //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
|
259 if(add_rate && (mx || my || size>0)) |
1013 | 260 d += (mv_penalty[mx - pred_x] + mv_penalty[my - pred_y])*penalty_factor; |
2967 | 261 |
1013 | 262 return d; |
263 } | |
264 | |
936 | 265 #define CHECK_QUARTER_MV(dx, dy, x, y)\ |
266 {\ | |
267 const int hx= 4*(x)+(dx);\ | |
268 const int hy= 4*(y)+(dy);\ | |
1950 | 269 d= cmp(s, x, y, dx, dy, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 270 d += (mv_penalty[hx - pred_x] + mv_penalty[hy - pred_y])*penalty_factor;\ |
271 COPY3_IF_LT(dmin, d, bx, hx, by, hy)\ | |
272 } | |
273 | |
1950 | 274 static int qpel_motion_search(MpegEncContext * s, |
2979 | 275 int *mx_ptr, int *my_ptr, int dmin, |
2967 | 276 int src_index, int ref_index, |
1950 | 277 int size, int h) |
936 | 278 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
279 MotionEstContext * const c= &s->me; |
936 | 280 const int mx = *mx_ptr; |
2967 | 281 const int my = *my_ptr; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
282 const int penalty_factor= c->sub_penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
283 const int map_generation= c->map_generation; |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
284 const int subpel_quality= c->avctx->me_subpel_quality; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
285 uint32_t *map= c->map; |
1950 | 286 me_cmp_func cmpf, chroma_cmpf; |
936 | 287 me_cmp_func cmp_sub, chroma_cmp_sub; |
288 | |
1708 | 289 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
290 int flags= c->sub_flags; |
2967 | 291 |
1950 | 292 cmpf= s->dsp.me_cmp[size]; |
293 chroma_cmpf= s->dsp.me_cmp[size+1]; //factorize FIXME | |
936 | 294 //FIXME factorize |
295 | |
296 cmp_sub= s->dsp.me_sub_cmp[size]; | |
297 chroma_cmp_sub= s->dsp.me_sub_cmp[size+1]; | |
298 | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
299 if(c->skip){ //FIXME somehow move up (benchmark) |
936 | 300 *mx_ptr = 0; |
301 *my_ptr = 0; | |
302 return dmin; | |
303 } | |
2967 | 304 |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
305 if(c->avctx->me_cmp != c->avctx->me_sub_cmp){ |
1950 | 306 dmin= cmp(s, mx, my, 0, 0, size, h, ref_index, src_index, cmp_sub, chroma_cmp_sub, flags); |
1011 | 307 if(mx || my || size>0) |
936 | 308 dmin += (mv_penalty[4*mx - pred_x] + mv_penalty[4*my - pred_y])*penalty_factor; |
309 } | |
2967 | 310 |
311 if (mx > xmin && mx < xmax && | |
936 | 312 my > ymin && my < ymax) { |
313 int bx=4*mx, by=4*my; | |
314 int d= dmin; | |
315 int i, nx, ny; | |
316 const int index= (my<<ME_MAP_SHIFT) + mx; | |
317 const int t= score_map[(index-(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; | |
318 const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)]; | |
319 const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)]; | |
320 const int b= score_map[(index+(1<<ME_MAP_SHIFT) )&(ME_MAP_SIZE-1)]; | |
321 const int c= score_map[(index )&(ME_MAP_SIZE-1)]; | |
322 int best[8]; | |
323 int best_pos[8][2]; | |
2967 | 324 |
936 | 325 memset(best, 64, sizeof(int)*8); |
326 #if 1 | |
2967 | 327 if(s->me.dia_size>=2){ |
936 | 328 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
329 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
330 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
331 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
332 | |
333 for(ny= -3; ny <= 3; ny++){ | |
334 for(nx= -3; nx <= 3; nx++){ | |
2079 | 335 //FIXME this could overflow (unlikely though) |
336 const int64_t t2= nx*nx*(tr + tl - 2*t) + 4*nx*(tr-tl) + 32*t; | |
337 const int64_t c2= nx*nx*( r + l - 2*c) + 4*nx*( r- l) + 32*c; | |
338 const int64_t b2= nx*nx*(br + bl - 2*b) + 4*nx*(br-bl) + 32*b; | |
339 int score= (ny*ny*(b2 + t2 - 2*c2) + 4*ny*(b2 - t2) + 32*c2 + 512)>>10; | |
936 | 340 int i; |
2967 | 341 |
936 | 342 if((nx&3)==0 && (ny&3)==0) continue; |
2967 | 343 |
2079 | 344 score += (mv_penalty[4*mx + nx - pred_x] + mv_penalty[4*my + ny - pred_y])*penalty_factor; |
2967 | 345 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
346 // if(nx&1) score-=1024*c->penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
347 // if(ny&1) score-=1024*c->penalty_factor; |
2967 | 348 |
936 | 349 for(i=0; i<8; i++){ |
350 if(score < best[i]){ | |
351 memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); | |
352 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); | |
353 best[i]= score; | |
354 best_pos[i][0]= nx + 4*mx; | |
355 best_pos[i][1]= ny + 4*my; | |
356 break; | |
357 } | |
358 } | |
359 } | |
360 } | |
361 }else{ | |
362 int tl; | |
2079 | 363 //FIXME this could overflow (unlikely though) |
936 | 364 const int cx = 4*(r - l); |
2967 | 365 const int cx2= r + l - 2*c; |
936 | 366 const int cy = 4*(b - t); |
367 const int cy2= b + t - 2*c; | |
368 int cxy; | |
2967 | 369 |
936 | 370 if(map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)] == (my<<ME_MAP_MV_BITS) + mx + map_generation && 0){ //FIXME |
371 tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
372 }else{ | |
1950 | 373 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 | 374 } |
2967 | 375 |
376 cxy= 2*tl + (cx + cy)/4 - (cx2 + cy2) - 2*c; | |
377 | |
936 | 378 assert(16*cx2 + 4*cx + 32*c == 32*r); |
379 assert(16*cx2 - 4*cx + 32*c == 32*l); | |
380 assert(16*cy2 + 4*cy + 32*c == 32*b); | |
381 assert(16*cy2 - 4*cy + 32*c == 32*t); | |
382 assert(16*cxy + 16*cy2 + 16*cx2 - 4*cy - 4*cx + 32*c == 32*tl); | |
2967 | 383 |
936 | 384 for(ny= -3; ny <= 3; ny++){ |
385 for(nx= -3; nx <= 3; nx++){ | |
2079 | 386 //FIXME this could overflow (unlikely though) |
936 | 387 int score= ny*nx*cxy + nx*nx*cx2 + ny*ny*cy2 + nx*cx + ny*cy + 32*c; //FIXME factor |
388 int i; | |
2967 | 389 |
936 | 390 if((nx&3)==0 && (ny&3)==0) continue; |
2967 | 391 |
936 | 392 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
|
393 // if(nx&1) score-=32*c->penalty_factor; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
394 // if(ny&1) score-=32*c->penalty_factor; |
2967 | 395 |
936 | 396 for(i=0; i<8; i++){ |
397 if(score < best[i]){ | |
398 memmove(&best[i+1], &best[i], sizeof(int)*(7-i)); | |
399 memmove(&best_pos[i+1][0], &best_pos[i][0], sizeof(int)*2*(7-i)); | |
400 best[i]= score; | |
401 best_pos[i][0]= nx + 4*mx; | |
402 best_pos[i][1]= ny + 4*my; | |
403 break; | |
404 } | |
405 } | |
406 } | |
2967 | 407 } |
936 | 408 } |
954 | 409 for(i=0; i<subpel_quality; i++){ |
936 | 410 nx= best_pos[i][0]; |
411 ny= best_pos[i][1]; | |
412 CHECK_QUARTER_MV(nx&3, ny&3, nx>>2, ny>>2) | |
413 } | |
954 | 414 |
936 | 415 #if 0 |
954 | 416 const int tl= score_map[(index-(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; |
417 const int bl= score_map[(index+(1<<ME_MAP_SHIFT)-1)&(ME_MAP_SIZE-1)]; | |
418 const int tr= score_map[(index-(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
419 const int br= score_map[(index+(1<<ME_MAP_SHIFT)+1)&(ME_MAP_SIZE-1)]; | |
420 // if(l < r && l < t && l < b && l < tl && l < bl && l < tr && l < br && bl < tl){ | |
421 if(tl<br){ | |
422 | |
423 // nx= FFMAX(4*mx - bx, bx - 4*mx); | |
424 // ny= FFMAX(4*my - by, by - 4*my); | |
2967 | 425 |
954 | 426 static int stats[7][7], count; |
427 count++; | |
428 stats[4*mx - bx + 3][4*my - by + 3]++; | |
429 if(256*256*256*64 % count ==0){ | |
430 for(i=0; i<49; i++){ | |
431 if((i%7)==0) printf("\n"); | |
936 | 432 printf("%6d ", stats[0][i]); |
433 } | |
434 printf("\n"); | |
435 } | |
954 | 436 } |
936 | 437 #endif |
438 #else | |
439 | |
440 CHECK_QUARTER_MV(2, 2, mx-1, my-1) | |
2967 | 441 CHECK_QUARTER_MV(0, 2, mx , my-1) |
936 | 442 CHECK_QUARTER_MV(2, 2, mx , my-1) |
443 CHECK_QUARTER_MV(2, 0, mx , my ) | |
444 CHECK_QUARTER_MV(2, 2, mx , my ) | |
445 CHECK_QUARTER_MV(0, 2, mx , my ) | |
446 CHECK_QUARTER_MV(2, 2, mx-1, my ) | |
447 CHECK_QUARTER_MV(2, 0, mx-1, my ) | |
2967 | 448 |
936 | 449 nx= bx; |
450 ny= by; | |
2967 | 451 |
936 | 452 for(i=0; i<8; i++){ |
453 int ox[8]= {0, 1, 1, 1, 0,-1,-1,-1}; | |
454 int oy[8]= {1, 1, 0,-1,-1,-1, 0, 1}; | |
455 CHECK_QUARTER_MV((nx + ox[i])&3, (ny + oy[i])&3, (nx + ox[i])>>2, (ny + oy[i])>>2) | |
456 } | |
457 #endif | |
458 #if 0 | |
459 //outer ring | |
460 CHECK_QUARTER_MV(1, 3, mx-1, my-1) | |
461 CHECK_QUARTER_MV(1, 2, mx-1, my-1) | |
462 CHECK_QUARTER_MV(1, 1, mx-1, my-1) | |
463 CHECK_QUARTER_MV(2, 1, mx-1, my-1) | |
464 CHECK_QUARTER_MV(3, 1, mx-1, my-1) | |
465 CHECK_QUARTER_MV(0, 1, mx , my-1) | |
466 CHECK_QUARTER_MV(1, 1, mx , my-1) | |
467 CHECK_QUARTER_MV(2, 1, mx , my-1) | |
468 CHECK_QUARTER_MV(3, 1, mx , my-1) | |
469 CHECK_QUARTER_MV(3, 2, mx , my-1) | |
470 CHECK_QUARTER_MV(3, 3, mx , my-1) | |
471 CHECK_QUARTER_MV(3, 0, mx , my ) | |
472 CHECK_QUARTER_MV(3, 1, mx , my ) | |
473 CHECK_QUARTER_MV(3, 2, mx , my ) | |
474 CHECK_QUARTER_MV(3, 3, mx , my ) | |
475 CHECK_QUARTER_MV(2, 3, mx , my ) | |
476 CHECK_QUARTER_MV(1, 3, mx , my ) | |
477 CHECK_QUARTER_MV(0, 3, mx , my ) | |
478 CHECK_QUARTER_MV(3, 3, mx-1, my ) | |
479 CHECK_QUARTER_MV(2, 3, mx-1, my ) | |
480 CHECK_QUARTER_MV(1, 3, mx-1, my ) | |
481 CHECK_QUARTER_MV(1, 2, mx-1, my ) | |
482 CHECK_QUARTER_MV(1, 1, mx-1, my ) | |
483 CHECK_QUARTER_MV(1, 0, mx-1, my ) | |
484 #endif | |
485 assert(bx >= xmin*4 && bx <= xmax*4 && by >= ymin*4 && by <= ymax*4); | |
486 | |
487 *mx_ptr = bx; | |
488 *my_ptr = by; | |
489 }else{ | |
490 *mx_ptr =4*mx; | |
491 *my_ptr =4*my; | |
492 } | |
493 | |
494 return dmin; | |
495 } | |
496 | |
497 | |
498 #define CHECK_MV(x,y)\ | |
499 {\ | |
500 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\ | |
501 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\ | |
2072 | 502 assert((x) >= xmin);\ |
503 assert((x) <= xmax);\ | |
504 assert((y) >= ymin);\ | |
505 assert((y) <= ymax);\ | |
948 | 506 /*printf("check_mv %d %d\n", x, y);*/\ |
936 | 507 if(map[index]!=key){\ |
1950 | 508 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 509 map[index]= key;\ |
510 score_map[index]= d;\ | |
511 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\ | |
948 | 512 /*printf("score:%d\n", d);*/\ |
936 | 513 COPY3_IF_LT(dmin, d, best[0], x, best[1], y)\ |
514 }\ | |
515 } | |
516 | |
4259 | 517 #define CHECK_CLIPPED_MV(ax,ay)\ |
948 | 518 {\ |
4248
4be0e20c0eeb
cosmetic (prevent name clashes of variables in a macro with surrounding code)
michael
parents:
4246
diff
changeset
|
519 const int Lx= ax;\ |
4be0e20c0eeb
cosmetic (prevent name clashes of variables in a macro with surrounding code)
michael
parents:
4246
diff
changeset
|
520 const int Ly= ay;\ |
4be0e20c0eeb
cosmetic (prevent name clashes of variables in a macro with surrounding code)
michael
parents:
4246
diff
changeset
|
521 const int Lx2= FFMAX(xmin, FFMIN(Lx, xmax));\ |
4be0e20c0eeb
cosmetic (prevent name clashes of variables in a macro with surrounding code)
michael
parents:
4246
diff
changeset
|
522 const int Ly2= FFMAX(ymin, FFMIN(Ly, ymax));\ |
4be0e20c0eeb
cosmetic (prevent name clashes of variables in a macro with surrounding code)
michael
parents:
4246
diff
changeset
|
523 CHECK_MV(Lx2, Ly2)\ |
948 | 524 } |
525 | |
936 | 526 #define CHECK_MV_DIR(x,y,new_dir)\ |
527 {\ | |
528 const int key= ((y)<<ME_MAP_MV_BITS) + (x) + map_generation;\ | |
529 const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);\ | |
948 | 530 /*printf("check_mv_dir %d %d %d\n", x, y, new_dir);*/\ |
936 | 531 if(map[index]!=key){\ |
1950 | 532 d= cmp(s, x, y, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
936 | 533 map[index]= key;\ |
534 score_map[index]= d;\ | |
535 d += (mv_penalty[((x)<<shift)-pred_x] + mv_penalty[((y)<<shift)-pred_y])*penalty_factor;\ | |
948 | 536 /*printf("score:%d\n", d);*/\ |
936 | 537 if(d<dmin){\ |
538 best[0]=x;\ | |
539 best[1]=y;\ | |
540 dmin=d;\ | |
541 next_dir= new_dir;\ | |
542 }\ | |
543 }\ | |
544 } | |
545 | |
546 #define check(x,y,S,v)\ | |
547 if( (x)<(xmin<<(S)) ) printf("%d %d %d %d %d xmin" #v, xmin, (x), (y), s->mb_x, s->mb_y);\ | |
548 if( (x)>(xmax<<(S)) ) printf("%d %d %d %d %d xmax" #v, xmax, (x), (y), s->mb_x, s->mb_y);\ | |
549 if( (y)<(ymin<<(S)) ) printf("%d %d %d %d %d ymin" #v, ymin, (x), (y), s->mb_x, s->mb_y);\ | |
550 if( (y)>(ymax<<(S)) ) printf("%d %d %d %d %d ymax" #v, ymax, (x), (y), s->mb_x, s->mb_y);\ | |
551 | |
1950 | 552 #define LOAD_COMMON2\ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
553 uint32_t *map= c->map;\ |
1950 | 554 const int qpel= flags&FLAG_QPEL;\ |
555 const int shift= 1+qpel;\ | |
936 | 556 |
4283
d6f83e2f8804
rename always_inline to av_always_inline and move to common.h
mru
parents:
4266
diff
changeset
|
557 static av_always_inline int small_diamond_search(MpegEncContext * s, int *best, int dmin, |
1950 | 558 int src_index, int ref_index, int const penalty_factor, |
559 int size, int h, int flags) | |
936 | 560 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
561 MotionEstContext * const c= &s->me; |
1950 | 562 me_cmp_func cmpf, chroma_cmpf; |
936 | 563 int next_dir=-1; |
1708 | 564 LOAD_COMMON |
1950 | 565 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
566 int map_generation= c->map_generation; |
2967 | 567 |
1950 | 568 cmpf= s->dsp.me_cmp[size]; |
569 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 570 |
948 | 571 { /* ensure that the best point is in the MAP as h/qpel refinement needs it */ |
572 const int key= (best[1]<<ME_MAP_MV_BITS) + best[0] + map_generation; | |
573 const int index= ((best[1]<<ME_MAP_SHIFT) + best[0])&(ME_MAP_SIZE-1); | |
574 if(map[index]!=key){ //this will be executed only very rarey | |
1950 | 575 score_map[index]= cmp(s, best[0], best[1], 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags); |
948 | 576 map[index]= key; |
577 } | |
578 } | |
579 | |
936 | 580 for(;;){ |
581 int d; | |
582 const int dir= next_dir; | |
583 const int x= best[0]; | |
584 const int y= best[1]; | |
585 next_dir=-1; | |
586 | |
587 //printf("%d", dir); | |
588 if(dir!=2 && x>xmin) CHECK_MV_DIR(x-1, y , 0) | |
589 if(dir!=3 && y>ymin) CHECK_MV_DIR(x , y-1, 1) | |
590 if(dir!=0 && x<xmax) CHECK_MV_DIR(x+1, y , 2) | |
591 if(dir!=1 && y<ymax) CHECK_MV_DIR(x , y+1, 3) | |
592 | |
593 if(next_dir==-1){ | |
594 return dmin; | |
595 } | |
596 } | |
597 } | |
598 | |
1950 | 599 static int funny_diamond_search(MpegEncContext * s, int *best, int dmin, |
600 int src_index, int ref_index, int const penalty_factor, | |
601 int size, int h, int flags) | |
948 | 602 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
603 MotionEstContext * const c= &s->me; |
1950 | 604 me_cmp_func cmpf, chroma_cmpf; |
948 | 605 int dia_size; |
1708 | 606 LOAD_COMMON |
1950 | 607 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
608 int map_generation= c->map_generation; |
2967 | 609 |
1950 | 610 cmpf= s->dsp.me_cmp[size]; |
611 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
948 | 612 |
613 for(dia_size=1; dia_size<=4; dia_size++){ | |
614 int dir; | |
615 const int x= best[0]; | |
616 const int y= best[1]; | |
2967 | 617 |
948 | 618 if(dia_size&(dia_size-1)) continue; |
619 | |
620 if( x + dia_size > xmax | |
621 || x - dia_size < xmin | |
622 || y + dia_size > ymax | |
623 || y - dia_size < ymin) | |
624 continue; | |
2967 | 625 |
948 | 626 for(dir= 0; dir<dia_size; dir+=2){ |
627 int d; | |
628 | |
629 CHECK_MV(x + dir , y + dia_size - dir); | |
630 CHECK_MV(x + dia_size - dir, y - dir ); | |
631 CHECK_MV(x - dir , y - dia_size + dir); | |
632 CHECK_MV(x - dia_size + dir, y + dir ); | |
633 } | |
634 | |
635 if(x!=best[0] || y!=best[1]) | |
636 dia_size=0; | |
637 #if 0 | |
638 { | |
639 int dx, dy, i; | |
640 static int stats[8*8]; | |
4001 | 641 dx= FFABS(x-best[0]); |
642 dy= FFABS(y-best[1]); | |
948 | 643 if(dy>dx){ |
644 dx^=dy; dy^=dx; dx^=dy; | |
645 } | |
646 stats[dy*8 + dx] ++; | |
647 if(256*256*256*64 % (stats[0]+1)==0){ | |
648 for(i=0; i<64; i++){ | |
649 if((i&7)==0) printf("\n"); | |
650 printf("%8d ", stats[i]); | |
651 } | |
652 printf("\n"); | |
653 } | |
654 } | |
655 #endif | |
656 } | |
2967 | 657 return dmin; |
948 | 658 } |
659 | |
4255 | 660 static int hex_search(MpegEncContext * s, int *best, int dmin, |
661 int src_index, int ref_index, int const penalty_factor, | |
662 int size, int h, int flags, int dia_size) | |
663 { | |
664 MotionEstContext * const c= &s->me; | |
665 me_cmp_func cmpf, chroma_cmpf; | |
666 LOAD_COMMON | |
667 LOAD_COMMON2 | |
668 int map_generation= c->map_generation; | |
4265
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
669 int x,y,d; |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
670 const int dec= dia_size & (dia_size-1); |
4255 | 671 |
672 cmpf= s->dsp.me_cmp[size]; | |
673 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
674 | |
4265
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
675 for(;dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){ |
4255 | 676 do{ |
677 x= best[0]; | |
678 y= best[1]; | |
4265
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
679 |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
680 CHECK_CLIPPED_MV(x -dia_size , y); |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
681 CHECK_CLIPPED_MV(x+ dia_size , y); |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
682 CHECK_CLIPPED_MV(x+( dia_size>>1), y+dia_size); |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
683 CHECK_CLIPPED_MV(x+( dia_size>>1), y-dia_size); |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
684 if(dia_size>1){ |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
685 CHECK_CLIPPED_MV(x+(-dia_size>>1), y+dia_size); |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
686 CHECK_CLIPPED_MV(x+(-dia_size>>1), y-dia_size); |
4255 | 687 } |
688 }while(best[0] != x || best[1] != y); | |
689 } | |
690 | |
691 return dmin; | |
692 } | |
693 | |
694 static int l2s_dia_search(MpegEncContext * s, int *best, int dmin, | |
695 int src_index, int ref_index, int const penalty_factor, | |
696 int size, int h, int flags) | |
697 { | |
698 MotionEstContext * const c= &s->me; | |
699 me_cmp_func cmpf, chroma_cmpf; | |
700 LOAD_COMMON | |
701 LOAD_COMMON2 | |
702 int map_generation= c->map_generation; | |
4265
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
703 int x,y,i,d; |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
704 int dia_size= c->dia_size&0xFF; |
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
705 const int dec= dia_size & (dia_size-1); |
4255 | 706 static const int hex[8][2]={{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1}, |
707 { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}}; | |
708 | |
709 cmpf= s->dsp.me_cmp[size]; | |
710 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
711 | |
4265
4241e92fb0c7
make hex and large 2 small diamond search half their size instead or -1 if the initial size was a power of 2
michael
parents:
4259
diff
changeset
|
712 for(; dia_size; dia_size= dec ? dia_size-1 : dia_size>>1){ |
4255 | 713 do{ |
714 x= best[0]; | |
715 y= best[1]; | |
716 for(i=0; i<8; i++){ | |
4259 | 717 CHECK_CLIPPED_MV(x+hex[i][0]*dia_size, y+hex[i][1]*dia_size); |
4255 | 718 } |
719 }while(best[0] != x || best[1] != y); | |
720 } | |
721 | |
722 x= best[0]; | |
723 y= best[1]; | |
4259 | 724 CHECK_CLIPPED_MV(x+1, y); |
725 CHECK_CLIPPED_MV(x, y+1); | |
726 CHECK_CLIPPED_MV(x-1, y); | |
727 CHECK_CLIPPED_MV(x, y-1); | |
4255 | 728 |
729 return dmin; | |
730 } | |
731 | |
4249 | 732 static int umh_search(MpegEncContext * s, int *best, int dmin, |
733 int src_index, int ref_index, int const penalty_factor, | |
734 int size, int h, int flags) | |
735 { | |
736 MotionEstContext * const c= &s->me; | |
737 me_cmp_func cmpf, chroma_cmpf; | |
738 LOAD_COMMON | |
739 LOAD_COMMON2 | |
740 int map_generation= c->map_generation; | |
741 int x,y,x2,y2, i, j, d; | |
4256 | 742 const int dia_size= c->dia_size&0xFE; |
4249 | 743 static const int hex[16][2]={{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2}, |
744 { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2}, | |
745 {-2, 3}, { 0, 4}, { 2, 3}, | |
4250 | 746 {-2,-3}, { 0,-4}, { 2,-3},}; |
4249 | 747 |
748 cmpf= s->dsp.me_cmp[size]; | |
749 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
750 | |
751 x= best[0]; | |
752 y= best[1]; | |
4256 | 753 for(x2=FFMAX(x-dia_size+1, xmin); x2<=FFMIN(x+dia_size-1,xmax); x2+=2){ |
4249 | 754 CHECK_MV(x2, y); |
755 } | |
4256 | 756 for(y2=FFMAX(y-dia_size/2+1, ymin); y2<=FFMIN(y+dia_size/2-1,ymax); y2+=2){ |
4249 | 757 CHECK_MV(x, y2); |
758 } | |
759 | |
760 x= best[0]; | |
761 y= best[1]; | |
762 for(y2=FFMAX(y-2, ymin); y2<=FFMIN(y+2,ymax); y2++){ | |
763 for(x2=FFMAX(x-2, xmin); x2<=FFMIN(x+2,xmax); x2++){ | |
764 CHECK_MV(x2, y2); | |
765 } | |
766 } | |
767 | |
768 //FIXME prevent the CLIP stuff | |
769 | |
4256 | 770 for(j=1; j<=dia_size/4; j++){ |
4249 | 771 for(i=0; i<16; i++){ |
4259 | 772 CHECK_CLIPPED_MV(x+hex[i][0]*j, y+hex[i][1]*j); |
4249 | 773 } |
774 } | |
775 | |
4266
8a50de4eafca
10l umh search needs hex size 2 now after the last change
michael
parents:
4265
diff
changeset
|
776 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, 2); |
4249 | 777 } |
778 | |
948 | 779 #define SAB_CHECK_MV(ax,ay)\ |
780 {\ | |
781 const int key= ((ay)<<ME_MAP_MV_BITS) + (ax) + map_generation;\ | |
782 const int index= (((ay)<<ME_MAP_SHIFT) + (ax))&(ME_MAP_SIZE-1);\ | |
783 /*printf("sab check %d %d\n", ax, ay);*/\ | |
784 if(map[index]!=key){\ | |
1950 | 785 d= cmp(s, ax, ay, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags);\ |
948 | 786 map[index]= key;\ |
787 score_map[index]= d;\ | |
788 d += (mv_penalty[((ax)<<shift)-pred_x] + mv_penalty[((ay)<<shift)-pred_y])*penalty_factor;\ | |
789 /*printf("score: %d\n", d);*/\ | |
790 if(d < minima[minima_count-1].height){\ | |
791 int j=0;\ | |
792 \ | |
793 while(d >= minima[j].height) j++;\ | |
794 \ | |
795 memmove(&minima [j+1], &minima [j], (minima_count - j - 1)*sizeof(Minima));\ | |
796 \ | |
797 minima[j].checked= 0;\ | |
798 minima[j].height= d;\ | |
799 minima[j].x= ax;\ | |
800 minima[j].y= ay;\ | |
801 \ | |
802 i=-1;\ | |
803 continue;\ | |
804 }\ | |
805 }\ | |
806 } | |
807 | |
2113
07a663d46be2
shape-adaptive diamond + prediction crash patch by (Loren Merritt <lorenm at u dot washington dot edu>)
michael
parents:
2079
diff
changeset
|
808 #define MAX_SAB_SIZE ME_MAP_SIZE |
1950 | 809 static int sab_diamond_search(MpegEncContext * s, int *best, int dmin, |
810 int src_index, int ref_index, int const penalty_factor, | |
811 int size, int h, int flags) | |
948 | 812 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
813 MotionEstContext * const c= &s->me; |
1950 | 814 me_cmp_func cmpf, chroma_cmpf; |
948 | 815 Minima minima[MAX_SAB_SIZE]; |
4001 | 816 const int minima_count= FFABS(c->dia_size); |
948 | 817 int i, j; |
1708 | 818 LOAD_COMMON |
1950 | 819 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
820 int map_generation= c->map_generation; |
2967 | 821 |
1950 | 822 cmpf= s->dsp.me_cmp[size]; |
823 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
2967 | 824 |
4298
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
825 /*Note j<MAX_SAB_SIZE is needed if MAX_SAB_SIZE < ME_MAP_SIZE as j can |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
826 become larger due to MVs overflowing their ME_MAP_MV_BITS bits space in map |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
827 */ |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
828 for(j=i=0; i<ME_MAP_SIZE && j<MAX_SAB_SIZE; i++){ |
948 | 829 uint32_t key= map[i]; |
830 | |
831 key += (1<<(ME_MAP_MV_BITS-1)) + (1<<(2*ME_MAP_MV_BITS-1)); | |
2967 | 832 |
948 | 833 if((key&((-1)<<(2*ME_MAP_MV_BITS))) != map_generation) continue; |
2967 | 834 |
948 | 835 minima[j].height= score_map[i]; |
836 minima[j].x= key & ((1<<ME_MAP_MV_BITS)-1); key>>=ME_MAP_MV_BITS; | |
837 minima[j].y= key & ((1<<ME_MAP_MV_BITS)-1); | |
838 minima[j].x-= (1<<(ME_MAP_MV_BITS-1)); | |
839 minima[j].y-= (1<<(ME_MAP_MV_BITS-1)); | |
4298
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
840 |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
841 // all entries in map should be in range except if the mv overflows their ME_MAP_MV_BITS bits space |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
842 if( minima[j].x > xmax || minima[j].x < xmin |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
843 || minima[j].y > ymax || minima[j].y < ymin) |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
844 continue; |
bba6e75e026b
mv overflow in map fix (untested except regression tests)
michael
parents:
4283
diff
changeset
|
845 |
948 | 846 minima[j].checked=0; |
847 if(minima[j].x || minima[j].y) | |
848 minima[j].height+= (mv_penalty[((minima[j].x)<<shift)-pred_x] + mv_penalty[((minima[j].y)<<shift)-pred_y])*penalty_factor; | |
2967 | 849 |
948 | 850 j++; |
851 } | |
2967 | 852 |
948 | 853 qsort(minima, j, sizeof(Minima), minima_cmp); |
2967 | 854 |
948 | 855 for(; j<minima_count; j++){ |
856 minima[j].height=256*256*256*64; | |
857 minima[j].checked=0; | |
858 minima[j].x= minima[j].y=0; | |
859 } | |
2967 | 860 |
948 | 861 for(i=0; i<minima_count; i++){ |
862 const int x= minima[i].x; | |
863 const int y= minima[i].y; | |
864 int d; | |
2967 | 865 |
948 | 866 if(minima[i].checked) continue; |
2967 | 867 |
948 | 868 if( x >= xmax || x <= xmin |
869 || y >= ymax || y <= ymin) | |
870 continue; | |
871 | |
872 SAB_CHECK_MV(x-1, y) | |
873 SAB_CHECK_MV(x+1, y) | |
874 SAB_CHECK_MV(x , y-1) | |
875 SAB_CHECK_MV(x , y+1) | |
2967 | 876 |
948 | 877 minima[i].checked= 1; |
878 } | |
2967 | 879 |
948 | 880 best[0]= minima[0].x; |
881 best[1]= minima[0].y; | |
882 dmin= minima[0].height; | |
2967 | 883 |
948 | 884 if( best[0] < xmax && best[0] > xmin |
885 && best[1] < ymax && best[1] > ymin){ | |
886 int d; | |
887 //ensure that the refernece samples for hpel refinement are in the map | |
888 CHECK_MV(best[0]-1, best[1]) | |
889 CHECK_MV(best[0]+1, best[1]) | |
890 CHECK_MV(best[0], best[1]-1) | |
891 CHECK_MV(best[0], best[1]+1) | |
892 } | |
2967 | 893 return dmin; |
948 | 894 } |
895 | |
1950 | 896 static int var_diamond_search(MpegEncContext * s, int *best, int dmin, |
897 int src_index, int ref_index, int const penalty_factor, | |
898 int size, int h, int flags) | |
936 | 899 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
900 MotionEstContext * const c= &s->me; |
1950 | 901 me_cmp_func cmpf, chroma_cmpf; |
948 | 902 int dia_size; |
1708 | 903 LOAD_COMMON |
1950 | 904 LOAD_COMMON2 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
905 int map_generation= c->map_generation; |
2967 | 906 |
1950 | 907 cmpf= s->dsp.me_cmp[size]; |
908 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 909 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
910 for(dia_size=1; dia_size<=c->dia_size; dia_size++){ |
936 | 911 int dir, start, end; |
912 const int x= best[0]; | |
913 const int y= best[1]; | |
914 | |
915 start= FFMAX(0, y + dia_size - ymax); | |
948 | 916 end = FFMIN(dia_size, xmax - x + 1); |
936 | 917 for(dir= start; dir<end; dir++){ |
918 int d; | |
919 | |
920 //check(x + dir,y + dia_size - dir,0, a0) | |
921 CHECK_MV(x + dir , y + dia_size - dir); | |
922 } | |
923 | |
924 start= FFMAX(0, x + dia_size - xmax); | |
948 | 925 end = FFMIN(dia_size, y - ymin + 1); |
936 | 926 for(dir= start; dir<end; dir++){ |
927 int d; | |
928 | |
929 //check(x + dia_size - dir, y - dir,0, a1) | |
930 CHECK_MV(x + dia_size - dir, y - dir ); | |
931 } | |
932 | |
933 start= FFMAX(0, -y + dia_size + ymin ); | |
948 | 934 end = FFMIN(dia_size, x - xmin + 1); |
936 | 935 for(dir= start; dir<end; dir++){ |
936 int d; | |
937 | |
938 //check(x - dir,y - dia_size + dir,0, a2) | |
939 CHECK_MV(x - dir , y - dia_size + dir); | |
940 } | |
941 | |
942 start= FFMAX(0, -x + dia_size + xmin ); | |
948 | 943 end = FFMIN(dia_size, ymax - y + 1); |
936 | 944 for(dir= start; dir<end; dir++){ |
945 int d; | |
946 | |
947 //check(x - dia_size + dir, y + dir,0, a3) | |
948 CHECK_MV(x - dia_size + dir, y + dir ); | |
949 } | |
950 | |
951 if(x!=best[0] || y!=best[1]) | |
952 dia_size=0; | |
948 | 953 #if 0 |
954 { | |
955 int dx, dy, i; | |
956 static int stats[8*8]; | |
4001 | 957 dx= FFABS(x-best[0]); |
958 dy= FFABS(y-best[1]); | |
948 | 959 stats[dy*8 + dx] ++; |
960 if(256*256*256*64 % (stats[0]+1)==0){ | |
961 for(i=0; i<64; i++){ | |
962 if((i&7)==0) printf("\n"); | |
963 printf("%6d ", stats[i]); | |
964 } | |
965 printf("\n"); | |
966 } | |
967 } | |
968 #endif | |
936 | 969 } |
2967 | 970 return dmin; |
936 | 971 } |
972 | |
4283
d6f83e2f8804
rename always_inline to av_always_inline and move to common.h
mru
parents:
4266
diff
changeset
|
973 static av_always_inline int diamond_search(MpegEncContext * s, int *best, int dmin, |
1950 | 974 int src_index, int ref_index, int const penalty_factor, |
975 int size, int h, int flags){ | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
976 MotionEstContext * const c= &s->me; |
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
977 if(c->dia_size==-1) |
4256 | 978 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
|
979 else if(c->dia_size<-1) |
1950 | 980 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
|
981 else if(c->dia_size<2) |
1950 | 982 return small_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
4256 | 983 else if(c->dia_size>768) |
984 return umh_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); | |
4255 | 985 else if(c->dia_size>512) |
986 return hex_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags, c->dia_size&0xFF); | |
987 else if(c->dia_size>256) | |
988 return l2s_dia_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); | |
1950 | 989 else |
990 return var_diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); | |
991 } | |
992 | |
4757
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
993 /*! |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
994 \param P[10][2] a list of candidate mvs to check before starting the |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
995 iterative search. If one of the candidates is close to the optimal mv, then |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
996 it takes fewer iterations. And it increases the chance that we find the |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
997 optimal mv. |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
998 */ |
4283
d6f83e2f8804
rename always_inline to av_always_inline and move to common.h
mru
parents:
4266
diff
changeset
|
999 static av_always_inline int epzs_motion_search_internal(MpegEncContext * s, int *mx_ptr, int *my_ptr, |
2967 | 1000 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], |
2184 | 1001 int ref_mv_scale, int flags, int size, int h) |
936 | 1002 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1003 MotionEstContext * const c= &s->me; |
4757
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1004 int best[2]={0, 0}; /*!< x and y coordinates of the best motion vector. |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1005 i.e. the difference between the position of the |
4758 | 1006 block currently being encoded and the position of |
4757
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1007 the block chosen to predict it from. */ |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1008 int d; ///< the score (cmp + penalty) of any given mv |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1009 int dmin; /*!< the best value of d, i.e. the score |
e511820c4a97
Add doxy comments, based on Loren's explanations posted here:
gpoirier
parents:
4326
diff
changeset
|
1010 corresponding to the mv stored in best[]. */ |
936 | 1011 int map_generation; |
2226 | 1012 int penalty_factor; |
1708 | 1013 const int ref_mv_stride= s->mb_stride; //pass as arg FIXME |
1014 const int ref_mv_xy= s->mb_x + s->mb_y*ref_mv_stride; //add to last_mv beforepassing FIXME | |
1950 | 1015 me_cmp_func cmpf, chroma_cmpf; |
2967 | 1016 |
1950 | 1017 LOAD_COMMON |
1018 LOAD_COMMON2 | |
2967 | 1019 |
2226 | 1020 if(c->pre_pass){ |
1021 penalty_factor= c->pre_penalty_factor; | |
1022 cmpf= s->dsp.me_pre_cmp[size]; | |
1023 chroma_cmpf= s->dsp.me_pre_cmp[size+1]; | |
1024 }else{ | |
1025 penalty_factor= c->penalty_factor; | |
1026 cmpf= s->dsp.me_cmp[size]; | |
1027 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
1028 } | |
2967 | 1029 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1030 map_generation= update_map_generation(c); |
936 | 1031 |
2184 | 1032 assert(cmpf); |
1950 | 1033 dmin= cmp(s, 0, 0, 0, 0, size, h, ref_index, src_index, cmpf, chroma_cmpf, flags); |
936 | 1034 map[0]= map_generation; |
1035 score_map[0]= dmin; | |
4313
13c897abcab3
fix special casing of the 0,0 MV for b frames (slight PSNR/bitrate gain)
michael
parents:
4312
diff
changeset
|
1036 |
13c897abcab3
fix special casing of the 0,0 MV for b frames (slight PSNR/bitrate gain)
michael
parents:
4312
diff
changeset
|
1037 //FIXME precalc first term below? |
4326 | 1038 if((s->pict_type == B_TYPE && !(c->flags & FLAG_DIRECT)) || s->flags&CODEC_FLAG_MV0) |
4312
eb0ae1ce40a5
dont favor the zero MV if mv0 is used (psnr per bitrate gains ranging from 0 to 0.14, most are <=0.04 though)
michael
parents:
4298
diff
changeset
|
1039 dmin += (mv_penalty[pred_x] + mv_penalty[pred_y])*penalty_factor; |
936 | 1040 |
1041 /* first line */ | |
1799 | 1042 if (s->first_slice_line) { |
936 | 1043 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
4259 | 1044 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
948 | 1045 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
936 | 1046 }else{ |
3293 | 1047 if(dmin<((h*h*s->avctx->mv0_threshold)>>8) |
1048 && ( P_LEFT[0] |P_LEFT[1] | |
936 | 1049 |P_TOP[0] |P_TOP[1] |
948 | 1050 |P_TOPRIGHT[0]|P_TOPRIGHT[1])==0){ |
936 | 1051 *mx_ptr= 0; |
1052 *my_ptr= 0; | |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1053 c->skip=1; |
936 | 1054 return dmin; |
1055 } | |
4246
a579dae361e2
1 step diamond search around the median MV predictor
michael
parents:
4001
diff
changeset
|
1056 CHECK_MV( P_MEDIAN[0] >>shift , P_MEDIAN[1] >>shift) |
4259 | 1057 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)-1) |
1058 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift) , (P_MEDIAN[1]>>shift)+1) | |
1059 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)-1, (P_MEDIAN[1]>>shift) ) | |
1060 CHECK_CLIPPED_MV((P_MEDIAN[0]>>shift)+1, (P_MEDIAN[1]>>shift) ) | |
1061 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, | |
4257 | 1062 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
1063 CHECK_MV(P_LEFT[0] >>shift, P_LEFT[1] >>shift) | |
1064 CHECK_MV(P_TOP[0] >>shift, P_TOP[1] >>shift) | |
1065 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
936 | 1066 } |
2184 | 1067 if(dmin>h*h*4){ |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1068 if(c->pre_pass){ |
4259 | 1069 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-1][0]*ref_mv_scale + (1<<15))>>16, |
952 | 1070 (last_mv[ref_mv_xy-1][1]*ref_mv_scale + (1<<15))>>16) |
1799 | 1071 if(!s->first_slice_line) |
4259 | 1072 CHECK_CLIPPED_MV((last_mv[ref_mv_xy-ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1799 | 1073 (last_mv[ref_mv_xy-ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) |
952 | 1074 }else{ |
4259 | 1075 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, |
952 | 1076 (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
|
1077 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
4259 | 1078 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1799 | 1079 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) |
952 | 1080 } |
936 | 1081 } |
948 | 1082 |
2015
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
1083 if(c->avctx->last_predictor_count){ |
3ab8f3e2ae6a
moving motion estimation specific variables from MpegEncContext -> MotionEstContext
michael
parents:
2014
diff
changeset
|
1084 const int count= c->avctx->last_predictor_count; |
948 | 1085 const int xstart= FFMAX(0, s->mb_x - count); |
1086 const int ystart= FFMAX(0, s->mb_y - count); | |
1087 const int xend= FFMIN(s->mb_width , s->mb_x + count + 1); | |
1088 const int yend= FFMIN(s->mb_height, s->mb_y + count + 1); | |
1089 int mb_y; | |
936 | 1090 |
948 | 1091 for(mb_y=ystart; mb_y<yend; mb_y++){ |
1092 int mb_x; | |
1093 for(mb_x=xstart; mb_x<xend; mb_x++){ | |
1094 const int xy= mb_x + 1 + (mb_y + 1)*ref_mv_stride; | |
1095 int mx= (last_mv[xy][0]*ref_mv_scale + (1<<15))>>16; | |
1096 int my= (last_mv[xy][1]*ref_mv_scale + (1<<15))>>16; | |
1097 | |
1098 if(mx>xmax || mx<xmin || my>ymax || my<ymin) continue; | |
1099 CHECK_MV(mx,my) | |
936 | 1100 } |
1101 } | |
1102 } | |
948 | 1103 |
936 | 1104 //check(best[0],best[1],0, b0) |
1950 | 1105 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
936 | 1106 |
1107 //check(best[0],best[1],0, b1) | |
1108 *mx_ptr= best[0]; | |
2967 | 1109 *my_ptr= best[1]; |
936 | 1110 |
1111 // printf("%d %d %d \n", best[0], best[1], dmin); | |
1112 return dmin; | |
1113 } | |
1114 | |
1950 | 1115 //this function is dedicated to the braindamaged gcc |
2184 | 1116 inline int ff_epzs_motion_search(MpegEncContext * s, int *mx_ptr, int *my_ptr, |
2967 | 1117 int P[10][2], int src_index, int ref_index, int16_t (*last_mv)[2], |
2184 | 1118 int ref_mv_scale, int size, int h) |
1950 | 1119 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1120 MotionEstContext * const c= &s->me; |
1950 | 1121 //FIXME convert other functions in the same way if faster |
2184 | 1122 if(c->flags==0 && h==16 && size==0){ |
1123 return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, 0, 0, 16); | |
1950 | 1124 // case FLAG_QPEL: |
1125 // return epzs_motion_search_internal(s, mx_ptr, my_ptr, P, src_index, ref_index, last_mv, ref_mv_scale, FLAG_QPEL); | |
2184 | 1126 }else{ |
1127 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 | 1128 } |
1129 } | |
1130 | |
1131 static int epzs_motion_search4(MpegEncContext * s, | |
1132 int *mx_ptr, int *my_ptr, int P[10][2], | |
2967 | 1133 int src_index, int ref_index, int16_t (*last_mv)[2], |
1950 | 1134 int ref_mv_scale) |
936 | 1135 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1136 MotionEstContext * const c= &s->me; |
936 | 1137 int best[2]={0, 0}; |
2967 | 1138 int d, dmin; |
936 | 1139 int map_generation; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1140 const int penalty_factor= c->penalty_factor; |
936 | 1141 const int size=1; |
1708 | 1142 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
|
1143 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
|
1144 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; |
1950 | 1145 me_cmp_func cmpf, chroma_cmpf; |
1708 | 1146 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1147 int flags= c->flags; |
1950 | 1148 LOAD_COMMON2 |
2967 | 1149 |
1950 | 1150 cmpf= s->dsp.me_cmp[size]; |
1151 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
936 | 1152 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1153 map_generation= update_map_generation(c); |
936 | 1154 |
1155 dmin = 1000000; | |
2967 | 1156 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); |
936 | 1157 /* first line */ |
1799 | 1158 if (s->first_slice_line) { |
2979 | 1159 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
4259 | 1160 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
948 | 1161 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
936 | 1162 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) |
1163 }else{ | |
1164 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1165 //FIXME try some early stop | |
4257 | 1166 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) |
1167 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) | |
1168 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) | |
1169 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
4259 | 1170 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
4257 | 1171 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
936 | 1172 } |
1173 if(dmin>64*4){ | |
4259 | 1174 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, |
948 | 1175 (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
|
1176 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
4259 | 1177 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1799 | 1178 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) |
936 | 1179 } |
1180 | |
1950 | 1181 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
1708 | 1182 |
1183 *mx_ptr= best[0]; | |
2967 | 1184 *my_ptr= best[1]; |
1708 | 1185 |
1186 // printf("%d %d %d \n", best[0], best[1], dmin); | |
1187 return dmin; | |
1188 } | |
1189 | |
1190 //try to merge with above FIXME (needs PSNR test) | |
1950 | 1191 static int epzs_motion_search2(MpegEncContext * s, |
1192 int *mx_ptr, int *my_ptr, int P[10][2], | |
2967 | 1193 int src_index, int ref_index, int16_t (*last_mv)[2], |
1950 | 1194 int ref_mv_scale) |
1708 | 1195 { |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1196 MotionEstContext * const c= &s->me; |
1708 | 1197 int best[2]={0, 0}; |
2967 | 1198 int d, dmin; |
1708 | 1199 int map_generation; |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1200 const int penalty_factor= c->penalty_factor; |
1708 | 1201 const int size=0; //FIXME pass as arg |
1202 const int h=8; | |
1203 const int ref_mv_stride= s->mb_stride; | |
1204 const int ref_mv_xy= s->mb_x + s->mb_y *ref_mv_stride; | |
1950 | 1205 me_cmp_func cmpf, chroma_cmpf; |
1708 | 1206 LOAD_COMMON |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1207 int flags= c->flags; |
1950 | 1208 LOAD_COMMON2 |
2967 | 1209 |
1950 | 1210 cmpf= s->dsp.me_cmp[size]; |
1211 chroma_cmpf= s->dsp.me_cmp[size+1]; | |
1708 | 1212 |
2014
15c885db82a8
reduce dependancy between motion estimation and MpegEncContext
michael
parents:
1950
diff
changeset
|
1213 map_generation= update_map_generation(c); |
1708 | 1214 |
1215 dmin = 1000000; | |
2967 | 1216 //printf("%d %d %d %d //",xmin, ymin, xmax, ymax); |
1708 | 1217 /* first line */ |
1799 | 1218 if (s->first_slice_line) { |
2979 | 1219 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) |
4259 | 1220 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
1708 | 1221 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
1222 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1223 }else{ | |
1224 CHECK_MV(P_MV1[0]>>shift, P_MV1[1]>>shift) | |
1225 //FIXME try some early stop | |
4257 | 1226 CHECK_MV(P_MEDIAN[0]>>shift, P_MEDIAN[1]>>shift) |
1227 CHECK_MV(P_LEFT[0]>>shift, P_LEFT[1]>>shift) | |
1228 CHECK_MV(P_TOP[0]>>shift, P_TOP[1]>>shift) | |
1229 CHECK_MV(P_TOPRIGHT[0]>>shift, P_TOPRIGHT[1]>>shift) | |
4259 | 1230 CHECK_CLIPPED_MV((last_mv[ref_mv_xy][0]*ref_mv_scale + (1<<15))>>16, |
4257 | 1231 (last_mv[ref_mv_xy][1]*ref_mv_scale + (1<<15))>>16) |
1708 | 1232 } |
1233 if(dmin>64*4){ | |
4259 | 1234 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+1][0]*ref_mv_scale + (1<<15))>>16, |
1708 | 1235 (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
|
1236 if(s->mb_y+1<s->end_mb_y) //FIXME replace at least with last_slice_line |
4259 | 1237 CHECK_CLIPPED_MV((last_mv[ref_mv_xy+ref_mv_stride][0]*ref_mv_scale + (1<<15))>>16, |
1799 | 1238 (last_mv[ref_mv_xy+ref_mv_stride][1]*ref_mv_scale + (1<<15))>>16) |
1708 | 1239 } |
1240 | |
1950 | 1241 dmin= diamond_search(s, best, dmin, src_index, ref_index, penalty_factor, size, h, flags); |
948 | 1242 |
936 | 1243 *mx_ptr= best[0]; |
2967 | 1244 *my_ptr= best[1]; |
936 | 1245 |
1246 // printf("%d %d %d \n", best[0], best[1], dmin); | |
1247 return dmin; | |
1248 } |