1 | /*
|
---|
2 | * Motion estimation
|
---|
3 | * Copyright (c) 2000,2001 Fabrice Bellard.
|
---|
4 | * Copyright (c) 2002-2004 Michael Niedermayer
|
---|
5 | *
|
---|
6 | *
|
---|
7 | * This library is free software; you can redistribute it and/or
|
---|
8 | * modify it under the terms of the GNU Lesser General Public
|
---|
9 | * License as published by the Free Software Foundation; either
|
---|
10 | * version 2 of the License, or (at your option) any later version.
|
---|
11 | *
|
---|
12 | * This library is distributed in the hope that it will be useful,
|
---|
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
|
---|
18 | * License along with this library; if not, write to the Free Software
|
---|
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
20 | *
|
---|
21 | * new Motion Estimation (X1/EPZS) by Michael Niedermayer <[email protected]>
|
---|
22 | */
|
---|
23 |
|
---|
24 | /**
|
---|
25 | * @file motion_est.c
|
---|
26 | * Motion estimation.
|
---|
27 | */
|
---|
28 |
|
---|
29 | #include <stdlib.h>
|
---|
30 | #include <stdio.h>
|
---|
31 | #include <limits.h>
|
---|
32 | #include "avcodec.h"
|
---|
33 | #include "dsputil.h"
|
---|
34 | #include "mpegvideo.h"
|
---|
35 |
|
---|
36 | #undef NDEBUG
|
---|
37 | #include <assert.h>
|
---|
38 |
|
---|
39 | #define SQ(a) ((a)*(a))
|
---|
40 |
|
---|
41 | #define P_LEFT P[1]
|
---|
42 | #define P_TOP P[2]
|
---|
43 | #define P_TOPRIGHT P[3]
|
---|
44 | #define P_MEDIAN P[4]
|
---|
45 | #define P_MV1 P[9]
|
---|
46 |
|
---|
47 | static inline int sad_hpel_motion_search(MpegEncContext * s,
|
---|
48 | int *mx_ptr, int *my_ptr, int dmin,
|
---|
49 | int src_index, int ref_index,
|
---|
50 | int size, int h);
|
---|
51 |
|
---|
52 | static inline int update_map_generation(MotionEstContext *c)
|
---|
53 | {
|
---|
54 | c->map_generation+= 1<<(ME_MAP_MV_BITS*2);
|
---|
55 | if(c->map_generation==0){
|
---|
56 | c->map_generation= 1<<(ME_MAP_MV_BITS*2);
|
---|
57 | memset(c->map, 0, sizeof(uint32_t)*ME_MAP_SIZE);
|
---|
58 | }
|
---|
59 | return c->map_generation;
|
---|
60 | }
|
---|
61 |
|
---|
62 | /* shape adaptive search stuff */
|
---|
63 | typedef struct Minima{
|
---|
64 | int height;
|
---|
65 | int x, y;
|
---|
66 | int checked;
|
---|
67 | }Minima;
|
---|
68 |
|
---|
69 | static int minima_cmp(const void *a, const void *b){
|
---|
70 | const Minima *da = (const Minima *) a;
|
---|
71 | const Minima *db = (const Minima *) b;
|
---|
72 |
|
---|
73 | return da->height - db->height;
|
---|
74 | }
|
---|
75 |
|
---|
76 | #define FLAG_QPEL 1 //must be 1
|
---|
77 | #define FLAG_CHROMA 2
|
---|
78 | #define FLAG_DIRECT 4
|
---|
79 |
|
---|
80 | static inline void init_ref(MotionEstContext *c, uint8_t *src[3], uint8_t *ref[3], uint8_t *ref2[3], int x, int y, int ref_index){
|
---|
81 | const int offset[3]= {
|
---|
82 | y*c-> stride + x,
|
---|
83 | ((y*c->uvstride + x)>>1),
|
---|
84 | ((y*c->uvstride + x)>>1),
|
---|
85 | };
|
---|
86 | int i;
|
---|
87 | for(i=0; i<3; i++){
|
---|
88 | c->src[0][i]= src [i] + offset[i];
|
---|
89 | c->ref[0][i]= ref [i] + offset[i];
|
---|
90 | }
|
---|
91 | if(ref_index){
|
---|
92 | for(i=0; i<3; i++){
|
---|
93 | c->ref[ref_index][i]= ref2[i] + offset[i];
|
---|
94 | }
|
---|
95 | }
|
---|
96 | }
|
---|
97 |
|
---|
98 | static int get_flags(MotionEstContext *c, int direct, int chroma){
|
---|
99 | return ((c->avctx->flags&CODEC_FLAG_QPEL) ? FLAG_QPEL : 0)
|
---|
100 | + (direct ? FLAG_DIRECT : 0)
|
---|
101 | + (chroma ? FLAG_CHROMA : 0);
|
---|
102 | }
|
---|
103 |
|
---|
104 | static always_inline int cmp(MpegEncContext *s, const int x, const int y, const int subx, const int suby,
|
---|
105 | const int size, const int h, int ref_index, int src_index,
|
---|
106 | me_cmp_func cmp_func, me_cmp_func chroma_cmp_func, const int flags){
|
---|
107 | MotionEstContext * const c= &s->me;
|
---|
108 | const int stride= c->stride;
|
---|
109 | const int uvstride= c->uvstride;
|
---|
110 | const int qpel= flags&FLAG_QPEL;
|
---|
111 | const int chroma= flags&FLAG_CHROMA;
|
---|
112 | const int dxy= subx + (suby<<(1+qpel)); //FIXME log2_subpel?
|
---|
113 | const int hx= subx + (x<<(1+qpel));
|
---|
114 | const int hy= suby + (y<<(1+qpel));
|
---|
115 | uint8_t * const * const ref= c->ref[ref_index];
|
---|
116 | uint8_t * const * const src= c->src[src_index];
|
---|
117 | int d;
|
---|
118 | //FIXME check chroma 4mv, (no crashes ...)
|
---|
119 | if(flags&FLAG_DIRECT){
|
---|
120 | if(x >= c->xmin && hx <= c->xmax<<(qpel+1) && y >= c->ymin && hy <= c->ymax<<(qpel+1)){
|
---|
121 | const int time_pp= s->pp_time;
|
---|
122 | const int time_pb= s->pb_time;
|
---|
123 | const int mask= 2*qpel+1;
|
---|
124 | if(s->mv_type==MV_TYPE_8X8){
|
---|
125 | int i;
|
---|
126 | for(i=0; i<4; i++){
|
---|
127 | int fx = c->direct_basis_mv[i][0] + hx;
|
---|
128 | int fy = c->direct_basis_mv[i][1] + hy;
|
---|
129 | int bx = hx ? fx - c->co_located_mv[i][0] : c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(qpel+4));
|
---|
130 | int by = hy ? fy - c->co_located_mv[i][1] : c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(qpel+4));
|
---|
131 | int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
|
---|
132 | int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
|
---|
133 |
|
---|
134 | uint8_t *dst= c->temp + 8*(i&1) + 8*stride*(i>>1);
|
---|
135 | if(qpel){
|
---|
136 | c->qpel_put[1][fxy](dst, ref[0] + (fx>>2) + (fy>>2)*stride, stride);
|
---|
137 | c->qpel_avg[1][bxy](dst, ref[8] + (bx>>2) + (by>>2)*stride, stride);
|
---|
138 | }else{
|
---|
139 | c->hpel_put[1][fxy](dst, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 8);
|
---|
140 | c->hpel_avg[1][bxy](dst, ref[8] + (bx>>1) + (by>>1)*stride, stride, 8);
|
---|
141 | }
|
---|
142 | }
|
---|
143 | }else{
|
---|
144 | int fx = c->direct_basis_mv[0][0] + hx;
|
---|
145 | int fy = c->direct_basis_mv[0][1] + hy;
|
---|
146 | int bx = hx ? fx - c->co_located_mv[0][0] : (c->co_located_mv[0][0]*(time_pb - time_pp)/time_pp);
|
---|
147 | int by = hy ? fy - c->co_located_mv[0][1] : (c->co_located_mv[0][1]*(time_pb - time_pp)/time_pp);
|
---|
148 | int fxy= (fx&mask) + ((fy&mask)<<(qpel+1));
|
---|
149 | int bxy= (bx&mask) + ((by&mask)<<(qpel+1));
|
---|
150 |
|
---|
151 | if(qpel){
|
---|
152 | c->qpel_put[1][fxy](c->temp , ref[0] + (fx>>2) + (fy>>2)*stride , stride);
|
---|
153 | c->qpel_put[1][fxy](c->temp + 8 , ref[0] + (fx>>2) + (fy>>2)*stride + 8 , stride);
|
---|
154 | c->qpel_put[1][fxy](c->temp + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8*stride, stride);
|
---|
155 | c->qpel_put[1][fxy](c->temp + 8 + 8*stride, ref[0] + (fx>>2) + (fy>>2)*stride + 8 + 8*stride, stride);
|
---|
156 | c->qpel_avg[1][bxy](c->temp , ref[8] + (bx>>2) + (by>>2)*stride , stride);
|
---|
157 | c->qpel_avg[1][bxy](c->temp + 8 , ref[8] + (bx>>2) + (by>>2)*stride + 8 , stride);
|
---|
158 | c->qpel_avg[1][bxy](c->temp + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8*stride, stride);
|
---|
159 | c->qpel_avg[1][bxy](c->temp + 8 + 8*stride, ref[8] + (bx>>2) + (by>>2)*stride + 8 + 8*stride, stride);
|
---|
160 | }else{
|
---|
161 | assert((fx>>1) + 16*s->mb_x >= -16);
|
---|
162 | assert((fy>>1) + 16*s->mb_y >= -16);
|
---|
163 | assert((fx>>1) + 16*s->mb_x <= s->width);
|
---|
164 | assert((fy>>1) + 16*s->mb_y <= s->height);
|
---|
165 | assert((bx>>1) + 16*s->mb_x >= -16);
|
---|
166 | assert((by>>1) + 16*s->mb_y >= -16);
|
---|
167 | assert((bx>>1) + 16*s->mb_x <= s->width);
|
---|
168 | assert((by>>1) + 16*s->mb_y <= s->height);
|
---|
169 |
|
---|
170 | c->hpel_put[0][fxy](c->temp, ref[0] + (fx>>1) + (fy>>1)*stride, stride, 16);
|
---|
171 | c->hpel_avg[0][bxy](c->temp, ref[8] + (bx>>1) + (by>>1)*stride, stride, 16);
|
---|
172 | }
|
---|
173 | }
|
---|
174 | d = cmp_func(s, c->temp, src[0], stride, 16);
|
---|
175 | }else
|
---|
176 | d= 256*256*256*32;
|
---|
177 | }else{
|
---|
178 | int uvdxy; /* no, it might not be used uninitialized */
|
---|
179 | if(dxy){
|
---|
180 | if(qpel){
|
---|
181 | c->qpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride); //FIXME prototype (add h)
|
---|
182 | if(chroma){
|
---|
183 | int cx= hx/2;
|
---|
184 | int cy= hy/2;
|
---|
185 | cx= (cx>>1)|(cx&1);
|
---|
186 | cy= (cy>>1)|(cy&1);
|
---|
187 | uvdxy= (cx&1) + 2*(cy&1);
|
---|
188 | //FIXME x/y wrong, but mpeg4 qpel is sick anyway, we should drop as much of it as possible in favor for h264
|
---|
189 | }
|
---|
190 | }else{
|
---|
191 | c->hpel_put[size][dxy](c->temp, ref[0] + x + y*stride, stride, h);
|
---|
192 | if(chroma)
|
---|
193 | uvdxy= dxy | (x&1) | (2*(y&1));
|
---|
194 | }
|
---|
195 | d = cmp_func(s, c->temp, src[0], stride, h);
|
---|
196 | }else{
|
---|
197 | d = cmp_func(s, src[0], ref[0] + x + y*stride, stride, h);
|
---|
198 | if(chroma)
|
---|
199 | uvdxy= (x&1) + 2*(y&1);
|
---|
200 | }
|
---|
201 | if(chroma){
|
---|
202 | uint8_t * const uvtemp= c->temp + 16*stride;
|
---|
203 | c->hpel_put[size+1][uvdxy](uvtemp , ref[1] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
|
---|
204 | c->hpel_put[size+1][uvdxy](uvtemp+8, ref[2] + (x>>1) + (y>>1)*uvstride, uvstride, h>>1);
|
---|
205 | d += chroma_cmp_func(s, uvtemp , src[1], uvstride, h>>1);
|
---|
206 | d += chroma_cmp_func(s, uvtemp+8, src[2], uvstride, h>>1);
|
---|
207 | }
|
---|
208 | }
|
---|
209 | #if 0
|
---|
210 | if(full_pel){
|
---|
211 | const int index= (((y)<<ME_MAP_SHIFT) + (x))&(ME_MAP_SIZE-1);
|
---|
212 | score_map[index]= d;
|
---|
213 | }
|
---|
214 |
|
---|
215 | d += (c->mv_penalty[hx - c->pred_x] + c->mv_penalty[hy - c->pred_y])*c->penalty_factor;
|
---|
216 | #endif
|
---|
217 | return d;
|
---|
218 | }
|
---|
219 |
|
---|
220 | #include "motion_est_template.c"
|
---|
221 |
|
---|
222 | static int zero_cmp(void *s, uint8_t *a, uint8_t *b, int stride, int h){
|
---|
223 | return 0;
|
---|
224 | }
|
---|
225 |
|
---|
226 | static void zero_hpel(uint8_t *a, const uint8_t *b, int stride, int h){
|
---|
227 | }
|
---|
228 |
|
---|
229 | void ff_init_me(MpegEncContext *s){
|
---|
230 | MotionEstContext * const c= &s->me;
|
---|
231 | c->avctx= s->avctx;
|
---|
232 |
|
---|
233 | ff_set_cmp(&s->dsp, s->dsp.me_pre_cmp, c->avctx->me_pre_cmp);
|
---|
234 | ff_set_cmp(&s->dsp, s->dsp.me_cmp, c->avctx->me_cmp);
|
---|
235 | ff_set_cmp(&s->dsp, s->dsp.me_sub_cmp, c->avctx->me_sub_cmp);
|
---|
236 | ff_set_cmp(&s->dsp, s->dsp.mb_cmp, c->avctx->mb_cmp);
|
---|
237 |
|
---|
238 | c->flags = get_flags(c, 0, c->avctx->me_cmp &FF_CMP_CHROMA);
|
---|
239 | c->sub_flags= get_flags(c, 0, c->avctx->me_sub_cmp&FF_CMP_CHROMA);
|
---|
240 | c->mb_flags = get_flags(c, 0, c->avctx->mb_cmp &FF_CMP_CHROMA);
|
---|
241 |
|
---|
242 | /*FIXME s->no_rounding b_type*/
|
---|
243 | if(s->flags&CODEC_FLAG_QPEL){
|
---|
244 | c->sub_motion_search= qpel_motion_search;
|
---|
245 | c->qpel_avg= s->dsp.avg_qpel_pixels_tab;
|
---|
246 | if(s->no_rounding) c->qpel_put= s->dsp.put_no_rnd_qpel_pixels_tab;
|
---|
247 | else c->qpel_put= s->dsp.put_qpel_pixels_tab;
|
---|
248 | }else{
|
---|
249 | if(c->avctx->me_sub_cmp&FF_CMP_CHROMA)
|
---|
250 | c->sub_motion_search= hpel_motion_search;
|
---|
251 | else if( c->avctx->me_sub_cmp == FF_CMP_SAD
|
---|
252 | && c->avctx-> me_cmp == FF_CMP_SAD
|
---|
253 | && c->avctx-> mb_cmp == FF_CMP_SAD)
|
---|
254 | c->sub_motion_search= sad_hpel_motion_search; // 2050 vs. 2450 cycles
|
---|
255 | else
|
---|
256 | c->sub_motion_search= hpel_motion_search;
|
---|
257 | }
|
---|
258 | c->hpel_avg= s->dsp.avg_pixels_tab;
|
---|
259 | if(s->no_rounding) c->hpel_put= s->dsp.put_no_rnd_pixels_tab;
|
---|
260 | else c->hpel_put= s->dsp.put_pixels_tab;
|
---|
261 |
|
---|
262 | if(s->linesize){
|
---|
263 | c->stride = s->linesize;
|
---|
264 | c->uvstride= s->uvlinesize;
|
---|
265 | }else{
|
---|
266 | c->stride = 16*s->mb_width + 32;
|
---|
267 | c->uvstride= 8*s->mb_width + 16;
|
---|
268 | }
|
---|
269 |
|
---|
270 | // 8x8 fullpel search would need a 4x4 chroma compare, which we dont have yet, and even if we had the motion estimation code doesnt expect it
|
---|
271 | if(s->codec_id != CODEC_ID_SNOW){
|
---|
272 | if((c->avctx->me_cmp&FF_CMP_CHROMA)/* && !s->dsp.me_cmp[2]*/){
|
---|
273 | s->dsp.me_cmp[2]= zero_cmp;
|
---|
274 | }
|
---|
275 | if((c->avctx->me_sub_cmp&FF_CMP_CHROMA) && !s->dsp.me_sub_cmp[2]){
|
---|
276 | s->dsp.me_sub_cmp[2]= zero_cmp;
|
---|
277 | }
|
---|
278 | c->hpel_put[2][0]= c->hpel_put[2][1]=
|
---|
279 | c->hpel_put[2][2]= c->hpel_put[2][3]= zero_hpel;
|
---|
280 | }
|
---|
281 |
|
---|
282 | if(s->codec_id == CODEC_ID_H261){
|
---|
283 | c->sub_motion_search= no_sub_motion_search;
|
---|
284 | }
|
---|
285 |
|
---|
286 | c->temp= c->scratchpad;
|
---|
287 | }
|
---|
288 |
|
---|
289 | #if 0
|
---|
290 | static int pix_dev(uint8_t * pix, int line_size, int mean)
|
---|
291 | {
|
---|
292 | int s, i, j;
|
---|
293 |
|
---|
294 | s = 0;
|
---|
295 | for (i = 0; i < 16; i++) {
|
---|
296 | for (j = 0; j < 16; j += 8) {
|
---|
297 | s += ABS(pix[0]-mean);
|
---|
298 | s += ABS(pix[1]-mean);
|
---|
299 | s += ABS(pix[2]-mean);
|
---|
300 | s += ABS(pix[3]-mean);
|
---|
301 | s += ABS(pix[4]-mean);
|
---|
302 | s += ABS(pix[5]-mean);
|
---|
303 | s += ABS(pix[6]-mean);
|
---|
304 | s += ABS(pix[7]-mean);
|
---|
305 | pix += 8;
|
---|
306 | }
|
---|
307 | pix += line_size - 16;
|
---|
308 | }
|
---|
309 | return s;
|
---|
310 | }
|
---|
311 | #endif
|
---|
312 |
|
---|
313 | static inline void no_motion_search(MpegEncContext * s,
|
---|
314 | int *mx_ptr, int *my_ptr)
|
---|
315 | {
|
---|
316 | *mx_ptr = 16 * s->mb_x;
|
---|
317 | *my_ptr = 16 * s->mb_y;
|
---|
318 | }
|
---|
319 |
|
---|
320 | #if 0 /* the use of these functions is inside #if 0 */
|
---|
321 | static int full_motion_search(MpegEncContext * s,
|
---|
322 | int *mx_ptr, int *my_ptr, int range,
|
---|
323 | int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
|
---|
324 | {
|
---|
325 | int x1, y1, x2, y2, xx, yy, x, y;
|
---|
326 | int mx, my, dmin, d;
|
---|
327 | uint8_t *pix;
|
---|
328 |
|
---|
329 | xx = 16 * s->mb_x;
|
---|
330 | yy = 16 * s->mb_y;
|
---|
331 | x1 = xx - range + 1; /* we loose one pixel to avoid boundary pb with half pixel pred */
|
---|
332 | if (x1 < xmin)
|
---|
333 | x1 = xmin;
|
---|
334 | x2 = xx + range - 1;
|
---|
335 | if (x2 > xmax)
|
---|
336 | x2 = xmax;
|
---|
337 | y1 = yy - range + 1;
|
---|
338 | if (y1 < ymin)
|
---|
339 | y1 = ymin;
|
---|
340 | y2 = yy + range - 1;
|
---|
341 | if (y2 > ymax)
|
---|
342 | y2 = ymax;
|
---|
343 | pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
|
---|
344 | dmin = 0x7fffffff;
|
---|
345 | mx = 0;
|
---|
346 | my = 0;
|
---|
347 | for (y = y1; y <= y2; y++) {
|
---|
348 | for (x = x1; x <= x2; x++) {
|
---|
349 | d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x,
|
---|
350 | s->linesize, 16);
|
---|
351 | if (d < dmin ||
|
---|
352 | (d == dmin &&
|
---|
353 | (abs(x - xx) + abs(y - yy)) <
|
---|
354 | (abs(mx - xx) + abs(my - yy)))) {
|
---|
355 | dmin = d;
|
---|
356 | mx = x;
|
---|
357 | my = y;
|
---|
358 | }
|
---|
359 | }
|
---|
360 | }
|
---|
361 |
|
---|
362 | *mx_ptr = mx;
|
---|
363 | *my_ptr = my;
|
---|
364 |
|
---|
365 | #if 0
|
---|
366 | if (*mx_ptr < -(2 * range) || *mx_ptr >= (2 * range) ||
|
---|
367 | *my_ptr < -(2 * range) || *my_ptr >= (2 * range)) {
|
---|
368 | av_log(NULL, AV_LOG_ERROR, "error %d %d\n", *mx_ptr, *my_ptr);
|
---|
369 | }
|
---|
370 | #endif
|
---|
371 | return dmin;
|
---|
372 | }
|
---|
373 |
|
---|
374 |
|
---|
375 | static int log_motion_search(MpegEncContext * s,
|
---|
376 | int *mx_ptr, int *my_ptr, int range,
|
---|
377 | int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
|
---|
378 | {
|
---|
379 | int x1, y1, x2, y2, xx, yy, x, y;
|
---|
380 | int mx, my, dmin, d;
|
---|
381 | uint8_t *pix;
|
---|
382 |
|
---|
383 | xx = s->mb_x << 4;
|
---|
384 | yy = s->mb_y << 4;
|
---|
385 |
|
---|
386 | /* Left limit */
|
---|
387 | x1 = xx - range;
|
---|
388 | if (x1 < xmin)
|
---|
389 | x1 = xmin;
|
---|
390 |
|
---|
391 | /* Right limit */
|
---|
392 | x2 = xx + range;
|
---|
393 | if (x2 > xmax)
|
---|
394 | x2 = xmax;
|
---|
395 |
|
---|
396 | /* Upper limit */
|
---|
397 | y1 = yy - range;
|
---|
398 | if (y1 < ymin)
|
---|
399 | y1 = ymin;
|
---|
400 |
|
---|
401 | /* Lower limit */
|
---|
402 | y2 = yy + range;
|
---|
403 | if (y2 > ymax)
|
---|
404 | y2 = ymax;
|
---|
405 |
|
---|
406 | pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
|
---|
407 | dmin = 0x7fffffff;
|
---|
408 | mx = 0;
|
---|
409 | my = 0;
|
---|
410 |
|
---|
411 | do {
|
---|
412 | for (y = y1; y <= y2; y += range) {
|
---|
413 | for (x = x1; x <= x2; x += range) {
|
---|
414 | d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
|
---|
415 | if (d < dmin || (d == dmin && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
|
---|
416 | dmin = d;
|
---|
417 | mx = x;
|
---|
418 | my = y;
|
---|
419 | }
|
---|
420 | }
|
---|
421 | }
|
---|
422 |
|
---|
423 | range = range >> 1;
|
---|
424 |
|
---|
425 | x1 = mx - range;
|
---|
426 | if (x1 < xmin)
|
---|
427 | x1 = xmin;
|
---|
428 |
|
---|
429 | x2 = mx + range;
|
---|
430 | if (x2 > xmax)
|
---|
431 | x2 = xmax;
|
---|
432 |
|
---|
433 | y1 = my - range;
|
---|
434 | if (y1 < ymin)
|
---|
435 | y1 = ymin;
|
---|
436 |
|
---|
437 | y2 = my + range;
|
---|
438 | if (y2 > ymax)
|
---|
439 | y2 = ymax;
|
---|
440 |
|
---|
441 | } while (range >= 1);
|
---|
442 |
|
---|
443 | #ifdef DEBUG
|
---|
444 | av_log(s->avctx, AV_LOG_DEBUG, "log - MX: %d\tMY: %d\n", mx, my);
|
---|
445 | #endif
|
---|
446 | *mx_ptr = mx;
|
---|
447 | *my_ptr = my;
|
---|
448 | return dmin;
|
---|
449 | }
|
---|
450 |
|
---|
451 | static int phods_motion_search(MpegEncContext * s,
|
---|
452 | int *mx_ptr, int *my_ptr, int range,
|
---|
453 | int xmin, int ymin, int xmax, int ymax, uint8_t *ref_picture)
|
---|
454 | {
|
---|
455 | int x1, y1, x2, y2, xx, yy, x, y, lastx, d;
|
---|
456 | int mx, my, dminx, dminy;
|
---|
457 | uint8_t *pix;
|
---|
458 |
|
---|
459 | xx = s->mb_x << 4;
|
---|
460 | yy = s->mb_y << 4;
|
---|
461 |
|
---|
462 | /* Left limit */
|
---|
463 | x1 = xx - range;
|
---|
464 | if (x1 < xmin)
|
---|
465 | x1 = xmin;
|
---|
466 |
|
---|
467 | /* Right limit */
|
---|
468 | x2 = xx + range;
|
---|
469 | if (x2 > xmax)
|
---|
470 | x2 = xmax;
|
---|
471 |
|
---|
472 | /* Upper limit */
|
---|
473 | y1 = yy - range;
|
---|
474 | if (y1 < ymin)
|
---|
475 | y1 = ymin;
|
---|
476 |
|
---|
477 | /* Lower limit */
|
---|
478 | y2 = yy + range;
|
---|
479 | if (y2 > ymax)
|
---|
480 | y2 = ymax;
|
---|
481 |
|
---|
482 | pix = s->new_picture.data[0] + (yy * s->linesize) + xx;
|
---|
483 | mx = 0;
|
---|
484 | my = 0;
|
---|
485 |
|
---|
486 | x = xx;
|
---|
487 | y = yy;
|
---|
488 | do {
|
---|
489 | dminx = 0x7fffffff;
|
---|
490 | dminy = 0x7fffffff;
|
---|
491 |
|
---|
492 | lastx = x;
|
---|
493 | for (x = x1; x <= x2; x += range) {
|
---|
494 | d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
|
---|
495 | if (d < dminx || (d == dminx && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
|
---|
496 | dminx = d;
|
---|
497 | mx = x;
|
---|
498 | }
|
---|
499 | }
|
---|
500 |
|
---|
501 | x = lastx;
|
---|
502 | for (y = y1; y <= y2; y += range) {
|
---|
503 | d = s->dsp.pix_abs[0][0](NULL, pix, ref_picture + (y * s->linesize) + x, s->linesize, 16);
|
---|
504 | if (d < dminy || (d == dminy && (abs(x - xx) + abs(y - yy)) < (abs(mx - xx) + abs(my - yy)))) {
|
---|
505 | dminy = d;
|
---|
506 | my = y;
|
---|
507 | }
|
---|
508 | }
|
---|
509 |
|
---|
510 | range = range >> 1;
|
---|
511 |
|
---|
512 | x = mx;
|
---|
513 | y = my;
|
---|
514 | x1 = mx - range;
|
---|
515 | if (x1 < xmin)
|
---|
516 | x1 = xmin;
|
---|
517 |
|
---|
518 | x2 = mx + range;
|
---|
519 | if (x2 > xmax)
|
---|
520 | x2 = xmax;
|
---|
521 |
|
---|
522 | y1 = my - range;
|
---|
523 | if (y1 < ymin)
|
---|
524 | y1 = ymin;
|
---|
525 |
|
---|
526 | y2 = my + range;
|
---|
527 | if (y2 > ymax)
|
---|
528 | y2 = ymax;
|
---|
529 |
|
---|
530 | } while (range >= 1);
|
---|
531 |
|
---|
532 | #ifdef DEBUG
|
---|
533 | av_log(s->avctx, AV_LOG_DEBUG, "phods - MX: %d\tMY: %d\n", mx, my);
|
---|
534 | #endif
|
---|
535 |
|
---|
536 | /* half pixel search */
|
---|
537 | *mx_ptr = mx;
|
---|
538 | *my_ptr = my;
|
---|
539 | return dminy;
|
---|
540 | }
|
---|
541 | #endif /* 0 */
|
---|
542 |
|
---|
543 | #define Z_THRESHOLD 256
|
---|
544 |
|
---|
545 | #define CHECK_SAD_HALF_MV(suffix, x, y) \
|
---|
546 | {\
|
---|
547 | d= s->dsp.pix_abs[size][(x?1:0)+(y?2:0)](NULL, pix, ptr+((x)>>1), stride, h);\
|
---|
548 | d += (mv_penalty[pen_x + x] + mv_penalty[pen_y + y])*penalty_factor;\
|
---|
549 | COPY3_IF_LT(dminh, d, dx, x, dy, y)\
|
---|
550 | }
|
---|
551 |
|
---|
552 | static inline int sad_hpel_motion_search(MpegEncContext * s,
|
---|
553 | int *mx_ptr, int *my_ptr, int dmin,
|
---|
554 | int src_index, int ref_index,
|
---|
555 | int size, int h)
|
---|
556 | {
|
---|
557 | MotionEstContext * const c= &s->me;
|
---|
558 | const int penalty_factor= c->sub_penalty_factor;
|
---|
559 | int mx, my, dminh;
|
---|
560 | uint8_t *pix, *ptr;
|
---|
561 | int stride= c->stride;
|
---|
562 | const int flags= c->sub_flags;
|
---|
563 | LOAD_COMMON
|
---|
564 |
|
---|
565 | assert(flags == 0);
|
---|
566 |
|
---|
567 | if(c->skip){
|
---|
568 | // printf("S");
|
---|
569 | *mx_ptr = 0;
|
---|
570 | *my_ptr = 0;
|
---|
571 | return dmin;
|
---|
572 | }
|
---|
573 | // printf("N");
|
---|
574 |
|
---|
575 | pix = c->src[src_index][0];
|
---|
576 |
|
---|
577 | mx = *mx_ptr;
|
---|
578 | my = *my_ptr;
|
---|
579 | ptr = c->ref[ref_index][0] + (my * stride) + mx;
|
---|
580 |
|
---|
581 | dminh = dmin;
|
---|
582 |
|
---|
583 | if (mx > xmin && mx < xmax &&
|
---|
584 | my > ymin && my < ymax) {
|
---|
585 | int dx=0, dy=0;
|
---|
586 | int d, pen_x, pen_y;
|
---|
587 | const int index= (my<<ME_MAP_SHIFT) + mx;
|
---|
588 | const int t= score_map[(index-(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
|
---|
589 | const int l= score_map[(index- 1 )&(ME_MAP_SIZE-1)];
|
---|
590 | const int r= score_map[(index+ 1 )&(ME_MAP_SIZE-1)];
|
---|
591 | const int b= score_map[(index+(1<<ME_MAP_SHIFT))&(ME_MAP_SIZE-1)];
|
---|
592 | mx<<=1;
|
---|
593 | my<<=1;
|
---|
594 |
|
---|
595 |
|
---|
596 | pen_x= pred_x + mx;
|
---|
597 | pen_y= pred_y + my;
|
---|
598 |
|
---|
599 | ptr-= stride;
|
---|
600 | if(t<=b){
|
---|
601 | CHECK_SAD_HALF_MV(y2 , 0, -1)
|
---|
602 | if(l<=r){
|
---|
603 | CHECK_SAD_HALF_MV(xy2, -1, -1)
|
---|
604 | if(t+r<=b+l){
|
---|
605 | CHECK_SAD_HALF_MV(xy2, +1, -1)
|
---|
606 | ptr+= stride;
|
---|
607 | }else{
|
---|
608 | ptr+= stride;
|
---|
609 | CHECK_SAD_HALF_MV(xy2, -1, +1)
|
---|
610 | }
|
---|
611 | CHECK_SAD_HALF_MV(x2 , -1, 0)
|
---|
612 | }else{
|
---|
613 | CHECK_SAD_HALF_MV(xy2, +1, -1)
|
---|
614 | if(t+l<=b+r){
|
---|
615 | CHECK_SAD_HALF_MV(xy2, -1, -1)
|
---|
616 | ptr+= stride;
|
---|
617 | }else{
|
---|
618 | ptr+= stride;
|
---|
619 | CHECK_SAD_HALF_MV(xy2, +1, +1)
|
---|
620 | }
|
---|
621 | CHECK_SAD_HALF_MV(x2 , +1, 0)
|
---|
622 | }
|
---|
623 | }else{
|
---|
624 | if(l<=r){
|
---|
625 | if(t+l<=b+r){
|
---|
626 | CHECK_SAD_HALF_MV(xy2, -1, -1)
|
---|
627 | ptr+= stride;
|
---|
628 | }else{
|
---|
629 | ptr+= stride;
|
---|
630 | CHECK_SAD_HALF_MV(xy2, +1, +1)
|
---|
631 | }
|
---|
632 | CHECK_SAD_HALF_MV(x2 , -1, 0)
|
---|
633 | CHECK_SAD_HALF_MV(xy2, -1, +1)
|
---|
634 | }else{
|
---|
635 | if(t+r<=b+l){
|
---|
636 | CHECK_SAD_HALF_MV(xy2, +1, -1)
|
---|
637 | ptr+= stride;
|
---|
638 | }else{
|
---|
639 | ptr+= stride;
|
---|
640 | CHECK_SAD_HALF_MV(xy2, -1, +1)
|
---|
641 | }
|
---|
642 | CHECK_SAD_HALF_MV(x2 , +1, 0)
|
---|
643 | CHECK_SAD_HALF_MV(xy2, +1, +1)
|
---|
644 | }
|
---|
645 | CHECK_SAD_HALF_MV(y2 , 0, +1)
|
---|
646 | }
|
---|
647 | mx+=dx;
|
---|
648 | my+=dy;
|
---|
649 |
|
---|
650 | }else{
|
---|
651 | mx<<=1;
|
---|
652 | my<<=1;
|
---|
653 | }
|
---|
654 |
|
---|
655 | *mx_ptr = mx;
|
---|
656 | *my_ptr = my;
|
---|
657 | return dminh;
|
---|
658 | }
|
---|
659 |
|
---|
660 | static inline void set_p_mv_tables(MpegEncContext * s, int mx, int my, int mv4)
|
---|
661 | {
|
---|
662 | const int xy= s->mb_x + s->mb_y*s->mb_stride;
|
---|
663 |
|
---|
664 | s->p_mv_table[xy][0] = mx;
|
---|
665 | s->p_mv_table[xy][1] = my;
|
---|
666 |
|
---|
667 | /* has already been set to the 4 MV if 4MV is done */
|
---|
668 | if(mv4){
|
---|
669 | int mot_xy= s->block_index[0];
|
---|
670 |
|
---|
671 | s->current_picture.motion_val[0][mot_xy ][0]= mx;
|
---|
672 | s->current_picture.motion_val[0][mot_xy ][1]= my;
|
---|
673 | s->current_picture.motion_val[0][mot_xy+1][0]= mx;
|
---|
674 | s->current_picture.motion_val[0][mot_xy+1][1]= my;
|
---|
675 |
|
---|
676 | mot_xy += s->b8_stride;
|
---|
677 | s->current_picture.motion_val[0][mot_xy ][0]= mx;
|
---|
678 | s->current_picture.motion_val[0][mot_xy ][1]= my;
|
---|
679 | s->current_picture.motion_val[0][mot_xy+1][0]= mx;
|
---|
680 | s->current_picture.motion_val[0][mot_xy+1][1]= my;
|
---|
681 | }
|
---|
682 | }
|
---|
683 |
|
---|
684 | /**
|
---|
685 | * get fullpel ME search limits.
|
---|
686 | */
|
---|
687 | static inline void get_limits(MpegEncContext *s, int x, int y)
|
---|
688 | {
|
---|
689 | MotionEstContext * const c= &s->me;
|
---|
690 | /*
|
---|
691 | if(c->avctx->me_range) c->range= c->avctx->me_range >> 1;
|
---|
692 | else c->range= 16;
|
---|
693 | */
|
---|
694 | if (s->unrestricted_mv) {
|
---|
695 | c->xmin = - x - 16;
|
---|
696 | c->ymin = - y - 16;
|
---|
697 | c->xmax = - x + s->mb_width *16;
|
---|
698 | c->ymax = - y + s->mb_height*16;
|
---|
699 | } else if (s->out_format == FMT_H261){
|
---|
700 | // Search range of H261 is different from other codec standards
|
---|
701 | c->xmin = (x > 15) ? - 15 : 0;
|
---|
702 | c->ymin = (y > 15) ? - 15 : 0;
|
---|
703 | c->xmax = (x < s->mb_width * 16 - 16) ? 15 : 0;
|
---|
704 | c->ymax = (y < s->mb_height * 16 - 16) ? 15 : 0;
|
---|
705 | } else {
|
---|
706 | c->xmin = - x;
|
---|
707 | c->ymin = - y;
|
---|
708 | c->xmax = - x + s->mb_width *16 - 16;
|
---|
709 | c->ymax = - y + s->mb_height*16 - 16;
|
---|
710 | }
|
---|
711 | }
|
---|
712 |
|
---|
713 | static inline void init_mv4_ref(MotionEstContext *c){
|
---|
714 | const int stride= c->stride;
|
---|
715 |
|
---|
716 | c->ref[1][0] = c->ref[0][0] + 8;
|
---|
717 | c->ref[2][0] = c->ref[0][0] + 8*stride;
|
---|
718 | c->ref[3][0] = c->ref[2][0] + 8;
|
---|
719 | c->src[1][0] = c->src[0][0] + 8;
|
---|
720 | c->src[2][0] = c->src[0][0] + 8*stride;
|
---|
721 | c->src[3][0] = c->src[2][0] + 8;
|
---|
722 | }
|
---|
723 |
|
---|
724 | static inline int h263_mv4_search(MpegEncContext *s, int mx, int my, int shift)
|
---|
725 | {
|
---|
726 | MotionEstContext * const c= &s->me;
|
---|
727 | const int size= 1;
|
---|
728 | const int h=8;
|
---|
729 | int block;
|
---|
730 | int P[10][2];
|
---|
731 | int dmin_sum=0, mx4_sum=0, my4_sum=0;
|
---|
732 | int same=1;
|
---|
733 | const int stride= c->stride;
|
---|
734 | uint8_t *mv_penalty= c->current_mv_penalty;
|
---|
735 |
|
---|
736 | init_mv4_ref(c);
|
---|
737 |
|
---|
738 | for(block=0; block<4; block++){
|
---|
739 | int mx4, my4;
|
---|
740 | int pred_x4, pred_y4;
|
---|
741 | int dmin4;
|
---|
742 | static const int off[4]= {2, 1, 1, -1};
|
---|
743 | const int mot_stride = s->b8_stride;
|
---|
744 | const int mot_xy = s->block_index[block];
|
---|
745 |
|
---|
746 | P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
|
---|
747 | P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
|
---|
748 |
|
---|
749 | if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
|
---|
750 |
|
---|
751 | /* special case for first line */
|
---|
752 | if (s->first_slice_line && block<2) {
|
---|
753 | c->pred_x= pred_x4= P_LEFT[0];
|
---|
754 | c->pred_y= pred_y4= P_LEFT[1];
|
---|
755 | } else {
|
---|
756 | P_TOP[0] = s->current_picture.motion_val[0][mot_xy - mot_stride ][0];
|
---|
757 | P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1];
|
---|
758 | P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][0];
|
---|
759 | P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + off[block]][1];
|
---|
760 | if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
|
---|
761 | if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
|
---|
762 | if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
|
---|
763 | if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
|
---|
764 |
|
---|
765 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
766 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
767 |
|
---|
768 | c->pred_x= pred_x4 = P_MEDIAN[0];
|
---|
769 | c->pred_y= pred_y4 = P_MEDIAN[1];
|
---|
770 | }
|
---|
771 | P_MV1[0]= mx;
|
---|
772 | P_MV1[1]= my;
|
---|
773 |
|
---|
774 | dmin4 = epzs_motion_search4(s, &mx4, &my4, P, block, block, s->p_mv_table, (1<<16)>>shift);
|
---|
775 |
|
---|
776 | dmin4= c->sub_motion_search(s, &mx4, &my4, dmin4, block, block, size, h);
|
---|
777 |
|
---|
778 | if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
|
---|
779 | int dxy;
|
---|
780 | const int offset= ((block&1) + (block>>1)*stride)*8;
|
---|
781 | uint8_t *dest_y = c->scratchpad + offset;
|
---|
782 | if(s->quarter_sample){
|
---|
783 | uint8_t *ref= c->ref[block][0] + (mx4>>2) + (my4>>2)*stride;
|
---|
784 | dxy = ((my4 & 3) << 2) | (mx4 & 3);
|
---|
785 |
|
---|
786 | if(s->no_rounding)
|
---|
787 | s->dsp.put_no_rnd_qpel_pixels_tab[1][dxy](dest_y , ref , stride);
|
---|
788 | else
|
---|
789 | s->dsp.put_qpel_pixels_tab [1][dxy](dest_y , ref , stride);
|
---|
790 | }else{
|
---|
791 | uint8_t *ref= c->ref[block][0] + (mx4>>1) + (my4>>1)*stride;
|
---|
792 | dxy = ((my4 & 1) << 1) | (mx4 & 1);
|
---|
793 |
|
---|
794 | if(s->no_rounding)
|
---|
795 | s->dsp.put_no_rnd_pixels_tab[1][dxy](dest_y , ref , stride, h);
|
---|
796 | else
|
---|
797 | s->dsp.put_pixels_tab [1][dxy](dest_y , ref , stride, h);
|
---|
798 | }
|
---|
799 | dmin_sum+= (mv_penalty[mx4-pred_x4] + mv_penalty[my4-pred_y4])*c->mb_penalty_factor;
|
---|
800 | }else
|
---|
801 | dmin_sum+= dmin4;
|
---|
802 |
|
---|
803 | if(s->quarter_sample){
|
---|
804 | mx4_sum+= mx4/2;
|
---|
805 | my4_sum+= my4/2;
|
---|
806 | }else{
|
---|
807 | mx4_sum+= mx4;
|
---|
808 | my4_sum+= my4;
|
---|
809 | }
|
---|
810 |
|
---|
811 | s->current_picture.motion_val[0][ s->block_index[block] ][0]= mx4;
|
---|
812 | s->current_picture.motion_val[0][ s->block_index[block] ][1]= my4;
|
---|
813 |
|
---|
814 | if(mx4 != mx || my4 != my) same=0;
|
---|
815 | }
|
---|
816 |
|
---|
817 | if(same)
|
---|
818 | return INT_MAX;
|
---|
819 |
|
---|
820 | if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
|
---|
821 | dmin_sum += s->dsp.mb_cmp[0](s, s->new_picture.data[0] + s->mb_x*16 + s->mb_y*16*stride, c->scratchpad, stride, 16);
|
---|
822 | }
|
---|
823 |
|
---|
824 | if(c->avctx->mb_cmp&FF_CMP_CHROMA){
|
---|
825 | int dxy;
|
---|
826 | int mx, my;
|
---|
827 | int offset;
|
---|
828 |
|
---|
829 | mx= ff_h263_round_chroma(mx4_sum);
|
---|
830 | my= ff_h263_round_chroma(my4_sum);
|
---|
831 | dxy = ((my & 1) << 1) | (mx & 1);
|
---|
832 |
|
---|
833 | offset= (s->mb_x*8 + (mx>>1)) + (s->mb_y*8 + (my>>1))*s->uvlinesize;
|
---|
834 |
|
---|
835 | if(s->no_rounding){
|
---|
836 | s->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad , s->last_picture.data[1] + offset, s->uvlinesize, 8);
|
---|
837 | s->dsp.put_no_rnd_pixels_tab[1][dxy](c->scratchpad+8 , s->last_picture.data[2] + offset, s->uvlinesize, 8);
|
---|
838 | }else{
|
---|
839 | s->dsp.put_pixels_tab [1][dxy](c->scratchpad , s->last_picture.data[1] + offset, s->uvlinesize, 8);
|
---|
840 | s->dsp.put_pixels_tab [1][dxy](c->scratchpad+8 , s->last_picture.data[2] + offset, s->uvlinesize, 8);
|
---|
841 | }
|
---|
842 |
|
---|
843 | dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.data[1] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad , s->uvlinesize, 8);
|
---|
844 | dmin_sum += s->dsp.mb_cmp[1](s, s->new_picture.data[2] + s->mb_x*8 + s->mb_y*8*s->uvlinesize, c->scratchpad+8, s->uvlinesize, 8);
|
---|
845 | }
|
---|
846 |
|
---|
847 | c->pred_x= mx;
|
---|
848 | c->pred_y= my;
|
---|
849 |
|
---|
850 | switch(c->avctx->mb_cmp&0xFF){
|
---|
851 | /*case FF_CMP_SSE:
|
---|
852 | return dmin_sum+ 32*s->qscale*s->qscale;*/
|
---|
853 | case FF_CMP_RD:
|
---|
854 | return dmin_sum;
|
---|
855 | default:
|
---|
856 | return dmin_sum+ 11*c->mb_penalty_factor;
|
---|
857 | }
|
---|
858 | }
|
---|
859 |
|
---|
860 | static inline void init_interlaced_ref(MpegEncContext *s, int ref_index){
|
---|
861 | MotionEstContext * const c= &s->me;
|
---|
862 |
|
---|
863 | c->ref[1+ref_index][0] = c->ref[0+ref_index][0] + s->linesize;
|
---|
864 | c->src[1][0] = c->src[0][0] + s->linesize;
|
---|
865 | if(c->flags & FLAG_CHROMA){
|
---|
866 | c->ref[1+ref_index][1] = c->ref[0+ref_index][1] + s->uvlinesize;
|
---|
867 | c->ref[1+ref_index][2] = c->ref[0+ref_index][2] + s->uvlinesize;
|
---|
868 | c->src[1][1] = c->src[0][1] + s->uvlinesize;
|
---|
869 | c->src[1][2] = c->src[0][2] + s->uvlinesize;
|
---|
870 | }
|
---|
871 | }
|
---|
872 |
|
---|
873 | static int interlaced_search(MpegEncContext *s, int ref_index,
|
---|
874 | int16_t (*mv_tables[2][2])[2], uint8_t *field_select_tables[2], int mx, int my, int user_field_select)
|
---|
875 | {
|
---|
876 | MotionEstContext * const c= &s->me;
|
---|
877 | const int size=0;
|
---|
878 | const int h=8;
|
---|
879 | int block;
|
---|
880 | int P[10][2];
|
---|
881 | uint8_t * const mv_penalty= c->current_mv_penalty;
|
---|
882 | int same=1;
|
---|
883 | const int stride= 2*s->linesize;
|
---|
884 | int dmin_sum= 0;
|
---|
885 | const int mot_stride= s->mb_stride;
|
---|
886 | const int xy= s->mb_x + s->mb_y*mot_stride;
|
---|
887 |
|
---|
888 | c->ymin>>=1;
|
---|
889 | c->ymax>>=1;
|
---|
890 | c->stride<<=1;
|
---|
891 | c->uvstride<<=1;
|
---|
892 | init_interlaced_ref(s, ref_index);
|
---|
893 |
|
---|
894 | for(block=0; block<2; block++){
|
---|
895 | int field_select;
|
---|
896 | int best_dmin= INT_MAX;
|
---|
897 | int best_field= -1;
|
---|
898 |
|
---|
899 | for(field_select=0; field_select<2; field_select++){
|
---|
900 | int dmin, mx_i, my_i;
|
---|
901 | int16_t (*mv_table)[2]= mv_tables[block][field_select];
|
---|
902 |
|
---|
903 | if(user_field_select){
|
---|
904 | assert(field_select==0 || field_select==1);
|
---|
905 | assert(field_select_tables[block][xy]==0 || field_select_tables[block][xy]==1);
|
---|
906 | if(field_select_tables[block][xy] != field_select)
|
---|
907 | continue;
|
---|
908 | }
|
---|
909 |
|
---|
910 | P_LEFT[0] = mv_table[xy - 1][0];
|
---|
911 | P_LEFT[1] = mv_table[xy - 1][1];
|
---|
912 | if(P_LEFT[0] > (c->xmax<<1)) P_LEFT[0] = (c->xmax<<1);
|
---|
913 |
|
---|
914 | c->pred_x= P_LEFT[0];
|
---|
915 | c->pred_y= P_LEFT[1];
|
---|
916 |
|
---|
917 | if(!s->first_slice_line){
|
---|
918 | P_TOP[0] = mv_table[xy - mot_stride][0];
|
---|
919 | P_TOP[1] = mv_table[xy - mot_stride][1];
|
---|
920 | P_TOPRIGHT[0] = mv_table[xy - mot_stride + 1][0];
|
---|
921 | P_TOPRIGHT[1] = mv_table[xy - mot_stride + 1][1];
|
---|
922 | if(P_TOP[1] > (c->ymax<<1)) P_TOP[1] = (c->ymax<<1);
|
---|
923 | if(P_TOPRIGHT[0] < (c->xmin<<1)) P_TOPRIGHT[0]= (c->xmin<<1);
|
---|
924 | if(P_TOPRIGHT[0] > (c->xmax<<1)) P_TOPRIGHT[0]= (c->xmax<<1);
|
---|
925 | if(P_TOPRIGHT[1] > (c->ymax<<1)) P_TOPRIGHT[1]= (c->ymax<<1);
|
---|
926 |
|
---|
927 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
928 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
929 | }
|
---|
930 | P_MV1[0]= mx; //FIXME not correct if block != field_select
|
---|
931 | P_MV1[1]= my / 2;
|
---|
932 |
|
---|
933 | dmin = epzs_motion_search2(s, &mx_i, &my_i, P, block, field_select+ref_index, mv_table, (1<<16)>>1);
|
---|
934 |
|
---|
935 | dmin= c->sub_motion_search(s, &mx_i, &my_i, dmin, block, field_select+ref_index, size, h);
|
---|
936 |
|
---|
937 | mv_table[xy][0]= mx_i;
|
---|
938 | mv_table[xy][1]= my_i;
|
---|
939 |
|
---|
940 | if(s->dsp.me_sub_cmp[0] != s->dsp.mb_cmp[0]){
|
---|
941 | int dxy;
|
---|
942 |
|
---|
943 | //FIXME chroma ME
|
---|
944 | uint8_t *ref= c->ref[field_select+ref_index][0] + (mx_i>>1) + (my_i>>1)*stride;
|
---|
945 | dxy = ((my_i & 1) << 1) | (mx_i & 1);
|
---|
946 |
|
---|
947 | if(s->no_rounding){
|
---|
948 | s->dsp.put_no_rnd_pixels_tab[size][dxy](c->scratchpad, ref , stride, h);
|
---|
949 | }else{
|
---|
950 | s->dsp.put_pixels_tab [size][dxy](c->scratchpad, ref , stride, h);
|
---|
951 | }
|
---|
952 | dmin= s->dsp.mb_cmp[size](s, c->src[block][0], c->scratchpad, stride, h);
|
---|
953 | dmin+= (mv_penalty[mx_i-c->pred_x] + mv_penalty[my_i-c->pred_y] + 1)*c->mb_penalty_factor;
|
---|
954 | }else
|
---|
955 | dmin+= c->mb_penalty_factor; //field_select bits
|
---|
956 |
|
---|
957 | dmin += field_select != block; //slightly prefer same field
|
---|
958 |
|
---|
959 | if(dmin < best_dmin){
|
---|
960 | best_dmin= dmin;
|
---|
961 | best_field= field_select;
|
---|
962 | }
|
---|
963 | }
|
---|
964 | {
|
---|
965 | int16_t (*mv_table)[2]= mv_tables[block][best_field];
|
---|
966 |
|
---|
967 | if(mv_table[xy][0] != mx) same=0; //FIXME check if these checks work and are any good at all
|
---|
968 | if(mv_table[xy][1]&1) same=0;
|
---|
969 | if(mv_table[xy][1]*2 != my) same=0;
|
---|
970 | if(best_field != block) same=0;
|
---|
971 | }
|
---|
972 |
|
---|
973 | field_select_tables[block][xy]= best_field;
|
---|
974 | dmin_sum += best_dmin;
|
---|
975 | }
|
---|
976 |
|
---|
977 | c->ymin<<=1;
|
---|
978 | c->ymax<<=1;
|
---|
979 | c->stride>>=1;
|
---|
980 | c->uvstride>>=1;
|
---|
981 |
|
---|
982 | if(same)
|
---|
983 | return INT_MAX;
|
---|
984 |
|
---|
985 | switch(c->avctx->mb_cmp&0xFF){
|
---|
986 | /*case FF_CMP_SSE:
|
---|
987 | return dmin_sum+ 32*s->qscale*s->qscale;*/
|
---|
988 | case FF_CMP_RD:
|
---|
989 | return dmin_sum;
|
---|
990 | default:
|
---|
991 | return dmin_sum+ 11*c->mb_penalty_factor;
|
---|
992 | }
|
---|
993 | }
|
---|
994 |
|
---|
995 | static void clip_input_mv(MpegEncContext * s, int16_t *mv, int interlaced){
|
---|
996 | int ymax= s->me.ymax>>interlaced;
|
---|
997 | int ymin= s->me.ymin>>interlaced;
|
---|
998 |
|
---|
999 | if(mv[0] < s->me.xmin) mv[0] = s->me.xmin;
|
---|
1000 | if(mv[0] > s->me.xmax) mv[0] = s->me.xmax;
|
---|
1001 | if(mv[1] < ymin) mv[1] = ymin;
|
---|
1002 | if(mv[1] > ymax) mv[1] = ymax;
|
---|
1003 | }
|
---|
1004 |
|
---|
1005 | static inline int check_input_motion(MpegEncContext * s, int mb_x, int mb_y, int p_type){
|
---|
1006 | MotionEstContext * const c= &s->me;
|
---|
1007 | Picture *p= s->current_picture_ptr;
|
---|
1008 | int mb_xy= mb_x + mb_y*s->mb_stride;
|
---|
1009 | int xy= 2*mb_x + 2*mb_y*s->b8_stride;
|
---|
1010 | int mb_type= s->current_picture.mb_type[mb_xy];
|
---|
1011 | int flags= c->flags;
|
---|
1012 | int shift= (flags&FLAG_QPEL) + 1;
|
---|
1013 | int mask= (1<<shift)-1;
|
---|
1014 | int x, y, i;
|
---|
1015 | int d=0;
|
---|
1016 | me_cmp_func cmpf= s->dsp.sse[0];
|
---|
1017 | me_cmp_func chroma_cmpf= s->dsp.sse[1];
|
---|
1018 |
|
---|
1019 | if(p_type && USES_LIST(mb_type, 1)){
|
---|
1020 | av_log(c->avctx, AV_LOG_ERROR, "backward motion vector in P frame\n");
|
---|
1021 | return INT_MAX/2;
|
---|
1022 | }
|
---|
1023 | assert(IS_INTRA(mb_type) || USES_LIST(mb_type,0) || USES_LIST(mb_type,1));
|
---|
1024 |
|
---|
1025 | for(i=0; i<4; i++){
|
---|
1026 | int xy= s->block_index[i];
|
---|
1027 | clip_input_mv(s, p->motion_val[0][xy], !!IS_INTERLACED(mb_type));
|
---|
1028 | clip_input_mv(s, p->motion_val[1][xy], !!IS_INTERLACED(mb_type));
|
---|
1029 | }
|
---|
1030 |
|
---|
1031 | if(IS_INTERLACED(mb_type)){
|
---|
1032 | int xy2= xy + s->b8_stride;
|
---|
1033 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
|
---|
1034 | c->stride<<=1;
|
---|
1035 | c->uvstride<<=1;
|
---|
1036 |
|
---|
1037 | if(!(s->flags & CODEC_FLAG_INTERLACED_ME)){
|
---|
1038 | av_log(c->avctx, AV_LOG_ERROR, "Interlaced macroblock selected but interlaced motion estimation disabled\n");
|
---|
1039 | return INT_MAX/2;
|
---|
1040 | }
|
---|
1041 |
|
---|
1042 | if(USES_LIST(mb_type, 0)){
|
---|
1043 | int field_select0= p->ref_index[0][xy ];
|
---|
1044 | int field_select1= p->ref_index[0][xy2];
|
---|
1045 | assert(field_select0==0 ||field_select0==1);
|
---|
1046 | assert(field_select1==0 ||field_select1==1);
|
---|
1047 | init_interlaced_ref(s, 0);
|
---|
1048 |
|
---|
1049 | if(p_type){
|
---|
1050 | s->p_field_select_table[0][mb_xy]= field_select0;
|
---|
1051 | s->p_field_select_table[1][mb_xy]= field_select1;
|
---|
1052 | *(uint32_t*)s->p_field_mv_table[0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
|
---|
1053 | *(uint32_t*)s->p_field_mv_table[1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
|
---|
1054 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER_I;
|
---|
1055 | }else{
|
---|
1056 | s->b_field_select_table[0][0][mb_xy]= field_select0;
|
---|
1057 | s->b_field_select_table[0][1][mb_xy]= field_select1;
|
---|
1058 | *(uint32_t*)s->b_field_mv_table[0][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[0][xy ];
|
---|
1059 | *(uint32_t*)s->b_field_mv_table[0][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[0][xy2];
|
---|
1060 | s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_FORWARD_I;
|
---|
1061 | }
|
---|
1062 |
|
---|
1063 | x= p->motion_val[0][xy ][0];
|
---|
1064 | y= p->motion_val[0][xy ][1];
|
---|
1065 | d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0, 0, cmpf, chroma_cmpf, flags);
|
---|
1066 | x= p->motion_val[0][xy2][0];
|
---|
1067 | y= p->motion_val[0][xy2][1];
|
---|
1068 | d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1, 1, cmpf, chroma_cmpf, flags);
|
---|
1069 | }
|
---|
1070 | if(USES_LIST(mb_type, 1)){
|
---|
1071 | int field_select0= p->ref_index[1][xy ];
|
---|
1072 | int field_select1= p->ref_index[1][xy2];
|
---|
1073 | assert(field_select0==0 ||field_select0==1);
|
---|
1074 | assert(field_select1==0 ||field_select1==1);
|
---|
1075 | init_interlaced_ref(s, 2);
|
---|
1076 |
|
---|
1077 | s->b_field_select_table[1][0][mb_xy]= field_select0;
|
---|
1078 | s->b_field_select_table[1][1][mb_xy]= field_select1;
|
---|
1079 | *(uint32_t*)s->b_field_mv_table[1][0][field_select0][mb_xy]= *(uint32_t*)p->motion_val[1][xy ];
|
---|
1080 | *(uint32_t*)s->b_field_mv_table[1][1][field_select1][mb_xy]= *(uint32_t*)p->motion_val[1][xy2];
|
---|
1081 | if(USES_LIST(mb_type, 0)){
|
---|
1082 | s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BIDIR_I;
|
---|
1083 | }else{
|
---|
1084 | s->mb_type[mb_xy]= CANDIDATE_MB_TYPE_BACKWARD_I;
|
---|
1085 | }
|
---|
1086 |
|
---|
1087 | x= p->motion_val[1][xy ][0];
|
---|
1088 | y= p->motion_val[1][xy ][1];
|
---|
1089 | d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select0+2, 0, cmpf, chroma_cmpf, flags);
|
---|
1090 | x= p->motion_val[1][xy2][0];
|
---|
1091 | y= p->motion_val[1][xy2][1];
|
---|
1092 | d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 8, field_select1+2, 1, cmpf, chroma_cmpf, flags);
|
---|
1093 | //FIXME bidir scores
|
---|
1094 | }
|
---|
1095 | c->stride>>=1;
|
---|
1096 | c->uvstride>>=1;
|
---|
1097 | }else if(IS_8X8(mb_type)){
|
---|
1098 | if(!(s->flags & CODEC_FLAG_4MV)){
|
---|
1099 | av_log(c->avctx, AV_LOG_ERROR, "4MV macroblock selected but 4MV encoding disabled\n");
|
---|
1100 | return INT_MAX/2;
|
---|
1101 | }
|
---|
1102 | cmpf= s->dsp.sse[1];
|
---|
1103 | chroma_cmpf= s->dsp.sse[1];
|
---|
1104 | init_mv4_ref(c);
|
---|
1105 | for(i=0; i<4; i++){
|
---|
1106 | xy= s->block_index[i];
|
---|
1107 | x= p->motion_val[0][xy][0];
|
---|
1108 | y= p->motion_val[0][xy][1];
|
---|
1109 | d+= cmp(s, x>>shift, y>>shift, x&mask, y&mask, 1, 8, i, i, cmpf, chroma_cmpf, flags);
|
---|
1110 | }
|
---|
1111 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER4V;
|
---|
1112 | }else{
|
---|
1113 | if(USES_LIST(mb_type, 0)){
|
---|
1114 | if(p_type){
|
---|
1115 | *(uint32_t*)s->p_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
|
---|
1116 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTER;
|
---|
1117 | }else if(USES_LIST(mb_type, 1)){
|
---|
1118 | *(uint32_t*)s->b_bidir_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
|
---|
1119 | *(uint32_t*)s->b_bidir_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
|
---|
1120 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BIDIR;
|
---|
1121 | }else{
|
---|
1122 | *(uint32_t*)s->b_forw_mv_table[mb_xy]= *(uint32_t*)p->motion_val[0][xy];
|
---|
1123 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_FORWARD;
|
---|
1124 | }
|
---|
1125 | x= p->motion_val[0][xy][0];
|
---|
1126 | y= p->motion_val[0][xy][1];
|
---|
1127 | d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 0, 0, cmpf, chroma_cmpf, flags);
|
---|
1128 | }else if(USES_LIST(mb_type, 1)){
|
---|
1129 | *(uint32_t*)s->b_back_mv_table[mb_xy]= *(uint32_t*)p->motion_val[1][xy];
|
---|
1130 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_BACKWARD;
|
---|
1131 |
|
---|
1132 | x= p->motion_val[1][xy][0];
|
---|
1133 | y= p->motion_val[1][xy][1];
|
---|
1134 | d = cmp(s, x>>shift, y>>shift, x&mask, y&mask, 0, 16, 2, 0, cmpf, chroma_cmpf, flags);
|
---|
1135 | }else
|
---|
1136 | s->mb_type[mb_xy]=CANDIDATE_MB_TYPE_INTRA;
|
---|
1137 | }
|
---|
1138 | return d;
|
---|
1139 | }
|
---|
1140 |
|
---|
1141 | void ff_estimate_p_frame_motion(MpegEncContext * s,
|
---|
1142 | int mb_x, int mb_y)
|
---|
1143 | {
|
---|
1144 | MotionEstContext * const c= &s->me;
|
---|
1145 | uint8_t *pix, *ppix;
|
---|
1146 | int sum, varc, vard, mx, my, dmin;
|
---|
1147 | int P[10][2];
|
---|
1148 | const int shift= 1+s->quarter_sample;
|
---|
1149 | int mb_type=0;
|
---|
1150 | Picture * const pic= &s->current_picture;
|
---|
1151 |
|
---|
1152 | init_ref(c, s->new_picture.data, s->last_picture.data, NULL, 16*mb_x, 16*mb_y, 0);
|
---|
1153 |
|
---|
1154 | assert(s->quarter_sample==0 || s->quarter_sample==1);
|
---|
1155 | assert(s->linesize == c->stride);
|
---|
1156 | assert(s->uvlinesize == c->uvstride);
|
---|
1157 |
|
---|
1158 | c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
|
---|
1159 | c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
|
---|
1160 | c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
|
---|
1161 | c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
|
---|
1162 |
|
---|
1163 | get_limits(s, 16*mb_x, 16*mb_y);
|
---|
1164 | c->skip=0;
|
---|
1165 |
|
---|
1166 | /* intra / predictive decision */
|
---|
1167 | pix = c->src[0][0];
|
---|
1168 | sum = s->dsp.pix_sum(pix, s->linesize);
|
---|
1169 | varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500;
|
---|
1170 |
|
---|
1171 | pic->mb_mean[s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
|
---|
1172 | pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
|
---|
1173 | c->mb_var_sum_temp += (varc+128)>>8;
|
---|
1174 |
|
---|
1175 | if(c->avctx->me_threshold){
|
---|
1176 | vard= check_input_motion(s, mb_x, mb_y, 1);
|
---|
1177 |
|
---|
1178 | if((vard+128)>>8 < c->avctx->me_threshold){
|
---|
1179 | pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
|
---|
1180 | c->mc_mb_var_sum_temp += (vard+128)>>8;
|
---|
1181 | if (vard <= 64<<8 || vard < varc) { //FIXME
|
---|
1182 | c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
|
---|
1183 | }else{
|
---|
1184 | c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
|
---|
1185 | }
|
---|
1186 | return;
|
---|
1187 | }
|
---|
1188 | if((vard+128)>>8 < c->avctx->mb_threshold)
|
---|
1189 | mb_type= s->mb_type[mb_x + mb_y*s->mb_stride];
|
---|
1190 | }
|
---|
1191 |
|
---|
1192 | switch(s->me_method) {
|
---|
1193 | case ME_ZERO:
|
---|
1194 | default:
|
---|
1195 | no_motion_search(s, &mx, &my);
|
---|
1196 | mx-= mb_x*16;
|
---|
1197 | my-= mb_y*16;
|
---|
1198 | dmin = 0;
|
---|
1199 | break;
|
---|
1200 | #if 0
|
---|
1201 | case ME_FULL:
|
---|
1202 | dmin = full_motion_search(s, &mx, &my, range, ref_picture);
|
---|
1203 | mx-= mb_x*16;
|
---|
1204 | my-= mb_y*16;
|
---|
1205 | break;
|
---|
1206 | case ME_LOG:
|
---|
1207 | dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
|
---|
1208 | mx-= mb_x*16;
|
---|
1209 | my-= mb_y*16;
|
---|
1210 | break;
|
---|
1211 | case ME_PHODS:
|
---|
1212 | dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
|
---|
1213 | mx-= mb_x*16;
|
---|
1214 | my-= mb_y*16;
|
---|
1215 | break;
|
---|
1216 | #endif
|
---|
1217 | case ME_X1:
|
---|
1218 | case ME_EPZS:
|
---|
1219 | {
|
---|
1220 | const int mot_stride = s->b8_stride;
|
---|
1221 | const int mot_xy = s->block_index[0];
|
---|
1222 |
|
---|
1223 | P_LEFT[0] = s->current_picture.motion_val[0][mot_xy - 1][0];
|
---|
1224 | P_LEFT[1] = s->current_picture.motion_val[0][mot_xy - 1][1];
|
---|
1225 |
|
---|
1226 | if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
|
---|
1227 |
|
---|
1228 | if(!s->first_slice_line) {
|
---|
1229 | P_TOP[0] = s->current_picture.motion_val[0][mot_xy - mot_stride ][0];
|
---|
1230 | P_TOP[1] = s->current_picture.motion_val[0][mot_xy - mot_stride ][1];
|
---|
1231 | P_TOPRIGHT[0] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][0];
|
---|
1232 | P_TOPRIGHT[1] = s->current_picture.motion_val[0][mot_xy - mot_stride + 2][1];
|
---|
1233 | if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1] = (c->ymax<<shift);
|
---|
1234 | if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
|
---|
1235 | if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
|
---|
1236 |
|
---|
1237 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
1238 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
1239 |
|
---|
1240 | if(s->out_format == FMT_H263){
|
---|
1241 | c->pred_x = P_MEDIAN[0];
|
---|
1242 | c->pred_y = P_MEDIAN[1];
|
---|
1243 | }else { /* mpeg1 at least */
|
---|
1244 | c->pred_x= P_LEFT[0];
|
---|
1245 | c->pred_y= P_LEFT[1];
|
---|
1246 | }
|
---|
1247 | }else{
|
---|
1248 | c->pred_x= P_LEFT[0];
|
---|
1249 | c->pred_y= P_LEFT[1];
|
---|
1250 | }
|
---|
1251 |
|
---|
1252 | }
|
---|
1253 | dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
|
---|
1254 |
|
---|
1255 | break;
|
---|
1256 | }
|
---|
1257 |
|
---|
1258 | /* At this point (mx,my) are full-pell and the relative displacement */
|
---|
1259 | ppix = c->ref[0][0] + (my * s->linesize) + mx;
|
---|
1260 |
|
---|
1261 | vard = s->dsp.sse[0](NULL, pix, ppix, s->linesize, 16);
|
---|
1262 |
|
---|
1263 | pic->mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
|
---|
1264 | // pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
|
---|
1265 | c->mc_mb_var_sum_temp += (vard+128)>>8;
|
---|
1266 |
|
---|
1267 | #if 0
|
---|
1268 | printf("varc=%4d avg_var=%4d (sum=%4d) vard=%4d mx=%2d my=%2d\n",
|
---|
1269 | varc, s->avg_mb_var, sum, vard, mx - xx, my - yy);
|
---|
1270 | #endif
|
---|
1271 | if(mb_type){
|
---|
1272 | if (vard <= 64<<8 || vard < varc)
|
---|
1273 | c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
|
---|
1274 | else
|
---|
1275 | c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
|
---|
1276 |
|
---|
1277 | if(mb_type == CANDIDATE_MB_TYPE_INTER){
|
---|
1278 | c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
|
---|
1279 | set_p_mv_tables(s, mx, my, 1);
|
---|
1280 | }else{
|
---|
1281 | mx <<=shift;
|
---|
1282 | my <<=shift;
|
---|
1283 | }
|
---|
1284 | if(mb_type == CANDIDATE_MB_TYPE_INTER4V){
|
---|
1285 | h263_mv4_search(s, mx, my, shift);
|
---|
1286 |
|
---|
1287 | set_p_mv_tables(s, mx, my, 0);
|
---|
1288 | }
|
---|
1289 | if(mb_type == CANDIDATE_MB_TYPE_INTER_I){
|
---|
1290 | interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 1);
|
---|
1291 | }
|
---|
1292 | }else if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
|
---|
1293 | if (vard <= 64<<8 || vard < varc)
|
---|
1294 | c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
|
---|
1295 | else
|
---|
1296 | c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
|
---|
1297 |
|
---|
1298 | if (vard*2 + 200*256 > varc)
|
---|
1299 | mb_type|= CANDIDATE_MB_TYPE_INTRA;
|
---|
1300 | if (varc*2 + 200*256 > vard){
|
---|
1301 | mb_type|= CANDIDATE_MB_TYPE_INTER;
|
---|
1302 | c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
|
---|
1303 | if(s->flags&CODEC_FLAG_MV0)
|
---|
1304 | if(mx || my)
|
---|
1305 | mb_type |= CANDIDATE_MB_TYPE_SKIPPED; //FIXME check difference
|
---|
1306 | }else{
|
---|
1307 | mx <<=shift;
|
---|
1308 | my <<=shift;
|
---|
1309 | }
|
---|
1310 | if((s->flags&CODEC_FLAG_4MV)
|
---|
1311 | && !c->skip && varc>50<<8 && vard>10<<8){
|
---|
1312 | if(h263_mv4_search(s, mx, my, shift) < INT_MAX)
|
---|
1313 | mb_type|=CANDIDATE_MB_TYPE_INTER4V;
|
---|
1314 |
|
---|
1315 | set_p_mv_tables(s, mx, my, 0);
|
---|
1316 | }else
|
---|
1317 | set_p_mv_tables(s, mx, my, 1);
|
---|
1318 | if((s->flags&CODEC_FLAG_INTERLACED_ME)
|
---|
1319 | && !c->skip){ //FIXME varc/d checks
|
---|
1320 | if(interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0) < INT_MAX)
|
---|
1321 | mb_type |= CANDIDATE_MB_TYPE_INTER_I;
|
---|
1322 | }
|
---|
1323 | }else{
|
---|
1324 | int intra_score, i;
|
---|
1325 | mb_type= CANDIDATE_MB_TYPE_INTER;
|
---|
1326 |
|
---|
1327 | dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
|
---|
1328 | if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
|
---|
1329 | dmin= ff_get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
|
---|
1330 |
|
---|
1331 | if((s->flags&CODEC_FLAG_4MV)
|
---|
1332 | && !c->skip && varc>50<<8 && vard>10<<8){
|
---|
1333 | int dmin4= h263_mv4_search(s, mx, my, shift);
|
---|
1334 | if(dmin4 < dmin){
|
---|
1335 | mb_type= CANDIDATE_MB_TYPE_INTER4V;
|
---|
1336 | dmin=dmin4;
|
---|
1337 | }
|
---|
1338 | }
|
---|
1339 | if((s->flags&CODEC_FLAG_INTERLACED_ME)
|
---|
1340 | && !c->skip){ //FIXME varc/d checks
|
---|
1341 | int dmin_i= interlaced_search(s, 0, s->p_field_mv_table, s->p_field_select_table, mx, my, 0);
|
---|
1342 | if(dmin_i < dmin){
|
---|
1343 | mb_type = CANDIDATE_MB_TYPE_INTER_I;
|
---|
1344 | dmin= dmin_i;
|
---|
1345 | }
|
---|
1346 | }
|
---|
1347 |
|
---|
1348 | // pic->mb_cmp_score[s->mb_stride * mb_y + mb_x] = dmin;
|
---|
1349 | set_p_mv_tables(s, mx, my, mb_type!=CANDIDATE_MB_TYPE_INTER4V);
|
---|
1350 |
|
---|
1351 | /* get intra luma score */
|
---|
1352 | if((c->avctx->mb_cmp&0xFF)==FF_CMP_SSE){
|
---|
1353 | intra_score= varc - 500;
|
---|
1354 | }else{
|
---|
1355 | int mean= (sum+128)>>8;
|
---|
1356 | mean*= 0x01010101;
|
---|
1357 |
|
---|
1358 | for(i=0; i<16; i++){
|
---|
1359 | *(uint32_t*)(&c->scratchpad[i*s->linesize+ 0]) = mean;
|
---|
1360 | *(uint32_t*)(&c->scratchpad[i*s->linesize+ 4]) = mean;
|
---|
1361 | *(uint32_t*)(&c->scratchpad[i*s->linesize+ 8]) = mean;
|
---|
1362 | *(uint32_t*)(&c->scratchpad[i*s->linesize+12]) = mean;
|
---|
1363 | }
|
---|
1364 |
|
---|
1365 | intra_score= s->dsp.mb_cmp[0](s, c->scratchpad, pix, s->linesize, 16);
|
---|
1366 | }
|
---|
1367 | #if 0 //FIXME
|
---|
1368 | /* get chroma score */
|
---|
1369 | if(c->avctx->mb_cmp&FF_CMP_CHROMA){
|
---|
1370 | for(i=1; i<3; i++){
|
---|
1371 | uint8_t *dest_c;
|
---|
1372 | int mean;
|
---|
1373 |
|
---|
1374 | if(s->out_format == FMT_H263){
|
---|
1375 | mean= (s->dc_val[i][mb_x + mb_y*s->b8_stride] + 4)>>3; //FIXME not exact but simple ;)
|
---|
1376 | }else{
|
---|
1377 | mean= (s->last_dc[i] + 4)>>3;
|
---|
1378 | }
|
---|
1379 | dest_c = s->new_picture.data[i] + (mb_y * 8 * (s->uvlinesize)) + mb_x * 8;
|
---|
1380 |
|
---|
1381 | mean*= 0x01010101;
|
---|
1382 | for(i=0; i<8; i++){
|
---|
1383 | *(uint32_t*)(&c->scratchpad[i*s->uvlinesize+ 0]) = mean;
|
---|
1384 | *(uint32_t*)(&c->scratchpad[i*s->uvlinesize+ 4]) = mean;
|
---|
1385 | }
|
---|
1386 |
|
---|
1387 | intra_score+= s->dsp.mb_cmp[1](s, c->scratchpad, dest_c, s->uvlinesize);
|
---|
1388 | }
|
---|
1389 | }
|
---|
1390 | #endif
|
---|
1391 | intra_score += c->mb_penalty_factor*16;
|
---|
1392 |
|
---|
1393 | if(intra_score < dmin){
|
---|
1394 | mb_type= CANDIDATE_MB_TYPE_INTRA;
|
---|
1395 | s->current_picture.mb_type[mb_y*s->mb_stride + mb_x]= CANDIDATE_MB_TYPE_INTRA; //FIXME cleanup
|
---|
1396 | }else
|
---|
1397 | s->current_picture.mb_type[mb_y*s->mb_stride + mb_x]= 0;
|
---|
1398 |
|
---|
1399 | if (vard <= 64<<8 || vard < varc) { //FIXME
|
---|
1400 | c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
|
---|
1401 | }else{
|
---|
1402 | c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
|
---|
1403 | }
|
---|
1404 | }
|
---|
1405 |
|
---|
1406 | s->mb_type[mb_y*s->mb_stride + mb_x]= mb_type;
|
---|
1407 | }
|
---|
1408 |
|
---|
1409 | int ff_pre_estimate_p_frame_motion(MpegEncContext * s,
|
---|
1410 | int mb_x, int mb_y)
|
---|
1411 | {
|
---|
1412 | MotionEstContext * const c= &s->me;
|
---|
1413 | int mx, my, dmin;
|
---|
1414 | int P[10][2];
|
---|
1415 | const int shift= 1+s->quarter_sample;
|
---|
1416 | const int xy= mb_x + mb_y*s->mb_stride;
|
---|
1417 | init_ref(c, s->new_picture.data, s->last_picture.data, NULL, 16*mb_x, 16*mb_y, 0);
|
---|
1418 |
|
---|
1419 | assert(s->quarter_sample==0 || s->quarter_sample==1);
|
---|
1420 |
|
---|
1421 | c->pre_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_pre_cmp);
|
---|
1422 | c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
|
---|
1423 |
|
---|
1424 | get_limits(s, 16*mb_x, 16*mb_y);
|
---|
1425 | c->skip=0;
|
---|
1426 |
|
---|
1427 | P_LEFT[0] = s->p_mv_table[xy + 1][0];
|
---|
1428 | P_LEFT[1] = s->p_mv_table[xy + 1][1];
|
---|
1429 |
|
---|
1430 | if(P_LEFT[0] < (c->xmin<<shift)) P_LEFT[0] = (c->xmin<<shift);
|
---|
1431 |
|
---|
1432 | /* special case for first line */
|
---|
1433 | if (s->first_slice_line) {
|
---|
1434 | c->pred_x= P_LEFT[0];
|
---|
1435 | c->pred_y= P_LEFT[1];
|
---|
1436 | P_TOP[0]= P_TOPRIGHT[0]= P_MEDIAN[0]=
|
---|
1437 | P_TOP[1]= P_TOPRIGHT[1]= P_MEDIAN[1]= 0; //FIXME
|
---|
1438 | } else {
|
---|
1439 | P_TOP[0] = s->p_mv_table[xy + s->mb_stride ][0];
|
---|
1440 | P_TOP[1] = s->p_mv_table[xy + s->mb_stride ][1];
|
---|
1441 | P_TOPRIGHT[0] = s->p_mv_table[xy + s->mb_stride - 1][0];
|
---|
1442 | P_TOPRIGHT[1] = s->p_mv_table[xy + s->mb_stride - 1][1];
|
---|
1443 | if(P_TOP[1] < (c->ymin<<shift)) P_TOP[1] = (c->ymin<<shift);
|
---|
1444 | if(P_TOPRIGHT[0] > (c->xmax<<shift)) P_TOPRIGHT[0]= (c->xmax<<shift);
|
---|
1445 | if(P_TOPRIGHT[1] < (c->ymin<<shift)) P_TOPRIGHT[1]= (c->ymin<<shift);
|
---|
1446 |
|
---|
1447 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
1448 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
1449 |
|
---|
1450 | c->pred_x = P_MEDIAN[0];
|
---|
1451 | c->pred_y = P_MEDIAN[1];
|
---|
1452 | }
|
---|
1453 |
|
---|
1454 | dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, s->p_mv_table, (1<<16)>>shift, 0, 16);
|
---|
1455 |
|
---|
1456 | s->p_mv_table[xy][0] = mx<<shift;
|
---|
1457 | s->p_mv_table[xy][1] = my<<shift;
|
---|
1458 |
|
---|
1459 | return dmin;
|
---|
1460 | }
|
---|
1461 |
|
---|
1462 | static int ff_estimate_motion_b(MpegEncContext * s,
|
---|
1463 | int mb_x, int mb_y, int16_t (*mv_table)[2], int ref_index, int f_code)
|
---|
1464 | {
|
---|
1465 | MotionEstContext * const c= &s->me;
|
---|
1466 | int mx, my, dmin;
|
---|
1467 | int P[10][2];
|
---|
1468 | const int shift= 1+s->quarter_sample;
|
---|
1469 | const int mot_stride = s->mb_stride;
|
---|
1470 | const int mot_xy = mb_y*mot_stride + mb_x;
|
---|
1471 | uint8_t * const mv_penalty= c->mv_penalty[f_code] + MAX_MV;
|
---|
1472 | int mv_scale;
|
---|
1473 |
|
---|
1474 | c->penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_cmp);
|
---|
1475 | c->sub_penalty_factor= get_penalty_factor(s->lambda, s->lambda2, c->avctx->me_sub_cmp);
|
---|
1476 | c->mb_penalty_factor = get_penalty_factor(s->lambda, s->lambda2, c->avctx->mb_cmp);
|
---|
1477 | c->current_mv_penalty= mv_penalty;
|
---|
1478 |
|
---|
1479 | get_limits(s, 16*mb_x, 16*mb_y);
|
---|
1480 |
|
---|
1481 | switch(s->me_method) {
|
---|
1482 | case ME_ZERO:
|
---|
1483 | default:
|
---|
1484 | no_motion_search(s, &mx, &my);
|
---|
1485 | dmin = 0;
|
---|
1486 | mx-= mb_x*16;
|
---|
1487 | my-= mb_y*16;
|
---|
1488 | break;
|
---|
1489 | #if 0
|
---|
1490 | case ME_FULL:
|
---|
1491 | dmin = full_motion_search(s, &mx, &my, range, ref_picture);
|
---|
1492 | mx-= mb_x*16;
|
---|
1493 | my-= mb_y*16;
|
---|
1494 | break;
|
---|
1495 | case ME_LOG:
|
---|
1496 | dmin = log_motion_search(s, &mx, &my, range / 2, ref_picture);
|
---|
1497 | mx-= mb_x*16;
|
---|
1498 | my-= mb_y*16;
|
---|
1499 | break;
|
---|
1500 | case ME_PHODS:
|
---|
1501 | dmin = phods_motion_search(s, &mx, &my, range / 2, ref_picture);
|
---|
1502 | mx-= mb_x*16;
|
---|
1503 | my-= mb_y*16;
|
---|
1504 | break;
|
---|
1505 | #endif
|
---|
1506 | case ME_X1:
|
---|
1507 | case ME_EPZS:
|
---|
1508 | {
|
---|
1509 | P_LEFT[0] = mv_table[mot_xy - 1][0];
|
---|
1510 | P_LEFT[1] = mv_table[mot_xy - 1][1];
|
---|
1511 |
|
---|
1512 | if(P_LEFT[0] > (c->xmax<<shift)) P_LEFT[0] = (c->xmax<<shift);
|
---|
1513 |
|
---|
1514 | /* special case for first line */
|
---|
1515 | if (!s->first_slice_line) {
|
---|
1516 | P_TOP[0] = mv_table[mot_xy - mot_stride ][0];
|
---|
1517 | P_TOP[1] = mv_table[mot_xy - mot_stride ][1];
|
---|
1518 | P_TOPRIGHT[0] = mv_table[mot_xy - mot_stride + 1 ][0];
|
---|
1519 | P_TOPRIGHT[1] = mv_table[mot_xy - mot_stride + 1 ][1];
|
---|
1520 | if(P_TOP[1] > (c->ymax<<shift)) P_TOP[1]= (c->ymax<<shift);
|
---|
1521 | if(P_TOPRIGHT[0] < (c->xmin<<shift)) P_TOPRIGHT[0]= (c->xmin<<shift);
|
---|
1522 | if(P_TOPRIGHT[1] > (c->ymax<<shift)) P_TOPRIGHT[1]= (c->ymax<<shift);
|
---|
1523 |
|
---|
1524 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
1525 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
1526 | }
|
---|
1527 | c->pred_x= P_LEFT[0];
|
---|
1528 | c->pred_y= P_LEFT[1];
|
---|
1529 | }
|
---|
1530 |
|
---|
1531 | if(mv_table == s->b_forw_mv_table){
|
---|
1532 | mv_scale= (s->pb_time<<16) / (s->pp_time<<shift);
|
---|
1533 | }else{
|
---|
1534 | mv_scale= ((s->pb_time - s->pp_time)<<16) / (s->pp_time<<shift);
|
---|
1535 | }
|
---|
1536 |
|
---|
1537 | dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, ref_index, s->p_mv_table, mv_scale, 0, 16);
|
---|
1538 |
|
---|
1539 | break;
|
---|
1540 | }
|
---|
1541 |
|
---|
1542 | dmin= c->sub_motion_search(s, &mx, &my, dmin, 0, ref_index, 0, 16);
|
---|
1543 |
|
---|
1544 | if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
|
---|
1545 | dmin= ff_get_mb_score(s, mx, my, 0, ref_index, 0, 16, 1);
|
---|
1546 |
|
---|
1547 | //printf("%d %d %d %d//", s->mb_x, s->mb_y, mx, my);
|
---|
1548 | // s->mb_type[mb_y*s->mb_width + mb_x]= mb_type;
|
---|
1549 | mv_table[mot_xy][0]= mx;
|
---|
1550 | mv_table[mot_xy][1]= my;
|
---|
1551 |
|
---|
1552 | return dmin;
|
---|
1553 | }
|
---|
1554 |
|
---|
1555 | static inline int check_bidir_mv(MpegEncContext * s,
|
---|
1556 | int motion_fx, int motion_fy,
|
---|
1557 | int motion_bx, int motion_by,
|
---|
1558 | int pred_fx, int pred_fy,
|
---|
1559 | int pred_bx, int pred_by,
|
---|
1560 | int size, int h)
|
---|
1561 | {
|
---|
1562 | //FIXME optimize?
|
---|
1563 | //FIXME better f_code prediction (max mv & distance)
|
---|
1564 | //FIXME pointers
|
---|
1565 | MotionEstContext * const c= &s->me;
|
---|
1566 | uint8_t * const mv_penalty_f= c->mv_penalty[s->f_code] + MAX_MV; // f_code of the prev frame
|
---|
1567 | uint8_t * const mv_penalty_b= c->mv_penalty[s->b_code] + MAX_MV; // f_code of the prev frame
|
---|
1568 | int stride= c->stride;
|
---|
1569 | uint8_t *dest_y = c->scratchpad;
|
---|
1570 | uint8_t *ptr;
|
---|
1571 | int dxy;
|
---|
1572 | int src_x, src_y;
|
---|
1573 | int fbmin;
|
---|
1574 | uint8_t **src_data= c->src[0];
|
---|
1575 | uint8_t **ref_data= c->ref[0];
|
---|
1576 | uint8_t **ref2_data= c->ref[2];
|
---|
1577 |
|
---|
1578 | if(s->quarter_sample){
|
---|
1579 | dxy = ((motion_fy & 3) << 2) | (motion_fx & 3);
|
---|
1580 | src_x = motion_fx >> 2;
|
---|
1581 | src_y = motion_fy >> 2;
|
---|
1582 |
|
---|
1583 | ptr = ref_data[0] + (src_y * stride) + src_x;
|
---|
1584 | s->dsp.put_qpel_pixels_tab[0][dxy](dest_y , ptr , stride);
|
---|
1585 |
|
---|
1586 | dxy = ((motion_by & 3) << 2) | (motion_bx & 3);
|
---|
1587 | src_x = motion_bx >> 2;
|
---|
1588 | src_y = motion_by >> 2;
|
---|
1589 |
|
---|
1590 | ptr = ref2_data[0] + (src_y * stride) + src_x;
|
---|
1591 | s->dsp.avg_qpel_pixels_tab[size][dxy](dest_y , ptr , stride);
|
---|
1592 | }else{
|
---|
1593 | dxy = ((motion_fy & 1) << 1) | (motion_fx & 1);
|
---|
1594 | src_x = motion_fx >> 1;
|
---|
1595 | src_y = motion_fy >> 1;
|
---|
1596 |
|
---|
1597 | ptr = ref_data[0] + (src_y * stride) + src_x;
|
---|
1598 | s->dsp.put_pixels_tab[size][dxy](dest_y , ptr , stride, h);
|
---|
1599 |
|
---|
1600 | dxy = ((motion_by & 1) << 1) | (motion_bx & 1);
|
---|
1601 | src_x = motion_bx >> 1;
|
---|
1602 | src_y = motion_by >> 1;
|
---|
1603 |
|
---|
1604 | ptr = ref2_data[0] + (src_y * stride) + src_x;
|
---|
1605 | s->dsp.avg_pixels_tab[size][dxy](dest_y , ptr , stride, h);
|
---|
1606 | }
|
---|
1607 |
|
---|
1608 | fbmin = (mv_penalty_f[motion_fx-pred_fx] + mv_penalty_f[motion_fy-pred_fy])*c->mb_penalty_factor
|
---|
1609 | +(mv_penalty_b[motion_bx-pred_bx] + mv_penalty_b[motion_by-pred_by])*c->mb_penalty_factor
|
---|
1610 | + s->dsp.mb_cmp[size](s, src_data[0], dest_y, stride, h); //FIXME new_pic
|
---|
1611 |
|
---|
1612 | if(c->avctx->mb_cmp&FF_CMP_CHROMA){
|
---|
1613 | }
|
---|
1614 | //FIXME CHROMA !!!
|
---|
1615 |
|
---|
1616 | return fbmin;
|
---|
1617 | }
|
---|
1618 |
|
---|
1619 | /* refine the bidir vectors in hq mode and return the score in both lq & hq mode*/
|
---|
1620 | static inline int bidir_refine(MpegEncContext * s, int mb_x, int mb_y)
|
---|
1621 | {
|
---|
1622 | MotionEstContext * const c= &s->me;
|
---|
1623 | const int mot_stride = s->mb_stride;
|
---|
1624 | const int xy = mb_y *mot_stride + mb_x;
|
---|
1625 | int fbmin;
|
---|
1626 | int pred_fx= s->b_bidir_forw_mv_table[xy-1][0];
|
---|
1627 | int pred_fy= s->b_bidir_forw_mv_table[xy-1][1];
|
---|
1628 | int pred_bx= s->b_bidir_back_mv_table[xy-1][0];
|
---|
1629 | int pred_by= s->b_bidir_back_mv_table[xy-1][1];
|
---|
1630 | int motion_fx= s->b_bidir_forw_mv_table[xy][0]= s->b_forw_mv_table[xy][0];
|
---|
1631 | int motion_fy= s->b_bidir_forw_mv_table[xy][1]= s->b_forw_mv_table[xy][1];
|
---|
1632 | int motion_bx= s->b_bidir_back_mv_table[xy][0]= s->b_back_mv_table[xy][0];
|
---|
1633 | int motion_by= s->b_bidir_back_mv_table[xy][1]= s->b_back_mv_table[xy][1];
|
---|
1634 | const int flags= c->sub_flags;
|
---|
1635 | const int qpel= flags&FLAG_QPEL;
|
---|
1636 | const int shift= 1+qpel;
|
---|
1637 | const int xmin= c->xmin<<shift;
|
---|
1638 | const int ymin= c->ymin<<shift;
|
---|
1639 | const int xmax= c->xmax<<shift;
|
---|
1640 | const int ymax= c->ymax<<shift;
|
---|
1641 | uint8_t map[8][8][8][8];
|
---|
1642 |
|
---|
1643 | memset(map,0,sizeof(map));
|
---|
1644 | #define BIDIR_MAP(fx,fy,bx,by) \
|
---|
1645 | map[(motion_fx+fx)&7][(motion_fy+fy)&7][(motion_bx+bx)&7][(motion_by+by)&7]
|
---|
1646 | BIDIR_MAP(0,0,0,0) = 1;
|
---|
1647 |
|
---|
1648 | fbmin= check_bidir_mv(s, motion_fx, motion_fy,
|
---|
1649 | motion_bx, motion_by,
|
---|
1650 | pred_fx, pred_fy,
|
---|
1651 | pred_bx, pred_by,
|
---|
1652 | 0, 16);
|
---|
1653 |
|
---|
1654 | if(s->avctx->bidir_refine){
|
---|
1655 | int score, end;
|
---|
1656 | #define CHECK_BIDIR(fx,fy,bx,by)\
|
---|
1657 | if( !BIDIR_MAP(fx,fy,bx,by)\
|
---|
1658 | &&(fx<=0 || motion_fx+fx<=xmax) && (fy<=0 || motion_fy+fy<=ymax) && (bx<=0 || motion_bx+bx<=xmax) && (by<=0 || motion_by+by<=ymax)\
|
---|
1659 | &&(fx>=0 || motion_fx+fx>=xmin) && (fy>=0 || motion_fy+fy>=ymin) && (bx>=0 || motion_bx+bx>=xmin) && (by>=0 || motion_by+by>=ymin)){\
|
---|
1660 | BIDIR_MAP(fx,fy,bx,by) = 1;\
|
---|
1661 | score= check_bidir_mv(s, motion_fx+fx, motion_fy+fy, motion_bx+bx, motion_by+by, pred_fx, pred_fy, pred_bx, pred_by, 0, 16);\
|
---|
1662 | if(score < fbmin){\
|
---|
1663 | fbmin= score;\
|
---|
1664 | motion_fx+=fx;\
|
---|
1665 | motion_fy+=fy;\
|
---|
1666 | motion_bx+=bx;\
|
---|
1667 | motion_by+=by;\
|
---|
1668 | end=0;\
|
---|
1669 | }\
|
---|
1670 | }
|
---|
1671 | #define CHECK_BIDIR2(a,b,c,d)\
|
---|
1672 | CHECK_BIDIR(a,b,c,d)\
|
---|
1673 | CHECK_BIDIR(-a,-b,-c,-d)
|
---|
1674 |
|
---|
1675 | #define CHECK_BIDIRR(a,b,c,d)\
|
---|
1676 | CHECK_BIDIR2(a,b,c,d)\
|
---|
1677 | CHECK_BIDIR2(b,c,d,a)\
|
---|
1678 | CHECK_BIDIR2(c,d,a,b)\
|
---|
1679 | CHECK_BIDIR2(d,a,b,c)
|
---|
1680 |
|
---|
1681 | do{
|
---|
1682 | end=1;
|
---|
1683 |
|
---|
1684 | CHECK_BIDIRR( 0, 0, 0, 1)
|
---|
1685 | if(s->avctx->bidir_refine > 1){
|
---|
1686 | CHECK_BIDIRR( 0, 0, 1, 1)
|
---|
1687 | CHECK_BIDIR2( 0, 1, 0, 1)
|
---|
1688 | CHECK_BIDIR2( 1, 0, 1, 0)
|
---|
1689 | CHECK_BIDIRR( 0, 0,-1, 1)
|
---|
1690 | CHECK_BIDIR2( 0,-1, 0, 1)
|
---|
1691 | CHECK_BIDIR2(-1, 0, 1, 0)
|
---|
1692 | if(s->avctx->bidir_refine > 2){
|
---|
1693 | CHECK_BIDIRR( 0, 1, 1, 1)
|
---|
1694 | CHECK_BIDIRR( 0,-1, 1, 1)
|
---|
1695 | CHECK_BIDIRR( 0, 1,-1, 1)
|
---|
1696 | CHECK_BIDIRR( 0, 1, 1,-1)
|
---|
1697 | if(s->avctx->bidir_refine > 3){
|
---|
1698 | CHECK_BIDIR2( 1, 1, 1, 1)
|
---|
1699 | CHECK_BIDIRR( 1, 1, 1,-1)
|
---|
1700 | CHECK_BIDIR2( 1, 1,-1,-1)
|
---|
1701 | CHECK_BIDIR2( 1,-1,-1, 1)
|
---|
1702 | CHECK_BIDIR2( 1,-1, 1,-1)
|
---|
1703 | }
|
---|
1704 | }
|
---|
1705 | }
|
---|
1706 | }while(!end);
|
---|
1707 | }
|
---|
1708 |
|
---|
1709 | s->b_bidir_forw_mv_table[xy][0]= motion_fx;
|
---|
1710 | s->b_bidir_forw_mv_table[xy][1]= motion_fy;
|
---|
1711 | s->b_bidir_back_mv_table[xy][0]= motion_bx;
|
---|
1712 | s->b_bidir_back_mv_table[xy][1]= motion_by;
|
---|
1713 |
|
---|
1714 | return fbmin;
|
---|
1715 | }
|
---|
1716 |
|
---|
1717 | static inline int direct_search(MpegEncContext * s, int mb_x, int mb_y)
|
---|
1718 | {
|
---|
1719 | MotionEstContext * const c= &s->me;
|
---|
1720 | int P[10][2];
|
---|
1721 | const int mot_stride = s->mb_stride;
|
---|
1722 | const int mot_xy = mb_y*mot_stride + mb_x;
|
---|
1723 | const int shift= 1+s->quarter_sample;
|
---|
1724 | int dmin, i;
|
---|
1725 | const int time_pp= s->pp_time;
|
---|
1726 | const int time_pb= s->pb_time;
|
---|
1727 | int mx, my, xmin, xmax, ymin, ymax;
|
---|
1728 | int16_t (*mv_table)[2]= s->b_direct_mv_table;
|
---|
1729 |
|
---|
1730 | c->current_mv_penalty= c->mv_penalty[1] + MAX_MV;
|
---|
1731 | ymin= xmin=(-32)>>shift;
|
---|
1732 | ymax= xmax= 31>>shift;
|
---|
1733 |
|
---|
1734 | if(IS_8X8(s->next_picture.mb_type[mot_xy])){
|
---|
1735 | s->mv_type= MV_TYPE_8X8;
|
---|
1736 | }else{
|
---|
1737 | s->mv_type= MV_TYPE_16X16;
|
---|
1738 | }
|
---|
1739 |
|
---|
1740 | for(i=0; i<4; i++){
|
---|
1741 | int index= s->block_index[i];
|
---|
1742 | int min, max;
|
---|
1743 |
|
---|
1744 | c->co_located_mv[i][0]= s->next_picture.motion_val[0][index][0];
|
---|
1745 | c->co_located_mv[i][1]= s->next_picture.motion_val[0][index][1];
|
---|
1746 | c->direct_basis_mv[i][0]= c->co_located_mv[i][0]*time_pb/time_pp + ((i& 1)<<(shift+3));
|
---|
1747 | c->direct_basis_mv[i][1]= c->co_located_mv[i][1]*time_pb/time_pp + ((i>>1)<<(shift+3));
|
---|
1748 | // c->direct_basis_mv[1][i][0]= c->co_located_mv[i][0]*(time_pb - time_pp)/time_pp + ((i &1)<<(shift+3);
|
---|
1749 | // c->direct_basis_mv[1][i][1]= c->co_located_mv[i][1]*(time_pb - time_pp)/time_pp + ((i>>1)<<(shift+3);
|
---|
1750 |
|
---|
1751 | max= FFMAX(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
|
---|
1752 | min= FFMIN(c->direct_basis_mv[i][0], c->direct_basis_mv[i][0] - c->co_located_mv[i][0])>>shift;
|
---|
1753 | max+= 16*mb_x + 1; // +-1 is for the simpler rounding
|
---|
1754 | min+= 16*mb_x - 1;
|
---|
1755 | xmax= FFMIN(xmax, s->width - max);
|
---|
1756 | xmin= FFMAX(xmin, - 16 - min);
|
---|
1757 |
|
---|
1758 | max= FFMAX(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
|
---|
1759 | min= FFMIN(c->direct_basis_mv[i][1], c->direct_basis_mv[i][1] - c->co_located_mv[i][1])>>shift;
|
---|
1760 | max+= 16*mb_y + 1; // +-1 is for the simpler rounding
|
---|
1761 | min+= 16*mb_y - 1;
|
---|
1762 | ymax= FFMIN(ymax, s->height - max);
|
---|
1763 | ymin= FFMAX(ymin, - 16 - min);
|
---|
1764 |
|
---|
1765 | if(s->mv_type == MV_TYPE_16X16) break;
|
---|
1766 | }
|
---|
1767 |
|
---|
1768 | assert(xmax <= 15 && ymax <= 15 && xmin >= -16 && ymin >= -16);
|
---|
1769 |
|
---|
1770 | if(xmax < 0 || xmin >0 || ymax < 0 || ymin > 0){
|
---|
1771 | s->b_direct_mv_table[mot_xy][0]= 0;
|
---|
1772 | s->b_direct_mv_table[mot_xy][1]= 0;
|
---|
1773 |
|
---|
1774 | return 256*256*256*64;
|
---|
1775 | }
|
---|
1776 |
|
---|
1777 | c->xmin= xmin;
|
---|
1778 | c->ymin= ymin;
|
---|
1779 | c->xmax= xmax;
|
---|
1780 | c->ymax= ymax;
|
---|
1781 | c->flags |= FLAG_DIRECT;
|
---|
1782 | c->sub_flags |= FLAG_DIRECT;
|
---|
1783 | c->pred_x=0;
|
---|
1784 | c->pred_y=0;
|
---|
1785 |
|
---|
1786 | P_LEFT[0] = clip(mv_table[mot_xy - 1][0], xmin<<shift, xmax<<shift);
|
---|
1787 | P_LEFT[1] = clip(mv_table[mot_xy - 1][1], ymin<<shift, ymax<<shift);
|
---|
1788 |
|
---|
1789 | /* special case for first line */
|
---|
1790 | if (!s->first_slice_line) { //FIXME maybe allow this over thread boundary as its cliped
|
---|
1791 | P_TOP[0] = clip(mv_table[mot_xy - mot_stride ][0], xmin<<shift, xmax<<shift);
|
---|
1792 | P_TOP[1] = clip(mv_table[mot_xy - mot_stride ][1], ymin<<shift, ymax<<shift);
|
---|
1793 | P_TOPRIGHT[0] = clip(mv_table[mot_xy - mot_stride + 1 ][0], xmin<<shift, xmax<<shift);
|
---|
1794 | P_TOPRIGHT[1] = clip(mv_table[mot_xy - mot_stride + 1 ][1], ymin<<shift, ymax<<shift);
|
---|
1795 |
|
---|
1796 | P_MEDIAN[0]= mid_pred(P_LEFT[0], P_TOP[0], P_TOPRIGHT[0]);
|
---|
1797 | P_MEDIAN[1]= mid_pred(P_LEFT[1], P_TOP[1], P_TOPRIGHT[1]);
|
---|
1798 | }
|
---|
1799 |
|
---|
1800 | dmin = ff_epzs_motion_search(s, &mx, &my, P, 0, 0, mv_table, 1<<(16-shift), 0, 16);
|
---|
1801 | if(c->sub_flags&FLAG_QPEL)
|
---|
1802 | dmin = qpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
|
---|
1803 | else
|
---|
1804 | dmin = hpel_motion_search(s, &mx, &my, dmin, 0, 0, 0, 16);
|
---|
1805 |
|
---|
1806 | if(c->avctx->me_sub_cmp != c->avctx->mb_cmp && !c->skip)
|
---|
1807 | dmin= ff_get_mb_score(s, mx, my, 0, 0, 0, 16, 1);
|
---|
1808 |
|
---|
1809 | get_limits(s, 16*mb_x, 16*mb_y); //restore c->?min/max, maybe not needed
|
---|
1810 |
|
---|
1811 | s->b_direct_mv_table[mot_xy][0]= mx;
|
---|
1812 | s->b_direct_mv_table[mot_xy][1]= my;
|
---|
1813 | c->flags &= ~FLAG_DIRECT;
|
---|
1814 | c->sub_flags &= ~FLAG_DIRECT;
|
---|
1815 |
|
---|
1816 | return dmin;
|
---|
1817 | }
|
---|
1818 |
|
---|
1819 | void ff_estimate_b_frame_motion(MpegEncContext * s,
|
---|
1820 | int mb_x, int mb_y)
|
---|
1821 | {
|
---|
1822 | MotionEstContext * const c= &s->me;
|
---|
1823 | const int penalty_factor= c->mb_penalty_factor;
|
---|
1824 | int fmin, bmin, dmin, fbmin, bimin, fimin;
|
---|
1825 | int type=0;
|
---|
1826 | const int xy = mb_y*s->mb_stride + mb_x;
|
---|
1827 | init_ref(c, s->new_picture.data, s->last_picture.data, s->next_picture.data, 16*mb_x, 16*mb_y, 2);
|
---|
1828 |
|
---|
1829 | get_limits(s, 16*mb_x, 16*mb_y);
|
---|
1830 |
|
---|
1831 | c->skip=0;
|
---|
1832 | if(c->avctx->me_threshold){
|
---|
1833 | int vard= check_input_motion(s, mb_x, mb_y, 0);
|
---|
1834 |
|
---|
1835 | if((vard+128)>>8 < c->avctx->me_threshold){
|
---|
1836 | // pix = c->src[0][0];
|
---|
1837 | // sum = s->dsp.pix_sum(pix, s->linesize);
|
---|
1838 | // varc = s->dsp.pix_norm1(pix, s->linesize) - (((unsigned)(sum*sum))>>8) + 500;
|
---|
1839 |
|
---|
1840 | // pic->mb_var [s->mb_stride * mb_y + mb_x] = (varc+128)>>8;
|
---|
1841 | s->current_picture.mc_mb_var[s->mb_stride * mb_y + mb_x] = (vard+128)>>8;
|
---|
1842 | /* pic->mb_mean [s->mb_stride * mb_y + mb_x] = (sum+128)>>8;
|
---|
1843 | c->mb_var_sum_temp += (varc+128)>>8;*/
|
---|
1844 | c->mc_mb_var_sum_temp += (vard+128)>>8;
|
---|
1845 | /* if (vard <= 64<<8 || vard < varc) {
|
---|
1846 | c->scene_change_score+= ff_sqrt(vard) - ff_sqrt(varc);
|
---|
1847 | }else{
|
---|
1848 | c->scene_change_score+= s->qscale * s->avctx->scenechange_factor;
|
---|
1849 | }*/
|
---|
1850 | return;
|
---|
1851 | }
|
---|
1852 | if((vard+128)>>8 < c->avctx->mb_threshold){
|
---|
1853 | type= s->mb_type[mb_y*s->mb_stride + mb_x];
|
---|
1854 | if(type == CANDIDATE_MB_TYPE_DIRECT){
|
---|
1855 | direct_search(s, mb_x, mb_y);
|
---|
1856 | }
|
---|
1857 | if(type == CANDIDATE_MB_TYPE_FORWARD || type == CANDIDATE_MB_TYPE_BIDIR){
|
---|
1858 | c->skip=0;
|
---|
1859 | ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code);
|
---|
1860 | }
|
---|
1861 | if(type == CANDIDATE_MB_TYPE_BACKWARD || type == CANDIDATE_MB_TYPE_BIDIR){
|
---|
1862 | c->skip=0;
|
---|
1863 | ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code);
|
---|
1864 | }
|
---|
1865 | if(type == CANDIDATE_MB_TYPE_FORWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
|
---|
1866 | c->skip=0;
|
---|
1867 | c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
|
---|
1868 | interlaced_search(s, 0,
|
---|
1869 | s->b_field_mv_table[0], s->b_field_select_table[0],
|
---|
1870 | s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 1);
|
---|
1871 | }
|
---|
1872 | if(type == CANDIDATE_MB_TYPE_BACKWARD_I || type == CANDIDATE_MB_TYPE_BIDIR_I){
|
---|
1873 | c->skip=0;
|
---|
1874 | c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
|
---|
1875 | interlaced_search(s, 2,
|
---|
1876 | s->b_field_mv_table[1], s->b_field_select_table[1],
|
---|
1877 | s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 1);
|
---|
1878 | }
|
---|
1879 | return;
|
---|
1880 | }
|
---|
1881 | }
|
---|
1882 |
|
---|
1883 | if (s->codec_id == CODEC_ID_MPEG4)
|
---|
1884 | dmin= direct_search(s, mb_x, mb_y);
|
---|
1885 | else
|
---|
1886 | dmin= INT_MAX;
|
---|
1887 | //FIXME penalty stuff for non mpeg4
|
---|
1888 | c->skip=0;
|
---|
1889 | fmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_forw_mv_table, 0, s->f_code) + 3*penalty_factor;
|
---|
1890 |
|
---|
1891 | c->skip=0;
|
---|
1892 | bmin= ff_estimate_motion_b(s, mb_x, mb_y, s->b_back_mv_table, 2, s->b_code) + 2*penalty_factor;
|
---|
1893 | //printf(" %d %d ", s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1]);
|
---|
1894 |
|
---|
1895 | c->skip=0;
|
---|
1896 | fbmin= bidir_refine(s, mb_x, mb_y) + penalty_factor;
|
---|
1897 | //printf("%d %d %d %d\n", dmin, fmin, bmin, fbmin);
|
---|
1898 |
|
---|
1899 | if(s->flags & CODEC_FLAG_INTERLACED_ME){
|
---|
1900 | //FIXME mb type penalty
|
---|
1901 | c->skip=0;
|
---|
1902 | c->current_mv_penalty= c->mv_penalty[s->f_code] + MAX_MV;
|
---|
1903 | fimin= interlaced_search(s, 0,
|
---|
1904 | s->b_field_mv_table[0], s->b_field_select_table[0],
|
---|
1905 | s->b_forw_mv_table[xy][0], s->b_forw_mv_table[xy][1], 0);
|
---|
1906 | c->current_mv_penalty= c->mv_penalty[s->b_code] + MAX_MV;
|
---|
1907 | bimin= interlaced_search(s, 2,
|
---|
1908 | s->b_field_mv_table[1], s->b_field_select_table[1],
|
---|
1909 | s->b_back_mv_table[xy][0], s->b_back_mv_table[xy][1], 0);
|
---|
1910 | }else
|
---|
1911 | fimin= bimin= INT_MAX;
|
---|
1912 |
|
---|
1913 | {
|
---|
1914 | int score= fmin;
|
---|
1915 | type = CANDIDATE_MB_TYPE_FORWARD;
|
---|
1916 |
|
---|
1917 | if (dmin <= score){
|
---|
1918 | score = dmin;
|
---|
1919 | type = CANDIDATE_MB_TYPE_DIRECT;
|
---|
1920 | }
|
---|
1921 | if(bmin<score){
|
---|
1922 | score=bmin;
|
---|
1923 | type= CANDIDATE_MB_TYPE_BACKWARD;
|
---|
1924 | }
|
---|
1925 | if(fbmin<score){
|
---|
1926 | score=fbmin;
|
---|
1927 | type= CANDIDATE_MB_TYPE_BIDIR;
|
---|
1928 | }
|
---|
1929 | if(fimin<score){
|
---|
1930 | score=fimin;
|
---|
1931 | type= CANDIDATE_MB_TYPE_FORWARD_I;
|
---|
1932 | }
|
---|
1933 | if(bimin<score){
|
---|
1934 | score=bimin;
|
---|
1935 | type= CANDIDATE_MB_TYPE_BACKWARD_I;
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 | score= ((unsigned)(score*score + 128*256))>>16;
|
---|
1939 | c->mc_mb_var_sum_temp += score;
|
---|
1940 | s->current_picture.mc_mb_var[mb_y*s->mb_stride + mb_x] = score; //FIXME use SSE
|
---|
1941 | }
|
---|
1942 |
|
---|
1943 | if(c->avctx->mb_decision > FF_MB_DECISION_SIMPLE){
|
---|
1944 | type= CANDIDATE_MB_TYPE_FORWARD | CANDIDATE_MB_TYPE_BACKWARD | CANDIDATE_MB_TYPE_BIDIR | CANDIDATE_MB_TYPE_DIRECT;
|
---|
1945 | if(fimin < INT_MAX)
|
---|
1946 | type |= CANDIDATE_MB_TYPE_FORWARD_I;
|
---|
1947 | if(bimin < INT_MAX)
|
---|
1948 | type |= CANDIDATE_MB_TYPE_BACKWARD_I;
|
---|
1949 | if(fimin < INT_MAX && bimin < INT_MAX){
|
---|
1950 | type |= CANDIDATE_MB_TYPE_BIDIR_I;
|
---|
1951 | }
|
---|
1952 | //FIXME something smarter
|
---|
1953 | if(dmin>256*256*16) type&= ~CANDIDATE_MB_TYPE_DIRECT; //dont try direct mode if its invalid for this MB
|
---|
1954 | #if 0
|
---|
1955 | if(s->out_format == FMT_MPEG1)
|
---|
1956 | type |= CANDIDATE_MB_TYPE_INTRA;
|
---|
1957 | #endif
|
---|
1958 | }
|
---|
1959 |
|
---|
1960 | s->mb_type[mb_y*s->mb_stride + mb_x]= type;
|
---|
1961 | }
|
---|
1962 |
|
---|
1963 | /* find best f_code for ME which do unlimited searches */
|
---|
1964 | int ff_get_best_fcode(MpegEncContext * s, int16_t (*mv_table)[2], int type)
|
---|
1965 | {
|
---|
1966 | if(s->me_method>=ME_EPZS){
|
---|
1967 | int score[8];
|
---|
1968 | int i, y, range= s->avctx->me_range ? s->avctx->me_range : (INT_MAX/2);
|
---|
1969 | uint8_t * fcode_tab= s->fcode_tab;
|
---|
1970 | int best_fcode=-1;
|
---|
1971 | int best_score=-10000000;
|
---|
1972 |
|
---|
1973 | if(s->msmpeg4_version)
|
---|
1974 | range= FFMIN(range, 16);
|
---|
1975 | else if(s->codec_id == CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL)
|
---|
1976 | range= FFMIN(range, 256);
|
---|
1977 |
|
---|
1978 | for(i=0; i<8; i++) score[i]= s->mb_num*(8-i);
|
---|
1979 |
|
---|
1980 | for(y=0; y<s->mb_height; y++){
|
---|
1981 | int x;
|
---|
1982 | int xy= y*s->mb_stride;
|
---|
1983 | for(x=0; x<s->mb_width; x++){
|
---|
1984 | if(s->mb_type[xy] & type){
|
---|
1985 | int mx= mv_table[xy][0];
|
---|
1986 | int my= mv_table[xy][1];
|
---|
1987 | int fcode= FFMAX(fcode_tab[mx + MAX_MV],
|
---|
1988 | fcode_tab[my + MAX_MV]);
|
---|
1989 | int j;
|
---|
1990 |
|
---|
1991 | if(mx >= range || mx < -range ||
|
---|
1992 | my >= range || my < -range)
|
---|
1993 | continue;
|
---|
1994 |
|
---|
1995 | for(j=0; j<fcode && j<8; j++){
|
---|
1996 | if(s->pict_type==B_TYPE || s->current_picture.mc_mb_var[xy] < s->current_picture.mb_var[xy])
|
---|
1997 | score[j]-= 170;
|
---|
1998 | }
|
---|
1999 | }
|
---|
2000 | xy++;
|
---|
2001 | }
|
---|
2002 | }
|
---|
2003 |
|
---|
2004 | for(i=1; i<8; i++){
|
---|
2005 | if(score[i] > best_score){
|
---|
2006 | best_score= score[i];
|
---|
2007 | best_fcode= i;
|
---|
2008 | }
|
---|
2009 | // printf("%d %d\n", i, score[i]);
|
---|
2010 | }
|
---|
2011 |
|
---|
2012 | // printf("fcode: %d type: %d\n", i, s->pict_type);
|
---|
2013 | return best_fcode;
|
---|
2014 | /* for(i=0; i<=MAX_FCODE; i++){
|
---|
2015 | printf("%d ", mv_num[i]);
|
---|
2016 | }
|
---|
2017 | printf("\n");*/
|
---|
2018 | }else{
|
---|
2019 | return 1;
|
---|
2020 | }
|
---|
2021 | }
|
---|
2022 |
|
---|
2023 | void ff_fix_long_p_mvs(MpegEncContext * s)
|
---|
2024 | {
|
---|
2025 | MotionEstContext * const c= &s->me;
|
---|
2026 | const int f_code= s->f_code;
|
---|
2027 | int y, range;
|
---|
2028 | assert(s->pict_type==P_TYPE);
|
---|
2029 |
|
---|
2030 | range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
|
---|
2031 |
|
---|
2032 | assert(range <= 16 || !s->msmpeg4_version);
|
---|
2033 | assert(range <=256 || !(s->codec_id == CODEC_ID_MPEG2VIDEO && s->avctx->strict_std_compliance >= FF_COMPLIANCE_NORMAL));
|
---|
2034 |
|
---|
2035 | if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
|
---|
2036 |
|
---|
2037 | //printf("%d no:%d %d//\n", clip, noclip, f_code);
|
---|
2038 | if(s->flags&CODEC_FLAG_4MV){
|
---|
2039 | const int wrap= s->b8_stride;
|
---|
2040 |
|
---|
2041 | /* clip / convert to intra 8x8 type MVs */
|
---|
2042 | for(y=0; y<s->mb_height; y++){
|
---|
2043 | int xy= y*2*wrap;
|
---|
2044 | int i= y*s->mb_stride;
|
---|
2045 | int x;
|
---|
2046 |
|
---|
2047 | for(x=0; x<s->mb_width; x++){
|
---|
2048 | if(s->mb_type[i]&CANDIDATE_MB_TYPE_INTER4V){
|
---|
2049 | int block;
|
---|
2050 | for(block=0; block<4; block++){
|
---|
2051 | int off= (block& 1) + (block>>1)*wrap;
|
---|
2052 | int mx= s->current_picture.motion_val[0][ xy + off ][0];
|
---|
2053 | int my= s->current_picture.motion_val[0][ xy + off ][1];
|
---|
2054 |
|
---|
2055 | if( mx >=range || mx <-range
|
---|
2056 | || my >=range || my <-range){
|
---|
2057 | s->mb_type[i] &= ~CANDIDATE_MB_TYPE_INTER4V;
|
---|
2058 | s->mb_type[i] |= CANDIDATE_MB_TYPE_INTRA;
|
---|
2059 | s->current_picture.mb_type[i]= CANDIDATE_MB_TYPE_INTRA;
|
---|
2060 | }
|
---|
2061 | }
|
---|
2062 | }
|
---|
2063 | xy+=2;
|
---|
2064 | i++;
|
---|
2065 | }
|
---|
2066 | }
|
---|
2067 | }
|
---|
2068 | }
|
---|
2069 |
|
---|
2070 | /**
|
---|
2071 | *
|
---|
2072 | * @param truncate 1 for truncation, 0 for using intra
|
---|
2073 | */
|
---|
2074 | void ff_fix_long_mvs(MpegEncContext * s, uint8_t *field_select_table, int field_select,
|
---|
2075 | int16_t (*mv_table)[2], int f_code, int type, int truncate)
|
---|
2076 | {
|
---|
2077 | MotionEstContext * const c= &s->me;
|
---|
2078 | int y, h_range, v_range;
|
---|
2079 |
|
---|
2080 | // RAL: 8 in MPEG-1, 16 in MPEG-4
|
---|
2081 | int range = (((s->out_format == FMT_MPEG1 || s->msmpeg4_version) ? 8 : 16) << f_code);
|
---|
2082 |
|
---|
2083 | if(c->avctx->me_range && range > c->avctx->me_range) range= c->avctx->me_range;
|
---|
2084 |
|
---|
2085 | h_range= range;
|
---|
2086 | v_range= field_select_table ? range>>1 : range;
|
---|
2087 |
|
---|
2088 | /* clip / convert to intra 16x16 type MVs */
|
---|
2089 | for(y=0; y<s->mb_height; y++){
|
---|
2090 | int x;
|
---|
2091 | int xy= y*s->mb_stride;
|
---|
2092 | for(x=0; x<s->mb_width; x++){
|
---|
2093 | if (s->mb_type[xy] & type){ // RAL: "type" test added...
|
---|
2094 | if(field_select_table==NULL || field_select_table[xy] == field_select){
|
---|
2095 | if( mv_table[xy][0] >=h_range || mv_table[xy][0] <-h_range
|
---|
2096 | || mv_table[xy][1] >=v_range || mv_table[xy][1] <-v_range){
|
---|
2097 |
|
---|
2098 | if(truncate){
|
---|
2099 | if (mv_table[xy][0] > h_range-1) mv_table[xy][0]= h_range-1;
|
---|
2100 | else if(mv_table[xy][0] < -h_range ) mv_table[xy][0]= -h_range;
|
---|
2101 | if (mv_table[xy][1] > v_range-1) mv_table[xy][1]= v_range-1;
|
---|
2102 | else if(mv_table[xy][1] < -v_range ) mv_table[xy][1]= -v_range;
|
---|
2103 | }else{
|
---|
2104 | s->mb_type[xy] &= ~type;
|
---|
2105 | s->mb_type[xy] |= CANDIDATE_MB_TYPE_INTRA;
|
---|
2106 | mv_table[xy][0]=
|
---|
2107 | mv_table[xy][1]= 0;
|
---|
2108 | }
|
---|
2109 | }
|
---|
2110 | }
|
---|
2111 | }
|
---|
2112 | xy++;
|
---|
2113 | }
|
---|
2114 | }
|
---|
2115 | }
|
---|