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

Generated by: LCOV version 1.13