PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/av1/encoder/hash_motion.c

https://gitlab.com/wjune/avm
C | 492 lines | 418 code | 55 blank | 19 comment | 85 complexity | 6cfd24c5e762684d3aaf29be6a54e3ba MD5 | raw file
  1. /*
  2. * Copyright (c) 2021, Alliance for Open Media. All rights reserved
  3. *
  4. * This source code is subject to the terms of the BSD 3-Clause Clear License
  5. * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
  6. * License was not distributed with this source code in the LICENSE file, you
  7. * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/. If the
  8. * Alliance for Open Media Patent License 1.0 was not distributed with this
  9. * source code in the PATENTS file, you can obtain it at
  10. * aomedia.org/license/patent-license/.
  11. */
  12. #include <assert.h>
  13. #include "config/av1_rtcd.h"
  14. #include "av1/encoder/block.h"
  15. #include "av1/encoder/hash.h"
  16. #include "av1/encoder/hash_motion.h"
  17. #define kSrcBits 16
  18. #define kBlockSizeBits 3
  19. #define kMaxAddr (1 << (kSrcBits + kBlockSizeBits))
  20. // TODO(youzhou@microsoft.com): is higher than 8 bits screen content supported?
  21. // If yes, fix this function
  22. static void get_pixels_in_1D_char_array_by_block_2x2(const uint8_t *y_src,
  23. int stride,
  24. uint8_t *p_pixels_in1D) {
  25. const uint8_t *p_pel = y_src;
  26. int index = 0;
  27. for (int i = 0; i < 2; i++) {
  28. for (int j = 0; j < 2; j++) {
  29. p_pixels_in1D[index++] = p_pel[j];
  30. }
  31. p_pel += stride;
  32. }
  33. }
  34. static void get_pixels_in_1D_short_array_by_block_2x2(const uint16_t *y_src,
  35. int stride,
  36. uint16_t *p_pixels_in1D) {
  37. const uint16_t *p_pel = y_src;
  38. int index = 0;
  39. for (int i = 0; i < 2; i++) {
  40. for (int j = 0; j < 2; j++) {
  41. p_pixels_in1D[index++] = p_pel[j];
  42. }
  43. p_pel += stride;
  44. }
  45. }
  46. static int is_block_2x2_row_same_value(const uint8_t *p) {
  47. if (p[0] != p[1] || p[2] != p[3]) {
  48. return 0;
  49. }
  50. return 1;
  51. }
  52. static int is_block16_2x2_row_same_value(const uint16_t *p) {
  53. if (p[0] != p[1] || p[2] != p[3]) {
  54. return 0;
  55. }
  56. return 1;
  57. }
  58. static int is_block_2x2_col_same_value(const uint8_t *p) {
  59. if ((p[0] != p[2]) || (p[1] != p[3])) {
  60. return 0;
  61. }
  62. return 1;
  63. }
  64. static int is_block16_2x2_col_same_value(const uint16_t *p) {
  65. if ((p[0] != p[2]) || (p[1] != p[3])) {
  66. return 0;
  67. }
  68. return 1;
  69. }
  70. // the hash value (hash_value1 consists two parts, the first 3 bits relate to
  71. // the block size and the remaining 16 bits are the crc values. This fuction
  72. // is used to get the first 3 bits.
  73. static int hash_block_size_to_index(int block_size) {
  74. switch (block_size) {
  75. case 4: return 0;
  76. case 8: return 1;
  77. case 16: return 2;
  78. case 32: return 3;
  79. case 64: return 4;
  80. case 128: return 5;
  81. default: return -1;
  82. }
  83. }
  84. void av1_hash_table_init(IntraBCHashInfo *intrabc_hash_info) {
  85. if (!intrabc_hash_info->g_crc_initialized) {
  86. av1_crc_calculator_init(&intrabc_hash_info->crc_calculator1, 24, 0x5D6DCB);
  87. av1_crc_calculator_init(&intrabc_hash_info->crc_calculator2, 24, 0x864CFB);
  88. intrabc_hash_info->g_crc_initialized = 1;
  89. }
  90. intrabc_hash_info->intrabc_hash_table.p_lookup_table = NULL;
  91. }
  92. void av1_hash_table_clear_all(hash_table *p_hash_table) {
  93. if (p_hash_table->p_lookup_table == NULL) {
  94. return;
  95. }
  96. for (int i = 0; i < kMaxAddr; i++) {
  97. if (p_hash_table->p_lookup_table[i] != NULL) {
  98. aom_vector_destroy(p_hash_table->p_lookup_table[i]);
  99. aom_free(p_hash_table->p_lookup_table[i]);
  100. p_hash_table->p_lookup_table[i] = NULL;
  101. }
  102. }
  103. }
  104. void av1_hash_table_destroy(hash_table *p_hash_table) {
  105. av1_hash_table_clear_all(p_hash_table);
  106. aom_free(p_hash_table->p_lookup_table);
  107. p_hash_table->p_lookup_table = NULL;
  108. }
  109. void av1_hash_table_create(hash_table *p_hash_table) {
  110. if (p_hash_table->p_lookup_table != NULL) {
  111. av1_hash_table_clear_all(p_hash_table);
  112. return;
  113. }
  114. p_hash_table->p_lookup_table =
  115. (Vector **)aom_malloc(sizeof(p_hash_table->p_lookup_table[0]) * kMaxAddr);
  116. memset(p_hash_table->p_lookup_table, 0,
  117. sizeof(p_hash_table->p_lookup_table[0]) * kMaxAddr);
  118. }
  119. static void hash_table_add_to_table(hash_table *p_hash_table,
  120. uint32_t hash_value,
  121. block_hash *curr_block_hash) {
  122. if (p_hash_table->p_lookup_table[hash_value] == NULL) {
  123. p_hash_table->p_lookup_table[hash_value] =
  124. aom_malloc(sizeof(p_hash_table->p_lookup_table[0][0]));
  125. aom_vector_setup(p_hash_table->p_lookup_table[hash_value], 10,
  126. sizeof(curr_block_hash[0]));
  127. aom_vector_push_back(p_hash_table->p_lookup_table[hash_value],
  128. curr_block_hash);
  129. } else {
  130. aom_vector_push_back(p_hash_table->p_lookup_table[hash_value],
  131. curr_block_hash);
  132. }
  133. }
  134. int32_t av1_hash_table_count(const hash_table *p_hash_table,
  135. uint32_t hash_value) {
  136. if (p_hash_table->p_lookup_table[hash_value] == NULL) {
  137. return 0;
  138. } else {
  139. return (int32_t)(p_hash_table->p_lookup_table[hash_value]->size);
  140. }
  141. }
  142. Iterator av1_hash_get_first_iterator(hash_table *p_hash_table,
  143. uint32_t hash_value) {
  144. assert(av1_hash_table_count(p_hash_table, hash_value) > 0);
  145. return aom_vector_begin(p_hash_table->p_lookup_table[hash_value]);
  146. }
  147. int32_t av1_has_exact_match(hash_table *p_hash_table, uint32_t hash_value1,
  148. uint32_t hash_value2) {
  149. if (p_hash_table->p_lookup_table[hash_value1] == NULL) {
  150. return 0;
  151. }
  152. Iterator iterator =
  153. aom_vector_begin(p_hash_table->p_lookup_table[hash_value1]);
  154. Iterator last = aom_vector_end(p_hash_table->p_lookup_table[hash_value1]);
  155. for (; !aom_iterator_equals(&iterator, &last);
  156. aom_iterator_increment(&iterator)) {
  157. if ((*(block_hash *)aom_iterator_get(&iterator)).hash_value2 ==
  158. hash_value2) {
  159. return 1;
  160. }
  161. }
  162. return 0;
  163. }
  164. void av1_generate_block_2x2_hash_value(IntraBCHashInfo *intrabc_hash_info,
  165. const YV12_BUFFER_CONFIG *picture,
  166. uint32_t *pic_block_hash[2],
  167. int8_t *pic_block_same_info[3]) {
  168. const int width = 2;
  169. const int height = 2;
  170. const int x_end = picture->y_crop_width - width + 1;
  171. const int y_end = picture->y_crop_height - height + 1;
  172. CRC_CALCULATOR *calc_1 = &intrabc_hash_info->crc_calculator1;
  173. CRC_CALCULATOR *calc_2 = &intrabc_hash_info->crc_calculator2;
  174. const int length = width * 2;
  175. if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
  176. uint16_t p[4];
  177. int pos = 0;
  178. for (int y_pos = 0; y_pos < y_end; y_pos++) {
  179. for (int x_pos = 0; x_pos < x_end; x_pos++) {
  180. get_pixels_in_1D_short_array_by_block_2x2(
  181. CONVERT_TO_SHORTPTR(picture->y_buffer) + y_pos * picture->y_stride +
  182. x_pos,
  183. picture->y_stride, p);
  184. pic_block_same_info[0][pos] = is_block16_2x2_row_same_value(p);
  185. pic_block_same_info[1][pos] = is_block16_2x2_col_same_value(p);
  186. pic_block_hash[0][pos] =
  187. av1_get_crc_value(calc_1, (uint8_t *)p, length * sizeof(p[0]));
  188. pic_block_hash[1][pos] =
  189. av1_get_crc_value(calc_2, (uint8_t *)p, length * sizeof(p[0]));
  190. pos++;
  191. }
  192. pos += width - 1;
  193. }
  194. } else {
  195. uint8_t p[4];
  196. int pos = 0;
  197. for (int y_pos = 0; y_pos < y_end; y_pos++) {
  198. for (int x_pos = 0; x_pos < x_end; x_pos++) {
  199. get_pixels_in_1D_char_array_by_block_2x2(
  200. picture->y_buffer + y_pos * picture->y_stride + x_pos,
  201. picture->y_stride, p);
  202. pic_block_same_info[0][pos] = is_block_2x2_row_same_value(p);
  203. pic_block_same_info[1][pos] = is_block_2x2_col_same_value(p);
  204. pic_block_hash[0][pos] =
  205. av1_get_crc_value(calc_1, p, length * sizeof(p[0]));
  206. pic_block_hash[1][pos] =
  207. av1_get_crc_value(calc_2, p, length * sizeof(p[0]));
  208. pos++;
  209. }
  210. pos += width - 1;
  211. }
  212. }
  213. }
  214. void av1_generate_block_hash_value(IntraBCHashInfo *intrabc_hash_info,
  215. const YV12_BUFFER_CONFIG *picture,
  216. int block_size,
  217. uint32_t *src_pic_block_hash[2],
  218. uint32_t *dst_pic_block_hash[2],
  219. int8_t *src_pic_block_same_info[3],
  220. int8_t *dst_pic_block_same_info[3]) {
  221. CRC_CALCULATOR *calc_1 = &intrabc_hash_info->crc_calculator1;
  222. CRC_CALCULATOR *calc_2 = &intrabc_hash_info->crc_calculator2;
  223. const int pic_width = picture->y_crop_width;
  224. const int x_end = picture->y_crop_width - block_size + 1;
  225. const int y_end = picture->y_crop_height - block_size + 1;
  226. const int src_size = block_size >> 1;
  227. const int quad_size = block_size >> 2;
  228. uint32_t p[4];
  229. const int length = sizeof(p);
  230. int pos = 0;
  231. for (int y_pos = 0; y_pos < y_end; y_pos++) {
  232. for (int x_pos = 0; x_pos < x_end; x_pos++) {
  233. p[0] = src_pic_block_hash[0][pos];
  234. p[1] = src_pic_block_hash[0][pos + src_size];
  235. p[2] = src_pic_block_hash[0][pos + src_size * pic_width];
  236. p[3] = src_pic_block_hash[0][pos + src_size * pic_width + src_size];
  237. dst_pic_block_hash[0][pos] =
  238. av1_get_crc_value(calc_1, (uint8_t *)p, length);
  239. p[0] = src_pic_block_hash[1][pos];
  240. p[1] = src_pic_block_hash[1][pos + src_size];
  241. p[2] = src_pic_block_hash[1][pos + src_size * pic_width];
  242. p[3] = src_pic_block_hash[1][pos + src_size * pic_width + src_size];
  243. dst_pic_block_hash[1][pos] =
  244. av1_get_crc_value(calc_2, (uint8_t *)p, length);
  245. dst_pic_block_same_info[0][pos] =
  246. src_pic_block_same_info[0][pos] &&
  247. src_pic_block_same_info[0][pos + quad_size] &&
  248. src_pic_block_same_info[0][pos + src_size] &&
  249. src_pic_block_same_info[0][pos + src_size * pic_width] &&
  250. src_pic_block_same_info[0][pos + src_size * pic_width + quad_size] &&
  251. src_pic_block_same_info[0][pos + src_size * pic_width + src_size];
  252. dst_pic_block_same_info[1][pos] =
  253. src_pic_block_same_info[1][pos] &&
  254. src_pic_block_same_info[1][pos + src_size] &&
  255. src_pic_block_same_info[1][pos + quad_size * pic_width] &&
  256. src_pic_block_same_info[1][pos + quad_size * pic_width + src_size] &&
  257. src_pic_block_same_info[1][pos + src_size * pic_width] &&
  258. src_pic_block_same_info[1][pos + src_size * pic_width + src_size];
  259. pos++;
  260. }
  261. pos += block_size - 1;
  262. }
  263. if (block_size >= 4) {
  264. const int size_minus_1 = block_size - 1;
  265. pos = 0;
  266. for (int y_pos = 0; y_pos < y_end; y_pos++) {
  267. for (int x_pos = 0; x_pos < x_end; x_pos++) {
  268. dst_pic_block_same_info[2][pos] =
  269. (!dst_pic_block_same_info[0][pos] &&
  270. !dst_pic_block_same_info[1][pos]) ||
  271. (((x_pos & size_minus_1) == 0) && ((y_pos & size_minus_1) == 0));
  272. pos++;
  273. }
  274. pos += block_size - 1;
  275. }
  276. }
  277. }
  278. void av1_add_to_hash_map_by_row_with_precal_data(hash_table *p_hash_table,
  279. uint32_t *pic_hash[2],
  280. int8_t *pic_is_same,
  281. int pic_width, int pic_height,
  282. int block_size) {
  283. const int x_end = pic_width - block_size + 1;
  284. const int y_end = pic_height - block_size + 1;
  285. const int8_t *src_is_added = pic_is_same;
  286. const uint32_t *src_hash[2] = { pic_hash[0], pic_hash[1] };
  287. int add_value = hash_block_size_to_index(block_size);
  288. assert(add_value >= 0);
  289. add_value <<= kSrcBits;
  290. const int crc_mask = (1 << kSrcBits) - 1;
  291. for (int x_pos = 0; x_pos < x_end; x_pos++) {
  292. for (int y_pos = 0; y_pos < y_end; y_pos++) {
  293. const int pos = y_pos * pic_width + x_pos;
  294. // valid data
  295. if (src_is_added[pos]) {
  296. block_hash curr_block_hash;
  297. curr_block_hash.x = x_pos;
  298. curr_block_hash.y = y_pos;
  299. const uint32_t hash_value1 = (src_hash[0][pos] & crc_mask) + add_value;
  300. curr_block_hash.hash_value2 = src_hash[1][pos];
  301. hash_table_add_to_table(p_hash_table, hash_value1, &curr_block_hash);
  302. }
  303. }
  304. }
  305. }
  306. int av1_hash_is_horizontal_perfect(const YV12_BUFFER_CONFIG *picture,
  307. int block_size, int x_start, int y_start) {
  308. const int stride = picture->y_stride;
  309. const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
  310. if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
  311. const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
  312. for (int i = 0; i < block_size; i++) {
  313. for (int j = 1; j < block_size; j++) {
  314. if (p16[j] != p16[0]) {
  315. return 0;
  316. }
  317. }
  318. p16 += stride;
  319. }
  320. } else {
  321. for (int i = 0; i < block_size; i++) {
  322. for (int j = 1; j < block_size; j++) {
  323. if (p[j] != p[0]) {
  324. return 0;
  325. }
  326. }
  327. p += stride;
  328. }
  329. }
  330. return 1;
  331. }
  332. int av1_hash_is_vertical_perfect(const YV12_BUFFER_CONFIG *picture,
  333. int block_size, int x_start, int y_start) {
  334. const int stride = picture->y_stride;
  335. const uint8_t *p = picture->y_buffer + y_start * stride + x_start;
  336. if (picture->flags & YV12_FLAG_HIGHBITDEPTH) {
  337. const uint16_t *p16 = CONVERT_TO_SHORTPTR(p);
  338. for (int i = 0; i < block_size; i++) {
  339. for (int j = 1; j < block_size; j++) {
  340. if (p16[j * stride + i] != p16[i]) {
  341. return 0;
  342. }
  343. }
  344. }
  345. } else {
  346. for (int i = 0; i < block_size; i++) {
  347. for (int j = 1; j < block_size; j++) {
  348. if (p[j * stride + i] != p[i]) {
  349. return 0;
  350. }
  351. }
  352. }
  353. }
  354. return 1;
  355. }
  356. void av1_get_block_hash_value(IntraBCHashInfo *intrabc_hash_info,
  357. const uint8_t *y_src, int stride, int block_size,
  358. uint32_t *hash_value1, uint32_t *hash_value2,
  359. int use_highbitdepth) {
  360. int add_value = hash_block_size_to_index(block_size);
  361. assert(add_value >= 0);
  362. add_value <<= kSrcBits;
  363. const int crc_mask = (1 << kSrcBits) - 1;
  364. CRC_CALCULATOR *calc_1 = &intrabc_hash_info->crc_calculator1;
  365. CRC_CALCULATOR *calc_2 = &intrabc_hash_info->crc_calculator2;
  366. uint32_t **buf_1 = intrabc_hash_info->hash_value_buffer[0];
  367. uint32_t **buf_2 = intrabc_hash_info->hash_value_buffer[1];
  368. // 2x2 subblock hash values in current CU
  369. int sub_block_in_width = (block_size >> 1);
  370. if (use_highbitdepth) {
  371. uint16_t pixel_to_hash[4];
  372. uint16_t *y16_src = CONVERT_TO_SHORTPTR(y_src);
  373. for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
  374. for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
  375. int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
  376. get_pixels_in_1D_short_array_by_block_2x2(
  377. y16_src + y_pos * stride + x_pos, stride, pixel_to_hash);
  378. assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
  379. buf_1[0][pos] = av1_get_crc_value(calc_1, (uint8_t *)pixel_to_hash,
  380. sizeof(pixel_to_hash));
  381. buf_2[0][pos] = av1_get_crc_value(calc_2, (uint8_t *)pixel_to_hash,
  382. sizeof(pixel_to_hash));
  383. }
  384. }
  385. } else {
  386. uint8_t pixel_to_hash[4];
  387. for (int y_pos = 0; y_pos < block_size; y_pos += 2) {
  388. for (int x_pos = 0; x_pos < block_size; x_pos += 2) {
  389. int pos = (y_pos >> 1) * sub_block_in_width + (x_pos >> 1);
  390. get_pixels_in_1D_char_array_by_block_2x2(y_src + y_pos * stride + x_pos,
  391. stride, pixel_to_hash);
  392. assert(pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
  393. buf_1[0][pos] =
  394. av1_get_crc_value(calc_1, pixel_to_hash, sizeof(pixel_to_hash));
  395. buf_2[0][pos] =
  396. av1_get_crc_value(calc_2, pixel_to_hash, sizeof(pixel_to_hash));
  397. }
  398. }
  399. }
  400. int src_sub_block_in_width = sub_block_in_width;
  401. sub_block_in_width >>= 1;
  402. int src_idx = 1;
  403. int dst_idx = 0;
  404. // 4x4 subblock hash values to current block hash values
  405. uint32_t to_hash[4];
  406. for (int sub_width = 4; sub_width <= block_size; sub_width *= 2) {
  407. src_idx = 1 - src_idx;
  408. dst_idx = 1 - dst_idx;
  409. int dst_pos = 0;
  410. for (int y_pos = 0; y_pos < sub_block_in_width; y_pos++) {
  411. for (int x_pos = 0; x_pos < sub_block_in_width; x_pos++) {
  412. int srcPos = (y_pos << 1) * src_sub_block_in_width + (x_pos << 1);
  413. assert(srcPos + 1 < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
  414. assert(srcPos + src_sub_block_in_width + 1 <
  415. AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
  416. assert(dst_pos < AOM_BUFFER_SIZE_FOR_BLOCK_HASH);
  417. to_hash[0] = buf_1[src_idx][srcPos];
  418. to_hash[1] = buf_1[src_idx][srcPos + 1];
  419. to_hash[2] = buf_1[src_idx][srcPos + src_sub_block_in_width];
  420. to_hash[3] = buf_1[src_idx][srcPos + src_sub_block_in_width + 1];
  421. buf_1[dst_idx][dst_pos] =
  422. av1_get_crc_value(calc_1, (uint8_t *)to_hash, sizeof(to_hash));
  423. to_hash[0] = buf_2[src_idx][srcPos];
  424. to_hash[1] = buf_2[src_idx][srcPos + 1];
  425. to_hash[2] = buf_2[src_idx][srcPos + src_sub_block_in_width];
  426. to_hash[3] = buf_2[src_idx][srcPos + src_sub_block_in_width + 1];
  427. buf_2[dst_idx][dst_pos] =
  428. av1_get_crc_value(calc_2, (uint8_t *)to_hash, sizeof(to_hash));
  429. dst_pos++;
  430. }
  431. }
  432. src_sub_block_in_width = sub_block_in_width;
  433. sub_block_in_width >>= 1;
  434. }
  435. *hash_value1 = (buf_1[dst_idx][0] & crc_mask) + add_value;
  436. *hash_value2 = buf_2[dst_idx][0];
  437. }