media/libvpx/vp8/common/mfqe.c

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  *  Copyright (c) 2012 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  */
    12 /* MFQE: Multiframe Quality Enhancement
    13  * In rate limited situations keyframes may cause significant visual artifacts
    14  * commonly referred to as "popping." This file implements a postproccesing
    15  * algorithm which blends data from the preceeding frame when there is no
    16  * motion and the q from the previous frame is lower which indicates that it is
    17  * higher quality.
    18  */
    20 #include "postproc.h"
    21 #include "variance.h"
    22 #include "vpx_mem/vpx_mem.h"
    23 #include "vp8_rtcd.h"
    24 #include "vpx_scale/yv12config.h"
    26 #include <limits.h>
    27 #include <stdlib.h>
    29 static void filter_by_weight(unsigned char *src, int src_stride,
    30                              unsigned char *dst, int dst_stride,
    31                              int block_size, int src_weight)
    32 {
    33     int dst_weight = (1 << MFQE_PRECISION) - src_weight;
    34     int rounding_bit = 1 << (MFQE_PRECISION - 1);
    35     int r, c;
    37     for (r = 0; r < block_size; r++)
    38     {
    39         for (c = 0; c < block_size; c++)
    40         {
    41             dst[c] = (src[c] * src_weight +
    42                       dst[c] * dst_weight +
    43                       rounding_bit) >> MFQE_PRECISION;
    44         }
    45         src += src_stride;
    46         dst += dst_stride;
    47     }
    48 }
    50 void vp8_filter_by_weight16x16_c(unsigned char *src, int src_stride,
    51                                  unsigned char *dst, int dst_stride,
    52                                  int src_weight)
    53 {
    54     filter_by_weight(src, src_stride, dst, dst_stride, 16, src_weight);
    55 }
    57 void vp8_filter_by_weight8x8_c(unsigned char *src, int src_stride,
    58                                unsigned char *dst, int dst_stride,
    59                                int src_weight)
    60 {
    61     filter_by_weight(src, src_stride, dst, dst_stride, 8, src_weight);
    62 }
    64 void vp8_filter_by_weight4x4_c(unsigned char *src, int src_stride,
    65                                unsigned char *dst, int dst_stride,
    66                                int src_weight)
    67 {
    68     filter_by_weight(src, src_stride, dst, dst_stride, 4, src_weight);
    69 }
    71 static void apply_ifactor(unsigned char *y_src,
    72                           int y_src_stride,
    73                           unsigned char *y_dst,
    74                           int y_dst_stride,
    75                           unsigned char *u_src,
    76                           unsigned char *v_src,
    77                           int uv_src_stride,
    78                           unsigned char *u_dst,
    79                           unsigned char *v_dst,
    80                           int uv_dst_stride,
    81                           int block_size,
    82                           int src_weight)
    83 {
    84     if (block_size == 16)
    85     {
    86         vp8_filter_by_weight16x16(y_src, y_src_stride, y_dst, y_dst_stride, src_weight);
    87         vp8_filter_by_weight8x8(u_src, uv_src_stride, u_dst, uv_dst_stride, src_weight);
    88         vp8_filter_by_weight8x8(v_src, uv_src_stride, v_dst, uv_dst_stride, src_weight);
    89     }
    90     else /* if (block_size == 8) */
    91     {
    92         vp8_filter_by_weight8x8(y_src, y_src_stride, y_dst, y_dst_stride, src_weight);
    93         vp8_filter_by_weight4x4(u_src, uv_src_stride, u_dst, uv_dst_stride, src_weight);
    94         vp8_filter_by_weight4x4(v_src, uv_src_stride, v_dst, uv_dst_stride, src_weight);
    95     }
    96 }
    98 static unsigned int int_sqrt(unsigned int x)
    99 {
   100     unsigned int y = x;
   101     unsigned int guess;
   102     int p = 1;
   103     while (y>>=1) p++;
   104     p>>=1;
   106     guess=0;
   107     while (p>=0)
   108     {
   109         guess |= (1<<p);
   110         if (x<guess*guess)
   111             guess -= (1<<p);
   112         p--;
   113     }
   114     /* choose between guess or guess+1 */
   115     return guess+(guess*guess+guess+1<=x);
   116 }
   118 #define USE_SSD
   119 static void multiframe_quality_enhance_block
   120 (
   121     int blksize, /* Currently only values supported are 16, 8 */
   122     int qcurr,
   123     int qprev,
   124     unsigned char *y,
   125     unsigned char *u,
   126     unsigned char *v,
   127     int y_stride,
   128     int uv_stride,
   129     unsigned char *yd,
   130     unsigned char *ud,
   131     unsigned char *vd,
   132     int yd_stride,
   133     int uvd_stride
   134 )
   135 {
   136     static const unsigned char VP8_ZEROS[16]=
   137     {
   138          0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
   139     };
   140     int uvblksize = blksize >> 1;
   141     int qdiff = qcurr - qprev;
   143     int i;
   144     unsigned char *up;
   145     unsigned char *udp;
   146     unsigned char *vp;
   147     unsigned char *vdp;
   149     unsigned int act, actd, sad, usad, vsad, sse, thr, thrsq, actrisk;
   151     if (blksize == 16)
   152     {
   153         actd = (vp8_variance16x16(yd, yd_stride, VP8_ZEROS, 0, &sse)+128)>>8;
   154         act = (vp8_variance16x16(y, y_stride, VP8_ZEROS, 0, &sse)+128)>>8;
   155 #ifdef USE_SSD
   156         sad = (vp8_variance16x16(y, y_stride, yd, yd_stride, &sse));
   157         sad = (sse + 128)>>8;
   158         usad = (vp8_variance8x8(u, uv_stride, ud, uvd_stride, &sse));
   159         usad = (sse + 32)>>6;
   160         vsad = (vp8_variance8x8(v, uv_stride, vd, uvd_stride, &sse));
   161         vsad = (sse + 32)>>6;
   162 #else
   163         sad = (vp8_sad16x16(y, y_stride, yd, yd_stride, UINT_MAX) + 128) >> 8;
   164         usad = (vp8_sad8x8(u, uv_stride, ud, uvd_stride, UINT_MAX) + 32) >> 6;
   165         vsad = (vp8_sad8x8(v, uv_stride, vd, uvd_stride, UINT_MAX)+ 32) >> 6;
   166 #endif
   167     }
   168     else /* if (blksize == 8) */
   169     {
   170         actd = (vp8_variance8x8(yd, yd_stride, VP8_ZEROS, 0, &sse)+32)>>6;
   171         act = (vp8_variance8x8(y, y_stride, VP8_ZEROS, 0, &sse)+32)>>6;
   172 #ifdef USE_SSD
   173         sad = (vp8_variance8x8(y, y_stride, yd, yd_stride, &sse));
   174         sad = (sse + 32)>>6;
   175         usad = (vp8_variance4x4(u, uv_stride, ud, uvd_stride, &sse));
   176         usad = (sse + 8)>>4;
   177         vsad = (vp8_variance4x4(v, uv_stride, vd, uvd_stride, &sse));
   178         vsad = (sse + 8)>>4;
   179 #else
   180         sad = (vp8_sad8x8(y, y_stride, yd, yd_stride, UINT_MAX) + 32) >> 6;
   181         usad = (vp8_sad4x4(u, uv_stride, ud, uvd_stride, UINT_MAX) + 8) >> 4;
   182         vsad = (vp8_sad4x4(v, uv_stride, vd, uvd_stride, UINT_MAX) + 8) >> 4;
   183 #endif
   184     }
   186     actrisk = (actd > act * 5);
   188     /* thr = qdiff/16 + log2(act) + log4(qprev) */
   189     thr = (qdiff >> 4);
   190     while (actd >>= 1) thr++;
   191     while (qprev >>= 2) thr++;
   193 #ifdef USE_SSD
   194     thrsq = thr * thr;
   195     if (sad < thrsq &&
   196         /* additional checks for color mismatch and excessive addition of
   197          * high-frequencies */
   198         4 * usad < thrsq && 4 * vsad < thrsq && !actrisk)
   199 #else
   200     if (sad < thr &&
   201         /* additional checks for color mismatch and excessive addition of
   202          * high-frequencies */
   203         2 * usad < thr && 2 * vsad < thr && !actrisk)
   204 #endif
   205     {
   206         int ifactor;
   207 #ifdef USE_SSD
   208         /* TODO: optimize this later to not need sqr root */
   209         sad = int_sqrt(sad);
   210 #endif
   211         ifactor = (sad << MFQE_PRECISION) / thr;
   212         ifactor >>= (qdiff >> 5);
   214         if (ifactor)
   215         {
   216             apply_ifactor(y, y_stride, yd, yd_stride,
   217                           u, v, uv_stride,
   218                           ud, vd, uvd_stride,
   219                           blksize, ifactor);
   220         }
   221     }
   222     else  /* else implicitly copy from previous frame */
   223     {
   224         if (blksize == 16)
   225         {
   226             vp8_copy_mem16x16(y, y_stride, yd, yd_stride);
   227             vp8_copy_mem8x8(u, uv_stride, ud, uvd_stride);
   228             vp8_copy_mem8x8(v, uv_stride, vd, uvd_stride);
   229         }
   230         else  /* if (blksize == 8) */
   231         {
   232             vp8_copy_mem8x8(y, y_stride, yd, yd_stride);
   233             for (up = u, udp = ud, i = 0; i < uvblksize; ++i, up += uv_stride, udp += uvd_stride)
   234                 vpx_memcpy(udp, up, uvblksize);
   235             for (vp = v, vdp = vd, i = 0; i < uvblksize; ++i, vp += uv_stride, vdp += uvd_stride)
   236                 vpx_memcpy(vdp, vp, uvblksize);
   237         }
   238     }
   239 }
   241 static int qualify_inter_mb(const MODE_INFO *mode_info_context, int *map)
   242 {
   243     if (mode_info_context->mbmi.mb_skip_coeff)
   244         map[0] = map[1] = map[2] = map[3] = 1;
   245     else if (mode_info_context->mbmi.mode==SPLITMV)
   246     {
   247         static int ndx[4][4] =
   248         {
   249             {0, 1, 4, 5},
   250             {2, 3, 6, 7},
   251             {8, 9, 12, 13},
   252             {10, 11, 14, 15}
   253         };
   254         int i, j;
   255         for (i=0; i<4; ++i)
   256         {
   257             map[i] = 1;
   258             for (j=0; j<4 && map[j]; ++j)
   259                 map[i] &= (mode_info_context->bmi[ndx[i][j]].mv.as_mv.row <= 2 &&
   260                            mode_info_context->bmi[ndx[i][j]].mv.as_mv.col <= 2);
   261         }
   262     }
   263     else
   264     {
   265         map[0] = map[1] = map[2] = map[3] =
   266             (mode_info_context->mbmi.mode > B_PRED &&
   267              abs(mode_info_context->mbmi.mv.as_mv.row) <= 2 &&
   268              abs(mode_info_context->mbmi.mv.as_mv.col) <= 2);
   269     }
   270     return (map[0]+map[1]+map[2]+map[3]);
   271 }
   273 void vp8_multiframe_quality_enhance
   274 (
   275     VP8_COMMON *cm
   276 )
   277 {
   278     YV12_BUFFER_CONFIG *show = cm->frame_to_show;
   279     YV12_BUFFER_CONFIG *dest = &cm->post_proc_buffer;
   281     FRAME_TYPE frame_type = cm->frame_type;
   282     /* Point at base of Mb MODE_INFO list has motion vectors etc */
   283     const MODE_INFO *mode_info_context = cm->show_frame_mi;
   284     int mb_row;
   285     int mb_col;
   286     int totmap, map[4];
   287     int qcurr = cm->base_qindex;
   288     int qprev = cm->postproc_state.last_base_qindex;
   290     unsigned char *y_ptr, *u_ptr, *v_ptr;
   291     unsigned char *yd_ptr, *ud_ptr, *vd_ptr;
   293     /* Set up the buffer pointers */
   294     y_ptr = show->y_buffer;
   295     u_ptr = show->u_buffer;
   296     v_ptr = show->v_buffer;
   297     yd_ptr = dest->y_buffer;
   298     ud_ptr = dest->u_buffer;
   299     vd_ptr = dest->v_buffer;
   301     /* postprocess each macro block */
   302     for (mb_row = 0; mb_row < cm->mb_rows; mb_row++)
   303     {
   304         for (mb_col = 0; mb_col < cm->mb_cols; mb_col++)
   305         {
   306             /* if motion is high there will likely be no benefit */
   307             if (frame_type == INTER_FRAME) totmap = qualify_inter_mb(mode_info_context, map);
   308             else totmap = (frame_type == KEY_FRAME ? 4 : 0);
   309             if (totmap)
   310             {
   311                 if (totmap < 4)
   312                 {
   313                     int i, j;
   314                     for (i=0; i<2; ++i)
   315                         for (j=0; j<2; ++j)
   316                         {
   317                             if (map[i*2+j])
   318                             {
   319                                 multiframe_quality_enhance_block(8, qcurr, qprev,
   320                                                                  y_ptr + 8*(i*show->y_stride+j),
   321                                                                  u_ptr + 4*(i*show->uv_stride+j),
   322                                                                  v_ptr + 4*(i*show->uv_stride+j),
   323                                                                  show->y_stride,
   324                                                                  show->uv_stride,
   325                                                                  yd_ptr + 8*(i*dest->y_stride+j),
   326                                                                  ud_ptr + 4*(i*dest->uv_stride+j),
   327                                                                  vd_ptr + 4*(i*dest->uv_stride+j),
   328                                                                  dest->y_stride,
   329                                                                  dest->uv_stride);
   330                             }
   331                             else
   332                             {
   333                                 /* copy a 8x8 block */
   334                                 int k;
   335                                 unsigned char *up = u_ptr + 4*(i*show->uv_stride+j);
   336                                 unsigned char *udp = ud_ptr + 4*(i*dest->uv_stride+j);
   337                                 unsigned char *vp = v_ptr + 4*(i*show->uv_stride+j);
   338                                 unsigned char *vdp = vd_ptr + 4*(i*dest->uv_stride+j);
   339                                 vp8_copy_mem8x8(y_ptr + 8*(i*show->y_stride+j), show->y_stride,
   340                                                 yd_ptr + 8*(i*dest->y_stride+j), dest->y_stride);
   341                                 for (k = 0; k < 4; ++k, up += show->uv_stride, udp += dest->uv_stride,
   342                                                         vp += show->uv_stride, vdp += dest->uv_stride)
   343                                 {
   344                                     vpx_memcpy(udp, up, 4);
   345                                     vpx_memcpy(vdp, vp, 4);
   346                                 }
   347                             }
   348                         }
   349                 }
   350                 else /* totmap = 4 */
   351                 {
   352                     multiframe_quality_enhance_block(16, qcurr, qprev, y_ptr,
   353                                                      u_ptr, v_ptr,
   354                                                      show->y_stride,
   355                                                      show->uv_stride,
   356                                                      yd_ptr, ud_ptr, vd_ptr,
   357                                                      dest->y_stride,
   358                                                      dest->uv_stride);
   359                 }
   360             }
   361             else
   362             {
   363                 vp8_copy_mem16x16(y_ptr, show->y_stride, yd_ptr, dest->y_stride);
   364                 vp8_copy_mem8x8(u_ptr, show->uv_stride, ud_ptr, dest->uv_stride);
   365                 vp8_copy_mem8x8(v_ptr, show->uv_stride, vd_ptr, dest->uv_stride);
   366             }
   367             y_ptr += 16;
   368             u_ptr += 8;
   369             v_ptr += 8;
   370             yd_ptr += 16;
   371             ud_ptr += 8;
   372             vd_ptr += 8;
   373             mode_info_context++;     /* step to next MB */
   374         }
   376         y_ptr += show->y_stride  * 16 - 16 * cm->mb_cols;
   377         u_ptr += show->uv_stride *  8 - 8 * cm->mb_cols;
   378         v_ptr += show->uv_stride *  8 - 8 * cm->mb_cols;
   379         yd_ptr += dest->y_stride  * 16 - 16 * cm->mb_cols;
   380         ud_ptr += dest->uv_stride *  8 - 8 * cm->mb_cols;
   381         vd_ptr += dest->uv_stride *  8 - 8 * cm->mb_cols;
   383         mode_info_context++;         /* Skip border mb */
   384     }
   385 }

mercurial