denoising.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /*
  2. * Copyright (c) 2012 The WebM project authors. All Rights Reserved.
  3. *
  4. * Use of this source code is governed by a BSD-style license
  5. * that can be found in the LICENSE file in the root of the source
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <limits.h>
  11. #include "denoising.h"
  12. #include "vp8/common/reconinter.h"
  13. #include "vpx/vpx_integer.h"
  14. #include "vpx_mem/vpx_mem.h"
  15. #include "vp8_rtcd.h"
  16. static const unsigned int NOISE_MOTION_THRESHOLD = 25 * 25;
  17. /* SSE_DIFF_THRESHOLD is selected as ~95% confidence assuming
  18. * var(noise) ~= 100.
  19. */
  20. static const unsigned int SSE_DIFF_THRESHOLD = 16 * 16 * 20;
  21. static const unsigned int SSE_THRESHOLD = 16 * 16 * 40;
  22. static const unsigned int SSE_THRESHOLD_HIGH = 16 * 16 * 80;
  23. /*
  24. * The filter function was modified to reduce the computational complexity.
  25. * Step 1:
  26. * Instead of applying tap coefficients for each pixel, we calculated the
  27. * pixel adjustments vs. pixel diff value ahead of time.
  28. * adjustment = filtered_value - current_raw
  29. * = (filter_coefficient * diff + 128) >> 8
  30. * where
  31. * filter_coefficient = (255 << 8) / (256 + ((absdiff * 330) >> 3));
  32. * filter_coefficient += filter_coefficient /
  33. * (3 + motion_magnitude_adjustment);
  34. * filter_coefficient is clamped to 0 ~ 255.
  35. *
  36. * Step 2:
  37. * The adjustment vs. diff curve becomes flat very quick when diff increases.
  38. * This allowed us to use only several levels to approximate the curve without
  39. * changing the filtering algorithm too much.
  40. * The adjustments were further corrected by checking the motion magnitude.
  41. * The levels used are:
  42. * diff adjustment w/o motion correction adjustment w/ motion correction
  43. * [-255, -16] -6 -7
  44. * [-15, -8] -4 -5
  45. * [-7, -4] -3 -4
  46. * [-3, 3] diff diff
  47. * [4, 7] 3 4
  48. * [8, 15] 4 5
  49. * [16, 255] 6 7
  50. */
  51. int vp8_denoiser_filter_c(unsigned char *mc_running_avg_y, int mc_avg_y_stride,
  52. unsigned char *running_avg_y, int avg_y_stride,
  53. unsigned char *sig, int sig_stride,
  54. unsigned int motion_magnitude,
  55. int increase_denoising) {
  56. unsigned char *running_avg_y_start = running_avg_y;
  57. unsigned char *sig_start = sig;
  58. int sum_diff_thresh;
  59. int r, c;
  60. int sum_diff = 0;
  61. int adj_val[3] = { 3, 4, 6 };
  62. int shift_inc1 = 0;
  63. int shift_inc2 = 1;
  64. int col_sum[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  65. /* If motion_magnitude is small, making the denoiser more aggressive by
  66. * increasing the adjustment for each level. Add another increment for
  67. * blocks that are labeled for increase denoising. */
  68. if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD) {
  69. if (increase_denoising) {
  70. shift_inc1 = 1;
  71. shift_inc2 = 2;
  72. }
  73. adj_val[0] += shift_inc2;
  74. adj_val[1] += shift_inc2;
  75. adj_val[2] += shift_inc2;
  76. }
  77. for (r = 0; r < 16; ++r) {
  78. for (c = 0; c < 16; ++c) {
  79. int diff = 0;
  80. int adjustment = 0;
  81. int absdiff = 0;
  82. diff = mc_running_avg_y[c] - sig[c];
  83. absdiff = abs(diff);
  84. // When |diff| <= |3 + shift_inc1|, use pixel value from
  85. // last denoised raw.
  86. if (absdiff <= 3 + shift_inc1) {
  87. running_avg_y[c] = mc_running_avg_y[c];
  88. col_sum[c] += diff;
  89. } else {
  90. if (absdiff >= 4 + shift_inc1 && absdiff <= 7) {
  91. adjustment = adj_val[0];
  92. } else if (absdiff >= 8 && absdiff <= 15) {
  93. adjustment = adj_val[1];
  94. } else {
  95. adjustment = adj_val[2];
  96. }
  97. if (diff > 0) {
  98. if ((sig[c] + adjustment) > 255) {
  99. running_avg_y[c] = 255;
  100. } else {
  101. running_avg_y[c] = sig[c] + adjustment;
  102. }
  103. col_sum[c] += adjustment;
  104. } else {
  105. if ((sig[c] - adjustment) < 0) {
  106. running_avg_y[c] = 0;
  107. } else {
  108. running_avg_y[c] = sig[c] - adjustment;
  109. }
  110. col_sum[c] -= adjustment;
  111. }
  112. }
  113. }
  114. /* Update pointers for next iteration. */
  115. sig += sig_stride;
  116. mc_running_avg_y += mc_avg_y_stride;
  117. running_avg_y += avg_y_stride;
  118. }
  119. for (c = 0; c < 16; ++c) {
  120. // Below we clip the value in the same way which SSE code use.
  121. // When adopting aggressive denoiser, the adj_val for each pixel
  122. // could be at most 8 (this is current max adjustment of the map).
  123. // In SSE code, we calculate the sum of adj_val for
  124. // the columns, so the sum could be upto 128(16 rows). However,
  125. // the range of the value is -128 ~ 127 in SSE code, that's why
  126. // we do this change in C code.
  127. // We don't do this for UV denoiser, since there are only 8 rows,
  128. // and max adjustments <= 8, so the sum of the columns will not
  129. // exceed 64.
  130. if (col_sum[c] >= 128) {
  131. col_sum[c] = 127;
  132. }
  133. sum_diff += col_sum[c];
  134. }
  135. sum_diff_thresh = SUM_DIFF_THRESHOLD;
  136. if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH;
  137. if (abs(sum_diff) > sum_diff_thresh) {
  138. // Before returning to copy the block (i.e., apply no denoising), check
  139. // if we can still apply some (weaker) temporal filtering to this block,
  140. // that would otherwise not be denoised at all. Simplest is to apply
  141. // an additional adjustment to running_avg_y to bring it closer to sig.
  142. // The adjustment is capped by a maximum delta, and chosen such that
  143. // in most cases the resulting sum_diff will be within the
  144. // accceptable range given by sum_diff_thresh.
  145. // The delta is set by the excess of absolute pixel diff over threshold.
  146. int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
  147. // Only apply the adjustment for max delta up to 3.
  148. if (delta < 4) {
  149. sig -= sig_stride * 16;
  150. mc_running_avg_y -= mc_avg_y_stride * 16;
  151. running_avg_y -= avg_y_stride * 16;
  152. for (r = 0; r < 16; ++r) {
  153. for (c = 0; c < 16; ++c) {
  154. int diff = mc_running_avg_y[c] - sig[c];
  155. int adjustment = abs(diff);
  156. if (adjustment > delta) adjustment = delta;
  157. if (diff > 0) {
  158. // Bring denoised signal down.
  159. if (running_avg_y[c] - adjustment < 0) {
  160. running_avg_y[c] = 0;
  161. } else {
  162. running_avg_y[c] = running_avg_y[c] - adjustment;
  163. }
  164. col_sum[c] -= adjustment;
  165. } else if (diff < 0) {
  166. // Bring denoised signal up.
  167. if (running_avg_y[c] + adjustment > 255) {
  168. running_avg_y[c] = 255;
  169. } else {
  170. running_avg_y[c] = running_avg_y[c] + adjustment;
  171. }
  172. col_sum[c] += adjustment;
  173. }
  174. }
  175. // TODO(marpan): Check here if abs(sum_diff) has gone below the
  176. // threshold sum_diff_thresh, and if so, we can exit the row loop.
  177. sig += sig_stride;
  178. mc_running_avg_y += mc_avg_y_stride;
  179. running_avg_y += avg_y_stride;
  180. }
  181. sum_diff = 0;
  182. for (c = 0; c < 16; ++c) {
  183. if (col_sum[c] >= 128) {
  184. col_sum[c] = 127;
  185. }
  186. sum_diff += col_sum[c];
  187. }
  188. if (abs(sum_diff) > sum_diff_thresh) return COPY_BLOCK;
  189. } else {
  190. return COPY_BLOCK;
  191. }
  192. }
  193. vp8_copy_mem16x16(running_avg_y_start, avg_y_stride, sig_start, sig_stride);
  194. return FILTER_BLOCK;
  195. }
  196. int vp8_denoiser_filter_uv_c(unsigned char *mc_running_avg_uv,
  197. int mc_avg_uv_stride,
  198. unsigned char *running_avg_uv, int avg_uv_stride,
  199. unsigned char *sig, int sig_stride,
  200. unsigned int motion_magnitude,
  201. int increase_denoising) {
  202. unsigned char *running_avg_uv_start = running_avg_uv;
  203. unsigned char *sig_start = sig;
  204. int sum_diff_thresh;
  205. int r, c;
  206. int sum_diff = 0;
  207. int sum_block = 0;
  208. int adj_val[3] = { 3, 4, 6 };
  209. int shift_inc1 = 0;
  210. int shift_inc2 = 1;
  211. /* If motion_magnitude is small, making the denoiser more aggressive by
  212. * increasing the adjustment for each level. Add another increment for
  213. * blocks that are labeled for increase denoising. */
  214. if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) {
  215. if (increase_denoising) {
  216. shift_inc1 = 1;
  217. shift_inc2 = 2;
  218. }
  219. adj_val[0] += shift_inc2;
  220. adj_val[1] += shift_inc2;
  221. adj_val[2] += shift_inc2;
  222. }
  223. // Avoid denoising color signal if its close to average level.
  224. for (r = 0; r < 8; ++r) {
  225. for (c = 0; c < 8; ++c) {
  226. sum_block += sig[c];
  227. }
  228. sig += sig_stride;
  229. }
  230. if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
  231. return COPY_BLOCK;
  232. }
  233. sig -= sig_stride * 8;
  234. for (r = 0; r < 8; ++r) {
  235. for (c = 0; c < 8; ++c) {
  236. int diff = 0;
  237. int adjustment = 0;
  238. int absdiff = 0;
  239. diff = mc_running_avg_uv[c] - sig[c];
  240. absdiff = abs(diff);
  241. // When |diff| <= |3 + shift_inc1|, use pixel value from
  242. // last denoised raw.
  243. if (absdiff <= 3 + shift_inc1) {
  244. running_avg_uv[c] = mc_running_avg_uv[c];
  245. sum_diff += diff;
  246. } else {
  247. if (absdiff >= 4 && absdiff <= 7) {
  248. adjustment = adj_val[0];
  249. } else if (absdiff >= 8 && absdiff <= 15) {
  250. adjustment = adj_val[1];
  251. } else {
  252. adjustment = adj_val[2];
  253. }
  254. if (diff > 0) {
  255. if ((sig[c] + adjustment) > 255) {
  256. running_avg_uv[c] = 255;
  257. } else {
  258. running_avg_uv[c] = sig[c] + adjustment;
  259. }
  260. sum_diff += adjustment;
  261. } else {
  262. if ((sig[c] - adjustment) < 0) {
  263. running_avg_uv[c] = 0;
  264. } else {
  265. running_avg_uv[c] = sig[c] - adjustment;
  266. }
  267. sum_diff -= adjustment;
  268. }
  269. }
  270. }
  271. /* Update pointers for next iteration. */
  272. sig += sig_stride;
  273. mc_running_avg_uv += mc_avg_uv_stride;
  274. running_avg_uv += avg_uv_stride;
  275. }
  276. sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
  277. if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
  278. if (abs(sum_diff) > sum_diff_thresh) {
  279. // Before returning to copy the block (i.e., apply no denoising), check
  280. // if we can still apply some (weaker) temporal filtering to this block,
  281. // that would otherwise not be denoised at all. Simplest is to apply
  282. // an additional adjustment to running_avg_y to bring it closer to sig.
  283. // The adjustment is capped by a maximum delta, and chosen such that
  284. // in most cases the resulting sum_diff will be within the
  285. // accceptable range given by sum_diff_thresh.
  286. // The delta is set by the excess of absolute pixel diff over threshold.
  287. int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
  288. // Only apply the adjustment for max delta up to 3.
  289. if (delta < 4) {
  290. sig -= sig_stride * 8;
  291. mc_running_avg_uv -= mc_avg_uv_stride * 8;
  292. running_avg_uv -= avg_uv_stride * 8;
  293. for (r = 0; r < 8; ++r) {
  294. for (c = 0; c < 8; ++c) {
  295. int diff = mc_running_avg_uv[c] - sig[c];
  296. int adjustment = abs(diff);
  297. if (adjustment > delta) adjustment = delta;
  298. if (diff > 0) {
  299. // Bring denoised signal down.
  300. if (running_avg_uv[c] - adjustment < 0) {
  301. running_avg_uv[c] = 0;
  302. } else {
  303. running_avg_uv[c] = running_avg_uv[c] - adjustment;
  304. }
  305. sum_diff -= adjustment;
  306. } else if (diff < 0) {
  307. // Bring denoised signal up.
  308. if (running_avg_uv[c] + adjustment > 255) {
  309. running_avg_uv[c] = 255;
  310. } else {
  311. running_avg_uv[c] = running_avg_uv[c] + adjustment;
  312. }
  313. sum_diff += adjustment;
  314. }
  315. }
  316. // TODO(marpan): Check here if abs(sum_diff) has gone below the
  317. // threshold sum_diff_thresh, and if so, we can exit the row loop.
  318. sig += sig_stride;
  319. mc_running_avg_uv += mc_avg_uv_stride;
  320. running_avg_uv += avg_uv_stride;
  321. }
  322. if (abs(sum_diff) > sum_diff_thresh) return COPY_BLOCK;
  323. } else {
  324. return COPY_BLOCK;
  325. }
  326. }
  327. vp8_copy_mem8x8(running_avg_uv_start, avg_uv_stride, sig_start, sig_stride);
  328. return FILTER_BLOCK;
  329. }
  330. void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) {
  331. assert(mode > 0); // Denoiser is allocated only if mode > 0.
  332. if (mode == 1) {
  333. denoiser->denoiser_mode = kDenoiserOnYOnly;
  334. } else if (mode == 2) {
  335. denoiser->denoiser_mode = kDenoiserOnYUV;
  336. } else if (mode == 3) {
  337. denoiser->denoiser_mode = kDenoiserOnYUVAggressive;
  338. } else {
  339. denoiser->denoiser_mode = kDenoiserOnYUV;
  340. }
  341. if (denoiser->denoiser_mode != kDenoiserOnYUVAggressive) {
  342. denoiser->denoise_pars.scale_sse_thresh = 1;
  343. denoiser->denoise_pars.scale_motion_thresh = 8;
  344. denoiser->denoise_pars.scale_increase_filter = 0;
  345. denoiser->denoise_pars.denoise_mv_bias = 95;
  346. denoiser->denoise_pars.pickmode_mv_bias = 100;
  347. denoiser->denoise_pars.qp_thresh = 0;
  348. denoiser->denoise_pars.consec_zerolast = UINT_MAX;
  349. denoiser->denoise_pars.spatial_blur = 0;
  350. } else {
  351. denoiser->denoise_pars.scale_sse_thresh = 2;
  352. denoiser->denoise_pars.scale_motion_thresh = 16;
  353. denoiser->denoise_pars.scale_increase_filter = 1;
  354. denoiser->denoise_pars.denoise_mv_bias = 60;
  355. denoiser->denoise_pars.pickmode_mv_bias = 75;
  356. denoiser->denoise_pars.qp_thresh = 80;
  357. denoiser->denoise_pars.consec_zerolast = 15;
  358. denoiser->denoise_pars.spatial_blur = 0;
  359. }
  360. }
  361. int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
  362. int num_mb_rows, int num_mb_cols, int mode) {
  363. int i;
  364. assert(denoiser);
  365. denoiser->num_mb_cols = num_mb_cols;
  366. for (i = 0; i < MAX_REF_FRAMES; ++i) {
  367. denoiser->yv12_running_avg[i].flags = 0;
  368. if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width,
  369. height, VP8BORDERINPIXELS) < 0) {
  370. vp8_denoiser_free(denoiser);
  371. return 1;
  372. }
  373. memset(denoiser->yv12_running_avg[i].buffer_alloc, 0,
  374. denoiser->yv12_running_avg[i].frame_size);
  375. }
  376. denoiser->yv12_mc_running_avg.flags = 0;
  377. if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
  378. height, VP8BORDERINPIXELS) < 0) {
  379. vp8_denoiser_free(denoiser);
  380. return 1;
  381. }
  382. memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
  383. denoiser->yv12_mc_running_avg.frame_size);
  384. if (vp8_yv12_alloc_frame_buffer(&denoiser->yv12_last_source, width, height,
  385. VP8BORDERINPIXELS) < 0) {
  386. vp8_denoiser_free(denoiser);
  387. return 1;
  388. }
  389. memset(denoiser->yv12_last_source.buffer_alloc, 0,
  390. denoiser->yv12_last_source.frame_size);
  391. denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1);
  392. if (!denoiser->denoise_state) {
  393. vp8_denoiser_free(denoiser);
  394. return 1;
  395. }
  396. memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols));
  397. vp8_denoiser_set_parameters(denoiser, mode);
  398. denoiser->nmse_source_diff = 0;
  399. denoiser->nmse_source_diff_count = 0;
  400. denoiser->qp_avg = 0;
  401. // QP threshold below which we can go up to aggressive mode.
  402. denoiser->qp_threshold_up = 80;
  403. // QP threshold above which we can go back down to normal mode.
  404. // For now keep this second threshold high, so not used currently.
  405. denoiser->qp_threshold_down = 128;
  406. // Bitrate thresholds and noise metric (nmse) thresholds for switching to
  407. // aggressive mode.
  408. // TODO(marpan): Adjust thresholds, including effect on resolution.
  409. denoiser->bitrate_threshold = 400000; // (bits/sec).
  410. denoiser->threshold_aggressive_mode = 80;
  411. if (width * height > 1280 * 720) {
  412. denoiser->bitrate_threshold = 3000000;
  413. denoiser->threshold_aggressive_mode = 200;
  414. } else if (width * height > 960 * 540) {
  415. denoiser->bitrate_threshold = 1200000;
  416. denoiser->threshold_aggressive_mode = 120;
  417. } else if (width * height > 640 * 480) {
  418. denoiser->bitrate_threshold = 600000;
  419. denoiser->threshold_aggressive_mode = 100;
  420. }
  421. return 0;
  422. }
  423. void vp8_denoiser_free(VP8_DENOISER *denoiser) {
  424. int i;
  425. assert(denoiser);
  426. for (i = 0; i < MAX_REF_FRAMES; ++i) {
  427. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]);
  428. }
  429. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
  430. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_last_source);
  431. vpx_free(denoiser->denoise_state);
  432. }
  433. void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, MACROBLOCK *x,
  434. unsigned int best_sse, unsigned int zero_mv_sse,
  435. int recon_yoffset, int recon_uvoffset,
  436. loop_filter_info_n *lfi_n, int mb_row, int mb_col,
  437. int block_index, int consec_zero_last)
  438. {
  439. int mv_row;
  440. int mv_col;
  441. unsigned int motion_threshold;
  442. unsigned int motion_magnitude2;
  443. unsigned int sse_thresh;
  444. int sse_diff_thresh = 0;
  445. // Spatial loop filter: only applied selectively based on
  446. // temporal filter state of block relative to top/left neighbors.
  447. int apply_spatial_loop_filter = 1;
  448. MV_REFERENCE_FRAME frame = x->best_reference_frame;
  449. MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame;
  450. enum vp8_denoiser_decision decision = FILTER_BLOCK;
  451. enum vp8_denoiser_decision decision_u = COPY_BLOCK;
  452. enum vp8_denoiser_decision decision_v = COPY_BLOCK;
  453. if (zero_frame) {
  454. YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame];
  455. YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg;
  456. YV12_BUFFER_CONFIG saved_pre, saved_dst;
  457. MB_MODE_INFO saved_mbmi;
  458. MACROBLOCKD *filter_xd = &x->e_mbd;
  459. MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi;
  460. int sse_diff = 0;
  461. // Bias on zero motion vector sse.
  462. const int zero_bias = denoiser->denoise_pars.denoise_mv_bias;
  463. zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100);
  464. sse_diff = (int)zero_mv_sse - (int)best_sse;
  465. saved_mbmi = *mbmi;
  466. /* Use the best MV for the compensation. */
  467. mbmi->ref_frame = x->best_reference_frame;
  468. mbmi->mode = x->best_sse_inter_mode;
  469. mbmi->mv = x->best_sse_mv;
  470. mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs;
  471. mv_col = x->best_sse_mv.as_mv.col;
  472. mv_row = x->best_sse_mv.as_mv.row;
  473. // Bias to zero_mv if small amount of motion.
  474. // Note sse_diff_thresh is intialized to zero, so this ensures
  475. // we will always choose zero_mv for denoising if
  476. // zero_mv_see <= best_sse (i.e., sse_diff <= 0).
  477. if ((unsigned int)(mv_row * mv_row + mv_col * mv_col) <=
  478. NOISE_MOTION_THRESHOLD) {
  479. sse_diff_thresh = (int)SSE_DIFF_THRESHOLD;
  480. }
  481. if (frame == INTRA_FRAME || sse_diff <= sse_diff_thresh) {
  482. /*
  483. * Handle intra blocks as referring to last frame with zero motion
  484. * and let the absolute pixel difference affect the filter factor.
  485. * Also consider small amount of motion as being random walk due
  486. * to noise, if it doesn't mean that we get a much bigger error.
  487. * Note that any changes to the mode info only affects the
  488. * denoising.
  489. */
  490. x->denoise_zeromv = 1;
  491. mbmi->ref_frame = x->best_zeromv_reference_frame;
  492. src = &denoiser->yv12_running_avg[zero_frame];
  493. mbmi->mode = ZEROMV;
  494. mbmi->mv.as_int = 0;
  495. x->best_sse_inter_mode = ZEROMV;
  496. x->best_sse_mv.as_int = 0;
  497. best_sse = zero_mv_sse;
  498. }
  499. mv_row = x->best_sse_mv.as_mv.row;
  500. mv_col = x->best_sse_mv.as_mv.col;
  501. motion_magnitude2 = mv_row * mv_row + mv_col * mv_col;
  502. motion_threshold =
  503. denoiser->denoise_pars.scale_motion_thresh * NOISE_MOTION_THRESHOLD;
  504. if (motion_magnitude2 <
  505. denoiser->denoise_pars.scale_increase_filter * NOISE_MOTION_THRESHOLD) {
  506. x->increase_denoising = 1;
  507. }
  508. sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD;
  509. if (x->increase_denoising) {
  510. sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD_HIGH;
  511. }
  512. if (best_sse > sse_thresh || motion_magnitude2 > motion_threshold) {
  513. decision = COPY_BLOCK;
  514. }
  515. // If block is considered skin, don't denoise if the block
  516. // (1) is selected as non-zero motion for current frame, or
  517. // (2) has not been selected as ZERO_LAST mode at least x past frames
  518. // in a row.
  519. // TODO(marpan): Parameter "x" should be varied with framerate.
  520. // In particualar, should be reduced for layers (base layer/LAST).
  521. if (x->is_skin && (consec_zero_last < 2 || motion_magnitude2 > 0)) {
  522. decision = COPY_BLOCK;
  523. }
  524. if (decision == FILTER_BLOCK) {
  525. saved_pre = filter_xd->pre;
  526. saved_dst = filter_xd->dst;
  527. /* Compensate the running average. */
  528. filter_xd->pre.y_buffer = src->y_buffer + recon_yoffset;
  529. filter_xd->pre.u_buffer = src->u_buffer + recon_uvoffset;
  530. filter_xd->pre.v_buffer = src->v_buffer + recon_uvoffset;
  531. /* Write the compensated running average to the destination buffer. */
  532. filter_xd->dst.y_buffer = dst->y_buffer + recon_yoffset;
  533. filter_xd->dst.u_buffer = dst->u_buffer + recon_uvoffset;
  534. filter_xd->dst.v_buffer = dst->v_buffer + recon_uvoffset;
  535. if (!x->skip) {
  536. vp8_build_inter_predictors_mb(filter_xd);
  537. } else {
  538. vp8_build_inter16x16_predictors_mb(
  539. filter_xd, filter_xd->dst.y_buffer, filter_xd->dst.u_buffer,
  540. filter_xd->dst.v_buffer, filter_xd->dst.y_stride,
  541. filter_xd->dst.uv_stride);
  542. }
  543. filter_xd->pre = saved_pre;
  544. filter_xd->dst = saved_dst;
  545. *mbmi = saved_mbmi;
  546. }
  547. } else {
  548. // zero_frame should always be 1 for real-time mode, as the
  549. // ZEROMV mode is always checked, so we should never go into this branch.
  550. // If case ZEROMV is not checked, then we will force no denoise (COPY).
  551. decision = COPY_BLOCK;
  552. }
  553. if (decision == FILTER_BLOCK) {
  554. unsigned char *mc_running_avg_y =
  555. denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset;
  556. int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride;
  557. unsigned char *running_avg_y =
  558. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset;
  559. int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
  560. /* Filter. */
  561. decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride,
  562. running_avg_y, avg_y_stride, x->thismb, 16,
  563. motion_magnitude2, x->increase_denoising);
  564. denoiser->denoise_state[block_index] =
  565. motion_magnitude2 > 0 ? kFilterNonZeroMV : kFilterZeroMV;
  566. // Only denoise UV for zero motion, and if y channel was denoised.
  567. if (denoiser->denoiser_mode != kDenoiserOnYOnly && motion_magnitude2 == 0 &&
  568. decision == FILTER_BLOCK) {
  569. unsigned char *mc_running_avg_u =
  570. denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset;
  571. unsigned char *running_avg_u =
  572. denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset;
  573. unsigned char *mc_running_avg_v =
  574. denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset;
  575. unsigned char *running_avg_v =
  576. denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset;
  577. int mc_avg_uv_stride = denoiser->yv12_mc_running_avg.uv_stride;
  578. int avg_uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
  579. int signal_stride = x->block[16].src_stride;
  580. decision_u = vp8_denoiser_filter_uv(
  581. mc_running_avg_u, mc_avg_uv_stride, running_avg_u, avg_uv_stride,
  582. x->block[16].src + *x->block[16].base_src, signal_stride,
  583. motion_magnitude2, 0);
  584. decision_v = vp8_denoiser_filter_uv(
  585. mc_running_avg_v, mc_avg_uv_stride, running_avg_v, avg_uv_stride,
  586. x->block[20].src + *x->block[20].base_src, signal_stride,
  587. motion_magnitude2, 0);
  588. }
  589. }
  590. if (decision == COPY_BLOCK) {
  591. /* No filtering of this block; it differs too much from the predictor,
  592. * or the motion vector magnitude is considered too big.
  593. */
  594. x->denoise_zeromv = 0;
  595. vp8_copy_mem16x16(
  596. x->thismb, 16,
  597. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  598. denoiser->yv12_running_avg[INTRA_FRAME].y_stride);
  599. denoiser->denoise_state[block_index] = kNoFilter;
  600. }
  601. if (denoiser->denoiser_mode != kDenoiserOnYOnly) {
  602. if (decision_u == COPY_BLOCK) {
  603. vp8_copy_mem8x8(
  604. x->block[16].src + *x->block[16].base_src, x->block[16].src_stride,
  605. denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset,
  606. denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
  607. }
  608. if (decision_v == COPY_BLOCK) {
  609. vp8_copy_mem8x8(
  610. x->block[20].src + *x->block[20].base_src, x->block[16].src_stride,
  611. denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset,
  612. denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
  613. }
  614. }
  615. // Option to selectively deblock the denoised signal, for y channel only.
  616. if (apply_spatial_loop_filter) {
  617. loop_filter_info lfi;
  618. int apply_filter_col = 0;
  619. int apply_filter_row = 0;
  620. int apply_filter = 0;
  621. int y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
  622. int uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
  623. // Fix filter level to some nominal value for now.
  624. int filter_level = 48;
  625. int hev_index = lfi_n->hev_thr_lut[INTER_FRAME][filter_level];
  626. lfi.mblim = lfi_n->mblim[filter_level];
  627. lfi.blim = lfi_n->blim[filter_level];
  628. lfi.lim = lfi_n->lim[filter_level];
  629. lfi.hev_thr = lfi_n->hev_thr[hev_index];
  630. // Apply filter if there is a difference in the denoiser filter state
  631. // between the current and left/top block, or if non-zero motion vector
  632. // is used for the motion-compensated filtering.
  633. if (mb_col > 0) {
  634. apply_filter_col =
  635. !((denoiser->denoise_state[block_index] ==
  636. denoiser->denoise_state[block_index - 1]) &&
  637. denoiser->denoise_state[block_index] != kFilterNonZeroMV);
  638. if (apply_filter_col) {
  639. // Filter left vertical edge.
  640. apply_filter = 1;
  641. vp8_loop_filter_mbv(
  642. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  643. NULL, NULL, y_stride, uv_stride, &lfi);
  644. }
  645. }
  646. if (mb_row > 0) {
  647. apply_filter_row =
  648. !((denoiser->denoise_state[block_index] ==
  649. denoiser->denoise_state[block_index - denoiser->num_mb_cols]) &&
  650. denoiser->denoise_state[block_index] != kFilterNonZeroMV);
  651. if (apply_filter_row) {
  652. // Filter top horizontal edge.
  653. apply_filter = 1;
  654. vp8_loop_filter_mbh(
  655. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  656. NULL, NULL, y_stride, uv_stride, &lfi);
  657. }
  658. }
  659. if (apply_filter) {
  660. // Update the signal block |x|. Pixel changes are only to top and/or
  661. // left boundary pixels: can we avoid full block copy here.
  662. vp8_copy_mem16x16(
  663. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  664. y_stride, x->thismb, 16);
  665. }
  666. }
  667. }