motion_estimation.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. #include "motion_estimation.h"
  21. static const int8_t sqr1[8][2] = {{ 0,-1}, { 0, 1}, {-1, 0}, { 1, 0}, {-1,-1}, {-1, 1}, { 1,-1}, { 1, 1}};
  22. static const int8_t dia1[4][2] = {{-1, 0}, { 0,-1}, { 1, 0}, { 0, 1}};
  23. static const int8_t dia2[8][2] = {{-2, 0}, {-1,-1}, { 0,-2}, { 1,-1}, { 2, 0}, { 1, 1}, { 0, 2}, {-1, 1}};
  24. static const int8_t hex2[6][2] = {{-2, 0}, {-1,-2}, {-1, 2}, { 1,-2}, { 1, 2}, { 2, 0}};
  25. static const int8_t hex4[16][2] = {{-4,-2}, {-4,-1}, {-4, 0}, {-4, 1}, {-4, 2},
  26. { 4,-2}, { 4,-1}, { 4, 0}, { 4, 1}, { 4, 2},
  27. {-2, 3}, { 0, 4}, { 2, 3}, {-2,-3}, { 0,-4}, { 2,-3}};
  28. #define COST_MV(x, y)\
  29. do {\
  30. cost = me_ctx->get_cost(me_ctx, x_mb, y_mb, x, y);\
  31. if (cost < cost_min) {\
  32. cost_min = cost;\
  33. mv[0] = x;\
  34. mv[1] = y;\
  35. }\
  36. } while(0)
  37. #define COST_P_MV(x, y)\
  38. if (x >= x_min && x <= x_max && y >= y_min && y <= y_max)\
  39. COST_MV(x, y);
  40. void ff_me_init_context(AVMotionEstContext *me_ctx, int mb_size, int search_param,
  41. int width, int height, int x_min, int x_max, int y_min, int y_max)
  42. {
  43. me_ctx->width = width;
  44. me_ctx->height = height;
  45. me_ctx->mb_size = mb_size;
  46. me_ctx->search_param = search_param;
  47. me_ctx->get_cost = &ff_me_cmp_sad;
  48. me_ctx->x_min = x_min;
  49. me_ctx->x_max = x_max;
  50. me_ctx->y_min = y_min;
  51. me_ctx->y_max = y_max;
  52. }
  53. uint64_t ff_me_cmp_sad(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int x_mv, int y_mv)
  54. {
  55. const int linesize = me_ctx->linesize;
  56. uint8_t *data_ref = me_ctx->data_ref;
  57. uint8_t *data_cur = me_ctx->data_cur;
  58. uint64_t sad = 0;
  59. int i, j;
  60. data_ref += y_mv * linesize;
  61. data_cur += y_mb * linesize;
  62. for (j = 0; j < me_ctx->mb_size; j++)
  63. for (i = 0; i < me_ctx->mb_size; i++)
  64. sad += FFABS(data_ref[x_mv + i + j * linesize] - data_cur[x_mb + i + j * linesize]);
  65. return sad;
  66. }
  67. uint64_t ff_me_search_esa(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  68. {
  69. int x, y;
  70. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  71. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  72. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  73. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  74. uint64_t cost, cost_min;
  75. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  76. return cost_min;
  77. for (y = y_min; y <= y_max; y++)
  78. for (x = x_min; x <= x_max; x++)
  79. COST_MV(x, y);
  80. return cost_min;
  81. }
  82. uint64_t ff_me_search_tss(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  83. {
  84. int x, y;
  85. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  86. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  87. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  88. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  89. uint64_t cost, cost_min;
  90. int step = ROUNDED_DIV(me_ctx->search_param, 2);
  91. int i;
  92. mv[0] = x_mb;
  93. mv[1] = y_mb;
  94. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  95. return cost_min;
  96. do {
  97. x = mv[0];
  98. y = mv[1];
  99. for (i = 0; i < 8; i++)
  100. COST_P_MV(x + sqr1[i][0] * step, y + sqr1[i][1] * step);
  101. step = step >> 1;
  102. } while (step > 0);
  103. return cost_min;
  104. }
  105. uint64_t ff_me_search_tdls(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  106. {
  107. int x, y;
  108. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  109. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  110. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  111. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  112. uint64_t cost, cost_min;
  113. int step = ROUNDED_DIV(me_ctx->search_param, 2);
  114. int i;
  115. mv[0] = x_mb;
  116. mv[1] = y_mb;
  117. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  118. return cost_min;
  119. do {
  120. x = mv[0];
  121. y = mv[1];
  122. for (i = 0; i < 4; i++)
  123. COST_P_MV(x + dia1[i][0] * step, y + dia1[i][1] * step);
  124. if (x == mv[0] && y == mv[1])
  125. step = step >> 1;
  126. } while (step > 0);
  127. return cost_min;
  128. }
  129. uint64_t ff_me_search_ntss(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  130. {
  131. int x, y;
  132. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  133. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  134. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  135. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  136. uint64_t cost, cost_min;
  137. int step = ROUNDED_DIV(me_ctx->search_param, 2);
  138. int first_step = 1;
  139. int i;
  140. mv[0] = x_mb;
  141. mv[1] = y_mb;
  142. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  143. return cost_min;
  144. do {
  145. x = mv[0];
  146. y = mv[1];
  147. for (i = 0; i < 8; i++)
  148. COST_P_MV(x + sqr1[i][0] * step, y + sqr1[i][1] * step);
  149. /* addition to TSS in NTSS */
  150. if (first_step) {
  151. for (i = 0; i < 8; i++)
  152. COST_P_MV(x + sqr1[i][0], y + sqr1[i][1]);
  153. if (x == mv[0] && y == mv[1])
  154. return cost_min;
  155. if (FFABS(x - mv[0]) <= 1 && FFABS(y - mv[1]) <= 1) {
  156. x = mv[0];
  157. y = mv[1];
  158. for (i = 0; i < 8; i++)
  159. COST_P_MV(x + sqr1[i][0], y + sqr1[i][1]);
  160. return cost_min;
  161. }
  162. first_step = 0;
  163. }
  164. step = step >> 1;
  165. } while (step > 0);
  166. return cost_min;
  167. }
  168. uint64_t ff_me_search_fss(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  169. {
  170. int x, y;
  171. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  172. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  173. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  174. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  175. uint64_t cost, cost_min;
  176. int step = 2;
  177. int i;
  178. mv[0] = x_mb;
  179. mv[1] = y_mb;
  180. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  181. return cost_min;
  182. do {
  183. x = mv[0];
  184. y = mv[1];
  185. for (i = 0; i < 8; i++)
  186. COST_P_MV(x + sqr1[i][0] * step, y + sqr1[i][1] * step);
  187. if (x == mv[0] && y == mv[1])
  188. step = step >> 1;
  189. } while (step > 0);
  190. return cost_min;
  191. }
  192. uint64_t ff_me_search_ds(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  193. {
  194. int x, y;
  195. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  196. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  197. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  198. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  199. uint64_t cost, cost_min;
  200. int i;
  201. av_unused int dir_x, dir_y;
  202. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  203. return cost_min;
  204. x = x_mb; y = y_mb;
  205. dir_x = dir_y = 0;
  206. do {
  207. x = mv[0];
  208. y = mv[1];
  209. #if 1
  210. for (i = 0; i < 8; i++)
  211. COST_P_MV(x + dia2[i][0], y + dia2[i][1]);
  212. #else
  213. /* this version skips previously examined 3 or 5 locations based on prev origin */
  214. if (dir_x <= 0)
  215. COST_P_MV(x - 2, y);
  216. if (dir_x <= 0 && dir_y <= 0)
  217. COST_P_MV(x - 1, y - 1);
  218. if (dir_y <= 0)
  219. COST_P_MV(x, y - 2);
  220. if (dir_x >= 0 && dir_y <= 0)
  221. COST_P_MV(x + 1, y - 1);
  222. if (dir_x >= 0)
  223. COST_P_MV(x + 2, y);
  224. if (dir_x >= 0 && dir_y >= 0)
  225. COST_P_MV(x + 1, y + 1);
  226. if (dir_y >= 0)
  227. COST_P_MV(x, y + 2);
  228. if (dir_x <= 0 && dir_y >= 0)
  229. COST_P_MV(x - 1, y + 1);
  230. dir_x = mv[0] - x;
  231. dir_y = mv[1] - y;
  232. #endif
  233. } while (x != mv[0] || y != mv[1]);
  234. for (i = 0; i < 4; i++)
  235. COST_P_MV(x + dia1[i][0], y + dia1[i][1]);
  236. return cost_min;
  237. }
  238. uint64_t ff_me_search_hexbs(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  239. {
  240. int x, y;
  241. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  242. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  243. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  244. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  245. uint64_t cost, cost_min;
  246. int i;
  247. if (!(cost_min = me_ctx->get_cost(me_ctx, x_mb, y_mb, x_mb, y_mb)))
  248. return cost_min;
  249. do {
  250. x = mv[0];
  251. y = mv[1];
  252. for (i = 0; i < 6; i++)
  253. COST_P_MV(x + hex2[i][0], y + hex2[i][1]);
  254. } while (x != mv[0] || y != mv[1]);
  255. for (i = 0; i < 4; i++)
  256. COST_P_MV(x + dia1[i][0], y + dia1[i][1]);
  257. return cost_min;
  258. }
  259. /* two subsets of predictors are used
  260. me->pred_x|y is set to median of current frame's left, top, top-right
  261. set 1: me->preds[0] has: (0, 0), left, top, top-right, collocated block in prev frame
  262. set 2: me->preds[1] has: accelerator mv, top, left, right, bottom adj mb of prev frame
  263. */
  264. uint64_t ff_me_search_epzs(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  265. {
  266. int x, y;
  267. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  268. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  269. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  270. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  271. uint64_t cost, cost_min;
  272. int i;
  273. AVMotionEstPredictor *preds = me_ctx->preds;
  274. cost_min = UINT64_MAX;
  275. COST_P_MV(x_mb + me_ctx->pred_x, y_mb + me_ctx->pred_y);
  276. for (i = 0; i < preds[0].nb; i++)
  277. COST_P_MV(x_mb + preds[0].mvs[i][0], y_mb + preds[0].mvs[i][1]);
  278. for (i = 0; i < preds[1].nb; i++)
  279. COST_P_MV(x_mb + preds[1].mvs[i][0], y_mb + preds[1].mvs[i][1]);
  280. do {
  281. x = mv[0];
  282. y = mv[1];
  283. for (i = 0; i < 4; i++)
  284. COST_P_MV(x + dia1[i][0], y + dia1[i][1]);
  285. } while (x != mv[0] || y != mv[1]);
  286. return cost_min;
  287. }
  288. /* required predictor order: median, (0,0), left, top, top-right
  289. rules when mb not available:
  290. replace left with (0, 0)
  291. replace top-right with top-left
  292. replace top two with left
  293. repeated can be skipped, if no predictors are used, set me_ctx->pred to (0,0)
  294. */
  295. uint64_t ff_me_search_umh(AVMotionEstContext *me_ctx, int x_mb, int y_mb, int *mv)
  296. {
  297. int x, y;
  298. int x_min = FFMAX(me_ctx->x_min, x_mb - me_ctx->search_param);
  299. int y_min = FFMAX(me_ctx->y_min, y_mb - me_ctx->search_param);
  300. int x_max = FFMIN(x_mb + me_ctx->search_param, me_ctx->x_max);
  301. int y_max = FFMIN(y_mb + me_ctx->search_param, me_ctx->y_max);
  302. uint64_t cost, cost_min;
  303. int d, i;
  304. int end_x, end_y;
  305. AVMotionEstPredictor *pred = &me_ctx->preds[0];
  306. cost_min = UINT64_MAX;
  307. COST_P_MV(x_mb + me_ctx->pred_x, y_mb + me_ctx->pred_y);
  308. for (i = 0; i < pred->nb; i++)
  309. COST_P_MV(x_mb + pred->mvs[i][0], y_mb + pred->mvs[i][1]);
  310. // Unsymmetrical-cross Search
  311. x = mv[0];
  312. y = mv[1];
  313. for (d = 1; d <= me_ctx->search_param; d += 2) {
  314. COST_P_MV(x - d, y);
  315. COST_P_MV(x + d, y);
  316. if (d <= me_ctx->search_param / 2) {
  317. COST_P_MV(x, y - d);
  318. COST_P_MV(x, y + d);
  319. }
  320. }
  321. // Uneven Multi-Hexagon-Grid Search
  322. end_x = FFMIN(mv[0] + 2, x_max);
  323. end_y = FFMIN(mv[1] + 2, y_max);
  324. for (y = FFMAX(y_min, mv[1] - 2); y <= end_y; y++)
  325. for (x = FFMAX(x_min, mv[0] - 2); x <= end_x; x++)
  326. COST_P_MV(x, y);
  327. x = mv[0];
  328. y = mv[1];
  329. for (d = 1; d <= me_ctx->search_param / 4; d++)
  330. for (i = 1; i < 16; i++)
  331. COST_P_MV(x + hex4[i][0] * d, y + hex4[i][1] * d);
  332. // Extended Hexagon-based Search
  333. do {
  334. x = mv[0];
  335. y = mv[1];
  336. for (i = 0; i < 6; i++)
  337. COST_P_MV(x + hex2[i][0], y + hex2[i][1]);
  338. } while (x != mv[0] || y != mv[1]);
  339. for (i = 0; i < 4; i++)
  340. COST_P_MV(x + dia1[i][0], y + dia1[i][1]);
  341. return cost_min;
  342. }