LCOV - code coverage report
Current view: top level - media/libvpx/libvpx/vp8/common - postproc.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 202 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 8 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 "vpx_config.h"
      12             : #include "vpx_dsp_rtcd.h"
      13             : #include "vp8_rtcd.h"
      14             : #include "vpx_dsp/postproc.h"
      15             : #include "vpx_ports/system_state.h"
      16             : #include "vpx_scale_rtcd.h"
      17             : #include "vpx_scale/yv12config.h"
      18             : #include "postproc.h"
      19             : #include "common.h"
      20             : #include "vpx_scale/vpx_scale.h"
      21             : #include "systemdependent.h"
      22             : 
      23             : #include <limits.h>
      24             : #include <math.h>
      25             : #include <stdlib.h>
      26             : #include <stdio.h>
      27             : 
      28             : /* clang-format off */
      29             : #define RGB_TO_YUV(t)                                     \
      30             :   (unsigned char)((0.257 * (float)(t >> 16)) +            \
      31             :                   (0.504 * (float)(t >> 8 & 0xff)) +      \
      32             :                   (0.098 * (float)(t & 0xff)) + 16),      \
      33             :   (unsigned char)(-(0.148 * (float)(t >> 16)) -           \
      34             :                   (0.291 * (float)(t >> 8 & 0xff)) +      \
      35             :                   (0.439 * (float)(t & 0xff)) + 128),     \
      36             :   (unsigned char)((0.439 * (float)(t >> 16)) -            \
      37             :                   (0.368 * (float)(t >> 8 & 0xff)) -      \
      38             :                   (0.071 * (float)(t & 0xff)) + 128)
      39             : /* clang-format on */
      40             : 
      41             : extern void vp8_blit_text(const char *msg, unsigned char *address,
      42             :                           const int pitch);
      43             : extern void vp8_blit_line(int x0, int x1, int y0, int y1, unsigned char *image,
      44             :                           const int pitch);
      45             : /***********************************************************************************************************
      46             :  */
      47             : #if CONFIG_POSTPROC
      48           0 : static int q2mbl(int x) {
      49           0 :   if (x < 20) x = 20;
      50             : 
      51           0 :   x = 50 + (x - 50) * 10 / 8;
      52           0 :   return x * x / 3;
      53             : }
      54             : 
      55           0 : static void vp8_de_mblock(YV12_BUFFER_CONFIG *post, int q) {
      56           0 :   vpx_mbpost_proc_across_ip(post->y_buffer, post->y_stride, post->y_height,
      57             :                             post->y_width, q2mbl(q));
      58           0 :   vpx_mbpost_proc_down(post->y_buffer, post->y_stride, post->y_height,
      59             :                        post->y_width, q2mbl(q));
      60           0 : }
      61             : 
      62           0 : void vp8_deblock(VP8_COMMON *cm, YV12_BUFFER_CONFIG *source,
      63             :                  YV12_BUFFER_CONFIG *post, int q, int low_var_thresh,
      64             :                  int flag) {
      65           0 :   double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
      66           0 :   int ppl = (int)(level + .5);
      67             : 
      68           0 :   const MODE_INFO *mode_info_context = cm->show_frame_mi;
      69             :   int mbr, mbc;
      70             : 
      71             :   /* The pixel thresholds are adjusted according to if or not the macroblock
      72             :    * is a skipped block.  */
      73           0 :   unsigned char *ylimits = cm->pp_limits_buffer;
      74           0 :   unsigned char *uvlimits = cm->pp_limits_buffer + 16 * cm->mb_cols;
      75             :   (void)low_var_thresh;
      76             :   (void)flag;
      77             : 
      78           0 :   if (ppl > 0) {
      79           0 :     for (mbr = 0; mbr < cm->mb_rows; ++mbr) {
      80           0 :       unsigned char *ylptr = ylimits;
      81           0 :       unsigned char *uvlptr = uvlimits;
      82           0 :       for (mbc = 0; mbc < cm->mb_cols; ++mbc) {
      83             :         unsigned char mb_ppl;
      84             : 
      85           0 :         if (mode_info_context->mbmi.mb_skip_coeff) {
      86           0 :           mb_ppl = (unsigned char)ppl >> 1;
      87             :         } else {
      88           0 :           mb_ppl = (unsigned char)ppl;
      89             :         }
      90             : 
      91           0 :         memset(ylptr, mb_ppl, 16);
      92           0 :         memset(uvlptr, mb_ppl, 8);
      93             : 
      94           0 :         ylptr += 16;
      95           0 :         uvlptr += 8;
      96           0 :         mode_info_context++;
      97             :       }
      98           0 :       mode_info_context++;
      99             : 
     100           0 :       vpx_post_proc_down_and_across_mb_row(
     101           0 :           source->y_buffer + 16 * mbr * source->y_stride,
     102           0 :           post->y_buffer + 16 * mbr * post->y_stride, source->y_stride,
     103             :           post->y_stride, source->y_width, ylimits, 16);
     104             : 
     105           0 :       vpx_post_proc_down_and_across_mb_row(
     106           0 :           source->u_buffer + 8 * mbr * source->uv_stride,
     107           0 :           post->u_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
     108             :           post->uv_stride, source->uv_width, uvlimits, 8);
     109           0 :       vpx_post_proc_down_and_across_mb_row(
     110           0 :           source->v_buffer + 8 * mbr * source->uv_stride,
     111           0 :           post->v_buffer + 8 * mbr * post->uv_stride, source->uv_stride,
     112             :           post->uv_stride, source->uv_width, uvlimits, 8);
     113             :     }
     114             :   } else {
     115           0 :     vp8_yv12_copy_frame(source, post);
     116             :   }
     117           0 : }
     118             : 
     119           0 : void vp8_de_noise(VP8_COMMON *cm, YV12_BUFFER_CONFIG *source,
     120             :                   YV12_BUFFER_CONFIG *post, int q, int low_var_thresh, int flag,
     121             :                   int uvfilter) {
     122             :   int mbr;
     123           0 :   double level = 6.0e-05 * q * q * q - .0067 * q * q + .306 * q + .0065;
     124           0 :   int ppl = (int)(level + .5);
     125           0 :   int mb_rows = cm->mb_rows;
     126           0 :   int mb_cols = cm->mb_cols;
     127           0 :   unsigned char *limits = cm->pp_limits_buffer;
     128             :   (void)post;
     129             :   (void)low_var_thresh;
     130             :   (void)flag;
     131             : 
     132           0 :   memset(limits, (unsigned char)ppl, 16 * mb_cols);
     133             : 
     134             :   /* TODO: The original code don't filter the 2 outer rows and columns. */
     135           0 :   for (mbr = 0; mbr < mb_rows; ++mbr) {
     136           0 :     vpx_post_proc_down_and_across_mb_row(
     137           0 :         source->y_buffer + 16 * mbr * source->y_stride,
     138           0 :         source->y_buffer + 16 * mbr * source->y_stride, source->y_stride,
     139             :         source->y_stride, source->y_width, limits, 16);
     140           0 :     if (uvfilter == 1) {
     141           0 :       vpx_post_proc_down_and_across_mb_row(
     142           0 :           source->u_buffer + 8 * mbr * source->uv_stride,
     143           0 :           source->u_buffer + 8 * mbr * source->uv_stride, source->uv_stride,
     144             :           source->uv_stride, source->uv_width, limits, 8);
     145           0 :       vpx_post_proc_down_and_across_mb_row(
     146           0 :           source->v_buffer + 8 * mbr * source->uv_stride,
     147           0 :           source->v_buffer + 8 * mbr * source->uv_stride, source->uv_stride,
     148             :           source->uv_stride, source->uv_width, limits, 8);
     149             :     }
     150             :   }
     151           0 : }
     152             : #endif  // CONFIG_POSTPROC
     153             : 
     154             : /* Blend the macro block with a solid colored square.  Leave the
     155             :  * edges unblended to give distinction to macro blocks in areas
     156             :  * filled with the same color block.
     157             :  */
     158           0 : void vp8_blend_mb_inner_c(unsigned char *y, unsigned char *u, unsigned char *v,
     159             :                           int y_1, int u_1, int v_1, int alpha, int stride) {
     160             :   int i, j;
     161           0 :   int y1_const = y_1 * ((1 << 16) - alpha);
     162           0 :   int u1_const = u_1 * ((1 << 16) - alpha);
     163           0 :   int v1_const = v_1 * ((1 << 16) - alpha);
     164             : 
     165           0 :   y += 2 * stride + 2;
     166           0 :   for (i = 0; i < 12; ++i) {
     167           0 :     for (j = 0; j < 12; ++j) {
     168           0 :       y[j] = (y[j] * alpha + y1_const) >> 16;
     169             :     }
     170           0 :     y += stride;
     171             :   }
     172             : 
     173           0 :   stride >>= 1;
     174             : 
     175           0 :   u += stride + 1;
     176           0 :   v += stride + 1;
     177             : 
     178           0 :   for (i = 0; i < 6; ++i) {
     179           0 :     for (j = 0; j < 6; ++j) {
     180           0 :       u[j] = (u[j] * alpha + u1_const) >> 16;
     181           0 :       v[j] = (v[j] * alpha + v1_const) >> 16;
     182             :     }
     183           0 :     u += stride;
     184           0 :     v += stride;
     185             :   }
     186           0 : }
     187             : 
     188             : /* Blend only the edge of the macro block.  Leave center
     189             :  * unblended to allow for other visualizations to be layered.
     190             :  */
     191           0 : void vp8_blend_mb_outer_c(unsigned char *y, unsigned char *u, unsigned char *v,
     192             :                           int y_1, int u_1, int v_1, int alpha, int stride) {
     193             :   int i, j;
     194           0 :   int y1_const = y_1 * ((1 << 16) - alpha);
     195           0 :   int u1_const = u_1 * ((1 << 16) - alpha);
     196           0 :   int v1_const = v_1 * ((1 << 16) - alpha);
     197             : 
     198           0 :   for (i = 0; i < 2; ++i) {
     199           0 :     for (j = 0; j < 16; ++j) {
     200           0 :       y[j] = (y[j] * alpha + y1_const) >> 16;
     201             :     }
     202           0 :     y += stride;
     203             :   }
     204             : 
     205           0 :   for (i = 0; i < 12; ++i) {
     206           0 :     y[0] = (y[0] * alpha + y1_const) >> 16;
     207           0 :     y[1] = (y[1] * alpha + y1_const) >> 16;
     208           0 :     y[14] = (y[14] * alpha + y1_const) >> 16;
     209           0 :     y[15] = (y[15] * alpha + y1_const) >> 16;
     210           0 :     y += stride;
     211             :   }
     212             : 
     213           0 :   for (i = 0; i < 2; ++i) {
     214           0 :     for (j = 0; j < 16; ++j) {
     215           0 :       y[j] = (y[j] * alpha + y1_const) >> 16;
     216             :     }
     217           0 :     y += stride;
     218             :   }
     219             : 
     220           0 :   stride >>= 1;
     221             : 
     222           0 :   for (j = 0; j < 8; ++j) {
     223           0 :     u[j] = (u[j] * alpha + u1_const) >> 16;
     224           0 :     v[j] = (v[j] * alpha + v1_const) >> 16;
     225             :   }
     226           0 :   u += stride;
     227           0 :   v += stride;
     228             : 
     229           0 :   for (i = 0; i < 6; ++i) {
     230           0 :     u[0] = (u[0] * alpha + u1_const) >> 16;
     231           0 :     v[0] = (v[0] * alpha + v1_const) >> 16;
     232             : 
     233           0 :     u[7] = (u[7] * alpha + u1_const) >> 16;
     234           0 :     v[7] = (v[7] * alpha + v1_const) >> 16;
     235             : 
     236           0 :     u += stride;
     237           0 :     v += stride;
     238             :   }
     239             : 
     240           0 :   for (j = 0; j < 8; ++j) {
     241           0 :     u[j] = (u[j] * alpha + u1_const) >> 16;
     242           0 :     v[j] = (v[j] * alpha + v1_const) >> 16;
     243             :   }
     244           0 : }
     245             : 
     246           0 : void vp8_blend_b_c(unsigned char *y, unsigned char *u, unsigned char *v,
     247             :                    int y_1, int u_1, int v_1, int alpha, int stride) {
     248             :   int i, j;
     249           0 :   int y1_const = y_1 * ((1 << 16) - alpha);
     250           0 :   int u1_const = u_1 * ((1 << 16) - alpha);
     251           0 :   int v1_const = v_1 * ((1 << 16) - alpha);
     252             : 
     253           0 :   for (i = 0; i < 4; ++i) {
     254           0 :     for (j = 0; j < 4; ++j) {
     255           0 :       y[j] = (y[j] * alpha + y1_const) >> 16;
     256             :     }
     257           0 :     y += stride;
     258             :   }
     259             : 
     260           0 :   stride >>= 1;
     261             : 
     262           0 :   for (i = 0; i < 2; ++i) {
     263           0 :     for (j = 0; j < 2; ++j) {
     264           0 :       u[j] = (u[j] * alpha + u1_const) >> 16;
     265           0 :       v[j] = (v[j] * alpha + v1_const) >> 16;
     266             :     }
     267           0 :     u += stride;
     268           0 :     v += stride;
     269             :   }
     270           0 : }
     271             : 
     272             : #if CONFIG_POSTPROC
     273           0 : int vp8_post_proc_frame(VP8_COMMON *oci, YV12_BUFFER_CONFIG *dest,
     274             :                         vp8_ppflags_t *ppflags) {
     275           0 :   int q = oci->filter_level * 10 / 6;
     276           0 :   int flags = ppflags->post_proc_flag;
     277           0 :   int deblock_level = ppflags->deblocking_level;
     278           0 :   int noise_level = ppflags->noise_level;
     279             : 
     280           0 :   if (!oci->frame_to_show) return -1;
     281             : 
     282           0 :   if (q > 63) q = 63;
     283             : 
     284           0 :   if (!flags) {
     285           0 :     *dest = *oci->frame_to_show;
     286             : 
     287             :     /* handle problem with extending borders */
     288           0 :     dest->y_width = oci->Width;
     289           0 :     dest->y_height = oci->Height;
     290           0 :     dest->uv_height = dest->y_height / 2;
     291           0 :     oci->postproc_state.last_base_qindex = oci->base_qindex;
     292           0 :     oci->postproc_state.last_frame_valid = 1;
     293           0 :     return 0;
     294             :   }
     295           0 :   if (flags & VP8D_ADDNOISE) {
     296           0 :     if (!oci->postproc_state.generated_noise) {
     297           0 :       oci->postproc_state.generated_noise = vpx_calloc(
     298           0 :           oci->Width + 256, sizeof(*oci->postproc_state.generated_noise));
     299           0 :       if (!oci->postproc_state.generated_noise) return 1;
     300             :     }
     301             :   }
     302             : 
     303             :   /* Allocate post_proc_buffer_int if needed */
     304           0 :   if ((flags & VP8D_MFQE) && !oci->post_proc_buffer_int_used) {
     305           0 :     if ((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) {
     306           0 :       int width = (oci->Width + 15) & ~15;
     307           0 :       int height = (oci->Height + 15) & ~15;
     308             : 
     309           0 :       if (vp8_yv12_alloc_frame_buffer(&oci->post_proc_buffer_int, width, height,
     310             :                                       VP8BORDERINPIXELS)) {
     311           0 :         vpx_internal_error(&oci->error, VPX_CODEC_MEM_ERROR,
     312             :                            "Failed to allocate MFQE framebuffer");
     313             :       }
     314             : 
     315           0 :       oci->post_proc_buffer_int_used = 1;
     316             : 
     317             :       /* insure that postproc is set to all 0's so that post proc
     318             :        * doesn't pull random data in from edge
     319             :        */
     320           0 :       memset((&oci->post_proc_buffer_int)->buffer_alloc, 128,
     321           0 :              (&oci->post_proc_buffer)->frame_size);
     322             :     }
     323             :   }
     324             : 
     325           0 :   vpx_clear_system_state();
     326             : 
     327           0 :   if ((flags & VP8D_MFQE) && oci->postproc_state.last_frame_valid &&
     328           0 :       oci->current_video_frame >= 2 &&
     329           0 :       oci->postproc_state.last_base_qindex < 60 &&
     330           0 :       oci->base_qindex - oci->postproc_state.last_base_qindex >= 20) {
     331           0 :     vp8_multiframe_quality_enhance(oci);
     332           0 :     if (((flags & VP8D_DEBLOCK) || (flags & VP8D_DEMACROBLOCK)) &&
     333           0 :         oci->post_proc_buffer_int_used) {
     334           0 :       vp8_yv12_copy_frame(&oci->post_proc_buffer, &oci->post_proc_buffer_int);
     335           0 :       if (flags & VP8D_DEMACROBLOCK) {
     336           0 :         vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer,
     337           0 :                     q + (deblock_level - 5) * 10, 1, 0);
     338           0 :         vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
     339           0 :       } else if (flags & VP8D_DEBLOCK) {
     340           0 :         vp8_deblock(oci, &oci->post_proc_buffer_int, &oci->post_proc_buffer, q,
     341             :                     1, 0);
     342             :       }
     343             :     }
     344             :     /* Move partially towards the base q of the previous frame */
     345           0 :     oci->postproc_state.last_base_qindex =
     346           0 :         (3 * oci->postproc_state.last_base_qindex + oci->base_qindex) >> 2;
     347           0 :   } else if (flags & VP8D_DEMACROBLOCK) {
     348           0 :     vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer,
     349           0 :                 q + (deblock_level - 5) * 10, 1, 0);
     350           0 :     vp8_de_mblock(&oci->post_proc_buffer, q + (deblock_level - 5) * 10);
     351             : 
     352           0 :     oci->postproc_state.last_base_qindex = oci->base_qindex;
     353           0 :   } else if (flags & VP8D_DEBLOCK) {
     354           0 :     vp8_deblock(oci, oci->frame_to_show, &oci->post_proc_buffer, q, 1, 0);
     355           0 :     oci->postproc_state.last_base_qindex = oci->base_qindex;
     356             :   } else {
     357           0 :     vp8_yv12_copy_frame(oci->frame_to_show, &oci->post_proc_buffer);
     358           0 :     oci->postproc_state.last_base_qindex = oci->base_qindex;
     359             :   }
     360           0 :   oci->postproc_state.last_frame_valid = 1;
     361             : 
     362           0 :   if (flags & VP8D_ADDNOISE) {
     363           0 :     if (oci->postproc_state.last_q != q ||
     364           0 :         oci->postproc_state.last_noise != noise_level) {
     365             :       double sigma;
     366           0 :       struct postproc_state *ppstate = &oci->postproc_state;
     367           0 :       vpx_clear_system_state();
     368           0 :       sigma = noise_level + .5 + .6 * q / 63.0;
     369           0 :       ppstate->clamp =
     370           0 :           vpx_setup_noise(sigma, ppstate->generated_noise, oci->Width + 256);
     371           0 :       ppstate->last_q = q;
     372           0 :       ppstate->last_noise = noise_level;
     373             :     }
     374             : 
     375           0 :     vpx_plane_add_noise(
     376           0 :         oci->post_proc_buffer.y_buffer, oci->postproc_state.generated_noise,
     377             :         oci->postproc_state.clamp, oci->postproc_state.clamp,
     378             :         oci->post_proc_buffer.y_width, oci->post_proc_buffer.y_height,
     379             :         oci->post_proc_buffer.y_stride);
     380             :   }
     381             : 
     382           0 :   *dest = oci->post_proc_buffer;
     383             : 
     384             :   /* handle problem with extending borders */
     385           0 :   dest->y_width = oci->Width;
     386           0 :   dest->y_height = oci->Height;
     387           0 :   dest->uv_height = dest->y_height / 2;
     388           0 :   return 0;
     389             : }
     390             : #endif

Generated by: LCOV version 1.13