2
0

denoising.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725
  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, int mc_avg_stride,
  197. unsigned char *running_avg, int avg_stride,
  198. unsigned char *sig, int sig_stride,
  199. unsigned int motion_magnitude,
  200. int increase_denoising) {
  201. unsigned char *running_avg_start = running_avg;
  202. unsigned char *sig_start = sig;
  203. int sum_diff_thresh;
  204. int r, c;
  205. int sum_diff = 0;
  206. int sum_block = 0;
  207. int adj_val[3] = { 3, 4, 6 };
  208. int shift_inc1 = 0;
  209. int shift_inc2 = 1;
  210. /* If motion_magnitude is small, making the denoiser more aggressive by
  211. * increasing the adjustment for each level. Add another increment for
  212. * blocks that are labeled for increase denoising. */
  213. if (motion_magnitude <= MOTION_MAGNITUDE_THRESHOLD_UV) {
  214. if (increase_denoising) {
  215. shift_inc1 = 1;
  216. shift_inc2 = 2;
  217. }
  218. adj_val[0] += shift_inc2;
  219. adj_val[1] += shift_inc2;
  220. adj_val[2] += shift_inc2;
  221. }
  222. // Avoid denoising color signal if its close to average level.
  223. for (r = 0; r < 8; ++r) {
  224. for (c = 0; c < 8; ++c) {
  225. sum_block += sig[c];
  226. }
  227. sig += sig_stride;
  228. }
  229. if (abs(sum_block - (128 * 8 * 8)) < SUM_DIFF_FROM_AVG_THRESH_UV) {
  230. return COPY_BLOCK;
  231. }
  232. sig -= sig_stride * 8;
  233. for (r = 0; r < 8; ++r) {
  234. for (c = 0; c < 8; ++c) {
  235. int diff = 0;
  236. int adjustment = 0;
  237. int absdiff = 0;
  238. diff = mc_running_avg[c] - sig[c];
  239. absdiff = abs(diff);
  240. // When |diff| <= |3 + shift_inc1|, use pixel value from
  241. // last denoised raw.
  242. if (absdiff <= 3 + shift_inc1) {
  243. running_avg[c] = mc_running_avg[c];
  244. sum_diff += diff;
  245. } else {
  246. if (absdiff >= 4 && absdiff <= 7) {
  247. adjustment = adj_val[0];
  248. } else if (absdiff >= 8 && absdiff <= 15) {
  249. adjustment = adj_val[1];
  250. } else {
  251. adjustment = adj_val[2];
  252. }
  253. if (diff > 0) {
  254. if ((sig[c] + adjustment) > 255) {
  255. running_avg[c] = 255;
  256. } else {
  257. running_avg[c] = sig[c] + adjustment;
  258. }
  259. sum_diff += adjustment;
  260. } else {
  261. if ((sig[c] - adjustment) < 0) {
  262. running_avg[c] = 0;
  263. } else {
  264. running_avg[c] = sig[c] - adjustment;
  265. }
  266. sum_diff -= adjustment;
  267. }
  268. }
  269. }
  270. /* Update pointers for next iteration. */
  271. sig += sig_stride;
  272. mc_running_avg += mc_avg_stride;
  273. running_avg += avg_stride;
  274. }
  275. sum_diff_thresh = SUM_DIFF_THRESHOLD_UV;
  276. if (increase_denoising) sum_diff_thresh = SUM_DIFF_THRESHOLD_HIGH_UV;
  277. if (abs(sum_diff) > sum_diff_thresh) {
  278. // Before returning to copy the block (i.e., apply no denoising), check
  279. // if we can still apply some (weaker) temporal filtering to this block,
  280. // that would otherwise not be denoised at all. Simplest is to apply
  281. // an additional adjustment to running_avg_y to bring it closer to sig.
  282. // The adjustment is capped by a maximum delta, and chosen such that
  283. // in most cases the resulting sum_diff will be within the
  284. // accceptable range given by sum_diff_thresh.
  285. // The delta is set by the excess of absolute pixel diff over threshold.
  286. int delta = ((abs(sum_diff) - sum_diff_thresh) >> 8) + 1;
  287. // Only apply the adjustment for max delta up to 3.
  288. if (delta < 4) {
  289. sig -= sig_stride * 8;
  290. mc_running_avg -= mc_avg_stride * 8;
  291. running_avg -= avg_stride * 8;
  292. for (r = 0; r < 8; ++r) {
  293. for (c = 0; c < 8; ++c) {
  294. int diff = mc_running_avg[c] - sig[c];
  295. int adjustment = abs(diff);
  296. if (adjustment > delta) adjustment = delta;
  297. if (diff > 0) {
  298. // Bring denoised signal down.
  299. if (running_avg[c] - adjustment < 0) {
  300. running_avg[c] = 0;
  301. } else {
  302. running_avg[c] = running_avg[c] - adjustment;
  303. }
  304. sum_diff -= adjustment;
  305. } else if (diff < 0) {
  306. // Bring denoised signal up.
  307. if (running_avg[c] + adjustment > 255) {
  308. running_avg[c] = 255;
  309. } else {
  310. running_avg[c] = running_avg[c] + adjustment;
  311. }
  312. sum_diff += adjustment;
  313. }
  314. }
  315. // TODO(marpan): Check here if abs(sum_diff) has gone below the
  316. // threshold sum_diff_thresh, and if so, we can exit the row loop.
  317. sig += sig_stride;
  318. mc_running_avg += mc_avg_stride;
  319. running_avg += avg_stride;
  320. }
  321. if (abs(sum_diff) > sum_diff_thresh) return COPY_BLOCK;
  322. } else {
  323. return COPY_BLOCK;
  324. }
  325. }
  326. vp8_copy_mem8x8(running_avg_start, avg_stride, sig_start, sig_stride);
  327. return FILTER_BLOCK;
  328. }
  329. void vp8_denoiser_set_parameters(VP8_DENOISER *denoiser, int mode) {
  330. assert(mode > 0); // Denoiser is allocated only if mode > 0.
  331. if (mode == 1) {
  332. denoiser->denoiser_mode = kDenoiserOnYOnly;
  333. } else if (mode == 2) {
  334. denoiser->denoiser_mode = kDenoiserOnYUV;
  335. } else if (mode == 3) {
  336. denoiser->denoiser_mode = kDenoiserOnYUVAggressive;
  337. } else {
  338. denoiser->denoiser_mode = kDenoiserOnYUV;
  339. }
  340. if (denoiser->denoiser_mode != kDenoiserOnYUVAggressive) {
  341. denoiser->denoise_pars.scale_sse_thresh = 1;
  342. denoiser->denoise_pars.scale_motion_thresh = 8;
  343. denoiser->denoise_pars.scale_increase_filter = 0;
  344. denoiser->denoise_pars.denoise_mv_bias = 95;
  345. denoiser->denoise_pars.pickmode_mv_bias = 100;
  346. denoiser->denoise_pars.qp_thresh = 0;
  347. denoiser->denoise_pars.consec_zerolast = UINT_MAX;
  348. denoiser->denoise_pars.spatial_blur = 0;
  349. } else {
  350. denoiser->denoise_pars.scale_sse_thresh = 2;
  351. denoiser->denoise_pars.scale_motion_thresh = 16;
  352. denoiser->denoise_pars.scale_increase_filter = 1;
  353. denoiser->denoise_pars.denoise_mv_bias = 60;
  354. denoiser->denoise_pars.pickmode_mv_bias = 75;
  355. denoiser->denoise_pars.qp_thresh = 80;
  356. denoiser->denoise_pars.consec_zerolast = 15;
  357. denoiser->denoise_pars.spatial_blur = 0;
  358. }
  359. }
  360. int vp8_denoiser_allocate(VP8_DENOISER *denoiser, int width, int height,
  361. int num_mb_rows, int num_mb_cols, int mode) {
  362. int i;
  363. assert(denoiser);
  364. denoiser->num_mb_cols = num_mb_cols;
  365. for (i = 0; i < MAX_REF_FRAMES; ++i) {
  366. denoiser->yv12_running_avg[i].flags = 0;
  367. if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_running_avg[i]), width,
  368. height, VP8BORDERINPIXELS) < 0) {
  369. vp8_denoiser_free(denoiser);
  370. return 1;
  371. }
  372. memset(denoiser->yv12_running_avg[i].buffer_alloc, 0,
  373. denoiser->yv12_running_avg[i].frame_size);
  374. }
  375. denoiser->yv12_mc_running_avg.flags = 0;
  376. if (vp8_yv12_alloc_frame_buffer(&(denoiser->yv12_mc_running_avg), width,
  377. height, VP8BORDERINPIXELS) < 0) {
  378. vp8_denoiser_free(denoiser);
  379. return 1;
  380. }
  381. memset(denoiser->yv12_mc_running_avg.buffer_alloc, 0,
  382. denoiser->yv12_mc_running_avg.frame_size);
  383. if (vp8_yv12_alloc_frame_buffer(&denoiser->yv12_last_source, width, height,
  384. VP8BORDERINPIXELS) < 0) {
  385. vp8_denoiser_free(denoiser);
  386. return 1;
  387. }
  388. memset(denoiser->yv12_last_source.buffer_alloc, 0,
  389. denoiser->yv12_last_source.frame_size);
  390. denoiser->denoise_state = vpx_calloc((num_mb_rows * num_mb_cols), 1);
  391. if (!denoiser->denoise_state) {
  392. vp8_denoiser_free(denoiser);
  393. return 1;
  394. }
  395. memset(denoiser->denoise_state, 0, (num_mb_rows * num_mb_cols));
  396. vp8_denoiser_set_parameters(denoiser, mode);
  397. denoiser->nmse_source_diff = 0;
  398. denoiser->nmse_source_diff_count = 0;
  399. denoiser->qp_avg = 0;
  400. // QP threshold below which we can go up to aggressive mode.
  401. denoiser->qp_threshold_up = 80;
  402. // QP threshold above which we can go back down to normal mode.
  403. // For now keep this second threshold high, so not used currently.
  404. denoiser->qp_threshold_down = 128;
  405. // Bitrate thresholds and noise metric (nmse) thresholds for switching to
  406. // aggressive mode.
  407. // TODO(marpan): Adjust thresholds, including effect on resolution.
  408. denoiser->bitrate_threshold = 400000; // (bits/sec).
  409. denoiser->threshold_aggressive_mode = 80;
  410. if (width * height > 1280 * 720) {
  411. denoiser->bitrate_threshold = 3000000;
  412. denoiser->threshold_aggressive_mode = 200;
  413. } else if (width * height > 960 * 540) {
  414. denoiser->bitrate_threshold = 1200000;
  415. denoiser->threshold_aggressive_mode = 120;
  416. } else if (width * height > 640 * 480) {
  417. denoiser->bitrate_threshold = 600000;
  418. denoiser->threshold_aggressive_mode = 100;
  419. }
  420. return 0;
  421. }
  422. void vp8_denoiser_free(VP8_DENOISER *denoiser) {
  423. int i;
  424. assert(denoiser);
  425. for (i = 0; i < MAX_REF_FRAMES; ++i) {
  426. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_running_avg[i]);
  427. }
  428. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_mc_running_avg);
  429. vp8_yv12_de_alloc_frame_buffer(&denoiser->yv12_last_source);
  430. vpx_free(denoiser->denoise_state);
  431. }
  432. void vp8_denoiser_denoise_mb(VP8_DENOISER *denoiser, MACROBLOCK *x,
  433. unsigned int best_sse, unsigned int zero_mv_sse,
  434. int recon_yoffset, int recon_uvoffset,
  435. loop_filter_info_n *lfi_n, int mb_row, int mb_col,
  436. int block_index, int consec_zero_last)
  437. {
  438. int mv_row;
  439. int mv_col;
  440. unsigned int motion_threshold;
  441. unsigned int motion_magnitude2;
  442. unsigned int sse_thresh;
  443. int sse_diff_thresh = 0;
  444. // Spatial loop filter: only applied selectively based on
  445. // temporal filter state of block relative to top/left neighbors.
  446. int apply_spatial_loop_filter = 1;
  447. MV_REFERENCE_FRAME frame = x->best_reference_frame;
  448. MV_REFERENCE_FRAME zero_frame = x->best_zeromv_reference_frame;
  449. enum vp8_denoiser_decision decision = FILTER_BLOCK;
  450. enum vp8_denoiser_decision decision_u = COPY_BLOCK;
  451. enum vp8_denoiser_decision decision_v = COPY_BLOCK;
  452. if (zero_frame) {
  453. YV12_BUFFER_CONFIG *src = &denoiser->yv12_running_avg[frame];
  454. YV12_BUFFER_CONFIG *dst = &denoiser->yv12_mc_running_avg;
  455. YV12_BUFFER_CONFIG saved_pre, saved_dst;
  456. MB_MODE_INFO saved_mbmi;
  457. MACROBLOCKD *filter_xd = &x->e_mbd;
  458. MB_MODE_INFO *mbmi = &filter_xd->mode_info_context->mbmi;
  459. int sse_diff = 0;
  460. // Bias on zero motion vector sse.
  461. const int zero_bias = denoiser->denoise_pars.denoise_mv_bias;
  462. zero_mv_sse = (unsigned int)((int64_t)zero_mv_sse * zero_bias / 100);
  463. sse_diff = (int)zero_mv_sse - (int)best_sse;
  464. saved_mbmi = *mbmi;
  465. /* Use the best MV for the compensation. */
  466. mbmi->ref_frame = x->best_reference_frame;
  467. mbmi->mode = x->best_sse_inter_mode;
  468. mbmi->mv = x->best_sse_mv;
  469. mbmi->need_to_clamp_mvs = x->need_to_clamp_best_mvs;
  470. mv_col = x->best_sse_mv.as_mv.col;
  471. mv_row = x->best_sse_mv.as_mv.row;
  472. // Bias to zero_mv if small amount of motion.
  473. // Note sse_diff_thresh is intialized to zero, so this ensures
  474. // we will always choose zero_mv for denoising if
  475. // zero_mv_see <= best_sse (i.e., sse_diff <= 0).
  476. if ((unsigned int)(mv_row * mv_row + mv_col * mv_col) <=
  477. NOISE_MOTION_THRESHOLD) {
  478. sse_diff_thresh = (int)SSE_DIFF_THRESHOLD;
  479. }
  480. if (frame == INTRA_FRAME || sse_diff <= sse_diff_thresh) {
  481. /*
  482. * Handle intra blocks as referring to last frame with zero motion
  483. * and let the absolute pixel difference affect the filter factor.
  484. * Also consider small amount of motion as being random walk due
  485. * to noise, if it doesn't mean that we get a much bigger error.
  486. * Note that any changes to the mode info only affects the
  487. * denoising.
  488. */
  489. x->denoise_zeromv = 1;
  490. mbmi->ref_frame = x->best_zeromv_reference_frame;
  491. src = &denoiser->yv12_running_avg[zero_frame];
  492. mbmi->mode = ZEROMV;
  493. mbmi->mv.as_int = 0;
  494. x->best_sse_inter_mode = ZEROMV;
  495. x->best_sse_mv.as_int = 0;
  496. best_sse = zero_mv_sse;
  497. }
  498. mv_row = x->best_sse_mv.as_mv.row;
  499. mv_col = x->best_sse_mv.as_mv.col;
  500. motion_magnitude2 = mv_row * mv_row + mv_col * mv_col;
  501. motion_threshold =
  502. denoiser->denoise_pars.scale_motion_thresh * NOISE_MOTION_THRESHOLD;
  503. if (motion_magnitude2 <
  504. denoiser->denoise_pars.scale_increase_filter * NOISE_MOTION_THRESHOLD) {
  505. x->increase_denoising = 1;
  506. }
  507. sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD;
  508. if (x->increase_denoising) {
  509. sse_thresh = denoiser->denoise_pars.scale_sse_thresh * SSE_THRESHOLD_HIGH;
  510. }
  511. if (best_sse > sse_thresh || motion_magnitude2 > motion_threshold) {
  512. decision = COPY_BLOCK;
  513. }
  514. // If block is considered skin, don't denoise if the block
  515. // (1) is selected as non-zero motion for current frame, or
  516. // (2) has not been selected as ZERO_LAST mode at least x past frames
  517. // in a row.
  518. // TODO(marpan): Parameter "x" should be varied with framerate.
  519. // In particualar, should be reduced for layers (base layer/LAST).
  520. if (x->is_skin && (consec_zero_last < 2 || motion_magnitude2 > 0)) {
  521. decision = COPY_BLOCK;
  522. }
  523. if (decision == FILTER_BLOCK) {
  524. saved_pre = filter_xd->pre;
  525. saved_dst = filter_xd->dst;
  526. /* Compensate the running average. */
  527. filter_xd->pre.y_buffer = src->y_buffer + recon_yoffset;
  528. filter_xd->pre.u_buffer = src->u_buffer + recon_uvoffset;
  529. filter_xd->pre.v_buffer = src->v_buffer + recon_uvoffset;
  530. /* Write the compensated running average to the destination buffer. */
  531. filter_xd->dst.y_buffer = dst->y_buffer + recon_yoffset;
  532. filter_xd->dst.u_buffer = dst->u_buffer + recon_uvoffset;
  533. filter_xd->dst.v_buffer = dst->v_buffer + recon_uvoffset;
  534. if (!x->skip) {
  535. vp8_build_inter_predictors_mb(filter_xd);
  536. } else {
  537. vp8_build_inter16x16_predictors_mb(
  538. filter_xd, filter_xd->dst.y_buffer, filter_xd->dst.u_buffer,
  539. filter_xd->dst.v_buffer, filter_xd->dst.y_stride,
  540. filter_xd->dst.uv_stride);
  541. }
  542. filter_xd->pre = saved_pre;
  543. filter_xd->dst = saved_dst;
  544. *mbmi = saved_mbmi;
  545. }
  546. } else {
  547. // zero_frame should always be 1 for real-time mode, as the
  548. // ZEROMV mode is always checked, so we should never go into this branch.
  549. // If case ZEROMV is not checked, then we will force no denoise (COPY).
  550. decision = COPY_BLOCK;
  551. }
  552. if (decision == FILTER_BLOCK) {
  553. unsigned char *mc_running_avg_y =
  554. denoiser->yv12_mc_running_avg.y_buffer + recon_yoffset;
  555. int mc_avg_y_stride = denoiser->yv12_mc_running_avg.y_stride;
  556. unsigned char *running_avg_y =
  557. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset;
  558. int avg_y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
  559. /* Filter. */
  560. decision = vp8_denoiser_filter(mc_running_avg_y, mc_avg_y_stride,
  561. running_avg_y, avg_y_stride, x->thismb, 16,
  562. motion_magnitude2, x->increase_denoising);
  563. denoiser->denoise_state[block_index] =
  564. motion_magnitude2 > 0 ? kFilterNonZeroMV : kFilterZeroMV;
  565. // Only denoise UV for zero motion, and if y channel was denoised.
  566. if (denoiser->denoiser_mode != kDenoiserOnYOnly && motion_magnitude2 == 0 &&
  567. decision == FILTER_BLOCK) {
  568. unsigned char *mc_running_avg_u =
  569. denoiser->yv12_mc_running_avg.u_buffer + recon_uvoffset;
  570. unsigned char *running_avg_u =
  571. denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset;
  572. unsigned char *mc_running_avg_v =
  573. denoiser->yv12_mc_running_avg.v_buffer + recon_uvoffset;
  574. unsigned char *running_avg_v =
  575. denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset;
  576. int mc_avg_uv_stride = denoiser->yv12_mc_running_avg.uv_stride;
  577. int avg_uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
  578. int signal_stride = x->block[16].src_stride;
  579. decision_u = vp8_denoiser_filter_uv(
  580. mc_running_avg_u, mc_avg_uv_stride, running_avg_u, avg_uv_stride,
  581. x->block[16].src + *x->block[16].base_src, signal_stride,
  582. motion_magnitude2, 0);
  583. decision_v = vp8_denoiser_filter_uv(
  584. mc_running_avg_v, mc_avg_uv_stride, running_avg_v, avg_uv_stride,
  585. x->block[20].src + *x->block[20].base_src, signal_stride,
  586. motion_magnitude2, 0);
  587. }
  588. }
  589. if (decision == COPY_BLOCK) {
  590. /* No filtering of this block; it differs too much from the predictor,
  591. * or the motion vector magnitude is considered too big.
  592. */
  593. x->denoise_zeromv = 0;
  594. vp8_copy_mem16x16(
  595. x->thismb, 16,
  596. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  597. denoiser->yv12_running_avg[INTRA_FRAME].y_stride);
  598. denoiser->denoise_state[block_index] = kNoFilter;
  599. }
  600. if (denoiser->denoiser_mode != kDenoiserOnYOnly) {
  601. if (decision_u == COPY_BLOCK) {
  602. vp8_copy_mem8x8(
  603. x->block[16].src + *x->block[16].base_src, x->block[16].src_stride,
  604. denoiser->yv12_running_avg[INTRA_FRAME].u_buffer + recon_uvoffset,
  605. denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
  606. }
  607. if (decision_v == COPY_BLOCK) {
  608. vp8_copy_mem8x8(
  609. x->block[20].src + *x->block[20].base_src, x->block[16].src_stride,
  610. denoiser->yv12_running_avg[INTRA_FRAME].v_buffer + recon_uvoffset,
  611. denoiser->yv12_running_avg[INTRA_FRAME].uv_stride);
  612. }
  613. }
  614. // Option to selectively deblock the denoised signal, for y channel only.
  615. if (apply_spatial_loop_filter) {
  616. loop_filter_info lfi;
  617. int apply_filter_col = 0;
  618. int apply_filter_row = 0;
  619. int apply_filter = 0;
  620. int y_stride = denoiser->yv12_running_avg[INTRA_FRAME].y_stride;
  621. int uv_stride = denoiser->yv12_running_avg[INTRA_FRAME].uv_stride;
  622. // Fix filter level to some nominal value for now.
  623. int filter_level = 48;
  624. int hev_index = lfi_n->hev_thr_lut[INTER_FRAME][filter_level];
  625. lfi.mblim = lfi_n->mblim[filter_level];
  626. lfi.blim = lfi_n->blim[filter_level];
  627. lfi.lim = lfi_n->lim[filter_level];
  628. lfi.hev_thr = lfi_n->hev_thr[hev_index];
  629. // Apply filter if there is a difference in the denoiser filter state
  630. // between the current and left/top block, or if non-zero motion vector
  631. // is used for the motion-compensated filtering.
  632. if (mb_col > 0) {
  633. apply_filter_col =
  634. !((denoiser->denoise_state[block_index] ==
  635. denoiser->denoise_state[block_index - 1]) &&
  636. denoiser->denoise_state[block_index] != kFilterNonZeroMV);
  637. if (apply_filter_col) {
  638. // Filter left vertical edge.
  639. apply_filter = 1;
  640. vp8_loop_filter_mbv(
  641. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  642. NULL, NULL, y_stride, uv_stride, &lfi);
  643. }
  644. }
  645. if (mb_row > 0) {
  646. apply_filter_row =
  647. !((denoiser->denoise_state[block_index] ==
  648. denoiser->denoise_state[block_index - denoiser->num_mb_cols]) &&
  649. denoiser->denoise_state[block_index] != kFilterNonZeroMV);
  650. if (apply_filter_row) {
  651. // Filter top horizontal edge.
  652. apply_filter = 1;
  653. vp8_loop_filter_mbh(
  654. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  655. NULL, NULL, y_stride, uv_stride, &lfi);
  656. }
  657. }
  658. if (apply_filter) {
  659. // Update the signal block |x|. Pixel changes are only to top and/or
  660. // left boundary pixels: can we avoid full block copy here.
  661. vp8_copy_mem16x16(
  662. denoiser->yv12_running_avg[INTRA_FRAME].y_buffer + recon_yoffset,
  663. y_stride, x->thismb, 16);
  664. }
  665. }
  666. }