vp9_noise_estimate.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * Copyright (c) 2015 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 <assert.h>
  11. #include <limits.h>
  12. #include <math.h>
  13. #include "./vpx_dsp_rtcd.h"
  14. #include "vpx_dsp/vpx_dsp_common.h"
  15. #include "vpx_scale/yv12config.h"
  16. #include "vpx/vpx_integer.h"
  17. #include "vp9/common/vp9_reconinter.h"
  18. #include "vp9/encoder/vp9_context_tree.h"
  19. #include "vp9/encoder/vp9_noise_estimate.h"
  20. #include "vp9/encoder/vp9_encoder.h"
  21. void vp9_noise_estimate_init(NOISE_ESTIMATE *const ne, int width, int height) {
  22. ne->enabled = 0;
  23. ne->level = kLowLow;
  24. ne->value = 0;
  25. ne->count = 0;
  26. ne->thresh = 90;
  27. ne->last_w = 0;
  28. ne->last_h = 0;
  29. if (width * height >= 1920 * 1080) {
  30. ne->thresh = 200;
  31. } else if (width * height >= 1280 * 720) {
  32. ne->thresh = 140;
  33. } else if (width * height >= 640 * 360) {
  34. ne->thresh = 115;
  35. }
  36. ne->num_frames_estimate = 15;
  37. }
  38. static int enable_noise_estimation(VP9_COMP *const cpi) {
  39. #if CONFIG_VP9_HIGHBITDEPTH
  40. if (cpi->common.use_highbitdepth) return 0;
  41. #endif
  42. // Enable noise estimation if denoising is on.
  43. #if CONFIG_VP9_TEMPORAL_DENOISING
  44. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
  45. cpi->common.width >= 320 && cpi->common.height >= 180)
  46. return 1;
  47. #endif
  48. // Only allow noise estimate under certain encoding mode.
  49. // Enabled for 1 pass CBR, speed >=5, and if resolution is same as original.
  50. // Not enabled for SVC mode and screen_content_mode.
  51. // Not enabled for low resolutions.
  52. if (cpi->oxcf.pass == 0 && cpi->oxcf.rc_mode == VPX_CBR &&
  53. cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && cpi->oxcf.speed >= 5 &&
  54. cpi->resize_state == ORIG && cpi->resize_pending == 0 && !cpi->use_svc &&
  55. cpi->oxcf.content != VP9E_CONTENT_SCREEN &&
  56. cpi->common.width * cpi->common.height >= 640 * 360)
  57. return 1;
  58. else
  59. return 0;
  60. }
  61. #if CONFIG_VP9_TEMPORAL_DENOISING
  62. static void copy_frame(YV12_BUFFER_CONFIG *const dest,
  63. const YV12_BUFFER_CONFIG *const src) {
  64. int r;
  65. const uint8_t *srcbuf = src->y_buffer;
  66. uint8_t *destbuf = dest->y_buffer;
  67. assert(dest->y_width == src->y_width);
  68. assert(dest->y_height == src->y_height);
  69. for (r = 0; r < dest->y_height; ++r) {
  70. memcpy(destbuf, srcbuf, dest->y_width);
  71. destbuf += dest->y_stride;
  72. srcbuf += src->y_stride;
  73. }
  74. }
  75. #endif // CONFIG_VP9_TEMPORAL_DENOISING
  76. NOISE_LEVEL vp9_noise_estimate_extract_level(NOISE_ESTIMATE *const ne) {
  77. int noise_level = kLowLow;
  78. if (ne->value > (ne->thresh << 1)) {
  79. noise_level = kHigh;
  80. } else {
  81. if (ne->value > ne->thresh)
  82. noise_level = kMedium;
  83. else if (ne->value > ((9 * ne->thresh) >> 4))
  84. noise_level = kLow;
  85. else
  86. noise_level = kLowLow;
  87. }
  88. return noise_level;
  89. }
  90. void vp9_update_noise_estimate(VP9_COMP *const cpi) {
  91. const VP9_COMMON *const cm = &cpi->common;
  92. NOISE_ESTIMATE *const ne = &cpi->noise_estimate;
  93. const int low_res = (cm->width <= 352 && cm->height <= 288);
  94. // Estimate of noise level every frame_period frames.
  95. int frame_period = 8;
  96. int thresh_consec_zeromv = 6;
  97. unsigned int thresh_sum_diff = 100;
  98. unsigned int thresh_sum_spatial = (200 * 200) << 8;
  99. unsigned int thresh_spatial_var = (32 * 32) << 8;
  100. int min_blocks_estimate = cm->mi_rows * cm->mi_cols >> 7;
  101. int frame_counter = cm->current_video_frame;
  102. // Estimate is between current source and last source.
  103. YV12_BUFFER_CONFIG *last_source = cpi->Last_Source;
  104. #if CONFIG_VP9_TEMPORAL_DENOISING
  105. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi)) {
  106. last_source = &cpi->denoiser.last_source;
  107. // Tune these thresholds for different resolutions when denoising is
  108. // enabled.
  109. if (cm->width > 640 && cm->width < 1920) {
  110. thresh_consec_zeromv = 4;
  111. thresh_sum_diff = 200;
  112. thresh_sum_spatial = (120 * 120) << 8;
  113. thresh_spatial_var = (48 * 48) << 8;
  114. }
  115. }
  116. #endif
  117. ne->enabled = enable_noise_estimation(cpi);
  118. if (cpi->svc.number_spatial_layers > 1)
  119. frame_counter = cpi->svc.current_superframe;
  120. if (!ne->enabled || frame_counter % frame_period != 0 ||
  121. last_source == NULL ||
  122. (cpi->svc.number_spatial_layers == 1 &&
  123. (ne->last_w != cm->width || ne->last_h != cm->height))) {
  124. #if CONFIG_VP9_TEMPORAL_DENOISING
  125. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi))
  126. copy_frame(&cpi->denoiser.last_source, cpi->Source);
  127. #endif
  128. if (last_source != NULL) {
  129. ne->last_w = cm->width;
  130. ne->last_h = cm->height;
  131. }
  132. return;
  133. } else if (cm->current_video_frame > 60 &&
  134. cpi->rc.avg_frame_low_motion < (low_res ? 70 : 50)) {
  135. // Force noise estimation to 0 and denoiser off if content has high motion.
  136. ne->level = kLowLow;
  137. ne->count = 0;
  138. ne->num_frames_estimate = 10;
  139. #if CONFIG_VP9_TEMPORAL_DENOISING
  140. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi) &&
  141. cpi->svc.current_superframe > 1) {
  142. vp9_denoiser_set_noise_level(&cpi->denoiser, ne->level);
  143. copy_frame(&cpi->denoiser.last_source, cpi->Source);
  144. }
  145. #endif
  146. return;
  147. } else {
  148. int num_samples = 0;
  149. uint64_t avg_est = 0;
  150. int bsize = BLOCK_16X16;
  151. static const unsigned char const_source[16] = { 0, 0, 0, 0, 0, 0, 0, 0,
  152. 0, 0, 0, 0, 0, 0, 0, 0 };
  153. // Loop over sub-sample of 16x16 blocks of frame, and for blocks that have
  154. // been encoded as zero/small mv at least x consecutive frames, compute
  155. // the variance to update estimate of noise in the source.
  156. const uint8_t *src_y = cpi->Source->y_buffer;
  157. const int src_ystride = cpi->Source->y_stride;
  158. const uint8_t *last_src_y = last_source->y_buffer;
  159. const int last_src_ystride = last_source->y_stride;
  160. const uint8_t *src_u = cpi->Source->u_buffer;
  161. const uint8_t *src_v = cpi->Source->v_buffer;
  162. const int src_uvstride = cpi->Source->uv_stride;
  163. int mi_row, mi_col;
  164. int num_low_motion = 0;
  165. int frame_low_motion = 1;
  166. for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
  167. for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
  168. int bl_index = mi_row * cm->mi_cols + mi_col;
  169. if (cpi->consec_zero_mv[bl_index] > thresh_consec_zeromv)
  170. num_low_motion++;
  171. }
  172. }
  173. if (num_low_motion < ((3 * cm->mi_rows * cm->mi_cols) >> 3))
  174. frame_low_motion = 0;
  175. for (mi_row = 0; mi_row < cm->mi_rows; mi_row++) {
  176. for (mi_col = 0; mi_col < cm->mi_cols; mi_col++) {
  177. // 16x16 blocks, 1/4 sample of frame.
  178. if (mi_row % 4 == 0 && mi_col % 4 == 0 && mi_row < cm->mi_rows - 1 &&
  179. mi_col < cm->mi_cols - 1) {
  180. int bl_index = mi_row * cm->mi_cols + mi_col;
  181. int bl_index1 = bl_index + 1;
  182. int bl_index2 = bl_index + cm->mi_cols;
  183. int bl_index3 = bl_index2 + 1;
  184. int consec_zeromv =
  185. VPXMIN(cpi->consec_zero_mv[bl_index],
  186. VPXMIN(cpi->consec_zero_mv[bl_index1],
  187. VPXMIN(cpi->consec_zero_mv[bl_index2],
  188. cpi->consec_zero_mv[bl_index3])));
  189. // Only consider blocks that are likely steady background. i.e, have
  190. // been encoded as zero/low motion x (= thresh_consec_zeromv) frames
  191. // in a row. consec_zero_mv[] defined for 8x8 blocks, so consider all
  192. // 4 sub-blocks for 16x16 block. Also, avoid skin blocks.
  193. if (frame_low_motion && consec_zeromv > thresh_consec_zeromv) {
  194. int is_skin = 0;
  195. if (cpi->use_skin_detection) {
  196. is_skin =
  197. vp9_compute_skin_block(src_y, src_u, src_v, src_ystride,
  198. src_uvstride, bsize, consec_zeromv, 0);
  199. }
  200. if (!is_skin) {
  201. unsigned int sse;
  202. // Compute variance.
  203. unsigned int variance = cpi->fn_ptr[bsize].vf(
  204. src_y, src_ystride, last_src_y, last_src_ystride, &sse);
  205. // Only consider this block as valid for noise measurement if the
  206. // average term (sse - variance = N * avg^{2}, N = 16X16) of the
  207. // temporal residual is small (avoid effects from lighting
  208. // change).
  209. if ((sse - variance) < thresh_sum_diff) {
  210. unsigned int sse2;
  211. const unsigned int spatial_variance = cpi->fn_ptr[bsize].vf(
  212. src_y, src_ystride, const_source, 0, &sse2);
  213. // Avoid blocks with high brightness and high spatial variance.
  214. if ((sse2 - spatial_variance) < thresh_sum_spatial &&
  215. spatial_variance < thresh_spatial_var) {
  216. avg_est += low_res ? variance >> 4
  217. : variance / ((spatial_variance >> 9) + 1);
  218. num_samples++;
  219. }
  220. }
  221. }
  222. }
  223. }
  224. src_y += 8;
  225. last_src_y += 8;
  226. src_u += 4;
  227. src_v += 4;
  228. }
  229. src_y += (src_ystride << 3) - (cm->mi_cols << 3);
  230. last_src_y += (last_src_ystride << 3) - (cm->mi_cols << 3);
  231. src_u += (src_uvstride << 2) - (cm->mi_cols << 2);
  232. src_v += (src_uvstride << 2) - (cm->mi_cols << 2);
  233. }
  234. ne->last_w = cm->width;
  235. ne->last_h = cm->height;
  236. // Update noise estimate if we have at a minimum number of block samples,
  237. // and avg_est > 0 (avg_est == 0 can happen if the application inputs
  238. // duplicate frames).
  239. if (num_samples > min_blocks_estimate && avg_est > 0) {
  240. // Normalize.
  241. avg_est = avg_est / num_samples;
  242. // Update noise estimate.
  243. ne->value = (int)((15 * ne->value + avg_est) >> 4);
  244. ne->count++;
  245. if (ne->count == ne->num_frames_estimate) {
  246. // Reset counter and check noise level condition.
  247. ne->num_frames_estimate = 30;
  248. ne->count = 0;
  249. ne->level = vp9_noise_estimate_extract_level(ne);
  250. #if CONFIG_VP9_TEMPORAL_DENOISING
  251. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi))
  252. vp9_denoiser_set_noise_level(&cpi->denoiser, ne->level);
  253. #endif
  254. }
  255. }
  256. }
  257. #if CONFIG_VP9_TEMPORAL_DENOISING
  258. if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc(cpi))
  259. copy_frame(&cpi->denoiser.last_source, cpi->Source);
  260. #endif
  261. }