1 /**
2 * Copyright (c) 2016 Davinder Singh (DSM_) <ds.mudhar<@gmail.com>
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
32
36 int method;
///< motion estimation method
37
42
44
45 int (*
mv_table[3])[2][2];
///< motion vectors of current & prev 2 frames
47
48 #define OFFSET(x) offsetof(MEContext, x)
49 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
50 #define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, 0, 0, FLAGS, unit }
51
66 };
67
69
80 };
81
83 {
86
88 s->mb_size = 1 <<
s->log2_mb_size;
89
90 s->b_width =
inlink->w >>
s->log2_mb_size;
91 s->b_height =
inlink->h >>
s->log2_mb_size;
92 s->b_count =
s->b_width *
s->b_height;
93
96
97 for (
i = 0;
i < 3;
i++) {
98 s->mv_table[
i] =
av_calloc(
s->b_count,
sizeof(*
s->mv_table[0]));
101 }
102
104
105 return 0;
106 }
107
109 int x, int y, int x_mv, int y_mv, int dir)
110 {
113 mv->dst_x = x + (mb_size >> 1);
114 mv->dst_y = y + (mb_size >> 1);
115 mv->src_x = x_mv + (mb_size >> 1);
116 mv->src_y = y_mv + (mb_size >> 1);
117 mv->source = dir ? 1 : -1;
119 }
120
121 #define SEARCH_MV(method)\
122 do {\
123 for (mb_y = 0; mb_y < s->b_height; mb_y++)\
124 for (mb_x = 0; mb_x < s->b_width; mb_x++) {\
125 const int x_mb = mb_x << s->log2_mb_size;\
126 const int y_mb = mb_y << s->log2_mb_size;\
127 int mv[2] = {x_mb, y_mb};\
128 ff_me_search_##method(me_ctx, x_mb, y_mb, mv);\
129 add_mv_data(((AVMotionVector *) sd->data) + mv_count++, me_ctx->mb_size, x_mb, y_mb, mv[0], mv[1], dir);\
130 }\
131 } while (0)
132
133 #define ADD_PRED(preds, px, py)\
134 do {\
135 preds.mvs[preds.nb][0] = px;\
136 preds.mvs[preds.nb][1] = py;\
137 preds.nb++;\
138 } while(0)
139
141 {
147 int mb_x, mb_y, dir;
150
154 }
155
160
161 s->mv_table[2] = memcpy(
s->mv_table[2],
s->mv_table[1],
sizeof(*
s->mv_table[1]) *
s->b_count);
162 s->mv_table[1] = memcpy(
s->mv_table[1],
s->mv_table[0],
sizeof(*
s->mv_table[0]) *
s->b_count);
163
168 }
169
171 return 0;
172
176
178 if (!sd) {
181 }
182
185
186 for (dir = 0; dir < 2; dir++) {
188
204 for (mb_y = 0; mb_y <
s->b_height; mb_y++)
205 for (mb_x = 0; mb_x <
s->b_width; mb_x++) {
206 const int mb_i = mb_x + mb_y *
s->b_width;
207 const int x_mb = mb_x <<
s->log2_mb_size;
208 const int y_mb = mb_y <<
s->log2_mb_size;
209 int mv[2] = {x_mb, y_mb};
210
213
215
216 //left mb in current frame
217 if (mb_x > 0)
218 ADD_PRED(preds[0],
s->mv_table[0][mb_i - 1][dir][0],
s->mv_table[0][mb_i - 1][dir][1]);
219
220 if (mb_y > 0) {
221 //top mb in current frame
222 ADD_PRED(preds[0],
s->mv_table[0][mb_i -
s->b_width][dir][0],
s->mv_table[0][mb_i -
s->b_width][dir][1]);
223
224 //top-right mb in current frame
225 if (mb_x + 1 <
s->b_width)
226 ADD_PRED(preds[0],
s->mv_table[0][mb_i -
s->b_width + 1][dir][0],
s->mv_table[0][mb_i -
s->b_width + 1][dir][1]);
227 //top-left mb in current frame
228 else if (mb_x > 0)
229 ADD_PRED(preds[0],
s->mv_table[0][mb_i -
s->b_width - 1][dir][0],
s->mv_table[0][mb_i -
s->b_width - 1][dir][1]);
230 }
231
232 //median predictor
233 if (preds[0].nb == 4) {
234 me_ctx->
pred_x =
mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
235 me_ctx->
pred_y =
mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
236 } else if (preds[0].nb == 3) {
237 me_ctx->
pred_x =
mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
238 me_ctx->
pred_y =
mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
239 } else if (preds[0].nb == 2) {
242 } else {
245 }
246
248
249 s->mv_table[0][mb_i][dir][0] =
mv[0] - x_mb;
250 s->mv_table[0][mb_i][dir][1] =
mv[1] - y_mb;
252 }
253
255
256 for (mb_y = 0; mb_y <
s->b_height; mb_y++)
257 for (mb_x = 0; mb_x <
s->b_width; mb_x++) {
258 const int mb_i = mb_x + mb_y *
s->b_width;
259 const int x_mb = mb_x <<
s->log2_mb_size;
260 const int y_mb = mb_y <<
s->log2_mb_size;
261 int mv[2] = {x_mb, y_mb};
262
266
268
269 //left mb in current frame
270 if (mb_x > 0)
271 ADD_PRED(preds[0],
s->mv_table[0][mb_i - 1][dir][0],
s->mv_table[0][mb_i - 1][dir][1]);
272
273 //top mb in current frame
274 if (mb_y > 0)
275 ADD_PRED(preds[0],
s->mv_table[0][mb_i -
s->b_width][dir][0],
s->mv_table[0][mb_i -
s->b_width][dir][1]);
276
277 //top-right mb in current frame
278 if (mb_y > 0 && mb_x + 1 <
s->b_width)
279 ADD_PRED(preds[0],
s->mv_table[0][mb_i -
s->b_width + 1][dir][0],
s->mv_table[0][mb_i -
s->b_width + 1][dir][1]);
280
281 //median predictor
282 if (preds[0].nb == 4) {
283 me_ctx->
pred_x =
mid_pred(preds[0].mvs[1][0], preds[0].mvs[2][0], preds[0].mvs[3][0]);
284 me_ctx->
pred_y =
mid_pred(preds[0].mvs[1][1], preds[0].mvs[2][1], preds[0].mvs[3][1]);
285 } else if (preds[0].nb == 3) {
286 me_ctx->
pred_x =
mid_pred(0, preds[0].mvs[1][0], preds[0].mvs[2][0]);
287 me_ctx->
pred_y =
mid_pred(0, preds[0].mvs[1][1], preds[0].mvs[2][1]);
288 } else if (preds[0].nb == 2) {
291 } else {
294 }
295
296 //collocated mb in prev frame
297 ADD_PRED(preds[0],
s->mv_table[1][mb_i][dir][0],
s->mv_table[1][mb_i][dir][1]);
298
299 //accelerator motion vector of collocated block in prev frame
300 ADD_PRED(preds[1],
s->mv_table[1][mb_i][dir][0] + (
s->mv_table[1][mb_i][dir][0] -
s->mv_table[2][mb_i][dir][0]),
301 s->mv_table[1][mb_i][dir][1] + (
s->mv_table[1][mb_i][dir][1] -
s->mv_table[2][mb_i][dir][1]));
302
303 //left mb in prev frame
304 if (mb_x > 0)
305 ADD_PRED(preds[1],
s->mv_table[1][mb_i - 1][dir][0],
s->mv_table[1][mb_i - 1][dir][1]);
306
307 //top mb in prev frame
308 if (mb_y > 0)
309 ADD_PRED(preds[1],
s->mv_table[1][mb_i -
s->b_width][dir][0],
s->mv_table[1][mb_i -
s->b_width][dir][1]);
310
311 //right mb in prev frame
312 if (mb_x + 1 <
s->b_width)
313 ADD_PRED(preds[1],
s->mv_table[1][mb_i + 1][dir][0],
s->mv_table[1][mb_i + 1][dir][1]);
314
315 //bottom mb in prev frame
316 if (mb_y + 1 <
s->b_height)
317 ADD_PRED(preds[1],
s->mv_table[1][mb_i +
s->b_width][dir][0],
s->mv_table[1][mb_i +
s->b_width][dir][1]);
318
320
321 s->mv_table[0][mb_i][dir][0] =
mv[0] - x_mb;
322 s->mv_table[0][mb_i][dir][1] =
mv[1] - y_mb;
324 }
325 }
326 }
327
329 }
330
332 {
335
339
340 for (
i = 0;
i < 3;
i++)
342 }
343
345 {
350 },
351 };
352
354 {
357 },
358 };
359
364 .priv_class = &mestimate_class,
370 };