2
0

picklpf.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /*
  2. * Copyright (c) 2010 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 "./vpx_dsp_rtcd.h"
  11. #include "./vpx_scale_rtcd.h"
  12. #include "vp8/common/onyxc_int.h"
  13. #include "onyx_int.h"
  14. #include "vp8/encoder/picklpf.h"
  15. #include "vp8/encoder/quantize.h"
  16. #include "vpx_mem/vpx_mem.h"
  17. #include "vpx_scale/vpx_scale.h"
  18. #include "vp8/common/alloccommon.h"
  19. #include "vp8/common/loopfilter.h"
  20. #if ARCH_ARM
  21. #include "vpx_ports/arm.h"
  22. #endif
  23. extern int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source,
  24. YV12_BUFFER_CONFIG *dest);
  25. static void yv12_copy_partial_frame(YV12_BUFFER_CONFIG *src_ybc,
  26. YV12_BUFFER_CONFIG *dst_ybc) {
  27. unsigned char *src_y, *dst_y;
  28. int yheight;
  29. int ystride;
  30. int yoffset;
  31. int linestocopy;
  32. yheight = src_ybc->y_height;
  33. ystride = src_ybc->y_stride;
  34. /* number of MB rows to use in partial filtering */
  35. linestocopy = (yheight >> 4) / PARTIAL_FRAME_FRACTION;
  36. linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
  37. /* Copy extra 4 so that full filter context is available if filtering done
  38. * on the copied partial frame and not original. Partial filter does mb
  39. * filtering for top row also, which can modify3 pixels above.
  40. */
  41. linestocopy += 4;
  42. /* partial image starts at ~middle of frame (macroblock border)*/
  43. yoffset = ystride * (((yheight >> 5) * 16) - 4);
  44. src_y = src_ybc->y_buffer + yoffset;
  45. dst_y = dst_ybc->y_buffer + yoffset;
  46. memcpy(dst_y, src_y, ystride * linestocopy);
  47. }
  48. static int calc_partial_ssl_err(YV12_BUFFER_CONFIG *source,
  49. YV12_BUFFER_CONFIG *dest) {
  50. int i, j;
  51. int Total = 0;
  52. int srcoffset, dstoffset;
  53. unsigned char *src = source->y_buffer;
  54. unsigned char *dst = dest->y_buffer;
  55. int linestocopy;
  56. /* number of MB rows to use in partial filtering */
  57. linestocopy = (source->y_height >> 4) / PARTIAL_FRAME_FRACTION;
  58. linestocopy = linestocopy ? linestocopy << 4 : 16; /* 16 lines per MB */
  59. /* partial image starts at ~middle of frame (macroblock border)*/
  60. srcoffset = source->y_stride * ((dest->y_height >> 5) * 16);
  61. dstoffset = dest->y_stride * ((dest->y_height >> 5) * 16);
  62. src += srcoffset;
  63. dst += dstoffset;
  64. /* Loop through the Y plane raw and reconstruction data summing
  65. * (square differences)
  66. */
  67. for (i = 0; i < linestocopy; i += 16) {
  68. for (j = 0; j < source->y_width; j += 16) {
  69. unsigned int sse;
  70. Total += vpx_mse16x16(src + j, source->y_stride, dst + j, dest->y_stride,
  71. &sse);
  72. }
  73. src += 16 * source->y_stride;
  74. dst += 16 * dest->y_stride;
  75. }
  76. return Total;
  77. }
  78. /* Enforce a minimum filter level based upon baseline Q */
  79. static int get_min_filter_level(VP8_COMP *cpi, int base_qindex) {
  80. int min_filter_level;
  81. if (cpi->source_alt_ref_active && cpi->common.refresh_golden_frame &&
  82. !cpi->common.refresh_alt_ref_frame) {
  83. min_filter_level = 0;
  84. } else {
  85. if (base_qindex <= 6) {
  86. min_filter_level = 0;
  87. } else if (base_qindex <= 16) {
  88. min_filter_level = 1;
  89. } else {
  90. min_filter_level = (base_qindex / 8);
  91. }
  92. }
  93. return min_filter_level;
  94. }
  95. /* Enforce a maximum filter level based upon baseline Q */
  96. static int get_max_filter_level(VP8_COMP *cpi, int base_qindex) {
  97. /* PGW August 2006: Highest filter values almost always a bad idea */
  98. /* jbb chg: 20100118 - not so any more with this overquant stuff allow
  99. * high values with lots of intra coming in.
  100. */
  101. int max_filter_level = MAX_LOOP_FILTER;
  102. (void)base_qindex;
  103. if (cpi->twopass.section_intra_rating > 8) {
  104. max_filter_level = MAX_LOOP_FILTER * 3 / 4;
  105. }
  106. return max_filter_level;
  107. }
  108. void vp8cx_pick_filter_level_fast(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
  109. VP8_COMMON *cm = &cpi->common;
  110. int best_err = 0;
  111. int filt_err = 0;
  112. int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
  113. int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
  114. int filt_val;
  115. int best_filt_val;
  116. YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
  117. /* Replace unfiltered frame buffer with a new one */
  118. cm->frame_to_show = &cpi->pick_lf_lvl_frame;
  119. if (cm->frame_type == KEY_FRAME) {
  120. cm->sharpness_level = 0;
  121. } else {
  122. cm->sharpness_level = cpi->oxcf.Sharpness;
  123. }
  124. if (cm->sharpness_level != cm->last_sharpness_level) {
  125. vp8_loop_filter_update_sharpness(&cm->lf_info, cm->sharpness_level);
  126. cm->last_sharpness_level = cm->sharpness_level;
  127. }
  128. /* Start the search at the previous frame filter level unless it is
  129. * now out of range.
  130. */
  131. if (cm->filter_level < min_filter_level) {
  132. cm->filter_level = min_filter_level;
  133. } else if (cm->filter_level > max_filter_level) {
  134. cm->filter_level = max_filter_level;
  135. }
  136. filt_val = cm->filter_level;
  137. best_filt_val = filt_val;
  138. /* Get the err using the previous frame's filter value. */
  139. /* Copy the unfiltered / processed recon buffer to the new buffer */
  140. yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
  141. vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
  142. best_err = calc_partial_ssl_err(sd, cm->frame_to_show);
  143. filt_val -= 1 + (filt_val > 10);
  144. /* Search lower filter levels */
  145. while (filt_val >= min_filter_level) {
  146. /* Apply the loop filter */
  147. yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
  148. vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
  149. /* Get the err for filtered frame */
  150. filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
  151. /* Update the best case record or exit loop. */
  152. if (filt_err < best_err) {
  153. best_err = filt_err;
  154. best_filt_val = filt_val;
  155. } else {
  156. break;
  157. }
  158. /* Adjust filter level */
  159. filt_val -= 1 + (filt_val > 10);
  160. }
  161. /* Search up (note that we have already done filt_val = cm->filter_level) */
  162. filt_val = cm->filter_level + 1 + (filt_val > 10);
  163. if (best_filt_val == cm->filter_level) {
  164. /* Resist raising filter level for very small gains */
  165. best_err -= (best_err >> 10);
  166. while (filt_val < max_filter_level) {
  167. /* Apply the loop filter */
  168. yv12_copy_partial_frame(saved_frame, cm->frame_to_show);
  169. vp8_loop_filter_partial_frame(cm, &cpi->mb.e_mbd, filt_val);
  170. /* Get the err for filtered frame */
  171. filt_err = calc_partial_ssl_err(sd, cm->frame_to_show);
  172. /* Update the best case record or exit loop. */
  173. if (filt_err < best_err) {
  174. /* Do not raise filter level if improvement is < 1 part
  175. * in 4096
  176. */
  177. best_err = filt_err - (filt_err >> 10);
  178. best_filt_val = filt_val;
  179. } else {
  180. break;
  181. }
  182. /* Adjust filter level */
  183. filt_val += 1 + (filt_val > 10);
  184. }
  185. }
  186. cm->filter_level = best_filt_val;
  187. if (cm->filter_level < min_filter_level) cm->filter_level = min_filter_level;
  188. if (cm->filter_level > max_filter_level) cm->filter_level = max_filter_level;
  189. /* restore unfiltered frame pointer */
  190. cm->frame_to_show = saved_frame;
  191. }
  192. /* Stub function for now Alt LF not used */
  193. void vp8cx_set_alt_lf_level(VP8_COMP *cpi, int filt_val) {
  194. MACROBLOCKD *mbd = &cpi->mb.e_mbd;
  195. (void)filt_val;
  196. mbd->segment_feature_data[MB_LVL_ALT_LF][0] =
  197. cpi->segment_feature_data[MB_LVL_ALT_LF][0];
  198. mbd->segment_feature_data[MB_LVL_ALT_LF][1] =
  199. cpi->segment_feature_data[MB_LVL_ALT_LF][1];
  200. mbd->segment_feature_data[MB_LVL_ALT_LF][2] =
  201. cpi->segment_feature_data[MB_LVL_ALT_LF][2];
  202. mbd->segment_feature_data[MB_LVL_ALT_LF][3] =
  203. cpi->segment_feature_data[MB_LVL_ALT_LF][3];
  204. }
  205. void vp8cx_pick_filter_level(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) {
  206. VP8_COMMON *cm = &cpi->common;
  207. int best_err = 0;
  208. int filt_err = 0;
  209. int min_filter_level = get_min_filter_level(cpi, cm->base_qindex);
  210. int max_filter_level = get_max_filter_level(cpi, cm->base_qindex);
  211. int filter_step;
  212. int filt_high = 0;
  213. int filt_mid;
  214. int filt_low = 0;
  215. int filt_best;
  216. int filt_direction = 0;
  217. /* Bias against raising loop filter and in favor of lowering it */
  218. int Bias = 0;
  219. int ss_err[MAX_LOOP_FILTER + 1];
  220. YV12_BUFFER_CONFIG *saved_frame = cm->frame_to_show;
  221. memset(ss_err, 0, sizeof(ss_err));
  222. /* Replace unfiltered frame buffer with a new one */
  223. cm->frame_to_show = &cpi->pick_lf_lvl_frame;
  224. if (cm->frame_type == KEY_FRAME) {
  225. cm->sharpness_level = 0;
  226. } else {
  227. cm->sharpness_level = cpi->oxcf.Sharpness;
  228. }
  229. /* Start the search at the previous frame filter level unless it is
  230. * now out of range.
  231. */
  232. filt_mid = cm->filter_level;
  233. if (filt_mid < min_filter_level) {
  234. filt_mid = min_filter_level;
  235. } else if (filt_mid > max_filter_level) {
  236. filt_mid = max_filter_level;
  237. }
  238. /* Define the initial step size */
  239. filter_step = (filt_mid < 16) ? 4 : filt_mid / 4;
  240. /* Get baseline error score */
  241. /* Copy the unfiltered / processed recon buffer to the new buffer */
  242. vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
  243. vp8cx_set_alt_lf_level(cpi, filt_mid);
  244. vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_mid);
  245. best_err = vp8_calc_ss_err(sd, cm->frame_to_show);
  246. ss_err[filt_mid] = best_err;
  247. filt_best = filt_mid;
  248. while (filter_step > 0) {
  249. Bias = (best_err >> (15 - (filt_mid / 8))) * filter_step;
  250. if (cpi->twopass.section_intra_rating < 20) {
  251. Bias = Bias * cpi->twopass.section_intra_rating / 20;
  252. }
  253. filt_high = ((filt_mid + filter_step) > max_filter_level)
  254. ? max_filter_level
  255. : (filt_mid + filter_step);
  256. filt_low = ((filt_mid - filter_step) < min_filter_level)
  257. ? min_filter_level
  258. : (filt_mid - filter_step);
  259. if ((filt_direction <= 0) && (filt_low != filt_mid)) {
  260. if (ss_err[filt_low] == 0) {
  261. /* Get Low filter error score */
  262. vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
  263. vp8cx_set_alt_lf_level(cpi, filt_low);
  264. vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_low);
  265. filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
  266. ss_err[filt_low] = filt_err;
  267. } else {
  268. filt_err = ss_err[filt_low];
  269. }
  270. /* If value is close to the best so far then bias towards a
  271. * lower loop filter value.
  272. */
  273. if ((filt_err - Bias) < best_err) {
  274. /* Was it actually better than the previous best? */
  275. if (filt_err < best_err) best_err = filt_err;
  276. filt_best = filt_low;
  277. }
  278. }
  279. /* Now look at filt_high */
  280. if ((filt_direction >= 0) && (filt_high != filt_mid)) {
  281. if (ss_err[filt_high] == 0) {
  282. vpx_yv12_copy_y(saved_frame, cm->frame_to_show);
  283. vp8cx_set_alt_lf_level(cpi, filt_high);
  284. vp8_loop_filter_frame_yonly(cm, &cpi->mb.e_mbd, filt_high);
  285. filt_err = vp8_calc_ss_err(sd, cm->frame_to_show);
  286. ss_err[filt_high] = filt_err;
  287. } else {
  288. filt_err = ss_err[filt_high];
  289. }
  290. /* Was it better than the previous best? */
  291. if (filt_err < (best_err - Bias)) {
  292. best_err = filt_err;
  293. filt_best = filt_high;
  294. }
  295. }
  296. /* Half the step distance if the best filter value was the same
  297. * as last time
  298. */
  299. if (filt_best == filt_mid) {
  300. filter_step = filter_step / 2;
  301. filt_direction = 0;
  302. } else {
  303. filt_direction = (filt_best < filt_mid) ? -1 : 1;
  304. filt_mid = filt_best;
  305. }
  306. }
  307. cm->filter_level = filt_best;
  308. /* restore unfiltered frame pointer */
  309. cm->frame_to_show = saved_frame;
  310. }