LCOV - code coverage report
Current view: top level - media/libvpx/libvpx/vp9/common - vp9_postproc.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 111 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 6 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      11             : #include <math.h>
      12             : #include <stdlib.h>
      13             : #include <stdio.h>
      14             : 
      15             : #include "./vpx_dsp_rtcd.h"
      16             : #include "./vpx_config.h"
      17             : #include "./vpx_scale_rtcd.h"
      18             : #include "./vp9_rtcd.h"
      19             : 
      20             : #include "vpx_dsp/vpx_dsp_common.h"
      21             : #include "vpx_dsp/postproc.h"
      22             : #include "vpx_ports/mem.h"
      23             : #include "vpx_ports/system_state.h"
      24             : #include "vpx_scale/vpx_scale.h"
      25             : #include "vpx_scale/yv12config.h"
      26             : 
      27             : #include "vp9/common/vp9_onyxc_int.h"
      28             : #include "vp9/common/vp9_postproc.h"
      29             : 
      30             : #if CONFIG_VP9_POSTPROC
      31             : 
      32             : static const uint8_t q_diff_thresh = 20;
      33             : static const uint8_t last_q_thresh = 170;
      34             : extern const int16_t vpx_rv[];
      35             : 
      36             : #if CONFIG_VP9_HIGHBITDEPTH
      37             : static const int16_t kernel5[] = { 1, 1, 4, 1, 1 };
      38             : 
      39             : void vp9_highbd_post_proc_down_and_across_c(const uint16_t *src_ptr,
      40             :                                             uint16_t *dst_ptr,
      41             :                                             int src_pixels_per_line,
      42             :                                             int dst_pixels_per_line, int rows,
      43             :                                             int cols, int flimit) {
      44             :   uint16_t const *p_src;
      45             :   uint16_t *p_dst;
      46             :   int row, col, i, v, kernel;
      47             :   int pitch = src_pixels_per_line;
      48             :   uint16_t d[8];
      49             : 
      50             :   for (row = 0; row < rows; row++) {
      51             :     // post_proc_down for one row.
      52             :     p_src = src_ptr;
      53             :     p_dst = dst_ptr;
      54             : 
      55             :     for (col = 0; col < cols; col++) {
      56             :       kernel = 4;
      57             :       v = p_src[col];
      58             : 
      59             :       for (i = -2; i <= 2; i++) {
      60             :         if (abs(v - p_src[col + i * pitch]) > flimit) goto down_skip_convolve;
      61             : 
      62             :         kernel += kernel5[2 + i] * p_src[col + i * pitch];
      63             :       }
      64             : 
      65             :       v = (kernel >> 3);
      66             : 
      67             :     down_skip_convolve:
      68             :       p_dst[col] = v;
      69             :     }
      70             : 
      71             :     /* now post_proc_across */
      72             :     p_src = dst_ptr;
      73             :     p_dst = dst_ptr;
      74             : 
      75             :     for (i = 0; i < 8; i++) d[i] = p_src[i];
      76             : 
      77             :     for (col = 0; col < cols; col++) {
      78             :       kernel = 4;
      79             :       v = p_src[col];
      80             : 
      81             :       d[col & 7] = v;
      82             : 
      83             :       for (i = -2; i <= 2; i++) {
      84             :         if (abs(v - p_src[col + i]) > flimit) goto across_skip_convolve;
      85             : 
      86             :         kernel += kernel5[2 + i] * p_src[col + i];
      87             :       }
      88             : 
      89             :       d[col & 7] = (kernel >> 3);
      90             : 
      91             :     across_skip_convolve:
      92             :       if (col >= 2) p_dst[col - 2] = d[(col - 2) & 7];
      93             :     }
      94             : 
      95             :     /* handle the last two pixels */
      96             :     p_dst[col - 2] = d[(col - 2) & 7];
      97             :     p_dst[col - 1] = d[(col - 1) & 7];
      98             : 
      99             :     /* next row */
     100             :     src_ptr += pitch;
     101             :     dst_ptr += dst_pixels_per_line;
     102             :   }
     103             : }
     104             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     105             : 
     106           0 : static int q2mbl(int x) {
     107           0 :   if (x < 20) x = 20;
     108             : 
     109           0 :   x = 50 + (x - 50) * 10 / 8;
     110           0 :   return x * x / 3;
     111             : }
     112             : 
     113             : #if CONFIG_VP9_HIGHBITDEPTH
     114             : void vp9_highbd_mbpost_proc_across_ip_c(uint16_t *src, int pitch, int rows,
     115             :                                         int cols, int flimit) {
     116             :   int r, c, i;
     117             : 
     118             :   uint16_t *s = src;
     119             :   uint16_t d[16];
     120             : 
     121             :   for (r = 0; r < rows; r++) {
     122             :     int sumsq = 0;
     123             :     int sum = 0;
     124             : 
     125             :     for (i = -8; i <= 6; i++) {
     126             :       sumsq += s[i] * s[i];
     127             :       sum += s[i];
     128             :       d[i + 8] = 0;
     129             :     }
     130             : 
     131             :     for (c = 0; c < cols + 8; c++) {
     132             :       int x = s[c + 7] - s[c - 8];
     133             :       int y = s[c + 7] + s[c - 8];
     134             : 
     135             :       sum += x;
     136             :       sumsq += x * y;
     137             : 
     138             :       d[c & 15] = s[c];
     139             : 
     140             :       if (sumsq * 15 - sum * sum < flimit) {
     141             :         d[c & 15] = (8 + sum + s[c]) >> 4;
     142             :       }
     143             : 
     144             :       s[c - 8] = d[(c - 8) & 15];
     145             :     }
     146             : 
     147             :     s += pitch;
     148             :   }
     149             : }
     150             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     151             : 
     152             : #if CONFIG_VP9_HIGHBITDEPTH
     153             : void vp9_highbd_mbpost_proc_down_c(uint16_t *dst, int pitch, int rows, int cols,
     154             :                                    int flimit) {
     155             :   int r, c, i;
     156             :   const int16_t *rv3 = &vpx_rv[63 & rand()];  // NOLINT
     157             : 
     158             :   for (c = 0; c < cols; c++) {
     159             :     uint16_t *s = &dst[c];
     160             :     int sumsq = 0;
     161             :     int sum = 0;
     162             :     uint16_t d[16];
     163             :     const int16_t *rv2 = rv3 + ((c * 17) & 127);
     164             : 
     165             :     for (i = -8; i <= 6; i++) {
     166             :       sumsq += s[i * pitch] * s[i * pitch];
     167             :       sum += s[i * pitch];
     168             :     }
     169             : 
     170             :     for (r = 0; r < rows + 8; r++) {
     171             :       sumsq += s[7 * pitch] * s[7 * pitch] - s[-8 * pitch] * s[-8 * pitch];
     172             :       sum += s[7 * pitch] - s[-8 * pitch];
     173             :       d[r & 15] = s[0];
     174             : 
     175             :       if (sumsq * 15 - sum * sum < flimit) {
     176             :         d[r & 15] = (rv2[r & 127] + sum + s[0]) >> 4;
     177             :       }
     178             : 
     179             :       s[-8 * pitch] = d[(r - 8) & 15];
     180             :       s += pitch;
     181             :     }
     182             :   }
     183             : }
     184             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     185             : 
     186           0 : static void deblock_and_de_macro_block(YV12_BUFFER_CONFIG *source,
     187             :                                        YV12_BUFFER_CONFIG *post, int q,
     188             :                                        int low_var_thresh, int flag,
     189             :                                        uint8_t *limits) {
     190             :   (void)low_var_thresh;
     191             :   (void)flag;
     192             : #if CONFIG_VP9_HIGHBITDEPTH
     193             :   if (source->flags & YV12_FLAG_HIGHBITDEPTH) {
     194             :     double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
     195             :     int ppl = (int)(level + .5);
     196             :     vp9_highbd_post_proc_down_and_across(
     197             :         CONVERT_TO_SHORTPTR(source->y_buffer),
     198             :         CONVERT_TO_SHORTPTR(post->y_buffer), source->y_stride, post->y_stride,
     199             :         source->y_height, source->y_width, ppl);
     200             : 
     201             :     vp9_highbd_mbpost_proc_across_ip(CONVERT_TO_SHORTPTR(post->y_buffer),
     202             :                                      post->y_stride, post->y_height,
     203             :                                      post->y_width, q2mbl(q));
     204             : 
     205             :     vp9_highbd_mbpost_proc_down(CONVERT_TO_SHORTPTR(post->y_buffer),
     206             :                                 post->y_stride, post->y_height, post->y_width,
     207             :                                 q2mbl(q));
     208             : 
     209             :     vp9_highbd_post_proc_down_and_across(
     210             :         CONVERT_TO_SHORTPTR(source->u_buffer),
     211             :         CONVERT_TO_SHORTPTR(post->u_buffer), source->uv_stride, post->uv_stride,
     212             :         source->uv_height, source->uv_width, ppl);
     213             :     vp9_highbd_post_proc_down_and_across(
     214             :         CONVERT_TO_SHORTPTR(source->v_buffer),
     215             :         CONVERT_TO_SHORTPTR(post->v_buffer), source->uv_stride, post->uv_stride,
     216             :         source->uv_height, source->uv_width, ppl);
     217             :   } else {
     218             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     219           0 :     vp9_deblock(source, post, q, limits);
     220           0 :     vpx_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
     221             :                               post->y_width, q2mbl(q));
     222           0 :     vpx_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
     223             :                          post->y_width, q2mbl(q));
     224             : #if CONFIG_VP9_HIGHBITDEPTH
     225             :   }
     226             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     227           0 : }
     228             : 
     229           0 : void vp9_deblock(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int q,
     230             :                  uint8_t *limits) {
     231           0 :   const int ppl =
     232           0 :       (int)(6.0e-05 * q * q * q - 0.0067 * q * q + 0.306 * q + 0.0065 + 0.5);
     233             : #if CONFIG_VP9_HIGHBITDEPTH
     234             :   if (src->flags & YV12_FLAG_HIGHBITDEPTH) {
     235             :     int i;
     236             :     const uint8_t *const srcs[3] = { src->y_buffer, src->u_buffer,
     237             :                                      src->v_buffer };
     238             :     const int src_strides[3] = { src->y_stride, src->uv_stride,
     239             :                                  src->uv_stride };
     240             :     const int src_widths[3] = { src->y_width, src->uv_width, src->uv_width };
     241             :     const int src_heights[3] = { src->y_height, src->uv_height,
     242             :                                  src->uv_height };
     243             : 
     244             :     uint8_t *const dsts[3] = { dst->y_buffer, dst->u_buffer, dst->v_buffer };
     245             :     const int dst_strides[3] = { dst->y_stride, dst->uv_stride,
     246             :                                  dst->uv_stride };
     247             :     for (i = 0; i < MAX_MB_PLANE; ++i) {
     248             :       vp9_highbd_post_proc_down_and_across(
     249             :           CONVERT_TO_SHORTPTR(srcs[i]), CONVERT_TO_SHORTPTR(dsts[i]),
     250             :           src_strides[i], dst_strides[i], src_heights[i], src_widths[i], ppl);
     251             :     }
     252             :   } else {
     253             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     254             :     int mbr;
     255           0 :     const int mb_rows = src->y_height / 16;
     256           0 :     const int mb_cols = src->y_width / 16;
     257             : 
     258           0 :     memset(limits, (unsigned char)ppl, 16 * mb_cols);
     259             : 
     260           0 :     for (mbr = 0; mbr < mb_rows; mbr++) {
     261           0 :       vpx_post_proc_down_and_across_mb_row(
     262           0 :           src->y_buffer + 16 * mbr * src->y_stride,
     263           0 :           dst->y_buffer + 16 * mbr * dst->y_stride, src->y_stride,
     264             :           dst->y_stride, src->y_width, limits, 16);
     265           0 :       vpx_post_proc_down_and_across_mb_row(
     266           0 :           src->u_buffer + 8 * mbr * src->uv_stride,
     267           0 :           dst->u_buffer + 8 * mbr * dst->uv_stride, src->uv_stride,
     268             :           dst->uv_stride, src->uv_width, limits, 8);
     269           0 :       vpx_post_proc_down_and_across_mb_row(
     270           0 :           src->v_buffer + 8 * mbr * src->uv_stride,
     271           0 :           dst->v_buffer + 8 * mbr * dst->uv_stride, src->uv_stride,
     272             :           dst->uv_stride, src->uv_width, limits, 8);
     273             :     }
     274             : #if CONFIG_VP9_HIGHBITDEPTH
     275             :   }
     276             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     277           0 : }
     278             : 
     279           0 : void vp9_denoise(const YV12_BUFFER_CONFIG *src, YV12_BUFFER_CONFIG *dst, int q,
     280             :                  uint8_t *limits) {
     281           0 :   vp9_deblock(src, dst, q, limits);
     282           0 : }
     283             : 
     284           0 : static void swap_mi_and_prev_mi(VP9_COMMON *cm) {
     285             :   // Current mip will be the prev_mip for the next frame.
     286           0 :   MODE_INFO *temp = cm->postproc_state.prev_mip;
     287           0 :   cm->postproc_state.prev_mip = cm->mip;
     288           0 :   cm->mip = temp;
     289             : 
     290             :   // Update the upper left visible macroblock ptrs.
     291           0 :   cm->mi = cm->mip + cm->mi_stride + 1;
     292           0 :   cm->postproc_state.prev_mi = cm->postproc_state.prev_mip + cm->mi_stride + 1;
     293           0 : }
     294             : 
     295           0 : int vp9_post_proc_frame(struct VP9Common *cm, YV12_BUFFER_CONFIG *dest,
     296             :                         vp9_ppflags_t *ppflags) {
     297           0 :   const int q = VPXMIN(105, cm->lf.filter_level * 2);
     298           0 :   const int flags = ppflags->post_proc_flag;
     299           0 :   YV12_BUFFER_CONFIG *const ppbuf = &cm->post_proc_buffer;
     300           0 :   struct postproc_state *const ppstate = &cm->postproc_state;
     301             : 
     302           0 :   if (!cm->frame_to_show) return -1;
     303             : 
     304           0 :   if (!flags) {
     305           0 :     *dest = *cm->frame_to_show;
     306           0 :     return 0;
     307             :   }
     308             : 
     309           0 :   vpx_clear_system_state();
     310             : 
     311             :   // Alloc memory for prev_mip in the first frame.
     312           0 :   if (cm->current_video_frame == 1) {
     313           0 :     ppstate->last_base_qindex = cm->base_qindex;
     314           0 :     ppstate->last_frame_valid = 1;
     315             :   }
     316             : 
     317           0 :   if ((flags & VP9D_MFQE) && ppstate->prev_mip == NULL) {
     318           0 :     ppstate->prev_mip = vpx_calloc(cm->mi_alloc_size, sizeof(*cm->mip));
     319           0 :     if (!ppstate->prev_mip) {
     320           0 :       return 1;
     321             :     }
     322           0 :     ppstate->prev_mi = ppstate->prev_mip + cm->mi_stride + 1;
     323             :   }
     324             : 
     325             :   // Allocate post_proc_buffer_int if needed.
     326           0 :   if ((flags & VP9D_MFQE) && !cm->post_proc_buffer_int.buffer_alloc) {
     327           0 :     if ((flags & VP9D_DEMACROBLOCK) || (flags & VP9D_DEBLOCK)) {
     328           0 :       const int width = ALIGN_POWER_OF_TWO(cm->width, 4);
     329           0 :       const int height = ALIGN_POWER_OF_TWO(cm->height, 4);
     330             : 
     331           0 :       if (vpx_alloc_frame_buffer(&cm->post_proc_buffer_int, width, height,
     332             :                                  cm->subsampling_x, cm->subsampling_y,
     333             : #if CONFIG_VP9_HIGHBITDEPTH
     334             :                                  cm->use_highbitdepth,
     335             : #endif  // CONFIG_VP9_HIGHBITDEPTH
     336             :                                  VP9_ENC_BORDER_IN_PIXELS,
     337             :                                  cm->byte_alignment) < 0) {
     338           0 :         vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
     339             :                            "Failed to allocate MFQE framebuffer");
     340             :       }
     341             : 
     342             :       // Ensure that postproc is set to all 0s so that post proc
     343             :       // doesn't pull random data in from edge.
     344           0 :       memset(cm->post_proc_buffer_int.buffer_alloc, 128,
     345           0 :              cm->post_proc_buffer.frame_size);
     346             :     }
     347             :   }
     348             : 
     349           0 :   if (vpx_realloc_frame_buffer(&cm->post_proc_buffer, cm->width, cm->height,
     350             :                                cm->subsampling_x, cm->subsampling_y,
     351             : #if CONFIG_VP9_HIGHBITDEPTH
     352             :                                cm->use_highbitdepth,
     353             : #endif
     354             :                                VP9_DEC_BORDER_IN_PIXELS, cm->byte_alignment,
     355             :                                NULL, NULL, NULL) < 0)
     356           0 :     vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
     357             :                        "Failed to allocate post-processing buffer");
     358             : 
     359           0 :   if (flags & (VP9D_DEMACROBLOCK | VP9D_DEBLOCK)) {
     360           0 :     if (!cm->postproc_state.limits) {
     361           0 :       cm->postproc_state.limits =
     362           0 :           vpx_calloc(cm->width, sizeof(*cm->postproc_state.limits));
     363             :     }
     364             :   }
     365             : 
     366           0 :   if (flags & VP9D_ADDNOISE) {
     367           0 :     if (!cm->postproc_state.generated_noise) {
     368           0 :       cm->postproc_state.generated_noise = vpx_calloc(
     369           0 :           cm->width + 256, sizeof(*cm->postproc_state.generated_noise));
     370           0 :       if (!cm->postproc_state.generated_noise) return 1;
     371             :     }
     372             :   }
     373             : 
     374           0 :   if ((flags & VP9D_MFQE) && cm->current_video_frame >= 2 &&
     375           0 :       ppstate->last_frame_valid && cm->bit_depth == 8 &&
     376           0 :       ppstate->last_base_qindex <= last_q_thresh &&
     377           0 :       cm->base_qindex - ppstate->last_base_qindex >= q_diff_thresh) {
     378           0 :     vp9_mfqe(cm);
     379             :     // TODO(jackychen): Consider whether enable deblocking by default
     380             :     // if mfqe is enabled. Need to take both the quality and the speed
     381             :     // into consideration.
     382           0 :     if ((flags & VP9D_DEMACROBLOCK) || (flags & VP9D_DEBLOCK)) {
     383           0 :       vp8_yv12_copy_frame(ppbuf, &cm->post_proc_buffer_int);
     384             :     }
     385           0 :     if ((flags & VP9D_DEMACROBLOCK) && cm->post_proc_buffer_int.buffer_alloc) {
     386           0 :       deblock_and_de_macro_block(&cm->post_proc_buffer_int, ppbuf,
     387           0 :                                  q + (ppflags->deblocking_level - 5) * 10, 1, 0,
     388             :                                  cm->postproc_state.limits);
     389           0 :     } else if (flags & VP9D_DEBLOCK) {
     390           0 :       vp9_deblock(&cm->post_proc_buffer_int, ppbuf, q,
     391             :                   cm->postproc_state.limits);
     392             :     } else {
     393           0 :       vp8_yv12_copy_frame(&cm->post_proc_buffer_int, ppbuf);
     394             :     }
     395           0 :   } else if (flags & VP9D_DEMACROBLOCK) {
     396           0 :     deblock_and_de_macro_block(cm->frame_to_show, ppbuf,
     397           0 :                                q + (ppflags->deblocking_level - 5) * 10, 1, 0,
     398             :                                cm->postproc_state.limits);
     399           0 :   } else if (flags & VP9D_DEBLOCK) {
     400           0 :     vp9_deblock(cm->frame_to_show, ppbuf, q, cm->postproc_state.limits);
     401             :   } else {
     402           0 :     vp8_yv12_copy_frame(cm->frame_to_show, ppbuf);
     403             :   }
     404             : 
     405           0 :   ppstate->last_base_qindex = cm->base_qindex;
     406           0 :   ppstate->last_frame_valid = 1;
     407           0 :   if (flags & VP9D_ADDNOISE) {
     408           0 :     const int noise_level = ppflags->noise_level;
     409           0 :     if (ppstate->last_q != q || ppstate->last_noise != noise_level) {
     410             :       double sigma;
     411           0 :       vpx_clear_system_state();
     412           0 :       sigma = noise_level + .5 + .6 * q / 63.0;
     413           0 :       ppstate->clamp =
     414           0 :           vpx_setup_noise(sigma, ppstate->generated_noise, cm->width + 256);
     415           0 :       ppstate->last_q = q;
     416           0 :       ppstate->last_noise = noise_level;
     417             :     }
     418           0 :     vpx_plane_add_noise(ppbuf->y_buffer, ppstate->generated_noise,
     419             :                         ppstate->clamp, ppstate->clamp, ppbuf->y_width,
     420             :                         ppbuf->y_height, ppbuf->y_stride);
     421             :   }
     422             : 
     423           0 :   *dest = *ppbuf;
     424             : 
     425             :   /* handle problem with extending borders */
     426           0 :   dest->y_width = cm->width;
     427           0 :   dest->y_height = cm->height;
     428           0 :   dest->uv_width = dest->y_width >> cm->subsampling_x;
     429           0 :   dest->uv_height = dest->y_height >> cm->subsampling_y;
     430             : 
     431           0 :   if (flags & VP9D_MFQE) swap_mi_and_prev_mi(cm);
     432           0 :   return 0;
     433             : }
     434             : #endif  // CONFIG_VP9_POSTPROC

Generated by: LCOV version 1.13